Actualización

This commit is contained in:
Xes
2025-04-10 12:24:57 +02:00
parent 8969cc929d
commit 45420b6f0d
39760 changed files with 4303286 additions and 0 deletions

View File

@@ -0,0 +1,77 @@
<?php
namespace Gedmo\ReferenceIntegrity\Mapping\Driver;
use Gedmo\Mapping\Driver\AbstractAnnotationDriver;
use Gedmo\Exception\InvalidMappingException;
use Gedmo\ReferenceIntegrity\Mapping\Validator;
/**
* This is an annotation mapping driver for ReferenceIntegrity
* behavioral extension. Used for extraction of extended
* metadata from Annotations specifically for ReferenceIntegrity
* extension.
*
* @author Evert Harmeling <evert.harmeling@freshheads.com>
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
*/
class Annotation extends AbstractAnnotationDriver
{
/**
* Annotation to identify the fields which manages the reference integrity
*/
const REFERENCE_INTEGRITY = 'Gedmo\\Mapping\\Annotation\\ReferenceIntegrity';
/**
* ReferenceIntegrityAction extension annotation
*/
const ACTION = 'Gedmo\\Mapping\\Annotation\\ReferenceIntegrityAction';
/**
* {@inheritDoc}
*/
public function readExtendedMetadata($meta, array &$config)
{
$validator = new Validator();
$reflClass = $this->getMetaReflectionClass($meta);
foreach ($reflClass->getProperties() as $reflProperty) {
if ($referenceIntegrity = $this->reader->getPropertyAnnotation($reflProperty, self::REFERENCE_INTEGRITY)) {
$property = $reflProperty->getName();
if (!$meta->hasField($property)) {
throw new InvalidMappingException(
sprintf(
"Unable to find reference integrity [%s] as mapped property in entity - %s",
$property,
$meta->name
)
);
}
$fieldMapping = $meta->getFieldMapping($property);
if (!isset($fieldMapping['mappedBy'])) {
throw new InvalidMappingException(
sprintf(
"'mappedBy' should be set on '%s' in '%s'",
$property,
$meta->name
)
);
}
if (!in_array($referenceIntegrity->value, $validator->getIntegrityActions())) {
throw new InvalidMappingException(
sprintf(
"Field - [%s] does not have a valid integrity option, [%s] in class - %s",
$property,
implode($validator->getIntegrityActions(), ', '),
$meta->name
)
);
}
$config['referenceIntegrity'][$property] = $referenceIntegrity->value;
}
}
}
}

View File

@@ -0,0 +1,83 @@
<?php
namespace Gedmo\ReferenceIntegrity\Mapping\Driver;
use Gedmo\Exception\InvalidMappingException;
use Gedmo\Mapping\Driver\File;
use Gedmo\Mapping\Driver;
use Gedmo\ReferenceIntegrity\Mapping\Validator;
/**
* This is a yaml mapping driver for ReferenceIntegrity
* extension. Used for extraction of extended
* metadata from yaml specifically for ReferenceIntegrity
* extension.
*
* @author Evert Harmeling <evert.harmeling@freshheads.com>
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
*/
class Yaml extends File implements Driver
{
/**
* File extension
* @var string
*/
protected $_extension = '.dcm.yml';
/**
* {@inheritDoc}
*/
public function readExtendedMetadata($meta, array &$config)
{
$mapping = $this->_getMapping($meta->name);
$validator = new Validator();
if (isset($mapping['fields'])) {
foreach ($mapping['fields'] as $property => $fieldMapping) {
if (isset($fieldMapping['gedmo']['referenceIntegrity'])) {
if (!$meta->hasField($property)) {
throw new InvalidMappingException(
sprintf(
"Unable to find reference integrity [%s] as mapped property in entity - %s",
$property,
$meta->name
)
);
}
if (empty($mapping['fields'][$property]['mappedBy'])) {
throw new InvalidMappingException(
sprintf(
"'mappedBy' should be set on '%s' in '%s'",
$property,
$meta->name
)
);
}
if (!in_array($fieldMapping['gedmo']['referenceIntegrity'], $validator->getIntegrityActions())) {
throw new InvalidMappingException(
sprintf(
"Field - [%s] does not have a valid integrity option, [%s] in class - %s",
$property,
implode($validator->getIntegrityActions(), ', '),
$meta->name
)
);
}
$config['referenceIntegrity'][$property][$mapping['fields'][$property]['mappedBy']] =
$fieldMapping['gedmo']['referenceIntegrity'];
}
}
}
}
/**
* {@inheritDoc}
*/
protected function _loadMappingFile($file)
{
return \Symfony\Component\Yaml\Yaml::parse(file_get_contents($file));
}
}

