src/Eccube/Entity/AbstractEntity.php line 34

Open in your IDE?
  1. <?php
  2. /*
  3.  * This file is part of EC-CUBE
  4.  *
  5.  * Copyright(c) EC-CUBE CO.,LTD. All Rights Reserved.
  6.  *
  7.  * http://www.ec-cube.co.jp/
  8.  *
  9.  * For the full copyright and license information, please view the LICENSE
  10.  * file that was distributed with this source code.
  11.  */
  12. namespace Eccube\Entity;
  13. use Doctrine\Common\Annotations\Reader;
  14. use Doctrine\Common\Collections\Collection;
  15. use Doctrine\Common\Inflector\Inflector;
  16. use Doctrine\ORM\Mapping\Id;
  17. use Doctrine\ORM\Mapping\MappedSuperclass;
  18. use Doctrine\ORM\Proxy\Proxy;
  19. use Eccube\Util\StringUtil;
  20. use Symfony\Component\Serializer\Encoder\XmlEncoder;
  21. use Symfony\Component\Serializer\Normalizer\PropertyNormalizer;
  22. use Symfony\Component\Serializer\Serializer;
  23. /** @MappedSuperclass */
  24. abstract class AbstractEntity implements \ArrayAccess
  25. {
  26.     private $AnnotationReader;
  27.     public function offsetExists($offset)
  28.     {
  29.         $method Inflector::classify($offset);
  30.         return method_exists($this$method)
  31.             || method_exists($this"get$method")
  32.             || method_exists($this"is$method")
  33.             || method_exists($this"has$method");
  34.     }
  35.     public function offsetSet($offset$value)
  36.     {
  37.     }
  38.     public function offsetGet($offset)
  39.     {
  40.         $method Inflector::classify($offset);
  41.         if (method_exists($this$method)) {
  42.             return $this->$method();
  43.         } elseif (method_exists($this"get$method")) {
  44.             return $this->{"get$method"}();
  45.         } elseif (method_exists($this"is$method")) {
  46.             return $this->{"is$method"}();
  47.         } elseif (method_exists($this"has$method")) {
  48.             return $this->{"has$method"}();
  49.         }
  50.     }
  51.     public function offsetUnset($offset)
  52.     {
  53.     }
  54.     /**
  55.      * 引数の連想配列を元にプロパティを設定します.
  56.      * DBから取り出した連想配列を, プロパティへ設定する際に使用します.
  57.      *
  58.      * @param array $arrProps プロパティの情報を格納した連想配列
  59.      * @param \ReflectionClass $parentClass 親のクラス. 本メソッドの内部的に使用します.
  60.      * @param string[] $excludeAttribute 除外したいフィールド名の配列
  61.      */
  62.     public function setPropertiesFromArray(array $arrProps, array $excludeAttribute = [], \ReflectionClass $parentClass null)
  63.     {
  64.         $objReflect null;
  65.         if (is_object($parentClass)) {
  66.             $objReflect $parentClass;
  67.         } else {
  68.             $objReflect = new \ReflectionClass($this);
  69.         }
  70.         $arrProperties $objReflect->getProperties();
  71.         foreach ($arrProperties as $objProperty) {
  72.             $objProperty->setAccessible(true);
  73.             $name $objProperty->getName();
  74.             if (in_array($name$excludeAttribute) || !array_key_exists($name$arrProps)) {
  75.                 continue;
  76.             }
  77.             $objProperty->setValue($this$arrProps[$name]);
  78.         }
  79.         // 親クラスがある場合は再帰的にプロパティを取得
  80.         $parentClass $objReflect->getParentClass();
  81.         if (is_object($parentClass)) {
  82.             self::setPropertiesFromArray($arrProps$excludeAttribute$parentClass);
  83.         }
  84.     }
  85.     /**
  86.      * Convert to associative array.
  87.      *
  88.      * Symfony Serializer Component is expensive, and hard to implementation.
  89.      * Use for encoder only.
  90.      *
  91.      * @param \ReflectionClass $parentClass parent class. Use internally of this method..
  92.      * @param array $excludeAttribute Array of field names to exclusion.
  93.      *
  94.      * @return array
  95.      */
  96.     public function toArray(array $excludeAttribute = ['__initializer__''__cloner__''__isInitialized__''AnnotationReader'], \ReflectionClass $parentClass null)
  97.     {
  98.         $objReflect null;
  99.         if (is_object($parentClass)) {
  100.             $objReflect $parentClass;
  101.         } else {
  102.             $objReflect = new \ReflectionClass($this);
  103.         }
  104.         $arrProperties $objReflect->getProperties();
  105.         $arrResults = [];
  106.         foreach ($arrProperties as $objProperty) {
  107.             $objProperty->setAccessible(true);
  108.             $name $objProperty->getName();
  109.             if (in_array($name$excludeAttribute)) {
  110.                 continue;
  111.             }
  112.             $arrResults[$name] = $objProperty->getValue($this);
  113.         }
  114.         $parentClass $objReflect->getParentClass();
  115.         if (is_object($parentClass)) {
  116.             $arrParents self::toArray($excludeAttribute$parentClass);
  117.             if (!is_array($arrParents)) {
  118.                 $arrParents = [];
  119.             }
  120.             if (!is_array($arrResults)) {
  121.                 $arrResults = [];
  122.             }
  123.             $arrResults array_merge($arrParents$arrResults);
  124.         }
  125.         return $arrResults;
  126.     }
  127.     /**
  128.      * Convert to associative array, and normalize to association properties.
  129.      *
  130.      * The type conversion such as:
  131.      * - Datetime ::  W3C datetime format string
  132.      * - AbstractEntity :: associative array such as [id => value]
  133.      * - PersistentCollection :: associative array of [[id => value], [id => value], ...]
  134.      *
  135.      * @param array $excludeAttribute Array of field names to exclusion.
  136.      *
  137.      * @return array
  138.      */
  139.     public function toNormalizedArray(array $excludeAttribute = ['__initializer__''__cloner__''__isInitialized__''AnnotationReader'])
  140.     {
  141.         $arrResult $this->toArray($excludeAttribute);
  142.         foreach ($arrResult as &$value) {
  143.             if ($value instanceof \DateTime) {
  144.                 // see also https://stackoverflow.com/a/17390817/4956633
  145.                 $value->setTimezone(new \DateTimeZone('UTC'));
  146.                 $value $value->format('Y-m-d\TH:i:s\Z');
  147.             } elseif ($value instanceof AbstractEntity) {
  148.                 // Entity の場合は [id => value] の配列を返す
  149.                 $value $this->getEntityIdentifierAsArray($value);
  150.             } elseif ($value instanceof Collection) {
  151.                 // Collection の場合は ID を持つオブジェクトの配列を返す
  152.                 $Collections $value;
  153.                 $value = [];
  154.                 foreach ($Collections as $Child) {
  155.                     $value[] = $this->getEntityIdentifierAsArray($Child);
  156.                 }
  157.             }
  158.         }
  159.         return $arrResult;
  160.     }
  161.     /**
  162.      * Convert to JSON.
  163.      *
  164.      * @param array $excludeAttribute Array of field names to exclusion.
  165.      *
  166.      * @return string
  167.      */
  168.     public function toJSON(array $excludeAttribute = ['__initializer__''__cloner__''__isInitialized__''AnnotationReader'])
  169.     {
  170.         return json_encode($this->toNormalizedArray($excludeAttribute));
  171.     }
  172.     /**
  173.      * Convert to XML.
  174.      *
  175.      * @param array $excludeAttribute Array of field names to exclusion.
  176.      *
  177.      * @return string
  178.      */
  179.     public function toXML(array $excludeAttribute = ['__initializer__''__cloner__''__isInitialized__''AnnotationReader'])
  180.     {
  181.         $ReflectionClass = new \ReflectionClass($this);
  182.         $serializer = new Serializer([new PropertyNormalizer()], [new XmlEncoder($ReflectionClass->getShortName())]);
  183.         $xml $serializer->serialize($this->toNormalizedArray($excludeAttribute), 'xml');
  184.         if ('\\' === DIRECTORY_SEPARATOR) {
  185.             // The m modifier of the preg functions converts the end-of-line to '\n'
  186.             $xml StringUtil::convertLineFeed($xml"\r\n");
  187.         }
  188.         return $xml;
  189.     }
  190.     /**
  191.      * コピー元のオブジェクトのフィールド名を指定して、同名のフィールドに値をコピー
  192.      *
  193.      * @param object $srcObject コピー元のオブジェクト
  194.      * @param string[] $excludeAttribute 除外したいフィールド名の配列
  195.      *
  196.      * @return AbstractEntity
  197.      */
  198.     public function copyProperties($srcObject, array $excludeAttribute = [])
  199.     {
  200.         $this->setPropertiesFromArray($srcObject->toArray($excludeAttribute), $excludeAttribute);
  201.         return $this;
  202.     }
  203.     /**
  204.      * Set AnnotationReader.
  205.      *
  206.      * @param Reader $Reader
  207.      *
  208.      * @return AbstractEntity
  209.      */
  210.     public function setAnnotationReader(Reader $Reader)
  211.     {
  212.         $this->AnnotationReader $Reader;
  213.         return $this;
  214.     }
  215.     /**
  216.      * Get AnnotationReader.
  217.      *
  218.      * @return Reader
  219.      */
  220.     public function getAnnotationReader()
  221.     {
  222.         if ($this->AnnotationReader) {
  223.             return $this->AnnotationReader;
  224.         }
  225.         return new \Doctrine\Common\Annotations\AnnotationReader();
  226.     }
  227.     /**
  228.      * Convert to Entity of Identity value to associative array.
  229.      *
  230.      * @param AbstractEntity $Entity
  231.      *
  232.      * @return array associative array of [[id => value], [id => value], ...]
  233.      */
  234.     public function getEntityIdentifierAsArray(AbstractEntity $Entity)
  235.     {
  236.         $Result = [];
  237.         $PropReflect = new \ReflectionClass($Entity);
  238.         if ($Entity instanceof Proxy) {
  239.             // Doctrine Proxy の場合は親クラスを取得
  240.             $PropReflect $PropReflect->getParentClass();
  241.         }
  242.         $Properties $PropReflect->getProperties();
  243.         foreach ($Properties as $Property) {
  244.             $anno $this->getAnnotationReader()->getPropertyAnnotation($PropertyId::class);
  245.             if ($anno) {
  246.                 $Property->setAccessible(true);
  247.                 $Result[$Property->getName()] = $Property->getValue($Entity);
  248.             }
  249.         }
  250.         return $Result;
  251.     }
  252. }