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,173 @@
<?php
namespace Gedmo\Sluggable\Mapping\Driver;
use Gedmo\Mapping\Annotation\SlugHandler;
use Gedmo\Mapping\Annotation\SlugHandlerOption;
use Gedmo\Mapping\Driver\AbstractAnnotationDriver;
use Gedmo\Exception\InvalidMappingException;
/**
* This is an annotation mapping driver for Sluggable
* behavioral extension. Used for extraction of extended
* metadata from Annotations specifically for Sluggable
* extension.
*
* @author Gediminas Morkevicius <gediminas.morkevicius@gmail.com>
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
*/
class Annotation extends AbstractAnnotationDriver
{
/**
* Annotation to identify field as one which holds the slug
* together with slug options
*/
const SLUG = 'Gedmo\\Mapping\\Annotation\\Slug';
/**
* SlugHandler extension annotation
*/
const HANDLER = 'Gedmo\\Mapping\\Annotation\\SlugHandler';
/**
* SlugHandler option annotation
*/
const HANDLER_OPTION = 'Gedmo\\Mapping\\Annotation\\SlugHandlerOption';
/**
* List of types which are valid for slug and sluggable fields
*
* @var array
*/
protected $validTypes = array(
'string',
'text',
'integer',
'int',
'datetime',
'citext',
);
/**
* {@inheritDoc}
*/
public function readExtendedMetadata($meta, array &$config)
{
$class = $this->getMetaReflectionClass($meta);
// property annotations
foreach ($class->getProperties() as $property) {
if ($meta->isMappedSuperclass && !$property->isPrivate() ||
$meta->isInheritedField($property->name) ||
isset($meta->associationMappings[$property->name]['inherited'])
) {
continue;
}
$config = $this->retrieveSlug($meta, $config, $property, '');
}
// Embedded entity
if (property_exists($meta, 'embeddedClasses') && $meta->embeddedClasses) {
foreach ($meta->embeddedClasses as $propertyName => $embeddedClassInfo) {
$embeddedClass = new \ReflectionClass($embeddedClassInfo['class']);
foreach ($embeddedClass->getProperties() as $embeddedProperty) {
$config = $this->retrieveSlug($meta, $config, $embeddedProperty, $propertyName);
}
}
}
return $config;
}
/**
* @param $meta
* @param array $config
* @param $property
* @param $fieldNamePrefix
* @return array
*/
private function retrieveSlug($meta, array &$config, $property, $fieldNamePrefix)
{
$fieldName = $fieldNamePrefix ? ($fieldNamePrefix . '.' . $property->getName()) : $property->getName();
// slug property
if ($slug = $this->reader->getPropertyAnnotation($property, self::SLUG)) {
if (!$meta->hasField($fieldName)) {
throw new InvalidMappingException("Unable to find slug [{$fieldName}] as mapped property in entity - {$meta->name}");
}
if (!$this->isValidField($meta, $fieldName)) {
throw new InvalidMappingException("Cannot use field - [{$fieldName}] for slug storage, type is not valid and must be 'string' or 'text' in class - {$meta->name}");
}
// process slug handlers
$handlers = array();
if (is_array($slug->handlers) && $slug->handlers) {
foreach ($slug->handlers as $handler) {
if (!$handler instanceof SlugHandler) {
throw new InvalidMappingException("SlugHandler: {$handler} should be instance of SlugHandler annotation in entity - {$meta->name}");
}
if (!strlen($handler->class)) {
throw new InvalidMappingException("SlugHandler class: {$handler->class} should be a valid class name in entity - {$meta->name}");
}
$class = $handler->class;
$handlers[$class] = array();
foreach ((array)$handler->options as $option) {
if (!$option instanceof SlugHandlerOption) {
throw new InvalidMappingException("SlugHandlerOption: {$option} should be instance of SlugHandlerOption annotation in entity - {$meta->name}");
}
if (!strlen($option->name)) {
throw new InvalidMappingException("SlugHandlerOption name: {$option->name} should be valid name in entity - {$meta->name}");
}
$handlers[$class][$option->name] = $option->value;
}
$class::validate($handlers[$class], $meta);
}
}
// process slug fields
if (empty($slug->fields) || !is_array($slug->fields)) {
throw new InvalidMappingException("Slug must contain at least one field for slug generation in class - {$meta->name}");
}
foreach ($slug->fields as $slugField) {
$slugFieldWithPrefix = $fieldNamePrefix ? ($fieldNamePrefix . '.' . $slugField) : $slugField;
if (!$meta->hasField($slugFieldWithPrefix)) {
throw new InvalidMappingException("Unable to find slug [{$slugFieldWithPrefix}] as mapped property in entity - {$meta->name}");
}
if (!$this->isValidField($meta, $slugFieldWithPrefix)) {
throw new InvalidMappingException("Cannot use field - [{$slugFieldWithPrefix}] for slug storage, type is not valid and must be 'string' or 'text' in class - {$meta->name}");
}
}
if (!is_bool($slug->updatable)) {
throw new InvalidMappingException("Slug annotation [updatable], type is not valid and must be 'boolean' in class - {$meta->name}");
}
if (!is_bool($slug->unique)) {
throw new InvalidMappingException("Slug annotation [unique], type is not valid and must be 'boolean' in class - {$meta->name}");
}
if (!empty($meta->identifier) && $meta->isIdentifier($fieldName) && !(bool)$slug->unique) {
throw new InvalidMappingException("Identifier field - [{$fieldName}] slug must be unique in order to maintain primary key in class - {$meta->name}");
}
if ($slug->unique === false && $slug->unique_base) {
throw new InvalidMappingException("Slug annotation [unique_base] can not be set if unique is unset or 'false'");
}
if ($slug->unique_base && !$meta->hasField($slug->unique_base) && !$meta->hasAssociation($slug->unique_base)) {
throw new InvalidMappingException("Unable to find [{$slug->unique_base}] as mapped property in entity - {$meta->name}");
}
$sluggableFields = array();
foreach ($slug->fields as $field) {
$sluggableFields[] = $fieldNamePrefix ? ($fieldNamePrefix . '.' . $field) : $field;
}
// set all options
$config['slugs'][$fieldName] = array(
'fields' => $sluggableFields,
'slug' => $fieldName,
'style' => $slug->style,
'dateFormat' => $slug->dateFormat,
'updatable' => $slug->updatable,
'unique' => $slug->unique,
'unique_base' => $slug->unique_base,
'separator' => $slug->separator,
'prefix' => $slug->prefix,
'suffix' => $slug->suffix,
'handlers' => $handlers,
);
}
return $config;
}
}

