Esempio n. 1
0
 /**
  * Do a programmatic 1:n join between the given objects and objects retrieved from the passed repository.
  *
  * Example:
  *
  *      $productRepository->joinMany($products, $tagsRepository, 'id', 'product_id', 'tags');
  *
  * The above code will query `$tagsRepository` for all tags that have `id`'s of the `$products` in `product_id`
  * property. Then it will match `$products` and the fetched tags and set all related tags on each product by
  * calling `::setTags()` with the related tags.
  *
  * @param array      $objects        Objects to which associated objects will be joined.
  * @param Repository $withRepository Repository from which associated objects should be fetched.
  * @param string     $leftProperty   Property of `$objects` under which the relation is stored.
  * @param string     $rightProperty  Property on which the fetched objects can be identified.
  * @param string     $targetProperty Property of `$objects` on which the associated object will be set. This is
  *                                   converted to a camelCase setter.
  * @param array      $criteria       [optional] Any additional criteria for finding the associated objects.
  * @param array      $params         [optional] Any additional search parameters for finding the associated objects.
  * @param boolean    $excludeEmpty   [optional] Should objects that didn't find the match be removed
  *                                   from the results set? Set as `Knit::EXCLUDE_EMPTY` constant. Default: `false`.
  *
  * @return array
  */
 public function joinMany(array $objects, Repository $withRepository, $leftProperty, $rightProperty, $targetProperty, array $criteria = [], array $params = [], $excludeEmpty = false)
 {
     // if empty collection then don't even waste time :)
     if (empty($objects)) {
         return $objects;
     }
     // select all objects for the right side of the join
     $criteria = array_merge($criteria, [$rightProperty => ObjectUtils::pluck($objects, $leftProperty)]);
     $withObjects = $withRepository->find($criteria, $params);
     $withObjects = ObjectUtils::groupBy($withObjects, $rightProperty);
     // do the programmatic join
     $getter = ObjectUtils::getter($leftProperty);
     $setter = ObjectUtils::setter($targetProperty);
     foreach ($objects as $i => $object) {
         $match = $object->{$getter}();
         if (isset($withObjects[$match])) {
             $object->{$setter}($withObjects[$match]);
         } elseif ($excludeEmpty === Knit::EXCLUDE_EMPTY) {
             unset($objects[$i]);
         }
     }
     return array_values($objects);
 }
Esempio n. 2
0
 /**
  * Tests finding objects by various queries.
  *
  * @param array $criteria Search criteria.
  * @param array $params   Search params.
  * @param array $expected Expected results.
  *
  * @depends      testInsert
  * @dataProvider provideFindCriteria
  */
 public function testFind(array $criteria, array $params, array $expected)
 {
     $this->insertData();
     $hobbits = $this->repository->find($criteria, $params);
     $this->assertCount(count($expected), $hobbits, $this->logger->getLastMessage());
     $this->assertEquals($expected, ObjectUtils::pluck($hobbits, 'name'), $this->logger->getLastMessage());
 }
Esempio n. 3
0
 public function testSetter()
 {
     $this->assertEquals('setId', ObjectUtils::setter('id'));
     $this->assertEquals('setName', ObjectUtils::setter('name'));
     $this->assertEquals('setCategoryId', ObjectUtils::setter('categoryId'));
     $this->assertEquals('setCategoryId', ObjectUtils::setter('category_id'));
     $this->assertEquals('setVeryLongRandomlySeparatedVariableName', ObjectUtils::setter('veryLong_randomly_Separated_variableName'));
 }
Esempio n. 4
0
 /**
  * Tests finding by multiple id's.
  *
  * @depends testInsert
  */
 public function testFindByMultipleIds()
 {
     $hobbits = $this->repository->find();
     $otherHobbits = $this->repository->find(['id:in' => ObjectUtils::pluck($hobbits, 'id')]);
     $this->assertEquals($hobbits, $otherHobbits, $this->logger->getLastMessage());
 }
