<?php
declare(strict_types = 1);

namespace Innmind\Http\Message\Form;

use Innmind\Http\{
    Message\Form as FormInterface,
    Exception\FormParameterNotFound
};
use Innmind\Immutable\{
    MapInterface,
    Map,
    Sequence
};

final class Form implements FormInterface
{
    private $parameters;

    public function __construct(MapInterface $parameters = null)
    {
        $parameters = $parameters ?? new Map('scalar', Parameter::class);

        if (
            (string) $parameters->keyType() !== 'scalar' ||
            (string) $parameters->valueType() !== Parameter::class
        ) {
            throw new \TypeError(sprintf(
                'Argument 1 must be of type MapInterface<scalar, %s>',
                Parameter::class
            ));
        }

        $this->parameters = $parameters;
    }

    public static function of(Parameter ...$parameters): self
    {
        return new self(
            Sequence::of(...$parameters)->reduce(
                new Map('scalar', Parameter::class),
                static function(MapInterface $parameters, Parameter $parameter): MapInterface {
                    return $parameters->put(
                        $parameter->name(),
                        $parameter
                    );
                }
            )
        );
    }

    /**
     * {@inheritdoc}
     */
    public function get($key): Parameter
    {
        if (!$this->has($key)) {
            throw new FormParameterNotFound;
        }

        return $this->parameters->get($key);
    }

    /**
     * {@inheritdoc}
     */
    public function has($key): bool
    {
        return $this->parameters->contains($key);
    }

    /**
     * {@inheritdoc}
     */
    public function current()
    {
        return $this->parameters->current();
    }

    /**
     * {@inheritdoc}
     */
    public function key()
    {
        return $this->parameters->key();
    }

    /**
     * {@inheritdoc}
     */
    public function next()
    {
        $this->parameters->next();
    }

    /**
     * {@inheritdoc}
     */
    public function rewind()
    {
        $this->parameters->rewind();
    }

    /**
     * {@inheritdoc}
     */
    public function valid()
    {
        return $this->parameters->valid();
    }

    /**
     * {@inheritdoc}
     */
    public function count()
    {
        return $this->parameters->size();
    }
}


<?php
/*
 * Copyright (c) 2012-2016, Hofmänner New Media.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This file is part of the N2N FRAMEWORK.
 *
 * The N2N FRAMEWORK is free software: you can redistribute it and/or modify it under the terms of
 * the GNU Lesser General Public License as published by the Free Software Foundation, either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * N2N is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
 * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU Lesser General Public License for more details: http://www.gnu.org/licenses/
 *
 * The following people participated in this project:
 *
 * Andreas von Burg.....: Architect, Lead Developer
 * Bert Hofmänner.......: Idea, Frontend UI, Community Leader, Marketing
 * Thomas Günther.......: Developer, Hangar
 */
namespace n2n\impl\persistence\orm\property\hangar\relation;

use hangar\api\HangarPropDef;
use hangar\api\PropSourceDef;
use n2n\util\type\attrs\Attributes;
use hangar\api\DbInfo;
use n2n\persistence\orm\annotation\AnnoOneToMany;
use n2n\persistence\meta\structure\Table;
use n2n\impl\persistence\orm\property\relation\RelationFactory;
use n2n\persistence\orm\property\EntityProperty;
use n2n\impl\persistence\orm\property\RelationEntityProperty;
use n2n\util\type\CastUtils;
use n2n\impl\persistence\orm\property\relation\JoinTableRelation;
use n2n\impl\persistence\orm\property\relation\InverseJoinColumnOneToManyRelation;
use n2n\reflection\annotation\AnnotationSet;
use n2n\util\type\ArgUtils;
use n2n\persistence\orm\annotation\AnnoJoinColumn;
use n2n\persistence\meta\structure\IndexType;
use n2n\persistence\orm\annotation\AnnoJoinTable;
use hangar\api\ColumnDefaults;
use hangar\api\CompatibilityLevel;
use phpbob\PhpbobUtils;
use phpbob\representation\PhpTypeDef;
use n2n\web\dispatch\mag\MagCollection;
use hangar\api\HuoContext;
use n2n\persistence\meta\structure\Column;

class OneToManyPropDef implements HangarPropDef {
	private $columnDefaults;
	private $huoContext;

	/**
	 * {@inheritDoc}
	 * @see \hangar\api\HangarPropDef::setup()
	 */
	public function setup(HuoContext $huoContext, ColumnDefaults $columnDefaults) {
		$this->columnDefaults = $columnDefaults;
		$this->huoContext = $huoContext;
	}

	/**
	 * {@inheritDoc}
	 * @see \hangar\api\HangarPropDef::getName()
	 */
	public function getName(): string {
		return 'OneToMany';
	}

	/**
	 * {@inheritDoc}
	 * @see \hangar\api\HangarPropDef::createMagCollection()
	 * @return MagCollection
	 */
	public function createMagCollection(PropSourceDef $propSourceDef = null): MagCollection {
		$magCollection = new OrmRelationMagCollection($this->huoContext->getEntityModelManager(), true, true);

		if (null !== $propSourceDef) {
			if ($propSourceDef->hasPhpPropertyAnno(AnnoOneToMany::class)) {
				$phpAnnotation = $propSourceDef->getPhpPropertyAnno(AnnoOneToMany::class);

				$localName = OrmRelationMagCollection::determineLocalName($phpAnnotation->getPhpAnnoParam(1));
				$magCollection->setTargetEntityClasName($propSourceDef->determineTypeName($localName));

				if ($phpAnnotation->hasPhpAnnoParam(2)) {
					$magCollection->setMappedBy($phpAnnotation->getPhpAnnoParam(2)->getStringValue());
				}

				if ($phpAnnotation->hasPhpAnnoParam(3)) {
					$magCollection->setCascadeTypes(
							OrmRelationMagCollection::determineCascadeTypes($phpAnnotation->getPhpAnnoParam(3)));
				}

				if ($phpAnnotation->hasPhpAnnoParam(4)) {
					$magCollection->setFetchType(
							OrmRelationMagCollection::determineFetchType($phpAnnotation->getPhpAnnoParam(4)));
				}

				if ($phpAnnotation->hasPhpAnnoParam(5)) {
					$magCollection->setOrphanRemoval($phpAnnotation->getPhpAnnoParam(5)->getBoolValue());
				}
			}
		}

		return $magCollection;
	}

	/**
	 * {@inheritDoc}
	 * @see \hangar\api\HangarPropDef::resetPropSourceDef()
	 */
	public function resetPropSourceDef(PropSourceDef $propSourceDef) {
		$propSourceDef->setArrayLikePhpTypeDef(null);

		if ($propSourceDef->hasPhpPropertyAnno(AnnoOneToMany::class)) {
			$phpAnno = $propSourceDef->getPhpPropertyAnno(AnnoOneToMany::class);
			$localName = OrmRelationMagCollection::determineLocalName($phpAnno->getPhpAnnoParam(1));
			$typeName = $propSourceDef->determineTypeName($localName);
			if (null === $typeName && null !== ($phpTypeDef = $propSourceDef->getArrayLikePhpTypeDef())) {
				$typeName = $phpTypeDef->getTypeName();
			}

			$propSourceDef->removePhpUse($typeName);
			$propSourceDef->removePhpPropertyAnno(AnnoOneToMany::class);
			$propSourceDef->removePhpUse(AnnoOneToMany::class);
		}
	}

	/**
	 * {@inheritDoc}
	 * @see \hangar\api\HangarPropDef::updatePropSourceDef()
	 */
	public function updatePropSourceDef(Attributes $attributes, PropSourceDef $propSourceDef) {
		$propSourceDef->getHangarData()->setAll($attributes->toArray());

		$targetEntityTypeName = $attributes->get(OrmRelationMagCollection::PROP_NAME_TARGET_ENTITY_CLASS);
		$propSourceDef->setArrayLikePhpTypeDef(PhpTypeDef::fromTypeName($targetEntityTypeName));

		$propSourceDef->setPhpTypeDef(null);

		$anno = $propSourceDef->getOrCreatePhpPropertyAnno(AnnoOneToMany::class);
		$anno->resetPhpAnnoParams();
		$anno->createPhpAnnoParam(PhpbobUtils::extractClassName($targetEntityTypeName) . '::getClass()');
		$propSourceDef->createPhpUse($targetEntityTypeName);

		$cascadeTypeValue = OrmRelationMagCollection::buildCascadeTypeAnnoParam(
				$attributes->get(OrmRelationMagCollection::PROP_NAME_CASCADE_TYPE));

		$fetchType = OrmRelationMagCollection::buildFetchTypeAnnoParam(
				$attributes->getString(OrmRelationMagCollection::PROP_NAME_FETCH_TYPE));

		$orphanRemoval = ($attributes->get(OrmRelationMagCollection::PROP_NAME_ORPHAN_REMOVAL));
		if (!$orphanRemoval) {
			$orphanRemoval = null;
		} else {
			$orphanRemoval = 'true';
		}

		if (null !== ($mappedBy = $attributes->get(OrmRelationMagCollection::PROP_NAME_MAPPED_BY))) {
			$anno->createPhpAnnoParam($mappedBy, true);
		} else {
			if (null !== $cascadeTypeValue || null !== $fetchType || null !== $orphanRemoval) {
				$anno->createPhpAnnoParam('null');
			}
		}

		if (null !== $cascadeTypeValue) {
			$anno->createPhpAnnoParam($cascadeTypeValue);
		} else if (null !== $fetchType || null !== $orphanRemoval) {
			$anno->createPhpAnnoParam('null');
		}

		if (null !== $fetchType) {
			$anno->createPhpAnnoParam($fetchType);
		} elseif (null !== $orphanRemoval) {
			$anno->createPhpAnnoParam('null');
		}

		if (null !== $orphanRemoval) {
			$anno->createPhpAnnoParam($orphanRemoval);
		}
	}

	/**
	 * {@inheritDoc}
	 * @see \hangar\api\HangarPropDef::applyDbMeta()
	 */
	public function applyDbMeta(DbInfo $dbInfo, PropSourceDef $propSourceDef, EntityProperty $entityProperty,
			AnnotationSet $annotationSet) {
		ArgUtils::assertTrue($entityProperty instanceof RelationEntityProperty);

		$propertyName = $propSourceDef->getPropertyName();
		$annoOneToMany = $annotationSet->getPropertyAnnotation($propertyName, AnnoOneToMany::class);
		CastUtils::assertTrue($annoOneToMany instanceof AnnoOneToMany);

		if (null === $annoOneToMany->getMappedBy()) {
			$idColumnSize = $this->columnDefaults->getDefaultIntegerSize();
			$idColumnSigned = $this->columnDefaults->getDefaultInterSigned();

			$joinMode = RelationFactory::detectJoinMode(RelationEntityProperty::TYPE_ONE_TO_MANY,
					null !== $annotationSet->getPropertyAnnotation($propertyName, AnnoJoinColumn::class),
					null !== $annotationSet->getPropertyAnnotation($propertyName, AnnoJoinTable::class));

			$relation = $entityProperty->getRelation();

			if ($joinMode == RelationFactory::JOIN_MODE_TABLE) {
				CastUtils::assertTrue($relation instanceof JoinTableRelation);

				$database = $dbInfo->getDatabase();
				$joinTable = null;
				$joinTableName = $relation->getJoinTableName();

				if ($database->containsMetaEntityName($joinTableName)) {
					$joinTable = $database->getMetaEntityByName($joinTableName);
					CastUtils::assertTrue($joinTable instanceof Table);
				} else {
					$joinTable = $database->createMetaEntityFactory()->createTable($joinTableName);
				}

				$columnFactory = $joinTable->createColumnFactory();
				$joinTable->removeAllColumns();

				$joinColumnName = $relation->getJoinColumnName();
				$inverseJoinColumnName = $relation->getInverseJoinColumnName();

				$columnFactory->createIntegerColumn($joinColumnName, $idColumnSize, $idColumnSigned);
				$columnFactory->createIntegerColumn($inverseJoinColumnName, $idColumnSize, $idColumnSigned);

				$joinTable->removeAllIndexes();
				$joinTable->createIndex(IndexType::PRIMARY, array($joinColumnName, $inverseJoinColumnName));
			} else {
				CastUtils::assertTrue($relation instanceof InverseJoinColumnOneToManyRelation);

				$targetTableName = $relation->getTargetEntityModel()->getTableName();
				$targetTable = null;

				if ($database->containsMetaEntityName($targetTableName)) {
					$targetTable = $database->getMetaEntityByName($targetTableName);
					CastUtils::assertTrue($joinTable instanceof Table);
				} else {
					$targetTable = $database->createMetaEntityFactory()->createTable($targetTableName);
				}

				$inverseJoinColumnName = $relation->getInverseJoinColumnName();
				if ($targetTable->containsColumnName($inverseJoinColumnName)) {
					$targetTable->removeColumnByName($inverseJoinColumnName);
				}

				$targetTable->createColumnFactory()->createIntegerColumn($inverseJoinColumnName, $idColumnSize, $idColumnSigned);
			}
		}
	}

