Example #1
0
 /**
  * Returns query with applied filter
  *
  * @param \Cake\ORM\Query $query Query.
  * @param string $field Field name.
  * @param string $value Field value.
  * @param array $data Filters values.
  * @return \Cake\ORM\Query
  */
 protected function _buildQuery(Query $query, $field, $value, array $data = [])
 {
     // @todo bind to parent Articles.id using initialization parameter
     $alias = $query->repository()->alias();
     $tags = TableRegistry::get('ArticlesTags')->find('all')->matching('Tags', function ($q) use($value, $alias) {
         return $q->where(['Tags.name' => $value]);
     })->where(["ArticlesTags.article_id = {$alias}.id"]);
     return $query->where([new UnaryExpression('EXISTS', $tags)]);
 }
 /**
  * Tests that HasMany associations are correctly eager loaded and results
  * correctly nested when multiple foreignKeys are used
  *
  * @dataProvider strategiesProvider
  * @return void
  */
 public function testHasManyEager($strategy)
 {
     $table = TableRegistry::get('SiteAuthors');
     $table->hasMany('SiteArticles', ['propertyName' => 'articles', 'strategy' => $strategy, 'sort' => ['SiteArticles.id' => 'asc'], 'foreignKey' => ['author_id', 'site_id']]);
     $query = new Query($this->connection, $table);
     $results = $query->select()->contain('SiteArticles')->hydrate(false)->toArray();
     $expected = [['id' => 1, 'name' => 'mark', 'site_id' => 1, 'articles' => [['id' => 1, 'title' => 'First Article', 'body' => 'First Article Body', 'author_id' => 1, 'site_id' => 1]]], ['id' => 2, 'name' => 'juan', 'site_id' => 2, 'articles' => []], ['id' => 3, 'name' => 'jose', 'site_id' => 2, 'articles' => [['id' => 2, 'title' => 'Second Article', 'body' => 'Second Article Body', 'author_id' => 3, 'site_id' => 2]]], ['id' => 4, 'name' => 'andy', 'site_id' => 1, 'articles' => []]];
     $this->assertEquals($expected, $results);
     $results = $query->repository($table)->select()->contain(['SiteArticles' => ['conditions' => ['id' => 2]]])->hydrate(false)->toArray();
     $expected[0]['articles'] = [];
     $this->assertEquals($expected, $results);
     $this->assertEquals($table->association('SiteArticles')->strategy(), $strategy);
 }
Example #3
0
 /**
  * Get CakePHP property
  *
  * @param string $dataName Column data name
  *
  * @throws Exception
  * @return array|string
  */
 protected function getProperty($dataName)
 {
     $dataName = explode('.', trim($dataName));
     if (count($dataName) != 2) {
         throw new Exception('You are set invalid date.');
     }
     $tableAlias = $dataName[0];
     $colName = $dataName[1];
     if ($this->query->repository()->alias() == $tableAlias) {
         return $colName;
     } elseif (array_key_exists($tableAlias, $this->query->contain())) {
         return ['propertyPath' => $this->query->eagerLoader()->normalized($this->query->repository())[$tableAlias]['propertyPath'], 'field' => $colName];
     }
 }
Example #4
0
 /**
  * Constructor
  *
  * @param \Cake\ORM\Query $query Query from where results come
  * @param \Cake\Database\StatementInterface $statement
  */
 public function __construct($query, $statement)
 {
     $repository = $query->repository();
     $this->_query = $query;
     $this->_statement = $statement;
     $this->_defaultTable = $this->_query->repository();
     $this->_calculateAssociationMap();
     $this->_hydrate = $this->_query->hydrate();
     $this->_entityClass = $repository->entityClass();
     $this->_useBuffering = $query->bufferResults();
     if ($statement) {
         $this->count();
     }
 }
 public function beforeFind(Event $event, Query $query, $options, $primary)
 {
     $config = $this->config();
     $tableAlias = $query->repository()->alias();
     $founded = false;
     if ($where = $query->clause('where')) {
         $where->iterateParts(function ($w) use($config, $tableAlias, &$founded) {
             $field = is_object($w) ? $w->getField() : $w;
             if ($field == $tableAlias . '.' . $config['field'] || $field == $config['field']) {
                 $founded = true;
             }
             return $w;
         });
     }
     if (!$founded) {
         $query->where(['deleted' => 0]);
     }
 }
 /**
  * Constructor
  *
  * @param \Cake\ORM\Query $query Query from where results come
  * @param \Cake\Database\StatementInterface $statement The statement to fetch from
  */
 public function __construct($query, $statement)
 {
     $repository = $query->repository();
     $this->_query = $query;
     $this->_statement = $statement;
     $this->_driver = $driver = $this->_query->connection()->driver();
     $this->_defaultTable = $this->_query->repository();
     $this->_calculateAssociationMap();
     $this->_hydrate = $this->_query->hydrate();
     $this->_entityClass = $repository->entityClass();
     $this->_useBuffering = $query->bufferResults();
     $this->_defaultAlias = $this->_defaultTable->alias();
     $this->_calculateColumnMap();
     $this->_calculateTypeMap();
     if ($this->_useBuffering) {
         $count = $this->count();
         $this->_results = new SplFixedArray($count);
     }
 }