View File

@@ -0,0 +1,147 @@
<?php
namespace Gedmo\Sluggable\Mapping\Driver;
use Gedmo\Mapping\Driver\Xml as BaseXml;
use Gedmo\Exception\InvalidMappingException;
/**
* This is a xml mapping driver for Sluggable
* behavioral extension. Used for extraction of extended
* metadata from xml specifically for Sluggable
* extension.
*
* @author Gediminas Morkevicius <gediminas.morkevicius@gmail.com>
* @author Miha Vrhovnik <miha.vrhovnik@gmail.com>
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
*/
class Xml extends BaseXml
{
/**
* List of types which are valid for slug and sluggable fields
*
* @var array
*/
private $validTypes = array(
'string',
'text',
'integer',
'int',
'datetime',
'citext',
);
/**
* {@inheritDoc}
*/
public function readExtendedMetadata($meta, array &$config)
{
/**
* @var \SimpleXmlElement $xml
*/
$xml = $this->_getMapping($meta->name);
if (isset($xml->field)) {
foreach ($xml->field as $mapping) {
$field = $this->_getAttribute($mapping, 'name');
$this->buildFieldConfiguration($meta, $field, $mapping, $config);
}
}
if (isset($xml->{'attribute-overrides'})) {
foreach ($xml->{'attribute-overrides'}->{'attribute-override'} as $mapping) {
$field = $this->_getAttribute($mapping, 'name');
$this->buildFieldConfiguration($meta, $field, $mapping->field, $config);
}
}
}
private function buildFieldConfiguration($meta, $field, \SimpleXMLElement $mapping, array &$config)
{
/**
* @var \SimpleXmlElement $mapping
*/
$mapping = $mapping->children(self::GEDMO_NAMESPACE_URI);
if (isset($mapping->slug)) {
/**
* @var \SimpleXmlElement $slug
*/
$slug = $mapping->slug;
if (!$this->isValidField($meta, $field)) {
throw new InvalidMappingException("Cannot use field - [{$field}] for slug storage, type is not valid and must be 'string' in class - {$meta->name}");
}
$fields = array_map('trim', explode(',', (string) $this->_getAttribute($slug, 'fields')));
foreach ($fields as $slugField) {
if (!$meta->hasField($slugField)) {
throw new InvalidMappingException("Unable to find slug [{$slugField}] as mapped property in entity - {$meta->name}");
}
if (!$this->isValidField($meta, $slugField)) {
throw new InvalidMappingException("Cannot use field - [{$slugField}] for slug storage, type is not valid and must be 'string' or 'text' in class - {$meta->name}");
}
}
$handlers = array();
if (isset($slug->handler)) {
foreach ($slug->handler as $handler) {
$class = (string) $this->_getAttribute($handler, 'class');
$handlers[$class] = array();
foreach ($handler->{'handler-option'} as $option) {
$handlers[$class][(string) $this->_getAttribute($option, 'name')]
= (string) $this->_getAttribute($option, 'value')
;
}
$class::validate($handlers[$class], $meta);
}
}
// set all options
$config['slugs'][$field] = array(
'fields' => $fields,
'slug' => $field,
'style' => $this->_isAttributeSet($slug, 'style') ?
$this->_getAttribute($slug, 'style') : 'default',
'updatable' => $this->_isAttributeSet($slug, 'updatable') ?
$this->_getBooleanAttribute($slug, 'updatable') : true,
'dateFormat' => $this->_isAttributeSet($slug, 'dateFormat') ?
$this->_getAttribute($slug, 'dateFormat') : 'Y-m-d-H:i',
'unique' => $this->_isAttributeSet($slug, 'unique') ?
$this->_getBooleanAttribute($slug, 'unique') : true,
'unique_base' => $this->_isAttributeSet($slug, 'unique-base') ?
$this->_getAttribute($slug, 'unique-base') : null,
'separator' => $this->_isAttributeSet($slug, 'separator') ?
$this->_getAttribute($slug, 'separator') : '-',
'prefix' => $this->_isAttributeSet($slug, 'prefix') ?
$this->_getAttribute($slug, 'prefix') : '',
'suffix' => $this->_isAttributeSet($slug, 'suffix') ?
$this->_getAttribute($slug, 'suffix') : '',
'handlers' => $handlers,
);
if (!$meta->isMappedSuperclass && $meta->isIdentifier($field) && !$config['slugs'][$field]['unique']) {
throw new InvalidMappingException("Identifier field - [{$field}] slug must be unique in order to maintain primary key in class - {$meta->name}");
}
$ubase = $config['slugs'][$field]['unique_base'];
if ($config['slugs'][$field]['unique'] === false && $ubase) {
throw new InvalidMappingException("Slug annotation [unique_base] can not be set if unique is unset or 'false'");
}
if ($ubase && !$meta->hasField($ubase) && !$meta->hasAssociation($ubase)) {
throw new InvalidMappingException("Unable to find [{$ubase}] as mapped property in entity - {$meta->name}");
}
}
}
/**
* Checks if $field type is valid as Sluggable field
*
* @param object $meta
* @param string $field
*
* @return boolean
*/
protected function isValidField($meta, $field)
{
$mapping = $meta->getFieldMapping($field);
return $mapping && in_array($mapping['type'], $this->validTypes);
}
}