Esempio n. 5
0
 /**
  * Tests joining many items to a collection of objects.
  *
  * @param array   $objects      Objects.
  * @param array   $criteria     Search criteria.
  * @param array   $params       Search params.
  * @param array   $withObjects  Search results from the other repository.
  * @param boolean $excludeEmpty Exclude empty?
  * @param array   $expected     Expected result.
  *
  * @dataProvider provideJoinManyData
  */
 public function testJoinMany(array $objects, array $criteria, array $params, array $withObjects, $excludeEmpty, array $expected)
 {
     $hobbitMocks = $this->provideMocks();
     $hobbitRepository = $this->provideRepository($hobbitMocks);
     $giftMocks = $this->provideMocks();
     $giftMocks['objectClass'] = Fixtures\ElvenGift::class;
     $giftRepository = $this->provideRepositoryStub($giftMocks, ['find']);
     if (!empty($objects)) {
         $giftRepository->expects($this->once())->method('find')->with(array_merge($criteria, ['owner_name' => ObjectUtils::pluck($objects, 'name')]), $params)->will($this->returnValue($withObjects));
     } else {
         $giftRepository->expects($this->never())->method('find');
     }
     $result = $hobbitRepository->joinMany($objects, $giftRepository, 'name', 'owner_name', 'gifts', $criteria, $params, $excludeEmpty);
     $this->assertInternalType('array', $result);
     $this->assertCount(count($expected), $result);
     foreach ($result as $hobbit) {
         $gifts = $hobbit->getGifts();
         $expectedGifts = $expected[$hobbit->getName()];
         $this->assertCount(count($expectedGifts), $gifts);
         foreach ($gifts as $i => $gift) {
             $this->assertEquals($expectedGifts[$i], $gift->getName());
         }
     }
 }
Esempio n. 6
0
 /**
  * Interpolates the given string with variables.
  * 
  * Looks for occurrences of placeholders like `{foo}` or `{bar}` and replaces them with values found under
  * keys `foo` or `bar` (respectively) in the given array of variables.
  *
  * Also accepts an object as the second argument and in such case it will attempt to read
  * the properties of that object using getters.
  *
  * Example:
  *
  *      echo \MD\Foundation\Utils\StringUtils::interpolate('I have a {item} and I will {action} it.', array(
  *          'item' => 'banana',
  *          'action' => 'eat'
  *      ));
  *      // -> 'I have a banana and I will eat it.'
  *
  * @param string $string String to interpolate.
  * @param mixed $variables Either an array or an object with variables to be interpolated into the string.
  * @return string
  *
  * @throws InvalidArgumentException If the `$variables` argument is neither an array or an object.
  */
 public static function interpolate($string, $variables)
 {
     if (!is_object($variables) && !is_array($variables)) {
         throw new InvalidArgumentException('array or object', $variables);
     }
     $string = preg_replace_callback('/{([\\w\\d_\\.]+)}/is', function ($matches) use($variables) {
         $var = $matches[1];
         $value = '';
         if (is_object($variables)) {
             $getter = ObjectUtils::getter($var);
             if (method_exists($variables, $getter)) {
                 $value = strval(call_user_func(array($variables, $getter)));
             } elseif (isset($variables->{$var})) {
                 $value = strval($variables->{$var});
             }
         } elseif (is_array($variables)) {
             if (isset($variables[$var])) {
                 $value = strval($variables[$var]);
             }
         }
         return $value;
     }, $string);
     return $string;
 }
Esempio n. 7
0
 /**
  * Get the property. It will try to call a defined getter first.
  * 
  * If the property does not exist then it will trigger an `E_USER_NOTICE`.
  *
  *      use MD\Foundation\MagicUtils;
  *
  *      class MyClass extends MagicUtils
  *      {
  *          protected $full_title = 'Lorem ipsum dolor sit amet.';
  *
  *          public function getFullTitle()
  *          {
  *              echo 'Getting full title "'. $this->full_title .'"';
  *              return $this->full_title;
  *          }
  *      }
  *
  *      $object = new MyClass();
  *      echo $object->full_title;
  *      // -> 'Getting full title "Lorem ipsum dolor sit amet."'
  * 
  * @param string $property Name of the property.
  * @return mixed
  */
 public final function __get($property)
 {
     // try to call a defined getter if it exists
     $getter = ObjectUtils::getter($property);
     if (method_exists($this, $getter)) {
         return call_user_func(array($this, $getter));
     }
     // if no getter then simply return the property if it exists
     if (array_key_exists($property, $this->__properties)) {
         return $this->__properties[$property];
     }
     // trigger a user notice if property not found
     return trigger_error('Call to undefined object property ' . get_called_class() . '::$' . $property . '.', E_USER_NOTICE);
 }