upgrade_comments.php 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. <?php
  2. /**
  3. * Convert comment annotations to entities
  4. *
  5. * Run for 2 seconds per request as set by $batch_run_time_in_secs. This includes
  6. * the engine loading time.
  7. */
  8. // from engine/start.php
  9. global $START_MICROTIME;
  10. $batch_run_time_in_secs = 2;
  11. // if upgrade has run correctly, mark it done
  12. if (get_input('upgrade_completed')) {
  13. // set the upgrade as completed
  14. $factory = new ElggUpgrade();
  15. $upgrade = $factory->getUpgradeFromPath('admin/upgrades/comments');
  16. if ($upgrade instanceof ElggUpgrade) {
  17. $upgrade->setCompleted();
  18. }
  19. return true;
  20. }
  21. // Offset is the total amount of errors so far. We skip these
  22. // comments to prevent them from possibly repeating the same error.
  23. $offset = get_input('offset', 0);
  24. $limit = 50;
  25. $access_status = access_get_show_hidden_status();
  26. access_show_hidden_entities(true);
  27. // don't want any event or plugin hook handlers from plugins to run
  28. $original_events = _elgg_services()->events;
  29. $original_hooks = _elgg_services()->hooks;
  30. _elgg_services()->events = new Elgg\EventsService();
  31. _elgg_services()->hooks = new Elgg\PluginHooksService();
  32. elgg_register_plugin_hook_handler('permissions_check', 'all', 'elgg_override_permissions');
  33. elgg_register_plugin_hook_handler('container_permissions_check', 'all', 'elgg_override_permissions');
  34. $success_count = 0;
  35. $error_count = 0;
  36. do {
  37. $annotations_to_delete = array();
  38. $container_guids = array();
  39. $annotations = elgg_get_annotations(array(
  40. 'annotation_names' => 'generic_comment',
  41. 'limit' => $limit,
  42. 'offset' => $offset,
  43. 'order_by' => 'n_table.id DESC',
  44. ));
  45. if (!$annotations) {
  46. // no annotations left
  47. break;
  48. }
  49. $db_prefix = elgg_get_config('dbprefix');
  50. // Create a new object for each annotation
  51. foreach ($annotations as $annotation) {
  52. $object = new ElggComment();
  53. $object->owner_guid = $annotation->owner_guid;
  54. $object->container_guid = $annotation->entity_guid;
  55. $object->description = $annotation->value;
  56. $object->access_id = $annotation->access_id;
  57. // make sure disabled comments stay disabled
  58. $object->enabled = $annotation->enabled;
  59. $object->time_created = $annotation->time_created;
  60. $object->save(false);
  61. $guid = $object->getGUID();
  62. if ($guid) {
  63. /**
  64. * Update the entry in river table for this comment
  65. *
  66. * - Update the view path
  67. * - Remove annotation id
  68. * - Save comment guid to the object_guid column
  69. */
  70. $query = "
  71. UPDATE {$db_prefix}river
  72. SET view = 'river/object/comment/create',
  73. type = 'object',
  74. subtype = 'comment',
  75. annotation_id = 0,
  76. object_guid = $guid,
  77. target_guid = $object->container_guid
  78. WHERE action_type = 'comment'
  79. AND annotation_id = $annotation->id
  80. ";
  81. if (!update_data($query)) {
  82. register_error(elgg_echo('upgrade:comments:river_update_failed', array($annotation->id)));
  83. $error_count++;
  84. continue;
  85. }
  86. // set the time_updated and last_action for this comment
  87. // to the original time_created
  88. $fix_ts_query = "
  89. UPDATE {$db_prefix}entities
  90. SET time_updated = time_created,
  91. last_action = time_created
  92. WHERE guid = $guid
  93. ";
  94. if (update_data($fix_ts_query)) {
  95. // It's now safe to delete the annotation
  96. $annotations_to_delete[] = $annotation->id;
  97. $container_guids[] = $object->container_guid;
  98. $success_count++;
  99. } else {
  100. register_error(elgg_echo('upgrade:comments:timestamp_update_fail', array($annotation->id)));
  101. $error_count++;
  102. }
  103. } else {
  104. register_error(elgg_echo('upgrade:comments:create_failed', array($annotation->id)));
  105. $error_count++;
  106. }
  107. }
  108. if ($annotations_to_delete) {
  109. $annotation_ids = implode(",", $annotations_to_delete);
  110. $delete_query = "DELETE FROM {$db_prefix}annotations WHERE id IN ($annotation_ids)";
  111. delete_data($delete_query);
  112. }
  113. // update the last action on containers to be the max of all its comments
  114. // or its own last action
  115. $comment_subtype_id = get_subtype_id('object', 'comment');
  116. foreach (array_unique($container_guids) as $guid) {
  117. // can't use a subquery in an update clause without hard to read tricks.
  118. $max = get_data_row("SELECT MAX(time_updated) as max_time_updated
  119. FROM {$db_prefix}entities e
  120. WHERE e.container_guid = $guid
  121. AND e.subtype = $comment_subtype_id");
  122. $query = "
  123. UPDATE {$db_prefix}entities
  124. SET last_action = '$max->max_time_updated'
  125. WHERE guid = $guid
  126. AND last_action < '$max->max_time_updated'
  127. ";
  128. update_data($query);
  129. }
  130. } while ((microtime(true) - $START_MICROTIME) < $batch_run_time_in_secs);
  131. access_show_hidden_entities($access_status);
  132. // replace events and hooks
  133. _elgg_services()->events = $original_events;
  134. _elgg_services()->hooks = $original_hooks;
  135. // remove the admin notice
  136. elgg_delete_admin_notice('comment_upgrade_needed');
  137. // Give some feedback for the UI
  138. echo json_encode(array(
  139. 'numSuccess' => $success_count,
  140. 'numErrors' => $error_count,
  141. ));