Implements the "Evaluating selection sets" section of the spec for "read" mode.

@param ExecutionContext $context
@param ObjectType $parent
@param $source
@param $fields

@return array
339997
protected static function executeFields(ExecutionContext $context, ObjectType $parent, $source, $fields)
    {
        return self::executeFieldsSerially($context, $parent, $source, $fields);
    }
1235605
private function parseTypes(\ArrayIterator $tokens, Context $context, $parserContext)
    {
        $types = [];
        $token = '';
        while ($tokens->valid()) {
            $token = $tokens->current();

            if ($token === '|') {
                if (count($types) === 0) {
                    throw new \RuntimeException(
                        'A type is missing before a type separator'
                    );
                }

                if ($parserContext !== self::PARSER_IN_COMPOUND
                    && $parserContext !== self::PARSER_IN_ARRAY_EXPRESSION
                    && $parserContext !== self::PARSER_IN_COLLECTION_EXPRESSION
                ) {
                    throw new \RuntimeException(
                        'Unexpected type separator'
                    );
                }

                $tokens->next();
            } elseif ($token === '?') {
                if ($parserContext !== self::PARSER_IN_COMPOUND
                    && $parserContext !== self::PARSER_IN_ARRAY_EXPRESSION
                    && $parserContext !== self::PARSER_IN_COLLECTION_EXPRESSION
                ) {
                    throw new \RuntimeException(
                        'Unexpected nullable character'
                    );
                }

                $tokens->next();
                $type = $this->parseTypes($tokens, $context, self::PARSER_IN_NULLABLE);
                $types[] = new Nullable($type);
            } elseif ($token === '(') {
                $tokens->next();
                $type = $this->parseTypes($tokens, $context, self::PARSER_IN_ARRAY_EXPRESSION);

                $resolvedType = new Array_($type);

                $token = $tokens->current();
                // Someone did not properly close their array expression ..
                if ($token === null) {
                    break;
                }

                // we generate arrays corresponding to the number of '[]' after the ')'
                $numberOfArrays = (strlen($token) - 1) / 2;
                for ($i = 0; $i < $numberOfArrays - 1; ++$i) {
                    $resolvedType = new Array_($resolvedType);
                }

                $types[] = $resolvedType;
                $tokens->next();
            } elseif ($parserContext === self::PARSER_IN_ARRAY_EXPRESSION && $token[0] === ')') {
                break;
            } elseif ($token === '<') {
                if (count($types) === 0) {
                    throw new \RuntimeException(
                        'Unexpected collection operator "<", class name is missing'
                    );
                }

                $classType = array_pop($types);
                if ($classType !== null) {
                    $types[] = $this->resolveCollection($tokens, $classType, $context);
                }

                $tokens->next();
            } elseif ($parserContext === self::PARSER_IN_COLLECTION_EXPRESSION
                && ($token === '>' || trim($token) === ',')
                ) {
                break;
            } else {
                $type = $this->resolveSingleType($token, $context);
                $tokens->next();
                if ($parserContext === self::PARSER_IN_NULLABLE) {
                    return $type;
                }

                $types[] = $type;
            }
        }

        if ($token === '|') {
            throw new \RuntimeException(
                'A type is missing after a type separator'
            );
        }

        if (count($types) === 0) {
            if ($parserContext === self::PARSER_IN_NULLABLE) {
                throw new \RuntimeException(
                    'A type is missing after a nullable character'
                );
            }

            if ($parserContext === self::PARSER_IN_ARRAY_EXPRESSION) {
                throw new \RuntimeException(
                    'A type is missing in an array expression'
                );
            }

            if ($parserContext === self::PARSER_IN_COLLECTION_EXPRESSION) {
                throw new \RuntimeException(
                    'A type is missing in a collection expression'
                );
            }
        } elseif (count($types) === 1) {
            return $types[0];
        }

        return new Compound($types);
    }
1204734
public function evaluate( Context $context ) {
		/* @var \Ruler\Variable $left */
		list( $left ) = $this->getOperands();

		return null === $left->prepareValue( $context )->getValue();
	}
293853
public static function execute($values, ContextInterface $context): array
    {
        assert(is_array($values));

        // let's consider an empty index list as `readable`
        $result = true;

        if (empty($values) === false) {
            $apiClass = $context->getProperties()->getProperty(static::PROPERTY_API_CLASS);

            /** @var FactoryInterface $apiFactory */
            $apiFactory = $context->getContainer()->get(FactoryInterface::class);

            /** @var CrudInterface $api */
            $api = $apiFactory->createApi($apiClass);

            $readIndexes = $api->withIndexesFilter($values)->indexIdentities();

            $result = count($readIndexes) === count($values);
        }

        return $result === true ?
            static::createSuccessReply($values) :
            static::createErrorReply(
                $context,
                $values,
                ErrorCodes::EXIST_IN_DATABASE_MULTIPLE,
                Messages::EXIST_IN_DATABASE_MULTIPLE,
                []
            );
    }
