This commit is contained in:
Xes
2025-08-14 22:41:49 +02:00
parent 2de81ccc46
commit 8ce45119b6
39774 changed files with 4309466 additions and 0 deletions

View File

@@ -0,0 +1,248 @@
<?php
namespace Gedmo\Tool\Logging\DBAL;
use Doctrine\DBAL\Logging\SQLLogger;
use Doctrine\DBAL\Types\Type;
use Doctrine\DBAL\Platforms\AbstractPlatform;
/**
* @author Gediminas Morkevicius <gediminas.morkevicius@gmail.com>
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
*/
class QueryAnalyzer implements SQLLogger
{
/**
* Used database platform
*
* @var AbstractPlatform
*/
protected $platform;
/**
* Start time of currently executed query
*
* @var integer
*/
private $queryStartTime = null;
/**
* Total execution time of all queries
*
* @var integer
*/
private $totalExecutionTime = 0;
/**
* List of queries executed
*
* @var array
*/
private $queries = array();
/**
* Query execution times indexed
* in same order as queries
*
* @var array
*/
private $queryExecutionTimes = array();
/**
* Initialize log listener with database
* platform, which is needed for parameter
* conversion
*
* @param AbstractPlatform $platform
*/
public function __construct(AbstractPlatform $platform)
{
$this->platform = $platform;
}
/**
* {@inheritdoc}
*/
public function startQuery($sql, array $params = null, array $types = null)
{
$this->queryStartTime = microtime(true);
$this->queries[] = $this->generateSql($sql, $params, $types);
}
/**
* {@inheritdoc}
*/
public function stopQuery()
{
$ms = round(microtime(true) - $this->queryStartTime, 4) * 1000;
$this->queryExecutionTimes[] = $ms;
$this->totalExecutionTime += $ms;
}
/**
* Clean all collected data
*
* @return QueryAnalyzer
*/
public function cleanUp()
{
$this->queries = array();
$this->queryExecutionTimes = array();
$this->totalExecutionTime = 0;
return $this;
}
/**
* Dump the statistics of executed queries
*
* @param boolean $dumpOnlySql
*
* @return string
*/
public function getOutput($dumpOnlySql = false)
{
$output = '';
if (!$dumpOnlySql) {
$output .= 'Platform: '.$this->platform->getName().PHP_EOL;
$output .= 'Executed queries: '.count($this->queries).', total time: '.$this->totalExecutionTime.' ms'.PHP_EOL;
}
foreach ($this->queries as $index => $sql) {
if (!$dumpOnlySql) {
$output .= 'Query('.($index+1).') - '.$this->queryExecutionTimes[$index].' ms'.PHP_EOL;
}
$output .= $sql.';'.PHP_EOL;
}
$output .= PHP_EOL;
return $output;
}
/**
* Index of the slowest query executed
*
* @return integer
*/
public function getSlowestQueryIndex()
{
$index = 0;
$slowest = 0;
foreach ($this->queryExecutionTimes as $i => $time) {
if ($time > $slowest) {
$slowest = $time;
$index = $i;
}
}
return $index;
}
/**
* Get total execution time of queries
*
* @return integer
*/
public function getTotalExecutionTime()
{
return $this->totalExecutionTime;
}
/**
* Get all queries
*
* @return array
*/
public function getExecutedQueries()
{
return $this->queries;
}
/**
* Get number of executed queries
*
* @return integer
*/
public function getNumExecutedQueries()
{
return count($this->queries);
}
/**
* Get all query execution times
*
* @return array
*/
public function getExecutionTimes()
{
return $this->queryExecutionTimes;
}
/**
* Create the SQL with mapped parameters
*
* @param string $sql
* @param null|array $params
* @param null|array $types
*
* @return string
*/
private function generateSql($sql, $params, $types)
{
if (null === $params || !count($params)) {
return $sql;
}
$converted = $this->getConvertedParams($params, $types);
if (is_int(key($params))) {
$index = key($converted);
$sql = preg_replace_callback('@\?@sm', function ($match) use (&$index, $converted) {
return $converted[$index++];
}, $sql);
} else {
foreach ($converted as $key => $value) {
$sql = str_replace(':'.$key, $value, $sql);
}
}
return $sql;
}
/**
* Get the converted parameter list
*
* @param array $params
* @param array $types
*
* @return array
*/
private function getConvertedParams($params, $types)
{
$result = array();
foreach ($params as $position => $value) {
if (isset($types[$position])) {
$type = $types[$position];
if (is_string($type)) {
$type = Type::getType($type);
}
if ($type instanceof Type) {
$value = $type->convertToDatabaseValue($value, $this->platform);
}
} else {
// Remove `$value instanceof \DateTime` check when PHP version is bumped to >=5.5
if (is_object($value) && ($value instanceof \DateTime || $value instanceof \DateTimeInterface)) {
$value = $value->format($this->platform->getDateTimeFormatString());
} elseif (!is_null($value)) {
$type = Type::getType(gettype($value));
$value = $type->convertToDatabaseValue($value, $this->platform);
}
}
if (is_string($value)) {
$value = "'{$value}'";
} elseif (is_null($value)) {
$value = 'NULL';
}
$result[$position] = $value;
}
return $result;
}
}

