Overview

Namespaces

  • LeanMapperQuery
    • Exception
    • QueryTarget

Classes

  • LeanMapperQuery\Caller
  • LeanMapperQuery\Entity
  • LeanMapperQuery\Query
  • LeanMapperQuery\QueryTarget\HasManyRelationshipTable
  • LeanMapperQuery\QueryTarget\HasManyTargetTable

Interfaces

  • LeanMapperQuery\ICaster
  • LeanMapperQuery\IQuery
  • LeanMapperQuery\QueryTarget\ITarget

Exceptions

  • LeanMapperQuery\Exception\Exception
  • LeanMapperQuery\Exception\InvalidArgumentException
  • LeanMapperQuery\Exception\InvalidMethodCallException
  • LeanMapperQuery\Exception\InvalidRelationshipException
  • LeanMapperQuery\Exception\InvalidStateException
  • LeanMapperQuery\Exception\MemberAccessException
  • LeanMapperQuery\Exception\NonExistingMethodException
  • LeanMapperQuery\Exception\NotImplementedException
  • Overview
  • Namespace
  • Class
  1:   2:   3:   4:   5:   6:   7:   8:   9:  10:  11:  12:  13:  14:  15:  16:  17:  18:  19:  20:  21:  22:  23:  24:  25:  26:  27:  28:  29:  30:  31:  32:  33:  34:  35:  36:  37:  38:  39:  40:  41:  42:  43:  44:  45:  46:  47:  48:  49:  50:  51:  52:  53:  54:  55:  56:  57:  58:  59:  60:  61:  62:  63:  64:  65:  66:  67:  68:  69:  70:  71:  72:  73:  74:  75:  76:  77:  78:  79:  80:  81:  82:  83:  84:  85:  86:  87:  88:  89:  90:  91:  92:  93:  94:  95:  96:  97:  98:  99: 100: 101: 102: 103: 104: 105: 106: 107: 108: 109: 110: 111: 112: 113: 114: 115: 116: 117: 118: 119: 120: 121: 122: 123: 124: 125: 126: 127: 128: 129: 130: 131: 132: 133: 134: 135: 136: 137: 138: 139: 140: 141: 142: 143: 
<?php

/**
 * This file is part of the LeanMapperQuery extension
 * for the Lean Mapper library (http://leanmapper.com)
 * Copyright (c) 2013 Michal Bohuslávek
 */

namespace LeanMapperQuery;

use LeanMapper;
use LeanMapper\Filtering;
use LeanMapper\Fluent;
use LeanMapper\Reflection\Property;
use LeanMapper\Relationship;
use LeanMapper\Result;
use LeanMapperQuery\Caller;
use LeanMapperQuery\Exception\InvalidArgumentException;
use LeanMapperQuery\Exception\InvalidMethodCallException;
use LeanMapperQuery\Exception\InvalidRelationshipException;
use LeanMapperQuery\Exception\InvalidStateException;
use LeanMapperQuery\Exception\MemberAccessException;
use LeanMapperQuery\IQuery;

/**
 * @author Michal Bohuslávek
 */
class Entity extends LeanMapper\Entity
{
    /** @var array */
    protected static $magicMethodsPrefixes = [];

    protected function queryProperty($field, IQuery $query)
    {
        return static::queryEntityProperty($this, $field, $query);
    }

