Remg/GeneratorBundle

View on GitHub
Command/Helper/AssociationHelper.php

Summary

Maintainability
A
1 hr
Test Coverage
<?php

/**
 * This file is part of the RemgGeneratorBundle package.
 *
 * (c) Rémi Gardien <remi@gardien.biz>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Remg\GeneratorBundle\Command\Helper;

use Remg\GeneratorBundle\Model\Association;
use Remg\GeneratorBundle\Model\AssociationInterface;

/**
 * A helper to interact with the user to define an AssociationInterface.
 *
 * @author Rémi Gardien <remi@gardien.biz>
 */
class AssociationHelper extends MappingHelper implements AssociationHelperInterface
{
    /**
     * {@inheritdoc}
     */
    public function askAssociation(AssociationInterface $association)
    {
        $association
            ->setName($this->askName($association))
            ->setType($this->askType($association))
            ->setTargetEntity($this->askTargetEntity($association))
            ->setBidirectional($this->askIfBidirectional($association))
            ->setOwningSide($this->askIfOwningSide($association))
            ->setMappedBy($this->askMappedBy($association))
            ->setInversedBy($this->askInversedBy($association));

        return $association;
    }

    /**
     * Asks an association name.
     *
     * @param AssociationInterface $association The association being defined.
     *
     * @return string The answered name.
     */
    private function askName(AssociationInterface $association)
    {
        $validator = $this->validator;

        return $this->display->ask(
            'Association name',
            $association->getName(),
            function ($answer) use ($validator, $association) {
                if ($association->getName() && $answer === $association->getName()) {
                    return $answer;
                }

                return $validator->validateFieldName($association->getEntity(), $answer);
            }
        );
    }

    /**
     * Asks an association type.
     *
     * @param AssociationInterface $association The association being defined.
     *
     * @return string The answered type.
     */
    private function askType(AssociationInterface $association)
    {
        return $this->display->choice(
            'Association type',
            $association->getSupportedTypes(),
            $this->guesser->guessAssociationType($association)
        );
    }

    /**
     * Asks what is the target association of an association.
     *
     * @param AssociationInterface $association The association being defined.
     *
     * @return string The answered target entity.
     */
    private function askTargetEntity(AssociationInterface $association)
    {
        return $this->display->ask(
            'Target entity',
            $this->guesser->guessTargetEntity($association),
            [$this->validator, 'validateTargetEntity']
        );
    }

    /**
     * Asks whether an association is bidirectional.
     *
     * @param AssociationInterface $association The association being defined.
     *
     * @return bool Whether the association is bidirectonal.
     */
    private function askIfBidirectional(AssociationInterface $association)
    {
        return $this->display->confirm(
            'Bidirectional ?',
            $this->guesser->guessIfBidirectional($association)
        );
    }

    /**
     * Asks whether an association is on the owning side of the relation.
     *
     * This question can be answered with logic in some cases.
     * Such cases are:
     *     1. If the association is unidirectional.
     *     2. If the association type is OneToMany (always false).
     *     3. If the association type is ManyToOne (always true).
     *
     * @param AssociationInterface $association The association being defined.
     *
     * @return bool Whether the association is on the owning side of the relation.
     */
    private function askIfOwningSide(AssociationInterface $association)
    {
        if (false === $association->isBidirectional()) {
            return;
        } elseif (Association::ONE_TO_MANY === $association->getType()) {
            return false;
        } elseif (Association::MANY_TO_ONE === $association->getType()) {
            return true;
        }

        return $this->display->confirm(
            'Owning side ?',
            $this->guesser->guessIfOwningSide($association)
        );
    }

    /**
     * Asks an association inversedBy property.
     *
     * This question can be answered with logic in some cases.
     * Such cases are:
     *     1. If the association is unidirectional.
     *     2. If the association is on the inversed side of the relation.
     *
     * @param AssociationInterface $association The association being defined.
     *
     * @return string The answered inversedBy property.
     */
    private function askInversedBy(AssociationInterface $association)
    {
        if (!$association->isBidirectional() || !$association->isOwningSide()) {
            return;
        }

        $validator = $this->validator;

        return $this->display->ask(
            'Inversed by :',
            $this->guesser->guessInverseProperty($association),
            function ($answer) use ($validator, $association) {
                return $validator->validateFieldName($association->getEntity(), $answer);
            }
        );
    }

    /**
     * Asks an association mappedBy property.
     *
     * This question can be answered with logic in some cases.
     * Such cases are:
     *     1. If the association is unidirectional.
     *     2. If the association is on the owning side of the relation.
     *
     * @param AssociationInterface $association The association being defined.
     *
     * @return string The answered mappedBy property.
     */
    private function askMappedBy(AssociationInterface $association)
    {
        if (!$association->isBidirectional() || $association->isOwningSide()) {
            return;
        }

        $validator = $this->validator;

        return $this->display->ask(
            'Mapped by :',
            $this->guesser->guessInverseProperty($association),
            function ($answer) use ($validator, $association) {
                return $validator->validateFieldName($association->getEntity(), $answer);
            }
        );
    }
}