	/**
	 * @param PropSourceDef $propSourceDef
	 * @return Column
	 */
	public function createMetaColumn(EntityProperty $entityProperty, PropSourceDef $propSourceDef): ?Column {
		return null;
	}

	/**
	 * {@inheritDoc}
	 * @see \hangar\api\HangarPropDef::testSourceCompatibility()
	 */
	public function testCompatibility(PropSourceDef $propSourceDef): int {
		$propertyAnnoCollection = $propSourceDef->getPhpProperty()->getPhpPropertyAnnoCollection();
		if ($propertyAnnoCollection->hasPhpAnno(AnnoOneToMany::class)) {
			return CompatibilityLevel::COMMON;
		}

		return CompatibilityLevel::NOT_COMPATIBLE;
	}
}


<?php
/*
 * Copyright (c) 2012-2016, Hofmänner New Media.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This file is part of the N2N FRAMEWORK.
 *
 * The N2N FRAMEWORK is free software: you can redistribute it and/or modify it under the terms of
 * the GNU Lesser General Public License as published by the Free Software Foundation, either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * N2N is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
 * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU Lesser General Public License for more details: http://www.gnu.org/licenses/
 *
 * The following people participated in this project:
 *
 * Andreas von Burg.....: Architect, Lead Developer
 * Bert Hofmänner.......: Idea, Frontend UI, Community Leader, Marketing
 * Thomas Günther.......: Developer, Hangar
 */
namespace n2n\impl\persistence\orm\property;

use n2n\persistence\orm\property\CustomComparableEntityProperty;
use n2n\persistence\orm\model\EntityPropertyCollection;
use n2n\persistence\orm\property\EntityProperty;
use n2n\persistence\orm\model\UnknownEntityPropertyException;
use n2n\reflection\property\AccessProxy;
use n2n\persistence\orm\query\from\MetaTreePoint;
use n2n\persistence\orm\query\QueryState;
use n2n\persistence\orm\store\action\PersistAction;
use n2n\util\type\ArgUtils;
use n2n\persistence\orm\store\action\RemoveAction;
use n2n\persistence\orm\store\operation\MergeOperation;
use n2n\reflection\ReflectionUtils;
use n2n\persistence\orm\property\JoinableEntityProperty;
use n2n\persistence\orm\query\from\meta\TreePointMeta;
use n2n\persistence\orm\query\from\ExtendableTreePoint;
use n2n\persistence\orm\query\from\JoinedTreePoint;
use n2n\persistence\orm\criteria\JoinType;
use n2n\persistence\orm\query\QueryConflictException;
use n2n\persistence\orm\criteria\compare\ComparisonStrategy;
use n2n\persistence\orm\EntityManager;
use n2n\persistence\meta\data\QueryComparator;
use n2n\persistence\orm\query\select\Selection;
use n2n\persistence\meta\data\QueryItem;
use n2n\persistence\orm\store\ValueHash;
use n2n\persistence\orm\store\CommonValueHash;

class EmbeddedEntityProperty extends EntityPropertyAdapter implements CustomComparableEntityProperty,
		EntityPropertyCollection, JoinableEntityProperty {
	private $targetClass;
	private $properties = array();

	public function __construct(AccessProxy $accessProxy, \ReflectionClass $targetClass) {
		parent::__construct($accessProxy);
		$this->targetClass = $targetClass;
	}

	/**
	 * @return \ReflectionClass
	 */
	public function getTargetClass() {
		return $this->targetClass;
	}

	/**
	 * {@inheritDoc}
	 * @see \n2n\persistence\orm\model\EntityPropertyCollection::getClass()
	 */
	public function getClass(): \ReflectionClass {
		return $this->targetClass;
	}

	public function addEntityProperty(EntityProperty $property) {
		$this->properties[$property->getName()] = $property;
		$property->setParent($this);
	}

	public function containsEntityPropertyName($name) {
		return isset($this->properties[$name]);
	}

	public function getEntityProperties() {
		return $this->properties;
	}

	public function getEntityPropertyByName($name) {
		if (!$this->containsEntityPropertyName($name)) {
			throw new UnknownEntityPropertyException(
					'Unkown entity property: ' . $this->targetClass->getName() . '::$' . $name);
		}

		return $this->properties[$name];
	}
	/* (non-PHPdoc)
	 * @see \n2n\persistence\orm\property\CustomComparableEntityProperty::createCustomComparable()
	 */
	public function createCustomComparable(MetaTreePoint $metaTreePoint, QueryState $queryState) {
		return new EmbeddedCustomComparable($metaTreePoint->requestPropertyJoinedTreePoint($this->getName(), false), $this);
	}

	/* (non-PHPdoc)
	 * @see \n2n\persistence\orm\property\EntityProperty::createSelection()
	 */
	public function createSelection(MetaTreePoint $metaTreePoint, QueryState $queryState) {
		return new EmbeddedSelection($this, $metaTreePoint->requestPropertyJoinedTreePoint($this->getName(), false));
	}

	/* (non-PHPdoc)
	 * @see \n2n\persistence\orm\property\EntityProperty::mergeValue()
	 */
	public function mergeValue($object, $sameEntity, MergeOperation $mergeOperation) {
		if ($object === null) return null;

		$mergedObject = null;
		if ($sameEntity) {
			$mergedObject = $object;
		} else {
			$mergedObject = ReflectionUtils::createObject($this->targetClass);
		}

		foreach ($this->properties as $property) {
			$mergedPropertyValue = $property->mergeValue($property->readValue($object), $sameEntity, $mergeOperation);
			$property->writeValue($mergedObject, $mergedPropertyValue);
		}

		return $mergedObject;
	}

	/* (non-PHPdoc)
	 * @see \n2n\persistence\orm\property\EntityProperty::supplyPersistAction()
	 */
	public function supplyPersistAction(PersistAction $persistingJob, $object, ValueHash $valueHash, ?ValueHash $oldValueHash) {
		ArgUtils::assertTrue($valueHash instanceof CommonValueHash);

		$propertyValueHashes = $valueHash->getHash();
		$oldPropertyValueHashes = null;
		if ($oldValueHash !== null) {
			$oldPropertyValueHashes = $oldValueHash->getHash();
		}

		foreach ($this->properties as $propertyName => $property)  {
			$propertyValue = null;
			if ($object !== null) {
				$propertyValue = $property->readValue($object);
			}

			ArgUtils::assertTrue(array_key_exists($propertyName, $propertyValueHashes));
			$propertyValueHash = $propertyValueHashes[$propertyName];

			$oldPropertyValueHash = null;
			if ($oldPropertyValueHashes !== null) {
				ArgUtils::assertTrue(array_key_exists($propertyName, $oldPropertyValueHashes));
				$oldPropertyValueHash = $oldPropertyValueHashes[$propertyName] ?? null;
			}

			$property->supplyPersistAction($persistingJob, $propertyValue, $propertyValueHash, $oldPropertyValueHash);
		}
	}

	/* (non-PHPdoc)
	 * @see \n2n\persistence\orm\property\EntityProperty::supplyRemoveAction()
	 */
	public function supplyRemoveAction(RemoveAction $removeAction, $value, ValueHash $oldValueHash) {
		ArgUtils::assertTrue($oldValueHash instanceof CommonValueHash);

		$valueHash = $oldValueHash->getHash();

		foreach ($this->properties as $propertyName => $property)  {
			$propertyValue = $property->readValue($object);
			$propertyValueHash = null;
			if ($valueHash !== null) {
				ArgUtils::assertTrue(array_key_exists($propertyName, $valueHash));
				$propertyValueHash = $valueHash[$propertyName];
			}

			$property->supplyRemoveAction($propertyValue, $propertyValueHash, $removeAction);
		}
	}

	public function createValueHash($value, EntityManager $em): ValueHash {
		$valueHashes = array();
		foreach ($this->properties as $propertyName => $property)  {
			$propertyValue = null;
			if ($value !== null) {
				$propertyValue = $property->readValue($value);
			}
			$valueHashes[$propertyName] = $property->createValueHash($propertyValue, $em);
		}
		return new CommonValueHash($valueHashes);
	}
	/* (non-PHPdoc)
	 * @see \n2n\persistence\orm\property\JoinableEntityProperty::createJoinTreePoint()
	 */
	public function createJoinTreePoint(TreePointMeta $treePointMeta, QueryState $queryState) {
		return new EmbeddedTreePoint($queryState, $treePointMeta, $this);
	}

	public function hasEmbeddedEntityPropertyCollection(): bool {
		return true;
	}

	public function getEmbeddedEntityPropertyCollection(): EntityPropertyCollection {
		return $this;
	}

	public function getAvailableJoinTypes(): array {
		return [JoinType::INNER];
	}

}

class EmbeddedTreePoint extends ExtendableTreePoint implements JoinedTreePoint {
	private $embeddedEntityProperty;

	public function __construct(QueryState $queryState, TreePointMeta $treePointMeta,
			EmbeddedEntityProperty $embeddedEntityProperty) {
		parent::__construct($queryState, $embeddedEntityProperty, $treePointMeta);

		$this->embeddedEntityProperty = $embeddedEntityProperty;
	}

	public function setJoinType($joinType) {
		if ($joinType == JoinType::INNER/* || $joinType == JoinType::LEFT*/) return;

		throw new QueryConflictException('Can not perform ' . $joinType . ' JOIN on embedded property '
				. $this->embeddedEntityProperty->toPropertyString() . '. Use INNER JOIN.');
	}
	/* (non-PHPdoc)
	 * @see \n2n\persistence\orm\query\from\JoinedTreePoint::getJoinType()
	 */
	public function getJoinType() {
		return JoinType::INNER;
	}

	public function getOnQueryComparator(): QueryComparator {
		throw new QueryConflictException('no on clause available for JOIN on embedded property '
				. $this->embeddedEntityProperty->toPropertyString() . '.');
	}

	private $comparisonStrategy;
	private $selection;
	/* (non-PHPdoc)
	 * @see \n2n\persistence\orm\query\QueryPoint::requestComparisonStrategy()
	 */
	public function requestComparisonStrategy(): ComparisonStrategy {
		if ($this->comparisonStrategy !== null) return $this->comparisonStrategy;
		return $this->comparisonStrategy = new ComparisonStrategy(null,
				$this->embeddedEntityProperty->createCustomComparable($this, $this->queryState));
	}
	/* (non-PHPdoc)
	 * @see \n2n\persistence\orm\query\QueryPoint::requestSelection()
	 */
	public function requestSelection(): Selection {
		if ($this->selection !== null) return $this->selection;
		return $this->selection = $this->embeddedEntityProperty->createSelection($this, $this->queryState);
	}
	/* (non-PHPdoc)
	 * @see \n2n\persistence\orm\query\QueryPoint::requestRepresentableQueryItem()
	 */
	public function requestRepresentableQueryItem(): QueryItem {
		throw new QueryConflictException('Embedded property is not representable by a single query item: '
				. $this->embeddedEntityProperty->toPropertyString());
	}

}


<?php
/*
 * Copyright (c) 2012-2016, Hofmänner New Media.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This file is part of the N2N FRAMEWORK.
 *
 * The N2N FRAMEWORK is free software: you can redistribute it and/or modify it under the terms of
 * the GNU Lesser General Public License as published by the Free Software Foundation, either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * N2N is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
 * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU Lesser General Public License for more details: http://www.gnu.org/licenses/
 *
 * The following people participated in this project:
 *
 * Andreas von Burg.....: Architect, Lead Developer
 * Bert Hofmänner.......: Idea, Frontend UI, Community Leader, Marketing
 * Thomas Günther.......: Developer, Hangar
 */
namespace n2n\impl\persistence\orm\property\hangar;

use n2n\util\type\attrs\Attributes;
use n2n\persistence\orm\property\EntityProperty;
use n2n\reflection\annotation\AnnotationSet;
use n2n\util\type\ArgUtils;
use n2n\impl\persistence\orm\property\DateTimeEntityProperty;
use n2n\impl\persistence\meta\mysql\MysqlDateTimeColumn;
use hangar\api\HangarPropDef;
use hangar\api\ColumnDefaults;
use hangar\api\PropSourceDef;
use hangar\api\DbInfo;
use hangar\api\CompatibilityLevel;
use phpbob\representation\PhpTypeDef;
use hangar\api\HuoContext;
use n2n\persistence\meta\structure\Column;
use n2n\web\dispatch\mag\MagCollection;
use n2n\persistence\orm\annotation\AnnoDateTime;