    public static function queryEntityProperty(LeanMapper\Entity $entity, $field, IQuery $query)
    {
        if ($entity->isDetached()) {
            throw new InvalidStateException('Cannot query detached entity.');
        }
        $property = $entity->getCurrentReflection()->getEntityProperty($field);
        if ($property === NULL) {
            throw new MemberAccessException("Cannot access undefined property '$field' in entity " . get_called_class() . '.');
        }
        if (!$property->hasRelationship()) {
            throw new InvalidArgumentException("Property '{$property->getName()}' in entity ". get_called_class() . " has no relationship.");
        }
        $class = $property->getType();
        $filters = $entity->createImplicitFilters($class, new Caller($entity, $property))->getFilters();
        $mapper = $entity->mapper;
        $relationship = $property->getRelationship();

        if (!($relationship instanceof Relationship\BelongsToMany) && !($relationship instanceof Relationship\HasMany)) {
            throw new InvalidRelationshipException('Only BelongsToMany and HasMany relationships are supported when querying entity property. ' . get_class($relationship) . ' given.');
        }

        $strategy = $relationship->getStrategy();

        if ($strategy !== Result::STRATEGY_UNION) {
            $strategy = $query->getStrategy();
        }

        if ($relationship instanceof Relationship\BelongsToMany) {
            $filters[] = function (Fluent $fluent) use ($mapper, $query) {
                $query->applyQuery($fluent, $mapper);
            };

            $targetTable = $relationship->getTargetTable();
            $referencingColumn = $relationship->getColumnReferencingSourceTable();
            $rows = $entity->row->referencing($targetTable, $referencingColumn, new Filtering($filters), $strategy);

        } elseif ($relationship instanceof Relationship\HasMany) {
            $filters[] = function (Fluent $fluent) use ($mapper, $query) {
                $query->applyQuery($fluent, $mapper, new QueryTarget\HasManyTargetTable);
            };

            $relationshipTable = $relationship->getRelationshipTable();
            $sourceReferencingColumn = $relationship->getColumnReferencingSourceTable();
            $targetReferencingColumn = $relationship->getColumnReferencingTargetTable();
            $targetTable = $relationship->getTargetTable();
            $targetPrimaryKey = $mapper->getPrimaryKey($targetTable);
            $rows = [];
            $resultRows = [];
            $targetResultProxy = NULL;
            $relationshipFiltering = NULL;

            if ($strategy === Result::STRATEGY_UNION) {
                $relationshipFiltering = new Filtering(function (Fluent $fluent) use ($mapper, $query, $relationship) {
                    $query->applyQuery($fluent, $mapper, new QueryTarget\HasManyRelationshipTable($relationship));
                });
            }

            foreach ($entity->row->referencing($relationshipTable, $sourceReferencingColumn, $relationshipFiltering, $strategy) as $relationship) {
                $row = $relationship->referenced($targetTable, $targetReferencingColumn, new Filtering($filters));
                if ($row !== NULL && $targetResultProxy === NULL) {
                    $targetResultProxy = $row->getResultProxy();
                }
                $row !== NULL && $resultRows[$row->{$targetPrimaryKey}] = $row;
            }

            if ($targetResultProxy) {
                foreach ($targetResultProxy as $rowId => $rowData) {
                    if (isset($resultRows[$rowId])) {
                        $rows[] = $resultRows[$rowId];
                    }
                }
            } else {
                $rows = $resultRows;
            }
        }
        $entities = [];
        $table = $mapper->getTable($class);
        foreach ($rows as $row) {
            $newEntity = $entity->entityFactory->createEntity($mapper->getEntityClass($table, $row), $row);
            $newEntity->makeAlive($entity->entityFactory);
            $entities[] = $newEntity;
        }
        return $entities;
    }

    public function __call($name, array $arguments)
    {
        if (preg_match('#^('.implode('|', static::$magicMethodsPrefixes).')(.+)$#', $name, $matches)) {
            if (count($arguments) !== 1) {
                throw new InvalidMethodCallException(get_called_class() . "::$name expects exactly 1 argument. " . count($arguments) . ' given.');
            }
            list($query) = $arguments;
            if (!$query instanceof IQuery) {
                throw new InvalidArgumentException('Argument 1 passed to ' . get_called_class() . "::$name must implement interface LeanMapperQuery\\IQuery. " . gettype($query) . ' given.');
            }
            list(, $method, $field) = $matches;
            $field = lcfirst($field);
            return $this->$method($field, $query);

        } else {
            return parent::__call($name, $arguments);
        }
    }

}
mibk/leanmapperquery master API documentation API documentation generated by ApiGen