798490
protected function _afterSelect(DatabaseContext $context)
    {
        if(!$context->query->isCountQuery())
        {
            $rowset = ObjectConfig::unbox($context->data);

            if ($rowset instanceof DatabaseRowsetInterface)
            {
                //Store the nodes
                $this->__nodes    = $rowset;
                $this->__iterator = null;
                $this->__children = array();

                foreach ($this->__nodes as $key => $row)
                {
                    //Force mixin the behavior into each row
                    $row->mixin($this);

                    if($row->isRecursable()) {
                        $parent = (int) $row->getProperty($this->_parent_column);
                    } else {
                        $parent = 0;
                    }

                    //Store the nodes by parent
                    $this->__children[$parent][$key] = $row;
                }

                //Sort the children
                ksort($this->__children);
            }
        }
    }
1241510
public function addTranslationSelect(
        string $root,
        EntityDefinition $definition,
        QueryBuilder $query,
        Context $context
    ): void {
        $translationDefinition = $definition->getTranslationDefinition();

        $fields = $translationDefinition->getFields();
        $chain = self::buildTranslationChain($root, $context, $definition->isInheritanceAware() && $context->considerInheritance());

        /** @var TranslatedField $field */
        foreach ($fields as $field) {
            if (!$field instanceof StorageAware) {
                continue;
            }

            foreach ($chain as $tableAccessor) {
                $name = $field->getPropertyName();
                $query->addSelect(
                    self::escape($tableAccessor['alias']) . '.' . self::escape($field->getStorageName()) . ' as '
                    . self::escape($tableAccessor['alias'] . '.' . $name)
                );
            }

            //check if current field is a translated field of the origin definition
            $origin = $definition->getFields()->get($field->getPropertyName());
            if ($origin instanceof TranslatedField) {
                //add selection for resolved parent-child and language inheritance
                $query->addSelect(
                    $this->getTranslationFieldSelectExpr($field, $chain) . ' as '
                    . self::escape($root . '.' . $field->getPropertyName())
                );
            }
        }
    }
335070
public function getVisitor(ValidationContext $context)
    {
        return [
            NodeKind::OPERATION_DEFINITION => function (OperationDefinitionNode $node) use ($context) {
                if ($node->operation === 'subscription') {
                    if (count($node->selectionSet->selections) !== 1) {
                        $context->reportError(
                            new Error(
                                $this->singleFieldOnlyMessage($node->name ? $node->name->value : null),
                                array_slice($node->selectionSet->selections, 1)
                            )
                        );
                    }
                }
            }
        ];
    }