class DateTimePropDef implements HangarPropDef {

	protected $columnDefaults;

	public function setup(HuoContext $huoContext, ColumnDefaults $columnDefaults) {
		$this->columnDefaults = $columnDefaults;
	}

	/**
	 * {@inheritDoc}
	 * @see \hangar\api\HangarPropDef::getName()
	 */
	public function getName(): string {
		return 'DateTime';
	}

	/**
	 * {@inheritDoc}
	 * @see \hangar\api\HangarPropDef::createMagCollection()
	 */
	public function createMagCollection(PropSourceDef $propSourceDef = null): MagCollection {
		return new MagCollection();
	}

	/**
	 * {@inheritDoc}
	 * @see \hangar\api\HangarPropDef::resetPropSourceDef()
	 */
	public function resetPropSourceDef(PropSourceDef $propSourceDef) {
		$propSourceDef->removePhpPropertyAnno(AnnoDateTime::class);
		$propSourceDef->removePhpUse(AnnoDateTime::class);
	}

	/**
	 * {@inheritDoc}
	 * @see \hangar\api\HangarPropDef::updatePropSourceDef()
	 */
	public function updatePropSourceDef(Attributes $attributes, PropSourceDef $propSourceDef) {
		$propSourceDef->setPhpTypeDef(new PhpTypeDef('\DateTime'));
	}

	/**
	 * {@inheritDoc}
	 * @see \hangar\api\HangarPropDef::applyDbMeta()
	 */
	public function applyDbMeta(DbInfo $dbInfo, PropSourceDef $propSourceDef, EntityProperty $entityProperty,
			AnnotationSet $annotationSet) {
		ArgUtils::assertTrue($entityProperty instanceof DateTimeEntityProperty);
		$columnName = $entityProperty->getColumnName();
		$dbInfo->removeColumn($columnName);
		$dbInfo->getTable()->createColumnFactory()->createDateTimeColumn($columnName, true, true);
	}

	/**
	 * {@inheritDoc}
	 * @see \hangar\api\HangarPropDef::createMetaColumn()
	 * @return Column
	 */
	public function createMetaColumn(EntityProperty $entityProperty, PropSourceDef $propSourceDef): ?Column {
		ArgUtils::assertTrue($entityProperty instanceof DateTimeEntityProperty);

		return new MysqlDateTimeColumn($entityProperty->getColumnName(), true, true);
	}

	/**
	 * {@inheritDoc}
	 * @see \hangar\api\HangarPropDef::testCompatibility()
	 */
	public function testCompatibility(PropSourceDef $propSourceDef): int {
		if ($propSourceDef->hasPhpPropertyAnno(AnnoDateTime::class)) return CompatibilityLevel::COMMON;
		if (null !== ($phpTypeDef = $propSourceDef->getPhpTypeDef()) &&
				$phpTypeDef->getLocalName() === '\DateTime') return CompatibilityLevel::COMMON;

		return CompatibilityLevel::NOT_COMPATIBLE;
	}
}


<?php
/*
 * Copyright (c) 2012-2016, Hofmänner New Media.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This file is part of the N2N FRAMEWORK.
 *
 * The N2N FRAMEWORK is free software: you can redistribute it and/or modify it under the terms of
 * the GNU Lesser General Public License as published by the Free Software Foundation, either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * N2N is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
 * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU Lesser General Public License for more details: http://www.gnu.org/licenses/
 *
 * The following people participated in this project:
 *
 * Andreas von Burg.....: Architect, Lead Developer
 * Bert Hofmänner.......: Idea, Frontend UI, Community Leader, Marketing
 * Thomas Günther.......: Developer, Hangar
 */
namespace n2n\impl\persistence\orm\property\hangar\scalar;

use n2n\util\type\attrs\Attributes;
use hangar\api\DbInfo;
use n2n\persistence\meta\structure\ColumnFactory;
use n2n\impl\web\dispatch\mag\model\StringArrayMag;
use hangar\api\PropSourceDef;
use n2n\persistence\orm\property\EntityProperty;
use n2n\util\type\ArgUtils;
use n2n\impl\persistence\orm\property\ScalarEntityProperty;
use n2n\persistence\meta\structure\common\CommonEnumColumn;
use phpbob\representation\PhpTypeDef;
use n2n\web\dispatch\mag\MagCollection;
use n2n\persistence\meta\structure\Column;
use hangar\api\CompatibilityLevel;

class EnumPropDef extends ScalarPropDefAdapter {
	const PROP_NAME_VALUES = 'values';

	public function getName(): string {
		return 'Enum';
	}

	protected function createColumn(EntityProperty $entityProperty, DbInfo $dbInfo, ColumnFactory $columnFactory,
			$columnName, Attributes $attributes) {
		$columnFactory->createEnumColumn($columnName, $this->getValues($attributes));
	}

	/**
	 * {@inheritDoc}
	 * @see \hangar\api\HangarPropDef::createMagCollection()
	 * @return MagCollection
	 */
	public function createMagCollection(PropSourceDef $propSourceDef = null): MagCollection {
		$optionCollection = new MagCollection();

		$values = array();
		if (null !== $propSourceDef) {
			$values = $propSourceDef->getHangarData()->getArray(self::PROP_NAME_VALUES, false);
		}

		$optionCollection->addMag(self::PROP_NAME_VALUES, new StringArrayMag('Values', $values, true));

		return $optionCollection;
	}

	/**
	 * {@inheritDoc}
	 * @see \hangar\api\HangarPropDef::updatePropSourceDef()
	 */
	public function updatePropSourceDef(Attributes $attributes, PropSourceDef $propSourceDef) {
		$propSourceDef->getHangarData()->setAll(array(self::PROP_NAME_VALUES =>
				$attributes->get(self::PROP_NAME_VALUES)));
		$propSourceDef->setPhpTypeDef(new PhpTypeDef('string'));
	}

	/**
	 * {@inheritDoc}
	 * @see \n2n\impl\persistence\orm\property\hangar\scalar\ScalarPropDefAdapter::testSourceCompatibility()
	 */
	public function testCompatibility(PropSourceDef $propSourceDef): int {
		if (null === $propSourceDef->getPhpTypeDef() || $propSourceDef->getPhpTypeDef()->isString()) {
			return CompatibilityLevel::COMPATIBLE;
		}

		return CompatibilityLevel::NOT_COMPATIBLE;
	}

	/**
	 * @param PropSourceDef $propSourceDef
	 * @return Column
	 */
	public function createMetaColumn(EntityProperty $entityProperty, PropSourceDef $propSourceDef): ?Column {
		ArgUtils::assertTrue($entityProperty instanceof ScalarEntityProperty);

		return new CommonEnumColumn($entityProperty->getColumnName(), $this->getValues($propSourceDef->getHangarData()));
	}

	private function getValues(Attributes $attributes) {
		return $attributes->getArray(self::PROP_NAME_VALUES, false, array());
	}
}


<?php
/*
 * Copyright (c) 2012-2016, Hofmänner New Media.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This file is part of the N2N FRAMEWORK.
 *
 * The N2N FRAMEWORK is free software: you can redistribute it and/or modify it under the terms of
 * the GNU Lesser General Public License as published by the Free Software Foundation, either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * N2N is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
 * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU Lesser General Public License for more details: http://www.gnu.org/licenses/
 *
 * The following people participated in this project:
 *
 * Andreas von Burg.....: Architect, Lead Developer
 * Bert Hofmänner.......: Idea, Frontend UI, Community Leader, Marketing
 * Thomas Günther.......: Developer, Hangar
 */
namespace n2n\persistence\orm\property;

use n2n\io\managed\FileManager;
use n2n\util\StringUtils;
use n2n\io\managed\impl\SimpleFileLocator;
use n2n\reflection\property\AccessProxy;
use n2n\persistence\orm\EntityManager;
use n2n\persistence\orm\model\EntityModel;
use n2n\util\type\TypeConstraint;
use n2n\core\N2N;
use n2n\persistence\orm\query\QueryState;
use n2n\persistence\orm\query\from\MetaTreePoint;
use n2n\persistence\orm\store\ValueHash;
use n2n\persistence\orm\store\action\PersistAction;
use n2n\persistence\orm\store\operation\MergeOperation;
use n2n\impl\persistence\orm\property\ColumnPropertyAdapter;
use n2n\persistence\orm\annotation\AnnoFile;
use n2n\persistence\orm\store\action\RemoveAction;

class FileProperty extends ColumnPropertyAdapter {
	private $fileManagerType;
	private $fileLocator;
	private $fileManager;

	public function __construct(EntityModel $entityModel, AccessProxy $accessProxy,
			$columnName, AnnoFile $fileAnnotaiton = null) {
		parent::__construct($entityModel, $accessProxy, $columnName);

		if (isset($fileAnnotaiton)) {
			$this->fileManagerType = $fileAnnotaiton->getManager();
			$this->fileLocator = $fileAnnotaiton->getLocator();
		}

		if ($this->fileLocator !== null) {
			$this->fileLocator = new SimpleFileLocator(
					StringUtils::hyphenated($entityModel->getTableName(), false));
		}

		$accessProxy->setConstraint(TypeConstraint::createSimple('n2n\io\managed\File'));
	}

	private function getFileManager() {
		if (isset($this->fileManager)) {
			return $this->fileManager;
		}

		if (isset($this->fileManagerType)) {
			return $this->fileManager = N2N::getLookupManager()->lookup($this->fileManagerType);
		}

		return $this->fileManager = N2N::getLookupManager()->lookup(FileManager::COMMON_PUBLIC);
	}

// 	public function mapValue(MappingJob $mappingJob, \ArrayObject $rawDataMap, \ArrayObject $mappedValues) {
// 		$mappedValues->offsetSet($this->getName(), $this->getFileManager()->getByQualifiedName($rawDataMap[$this->getColumnName()]));
// 	}

	public function supplyPersistAction($mappedValue, PersistAction $persistingJob) {
		$columnName = $this->getColumnName();

		$fileManager = $this->getFileManager();
		$fileLocator = $this->fileLocator;

		$that = $this;
		$persistingJob->executeAtStart(function(PersistAction $persistingJob) use ($that, $fileManager, $fileLocator, $mappedValue, $columnName) {
			$oldDataSet = $persistingJob->getOldRawDataMap();

			$oldQualifiedName = null;
			if (isset($oldDataSet)) {
				$oldQualifiedName = $oldDataSet->offsetGet($columnName);
			}

			if (isset($oldQualifiedName) && isset($mappedValue) && $mappedValue->isManaged()
					&& $fileManager->equals($mappedValue->getFileManager())
					&& $oldQualifiedName === $mappedValue->getQualifiedName()) {
				$persistingJob->getMeta()->setRawValue($that->getEntityModel(), $that->getColumnName(), $oldQualifiedName);
				return;
			}

			if (isset($oldQualifiedName)) {
				$oldFile = $fileManager->getByQualifiedName($oldQualifiedName);
				if (isset($oldFile)) $oldFile->moveToTmp();
			}

			if (isset($mappedValue)) {
				$persistingJob->getMeta()->setRawValue($that->getEntityModel(), $columnName,
						$fileManager->persist($mappedValue, $fileLocator));
				return;
			}

			$persistingJob->getMeta()->setRawValue($that->getEntityModel(), $columnName, null);
		});
	}

	public function supplyRemoveAction($mappedValue, RemoveAction $removingJob) {
		if (!isset($mappedValue)) return;

		$removingJob->executeAtStart(function(RemoveAction $removingJob) use ($mappedValue) {
			$mappedValue->moveToTmp();
		});
	}

// 	public function copy($mappedValue) {
// 		if (isset($mappedValue)) {
// 			return new ClonedFile($mappedValue);
// 		}
// 		return null;
// 	}

	public static function areConstraintsTypical(TypeConstraint $constraints = null) {
		return isset($constraints) && !is_null($constraints->getParamClass())
				&& $constraints->getParamClass()->getName() == 'n2n\io\managed\File' && !$constraints->isArray();
	}
	public function createValueHash($value, EntityManager $em): ValueHash {
	}

	public function createSelection(MetaTreePoint $metaTreePoint, QueryState $queryState) {
	}

	public function mergeValue($value, $sameEntity, MergeOperation $mergeOperation) {
	}

}