View File

@@ -0,0 +1,100 @@
<?php
namespace Gedmo\Tool\Wrapper;
use Doctrine\ODM\MongoDB\DocumentManager;
use Doctrine\Common\Persistence\ObjectManager;
use Doctrine\ORM\EntityManagerInterface;
use Gedmo\Tool\WrapperInterface;
use Gedmo\Exception\UnsupportedObjectManagerException;
/**
* Wraps entity or proxy for more convenient
* manipulation
*
* @author Gediminas Morkevicius <gediminas.morkevicius@gmail.com>
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
*/
abstract class AbstractWrapper implements WrapperInterface
{
/**
* Object metadata
*
* @var object
*/
protected $meta;
/**
* Wrapped object
*
* @var object
*/
protected $object;
/**
* Object manager instance
*
* @var \Doctrine\Common\Persistence\ObjectManager
*/
protected $om;
/**
* List of wrapped object references
*
* @var array
*/
private static $wrappedObjectReferences;
/**
* Wrap object factory method
*
* @param object $object
* @param ObjectManager $om
*
* @throws \Gedmo\Exception\UnsupportedObjectManagerException
*
* @return \Gedmo\Tool\WrapperInterface
*/
public static function wrap($object, ObjectManager $om)
{
if ($om instanceof EntityManagerInterface) {
return new EntityWrapper($object, $om);
} elseif ($om instanceof DocumentManager) {
return new MongoDocumentWrapper($object, $om);
}
throw new UnsupportedObjectManagerException('Given object manager is not managed by wrapper');
}
public static function clear()
{
self::$wrappedObjectReferences = array();
}
/**
* {@inheritDoc}
*/
public function getObject()
{
return $this->object;
}
/**
* {@inheritDoc}
*/
public function getMetadata()
{
return $this->meta;
}
/**
* {@inheritDoc}
*/
public function populate(array $data)
{
foreach ($data as $field => $value) {
$this->setPropertyValue($field, $value);
}
return $this;
}
}

View File

@@ -0,0 +1,138 @@
<?php
namespace Gedmo\Tool\Wrapper;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\Proxy\Proxy;
/**
* Wraps entity or proxy for more convenient
* manipulation
*
* @author Gediminas Morkevicius <gediminas.morkevicius@gmail.com>
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
*/
class EntityWrapper extends AbstractWrapper
{
/**
* Entity identifier
*
* @var array
*/
private $identifier;
/**
* True if entity or proxy is loaded
*
* @var boolean
*/
private $initialized = false;
/**
* Wrap entity
*
* @param object $entity
* @param \Doctrine\ORM\EntityManagerInterface $em
*/
public function __construct($entity, EntityManagerInterface $em)
{
$this->om = $em;
$this->object = $entity;
$this->meta = $em->getClassMetadata(get_class($this->object));
}
/**
* {@inheritDoc}
*/
public function getPropertyValue($property)
{
$this->initialize();
return $this->meta->getReflectionProperty($property)->getValue($this->object);
}
/**
* {@inheritDoc}
*/
public function setPropertyValue($property, $value)
{
$this->initialize();
$this->meta->getReflectionProperty($property)->setValue($this->object, $value);
return $this;
}
/**
* {@inheritDoc}
*/
public function hasValidIdentifier()
{
return (null !== $this->getIdentifier());
}
/**
* {@inheritDoc}
*/
public function getRootObjectName()
{
return $this->meta->rootEntityName;
}
/**
* {@inheritDoc}
*/
public function getIdentifier($single = true)
{
if (null === $this->identifier) {
if ($this->object instanceof Proxy) {
$uow = $this->om->getUnitOfWork();
if ($uow->isInIdentityMap($this->object)) {
$this->identifier = $uow->getEntityIdentifier($this->object);
} else {
$this->initialize();
}
}
if (null === $this->identifier) {
$this->identifier = array();
$incomplete = false;
foreach ($this->meta->identifier as $name) {
$this->identifier[$name] = $this->getPropertyValue($name);
if (null === $this->identifier[$name]) {
$incomplete = true;
}
}
if ($incomplete) {
$this->identifier = null;
}
}
}
if ($single && is_array($this->identifier)) {
return reset($this->identifier);
}
return $this->identifier;
}
/**
* Initialize the entity if it is proxy
* required when is detached or not initialized
*/
protected function initialize()
{
if (!$this->initialized) {
if ($this->object instanceof Proxy) {
if (!$this->object->__isInitialized__) {
$this->object->__load();
}
}
}
}
/**
* {@inheritDoc}
*/
public function isEmbeddedAssociation($field)
{
return false;
}
}

