src/Package/Toolkit/Doctrine/DataCollector/DataCollector.php line 119

Open in your IDE?
  1. <?php
  2. namespace App\Package\Toolkit\Doctrine\DataCollector;
  3. use Doctrine\Bundle\DoctrineBundle\DataCollector\DoctrineDataCollector,
  4.     Doctrine\Persistence\ManagerRegistry;
  5. use Doctrine\ORM\Cache\Logging\{ CacheLoggerChainStatisticsCacheLogger };
  6. use Doctrine\ORM\Configuration,
  7.     Doctrine\ORM\Mapping\ClassMetadataFactory,
  8.     Doctrine\ORM\Version,
  9.     Doctrine\DBAL\Logging\DebugStack,
  10.     Doctrine\DBAL\Types\Type;
  11. use Symfony\Component\HttpFoundation\{ RequestResponse };
  12. use Throwable;
  13. use Symfony\Bridge\Doctrine\DataCollector\ObjectParameter;
  14. use App\Package\Toolkit\Doctrine\DataCollector\SchemaValidator;
  15. /**
  16.  * DataCollector
  17.  * 
  18.  * Collects informations for profiler
  19.  * 
  20.  * @brief      manually setting logger as default logger from loggers
  21.  * 
  22.  * @origin
  23.  * - type:     extended and overwritten
  24.  * - vendor:   doctrine/doctrine-bundle [ version = 1.6 ]
  25.  * - class:    Doctrine\Bundle\DoctrineBundle\DataCollector\DoctrineDataCollector
  26.  * - reason:   doctrine inheritance system interference (see Documentation\CHANGELOG.md)
  27.  *             (had to manually set logger as default logger from loggers)
  28.  * 
  29.  * @overwritten
  30.  * - __construct
  31.  * - collect
  32.  * 
  33.  * @copied [ from DoctrineDataCollector (parent) ]
  34.  * - $registry
  35.  * 
  36.  * @copied [ from parent of DoctrineDataCollector - 
  37.  *           Symfony\Bridge\Doctrine\DataCollector\DoctrineDataCollector (parent of parent) ]
  38.  * - $connections
  39.  * - $managers
  40.  * - $loggers
  41.  * 
  42.  * @copiedAndRenamed [ from parent of DoctrineDataCollector - 
  43.  *                     Symfony\Bridge\Doctrine\DataCollector\DoctrineDataCollector (parent of parent) ]
  44.  * - sanitizeQueries  => renamed to =>  customSanitizeQueries
  45.  * - sanitizeQuery    => renamed to =>  customSanitizeQuery
  46.  * - sanitizeParam    => renamed to =>  customSanitizeParam
  47.  * 
  48.  * @see        @openformCustomized tags for customized content
  49.  *             modified functions are marked with @OVEWRITTEN
  50.  *             renamed and modified functions are marekd with @RENAMED_AND_MODIFIED
  51.  * 
  52.  * @author     Doctrine
  53.  * @author     Daniel Balowski <d.balowski@openform.pl> (_developer)
  54.  * @copyright  Openform
  55.  * @since      03.2019
  56.  */
  57. class DataCollector extends DoctrineDataCollector
  58. {
  59.     /**
  60.      * Copied from DoctrineDataCollector (parent)
  61.      * 
  62.      * @var ManagerRegistry
  63.      */
  64.     protected $registry;
  65.     
  66.     /**
  67.      * Copied from Symfony\Bridge\Doctrine\DataCollector\DoctrineDataCollector (parent of parent)
  68.      * 
  69.      * @var array
  70.      */
  71.     protected $connections;
  72.     
  73.     /**
  74.      * Copied from Symfony\Bridge\Doctrine\DataCollector\DoctrineDataCollector (parent of parent)
  75.      * 
  76.      * @var array
  77.      */
  78.     protected $managers;
  79.     /**
  80.      * Copied from Symfony\Bridge\Doctrine\DataCollector\DoctrineDataCollector (parent of parent)
  81.      * 
  82.      * @var array
  83.      */
  84.     protected $loggers = [];
  85.     /**
  86.      * @OVERWRITTEN
  87.      * 
  88.      * @openformCustomized
  89.      * - added check if logger passed then set default logger in loggers
  90.      * 
  91.      * {@inheritDoc}
  92.      */
  93.     public function __construct(ManagerRegistry $registryDebugStack $logger null)
  94.     {
  95.         $this->registry    $registry;
  96.         $this->connections $registry->getConnectionNames();
  97.         $this->managers    $registry->getManagerNames();
  98.         if ($logger) {
  99.             $this->loggers['default'] = $logger;
  100.         }
  101.         parent::__construct($registry);
  102.     }
  103.     /**
  104.      * @OVERWRITTEN
  105.      * 
  106.      * @openformCustomized
  107.      * - changed to use customSanitizeQueries instead of sanitizeQueries
  108.      * 
  109.      * {@inheritDoc}
  110.      */
  111.     public function collect(Request $requestResponse $response, ?Throwable $exception null)
  112.     {
  113.         $queries = array();
  114.         foreach ($this->loggers as $name => $logger) {
  115.             $queries[$name] = $this->customSanitizeQueries($name$logger->queries);
  116.         }
  117.         $this->data = array(
  118.             'queries' => $queries,
  119.             'connections' => $this->connections,
  120.             'managers' => $this->managers,
  121.         );
  122.         $errors   = [];
  123.         $entities = [];
  124.         $caches   = [
  125.             'enabled' => false,
  126.             'log_enabled' => false,
  127.             'counts' => [
  128.                 'puts' => 0,
  129.                 'hits' => 0,
  130.                 'misses' => 0,
  131.             ],
  132.             'regions' => [
  133.                 'puts' => [],
  134.                 'hits' => [],
  135.                 'misses' => [],
  136.             ],
  137.         ];
  138.         /** @var \Doctrine\ORM\EntityManagerInterface $em */
  139.         foreach ($this->registry->getManagers() as $name => $em) {
  140.             $entities[$name] = [];
  141.             /** @var ClassMetadataFactory $factory */
  142.             $factory   $em->getMetadataFactory();
  143.             $validator = new SchemaValidator($em);
  144.             /** @var \Doctrine\ORM\Mapping\ClassMetadataInfo $class*/
  145.             foreach ($factory->getLoadedMetadata() as $class) {
  146.                 if (isset($entities[$name][$class->getName()])) {
  147.                     continue;
  148.                 }
  149.                 $classErrors                        $validator->validateClass($class);
  150.                 $entities[$name][$class->getName()] = $class->getName();
  151.                 if (empty($classErrors)) {
  152.                     continue;
  153.                 }
  154.                 $errors[$name][$class->getName()] = $classErrors;
  155.             }
  156.             if (version_compare(Version::VERSION'2.5.0-DEV') < 0) {
  157.                 continue;
  158.             }
  159.             /** @var Configuration $emConfig */
  160.             $emConfig   $em->getConfiguration();
  161.             $slcEnabled $emConfig->isSecondLevelCacheEnabled();
  162.             if (! $slcEnabled) {
  163.                 continue;
  164.             }
  165.             $caches['enabled'] = true;
  166.             /** @var \Doctrine\ORM\Cache\CacheConfiguration */
  167.             $cacheConfiguration $emConfig->getSecondLevelCacheConfiguration();
  168.             /** @var \Doctrine\ORM\Cache\Logging\CacheLoggerChain */
  169.             $cacheLoggerChain $cacheConfiguration->getCacheLogger();
  170.             if (! $cacheLoggerChain || ! $cacheLoggerChain->getLogger('statistics')) {
  171.                 continue;
  172.             }
  173.             /** @var StatisticsCacheLogger $cacheLoggerStats */
  174.             $cacheLoggerStats      $cacheLoggerChain->getLogger('statistics');
  175.             $caches['log_enabled'] = true;
  176.             $caches['counts']['puts']   += $cacheLoggerStats->getPutCount();
  177.             $caches['counts']['hits']   += $cacheLoggerStats->getHitCount();
  178.             $caches['counts']['misses'] += $cacheLoggerStats->getMissCount();
  179.             foreach ($cacheLoggerStats->getRegionsPut() as $key => $value) {
  180.                 if (! isset($caches['regions']['puts'][$key])) {
  181.                     $caches['regions']['puts'][$key] = 0;
  182.                 }
  183.                 $caches['regions']['puts'][$key] += $value;
  184.             }
  185.             foreach ($cacheLoggerStats->getRegionsHit() as $key => $value) {
  186.                 if (! isset($caches['regions']['hits'][$key])) {
  187.                     $caches['regions']['hits'][$key] = 0;
  188.                 }
  189.                 $caches['regions']['hits'][$key] += $value;
  190.             }
  191.             foreach ($cacheLoggerStats->getRegionsMiss() as $key => $value) {
  192.                 if (! isset($caches['regions']['misses'][$key])) {
  193.                     $caches['regions']['misses'][$key] = 0;
  194.                 }
  195.                 $caches['regions']['misses'][$key] += $value;
  196.             }
  197.         }
  198.         // HttpKernel < 3.2 compatibility layer
  199.         if (method_exists($this'cloneVar')) {
  200.             // Might be good idea to replicate this block in doctrine bridge so we can drop this from here after some time.
  201.             // This code is compatible with such change, because cloneVar is supposed to check if input is already cloned.
  202.             foreach ($this->data['queries'] as &$queries) {
  203.                 foreach ($queries as &$query) {
  204.                     $query['params'] = $this->cloneVar($query['params']);
  205.                 }
  206.             }
  207.         }
  208.         $this->data['entities'] = $entities;
  209.         $this->data['errors']   = $errors;
  210.         $this->data['caches']   = $caches;
  211.         $this->groupedQueries   null;
  212.     }
  213.     /**
  214.      * @RENAMED_AND_MODIFIED
  215.      * 
  216.      * @openformCustomized
  217.      * - changed to use customSanitizeQuery instead of sanitizeQuery
  218.      * 
  219.      * @param  $connectionName
  220.      * @param  $queries
  221.      * 
  222.      * @return array
  223.      */
  224.     protected function customSanitizeQueries($connectionName$queries)
  225.     {
  226.         foreach ($queries as $i => $query) {
  227.             $queries[$i] = $this->customSanitizeQuery($connectionName$query);
  228.         }
  229.         return $queries;
  230.     }
  231.     /**
  232.      * @RENAMED_AND_MODIFIED
  233.      * 
  234.      * @openformCustomized
  235.      * - changed to use customSanitizeParam instead of sanitizeParam
  236.      * 
  237.      * @param  $connectionName
  238.      * @param  $query
  239.      * 
  240.      * @return array
  241.      */
  242.     protected function customSanitizeQuery($connectionName$query)
  243.     {
  244.         $query['explainable'] = true;
  245.         $query['runnable'] = true;
  246.         if (null === $query['params']) {
  247.             $query['params'] = array();
  248.         }
  249.         if (!\is_array($query['params'])) {
  250.             $query['params'] = array($query['params']);
  251.         }
  252.         if (!\is_array($query['types'])) {
  253.             $query['types'] = [];
  254.         }
  255.         foreach ($query['params'] as $j => $param) {
  256.             $e null;
  257.             if (isset($query['types'][$j])) {
  258.                 // Transform the param according to the type
  259.                 $type $query['types'][$j];
  260.                 if (\is_string($type)) {
  261.                     $type Type::getType($type);
  262.                 }
  263.                 if ($type instanceof Type) {
  264.                     $query['types'][$j] = $type->getBindingType();
  265.                     try {
  266.                         $param $type->convertToDatabaseValue($param$this->registry->getConnection($connectionName)->getDatabasePlatform());
  267.                     } catch (\TypeError $e) {
  268.                     } catch (\Doctrine\DBAL\Types\ConversionException $e) {
  269.                     }
  270.                 }
  271.             }
  272.             [$query['params'][$j], $explainable$runnable] = $this->customSanitizeParam($param$e);
  273.             if (!$explainable) {
  274.                 $query['explainable'] = false;
  275.             }
  276.             if (!$runnable) {
  277.                 $query['runnable'] = false;
  278.             }
  279.         }
  280.         $query['params'] = $this->cloneVar($query['params']);
  281.         return $query;
  282.     }
  283.     /**
  284.      * @RENAMED_AND_MODIFIED
  285.      * 
  286.      * @openformCustomized
  287.      * - changed to use customSanitizeParam instead of sanitizeParam
  288.      * 
  289.      * Sanitizes a param
  290.      *
  291.      * The return value is an array with the sanitized value and a boolean
  292.      * indicating if the original value was kept (allowing to use the sanitized
  293.      * value to explain the query)
  294.      *
  295.      * @param mixed $var
  296.      *
  297.      * @return array
  298.      */
  299.     protected function customSanitizeParam($var, ?\Throwable $error)
  300.     {
  301.         if (\is_object($var)) {
  302.             return [$o = new ObjectParameter($var$error), false$o->isStringable() && !$error];
  303.         }
  304.         if ($error) {
  305.             return ['⚠ '.$error->getMessage(), falsefalse];
  306.         }
  307.         if (\is_array($var)) {
  308.             $a = array();
  309.             $explainable $runnable true;
  310.             foreach ($var as $k => $v) {
  311.                 [$value$e$r] = $this->customSanitizeParam($vnull);
  312.                 $explainable $explainable && $e;
  313.                 $runnable $runnable && $r;
  314.                 $a[$k] = $value;
  315.             }
  316.     
  317.             return [$a$explainable$runnable];    
  318.         }
  319.         if (\is_resource($var)) {
  320.             return [sprintf('/* Resource(%s) */'get_resource_type($var)), falsefalse];
  321.         }
  322.         return [$vartruetrue];
  323.     }
  324. }