<?php
/*
 * Copyright (c) 2012-2016, Hofmänner New Media.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This file is part of the N2N FRAMEWORK.
 *
 * The N2N FRAMEWORK is free software: you can redistribute it and/or modify it under the terms of
 * the GNU Lesser General Public License as published by the Free Software Foundation, either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * N2N is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
 * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU Lesser General Public License for more details: http://www.gnu.org/licenses/
 *
 * The following people participated in this project:
 *
 * Andreas von Burg.....: Architect, Lead Developer
 * Bert Hofmänner.......: Idea, Frontend UI, Community Leader, Marketing
 * Thomas Günther.......: Developer, Hangar
 */
namespace n2n\impl\persistence\orm\property\hangar\relation;

use hangar\api\HangarPropDef;
use hangar\api\PropSourceDef;
use n2n\util\type\attrs\Attributes;
use hangar\api\DbInfo;
use n2n\persistence\orm\property\EntityProperty;
use n2n\impl\persistence\orm\property\RelationEntityProperty;
use n2n\reflection\annotation\AnnotationSet;
use n2n\util\type\ArgUtils;
use n2n\persistence\orm\annotation\AnnoOneToOne;
use n2n\util\type\CastUtils;
use n2n\impl\persistence\orm\property\relation\ToOneRelation;
use n2n\impl\persistence\orm\property\relation\JoinColumnToOneRelation;
use hangar\api\ColumnDefaults;
use hangar\api\CompatibilityLevel;
use phpbob\representation\PhpTypeDef;
use phpbob\PhpbobUtils;
use hangar\api\HuoContext;
use n2n\web\dispatch\mag\MagCollection;
use n2n\persistence\meta\structure\Column;

class OneToOnePropDef implements HangarPropDef {
	const PROP_NAME_PROPS = 'props';

	private $columnDefaults;
	private $huoContext;

	/**
	 * {@inheritDoc}
	 * @see \hangar\api\HangarPropDef::setup()
	 */
	public function setup(HuoContext $huoContext, ColumnDefaults $columnDefaults) {
		$this->columnDefaults = $columnDefaults;
		$this->huoContext = $huoContext;
	}

	/**
	 * {@inheritDoc}
	 * @see \hangar\api\HangarPropDef::getName()
	 */
	public function getName(): string {
		return 'OneToOne';
	}

	/**
	 * {@inheritDoc}
	 * @see \hangar\api\HangarPropDef::createMagCollection()
	 * @return MagCollection
	 */
	public function createMagCollection(PropSourceDef $propSourceDef = null): MagCollection {
		$magCollection = new OrmRelationMagCollection($this->huoContext->getEntityModelManager(), true, true);

		if (null !== $propSourceDef) {

			if ($propSourceDef->hasPhpPropertyAnno(AnnoOneToOne::class)) {
				$phpAnnotation = $propSourceDef->getPhpPropertyAnno(AnnoOneToOne::class);

				$localName = OrmRelationMagCollection::determineLocalName($phpAnnotation->getPhpAnnoParam(1));
				$magCollection->setTargetEntityClasName($propSourceDef->determineTypeName($localName) ?? $localName);

				if ($phpAnnotation->hasPhpAnnoParam(2)) {
					$magCollection->setMappedBy($phpAnnotation->getPhpAnnoParam(2)->getStringValue());
				}

				if ($phpAnnotation->hasPhpAnnoParam(3)) {
					$magCollection->setCascadeTypes(
							OrmRelationMagCollection::determineCascadeTypes($phpAnnotation->getPhpAnnoParam(3)));
				}

				if ($phpAnnotation->hasPhpAnnoParam(4)) {
					$magCollection->setFetchType(
							OrmRelationMagCollection::determineFetchType($phpAnnotation->getPhpAnnoParam(4)));
				}

				if ($phpAnnotation->hasPhpAnnoParam(5)) {
					$magCollection->setOrphanRemoval($phpAnnotation->getPhpAnnoParam(5)->getBoolValue());
				}
			}
		}

		return $magCollection;
	}

	/**
	 * {@inheritDoc}
	 * @see \hangar\api\HangarPropDef::resetPropSourceDef()
	 */
	public function resetPropSourceDef(PropSourceDef $propSourceDef) {
		if ($propSourceDef->hasPhpPropertyAnno(AnnoOneToOne::class)) {
			$phpAnno = $propSourceDef->getPhpPropertyAnno(AnnoOneToOne::class);
			$localName = OrmRelationMagCollection::determineLocalName($phpAnno->getPhpAnnoParam(1));
			$typeName = $propSourceDef->determineTypeName($localName);

			if (null === $typeName && null !== ($phpTypeDef = $propSourceDef->getPhpTypeDef())) {
				$typeName = $phpTypeDef->getTypeName();
			}

			$propSourceDef->removePhpUse($typeName);
			$propSourceDef->removePhpPropertyAnno(AnnoOneToOne::class);
			$propSourceDef->removePhpUse(AnnoOneToOne::class);
		}
	}

	/**
	 * {@inheritDoc}
	 * @see \hangar\api\HangarPropDef::updatePropSourceDef()
	 */
	public function updatePropSourceDef(Attributes $attributes, PropSourceDef $propSourceDef) {
		$propSourceDef->getHangarData()->setAll($attributes->toArray());

		$targetEntityTypeName = $attributes->get(OrmRelationMagCollection::PROP_NAME_TARGET_ENTITY_CLASS);
		$propSourceDef->setPhpTypeDef(PhpTypeDef::fromTypeName($targetEntityTypeName));

		$anno = $propSourceDef->getOrCreatePhpPropertyAnno(AnnoOneToOne::class);
		$anno->resetPhpAnnoParams();
		$anno->createPhpAnnoParam(PhpbobUtils::extractClassName($targetEntityTypeName) . '::getClass()');
		$propSourceDef->createPhpUse($targetEntityTypeName);

		$cascadeTypeValue = OrmRelationMagCollection::buildCascadeTypeAnnoParam(
				$attributes->get(OrmRelationMagCollection::PROP_NAME_CASCADE_TYPE));

		$fetchType = OrmRelationMagCollection::buildFetchTypeAnnoParam(
				$attributes->getString(OrmRelationMagCollection::PROP_NAME_FETCH_TYPE));

		$orphanRemoval = $attributes->get(OrmRelationMagCollection::PROP_NAME_ORPHAN_REMOVAL);
		if (!$orphanRemoval) {
			$orphanRemoval = null;
		} else {
			$orphanRemoval = 'true';
		}

		if (null !== ($mappedBy = $attributes->get(OrmRelationMagCollection::PROP_NAME_MAPPED_BY))) {
			$anno->createPhpAnnoParam($mappedBy, true);
		} else {
			if (null !== $cascadeTypeValue || null !== $fetchType || null !== $orphanRemoval) {
				$anno->createPhpAnnoParam('null');
			}
		}

		if (null !== $cascadeTypeValue) {
			$anno->createPhpAnnoParam($cascadeTypeValue);
		} else if (null !== $fetchType || null !== $orphanRemoval) {
			$anno->createPhpAnnoParam('null');
		}

		if (null !== $fetchType) {
			$anno->createPhpAnnoParam($fetchType);
		} elseif (null !== $orphanRemoval) {
			$anno->createPhpAnnoParam('null');
		}

		if (null !== $orphanRemoval) {
			$anno->createPhpAnnoParam($orphanRemoval);
		}
	}

	/**
	 * {@inheritDoc}
	 * @see \hangar\api\HangarPropDef::applyDbMeta()
	 */
	public function applyDbMeta(DbInfo $dbInfo, PropSourceDef $propSourceDef,
			EntityProperty $entityProperty, AnnotationSet $annotationSet) {
		ArgUtils::assertTrue($entityProperty instanceof RelationEntityProperty);

		$propertyName = $propSourceDef->getPropertyName();
		$annoOneToOne = $annotationSet->getPropertyAnnotation($propertyName,
				AnnoOneToOne::class);
		CastUtils::assertTrue($annoOneToOne instanceof AnnoOneToOne);

		if (null !== $annoOneToOne->getMappedBy()) return;

		$relation = $entityProperty->getRelation();
		ArgUtils::assertTrue($relation instanceof ToOneRelation);
		if (!$relation instanceof JoinColumnToOneRelation) return;

		$table = $dbInfo->getTable();
		if (!$table->containsColumnName($relation->getJoinColumnName())) {
			$table->createColumnFactory()->createIntegerColumn(
					$relation->getJoinColumnName(),
					$this->columnDefaults->getDefaultIntegerSize(),
					$this->columnDefaults->getDefaultInterSigned());
		}
	}

	/**
	 * @param PropSourceDef $propSourceDef
	 * @return Column
	 */
	public function createMetaColumn(EntityProperty $entityProperty, PropSourceDef $propSourceDef): ?Column {
		return null;
	}

	/**
	 * {@inheritDoc}
	 * @see \hangar\api\HangarPropDef::testSourceCompatibility()
	 */
	public function testCompatibility(PropSourceDef $propSourceDef): int {
		$propertyAnnoCollection = $propSourceDef->getPhpProperty()->getPhpPropertyAnnoCollection();
		if ($propertyAnnoCollection->hasPhpAnno(AnnoOneToOne::class)) {
			return CompatibilityLevel::COMMON;
		}

		return CompatibilityLevel::NOT_COMPATIBLE;
	}
}


<?php
/*
 * Copyright (c) 2012-2016, Hofmänner New Media.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This file is part of the N2N FRAMEWORK.
 *
 * The N2N FRAMEWORK is free software: you can redistribute it and/or modify it under the terms of
 * the GNU Lesser General Public License as published by the Free Software Foundation, either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * N2N is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
 * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU Lesser General Public License for more details: http://www.gnu.org/licenses/
 *
 * The following people participated in this project:
 *
 * Andreas von Burg.....: Architect, Lead Developer
 * Bert Hofmänner.......: Idea, Frontend UI, Community Leader, Marketing
 * Thomas Günther.......: Developer, Hangar
 */
namespace n2n\impl\persistence\orm\property\hangar;

use hangar\api\HangarPropDef;
use hangar\api\PropSourceDef;
use n2n\util\type\attrs\Attributes;
use n2n\web\dispatch\mag\MagCollection;
use hangar\api\DbInfo;
use n2n\persistence\orm\property\EntityProperty;
use n2n\reflection\annotation\AnnotationSet;
use n2n\impl\persistence\orm\property\N2nLocaleEntityProperty;
use n2n\l10n\N2nLocale;
use n2n\util\type\ArgUtils;
use hangar\api\ColumnDefaults;
use n2n\persistence\meta\structure\common\CommonStringColumn;
use hangar\api\CompatibilityLevel;
use phpbob\representation\PhpTypeDef;
use hangar\api\HuoContext;
use n2n\persistence\meta\structure\Column;
use n2n\persistence\orm\annotation\AnnoN2nLocale;

class N2nLocalePropDef implements HangarPropDef {
	const DEFAULT_LOCALE_COLUMN_LENGTH = '12';

	protected $columnDefaults;

	public function setup(HuoContext $huoContext, ColumnDefaults $columnDefaults) {
		$this->columnDefaults = $columnDefaults;
	}

	public function getName(): string {
		return 'N2nLocale';
	}

	public function createMagCollection(PropSourceDef $propSourceDef = null): MagCollection {
		return new MagCollection();
	}

	/**
	 * {@inheritDoc}
	 * @see \hangar\api\HangarPropDef::resetPropSourceDef()
	 */
	public function resetPropSourceDef(PropSourceDef $propSourceDef) {
	    $propSourceDef->removePhpPropertyAnno(AnnoN2nLocale::class);
	    $propSourceDef->removePhpUse(AnnoN2nLocale::class);
	    $propSourceDef->removePhpUse(N2nLocale::class);
	}

	public function updatePropSourceDef(Attributes $attributes, PropSourceDef $propSourceDef) {
		$propSourceDef->setPhpTypeDef(PhpTypeDef::fromTypeName(N2nLocale::class));
	}

	/**
	 * {@inheritDoc}
	 * @see \hangar\api\HangarPropDef::applyDbMeta()
	 */
	public function applyDbMeta(DbInfo $dbInfo, PropSourceDef $propSourceDef, EntityProperty $entityProperty,
			AnnotationSet $annotationSet) {
		ArgUtils::assertTrue($entityProperty instanceof N2nLocaleEntityProperty);
		$columnName = $entityProperty->getColumnName();
		$dbInfo->removeColumn($columnName);

		$dbInfo->getTable()->createColumnFactory()
				->createStringColumn($columnName, self::DEFAULT_LOCALE_COLUMN_LENGTH);
	}

