protected function _appendNotMatching($query, $options)
{
if (empty($options['negateMatch'])) {
return;
}
if (!isset($options['conditions'])) {
$options['conditions'] = [];
}
$junction = $this->junction();
$belongsTo = $junction->association($this->source()->alias());
$conds = $belongsTo->_joinCondition(['foreignKey' => $belongsTo->foreignKey()]);
$subquery = $this->find()->select(array_values($conds))->where($options['conditions'])->andWhere($this->junctionConditions());
if (!empty($options['queryBuilder'])) {
$subquery = $options['queryBuilder']($subquery);
}
$assoc = $junction->association($this->target()->alias());
$conditions = $assoc->_joinCondition(['foreignKey' => $this->targetForeignKey()]);
$subquery = $this->_appendJunctionJoin($subquery, $conditions);
$query->andWhere(function ($exp) use($subquery, $conds) {
$identifiers = [];
foreach (array_keys($conds) as $field) {
$identifiers = new IdentifierExpression($field);
}
$identifiers = $subquery->newExpr()->add($identifiers)->tieWith(',');
$nullExp = clone $exp;
return $exp->or_([$exp->notIn($identifiers, $subquery), $nullExp->and(array_map([$nullExp, 'isNull'], array_keys($conds)))]);
});
}