557814
protected function doJoins($source, $joins, &$dest, $from, $contextAlias, $buildImpactIndex=true)
    {
        // expand sequences before doing any joins...
        $this->expandSequence($joins,$source);

        foreach ($joins as $predicate=>$ruleset) {
            if ($predicate=='followSequence') {
                continue;
            }

            if (isset($source[$predicate]))
            {
                // todo: perhaps we can get better performance by detecting whether or not
                // the uri to join on is already in the impact index, and if so not attempting
                // to join on it. However, we need to think about different combinations of
                // nested joins in different points of the view spec and see if this would
                // complicate things. Needs a unit test or two.
                $joinUris = [];
                if (isset($source[$predicate][VALUE_URI]))
                {
                    // single value for join
                    $joinUris[] = array(_ID_RESOURCE=>$source[$predicate][VALUE_URI],_ID_CONTEXT=>$contextAlias);
                }
                else
                {
                    // multiple values for join
                    $joinsPushed = 0;
                    foreach ($source[$predicate] as $v)
                    {
                        if (isset($ruleset['maxJoins']) && !$joinsPushed<$ruleset['maxJoins'])
                        {
                            break; // maxJoins reached
                        }
                        $joinUris[] = array(_ID_RESOURCE=>$v[VALUE_URI],_ID_CONTEXT=>$contextAlias);
                        $joinsPushed++;
                    }
                }

                $recursiveJoins = [];
                $collection = (
                isset($ruleset['from'])
                    ? $this->config->getCollectionForCBD($this->storeName, $ruleset['from'])
                    : $this->config->getCollectionForCBD($this->storeName, $from)
                );

                $cursor = $collection->find(array('_id'=>array('$in'=>$joinUris)), array(
                    'maxTimeMS' => $this->getConfigInstance()->getMongoCursorTimeout()
                ));

                $this->addIdToImpactIndex($joinUris, $dest, $buildImpactIndex);
                foreach($cursor as $linkMatch) {
                    // if there is a condition, check it...
                    if (isset($ruleset['condition']))
                    {
                        $ruleset['condition']['._id'] = $linkMatch['_id'];
                    }
                    if (!(isset($ruleset['condition']) && $collection->count($ruleset['condition'])==0))
                    {
                        // make sure any sequences are expanded before extracting properties
                        if (isset($ruleset['joins'])) $this->expandSequence($ruleset['joins'],$linkMatch);
                        if (isset($ruleset['filter']))
                        {
                            foreach($ruleset['filter'] as $filterPredicate => $filter)
                            {
                                foreach($filter as $filterType => $filterMatch)
                                {
                                    if (isset($linkMatch[$filterPredicate]))
                                    {
                                        foreach($linkMatch[$filterPredicate] as $linkMatchType => $linkMatchValues)
                                        {
                                            if (is_array($linkMatchValues) == false)
                                            {
                                                $linkMatchValues = array($linkMatchType => $linkMatchValues);
                                            }
                                            foreach($linkMatchValues as $linkMatchType => $linkMatchValue)
                                            {
                                                if ($this->matchesFilter($linkMatchType, $linkMatchValue, $filterType, $filterMatch))
                                                {
                                                    $dest[_GRAPHS][] = $this->extractProperties($linkMatch,$ruleset,$from);
                                                }
                                            }

                                        }
                                    }
                                }
                            }
                        }
                        else
                        {
                            $dest[_GRAPHS][] = $this->extractProperties($linkMatch,$ruleset,$from);
                        }

                        if (isset($ruleset['joins']))
                        {
                            // recursive joins must be done after this cursor has completed, otherwise things get messy
                            $recursiveJoins[] = array('data'=>$linkMatch, 'ruleset'=>$ruleset['joins']);
                        }
                    }
                }
                if (count($recursiveJoins)>0)
                {
                    foreach ($recursiveJoins as $r)
                    {
                        $this->doJoins($r['data'],$r['ruleset'],$dest,$from,$contextAlias,$buildImpactIndex);
                    }
                }
            }
        }
        return;
    }
1281229
public static function execute($values, ContextInterface $context): array
    {
        // let's consider an empty index list as `exists`
        $result = is_array($values);

        if ($result === true && empty($values) === false) {
            $tableName   = $context->getProperties()->getProperty(static::PROPERTY_TABLE_NAME);
            $primaryName = $context->getProperties()->getProperty(static::PROPERTY_PRIMARY_NAME);

            /** @var Connection $connection */
            $connection   = $context->getContainer()->get(Connection::class);
            $builder      = $connection->createQueryBuilder();
            $placeholders = [];
            foreach ($values as $value) {
                $placeholders[] = $builder->createPositionalParameter($value);
            }
            $statement = $builder
                ->select('count(*)')
                ->from($tableName)
                ->where($builder->expr()->in($primaryName, $placeholders))
                ->execute();

            $count  = (int)$statement->fetchColumn();
            $result = $count === count($values);
        }

        $reply = $result === true ?
            static::createSuccessReply($values) :
            static::createErrorReply(
                $context,
                $values,
                ErrorCodes::EXIST_IN_DATABASE_MULTIPLE,
                Messages::EXIST_IN_DATABASE_MULTIPLE,
                []
            );

        return $reply;
    }
1140376
private function renderHeaderFields($parentModel, EnvironmentInterface $environment)
    {
        $definition = $environment->getDataDefinition();
        $parentName = $definition->getBasicDefinition()->getParentDataProvider();
        $add        = [];
        $properties = $environment->getParentDataDefinition()->getPropertiesDefinition();
        foreach ($this->getViewSection($definition)->getListingConfig()->getHeaderPropertyNames() as $field) {
            $value = StringUtil::deserialize($parentModel->getProperty($field));

            if ('tstamp' === $field) {
                $value = date(Config::get('datimFormat'), $value);
            } else {
                $value = $this->renderParentProperty($environment, $properties->getProperty($field), $value);
            }

            // Add the field.
            if ('' !== $value) {
                $add[$this->translateHeaderColumnName($field, $parentName)] = $value;
            }
        }

        $event = new GetParentHeaderEvent($environment, $parentModel);
        $event->setAdditional($add);

        $environment->getEventDispatcher()->dispatch(GetParentHeaderEvent::NAME, $event);

        if (null !== !$event->getAdditional()) {
            $add = $event->getAdditional();
        }

        return \array_map(
            function ($value) {
                if (\is_array($value)) {
                    return $value[0];
                }
                return $value;
            },
            $add
        );
    }