	/**
	 * @param PropSourceDef $propSourceDef
	 * @return Column
	 */
	public function createMetaColumn(EntityProperty $entityProperty, PropSourceDef $propSourceDef): ?Column {
		ArgUtils::assertTrue($entityProperty instanceof N2nLocaleEntityProperty);
		return new CommonStringColumn($entityProperty->getColumnName(), self::DEFAULT_LOCALE_COLUMN_LENGTH);
	}

	/**
	 * {@inheritDoc}
	 * @see \hangar\api\HangarPropDef::testCompatibility()
	 */
	public function testCompatibility(PropSourceDef $propSourceDef): int {
		if ($propSourceDef->hasPhpPropertyAnno(AnnoN2nLocale::class)) return CompatibilityLevel::COMMON;
		if (null !== ($phpTypeDef = $propSourceDef->getPhpTypeDef()) &&
				$phpTypeDef->getTypeName() === N2nLocale::class) return CompatibilityLevel::COMMON;

		return CompatibilityLevel::NOT_COMPATIBLE;
	}
}


<?php

/*
 * This file is part of the xAPI package.
 *
 * (c) Christian Flothmann <christian.flothmann@xabbuh.de>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Xabbuh\XApi\DataFixtures;

use Xabbuh\XApi\Model\Agent;
use Xabbuh\XApi\Model\Activity;
use Xabbuh\XApi\Model\Definition;
use Xabbuh\XApi\Model\InverseFunctionalIdentifier;
use Xabbuh\XApi\Model\IRI;
use Xabbuh\XApi\Model\LanguageMap;
use Xabbuh\XApi\Model\Statement;
use Xabbuh\XApi\Model\StatementId;
use Xabbuh\XApi\Model\StatementReference;
use Xabbuh\XApi\Model\SubStatement;
use Xabbuh\XApi\Model\Verb;

/**
 * xAPI statement fixtures.
 *
 * These fixtures are borrowed from the
 * {@link https://github.com/adlnet/xAPI_LRS_Test Experience API Learning Record Store Conformance Test} package.
 */
class StatementFixtures
{
    const DEFAULT_STATEMENT_ID = '12345678-1234-5678-8234-567812345678';

    public static function getMinimalStatement($id = self::DEFAULT_STATEMENT_ID)
    {
        if (null === $id) {
            $id = UuidFixtures::getUniqueUuid();
        }

        return new Statement(StatementId::fromString($id), ActorFixtures::getTypicalAgent(), VerbFixtures::getTypicalVerb(), ActivityFixtures::getTypicalActivity());
    }

    public static function getTypicalStatement($id = self::DEFAULT_STATEMENT_ID)
    {
        if (null === $id) {
            $id = UuidFixtures::getUniqueUuid();
        }

        return new Statement(StatementId::fromString($id), ActorFixtures::getTypicalAgent(), VerbFixtures::getTypicalVerb(), ActivityFixtures::getTypicalActivity(), null, null, new \DateTime('2014-07-23T12:34:02-05:00'));
    }

    public static function getVoidingStatement($id = null, $voidedStatementId = 'e05aa883-acaf-40ad-bf54-02c8ce485fb0')
    {
        if (null === $id) {
            $id = UuidFixtures::getUniqueUuid();
        }

        return new Statement(StatementId::fromString($id), ActorFixtures::getTypicalAgent(), VerbFixtures::getVoidingVerb(), new StatementReference(StatementId::fromString($voidedStatementId)));
    }

    public static function getAttachmentStatement()
    {
        return new Statement(null, ActorFixtures::getTypicalAgent(), VerbFixtures::getTypicalVerb(), ActivityFixtures::getTypicalActivity(), null, null, null, null, null, array(AttachmentFixtures::getTextAttachment()));
    }

    /**
     * Loads a statement with a group as an actor.
     *
     * @param string $id The id of the new Statement
     *
     * @return Statement
     */
    public static function getStatementWithGroupActor($id = self::DEFAULT_STATEMENT_ID)
    {
        if (null === $id) {
            $id = UuidFixtures::getUniqueUuid();
        }

        $group = ActorFixtures::getTypicalGroup();
        $verb = VerbFixtures::getTypicalVerb();
        $activity = ActivityFixtures::getTypicalActivity();

        return new Statement(StatementId::fromString($id), $group, $verb, $activity);
    }

    /**
     * Loads a statement with a group that has no members as an actor.
     *
     * @param string $id The id of the new Statement
     *
     * @return Statement
     */
    public static function getStatementWithGroupActorWithoutMembers($id = self::DEFAULT_STATEMENT_ID)
    {
        if (null === $id) {
            $id = UuidFixtures::getUniqueUuid();
        }

        $group = ActorFixtures::getTypicalGroup();
        $verb = VerbFixtures::getTypicalVerb();
        $activity = ActivityFixtures::getTypicalActivity();

        return new Statement(StatementId::fromString($id), $group, $verb, $activity);
    }

    /**
     * Loads a statement including a reference to another statement.
     *
     * @param string $id The id of the new Statement
     *
     * @return Statement
     */
    public static function getStatementWithStatementRef($id = self::DEFAULT_STATEMENT_ID)
    {
        $minimalStatement = static::getMinimalStatement($id);

        return new Statement(
            $minimalStatement->getId(),
            $minimalStatement->getActor(),
            $minimalStatement->getVerb(),
            new StatementReference(StatementId::fromString('8f87ccde-bb56-4c2e-ab83-44982ef22df0'))
        );
    }

    /**
     * Loads a statement including a result.
     *
     * @param string $id The id of the new Statement
     *
     * @return Statement
     */
    public static function getStatementWithResult($id = self::DEFAULT_STATEMENT_ID)
    {
        if (null === $id) {
            $id = UuidFixtures::getUniqueUuid();
        }

        return new Statement(StatementId::fromString($id), ActorFixtures::getTypicalAgent(), VerbFixtures::getTypicalVerb(), ActivityFixtures::getTypicalActivity(), ResultFixtures::getScoreAndDurationResult());
    }

    /**
     * Loads a statement including a sub statement.
     *
     * @param string $id The id of the new Statement
     *
     * @return Statement
     */
    public static function getStatementWithSubStatement($id = self::DEFAULT_STATEMENT_ID)
    {
        if (null === $id) {
            $id = UuidFixtures::getUniqueUuid();
        }

        $actor = new Agent(InverseFunctionalIdentifier::withMbox(IRI::fromString('mailto:test@example.com')));
        $verb = new Verb(IRI::fromString('http://example.com/visited'), LanguageMap::create(array('en-US' => 'will visit')));
        $definition = new Definition(
            LanguageMap::create(array('en-US' => 'Some Awesome Website')),
            LanguageMap::create(array('en-US' => 'The visited website')),
            IRI::fromString('http://example.com/definition-type')
        );
        $activity = new Activity(IRI::fromString('http://example.com/website'), $definition);
        $subStatement = new SubStatement($actor, $verb, $activity);

        $actor = new Agent(InverseFunctionalIdentifier::withMbox(IRI::fromString('mailto:test@example.com')));
        $verb = new Verb(IRI::fromString('http://example.com/planned'), LanguageMap::create(array('en-US' => 'planned')));

        return new Statement(StatementId::fromString($id), $actor, $verb, $subStatement);
    }

    /**
     * Loads a statement including an agent authority.
     *
     * @param string $id The id of the new Statement
     *
     * @return Statement
     */
    public static function getStatementWithAgentAuthority($id = self::DEFAULT_STATEMENT_ID)
    {
        if (null === $id) {
            $id = UuidFixtures::getUniqueUuid();
        }

        return new Statement(StatementId::fromString($id), ActorFixtures::getTypicalAgent(), VerbFixtures::getTypicalVerb(), ActivityFixtures::getTypicalActivity(), null, ActorFixtures::getAccountAgent());
    }

    /**
     * Loads a statement including a group authority.
     *
     * @param string $id The id of the new Statement
     *
     * @return Statement
     */
    public static function getStatementWithGroupAuthority($id = self::DEFAULT_STATEMENT_ID)
    {
        if (null === $id) {
            $id = UuidFixtures::getUniqueUuid();
        }

        return new Statement(StatementId::fromString($id), ActorFixtures::getTypicalAgent(), VerbFixtures::getTypicalVerb(), ActivityFixtures::getTypicalActivity(), null, ActorFixtures::getTypicalGroup());
    }

    public static function getAllPropertiesStatement($id = self::DEFAULT_STATEMENT_ID)
    {
        if (null === $id) {
            $id = UuidFixtures::getUniqueUuid();
        }

        return new Statement(
            StatementId::fromString($id),
            ActorFixtures::getTypicalAgent(),
            VerbFixtures::getTypicalVerb(),
            ActivityFixtures::getTypicalActivity(),
            ResultFixtures::getAllPropertiesResult(),
            ActorFixtures::getAccountAgent(),
            new \DateTime('2013-05-18T05:32:34+00:00'),
            new \DateTime('2014-07-23T12:34:02-05:00'),
            ContextFixtures::getAllPropertiesContext(),
            array(AttachmentFixtures::getTextAttachment())
        );
    }

    /**
     * @return Statement[]
     */
    public static function getStatementCollection()
    {
        return array(
            self::getMinimalStatement('12345678-1234-5678-8234-567812345678'),
            self::getMinimalStatement('12345678-1234-5678-8234-567812345679'),
        );
    }
}


<?php

/*
 * This file is part of the Wid'op package.
 *
 * (c) Wid'op <contact@widop.com>
 *
 * For the full copyright and license information, please read the LICENSE
 * file that was distributed with this source code.
 */

namespace Widop\Twitter\Options;

/**
 * Abstract datetime option.
 *
 * @author Geoffrey Brier <geoffrey.brier@gmail.com>
 */
abstract class AbstractDateTimeOption extends AbstractOption
{
    /**
     * {@inheritdoc}
     */
    public function setValue($value)
    {
        if (is_string($value)) {
            try {
               $value = new \DateTime($value);
            } catch (\Exception $e) {
                throw new \InvalidArgumentException($e->getMessage());
            }
        }

        if (!($value instanceof \DateTime) && ($value !== null)) {
            throw new \InvalidArgumentException(sprintf(
                'The option "%s" only accepts \DateTime objects or strings.',
                $this->getName()
            ));
        }

        parent::setValue($value);
    }

    /**
     * {@inheritdoc}
     */
    public function getNormalizedValue()
    {
        return $this->getValue()->format('Y-m-d');
    }
}


<?php
declare(strict_types = 1);

namespace Innmind\Http\Message\Files;

use Innmind\Http\{
    Message\Files as FilesInterface,
    File,
    Exception\FileNotFound
};
use Innmind\Immutable\{
    MapInterface,
    Map,
    Sequence
};

final class Files implements FilesInterface
{
    private $files;

    public function __construct(MapInterface $files = null)
    {
        $files = $files ?? new Map('string', File::class);

        if (
            (string) $files->keyType() !== 'string' ||
            (string) $files->valueType() !== File::class
        ) {
            throw new \TypeError(sprintf(
                'Argument 1 must be of type MapInterface<string, %s>',
                File::class
            ));
        }

        $this->files = $files;
    }

    public static function of(File ...$files): self
    {
        return new self(
            Sequence::of(...$files)->reduce(
                new Map('string', File::class),
                static function(MapInterface $files, File $file): MapInterface {
                    return $files->put(
                        (string) $file->name(),
                        $file
                    );
                }
            )
        );
    }

    /**
     * {@inheritdoc}
     */
    public function get(string $name): File
    {
        if (!$this->has($name)) {
            throw new FileNotFound;
        }

        return $this->files->get($name);
    }

    /**
     * {@inheritdoc}
     */
    public function has(string $name): bool
    {
        return $this->files->contains($name);
    }

    /**
     * {@inheritdoc}
     */
    public function current()
    {
        return $this->files->current();
    }

    /**
     * {@inheritdoc}
     */
    public function key()
    {
        return $this->files->key();
    }

    /**
     * {@inheritdoc}
     */
    public function next()
    {
        $this->files->next();
    }

    /**
     * {@inheritdoc}
     */
    public function rewind()
    {
        $this->files->rewind();
    }

    /**
     * {@inheritdoc}
     */
    public function valid()
    {
        return $this->files->valid();
    }

    /**
     * {@inheritdoc}
     */
    public function count()
    {
        return $this->files->size();
    }
}


<?php
declare(strict_types = 1);

namespace Innmind\Http\Bridge\Psr7;

use Innmind\Http\Exception\LogicException;
use Innmind\Stream\{
    Readable,
    Stream as StreamInterface,
    Stream\Position,
    Stream\Position\Mode,
    Stream\Size
};
use Innmind\Immutable\Str;
use Psr\Http\Message\StreamInterface as PsrStream;