View File

@@ -0,0 +1,38 @@
<?php
namespace Gedmo\ReferenceIntegrity\Mapping;
/**
* This class is used to validate mapping information
*
* @author Evert Harmeling <evert.harmeling@freshheads.com>
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
*/
class Validator
{
const NULLIFY = 'nullify';
const PULL = 'pull';
const RESTRICT = 'restrict';
/**
* List of actions which are valid as integrity check
*
* @var array
*/
private $integrityActions = array(
self::NULLIFY,
self::PULL,
self::RESTRICT,
);
/**
* Returns a list of available integrity actions
*
* @return array
*/
public function getIntegrityActions()
{
return $this->integrityActions;
}
}

View File

@@ -0,0 +1,47 @@
<?php
namespace Gedmo\ReferenceIntegrity;
/**
* This interface is not necessary but can be implemented for
* Entities which in some cases needs to be identified te have
* ReferenceIntegrity checks
*
* @author Evert Harmeling <evert.harmeling@freshheads.com>
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
*/
interface ReferenceIntegrity
{
/**
* ReferenceIntegrity expects certain settings to be required
* in combination with an association
*/
/**
* example
* @ODM\ReferenceOne(targetDocument="Article", nullable="true", mappedBy="type")
* @Gedmo\ReferenceIntegrity("nullify")
* @var Article
*/
/**
* example
* @ODM\ReferenceOne(targetDocument="Article", nullable="true", mappedBy="type")
* @Gedmo\ReferenceIntegrity("restrict")
* @var Article
*/
/**
* example
* @ODM\ReferenceMany(targetDocument="Article", nullable="true", mappedBy="type")
* @Gedmo\ReferenceIntegrity("nullify")
* @var Doctrine\Common\Collections\ArrayCollection
*/
/**
* example
* @ODM\ReferenceMany(targetDocument="Article", nullable="true", mappedBy="type")
* @Gedmo\ReferenceIntegrity("restrict")
* @var Doctrine\Common\Collections\ArrayCollection
*/
}

View File