View File

@@ -0,0 +1,137 @@
<?php
namespace Gedmo\Tool\Wrapper;
use Doctrine\ODM\MongoDB\DocumentManager;
use Doctrine\ODM\MongoDB\Proxy\Proxy;
/**
* Wraps document or proxy for more convenient
* manipulation
*
* @author Gediminas Morkevicius <gediminas.morkevicius@gmail.com>
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
*/
class MongoDocumentWrapper extends AbstractWrapper
{
/**
* Document identifier
*
* @var mixed
*/
private $identifier;
/**
* True if document or proxy is loaded
*
* @var boolean
*/
private $initialized = false;
/**
* Wrap document
*
* @param object $document
* @param \Doctrine\ODM\MongoDB\DocumentManager $dm
*/
public function __construct($document, DocumentManager $dm)
{
$this->om = $dm;
$this->object = $document;
$this->meta = $dm->getClassMetadata(get_class($this->object));
}
/**
* {@inheritDoc}
*/
public function getPropertyValue($property)
{
$this->initialize();
return $this->meta->getReflectionProperty($property)->getValue($this->object);
}
/**
* {@inheritDoc}
*/
public function getRootObjectName()
{
return $this->meta->rootDocumentName;
}
/**
* {@inheritDoc}
*/
public function setPropertyValue($property, $value)
{
$this->initialize();
$this->meta->getReflectionProperty($property)->setValue($this->object, $value);
return $this;
}
/**
* {@inheritDoc}
*/
public function hasValidIdentifier()
{
return (bool) $this->getIdentifier();
}
/**
* {@inheritDoc}
*/
public function getIdentifier($single = true)
{
if (!$this->identifier) {
if ($this->object instanceof Proxy) {
$uow = $this->om->getUnitOfWork();
if ($uow->isInIdentityMap($this->object)) {
$this->identifier = (string) $uow->getDocumentIdentifier($this->object);
} else {
$this->initialize();
}
}
if (!$this->identifier) {
$this->identifier = (string) $this->getPropertyValue($this->meta->identifier);
}
}
return $this->identifier;
}
/**
* Initialize the document if it is proxy
* required when is detached or not initialized
*/
protected function initialize()
{
if (!$this->initialized) {
if ($this->object instanceof Proxy) {
$uow = $this->om->getUnitOfWork();
if (!$this->object->__isInitialized__) {
$persister = $uow->getDocumentPersister($this->meta->name);
$identifier = null;
if ($uow->isInIdentityMap($this->object)) {
$identifier = $this->getIdentifier();
} else {
// this may not happen but in case
$reflProperty = new \ReflectionProperty($this->object, 'identifier');
$reflProperty->setAccessible(true);
$identifier = $reflProperty->getValue($this->object);
}
$this->object->__isInitialized__ = true;
$persister->load($identifier, $this->object);
}
}
}
}
/**
* {@inheritDoc}
*/
public function isEmbeddedAssociation($field)
{
return $this->getMetadata()->isSingleValuedEmbed($field);
}
}

View File

@@ -0,0 +1,87 @@
<?php
namespace Gedmo\Tool;
/**
* Object wrapper interface
*
* @author Gediminas Morkevicius <gediminas.morkevicius@gmail.com>
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
*/
interface WrapperInterface
{
/**
* Get currently wrapped object
* etc.: entity, document
*
* @return object
*/
public function getObject();
/**
* Extract property value from object
*
* @param string $property
*
* @return mixed
*/
public function getPropertyValue($property);
/**
* Set the property
*
* @param string $property
* @param mixed $value
*
* @return \Gedmo\Tool\WrapperInterface
*/
public function setPropertyValue($property, $value);
/**
* Populates the object with given property values
*
* @param array $data
*
* @return static
*/
public function populate(array $data);
/**
* Checks if identifier is valid
*
* @return boolean
*/
public function hasValidIdentifier();
/**
* Get metadata
*
* @return object
*/
public function getMetadata();
/**
* Get the object identifier, single or composite
*
* @param boolean $single
*
* @return array|mixed
*/
public function getIdentifier($single = true);
/**
* Get root object class name
*
* @return string
*/
public function getRootObjectName();
/**
* Chechks if association is embedded
*
* @param string $field
*
* @return bool
*/
public function isEmbeddedAssociation($field);
}