]> gitweb.fluxo.info Git - lorea/elgg.git/commitdiff
Refs #5357: Introduces ElggBatch awareness of incomplete entities during fetch
authorSteve Clay <steve@mrclay.org>
Mon, 3 Jun 2013 21:02:33 +0000 (17:02 -0400)
committerSteve Clay <steve@mrclay.org>
Mon, 3 Jun 2013 21:02:33 +0000 (17:02 -0400)
engine/classes/ElggBatch.php
engine/lib/entities.php
engine/tests/api/helpers.php

index eb93b0f5d5453edb44a165cf3c3fc59f690619ec..34520f2bca6eac105e1cc174e179c2bb41456948 100644 (file)
@@ -149,6 +149,13 @@ class ElggBatch
         */
        private $incrementOffset = true;
 
+       /**
+        * Entities that could not be instantiated during a fetch
+        *
+        * @var stdClass[]
+        */
+       private $incompleteEntities = array();
+
        /**
         * Batches operations on any elgg_get_*() or compatible function that supports
         * an options array.
@@ -221,6 +228,17 @@ class ElggBatch
                }
        }
 
+       /**
+        * Tell the process that an entity was incomplete during a fetch
+        *
+        * @param stdClass $row
+        *
+        * @access private
+        */
+       public function reportIncompleteEntity(stdClass $row) {
+               $this->incompleteEntities[] = $row;
+       }
+
        /**
         * Fetches the next chunk of results
         *
@@ -265,16 +283,16 @@ class ElggBatch
 
                $current_options = array(
                        'limit' => $limit,
-                       'offset' => $offset
+                       'offset' => $offset,
+                       '__ElggBatch' => $this,
                );
 
                $options = array_merge($this->options, $current_options);
-               $getter = $this->getter;
 
-               if (is_string($getter)) {
-                       $this->results = $getter($options);
-               } else {
-                       $this->results = call_user_func_array($getter, array($options));
+               $this->incompleteEntities = array();
+               $this->results = call_user_func_array($this->getter, array($options));
+               if ($this->incompleteEntities) {
+                       // @todo what to do here?
                }
 
                if ($this->results) {
index 5cfeca6f8aa547b95c72762e70b4257b0dbffcf8..b7f8c14661f2eeb72500de6fc735949bf0b0b346 100644 (file)
@@ -891,6 +891,8 @@ function elgg_get_entities(array $options = array()) {
                'joins'                                 =>      array(),
 
                'callback'                              => 'entity_row_to_elggstar',
+
+               '__ElggBatch'                   => null,
        );
 
        $options = array_merge($defaults, $options);
@@ -1008,7 +1010,7 @@ function elgg_get_entities(array $options = array()) {
                }
 
                if ($options['callback'] === 'entity_row_to_elggstar') {
-                       $dt = _elgg_fetch_entities_from_sql($query);
+                       $dt = _elgg_fetch_entities_from_sql($query, $options['__ElggBatch']);
                } else {
                        $dt = get_data($query, $options['callback']);
                }
@@ -1043,13 +1045,14 @@ function elgg_get_entities(array $options = array()) {
 /**
  * Return entities from an SQL query generated by elgg_get_entities.
  *
- * @param string $sql
+ * @param string    $sql
+ * @param ElggBatch $batch
  * @return ElggEntity[]
  *
  * @access private
  * @throws LogicException
  */
-function _elgg_fetch_entities_from_sql($sql) {
+function _elgg_fetch_entities_from_sql($sql, ElggBatch $batch = null) {
        static $plugin_subtype;
        if (null === $plugin_subtype) {
                $plugin_subtype = get_subtype_id('object', 'plugin');
@@ -1126,6 +1129,11 @@ function _elgg_fetch_entities_from_sql($sql) {
                        } catch (IncompleteEntityException $e) {
                                // don't let incomplete entities throw fatal errors
                                unset($rows[$i]);
+
+                               // report incompletes to the batch process that spawned this query
+                               if ($batch) {
+                                       $batch->reportIncompleteEntity($row);
+                               }
                        }
                }
        }
index 62e4471e07c9e67f831926c9ca16ecf8e0b4b300..753d02915f9360d2a18c05e564a4bc6e9ab5415f 100644 (file)
@@ -578,6 +578,54 @@ class ElggCoreHelpersTest extends ElggCoreUnitTest {
                $this->assertEqual(11, $j);
        }
 
+       public function testElggBatchHandlesBrokenEntities() {
+               $num_test_entities = 4;
+               $guids = array();
+               $now = time();
+               for ($i = $num_test_entities; $i > 0; $i--) {
+                       $entity = new ElggObject();
+                       $entity->type = 'object';
+                       $entity->subtype = 'test_5357_subtype';
+                       $entity->access_id = ACCESS_PUBLIC;
+                       $entity->time_created = ($now - $i);
+                       $entity->save();
+                       $guids[] = $entity->guid;
+                       _elgg_invalidate_cache_for_entity($entity->guid);
+               }
+
+               // break the second entity
+               $db_prefix = elgg_get_config('dbprefix');
+               delete_data("DELETE FROM {$db_prefix}objects_entity WHERE guid = {$guids[1]}");
+
+               $options = array(
+                       'type' => 'object',
+                       'subtype' => 'test_5357_subtype',
+                       'order' => 'e.time_created ASC',
+               );
+
+               $entities_visited = array();
+
+               $batch = new ElggBatch('elgg_get_entities', $options, null, 2);
+               foreach ($batch as $entity) {
+                       $entities_visited[$entity->guid] = true;
+               }
+
+               // All but the broken entity should have been visited
+               $this->assertEqual(count($entities_visited), $num_test_entities - 1);
+
+               // cleanup (including leftovers from previous tests)
+               $entity_rows = elgg_get_entities(array_merge($options, array(
+                       'callback' => '',
+                       'limit' => false,
+               )));
+               $guids = array();
+               foreach ($entity_rows as $row) {
+                       $guids[] = $row->guid;
+               }
+               delete_data("DELETE FROM {$db_prefix}entities WHERE guid IN (" . implode(',', $guids) . ")");
+               delete_data("DELETE FROM {$db_prefix}objects_entity WHERE guid IN (" . implode(',', $guids) . ")");
+       }
+
        static function elgg_batch_callback_test($options, $reset = false) {
                static $count = 1;