Example #7
0
 /**
  * Decorates the passed statement object in order to inject data from associations
  * that cannot be joined directly.
  *
  * @param \Cake\ORM\Query $query The query for which to eager load external
  * associations
  * @param \Cake\Database\StatementInterface $statement The statement created after executing the $query
  * @return CallbackStatement statement modified statement with extra loaders
  */
 public function loadExternal($query, $statement)
 {
     $external = $this->externalAssociations($query->repository());
     if (empty($external)) {
         return $statement;
     }
     $driver = $query->connection()->driver();
     list($collected, $statement) = $this->_collectKeys($external, $query, $statement);
     foreach ($external as $meta) {
         $contain = $meta->associations();
         $instance = $meta->instance();
         $config = $meta->config();
         $alias = $instance->source()->alias();
         $path = $meta->aliasPath();
         $requiresKeys = $instance->requiresKeys($config);
         if ($requiresKeys && empty($collected[$path][$alias])) {
             continue;
         }
         $keys = isset($collected[$path][$alias]) ? $collected[$path][$alias] : null;
         $f = $instance->eagerLoader($config + ['query' => $query, 'contain' => $contain, 'keys' => $keys, 'nestKey' => $meta->aliasPath()]);
         $statement = new CallbackStatement($statement, $driver, $f);
     }
     return $statement;
 }
Example #8
0
 /**
  * Tests that it is possible to call matching and contain on the same
  * association.
  *
  * @return void
  */
 public function testMatchingWithContain()
 {
     $query = new Query($this->connection, $this->table);
     $table = TableRegistry::get('authors');
     $table->hasMany('articles');
     TableRegistry::get('articles')->belongsToMany('tags');
     $result = $query->repository($table)->select()->matching('articles.tags', function ($q) {
         return $q->where(['tags.id' => 2]);
     })->contain('articles')->first();
     $this->assertEquals(1, $result->id);
     $this->assertCount(2, $result->articles);
     $this->assertEquals(2, $result->_matchingData['tags']->id);
 }
 /**
  * Builds a query to be used as a condition for filtering records in the
  * target table, it is constructed by cloning the original query that was used
  * to load records in the source table.
  *
  * @param \Cake\ORM\Query $query the original query used to load source records
  * @return \Cake\ORM\Query
  */
 protected function _buildSubquery($query)
 {
     $filterQuery = clone $query;
     $filterQuery->autoFields(false);
     $filterQuery->mapReduce(null, null, true);
     $filterQuery->formatResults(null, true);
     $filterQuery->contain([], true);
     if (!$filterQuery->clause('limit')) {
         $filterQuery->limit(null);
         $filterQuery->order([], true);
         $filterQuery->offset(null);
     }
     $keys = (array) $query->repository()->primaryKey();
     if ($this->type() === $this::MANY_TO_ONE) {
         $keys = (array) $this->foreignKey();
     }
     $fields = $query->aliasFields($keys, $this->source()->alias());
     $filterQuery->select($fields, true)->group(array_values($fields));
     return $filterQuery;
 }
 /**
  * testbeforePaginate
  *
  * @return void
  */
 public function testbeforePaginate()
 {
     $listener = $this->getMockBuilder('\\Crud\\Listener\\RelatedModelsListener')->disableOriginalConstructor()->setMethods(['models'])->getMock();
     $table = $this->getMockBuilder('\\Cake\\ORM\\Table')->disableOriginalConstructor()->setMethods(['associations', 'association'])->getMock();
     $listener->expects($this->once())->method('models')->will($this->returnValue(['Users' => 'manyToOne']));
     $db = $this->getMockBuilder('\\Cake\\Database\\Connection')->disableOriginalConstructor()->getMock();
     $query = new Query($db, null);
     $query->repository($table);
     $subject = new Subject(['query' => $query]);
     $event = new Event('beforePaginate', $subject);
     $listener->beforePaginate($event);
     $result = $event->subject()->query->contain();
     $this->assertEquals(['Users' => []], $result);
 }
Example #11
0
 /**
  * Tests that it is possible to filter by deep associations
  *
  * @return void
  */
 public function testMatchingDotNotation()
 {
     $query = new Query($this->connection, $this->table);
     $table = TableRegistry::get('authors');
     TableRegistry::get('articles');
     $table->hasMany('articles');
     TableRegistry::get('articles')->belongsToMany('tags');
     $results = $query->repository($table)->select()->hydrate(false)->matching('articles.tags', function ($q) {
         return $q->where(['tags.id' => 2]);
     })->toArray();
     $expected = [['id' => 1, 'name' => 'mariano', 'articles' => ['id' => 1, 'title' => 'First Article', 'body' => 'First Article Body', 'author_id' => 1, 'published' => 'Y', 'tags' => ['id' => 2, 'name' => 'tag2', '_joinData' => ['article_id' => 1, 'tag_id' => 2]]]]];
     $this->assertEquals($expected, $results);
 }
 /**
  * Builds a query to be used as a condition for filtering records in the
  * target table, it is constructed by cloning the original query that was used
  * to load records in the source table.
  *
  * @param \Cake\ORM\Query $query the original query used to load source records
  * @return \Cake\ORM\Query
  */
 protected function _buildSubquery($query)
 {
     $filterQuery = clone $query;
     $filterQuery->limit(null);
     $filterQuery->order([], true);
     $filterQuery->contain([], true);
     $joins = $filterQuery->join();
     foreach ($joins as $i => $join) {
         if (strtolower($join['type']) !== 'inner') {
             unset($joins[$i]);
         }
     }
     $keys = (array) $query->repository()->primaryKey();
     if ($this->type() === $this::MANY_TO_ONE) {
         $keys = (array) $this->foreignKey();
     }
     $filterQuery->join($joins, [], true);
     $fields = $query->aliasFields($keys);
     return $filterQuery->select($fields, true);
 }