View File

@@ -0,0 +1,155 @@
<?php
namespace Gedmo\Sluggable\Mapping\Driver;
use Gedmo\Mapping\Driver\File;
use Gedmo\Mapping\Driver;
use Gedmo\Exception\InvalidMappingException;
/**
* This is a yaml mapping driver for Sluggable
* behavioral extension. Used for extraction of extended
* metadata from yaml specifically for Sluggable
* extension.
*
* @author Gediminas Morkevicius <gediminas.morkevicius@gmail.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';
/**
* List of types which are valid for slug and sluggable fields
*
* @var array
*/
private $validTypes = array(
'string',
'text',
'integer',
'int',
'datetime',
'citext',
);
/**
* {@inheritDoc}
*/
public function readExtendedMetadata($meta, array &$config)
{
$mapping = $this->_getMapping($meta->name);
if (isset($mapping['fields'])) {
foreach ($mapping['fields'] as $field => $fieldMapping) {
$this->buildFieldConfiguration($field, $fieldMapping, $meta, $config);
}
}
if (isset($mapping['attributeOverride'])) {
foreach ($mapping['attributeOverride'] as $field => $overrideMapping) {
$this->buildFieldConfiguration($field, $overrideMapping, $meta, $config);
}
}
}
/**
* {@inheritDoc}
*/
protected function _loadMappingFile($file)
{
return \Symfony\Component\Yaml\Yaml::parse(file_get_contents($file));
}
/**
* Checks if $field type is valid as Sluggable field
*
* @param object $meta
* @param string $field
*
* @return boolean
*/
protected function isValidField($meta, $field)
{
$mapping = $meta->getFieldMapping($field);
return $mapping && in_array($mapping['type'], $this->validTypes);
}
private function buildFieldConfiguration($field, array $fieldMapping, $meta, array &$config)
{
if (isset($fieldMapping['gedmo'])) {
if (isset($fieldMapping['gedmo']['slug'])) {
$slug = $fieldMapping['gedmo']['slug'];
if (!$this->isValidField($meta, $field)) {
throw new InvalidMappingException("Cannot use field - [{$field}] for slug storage, type is not valid and must be 'string' or 'text' in class - {$meta->name}");
}
// process slug handlers
$handlers = array();
if (isset($slug['handlers'])) {
foreach ($slug['handlers'] as $handlerClass => $options) {
if (!strlen($handlerClass)) {
throw new InvalidMappingException("SlugHandler class: {$handlerClass} should be a valid class name in entity - {$meta->name}");
}
$handlers[$handlerClass] = $options;
$handlerClass::validate($handlers[$handlerClass], $meta);
}
}
// process slug fields
if (empty($slug['fields']) || !is_array($slug['fields'])) {
throw new InvalidMappingException("Slug must contain at least one field for slug generation in class - {$meta->name}");
}
foreach ($slug['fields'] as $slugField) {
if (!$meta->hasField($slugField)) {
throw new InvalidMappingException("Unable to find slug [{$slugField}] as mapped property in entity - {$meta->name}");
}
if (!$this->isValidField($meta, $slugField)) {
throw new InvalidMappingException("Cannot use field - [{$slugField}] for slug storage, type is not valid and must be 'string' or 'text' in class - {$meta->name}");
}
}
$config['slugs'][$field]['fields'] = $slug['fields'];
$config['slugs'][$field]['handlers'] = $handlers;
$config['slugs'][$field]['slug'] = $field;
$config['slugs'][$field]['style'] = isset($slug['style']) ?
(string) $slug['style'] : 'default';
$config['slugs'][$field]['dateFormat'] = isset($slug['dateFormat']) ?
(string) $slug['dateFormat'] : 'Y-m-d-H:i';
$config['slugs'][$field]['updatable'] = isset($slug['updatable']) ?
(bool) $slug['updatable'] : true;
$config['slugs'][$field]['unique'] = isset($slug['unique']) ?
(bool) $slug['unique'] : true;
$config['slugs'][$field]['unique_base'] = isset($slug['unique_base']) ?
$slug['unique_base'] : null;
$config['slugs'][$field]['separator'] = isset($slug['separator']) ?
(string) $slug['separator'] : '-';
$config['slugs'][$field]['prefix'] = isset($slug['prefix']) ?
(string) $slug['prefix'] : '';
$config['slugs'][$field]['suffix'] = isset($slug['suffix']) ?
(string) $slug['suffix'] : '';
if (!$meta->isMappedSuperclass && $meta->isIdentifier($field) && !$config['slugs'][$field]['unique']) {
throw new InvalidMappingException("Identifier field - [{$field}] slug must be unique in order to maintain primary key in class - {$meta->name}");
}
$ubase = $config['slugs'][$field]['unique_base'];
if ($config['slugs'][$field]['unique'] === false && $ubase) {
throw new InvalidMappingException("Slug annotation [unique_base] can not be set if unique is unset or 'false'");
}
if ($ubase && !$meta->hasField($ubase) && !$meta->hasAssociation($ubase)) {
throw new InvalidMappingException("Unable to find [{$ubase}] as mapped property in entity - {$meta->name}");
}
}
}
}
}