upgrade_discussion_replies.php 4.7 KB

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