/** * Analyzes the given unary expression and alters it according. * * @param \Cake\Database\Expression\UnaryExpression $expression Unary expression * @param string $bundle Consider attributes only for a specific bundle * @param \Cake\ORM\Query $query The query instance this expression comes from * @return \Cake\Database\Expression\UnaryExpression Scoped expression (or not) */ protected function _inspectUnaryExpression(UnaryExpression $expression, $bundle, Query $query) { $class = new \ReflectionClass($expression); $property = $class->getProperty('_value'); $property->setAccessible(true); $value = $property->getValue($expression); if ($value instanceof IdentifierExpression) { $field = $value->getIdentifier(); $column = is_string($field) ? $this->_toolbox->columnName($field) : ''; if (empty($column) || in_array($column, (array) $this->_table->schema()->columns()) || !in_array($column, $this->_toolbox->getAttributeNames($bundle)) || !$this->_toolbox->isSearchable($column)) { // nothing to alter return $expression; } $pk = $this->_tablePrimaryKey(); $driverClass = $this->_driverClass($query); switch ($driverClass) { case 'sqlite': $concat = implode(' || ', $pk); $field = "({$concat} || '')"; break; case 'mysql': case 'postgres': case 'sqlserver': default: $concat = implode(', ', $pk); $field = "CONCAT({$concat}, '')"; break; } $attr = $this->_toolbox->attributes($bundle)[$column]; $type = $this->_toolbox->getType($column); $subQuery = TableRegistry::get('Eav.EavValues')->find()->select("EavValues.value_{$type}")->where(['EavValues.entity_id' => $field, 'EavValues.eav_attribute_id' => $attr['id']])->sql(); $subQuery = str_replace([':c0', ':c1'], [$field, $attr['id']], $subQuery); $property->setValue($expression, "({$subQuery})"); } return $expression; }