@@ -0,0 +1,181 @@
<?php
namespace Gedmo\ReferenceIntegrity;
use Doctrine\Common\EventArgs;
use Gedmo\Exception\InvalidMappingException;
use Gedmo\Exception\ReferenceIntegrityStrictException;
use Gedmo\Mapping\MappedEventSubscriber;
use Gedmo\ReferenceIntegrity\Mapping\Validator;
/**
* The ReferenceIntegrity listener handles the reference integrity on related documents
*
* @author Evert Harmeling <evert.harmeling@freshheads.com>
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
*/
class ReferenceIntegrityListener extends MappedEventSubscriber
{
/**
* {@inheritDoc}
*/
public function getSubscribedEvents()
{
return array(
'loadClassMetadata',
'preRemove',
);
}
/**
* Maps additional metadata for the Document
*
* @param EventArgs $eventArgs
* @return void
*/
public function loadClassMetadata(EventArgs $eventArgs)
{
$ea = $this->getEventAdapter($eventArgs);
$this->loadMetadataForObjectClass($ea->getObjectManager(), $eventArgs->getClassMetadata());
}
/**
* Looks for referenced objects being removed
* to nullify the relation or throw an exception
*
* @param EventArgs $args
* @return void
*/
public function preRemove(EventArgs $args)
{
$ea = $this->getEventAdapter($args);
$om = $ea->getObjectManager();
$object = $ea->getObject();
$class = get_class($object);
$meta = $om->getClassMetadata($class);
if ($config = $this->getConfiguration($om, $meta->name)) {
foreach ($config['referenceIntegrity'] as $property => $action) {
$reflProp = $meta->getReflectionProperty($property);
$refDoc = $reflProp->getValue($object);
$fieldMapping = $meta->getFieldMapping($property);
switch ($action) {
case Validator::NULLIFY:
if (!isset($fieldMapping['mappedBy'])) {
throw new InvalidMappingException(
sprintf(
"Reference '%s' on '%s' should have 'mappedBy' option defined",
$property,
$meta->name
)
);
}
$subMeta = $om->getClassMetadata($fieldMapping['targetDocument']);
if (!$subMeta->hasField($fieldMapping['mappedBy'])) {
throw new InvalidMappingException(
sprintf(
"Unable to find reference integrity [%s] as mapped property in entity - %s",
$fieldMapping['mappedBy'],
$fieldMapping['targetDocument']
)
);
}
$refReflProp = $subMeta->getReflectionProperty($fieldMapping['mappedBy']);
if ($meta->isCollectionValuedReference($property)) {
foreach ($refDoc as $refObj) {
$refReflProp->setValue($refObj, null);
$om->persist($refObj);
}
} else {
$refReflProp->setValue($refDoc, null);
$om->persist($refDoc);
}
break;
case Validator::PULL:
if (!isset($fieldMapping['mappedBy'])) {
throw new InvalidMappingException(
sprintf(
"Reference '%s' on '%s' should have 'mappedBy' option defined",
$property,
$meta->name
)
);
}
$subMeta = $om->getClassMetadata($fieldMapping['targetDocument']);
if (!$subMeta->hasField($fieldMapping['mappedBy'])) {
throw new InvalidMappingException(
sprintf(
"Unable to find reference integrity [%s] as mapped property in entity - %s",
$fieldMapping['mappedBy'],
$fieldMapping['targetDocument']
)
);
}
if (!$subMeta->isCollectionValuedReference($fieldMapping['mappedBy'])) {
throw new InvalidMappingException(
sprintf(
"Reference integrity [%s] mapped property in entity - %s should be a Reference Many",
$fieldMapping['mappedBy'],
$fieldMapping['targetDocument']
)
);
}
$refReflProp = $subMeta->getReflectionProperty($fieldMapping['mappedBy']);
if ($meta->isCollectionValuedReference($property)) {
foreach ($refDoc as $refObj) {
$collection = $refReflProp->getValue($refObj);
$collection->removeElement($object);
$refReflProp->setValue($refObj, $collection);
$om->persist($refObj);
}
} else if (is_object($refDoc)) {
$collection = $refReflProp->getValue($refDoc);
$collection->removeElement($object);
$refReflProp->setValue($refDoc, $collection);
$om->persist($refDoc);
}
break;
case Validator::RESTRICT:
if ($meta->isCollectionValuedReference($property) && $refDoc->count() > 0) {
throw new ReferenceIntegrityStrictException(
sprintf(
"The reference integrity for the '%s' collection is restricted",
$fieldMapping['targetDocument']
)
);
}
if ($meta->isSingleValuedReference($property) && !is_null($refDoc)) {
throw new ReferenceIntegrityStrictException(
sprintf(
"The reference integrity for the '%s' document is restricted",
$fieldMapping['targetDocument']
)
);
}
break;
}
}
}
}
/**
* {@inheritDoc}
*/
protected function getNamespace()
{
return __NAMESPACE__;
}
}