final class Stream implements Readable
{
    private $stream;
    private $closed = false;

    public function __construct(PsrStream $stream)
    {
        $this->stream = $stream;
    }

    public function close(): StreamInterface
    {
        $this->stream->close();
        $this->closed = true;

        return $this;
    }

    public function closed(): bool
    {
        return $this->closed;
    }

    public function position(): Position
    {
        return new Position($this->stream->tell());
    }

    public function seek(Position $position, Mode $mode = null): StreamInterface
    {
        $this->stream->seek($position->toInt(), $mode ? $mode->toInt() : null);

        return $this;
    }

    public function rewind(): StreamInterface
    {
        $this->stream->rewind();

        return $this;
    }

    public function end(): bool
    {
        return $this->stream->eof();
    }

    public function size(): Size
    {
        return new Size($this->stream->getSize());
    }

    public function knowsSize(): bool
    {
        return is_int($this->stream->getSize());
    }

    /**
     * {@inheritdoc}
     */
    public function read(int $length = null): Str
    {
        if (is_null($length)) {
            return new Str($this->stream->getContents());
        }

        return new Str($this->stream->read($length));
    }

    public function readLine(): Str
    {
        throw new LogicException('not implemented');
    }

    public function __toString(): string
    {
        return (string) $this->stream;
    }
}


<?php

namespace Igorwanbarros\Php2Html\Menu;

use Igorwanbarros\Php2Html\ViewAbstract;

/**
 * Class MenuView
 * @package Igorwanbarros\Php2Html\Menu
 */
class MenuView extends ViewAbstract
{

    /**
     * @var string
     */
    protected $template     = 'templates/%s/menu.php';

    /**
     * @var array
     */
    protected $itensMenu    = [];

    /**
     * @return array
     */
    public function getVars()
    {
        return array('menu' => $this);
    }

    /**
     * @return array
     */
    public function getItensMenu()
    {
        return $this->itensMenu;
    }

    /**
     * @param string        $itemName
     * @param ItemMenu      $itemMenu
     *
     * @return $this
     */
    public function addItemMenu($itemName, ItemMenu $itemMenu)
    {
        $this->itensMenu[$itemName] = $itemMenu;

        return $this;
    }

    /**
     * @param $itemName
     *
     * @return $this
     */
    public function removeItemMenu($itemName)
    {
        if (is_array($itemName)) {
            foreach ($itemName as $item) {
                $this->removeItemMenu($item);
            }

            return $this;
        }

        if (is_scalar($itemName) && array_key_exists($itemName, $this->itensMenu)) {
            unset($this->itensMenu[$itemName]);
        }

        return $this;
    }

    /**
     * @return $this
     */
    public function clearItens()
    {
        $this->itensMenu = [];

        return $this;
    }

    /**
     * @param string   $subNivelName
     * @param ItemMenu $itemMenu
     *
     * @return $this
     */
    public function createSubNivel($subNivelName, ItemMenu $itemMenu)
    {
        $this->_setDotNotation($this->itensMenu, $subNivelName, [$itemMenu]);

        return $this;
    }

    /**
     * @param array     $array
     * @param string    $string
     * @param string    $value
     *
     * @return array
     */
    protected function _setDotNotation(array &$array, $string, $value)
    {
        $niveis = explode('.', $string);

        foreach ($niveis as $nivel)
            $array = &$array[$nivel];

        $array = $value;
        return $array;
    }

    /**
     * @param string    $subNivelName
     * @param string    $itemName
     * @param ItemMenu  $itemMenu
     *
     * @return $this
     */
    public function addItemSubNivel($subNivelName, $itemName, ItemMenu $itemMenu)
    {
        $this->_setDotNotation($this->itensMenu, $subNivelName . '.' . $itemName, $itemMenu);

        return $this;
    }

    /**
     * @param $itemName
     *
     * @return string
     */
    public function hasItemMenu($itemName)
    {
        return array_key_exists($itemName, $this->itensMenu) ? true : false;
    }

    /**
     * @return $this
     */
    public function clearItensMenu()
    {
        $this->itensMenu = [];
        return $this;
    }
}


<?php
/*
 * Copyright (c) 2012-2016, Hofmänner New Media.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This file is part of the N2N FRAMEWORK.
 *
 * The N2N FRAMEWORK is free software: you can redistribute it and/or modify it under the terms of
 * the GNU Lesser General Public License as published by the Free Software Foundation, either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * N2N is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
 * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU Lesser General Public License for more details: http://www.gnu.org/licenses/
 *
 * The following people participated in this project:
 *
 * Andreas von Burg.....: Architect, Lead Developer
 * Bert Hofmänner.......: Idea, Frontend UI, Community Leader, Marketing
 * Thomas Günther.......: Developer, Hangar
 */
namespace n2n\impl\persistence\orm\property;

use n2n\impl\persistence\orm\property\relation\Relation;
use n2n\util\ex\IllegalStateException;
use n2n\reflection\property\AccessProxy;
use n2n\util\type\ArgUtils;
use n2n\impl\persistence\orm\property\relation\MasterRelation;
use n2n\impl\persistence\orm\property\relation\MappedRelation;
use n2n\persistence\orm\query\from\MetaTreePoint;
use n2n\persistence\orm\query\QueryState;
use n2n\persistence\orm\property\CascadableEntityProperty;
use n2n\persistence\orm\store\action\PersistAction;
use n2n\persistence\orm\store\action\RemoveAction;
use n2n\persistence\orm\query\from\meta\TreePointMeta;
use n2n\persistence\orm\store\action\supply\SupplyJob;
use n2n\persistence\orm\EntityManager;
use n2n\persistence\orm\model\EntityModel;
use n2n\persistence\orm\store\ValueHash;
use n2n\persistence\orm\criteria\JoinType;

abstract class RelationEntityPropertyAdapter extends EntityPropertyAdapter implements RelationEntityProperty,
		CascadableEntityProperty {
	protected $master;
	protected $type;
	protected $relation;

	public function __construct(AccessProxy $accessProxy, bool $master, string $type) {
		parent::__construct($accessProxy);
		$this->master = $master;
		$this->type = $type;
	}

	public function getType(): string {
		return $this->type;
	}

	public function isMaster(): bool {
		return $this->master;
	}

	public function isToMany(): bool {
		return $this->type == self::TYPE_ONE_TO_MANY || $this->type == self::TYPE_MANY_TO_MANY;
	}

	public function copy($value) {
		return $value;
	}

	/* (non-PHPdoc)
	 * @see n2n\persistence\orm\property.RelationEntityProperty::getRelation()
	 */
	public function getRelation(): Relation {
		if ($this->relation === null) {
			throw new IllegalStateException('No relation assigned for ' . $this->__toString());
		}

		return $this->relation;
	}

	protected function assignRelation(Relation $relation) {
		if ($this->master) {
			ArgUtils::assertTrue($relation instanceof MasterRelation);
		} else {
			ArgUtils::assertTrue($relation instanceof MappedRelation);
		}

		$this->relation = $relation;
	}
	/* (non-PHPdoc)
	 * @see \n2n\persistence\orm\property\EntityProperty::createSelection()
	 */
	public function createSelection(MetaTreePoint $metaTreePoint, QueryState $queryState) {
		return $this->getRelation()->createSelection($metaTreePoint, $queryState);
	}
	/* (non-PHPdoc)
	 * @see \n2n\persistence\orm\property\JoinableEntityProperty::createJoinTreePoint()
	 */
	public function createJoinTreePoint(TreePointMeta $treePointMeta, QueryState $queryState) {
		return $this->getRelation()->createJoinTreePoint($treePointMeta, $queryState);
	}

	/**
	 * {@inheritDoc}
	 * @see \n2n\persistence\orm\property\CascadableEntityProperty::prepareSupplyJob()
	 */
	public function prepareSupplyJob(SupplyJob $supplyJob, $value, ?ValueHash $oldValueHash) {
		$this->getRelation()->prepareSupplyJob($supplyJob, $value, $oldValueHash);
	}

	/**
	 * {@inheritDoc}
	 * @see \n2n\persistence\orm\property\EntityProperty::supplyPersistAction()
	 */
	public function supplyPersistAction(PersistAction $persistAction, $value, ValueHash $valueHash, ?ValueHash $oldValueHash) {
		$this->getRelation()->supplyPersistAction($persistAction, $value, $valueHash, $oldValueHash);
	}

	/**
	 * {@inheritDoc}
	 * @see \n2n\persistence\orm\property\EntityProperty::supplyRemoveAction()
	 */
	public function supplyRemoveAction(RemoveAction $removeAction, $value, ValueHash $oldValueHash) {
		$this->getRelation()->supplyRemoveAction($removeAction, $value, $oldValueHash);
	}

	/**
	 * {@inheritDoc}
	 * @see \n2n\persistence\orm\property\EntityProperty::createValueHash()
	 */
	public function createValueHash($value, EntityManager $em): ValueHash {
		return $this->getRelation()->createValueHash($value, $em);
	}

	public function hasTargetEntityModel(): bool {
		return true;
	}

	public function getTargetEntityModel(): EntityModel {
		return $this->getRelation()->getTargetEntityModel();
	}

	/**
	 * {@inheritDoc}
	 * @see \n2n\persistence\orm\property\JoinableEntityProperty::getAvailableJoinTypes()
	 */
	public function getAvailableJoinTypes(): array {
		return JoinType::getValues();
	}
}


<?php
/*
 * Copyright (c) 2012-2016, Hofmänner New Media.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This file is part of the N2N FRAMEWORK.
 *
 * The N2N FRAMEWORK is free software: you can redistribute it and/or modify it under the terms of
 * the GNU Lesser General Public License as published by the Free Software Foundation, either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * N2N is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
 * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU Lesser General Public License for more details: http://www.gnu.org/licenses/
 *
 * The following people participated in this project:
 *
 * Andreas von Burg.....: Architect, Lead Developer
 * Bert Hofmänner.......: Idea, Frontend UI, Community Leader, Marketing
 * Thomas Günther.......: Developer, Hangar
 */
namespace n2n\impl\persistence\orm\property\relation\compare;

use n2n\persistence\orm\criteria\compare\ColumnComparable;
use n2n\persistence\orm\model\EntityModel;
use n2n\util\type\TypeConstraint;
use n2n\persistence\orm\criteria\compare\CriteriaComparator;
use n2n\util\type\ArgUtils;

class IdColumnComparableDecorator implements ColumnComparable {
	private $idColumnComparable;
	private $entityModel;
	private $idEntityProperty;

	public function __construct(ColumnComparable $idColumnComparable, EntityModel $entityModel) {
		$this->idColumnComparable = $idColumnComparable;
		$this->entityModel = $entityModel;
		$this->idEntityProperty = $entityModel->getIdDef()->getEntityProperty();
	}
	/* (non-PHPdoc)
	 * @see \n2n\persistence\orm\criteria\compare\ColumnComparable::getAvailableOperators()
	 */
	public function getAvailableOperators() {
		return $this->idColumnComparable->getAvailableOperators();
	}
	/* (non-PHPdoc)
	 * @see \n2n\persistence\orm\criteria\compare\ColumnComparable::getTypeConstraint()
	 */
	public function getTypeConstraint($operator) {
		return TypeConstraint::createSimple($this->entityModel->getClass()->getName());
	}
	/* (non-PHPdoc)
	 * @see \n2n\persistence\orm\criteria\compare\ColumnComparable::isSelectable()
	 */
	public function isSelectable($operator) {
		return $this->idColumnComparable->isSelectable($operator);
	}
	/* (non-PHPdoc)
	 * @see \n2n\persistence\orm\criteria\compare\ColumnComparable::buildQueryItem($operator)
	 */
	public function buildQueryItem($operator) {
		return $this->idColumnComparable->buildQueryItem($operator);
	}
	/* (non-PHPdoc)
	 * @see \n2n\persistence\orm\criteria\compare\ColumnComparable::buildCounterpartQueryItemFromValue()
	 */
	public function buildCounterpartQueryItemFromValue($operator, $value) {
		return $this->idColumnComparable->buildCounterpartQueryItemFromValue($operator,
				$this->parseComparableValue($operator, $value));
	}

	private function parseComparableValue($operator, $value) {
		if ($operator !== CriteriaComparator::OPERATOR_IN
				&& $operator !== CriteriaComparator::OPERATOR_NOT_IN) {
			return $this->parseFieldValue($value);
		}

		ArgUtils::valArrayLike($value, 'object');
		$idValues = array();
		foreach ($value as $key => $fieldValue) {
			$idValues[$key] = $this->parseFieldValue($fieldValue);
		}
		return $idValues;
	}

