Esempio n. 1
0
 /**
  * Initializes the repository instance.
  *
  * Initializes the repository instance based on a classes meta information.
  *
  * @param Arachnid $entityManager The entity manager.
  * @param Meta\GraphElement $meta The classes meta information.
  */
 public function __construct(Arachnid $entityManager, Meta\GraphElement $meta)
 {
     $this->entityManager = $entityManager;
     $this->class = $meta->getName();
     $this->meta = $meta;
 }
Esempio n. 2
0
 /**
  * Find properties based on a method name.
  *
  * This overrides graph elements findProperty, in order to allow for finding the start/end properties.
  *
  * @param string $name Method name.
  * @return Property|null Property if found, otherwise null.
  */
 function findProperty($name)
 {
     //Get the property from the method name
     $property = Reflection::getProperty($name);
     if ($this->start->matches($property)) {
         return $this->start;
     }
     if ($this->end->matches($property)) {
         return $this->end;
     }
     return parent::findProperty($name);
 }
Esempio n. 3
0
    /**
     * Creates a proxy class for a graph element.
     *
     * This method will create a proxy class for an entity that extends the required class and implements
     * LRezek\Arachnid\Proxy\Entity. This class will be generated and stored in the directory specified by the $proxyDir
     * property of this class. This is done so that the object returned by a query seemingly matches the object type
     * being queried for, while retaining its ID and other required information.
     *
     * @param GraphElement $meta The meta for the entity object being proxied.
     * @return mixed An instance of the proxy class.
     * @throws \LRezek\Arachnid\Exception If something goes wrong in file writing.
     */
    private function createProxy(GraphElement $meta)
    {
        //Get the proxy class name, as well as the regular class name
        $proxyClass = $meta->getProxyClass();
        $className = $meta->getName();
        //If the class already exists, just make an instance of it with the correct properties and return it.
        if (class_exists($proxyClass, false)) {
            return $this->newInstance($proxyClass);
        }
        //Create a target file for the class
        $targetFile = "{$this->proxyDir}/{$proxyClass}.php";
        //If the file doesn't exist
        if ($this->debug || !file_exists($targetFile)) {
            //Initialize functions
            $functions = '';
            $reflectionClass = new \ReflectionClass($className);
            //Loop through entities public methods
            foreach ($reflectionClass->getMethods(\ReflectionMethod::IS_PUBLIC) as $method) {
                //If the method isn't a constructor, destructor, or final, add it to the methods via method proxy.
                if (!$method->isConstructor() && !$method->isDestructor() && !$method->isFinal()) {
                    $functions .= $this->methodProxy($method, $meta);
                }
            }
            //Get the properties and primary key.
            $properties = $meta->getProperties();
            $properties[] = $meta->getPrimaryKey();
            //Filter out private properties
            $properties = array_filter($properties, function ($property) {
                return !$property->isPrivate();
            });
            //Create an array map by property name
            $properties = array_map(function ($property) {
                return $property->getName();
            }, $properties);
            //Create php code for properties.
            $properties = var_export($properties, true);
            //Create the actual class.
            $content = <<<CONTENT
<?php

class {$proxyClass} extends {$className} implements LRezek\\Arachnid\\Proxy\\Entity
{
    private \$neo4j_hydrated = array();
    private \$neo4j_meta;
    private \$neo4j_entity;
    private \$neo4j_loadCallback;

    function getEntity()
    {
        \$entity = new {$className};

        foreach (\$this->neo4j_meta->getProperties() as \$prop)
        {
            \$prop->setValue(\$entity, \$prop->getValue(\$this));
        }

        \$prop = \$this->neo4j_meta->getPrimaryKey();
        \$prop->setValue(\$entity, \$prop->getValue(\$this));

        return \$entity;
    }

    {$functions}

    function __addHydrated(\$name)
    {
        \$this->neo4j_hydrated[] = \$name;
    }

    function __setMeta(\$meta)
    {
        \$this->neo4j_meta = \$meta;
    }

    function __setEntity(\$entity)
    {
        \$this->neo4j_entity = \$entity;
    }

    function __getEntity()
    {
        return \$this->neo4j_entity;
    }

    function __setLoadCallback(\$loadCallback)
    {
        \$this->neo4j_loadCallback = \$loadCallback;
    }

    private function __load(\$name, \$propertyName)
    {
        //Already hydrated
        if(in_array(\$propertyName, \$this->neo4j_hydrated))
        {
            return;
        }

        if(! \$this->neo4j_meta)
        {
            throw new \\LRezek\\Arachnid\\Exception('Proxy not fully initialized.');
        }

        \$property = \$this->neo4j_meta->findProperty(\$name);

        if(strpos(\$name, 'set') === 0)
        {
            \$this->__addHydrated(\$propertyName);
            return;
        }

        //Make property node
        if(\$property->isStart() || \$property->isEnd())
        {
            \$loader = \$this->neo4j_loadCallback;

            //Get the node
            if(\$property->isStart())
            {
                \$node = \$this->neo4j_entity->getStartNode();
            }
            else
            {
                \$node = \$this->neo4j_entity->getEndNode();
            }

            \$node = \$loader(\$node);

            //Set the property
            \$property->setValue(\$this, \$node);
        }

        //Hydrate the property
        \$this->__addHydrated(\$propertyName);

    }

    function __sleep()
    {
        return {$properties};
    }
}


CONTENT;
            //Make sure the proxy directory is an actual directory
            if (!is_dir($this->proxyDir)) {
                if (false === @mkdir($this->proxyDir, 0775, true)) {
                    throw new Exception('Proxy Dir is not writable.');
                }
            } else {
                if (!is_writable($this->proxyDir)) {
                    throw new Exception('Proxy Dir is not writable.');
                }
            }
            //Write the file
            file_put_contents($targetFile, $content);
        }
        //Add file to class loader
        require $targetFile;
        //Return an instance of the proxy class
        return $this->newInstance($proxyClass);
    }