856670
protected function joinSelectors($parent, $child) {
        $setSelf = false;
        $out = array();
        foreach ($child as $part) {
            $newPart = array();
            foreach ($part as $p) {
                if ($p == self::$selfSelector) {
                    $setSelf = true;
                    foreach ($parent as $i => $parentPart) {
                        if ($i > 0) {
                            $out[] = $newPart;
                            $newPart = array();
                        }

                        foreach ($parentPart as $pp) {
                            $newPart[] = $pp;
                        }
                    }
                } else {
                    $newPart[] = $p;
                }
            }

            $out[] = $newPart;
        }

        return $setSelf ? $out : array_merge($parent, $child);
    }
1274007
protected function _actionRead(ControllerContext $context)
    {
        if(!$context->result instanceof ModelEntityInterface)
        {
            if($this->getModel()->getState()->isUnique())
            {
                $entity = $this->getModel()->fetch();

                if(!count($entity))
                {
                    $name   = ucfirst($this->getView()->getName());
                    throw new ControllerExceptionResourceNotFound($name.' Not Found');
                }
            }
            else $entity = $this->getModel()->create();
        }
        else $entity = $context->result;

        //Set the entity in the context
        $context->setEntity($entity);

        return $entity;
    }
950290
public function getFieldData( VersionInfo $versionInfo, Field $field, array $context )
    {
        /** @var LegacyStorage $gateway */
        $gateway = $this->getGateway( $context );
        $gateway->getFieldData( $versionInfo, $field );
    }
475601
public function evaluate( Context $context ) {
		/**
		 * Extracts variables.
		 *
		 * @var \Ruler\Variable $left
		 * @var \Ruler\Variable $right
		 */
		list( $left, $right ) = $this->getOperands();

		$left  = $left->prepareValue( $context )->getValue();
		$right = $right->prepareValue( $context )->getValue();

		return in_array( $left, is_array( $right ) ? $right : [ $right ] );
	}
171052
public function createQuery($context = 'list')
    {
        $query = parent::createQuery($context);
        $query->leftJoin($query->getRootAlias().'.article', 'article')->addSelect('article')
              ->leftJoin($query->getRootAlias().'.parent', 'parent')->addSelect('parent')
              ->leftJoin($query->getRootAlias().'.children', 'children')->addSelect('children')
              ->orderBy($query->getRootAlias().'.root, '.$query->getRootAlias().'.lft', 'ASC');

        return $query;
    }
647939
public function evaluate(Context $context) {
		$opL = $this->operands[0]->evaluate($context);
		$opR = $this->operands[1]->evaluate($context);

		if ($opL instanceof \DOMNode) {
		    $opL = $opL->nodeValue;
		}
		if ($opR instanceof \DOMNode) {
		    $opR = $opR->nodeValue;
		}

		switch($this->comparator) {
			case 'gt' : return ($opL >  $opR);
			case 'gte': return ($opL >= $opR);
			case 'lt' : return ($opL <  $opR);
			case 'lte': return ($opL <= $opR);

			case '==' :
				//First: let's check for empty variables:
				if(
						(empty($opL) && ! empty($opR)) ||
						(empty($opR) && ! empty($opL))
					) {
					return false;
				}

				//If one of the operands is a string,
				//we must do a string comparison.
				if(is_string($opL) || is_string($opR)) {
					if(is_array($opL) || is_array($opR)) {
						//But if the other is an array, we cannot convert Array to String
						//to perform the comparison, so we throw an error.
						throw new LexerArrayToStringConversionException();
					} else {
						return (0 === strcmp($opL, $opR));
					}
				} else {
					return $opL == $opR;
				}

			case '!=' :
				if(is_float($opL)) {
					return ($opL . '' != $opR . '');
				} else {
					return ($opL != $opR);
				}

      // the "default:" case is not a possible branch.
      // I am required to write a default for the switch statement,
      // but it can never happen because the TokenComparisonBinop is only valid
      // for the above operators.
      // @codeCoverageIgnoreStart
			default: return false;
		}
    // @codeCoverageIgnoreEnd
    // I place this end annotation after the } of the switch, otherwise the } is
    // considered not covered!
    // I hate these hacks, but so far this is all what PHPUnit Coverage as to offer.
	}
1112237
public function evaluate(Context $context)
    {
        /** @var VariableOperand $left */
        /** @var VariableOperand $right */
        list($left, $right) = $this->getOperands();

        $left = $left->prepareValue($context);

        if (is_array($left->getValue())) {
            trigger_error('Contains operator is deprecated, please use SetContains', E_USER_DEPRECATED);

            return $left->getSet()->setContains($right->prepareValue($context));
        } else {
            trigger_error('Contains operator is deprecated, please use StringContains', E_USER_DEPRECATED);

            return $left->stringContains($right->prepareValue($context));
        }
    }