/** * Constructor * * @param string $fields the fields to use to form a tuple * @param array|ExpressionInterface $values the values to use to form a tuple * @param array $types the types names to use for casting each of the values, only * one type per position in the value array in needed * @param string $conjunction the operator used for comparing field and value */ public function __construct($fields, $values, $types = [], $conjunction = '=') { parent::__construct($fields, $values, $types, $conjunction); $this->_type = (array) $types; }
/** * Analyzes the given comparison expression and alters it according. * * @param \Cake\Database\Expression\Comparison $expression Comparison 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\Comparison Scoped expression (or not) */ protected function _inspectComparisonExpression(Comparison $expression, $bundle, Query $query) { $field = $expression->getField(); $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()) || !$this->_toolbox->isSearchable($column)) { // nothing to alter return $expression; } $attr = $this->_toolbox->attributes($bundle)[$column]; $value = $expression->getValue(); $type = $this->_toolbox->getType($column); $conjunction = $expression->getOperator(); $conditions = ['EavValues.eav_attribute_id' => $attr['id'], "EavValues.value_{$type} {$conjunction}" => $value]; // subquery scope $subQuery = TableRegistry::get('Eav.EavValues')->find()->select('EavValues.entity_id')->where($conditions); // some variables $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; } // compile query, faster than raw subquery in most cases $ids = $subQuery->all()->extract('entity_id')->toArray(); $ids = empty($ids) ? ['-1'] : $ids; $expression->setField($field); $expression->setValue($ids); $expression->setOperator('IN'); $class = new \ReflectionClass($expression); $property = $class->getProperty('_type'); $property->setAccessible(true); $property->setValue($expression, 'string'); $property = $class->getProperty('_isMultiple'); $property->setAccessible(true); $property->setValue($expression, true); return $expression; }
/** * Quotes identifiers in comparison expression objects * * @param \Cake\Database\Expression\Comparison $expression * @return void */ protected function _quoteComparison(Comparison $expression) { $field = $expression->getField(); if (is_string($field)) { $expression->field($this->_driver->quoteIdentifier($field)); } elseif (is_array($field)) { $quoted = []; foreach ($field as $f) { $quoted[] = $this->_driver->quoteIdentifier($f); } $expression->field($quoted); } elseif ($field instanceof ExpressionInterface) { $expression->field($this->quoteExpression($field)); } $value = $expression->getValue(); if ($value instanceof ExpressionInterface) { $this->quoteExpression($value); $expression->value($value); } }
/** * Método a ser usado como callable no beforeFind. * @param Comparison $comparison O objeto de comparação da query * @return void */ public function traverseClause($comparison) { if (isset($comparison)) { if ($this->_table->schema()->columnType($comparison->getField()) === "float") { if (is_string($comparison->getValue()) && !preg_match('/^[0-9]+(\\.[0-9]+)?$/', $comparison->getValue())) { $comparison->setValue(str_replace(',', '.', str_replace('.', '', $comparison->getValue()))); } } } }