	private function parseFieldValue($value) {
		if ($value === null) return null;

		ArgUtils::assertTrue(is_object($value));
		return $this->idEntityProperty->readValue($value);
	}
}


<?php
/*
 * Copyright (c) 2012-2016, Hofmänner New Media.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This file is part of the N2N FRAMEWORK.
 *
 * The N2N FRAMEWORK is free software: you can redistribute it and/or modify it under the terms of
 * the GNU Lesser General Public License as published by the Free Software Foundation, either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * N2N is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
 * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU Lesser General Public License for more details: http://www.gnu.org/licenses/
 *
 * The following people participated in this project:
 *
 * Andreas von Burg.....: Architect, Lead Developer
 * Bert Hofmänner.......: Idea, Frontend UI, Community Leader, Marketing
 * Thomas Günther.......: Developer, Hangar
 */
namespace n2n\impl\persistence\orm\property\relation;

use n2n\persistence\orm\query\QueryState;
use n2n\persistence\orm\query\from\MetaTreePoint;
use n2n\impl\persistence\orm\property\relation\tree\JoinColumnTreePoint;
use n2n\persistence\orm\FetchType;
use n2n\impl\persistence\orm\property\relation\selection\ToOneRelationSelection;
use n2n\impl\persistence\orm\property\relation\selection\JoinColumnToManyLoader;
use n2n\persistence\orm\store\SimpleLoaderUtils;
use n2n\persistence\orm\store\action\PersistAction;
use n2n\persistence\orm\store\action\RemoveAction;
use n2n\persistence\orm\query\from\meta\TreePointMeta;
use n2n\impl\persistence\orm\property\relation\util\ToOneValueHasher;
use n2n\impl\persistence\orm\property\relation\compare\InverseJoinColumnToManyQueryItemFactory;
use n2n\impl\persistence\orm\property\relation\compare\IdColumnComparableDecorator;
use n2n\persistence\orm\property\EntityProperty;
use n2n\persistence\orm\model\EntityModel;
use n2n\persistence\orm\model\ActionDependency;
use n2n\impl\persistence\orm\property\relation\util\JoinColumnResetAction;
use n2n\persistence\orm\store\action\supply\SupplyJob;
use n2n\persistence\orm\EntityManager;
use n2n\persistence\orm\store\ValueHash;
use n2n\impl\persistence\orm\property\relation\util\ToOneUtils;
use n2n\persistence\orm\store\PersistenceOperationException;
use n2n\persistence\orm\store\EntityInfo;
use n2n\util\type\ArgUtils;
use n2n\impl\persistence\orm\property\relation\util\ToOneValueHash;

class JoinColumnToOneRelation extends MasterRelation implements ToOneRelation, ActionDependency {
	private $joinColumnName;
	private $toOneUtils;

	public function __construct(EntityProperty $entityProperty, EntityModel $targetEntityModel) {
		parent::__construct($entityProperty, $targetEntityModel);
		$targetEntityModel->registerActionDependency($this);

		$this->toOneUtils = new ToOneUtils($this, true);
	}

	public function setJoinColumnName($joinColumnName) {
		$this->joinColumnName = $joinColumnName;
	}

	public function getJoinColumnName() {
		return $this->joinColumnName;
	}

	public function createJoinTreePoint(TreePointMeta $treePointMeta, QueryState $queryState) {
		$joinColumn = $treePointMeta->registerColumn($this->entityModel,
				$this->joinColumnName);

		$targetTreePointMeta = $this->targetEntityModel->createTreePointMeta($queryState);
		$targetIdColumn = $this->targetEntityModel->getIdDef()->getEntityProperty()
				->createQueryColumn($targetTreePointMeta);

		$treePoint = new JoinColumnTreePoint($queryState, $targetTreePointMeta);
		$treePoint->setJoinColumn($joinColumn);
		$treePoint->setTargetJoinColumn($targetIdColumn);
		return $treePoint;
	}
	/* (non-PHPdoc)
	 * @see \n2n\impl\persistence\orm\property\relation\MasterRelation::createInverseJoinTreePoint()
	 */
	public function createInverseJoinTreePoint(EntityModel $entityModel, TreePointMeta $targetTreePointMeta, QueryState $queryState) {
		$treePointMeta = $entityModel->createTreePointMeta($queryState);
		$joinColumn = $treePointMeta->registerColumn($this->entityModel, $this->joinColumnName);

		$targetIdColumn = $this->targetEntityModel->getIdDef()->getEntityProperty()
				->createQueryColumn($targetTreePointMeta);

		$treePoint = new JoinColumnTreePoint($queryState, $treePointMeta);
		$treePoint->setJoinColumn($targetIdColumn);
		$treePoint->setTargetJoinColumn($joinColumn);
		return $treePoint;
	}
	/* (non-PHPdoc)
	 * @see \n2n\impl\persistence\orm\property\relation\Relation::createColumnComparable()
	 */
	public function createColumnComparable(MetaTreePoint $metaTreePoint, QueryState $queryState) {
		$meta = $metaTreePoint->getMeta();
		$targetIdProperty = $this->targetEntityModel->getIdDef()->getEntityProperty();

		return new IdColumnComparableDecorator(
				$targetIdProperty->createColumnComparableFromQueryItem(
						$meta->registerColumn($this->entityModel, $this->joinColumnName), $queryState),
				$this->targetEntityModel);
	}
	/* (non-PHPdoc)
	 * @see \n2n\impl\persistence\orm\property\relation\ToOneRelation::createRepresentingQueryItem()
	 */
	public function createRepresentingQueryItem(MetaTreePoint $metaTreePoint, QueryState $queryState) {
		return $metaTreePoint->getMeta()->registerColumn($this->entityModel, $this->joinColumnName);
	}
	/* (non-PHPdoc)
	 * @see \n2n\impl\persistence\orm\property\relation\Relation::createSelection()
	 */
	public function createSelection(MetaTreePoint $metaTreePoint, QueryState $queryState) {
		$targetIdProperty = $this->targetEntityModel->getIdDef()->getEntityProperty();
		$idSelection = $targetIdProperty->createSelectionFromQueryItem($metaTreePoint->getMeta()
				->registerColumn($this->entityModel, $this->joinColumnName), $queryState);

		$toOneRelationSelection = new ToOneRelationSelection($this->targetEntityModel, $idSelection, $queryState);
		$toOneRelationSelection->setLazy($this->fetchType == FetchType::LAZY);
		return $toOneRelationSelection;
	}
	/* (non-PHPdoc)
	 * @see \n2n\impl\persistence\orm\property\relation\MasterRelation::createInverseToManyLoader()
	 */
	public function createInverseToManyLoader(EntityModel $entityModel, QueryState $queryState) {
		return new JoinColumnToManyLoader(
				new SimpleLoaderUtils($queryState->getEntityManager(), $entityModel),
				$this->targetEntityModel->getIdDef()->getEntityProperty(), $this->joinColumnName);
	}

	public function prepareSupplyJob(SupplyJob $supplyJob, $value, ?ValueHash $oldValueHash) {
		$this->toOneUtils->prepareSupplyJob($supplyJob, $value, $oldValueHash);
	}
	/* (non-PHPdoc)
	 * @see \n2n\impl\persistence\orm\property\relation\Relation::supplyPersistAction()
	 */
	public function supplyPersistAction(PersistAction $persistAction, $value, ValueHash $valueHash,
				?ValueHash $oldValueHash) {
		if ($value === null) {
			$persistAction->getMeta()->setRawValue($this->entityModel, $this->joinColumnName, null);
			return;
		}

		$actionQueue = $persistAction->getActionQueue();
		$pdo = $actionQueue->getEntityManager()->getPdo();
		$targetPersistAction = $persistAction->getActionQueue()->getPersistAction($value);

		try {
			$targetPersistAction = $persistAction->getActionQueue()->getPersistAction($value);
		} catch (PersistenceOperationException $e) {
			throw new PersistenceOperationException($this->entityProperty->toPropertyString() . ' of entity obj '
				. EntityInfo::buildEntityString($persistAction->getEntityModel(), $persistAction->getId())
				. ' contains value that can not be persisted.', 0, $e, 3);
		}

		if ($targetPersistAction->hasId()) {
			$persistAction->getMeta()->setRawValue($this->entityModel, $this->joinColumnName,
					$this->getTargetIdEntityProperty()->buildRaw($targetPersistAction->getId(), $pdo));
			return;
		}

		$persistAction->addDependent($targetPersistAction);

		ArgUtils::assertTrue($valueHash instanceof ToOneValueHash);
		$targetPersistAction->executeAtEnd(function () use ($persistAction, $valueHash, $targetPersistAction, $pdo) {
			$targetId = $targetPersistAction->getId();

			$persistAction->getMeta()->setRawValue($this->entityModel, $this->joinColumnName,
					$this->getTargetIdEntityProperty()->buildRaw($targetId, $pdo));

			$hasher = new ToOneValueHasher($this->getTargetIdEntityProperty());
			$hasher->reportId($targetId, $valueHash);
		});
	}
// 	/* (non-PHPdoc)
// 	 * @see \n2n\impl\persistence\orm\property\relation\Relation::supplyRemoveAction()
// 	 */
// 	public function supplyRemoveAction($value, $valueHash, RemoveAction $removeAction) {

// 	}

// 	public function supplyInverseToManyRemoveAction($targetValue, $targetValueHash, RemoveAction $targetRemoveAction) {
// 		$actionQueue = $targetRemoveAction->getActionQueue();
// 		$pdo = $actionQueue->getEntityManager()->getPdo();
// 		$persistenceContext = $actionQueue->getEntityManager()->getPersistenceContext();
// 		$idProperty = $this->entityModel->getIdDef()->getEntityProperty;

// 		foreach (ToManyValueHasher::extractIdReps($targetValueHash) as $idRep) {
// 			$entity = $persistenceContext->getEntityByIdRep($this->entityModel, $idRep);
// 			if ($persistenceContext->containsRemovedEntity($entity)) continue;

// 			$persistActionMeta = $actionQueue->getOrCreatePersistAction($entity)->getMeta();
// 			if (!$persistActionMeta->containsRawValue($this->entityModel, $this->joinColumnName)) {
// 				$persistActionMeta->setRawValue($this->entityModel, $this->joinColumnName,
// 						$idProperty->buildRaw($idProperty->repToValue($idRep), $pdo));
// 			}
// 		}
// 	}

// 	public function supplyInverseToOneRemoveAction($targetValue, $targetValueHash, RemoveAction $targetRemoveAction) {
// 		if ($targetValueHash === null) return;

// 		$actionQueue = $targetRemoveAction->getActionQueue();
// 		$persistenceContext = $actionQueue->getEntityManager()->getPersistenceContext();

// 		$entity = $persistenceContext->getEntityByIdRep($this->entityModel, $targetValueHash);
// 		if ($persistenceContext->containsRemovedEntity($entity)) return;

// 		$persistActionMeta = $actionQueue->getOrCreatePersistAction($entity)->getMeta();
// 		if (!$persistActionMeta->containsRawValue($this->entityModel, $this->joinColumnName)) {
// 			$idProperty = $this->entityModel->getIdDef()->getEntityProperty();
// 			$pdo = $actionQueue->getEntityManager()->getPdo();
// 			$persistActionMeta->setRawValue($this->entityModel, $this->joinColumnName,
// 					$idProperty->buildRaw($idProperty->repToValue($targetValueHash), $pdo));
// 		}
// 	}

	public function createValueHash($value, EntityManager $em): ValueHash {
		return ToOneValueHasher::createFromEntityModel($this->targetEntityModel)
				->createValueHash($value);
	}

	public function createInverseJoinTableToManyQueryItemFactory(EntityModel $entityModel) {
		return new InverseJoinColumnToManyQueryItemFactory($entityModel, $this->joinColumnName);
	}
	/* (non-PHPdoc)
	 * @see \n2n\persistence\orm\model\ActionDependency::persistActionSupplied()
	 */
	public function persistActionSupplied(PersistAction $targetPersistAction) {

	}

	private function markRemoveAction(RemoveAction $removeAction) {
		$removeAction->setAttribute(get_class($this), true);
	}

