metatag.install 55 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557
  1. <?php
  2. /**
  3. * @file
  4. * Install, update, and uninstall functions for the metatag module.
  5. */
  6. /**
  7. * Implements hook_requirements().
  8. */
  9. function metatag_requirements($phase) {
  10. $requirements = array();
  11. // Ensure translations don't break during installation.
  12. $t = get_t();
  13. if ($phase == 'install') {
  14. // Handle scenarios where the site had the legacy "metatags" module
  15. // installed but then had Metatag installed on top of it.
  16. if (function_exists('db_table_exists') && function_exists('db_field_exists') && function_exists('db_query') && Database::isActiveConnection()) {
  17. // Check if the primary table already exists.
  18. if (db_table_exists('metatag')) {
  19. // Check to see if all of the fields exist in the table. If one of the
  20. // fields does not exist, proceed with the fix.
  21. $fields = array(
  22. 'entity_type',
  23. 'entity_id',
  24. 'revision_id',
  25. 'language',
  26. 'data',
  27. );
  28. foreach ($fields as $field) {
  29. // This field doesn't exist, so determine what to do.
  30. if (!db_field_exists('metatag', $field)) {
  31. // The table contains data, so rename it.
  32. if (db_query("SELECT COUNT(*) FROM {metatag}")->fetchField() > 0) {
  33. db_query("RENAME TABLE {metatag} TO {metatag}_legacy");
  34. $message = 'An out-of-date version of the {metatag} table was discovered. As the table contained data it was renamed with a suffix of "_legacy". This will not prevent installation from continuing, but will need to be dealt with later. See <a href="https://www.drupal.org/node/1391554">https://www.drupal.org/node/1391554</a> for further details.';
  35. }
  36. // The table is empty, so delete it.
  37. else {
  38. db_query("DROP TABLE {metatag}");
  39. $message = 'An out-of-date version of the {metatag} table was discovered. As the table was empty it was simply removed so that it could be recreated in the correct format. Installation may now proceed. See <a href="https://www.drupal.org/node/1391554">https://www.drupal.org/node/1391554</a> for further details.';
  40. }
  41. $requirements['metatag'] = array(
  42. 'severity' => REQUIREMENT_WARNING,
  43. 'title' => 'Metatag',
  44. 'value' => $t('Legacy data discovered.'),
  45. 'description' => $t($message),
  46. );
  47. drupal_set_message($t($message), 'warning');
  48. break;
  49. }
  50. }
  51. }
  52. }
  53. }
  54. elseif ($phase == 'runtime') {
  55. // Work out the release of D7 that is currently running.
  56. list($major, $minor) = explode('.', VERSION);
  57. // Strip off any suffixes on the version string, e.g. "17-dev".
  58. if (strpos('-', $minor)) {
  59. list($minor, $suffix) = explode('-', $minor);
  60. }
  61. // Releases of Drupal older than 7.28 did not have entity_language(), which
  62. // is now required, and had a broken [node:summary] token.
  63. if ($minor < 28) {
  64. $requirements['metatag'] = array(
  65. 'severity' => REQUIREMENT_WARNING,
  66. 'title' => 'Metatag',
  67. 'value' => $t('Upgrade Drupal core to v7.28 or newer'),
  68. 'description' => $t("This older version of Drupal core is missing functionality necessary for the module's multilingual support and contains a broken [node:summary] token, it must be upgraded to version 7.28 or newer."),
  69. );
  70. }
  71. // Everything's OK.
  72. else {
  73. $requirements['metatag'] = array(
  74. 'severity' => REQUIREMENT_OK,
  75. 'title' => 'Metatag',
  76. 'value' => $t('Drupal core is compatible'),
  77. 'description' => $t('Older versions of Drupal core contained bugs that made them incompatible with Metatag, but this version will work correctly.'),
  78. );
  79. }
  80. // Add a note if Page Title is also installed.
  81. if (module_exists('page_title')) {
  82. $requirements['metatag_page_title'] = array(
  83. 'severity' => REQUIREMENT_INFO,
  84. 'title' => 'Metatag',
  85. 'value' => $t('Possible conflicts with Page Title module'),
  86. 'description' => $t('The Metatag module is able to customize page titles so running the Page Title module simultaneously can lead to complications.'),
  87. );
  88. }
  89. // Add a note if the deprecated metatag.entity_translation.inc file still
  90. // exists.
  91. $filename = 'metatag.entity_translation.inc';
  92. if (file_exists(dirname(__FILE__) . '/' . $filename)) {
  93. $requirements['metatag_deprecated_et_file'] = array(
  94. 'severity' => REQUIREMENT_ERROR,
  95. 'title' => 'Metatag',
  96. 'value' => $t('Unwanted :filename file found', array(':filename' => $filename)),
  97. 'description' => $t("The :filename file was removed in v7.x-1.0-beta5 but it still exists in the site's Metatag module's directory and will cause problems. This file needs to be removed. The file's path in the Drupal directory structure is:<br /><code>!short_path</code><br />The file's full path is:<br /><code>!full_path</code>", array(':filename' => $filename, '!short_path' => drupal_get_path('module', 'metatag') . '/' . $filename, '!full_path' => dirname(__FILE__) . $filename)),
  98. );
  99. }
  100. // Check that Entity_Translation is current.
  101. if (module_exists('entity_translation')) {
  102. $rev = db_query("SELECT schema_version FROM {system} WHERE name = :module", array(':module' => 'entity_translation'))->fetchColumn();
  103. if ($rev < 7004) {
  104. $requirements['metatag_et_old'] = array(
  105. 'severity' => REQUIREMENT_ERROR,
  106. 'title' => 'Metatag',
  107. 'value' => $t('<a href="@url">Entity_Translation</a> is out of date and requires updating', array('@url' => 'https://www.drupal.org/project/entity_translation')),
  108. 'description' => $t('The Entity_Translation module is out of date and needs to be updated in order to be compatible with Metatag.'),
  109. );
  110. }
  111. }
  112. // It's recommended to install the Transliteration module to clean up file
  113. // paths for use with image meta tags.
  114. if (!module_exists('transliteration')) {
  115. $requirements['metatag_transliteration'] = array(
  116. 'severity' => REQUIREMENT_INFO,
  117. 'title' => 'Metatag',
  118. 'value' => $t('The Transliteration module is recommended.'),
  119. 'description' => $t("It is recommended to install the <a href=\"@url\">Transliteration module</a> to clean up filenames of uploaded files that may be used with image meta tags.", array('@url' => 'https://drupal.org/project/transliteration')),
  120. );
  121. }
  122. // It's recommended to install the Imagecache Token module to make image
  123. // tokens easier to do.
  124. if (!module_exists('imagecache_token')) {
  125. $requirements['metatag_imagecache_token'] = array(
  126. 'severity' => REQUIREMENT_INFO,
  127. 'title' => 'Metatag',
  128. 'value' => $t('The Imagecache Token module is recommended.'),
  129. 'description' => $t("It is recommended to install the <a href=\"@url\">Imagecache Token module</a> to make it easier to control image meta tags, e.g. og:image.", array('@url' => 'https://drupal.org/project/imagecache_token')),
  130. );
  131. }
  132. // The Admin Language module can cause problems.
  133. if (!module_exists('admin_language') && variable_get('admin_language_force_neutral', 0)) {
  134. $requirements['metatag_admin_language'] = array(
  135. 'severity' => REQUIREMENT_WARNING,
  136. 'title' => 'Metatag',
  137. 'value' => $t('Conflict with Admin Language module.'),
  138. 'description' => $t("Using the \"@option\" with Metatag can lead to data loss, so it is recommended to <a href=\"@url\">disable that option</a>.", array('@option' => t('Force language neutral aliases'), '@url' => url('admin/config/regional/language/admin_language'))),
  139. );
  140. }
  141. }
  142. return $requirements;
  143. }
  144. /**
  145. * Implements hook_schema().
  146. */
  147. function metatag_schema() {
  148. $schema['metatag_config'] = array(
  149. 'description' => 'Storage of meta tag configuration and defaults.',
  150. 'export' => array(
  151. 'key' => 'instance',
  152. 'key name' => 'Instance',
  153. 'primary key' => 'cid',
  154. 'identifier' => 'config',
  155. 'default hook' => 'metatag_config_default',
  156. 'api' => array(
  157. 'owner' => 'metatag',
  158. 'api' => 'metatag',
  159. 'minimum_version' => 1,
  160. 'current_version' => 1,
  161. ),
  162. 'cache defaults' => TRUE,
  163. 'default cache bin' => 'cache_metatag',
  164. ),
  165. 'fields' => array(
  166. 'cid' => array(
  167. 'type' => 'serial',
  168. 'unsigned' => TRUE,
  169. 'not null' => TRUE,
  170. 'description' => 'The primary identifier for a metatag configuration set.',
  171. 'no export' => TRUE,
  172. ),
  173. 'instance' => array(
  174. 'type' => 'varchar',
  175. 'length' => 255,
  176. 'not null' => TRUE,
  177. 'default' => '',
  178. 'description' => 'The machine-name of the configuration, typically entity-type:bundle.',
  179. ),
  180. 'config' => array(
  181. 'type' => 'blob',
  182. 'size' => 'big',
  183. 'not null' => TRUE,
  184. 'serialize' => TRUE,
  185. 'description' => 'Serialized data containing the meta tag configuration.',
  186. 'translatable' => TRUE,
  187. ),
  188. ),
  189. 'primary key' => array('cid'),
  190. 'unique keys' => array(
  191. 'instance' => array('instance'),
  192. ),
  193. );
  194. $schema['metatag'] = array(
  195. 'fields' => array(
  196. 'entity_type' => array(
  197. 'type' => 'varchar',
  198. 'length' => 32,
  199. 'not null' => TRUE,
  200. 'default' => '',
  201. 'description' => 'The entity type this data is attached to.',
  202. ),
  203. 'entity_id' => array(
  204. 'type' => 'int',
  205. 'unsigned' => TRUE,
  206. 'not null' => TRUE,
  207. 'default' => 0,
  208. 'description' => 'The entity id this data is attached to.',
  209. ),
  210. 'revision_id' => array(
  211. 'type' => 'int',
  212. 'unsigned' => TRUE,
  213. 'not null' => TRUE,
  214. 'default' => 0,
  215. 'description' => 'The revision_id for the entity object this data is attached to.',
  216. ),
  217. 'language' => array(
  218. 'type' => 'varchar',
  219. 'length' => 32,
  220. 'not null' => TRUE,
  221. 'default' => '',
  222. 'description' => 'The language of the tag.',
  223. ),
  224. 'data' => array(
  225. 'type' => 'blob',
  226. 'size' => 'big',
  227. 'not null' => TRUE,
  228. 'serialize' => TRUE,
  229. ),
  230. ),
  231. 'indexes' => array(
  232. 'type_revision' => array('entity_type','revision_id'),
  233. ),
  234. 'primary key' => array('entity_type', 'entity_id', 'revision_id', 'language'),
  235. );
  236. $schema['cache_metatag'] = drupal_get_schema_unprocessed('system', 'cache');
  237. $schema['cache_metatag']['description'] = t('Cache table for the generated meta tag output.');
  238. return $schema;
  239. }
  240. /**
  241. * Implements hook_install().
  242. */
  243. function metatag_install() {
  244. drupal_set_message(t("Thank you for installing the Metatag module. It is recommended to read the module's <a href=\"!url\" title=\"Read the Metatag module's documentation\">README.txt</a> file as there are some known issues that may affect this site.", array('!url' => url(drupal_get_path('module', 'metatag') . '/README.txt'))));
  245. }
  246. /**
  247. * Implements hook_uninstall().
  248. */
  249. function metatag_uninstall() {
  250. // This variable is created via hook_enable.
  251. variable_del('metatag_schema_installed');
  252. // Used to control whether 403/404 pages are cached.
  253. variable_del('metatag_cache_error_pages');
  254. // Used to make meta tags display on admin pages.
  255. variable_del('metatag_tag_admin_pages');
  256. // Temp variables, just in case they weren't removed already.
  257. variable_del('metatag_skip_update_7017');
  258. // Used to note that the schema for the main {metatag} table were sufficiently
  259. // updated.
  260. variable_del('metatag_has_revision_id');
  261. // Used to force an entity's default language values to be used if nothing
  262. // else matched.
  263. variable_del('metatag_entity_no_lang_default');
  264. // Controls which page region is used to trigger output of the meta tags.
  265. variable_del('metatag_page_region');
  266. // Optionally disable the default configurations.
  267. variable_del('metatag_load_defaults');
  268. }
  269. /**
  270. * Implements hook_enable().
  271. */
  272. function metatag_enable() {
  273. variable_set('metatag_schema_installed', TRUE);
  274. }
  275. /**
  276. * Implements hook_disable().
  277. */
  278. // function metatag_disable() {
  279. // }
  280. /**
  281. * Disable the deprecated metatag_ui module which has been merged into metatag.
  282. */
  283. function metatag_update_7000() {
  284. if (module_exists('metatag_ui')) {
  285. module_disable(array('metatag_ui'), FALSE);
  286. drupal_uninstall_modules(array('metatag_ui'), FALSE);
  287. }
  288. }
  289. /**
  290. * Fix the "{metatag_config}.cid column cannot be NULL" error.
  291. */
  292. function metatag_update_7001() {
  293. $table_name = 'metatag_config';
  294. $field_name = 'cid';
  295. $field_spec = array(
  296. 'type' => 'serial',
  297. 'unsigned' => TRUE,
  298. 'not null' => TRUE,
  299. 'description' => 'The primary identifier for a metatag configuration set.',
  300. );
  301. $keys = array('primary key' => array($field_name));
  302. // Before making any changes, drop the existing primary key.
  303. // Let's add a temporary unique key for cid so MySQL will let it go.
  304. // Hint taken from https://drupal.org/node/2064305#comment-7753197.
  305. db_add_unique_key($table_name, 'temp_key', array($field_name, 'instance'));
  306. // Unforunately there is no API way to check if a primary key exists, so if
  307. // it doesn't exist the db_drop_primary_key() call will fail.
  308. try {
  309. db_drop_primary_key($table_name);
  310. }
  311. catch (Exception $e) {
  312. drupal_set_message('Caught an exception: ', $e->getMessage());
  313. }
  314. // Rejig the field, and turn on the primary key again.
  315. db_change_field($table_name, $field_name, $field_name, $field_spec, $keys);
  316. // Finally, remove the temporary unique key because it's no longer useful.
  317. db_drop_unique_key($table_name, 'temp_key');
  318. }
  319. /**
  320. * Disable the deprecated metatag_ui module which has been merged into metatag,
  321. * again.
  322. */
  323. function metatag_update_7002() {
  324. if (module_exists('metatag_ui')) {
  325. module_disable(array('metatag_ui'), FALSE);
  326. drupal_uninstall_modules(array('metatag_ui'), FALSE);
  327. drupal_set_message(t('The deprecated Metatag UI module has been disabled.'));
  328. }
  329. }
  330. /**
  331. * Add the {metatag}.language field.
  332. */
  333. function metatag_update_7003() {
  334. // Set the target table and field name.
  335. $table_name = 'metatag';
  336. $field_name = 'language';
  337. // Don't add the new field if it already exists.
  338. if (!db_field_exists($table_name, $field_name)) {
  339. // Describe the new field.
  340. $field_spec = array(
  341. 'type' => 'varchar',
  342. 'length' => 32,
  343. 'not null' => TRUE,
  344. 'default' => '',
  345. 'description' => 'The language of the tag',
  346. );
  347. // Add it and update the primary key.
  348. db_add_field($table_name, $field_name, $field_spec);
  349. db_drop_primary_key($table_name);
  350. db_add_primary_key($table_name, array('entity_type', 'entity_id', 'language'));
  351. }
  352. }
  353. /**
  354. * Replaced by updates 7009, 7010, 7011, 7012 and 7013.
  355. */
  356. function metatag_update_7004() {
  357. // Do nothing.
  358. }
  359. /**
  360. * Removing wrong metatag watchdog entries that break the admin/reports/dblog
  361. * page.
  362. */
  363. function metatag_update_7005() {
  364. if (db_table_exists('watchdog')) {
  365. db_delete('watchdog')
  366. ->condition('type', 'metatag')
  367. ->condition('variables', serialize('info'))
  368. ->execute();
  369. }
  370. }
  371. /**
  372. * Remove {metatag} records that were added by old versions of the module for
  373. * entities that don't actually support Metatag. A more complete version of
  374. * this will be added later on after it's (hopefully) guaranteed that all
  375. * modules have updated to the correct API usage.
  376. */
  377. function metatag_update_7006() {
  378. $entity_types = array(
  379. // Core.
  380. 'comment',
  381. 'menu_link',
  382. 'taxonomy_vocabulary',
  383. // Some contrib entities.
  384. 'mailchimp_list',
  385. 'profile2',
  386. 'profile2_type',
  387. 'redirect',
  388. 'rules_config',
  389. 'wysiwyg_profile',
  390. );
  391. foreach ($entity_types as $entity_type) {
  392. $num_deleted = db_delete('metatag')
  393. ->condition('entity_type', $entity_type)
  394. ->execute();
  395. if ($num_deleted > 0) {
  396. drupal_set_message(t('Removed @count meta tag record(s) for the @type entity type, it does not support meta tags.', array('@count' => $num_deleted, '@type' => $entity_type)));
  397. }
  398. }
  399. }
  400. /**
  401. * Remove {metatag} records for nodes, users and taxonomy terms that have been
  402. * deleted; older versions of Metatag may have failed to purge these.
  403. */
  404. function metatag_update_7007() {
  405. $nodes = db_query("SELECT m.entity_id
  406. FROM {metatag} m
  407. LEFT OUTER JOIN {node} n
  408. ON m.entity_id=n.nid
  409. WHERE m.entity_type='node'
  410. AND n.nid IS NULL")
  411. ->fetchCol();
  412. if (count($nodes) > 0) {
  413. $deleted = db_delete('metatag')
  414. ->condition('entity_type', 'node')
  415. ->condition('entity_id', $nodes)
  416. ->execute();
  417. if ($deleted > 0) {
  418. drupal_set_message(t('Removed @count meta tag record(s) for nodes that had been purged.', array('@count' => $deleted)));
  419. }
  420. else {
  421. drupal_set_message(t('There were no meta tag records to purge for removed nodes. This is a good thing :)'));
  422. }
  423. }
  424. $users = db_query("SELECT m.entity_id
  425. FROM {metatag} m
  426. LEFT OUTER JOIN {users} u
  427. ON m.entity_id=u.uid
  428. WHERE m.entity_type='user'
  429. AND u.uid IS NULL")
  430. ->fetchCol();
  431. if (count($users) > 0) {
  432. $deleted = db_delete('metatag')
  433. ->condition('entity_type', 'user')
  434. ->condition('entity_id', $users)
  435. ->execute();
  436. if ($deleted > 0) {
  437. drupal_set_message(t('Removed @count meta tag record(s) for users that had been purged.', array('@count' => $deleted)));
  438. }
  439. else {
  440. drupal_set_message(t('There were no meta tag records to purge for removed users. This is a good thing :)'));
  441. }
  442. }
  443. // Only run this if the Taxonomy module is enabled.
  444. if (module_exists('taxonomy')) {
  445. $terms = db_query("SELECT m.entity_id
  446. FROM {metatag} m
  447. LEFT OUTER JOIN {taxonomy_term_data} t
  448. ON m.entity_id=t.tid
  449. WHERE m.entity_type='taxonomy_term'
  450. AND t.tid IS NULL")
  451. ->fetchCol();
  452. if (count($terms) > 0) {
  453. $deleted = db_delete('metatag')
  454. ->condition('entity_type', 'taxonomy_term')
  455. ->condition('entity_id', $terms)
  456. ->execute();
  457. if ($deleted > 0) {
  458. drupal_set_message(t('Removed @count meta tag record(s) for taxonomy terms that had been purged.', array('@count' => $deleted)));
  459. }
  460. else {
  461. drupal_set_message(t('There were no meta tag records to purge for removed taxonomy terms. This is a good thing :)'));
  462. }
  463. }
  464. }
  465. }
  466. /**
  467. * Remove any empty records that may be hanging around from old releases.
  468. */
  469. function metatag_update_7008() {
  470. $conditions = db_or()
  471. ->isNull('data')
  472. ->condition('data', '')
  473. ->condition('data', serialize(array()));
  474. $deleted = db_delete("metatag")
  475. ->condition($conditions)
  476. ->execute();
  477. if ($deleted > 0) {
  478. drupal_set_message(t('Purged @count empty meta tag record(s).', array('@count' => $deleted)));
  479. }
  480. }
  481. /**
  482. * Fix {metatag} records for taxonomy terms.
  483. */
  484. function metatag_update_7009() {
  485. if (module_exists('taxonomy')) {
  486. // Fix the {metatag} table first.
  487. metatag_update_7015();
  488. // Remove duplicates.
  489. _metatag_remove_dupes('taxonomy_term');
  490. }
  491. // The taxonomy term entity doesn't support a 'language' option, so reset it
  492. // to LANGUAGE_NONE.
  493. $result = db_query("UPDATE {metatag} SET language = :language WHERE entity_type='taxonomy_term'", array(':language' => LANGUAGE_NONE));
  494. if ($result->rowCount() > 0) {
  495. drupal_set_message(t('Fixed language values for @count taxonomy terms.', array('@count' => $result->rowCount())));
  496. }
  497. }
  498. /**
  499. * Fix {metatag} records for users.
  500. */
  501. function metatag_update_7010() {
  502. // Fix the {metatag} table first.
  503. metatag_update_7015();
  504. // Remove duplicates.
  505. _metatag_remove_dupes('user');
  506. // Update User values.
  507. $result = db_query("UPDATE {metatag} SET language = :language WHERE entity_type='user'", array(':language' => LANGUAGE_NONE));
  508. if ($result->rowCount() > 0) {
  509. drupal_set_message(t('Fixed language values for @count user records.', array('@count' => $result->rowCount())));
  510. }
  511. }
  512. /**
  513. * Fix {metatag} records for nodes.
  514. */
  515. function metatag_update_7011(&$sandbox) {
  516. // Fix the {metatag} table first.
  517. metatag_update_7015();
  518. // Only proceed if Entity_Translation is not enabled as it allows each node
  519. // record to have multiple languages available.
  520. if (module_exists('entity_translation')) {
  521. drupal_set_message(t("Entity Translation is enabled, so node meta tags will not be updated, to avoid accidental dataloss."));
  522. return;
  523. }
  524. // Process records by groups of 10 (arbitrary value).
  525. // When a group is processed, the batch update engine determines whether it
  526. // should continue processing in the same request or provide progress
  527. // feedback to the user and wait for the next request.
  528. $limit = 10;
  529. // When ran through Drush it's Ok to process a larger number of objects at a
  530. // time.
  531. if (drupal_is_cli()) {
  532. $limit = 100;
  533. }
  534. // Use the sandbox at your convenience to store the information needed
  535. // to track progression between successive calls to the function.
  536. if (!isset($sandbox['progress'])) {
  537. // The count of records visited so far.
  538. $sandbox['progress'] = 0;
  539. // Remove duplicates.
  540. _metatag_remove_dupes('node');
  541. // Update Node values.
  542. $nodes = db_query("SELECT n.nid, n.language FROM {node} n INNER JOIN {metatag} m ON n.nid = m.entity_id WHERE m.entity_type = 'node' AND n.language != m.language ORDER BY nid");
  543. $sandbox['records'] = array();
  544. foreach ($nodes as $record) {
  545. $sandbox['records'][] = $record;
  546. }
  547. // If there's no data, don't bother with the extra work.
  548. if (empty($sandbox['records'])) {
  549. watchdog('metatag', 'Update 7011: No nodes need the Metatag language values fixed.', array(), WATCHDOG_INFO);
  550. if (drupal_is_cli()) {
  551. drupal_set_message(t('Update 7011: No nodes need the Metatag language values fixed.'));
  552. }
  553. return t('No nodes need the Metatag language values fixed.');
  554. }
  555. // Total records that must be visited.
  556. $sandbox['max'] = count($sandbox['records']);
  557. // A place to store messages during the run.
  558. $sandbox['messages'] = array();
  559. // An initial record of the number of records to be updated.
  560. watchdog('metatag', 'Update 7011: !count records to update.', array('!count' => $sandbox['max']), WATCHDOG_INFO);
  561. if (drupal_is_cli()) {
  562. drupal_set_message(t('Update 7011: !count records to update.', array('!count' => $sandbox['max'])));
  563. }
  564. // Last record processed.
  565. $sandbox['current_record'] = -1;
  566. // Because a lot of other processing happens on the first iteration, just do
  567. // one.
  568. $limit = 1;
  569. }
  570. // Set default values.
  571. for ($ctr = 0; $ctr < $limit; $ctr++) {
  572. $sandbox['current_record']++;
  573. if (empty($sandbox['records'][$sandbox['current_record']])) {
  574. break;
  575. }
  576. // Shortcuts for later.
  577. $langcode = $sandbox['records'][$sandbox['current_record']]->language;
  578. $nid = $sandbox['records'][$sandbox['current_record']]->nid;
  579. db_update('metatag')
  580. ->fields(array('language' => $langcode))
  581. ->condition('entity_type', 'node')
  582. ->condition('entity_id', $nid)
  583. ->execute();
  584. // Update our progress information.
  585. $sandbox['progress']++;
  586. }
  587. // Set the "finished" status, to tell batch engine whether this function
  588. // needs to run again. If you set a float, this will indicate the progress of
  589. // the batch so the progress bar will update.
  590. $sandbox['#finished'] = ($sandbox['progress'] >= $sandbox['max']) ? TRUE : ($sandbox['progress'] / $sandbox['max']);
  591. if ($sandbox['#finished']) {
  592. // Clear all caches so the fixed data will be reloaded.
  593. cache_clear_all('*', 'cache_metatag', TRUE);
  594. // A final log of the number of records that were converted.
  595. watchdog('metatag', 'Update 7011: !count records were updated in total.', array('!count' => $sandbox['progress']), WATCHDOG_INFO);
  596. if (drupal_is_cli()) {
  597. drupal_set_message(t('Update 7011: !count records were updated.', array('!count' => $sandbox['progress'])));
  598. }
  599. // hook_update_N() may optionally return a string which will be displayed
  600. // to the user.
  601. return t('Fixed the Metatag language values for @count nodes.', array('@count' => $sandbox['progress']));
  602. }
  603. }
  604. /**
  605. * Remove duplicate {metatag} records for non-core entities.
  606. */
  607. function metatag_update_7012() {
  608. // Fix the {metatag} table first.
  609. metatag_update_7015();
  610. if (module_exists('entity_translation')) {
  611. drupal_set_message(t("Entity Translation is enabled, duplicate meta tags will not be removed for custom entities, to avoid accidental dataloss."));
  612. return;
  613. }
  614. $records = db_select('metatag', 'm')
  615. ->fields('m', array('entity_type'))
  616. ->condition('m.entity_type', array('node', 'taxonomy_term', 'user'), 'NOT IN')
  617. ->orderBy('m.entity_type', 'ASC')
  618. ->orderBy('m.entity_id', 'ASC')
  619. ->distinct()
  620. ->execute();
  621. $entity_types = array();
  622. foreach ($records as $record) {
  623. $entity_types[] = $record->entity_type;
  624. // Remove duplicates.
  625. _metatag_remove_dupes($record->entity_type);
  626. }
  627. if (empty($entity_types)) {
  628. drupal_set_message(t('There were no other records to fix.'));
  629. }
  630. }
  631. /**
  632. * Fix the {metatag} language value for all non-core entity records. This might
  633. * take a while, depending on how much data needs to be converted.
  634. */
  635. function metatag_update_7013(&$sandbox) {
  636. // Fix the {metatag} table first.
  637. metatag_update_7015();
  638. if (module_exists('entity_translation')) {
  639. drupal_set_message(t("Entity Translation is enabled, meta tags will not be updated for custom entities, to avoid accidental dataloss."));
  640. return;
  641. }
  642. // Use the sandbox at your convenience to store the information needed
  643. // to track progression between successive calls to the function.
  644. if (!isset($sandbox['progress'])) {
  645. // The count of records visited so far.
  646. $sandbox['progress'] = 0;
  647. // Because the {metatag} table uses multiple primary keys, there's no easy
  648. // way to do this, so we're going to cache all record keys and manually
  649. // step through them.
  650. $records = db_select('metatag', 'm')
  651. ->fields('m', array('entity_type', 'entity_id'))
  652. ->condition('m.entity_type', array('node', 'taxonomy_term', 'user'), 'NOT IN')
  653. ->orderBy('m.entity_type', 'ASC')
  654. ->orderBy('m.entity_id', 'ASC')
  655. ->execute();
  656. $sandbox['records'] = array();
  657. foreach ($records as $record) {
  658. $sandbox['records'][] = $record;
  659. }
  660. // If there's no data, don't bother with the extra work.
  661. if (empty($sandbox['records'])) {
  662. watchdog('metatag', 'Update 7013: No meta tag records need updating.', array(), WATCHDOG_INFO);
  663. if (drupal_is_cli()) {
  664. drupal_set_message(t('Update 7013: No meta tag records need updating.'));
  665. }
  666. return t('No meta tag records need updating.');
  667. }
  668. // Total records that must be visited.
  669. $sandbox['max'] = count($sandbox['records']);
  670. // A place to store messages during the run.
  671. $sandbox['messages'] = array();
  672. // An initial record of the number of records to be updated.
  673. watchdog('metatag', 'Update 7013: !count records to update.', array('!count' => $sandbox['max']), WATCHDOG_INFO);
  674. if (drupal_is_cli()) {
  675. drupal_set_message(t('Update 7013: !count records to update.', array('!count' => $sandbox['max'])));
  676. }
  677. // Last record processed.
  678. $sandbox['current_record'] = -1;
  679. }
  680. // Process records by groups of 10 (arbitrary value).
  681. // When a group is processed, the batch update engine determines whether it
  682. // should continue processing in the same request or provide progress
  683. // feedback to the user and wait for the next request.
  684. $limit = 10;
  685. // When ran through Drush it's Ok to process a larger number of objects at a
  686. // time.
  687. if (drupal_is_cli()) {
  688. $limit = 100;
  689. }
  690. // Set default values.
  691. for ($ctr = 0; $ctr < $limit; $ctr++) {
  692. $sandbox['current_record']++;
  693. if (empty($sandbox['records'][$sandbox['current_record']])) {
  694. break;
  695. }
  696. // Shortcuts for later.
  697. $entity_type = $sandbox['records'][$sandbox['current_record']]->entity_type;
  698. $entity_id = $sandbox['records'][$sandbox['current_record']]->entity_id;
  699. // Load the entity.
  700. $entities = entity_load($entity_type, array($entity_id));
  701. if (!empty($entities)) {
  702. $entity = array_pop($entities);
  703. // Make sure that the entity has a language set.
  704. if (!empty($entity)) {
  705. // If there's a (non-empty) language value, use it.
  706. $new_language = entity_language($entity_type, $entity);
  707. if (empty($new_language)) {
  708. $new_language = LANGUAGE_NONE;
  709. }
  710. // Update the 'language' value.
  711. db_update('metatag')
  712. ->fields(array('language' => $new_language))
  713. ->condition('entity_type', $entity_type)
  714. ->condition('entity_id', $entity_id)
  715. ->execute();
  716. }
  717. }
  718. // Update our progress information.
  719. $sandbox['progress']++;
  720. }
  721. // Set the "finished" status, to tell batch engine whether this function
  722. // needs to run again. If you set a float, this will indicate the progress of
  723. // the batch so the progress bar will update.
  724. $sandbox['#finished'] = ($sandbox['progress'] >= $sandbox['max']) ? TRUE : ($sandbox['progress'] / $sandbox['max']);
  725. if ($sandbox['#finished']) {
  726. // Clear all caches so the fixed data will be reloaded.
  727. cache_clear_all('*', 'cache_metatag', TRUE);
  728. // A final log of the number of records that were converted.
  729. watchdog('metatag', 'Update 7013: !count records were updated in total.', array('!count' => $sandbox['progress']), WATCHDOG_INFO);
  730. if (drupal_is_cli()) {
  731. drupal_set_message(t('Update 7013: !count records were updated.', array('!count' => $sandbox['progress'])));
  732. }
  733. // hook_update_N() may optionally return a string which will be displayed
  734. // to the user.
  735. return t('!count records were updated in total.', array('!count' => $sandbox['progress']));
  736. }
  737. }
  738. /**
  739. * Remove duplicate records for a given entity.
  740. *
  741. * It should be OK to run this without doing a separate batch process as there
  742. * shouldn't be many records that have this problem. Hopefully.
  743. *
  744. * @param $entity_type
  745. * The name of an entity type to check for.
  746. */
  747. function _metatag_remove_dupes($entity_type) {
  748. $purge_count = 0;
  749. // First step: fix the records. There should not be multiple records for the
  750. // same entity_id with different languages.
  751. $dupe_records = db_query("SELECT m.entity_id, count(m.language) AS the_count
  752. FROM {metatag} m
  753. WHERE
  754. m.entity_type = :type
  755. GROUP BY m.entity_id
  756. HAVING count(m.language) > 1", array(':type' => $entity_type));
  757. if (!empty($dupe_records)) {
  758. foreach ($dupe_records as $record) {
  759. $entity_id = $record->entity_id;
  760. $langs = db_query("SELECT m.entity_id, m.language, m.data FROM {metatag} m WHERE m.entity_type = :type AND m.entity_id = :id", array(':type' => $entity_type, ':id' => $entity_id))->fetchAll();
  761. // Work out which language record to remove. Will need to store this as
  762. // an array incase there are multiple records to purge.
  763. $langs_to_remove = array();
  764. // Check for duplicate records.
  765. // Outer loop starts from the beginning.
  766. for ($outer = 0; $outer < count($langs); $outer++) {
  767. // This record may have been removed already.
  768. if (isset($langs[$outer])) {
  769. // Inner loop starts from the end.
  770. for ($inner = count($langs) - 1; $inner > 0; $inner--) {
  771. // Work out if the outer loop's data is the same as the inner
  772. // loop's.
  773. if (isset($langs[$inner]) && $langs[$outer]->data == $langs[$inner]->data) {
  774. // Remove the second record.
  775. $langs_to_remove[] = $langs[$inner]->language;
  776. unset($langs[$inner]);
  777. }
  778. }
  779. }
  780. }
  781. // Only one record left.
  782. if (count($langs) == 1) {
  783. // This is how it should be, this record is fine.
  784. }
  785. // More than one record, work out which one to keep.
  786. elseif (count($langs) > 1) {
  787. // Work out the entity's language.
  788. $entity = entity_load($entity_type, $entity_id);
  789. $entity_language = entity_language($entity_type, $entity);
  790. if (empty($language)) {
  791. $entity_language = LANGUAGE_NONE;
  792. }
  793. // Work out if the entity's language record exists.
  794. $lang_pos = NULL;
  795. foreach ($langs as $key => $record) {
  796. if ($record->language == $entity_language) {
  797. $lang_pos = $key;
  798. break;
  799. }
  800. }
  801. // If the language record exists, delete the others.
  802. if (isset($lang_pos)) {
  803. foreach ($langs as $key => $record) {
  804. if ($record->language != $entity_language) {
  805. $langs_to_remove[] = $record->language;
  806. }
  807. }
  808. }
  809. // Otherwise look for a record for the site's default language.
  810. else {
  811. foreach ($langs as $key => $record) {
  812. if ($record->language == $GLOBALS['language']->language) {
  813. $lang_pos = $key;
  814. break;
  815. }
  816. }
  817. if (isset($lang_pos)) {
  818. foreach ($langs as $key => $record) {
  819. if ($record->language != $GLOBALS['language']->language) {
  820. $langs_to_remove[] = $record->language;
  821. }
  822. }
  823. }
  824. // Finally check for LANGUAGE_NONE.
  825. else {
  826. foreach ($langs as $key => $record) {
  827. if ($record->language == LANGUAGE_NONE) {
  828. $lang_pos = $key;
  829. break;
  830. }
  831. }
  832. if (isset($lang_pos)) {
  833. foreach ($langs as $key => $record) {
  834. if ($record->language != LANGUAGE_NONE) {
  835. $langs_to_remove[] = $record->language;
  836. }
  837. }
  838. }
  839. }
  840. }
  841. }
  842. // Purge the redundant records.
  843. if (!empty($langs_to_remove)) {
  844. $purge_count += db_delete('metatag')
  845. ->condition('entity_type', $entity_type)
  846. ->condition('entity_id', $entity_id)
  847. ->condition('language', $langs_to_remove)
  848. ->execute();
  849. }
  850. }
  851. }
  852. if (empty($purge_count)) {
  853. drupal_set_message(t('No duplicate :entity_type records were found (this is a good thing).', array(':entity_type' => $entity_type)));
  854. watchdog('metatag', 'No duplicate :entity_type records were found (this is a good thing).', array(':entity_type' => $entity_type));
  855. }
  856. else {
  857. drupal_set_message(t('Purged :count duplicate :entity_type record(s).', array(':count' => $purge_count, ':entity_type' => $entity_type)));
  858. watchdog('metatag', 'Purged :count duplicate :entity_type record(s).', array(':count' => $purge_count, ':entity_type' => $entity_type));
  859. return;
  860. }
  861. }
  862. /**
  863. * Fix {metatag} records that may have been corrupted by #1871020.
  864. */
  865. function metatag_update_7014() {
  866. $records = db_query("SELECT *
  867. FROM {metatag} m
  868. WHERE
  869. m.data LIKE :nolang
  870. OR m.data LIKE :lang
  871. OR m.data LIKE :und",
  872. array(
  873. ':nolang' => 'a:1:{s:0:"";a:%:{s:%;a:%:{%;}}}',
  874. ':lang' => 'a:1:{s:2:"__";a:%:{s:%;a:%:{%;}}}',
  875. ':und' => 'a:1:{s:3:"___";a:%:{s:%;a:%:{%;}}}',
  876. ));
  877. // Nothing to fix.
  878. if ($records->rowCount() == 0) {
  879. drupal_set_message(t('No corrupt records to fix, this is good news :-)'));
  880. }
  881. // Fix the faulty records.
  882. else {
  883. foreach ($records as $record) {
  884. // Extract the data and get the first element of the array, this should be
  885. // valid data.
  886. $record->data = reset(unserialize($record->data));
  887. // Update the record.
  888. drupal_write_record('metatag', $record, array('entity_type', 'entity_id', 'language'));
  889. }
  890. drupal_set_message(t('Fixed @count corrupt meta tag record(s).', array('@count' => $records->rowCount())));
  891. }
  892. }
  893. /**
  894. * Add the revision_id from the entity into metatag schema, adjust the primary
  895. * keys accordingly.
  896. */
  897. function metatag_update_7015() {
  898. if (!db_field_exists('metatag', 'revision_id')) {
  899. // Leave a note for metatag_metatags_load_multiple() that the revision_id
  900. // field has been added.
  901. variable_set('metatag_has_revision_id', TRUE);
  902. // Tell update 7017 that it isn't needed.
  903. variable_set('metatag_skip_update_7017', TRUE);
  904. // Add the new field.
  905. db_add_field('metatag', 'revision_id', array(
  906. 'type' => 'int',
  907. 'unsigned' => TRUE,
  908. 'not null' => TRUE,
  909. 'default' => 0,
  910. 'description' => 'The revision_id for the entity object this data is attached to.',
  911. ));
  912. // Remove the existing primary key. This may take some work so it can be
  913. // database agnostic, i.e. some databases will not like it.
  914. db_drop_primary_key('metatag');
  915. // Add the new primary key.
  916. db_add_primary_key('metatag', array('entity_type', 'entity_id', 'revision_id', 'language'));
  917. drupal_set_message(t('Added the {metatag}.revision_id field.'));
  918. }
  919. else {
  920. drupal_set_message(t('The {metatag}.revision_id field has already been added, nothing to do.'));
  921. }
  922. }
  923. /**
  924. * Update the revision ID to fix the NULL values, help avoid problems with
  925. * update 7017.
  926. */
  927. function metatag_update_7016() {
  928. // It's possible that 7015 was not executed if the site had been updated to
  929. // an early dev release, so make sure the revision_id field exists.
  930. metatag_update_7015();
  931. // Run the update.
  932. db_query("UPDATE {metatag} SET revision_id = 0 WHERE revision_id IS NULL");
  933. }
  934. /**
  935. * The {metatag}.revision_id field is required.
  936. */
  937. function metatag_update_7017() {
  938. if (!variable_get('metatag_skip_update_7017', FALSE)) {
  939. // Let's add a temporary unique key so MySQL will let it go.
  940. db_add_unique_key('metatag', 'temp_key', array('entity_type', 'entity_id', 'revision_id', 'language'));
  941. // Now remove the PK before changing a field from serial.
  942. db_drop_primary_key('metatag');
  943. // Change the field.
  944. db_change_field('metatag', 'revision_id', 'revision_id', array(
  945. 'type' => 'int',
  946. 'unsigned' => TRUE,
  947. 'not null' => TRUE,
  948. 'default' => 0,
  949. 'description' => 'The revision_id for the entity object this data is attached to.',
  950. ));
  951. // Manually re-add the PK.
  952. db_add_primary_key('metatag', array('entity_type', 'entity_id', 'revision_id', 'language'));
  953. // Finally, remove the temporary unique key because it's no longer useful.
  954. db_drop_unique_key('metatag', 'temp_key');
  955. drupal_set_message(t('Fixed the {metatag}.revision_id field.'));
  956. }
  957. else {
  958. drupal_set_message(t("Didn't need to fix the {metatag}.revision_id field; please disperse, nothing to see here."));
  959. }
  960. // Delete the temporary variable.
  961. variable_del('metatag_skip_update_7017');
  962. }
  963. /**
  964. * Update the revision ID for each record. This may take some time. Should any
  965. * nodes be discovered with a meta tag record for both revision_id 0 and the
  966. * correct revision_id, the "0" value will be deleted; if this is not the
  967. * desired result the {metatag} table must be manually pruned to have the
  968. * correct records prior to letting this update run.
  969. */
  970. function metatag_update_7018(&$sandbox) {
  971. // Process records in small groups.
  972. // When a group is processed, the batch update engine determines whether it
  973. // should continue processing in the same request or provide progress
  974. // feedback to the user and wait for the next request.
  975. $limit = 10;
  976. // When ran through Drush it's Ok to process a larger number of objects at a
  977. // time.
  978. if (drupal_is_cli()) {
  979. $limit = 100;
  980. }
  981. // Use the sandbox at your convenience to store the information needed
  982. // to track progression between successive calls to the function.
  983. if (!isset($sandbox['progress'])) {
  984. // The count of records visited so far.
  985. $sandbox['progress'] = 0;
  986. // Get a list of all records affected.
  987. $sandbox['records'] = db_query("SELECT entity_type, entity_id, language
  988. FROM {metatag}
  989. WHERE revision_id = 0")
  990. ->fetchAll();
  991. // If there's no data, don't bother with the extra work.
  992. if (empty($sandbox['records'])) {
  993. watchdog('metatag', 'Update 7018: No {metatag} records needed to have the revision_id value fixed.', array(), WATCHDOG_INFO);
  994. if (drupal_is_cli()) {
  995. drupal_set_message(t('Update 7018: No {metatag} records needed to have the revision_id value fixed.'));
  996. }
  997. return t('No {metatag} records needed to have the revision_id value fixed.');
  998. }
  999. // Total records that must be visited.
  1000. $sandbox['max'] = count($sandbox['records']);
  1001. // A place to store messages during the run.
  1002. $sandbox['messages'] = array();
  1003. // An initial record of the number of records to be updated.
  1004. watchdog('metatag', 'Update 7018: !count records to update.', array('!count' => $sandbox['max']), WATCHDOG_INFO);
  1005. if (drupal_is_cli()) {
  1006. drupal_set_message(t('Update 7018: !count records to update.', array('!count' => $sandbox['max'])));
  1007. }
  1008. // Last record processed.
  1009. $sandbox['current_record'] = -1;
  1010. // Because a lot of other processing happens on the first iteration, just do
  1011. // one.
  1012. $limit = 1;
  1013. }
  1014. // Work out which entities support languages and revisions.
  1015. $has_language = array();
  1016. $has_revisions = array();
  1017. foreach (entity_get_info() as $entity_type => $info) {
  1018. $has_language[$entity_type] = FALSE;
  1019. $has_revisions[$entity_type] = FALSE;
  1020. if (!empty($info['entity keys']['language'])) {
  1021. $has_language[$entity_type] = $info['entity keys']['language'];
  1022. }
  1023. if (!empty($info['entity keys']['revision'])) {
  1024. $has_revisions[$entity_type] = $info['entity keys']['revision'];
  1025. }
  1026. }
  1027. // Set default values.
  1028. for ($ctr = 0; $ctr < $limit; $ctr++) {
  1029. $sandbox['current_record']++;
  1030. if (empty($sandbox['records'][$sandbox['current_record']])) {
  1031. break;
  1032. }
  1033. // Shortcuts for later.
  1034. $entity_type = $sandbox['records'][$sandbox['current_record']]->entity_type;
  1035. $entity_id = $sandbox['records'][$sandbox['current_record']]->entity_id;
  1036. // Make sure to load the correct language record.
  1037. $language = $sandbox['records'][$sandbox['current_record']]->language;
  1038. $conditions = array();
  1039. // Some entities don't include a language value.
  1040. if (!empty($has_language[$entity_type])) {
  1041. $conditions['language'] = $language;
  1042. }
  1043. $records = entity_load($entity_type, array($entity_id), $conditions);
  1044. // Fix this record.
  1045. if (!empty($records)) {
  1046. $entity = reset($records);
  1047. // Speed up the handling of entities that don't support revisions.
  1048. $revision_id = 0;
  1049. if (!empty($has_revisions[$entity_type])) {
  1050. list($entity_id, $revision_id, $bundle) = entity_extract_ids($entity_type, $entity);
  1051. $revision_id = intval($revision_id);
  1052. }
  1053. // Don't bother updating records if the revision_id is 0.
  1054. if (!empty($revision_id)) {
  1055. $exists = db_query("SELECT entity_id
  1056. FROM {metatag}
  1057. WHERE entity_type = :entity_type
  1058. AND entity_id = :entity_id
  1059. AND revision_id = :revision_id
  1060. AND language = :language",
  1061. array(
  1062. ':entity_type' => $entity_type,
  1063. ':entity_id' => $entity_id,
  1064. ':revision_id' => $revision_id,
  1065. ':language' => $language,
  1066. ))->fetchObject();
  1067. // There isn't already a record for the revision_id, so update the
  1068. // metatag record.
  1069. if (!$exists) {
  1070. db_update('metatag')
  1071. ->fields(array('revision_id' => $revision_id))
  1072. ->condition('entity_type', $entity_type)
  1073. ->condition('entity_id', $entity_id)
  1074. ->condition('revision_id', 0)
  1075. ->condition('language', $language)
  1076. ->execute();
  1077. }
  1078. // The record exists, so delete the old one under the grounds that the
  1079. // one with a revision_id is newer.
  1080. // Disclaimer: this is completely arbitrary, without providing a UI to
  1081. // let the site maintainer/builder choose which of the two records to
  1082. // keep, we're stuck with a bad scenario. Thankfully this should not
  1083. // happen very often and would only affect sites that were running a
  1084. // dev release. Also, sorry :(
  1085. else {
  1086. db_delete('metatag')
  1087. ->condition('entity_type', $entity_type)
  1088. ->condition('entity_id', $entity_id)
  1089. ->condition('revision_id', 0)
  1090. ->condition('language', $language)
  1091. ->execute();
  1092. }
  1093. // Nodes can have multiple revisions, so create new {metatag} records
  1094. // for each of the other revisions.
  1095. if ($entity_type == 'node') {
  1096. $revisions = node_revision_list($entity);
  1097. if (count($revisions) > 1) {
  1098. $metatags = db_query("SELECT data
  1099. FROM {metatag}
  1100. WHERE entity_type = :entity_type
  1101. AND entity_id = :entity_id
  1102. AND language = :language",
  1103. array(
  1104. ':entity_type' => $entity_type,
  1105. ':entity_id' => $entity_id,
  1106. ':language' => $language,
  1107. ));
  1108. if (!empty($metatags) && isset($metatags->data) && !empty($metatags->data)) {
  1109. foreach ($revisions as $vid => $revision) {
  1110. // Only one record per nid/vid/langcode, thank you.
  1111. if ($vid != $revision_id) {
  1112. // Check that there isn't already a record for this revision.
  1113. $exists = db_query("SELECT entity_id
  1114. FROM {metatag}
  1115. WHERE entity_type = :entity_type
  1116. AND entity_id = :entity_id
  1117. AND revision_id = :revision_id
  1118. AND language = :language",
  1119. array(
  1120. ':entity_type' => $entity_type,
  1121. ':entity_id' => $entity_id,
  1122. ':revision_id' => $vid,
  1123. ':language' => $language,
  1124. ))->fetchObject();
  1125. if (!$exists) {
  1126. $node = node_load($entity_id, $vid);
  1127. $record = new StdClass();
  1128. $record->entity_type = $entity_type;
  1129. $record->entity_id = $entity_id;
  1130. $record->revision_id = $vid;
  1131. $record->language = $language;
  1132. $record->data = $metatags->data;
  1133. drupal_write_record('metatag', $record);
  1134. }
  1135. }
  1136. }
  1137. }
  1138. }
  1139. }
  1140. // Other entity types.
  1141. else {
  1142. drupal_set_message(t('Metatag records for @type objects have not been checked for revisions.', array('@type' => $entity_type)), 'status', FALSE);
  1143. }
  1144. }
  1145. }
  1146. // Update our progress information.
  1147. $sandbox['progress']++;
  1148. }
  1149. // Set the "finished" status, to tell batch engine whether this function
  1150. // needs to run again. If you set a float, this will indicate the progress of
  1151. // the batch so the progress bar will update.
  1152. $sandbox['#finished'] = ($sandbox['progress'] >= $sandbox['max']) ? TRUE : ($sandbox['progress'] / $sandbox['max']);
  1153. if ($sandbox['#finished']) {
  1154. // Clear all caches so the fixed data will be reloaded.
  1155. cache_clear_all('*', 'cache_metatag', TRUE);
  1156. // A final log of the number of records that were converted.
  1157. watchdog('metatag', 'Update 7018: !count records were updated in total.', array('!count' => $sandbox['progress']), WATCHDOG_INFO);
  1158. if (drupal_is_cli()) {
  1159. drupal_set_message(t('Update 7018: !count records were updated.', array('!count' => $sandbox['progress'])));
  1160. }
  1161. // hook_update_N() may optionally return a string which will be displayed
  1162. // to the user.
  1163. return t('Fixed the revision_id values for !count {metatag} records.', array('!count' => $sandbox['progress']));
  1164. }
  1165. }
  1166. /**
  1167. * Clear the entity_cache bins.
  1168. */
  1169. function metatag_update_7019() {
  1170. if (module_exists('entitycache')) {
  1171. foreach (drupal_get_schema() as $table_name => $spec) {
  1172. if (strpos($table_name, 'cache_entity_') === 0) {
  1173. cache_clear_all('*', $table_name, TRUE);
  1174. drupal_set_message(t("Cleared the @table cache bin", array('@table' => $table_name)));
  1175. }
  1176. }
  1177. }
  1178. else {
  1179. drupal_set_message(t("The EntityCache module is not installed, nothing to do."));
  1180. }
  1181. }
  1182. /**
  1183. * Clear the Metatag cache.
  1184. */
  1185. function metatag_update_7020() {
  1186. cache_clear_all('*', 'cache_metatag', TRUE);
  1187. return t('All Metatag caches cleared.');
  1188. }
  1189. /**
  1190. * Clear the existing Metatag cache so all unwanted 403/404 paths can be
  1191. * purged.
  1192. */
  1193. function metatag_update_7021() {
  1194. cache_clear_all('*', 'cache_metatag', TRUE);
  1195. return t('All Metatag caches cleared.');
  1196. }
  1197. /**
  1198. * A minor bit of tidy-up after update 7015.
  1199. */
  1200. function metatag_update_7022() {
  1201. variable_del('metatag_skip_update_7015');
  1202. }
  1203. /**
  1204. * Clear the Metatag cache because $cid_parts was changed.
  1205. */
  1206. function metatag_update_7023() {
  1207. cache_clear_all('*', 'cache_metatag', TRUE);
  1208. return t('All Metatag caches cleared.');
  1209. }
  1210. /**
  1211. * Rename the 'twitter:image' meta tag to 'twitter:image:src', part 1.
  1212. */
  1213. function metatag_update_7024() {
  1214. // Find all {metatag} records that contained an entry for the old meta tag.
  1215. $records = db_query("SELECT entity_type, entity_id, revision_id, language, data
  1216. FROM {metatag}
  1217. WHERE data LIKE '%twitter:image%'");
  1218. // This message will be returned if nothing needed to be updated.
  1219. $none_message = t('No Metatag entity records needed to have the "twitter:image" meta tag fixed.');
  1220. if ($records->rowCount() == 0) {
  1221. drupal_set_message($none_message);
  1222. }
  1223. else {
  1224. $keys = array('entity_type', 'entity_id', 'revision_id', 'language');
  1225. // Loop over the values and correct them.
  1226. $counter = 0;
  1227. foreach ($records as $record) {
  1228. $record->data = unserialize($record->data);
  1229. if (isset($record->data['twitter:image'])) {
  1230. $record->data['twitter:image:src'] = $record->data['twitter:image'];
  1231. unset($record->data['twitter:image']);
  1232. drupal_write_record('metatag', $record, $keys);
  1233. $counter++;
  1234. }
  1235. }
  1236. if ($counter == 0) {
  1237. drupal_set_message($none_message);
  1238. }
  1239. else {
  1240. drupal_set_message(t('Converted the "twitter:image" meta tag for @count entity records to the correct "twitter:image:src" meta tag.', array('@count' => $counter)));
  1241. }
  1242. }
  1243. }
  1244. /**
  1245. * Replaced by update 7030.
  1246. */
  1247. function metatag_update_7025() {
  1248. // Do nothing.
  1249. }
  1250. /**
  1251. * Rename the 'copyright' meta tag to 'rights', part 1.
  1252. */
  1253. function metatag_update_7026() {
  1254. // Find all {metatag} records that contained an entry for the old meta tag.
  1255. $records = db_query("SELECT entity_type, entity_id, revision_id, language, data
  1256. FROM {metatag}
  1257. WHERE data LIKE '%copyright%'");
  1258. // This message will be returned if nothing needed to be updated.
  1259. $none_message = t('No Metatag entity records needed to have the "copyright" meta tag fixed.');
  1260. if ($records->rowCount() == 0) {
  1261. drupal_set_message($none_message);
  1262. }
  1263. else {
  1264. $keys = array('entity_type', 'entity_id', 'revision_id', 'language');
  1265. // Loop over the values and correct them.
  1266. $counter = 0;
  1267. foreach ($records as $record) {
  1268. $record->data = unserialize($record->data);
  1269. if (isset($record->data['copyright'])) {
  1270. $record->data['rights'] = $record->data['copyright'];
  1271. unset($record->data['copyright']);
  1272. drupal_write_record('metatag', $record, $keys);
  1273. $counter++;
  1274. }
  1275. }
  1276. if ($counter == 0) {
  1277. drupal_set_message($none_message);
  1278. }
  1279. else {
  1280. drupal_set_message(t('Converted the "copyright" meta tag for @count entity records to the correct "rights" meta tag.', array('@count' => $counter)));
  1281. }
  1282. }
  1283. }
  1284. /**
  1285. * Replaced by update 7031.
  1286. */
  1287. function metatag_update_7027() {
  1288. // Do nothing.
  1289. }
  1290. /**
  1291. * Clear the menu cache so the new Advanced Settings page will be picked up.
  1292. */
  1293. function metatag_update_7028() {
  1294. variable_set('menu_rebuild_needed', TRUE);
  1295. }
  1296. /**
  1297. * Add an index to the {metatag} table to speed up some queries.
  1298. */
  1299. function metatag_update_7029() {
  1300. db_add_index('metatag', 'type_revision', array('entity_type', 'revision_id'));
  1301. drupal_set_message(t('Added an index to the main Metatag table that will hopefully improve performance a little.'));
  1302. }
  1303. /**
  1304. * Rename the 'twitter:image' meta tag to 'twitter:image:src', part 2.
  1305. */
  1306. function metatag_update_7030() {
  1307. // Find all {metatag_config} records that contained an entry for the old meta
  1308. // tag.
  1309. $records = db_query("SELECT cid, config
  1310. FROM {metatag_config}
  1311. WHERE config LIKE '%twitter:image%'");
  1312. // This message will be returned if nothing needed to be updated.
  1313. $none_message = t('No Metatag configuration records needed to have the "twitter:image" meta tag fixed. That said, there may be other configurations elsewhere that do need updating.');
  1314. // Loop over the values and correct them.
  1315. if ($records->rowCount() == 0) {
  1316. drupal_set_message($none_message);
  1317. }
  1318. else {
  1319. $keys = array('cid');
  1320. // Loop over the values and correct them.
  1321. $counter = 0;
  1322. foreach ($records as $record) {
  1323. $record->config = unserialize($record->config);
  1324. if (isset($record->config['twitter:image'])) {
  1325. $record->config['twitter:image:src'] = $record->config['twitter:image'];
  1326. unset($record->config['twitter:image']);
  1327. drupal_write_record('metatag_config', $record, $keys);
  1328. $counter++;
  1329. }
  1330. }
  1331. if ($counter == 0) {
  1332. drupal_set_message($none_message);
  1333. }
  1334. else {
  1335. drupal_set_message(t('Converted the "twitter:image" meta tag for @count configurations to the correct "twitter:image:src" meta tag.', array('@count' => $counter)));
  1336. }
  1337. }
  1338. }
  1339. /**
  1340. * Rename the 'copyright' meta tag to 'rights', part 2.
  1341. */
  1342. function metatag_update_7031() {
  1343. // Find all {metatag_config} records that contained an entry for the old meta
  1344. // tag.
  1345. $records = db_query("SELECT cid, config
  1346. FROM {metatag_config}
  1347. WHERE config LIKE '%copyright%'");
  1348. // This message will be returned if nothing needed to be updated.
  1349. $none_message = t('No Metatag configuration records needed to have the "copyright" meta tag fixed. That said, there may be other configurations elsewhere that do need updating.');
  1350. // Loop over the values and correct them.
  1351. if ($records->rowCount() == 0) {
  1352. drupal_set_message($none_message);
  1353. }
  1354. else {
  1355. $keys = array('cid');
  1356. // Loop over the values and correct them.
  1357. $counter = 0;
  1358. foreach ($records as $record) {
  1359. $record->config = unserialize($record->config);
  1360. if (isset($record->config['copyright'])) {
  1361. $record->config['rights'] = $record->config['copyright'];
  1362. unset($record->config['copyright']);
  1363. drupal_write_record('metatag_config', $record, $keys);
  1364. $counter++;
  1365. }
  1366. }
  1367. if ($counter == 0) {
  1368. drupal_set_message($none_message);
  1369. }
  1370. else {
  1371. drupal_set_message(t('Converted the "copyright" meta tag for @count configurations to the correct "rights" meta tag.', array('@count' => $counter)));
  1372. }
  1373. }
  1374. }
  1375. /**
  1376. * Clear the Metatag cache.
  1377. */
  1378. function metatag_update_7032() {
  1379. cache_clear_all('*', 'cache_metatag', TRUE);
  1380. return t('All Metatag caches cleared.');
  1381. }
  1382. /**
  1383. * These originally removed the 'author' meta tag, but it was subsequently
  1384. * decided that this was not the correct approach, that the meta tag should not
  1385. * be removed after all.
  1386. *
  1387. * @see https://www.drupal.org/node/2330823
  1388. */
  1389. function metatag_update_7033() {
  1390. }
  1391. function metatag_update_7034() {
  1392. }
  1393. function metatag_update_7035() {
  1394. }