	private function isRemoveActionMarked(RemoveAction $removeAction) {
		return (boolean) $removeAction->getAttribute(get_class($this));
	}
	/* (non-PHPdoc)
	 * @see \n2n\persistence\orm\model\ActionDependency::removeActionSupplied()
	 */
	public function removeActionSupplied(RemoveAction $targetRemoveAction) {
		if ($this->actionMarker->isConstraintReleased($targetRemoveAction)) return;

		$actionQueue = $targetRemoveAction->getActionQueue();
		$pdo = $actionQueue->getEntityManager()->getPdo();
		$idRaw = $this->getTargetIdEntityProperty()->buildRaw($targetRemoveAction->getId(), $pdo);

		$resetAction = new JoinColumnResetAction($pdo,
				$this->entityModel->getTableName(), $this->joinColumnName);
		$resetAction->setJoinIdRaw($idRaw);

		$targetRemoveAction->executeAtEnd(function ($actionQueue, $resetAction) {
			$actionQueue->add($resetAction);
		});
	}
}


<?php

/*
 * This file is part of the Wid'op package.
 *
 * (c) Wid'op <contact@widop.com>
 *
 * For the full copyright and license information, please read the LICENSE
 * file that was distributed with this source code.
 */

namespace Widop\Twitter\Options;

use Widop\Twitter\Options\OptionInterface;

/**
 * Option factory.
 *
 * @author GeLo <geloen.eric@gmail.com>
 */
class OptionFactory
{
    /** @var array */
    private $mapping;

    /**
     * Creates an option factory.
     */
    public function __construct()
    {
        $this->mapping = array(
            'accuracy'                     => 'Widop\Twitter\Options\AccuracyOption',
            'align'                        => 'Widop\Twitter\Options\AlignOption',
            'attribute:street_address'     => 'Widop\Twitter\Options\AttributeStreetAddressOption',
            'banner'                       => 'Widop\Twitter\Options\BannerOption',
            'contributor_details'          => 'Widop\Twitter\Options\ContributorDetailsOption',
            'callback'                     => 'Widop\Twitter\Options\CallbackOption',
            'contained_within'             => 'Widop\Twitter\Options\ContainedWithinOption',
            'count'                        => 'Widop\Twitter\Options\CountOption',
            'cursor'                       => 'Widop\Twitter\Options\CursorOption',
            'delimited'                    => 'Widop\Twitter\Options\DelimitedOption',
            'description'                  => 'Widop\Twitter\Options\DescriptionOption',
            'device'                       => 'Widop\Twitter\Options\DeviceOption',
            'device_notification'          => 'Widop\Twitter\Options\DeviceNotificationOption',
            'display_coordinates'          => 'Widop\Twitter\Options\DisplayCoordinatesOption',
            'end_sleep_time'               => 'Widop\Twitter\Options\EndSleepTimeOption',
            'exclude'                      => 'Widop\Twitter\Options\ExcludeOption',
            'exclude_replies'              => 'Widop\Twitter\Options\ExcludeRepliesOption',
            'filter_to_owned_lists'        => 'Widop\Twitter\Options\FilterToOwnedListsOption',
            'follow'                       => 'Widop\Twitter\Options\FollowOption',
            'geocode'                      => 'Widop\Twitter\Options\GeocodeOption',
            'granularity'                  => 'Widop\Twitter\Options\GranularityOption',
            'height'                       => 'Widop\Twitter\Options\HeightOption',
            'hide_media'                   => 'Widop\Twitter\Options\HideMediaOption',
            'hide_thread'                  => 'Widop\Twitter\Options\HideThreadOption',
            'id'                           => 'Widop\Twitter\Options\IdOption',
            'image'                        => 'Widop\Twitter\Options\ImageOption',
            'in_reply_to_status_id'        => 'Widop\Twitter\Options\InReplyToStatusIdOption',
            'include_entities'             => 'Widop\Twitter\Options\IncludeEntitiesOption',
            'include_my_retweet'           => 'Widop\Twitter\Options\IncludeMyRetweetOption',
            'include_rts'                  => 'Widop\Twitter\Options\IncludeRtsOption',
            'include_user_entities'        => 'Widop\Twitter\Options\IncludeUserEntitiesOption',
            'ip'                           => 'Widop\Twitter\Options\IpOption',
            'lang'                         => 'Widop\Twitter\Options\LangOption',
            'lat'                          => 'Widop\Twitter\Options\LatOption',
            'list_id'                      => 'Widop\Twitter\Options\ListIdOption',
            'locale'                       => 'Widop\Twitter\Options\LocaleOption',
            'location'                     => 'Widop\Twitter\Options\LocationOption',
            'locations'                    => 'Widop\Twitter\Options\LocationsOption',
            'long'                         => 'Widop\Twitter\Options\LongOption',
            'max_id'                       => 'Widop\Twitter\Options\MaxIdOption',
            'max_results'                  => 'Widop\Twitter\Options\MaxResultsOption',
            'maxwidth'                     => 'Widop\Twitter\Options\MaxwidthOption',
            'media'                        => 'Widop\Twitter\Options\MediaOption',
            'mode'                         => 'Widop\Twitter\Options\ModeOption',
            'name'                         => 'Widop\Twitter\Options\NameOption',
            'offset_left'                  => 'Widop\Twitter\Options\OffsetLeftOption',
            'offset_top'                   => 'Widop\Twitter\Options\OffsetTopOption',
            'omit_script'                  => 'Widop\Twitter\Options\OmitScriptOption',
            'owner_id'                     => 'Widop\Twitter\Options\OwnerIdOption',
            'owner_screen_name'            => 'Widop\Twitter\Options\OwnerScreenNameOption',
            'page'                         => 'Widop\Twitter\Options\PageOption',
            'place_id'                     => 'Widop\Twitter\Options\PlaceIdOption',
            'profile_background_color'     => 'Widop\Twitter\Options\ProfileBackgroundColorOption',
            'profile_link_color'           => 'Widop\Twitter\Options\ProfileLinkColorOption',
            'profile_sidebar_border_color' => 'Widop\Twitter\Options\ProfileSidebarBorderColorOption',
            'profile_sidebar_fill_color'   => 'Widop\Twitter\Options\ProfileSidebarFillColorOption',
            'profile_text_color'           => 'Widop\Twitter\Options\ProfileTextColorOption',
            'q'                            => 'Widop\Twitter\Options\QOption',
            'query'                        => 'Widop\Twitter\Options\QueryOption',
            'related'                      => 'Widop\Twitter\Options\RelatedOption',
            'replies'                      => 'Widop\Twitter\Options\RepliesOption',
            'resources'                    => 'Widop\Twitter\Options\ResourcesOption',
            'result_type'                  => 'Widop\Twitter\Options\ResultTypeOption',
            'retweets'                     => 'Widop\Twitter\Options\RetweetsOption',
            'reverse'                      => 'Widop\Twitter\Options\ReverseOption',
            'screen_name'                  => 'Widop\Twitter\Options\ScreenNameOption',
            'since_id'                     => 'Widop\Twitter\Options\SinceIdOption',
            'skip_status'                  => 'Widop\Twitter\Options\SkipStatusOption',
            'sleep_time_enabled'           => 'Widop\Twitter\Options\SleepTimeEnabledOption',
            'slug'                         => 'Widop\Twitter\Options\SlugOption',
            'source_id'                    => 'Widop\Twitter\Options\SourceIdOption',
            'source_screen_name'           => 'Widop\Twitter\Options\SourceScreenNameOption',
            'stall_warnings'               => 'Widop\Twitter\Options\StallWarningsOption',
            'start_sleep_time'             => 'Widop\Twitter\Options\StartSleepTimeOption',
            'status'                       => 'Widop\Twitter\Options\StatusOption',
            'stream_id'                    => 'Widop\Twitter\Options\SteamIdOption',
            'stringify_friend_ids'         => 'Widop\Twitter\Options\StringifyFriendIdsOption',
            'stringify_ids'                => 'Widop\Twitter\Options\StringifyIdsOption',
            'target_id'                    => 'Widop\Twitter\Options\TargetIdOption',
            'target_screen_name'           => 'Widop\Twitter\Options\TargetScreenNameOption',
            'text'                         => 'Widop\Twitter\Options\TextOption',
            'tile'                         => 'Widop\Twitter\Options\TileOption',
            'time_zone'                    => 'Widop\Twitter\Options\TimeZoneOption',
            'track'                        => 'Widop\Twitter\Options\TrackOption',
            'trend_location_woeid'         => 'Widop\Twitter\Options\TrendLocationWoeidOption',
            'trim_user'                    => 'Widop\Twitter\Options\TrimUserOption',
            'until'                        => 'Widop\Twitter\Options\UntilOption',
            'url'                          => 'Widop\Twitter\Options\UrlOption',
            'use'                          => 'Widop\Twitter\Options\UseOption',
            'user_id'                      => 'Widop\Twitter\Options\UserIdOption',
            'width'                        => 'Widop\Twitter\Options\WidthOption',
            'with'                         => 'Widop\Twitter\Options\WithOption',
        );
    }

    /**
     * Creates an option.
     *
     * @param string $option The option name.
     * @param string $type   The option type.
     *
     * @throws \InvalidArgumentException If the option does not exist.
     *
     * @return \Widop\Twitter\Options\OptionInterface The option.
     */
    public function create($option, $type = OptionInterface::TYPE_GET)
    {
        if (!isset($this->mapping[$option])) {
            throw new \InvalidArgumentException(sprintf('The option "%s" does not exist.', $option));
        }

        return new $this->mapping[$option]($type);
    }
}


<?php

namespace Igorwanbarros\Php2Html\Breadcrumbs;

use Igorwanbarros\Php2Html\ViewAbstract;

/**
 * Class BreadcrumbsView
 * @package Igorwanbarros\Php2Html\Breadcrumbs
 */
class BreadcrumbsView extends ViewAbstract
{

    /**
     * @var string
     */
    protected $template = 'templates/%s/breadcrumbs.php';

    /**
     * @type array
     */
    protected $itens = [];

    /**
     * @type bool
     */
    protected $active = false;

    /**
     * @param array $itens
     */
    public function __construct(array $itens = [])
    {
        parent::__construct();
        $this->setItens($itens);
        $this->addAttribute('class', 'breadcrumb');
    }

    public function getVars()
    {
        return ['breadcrumbs' => $this];
    }

    /**
     * @return array
     */
    public function getItens()
    {
        return $this->itens;
    }

    /**
     * @param $itens
     *
     * @return $this
     */
    public function setItens(array $itens)
    {
        $this->itens = [];

        foreach ($itens as $url => $linkName) {
            $this->addItem($url, $linkName);
        }

        return $this;
    }

    public function addItem($url, $linkName)
    {
        $this->itens[$url] = $linkName;

        $this->active = $url;

        return $this;
    }

    /**
     * @return bool|string
     */
    public function getActive()
    {
        return $this->active;
    }

    /**
     * @param string $active
     *
     * @return $this
     */
    public function setActive($active)
    {
        $this->active = $active;

        return $this;
    }
}


<?php

/*
 * This file is part of the xAPI package.
 *
 * (c) Christian Flothmann <christian.flothmann@xabbuh.de>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Xabbuh\XApi\DataFixtures;

use Xabbuh\XApi\Model\Agent;
use Xabbuh\XApi\Model\InverseFunctionalIdentifier;
use Xabbuh\XApi\Model\IRI;
use Xabbuh\XApi\Model\IRL;
use Xabbuh\XApi\Model\LanguageMap;
use Xabbuh\XApi\Model\Statement;
use Xabbuh\XApi\Model\StatementId;
use Xabbuh\XApi\Model\StatementResult;
use Xabbuh\XApi\Model\Verb;

/**
 * Statement result fixtures.
 *
 * @author Christian Flothmann <christian.flothmann@xabbuh.de>
 */
class StatementResultFixtures
{
    /**
     * Loads a statement result.
     *
     * @param IRL $urlPath An optional URL path refering to more results
     *
     * @return StatementResult
     */
    public static function getStatementResult(IRL $urlPath = null)
    {
        $statement1 = StatementFixtures::getMinimalStatement();

        $verb = new Verb(IRI::fromString('http://adlnet.gov/expapi/verbs/deleted'), LanguageMap::create(array('en-US' => 'deleted')));
        $statement2 = new Statement(
            StatementId::fromString('12345678-1234-5678-8234-567812345679'),
            new Agent(InverseFunctionalIdentifier::withMbox(IRI::fromString('mailto:bob@example.com'))),
            $verb,
            $statement1->getObject()
        );

        $statementResult = new StatementResult(array($statement1, $statement2), $urlPath);

        return $statementResult;
    }

    /**
     * Loads a statement result including a more reference.
     *
     * @return StatementResult
     */
    public static function getStatementResultWithMore()
    {
        $statementResult = static::getStatementResult(IRL::fromString('/xapi/statements/more/b381d8eca64a61a42c7b9b4ecc2fabb6'));

        return $statementResult;
    }
}