<commit_before><?php

namespace Oro\Bundle\ActivityBundle\Routing;

use Symfony\Component\Routing\Route;

use Oro\Component\Routing\Resolver\RouteCollectionAccessor;
use Oro\Component\Routing\Resolver\RouteOptionsResolverInterface;

use Oro\Bundle\ActivityBundle\EntityConfig\ActivityScope;
use Oro\Bundle\EntityBundle\ORM\EntityAliasResolver;
use Oro\Bundle\EntityConfigBundle\Config\ConfigInterface;
use Oro\Bundle\EntityConfigBundle\Provider\ConfigProvider;

class ActivityAssociationRouteOptionsResolver implements RouteOptionsResolverInterface
{
    const ACTIVITY_ATTRIBUTE = 'activity';
    const ACTIVITY_PLACEHOLDER = '{activity}';
    const ACTIVITY_ID_ATTRIBUTE = 'id';
    const ACTIVITY_ID_PLACEHOLDER = '{id}';
    const ENTITY_ATTRIBUTE = 'entity';
    const ENTITY_PLACEHOLDER = '{entity}';
    const ENTITY_ID_ATTRIBUTE = 'entityId';
    const ENTITY_ID_PLACEHOLDER = '{entityId}';

    /** @var ConfigProvider */
    protected $groupingConfigProvider;

    /** @var EntityAliasResolver */
    protected $entityAliasResolver;

    /**
     * @param ConfigProvider      $groupingConfigProvider
     * @param EntityAliasResolver $entityAliasResolver
     */
    public function __construct(ConfigProvider $groupingConfigProvider, EntityAliasResolver $entityAliasResolver)
    {
        $this->groupingConfigProvider = $groupingConfigProvider;
        $this->entityAliasResolver    = $entityAliasResolver;
    }

    /**
     * {@inheritdoc}
     */
    public function resolve(Route $route, RouteCollectionAccessor $routes)
    {
        if ($route->getOption('group') !== 'activity_association') {
            return;
        }

        if ($this->hasAttribute($route, self::ACTIVITY_PLACEHOLDER)) {
            $activities = array_map(
                function (ConfigInterface $config) {
                    // convert to entity alias
                    return $this->entityAliasResolver->getPluralAlias(
                        $config->getId()->getClassName()
                    );
                },
                $this->groupingConfigProvider->filter(
                    function (ConfigInterface $config) {
                        // filter activity entities
                        $groups = $config->get('groups');

                        return
                            !empty($groups)
                            && in_array(ActivityScope::GROUP_ACTIVITY, $groups, true);
                    }
                )
            );

            $this->adjustRoutes($route, $routes, $activities);

            $route->setRequirement(self::ACTIVITY_ATTRIBUTE, implode('|', $activities));
            $this->completeRouteRequirements($route);
        } elseif ($this->hasAttribute($route, self::ENTITY_PLACEHOLDER)) {
            $this->completeRouteRequirements($route);
        }
    }

    /**
     * @param Route                   $route
     * @param RouteCollectionAccessor $routes
     * @param string[]                $activities
     */
    protected function adjustRoutes(Route $route, RouteCollectionAccessor $routes, $activities)
    {
        $routeName = $routes->getName($route);

        foreach ($activities as $activity) {
            $existingRoute = $routes->getByPath(
                str_replace(self::ACTIVITY_PLACEHOLDER, $activity, $route->getPath()),
                $route->getMethods()
            );
            if ($existingRoute) {
                // move existing route before the current route
                $existingRouteName = $routes->getName($existingRoute);
                $routes->remove($existingRouteName);
                $routes->insert(
                    $existingRouteName,
                    $existingRoute,
                    $routeName,
                    true
                );
            } else {
                // add an additional strict route based on the base route and current activity
                $strictRoute = $routes->cloneRoute($route);
                $strictRoute->setPath(str_replace(self::ACTIVITY_PLACEHOLDER, $activity, $strictRoute->getPath()));
                $strictRoute->setDefault(self::ACTIVITY_ATTRIBUTE, $activity);
                $this->completeRouteRequirements($strictRoute);
                $routes->insert(
                    $routes->generateRouteName($routeName),
                    $strictRoute,
                    $routeName,
                    true
                );
            }
        }
    }

    /**
     * Adds not filled requirements for the given route
     *
     * @param Route $route
     */
    protected function completeRouteRequirements(Route $route)
    {
        if (null === $route->getRequirement(self::ACTIVITY_ID_ATTRIBUTE)
            && $this->hasAttribute($route, self::ACTIVITY_ID_PLACEHOLDER)
        ) {
            $route->setRequirement(self::ACTIVITY_ID_ATTRIBUTE, '\d+');
        }
        if (null === $route->getRequirement(self::ENTITY_ATTRIBUTE)
            && $this->hasAttribute($route, self::ENTITY_PLACEHOLDER)
        ) {
            $route->setRequirement(self::ENTITY_ATTRIBUTE, '\w+');
        }
        if (null === $route->getRequirement(self::ENTITY_ID_ATTRIBUTE)
            && $this->hasAttribute($route, self::ENTITY_ID_PLACEHOLDER)
        ) {
            $route->setRequirement(self::ENTITY_ID_ATTRIBUTE, '[^/]+');
        }
    }

    /**
     * Checks if a route has the given attribute
     *
     * @param Route  $route
     * @param string $placeholder
     *
     * @return bool
     */
    protected function hasAttribute(Route $route, $placeholder)
    {
        return false !== strpos($route->getPath(), $placeholder);
    }
}
<commit_msg>Fix activity API routing when no any activity entity - Fix error during Web installer failed by timeout: [2015-06-22 11:42:06] request.CRITICAL: Uncaught PHP Exception Symfony\Component\Config\Exception\FileLoaderLoadException: "Cannot import resource "." from "/home/bamboo/bamboo-agent-home/xml-data/build-dir/OEE-SEL-IT/app/config/routing.yml". (Routing requirement for "activity" cannot be empty.)" at /home/bamboo/bamboo-agent-home/xml-data/build-dir/OEE-SEL-IT/vendor/symfony/symfony/src/Symfony/Component/Config/Loader/FileLoader.php line 125 {"exception":"[object] (Symfony\\Component\\Config\\Exception\\FileLoaderLoadException: Cannot import resource \".\" from \"/home/bamboo/bamboo-agent-home/xml-data/build-dir/OEE-SEL-IT/app/config/routing.yml\". (Routing requirement for \"activity\" cannot be empty.) at /home/bamboo/bamboo-agent-home/xml-data/build-dir/OEE-SEL-IT/vendor/symfony/symfony/src/Symfony/Component/Config/Loader/FileLoader.php:125, InvalidArgumentException: Routing requirement for \"activity\" cannot be empty. at /home/bamboo/bamboo-agent-home/xml-data/build-dir/OEE-SEL-IT/vendor/symfony/symfony/src/Symfony/Component/Routing/Route.php:604)"} [] [2015-06-22 11:42:06] security.DEBUG: Invoked controller "FOS\RestBundle\Controller\ExceptionController::showAction". (SUB_REQUEST) [] []<commit_after><?php

namespace Oro\Bundle\ActivityBundle\Routing;

use Symfony\Component\Routing\Route;

use Oro\Component\Routing\Resolver\RouteCollectionAccessor;
use Oro\Component\Routing\Resolver\RouteOptionsResolverInterface;

use Oro\Bundle\ActivityBundle\EntityConfig\ActivityScope;
use Oro\Bundle\EntityBundle\ORM\EntityAliasResolver;
use Oro\Bundle\EntityConfigBundle\Config\ConfigInterface;
use Oro\Bundle\EntityConfigBundle\Provider\ConfigProvider;

class ActivityAssociationRouteOptionsResolver implements RouteOptionsResolverInterface
{
    const ACTIVITY_ATTRIBUTE = 'activity';
    const ACTIVITY_PLACEHOLDER = '{activity}';
    const ACTIVITY_ID_ATTRIBUTE = 'id';
    const ACTIVITY_ID_PLACEHOLDER = '{id}';
    const ENTITY_ATTRIBUTE = 'entity';
    const ENTITY_PLACEHOLDER = '{entity}';
    const ENTITY_ID_ATTRIBUTE = 'entityId';
    const ENTITY_ID_PLACEHOLDER = '{entityId}';

    /** @var ConfigProvider */
    protected $groupingConfigProvider;

    /** @var EntityAliasResolver */
    protected $entityAliasResolver;

    /**
     * @param ConfigProvider      $groupingConfigProvider
     * @param EntityAliasResolver $entityAliasResolver
     */
    public function __construct(ConfigProvider $groupingConfigProvider, EntityAliasResolver $entityAliasResolver)
    {
        $this->groupingConfigProvider = $groupingConfigProvider;
        $this->entityAliasResolver    = $entityAliasResolver;
    }

    /**
     * {@inheritdoc}
     */
    public function resolve(Route $route, RouteCollectionAccessor $routes)
    {
        if ($route->getOption('group') !== 'activity_association') {
            return;
        }

        if ($this->hasAttribute($route, self::ACTIVITY_PLACEHOLDER)) {
            $activities = array_map(
                function (ConfigInterface $config) {
                    // convert to entity alias
                    return $this->entityAliasResolver->getPluralAlias(
                        $config->getId()->getClassName()
                    );
                },
                $this->groupingConfigProvider->filter(
                    function (ConfigInterface $config) {
                        // filter activity entities
                        $groups = $config->get('groups');

                        return
                            !empty($groups)
                            && in_array(ActivityScope::GROUP_ACTIVITY, $groups, true);
                    }
                )
            );

            if (!empty($activities)) {
                $this->adjustRoutes($route, $routes, $activities);
                $route->setRequirement(self::ACTIVITY_ATTRIBUTE, implode('|', $activities));
            }
            $this->completeRouteRequirements($route);
        } elseif ($this->hasAttribute($route, self::ENTITY_PLACEHOLDER)) {
            $this->completeRouteRequirements($route);
        }
    }

    /**
     * @param Route                   $route
     * @param RouteCollectionAccessor $routes
     * @param string[]                $activities
     */
    protected function adjustRoutes(Route $route, RouteCollectionAccessor $routes, $activities)
    {
        $routeName = $routes->getName($route);

        foreach ($activities as $activity) {
            $existingRoute = $routes->getByPath(
                str_replace(self::ACTIVITY_PLACEHOLDER, $activity, $route->getPath()),
                $route->getMethods()
            );
            if ($existingRoute) {
                // move existing route before the current route
                $existingRouteName = $routes->getName($existingRoute);
                $routes->remove($existingRouteName);
                $routes->insert(
                    $existingRouteName,
                    $existingRoute,
                    $routeName,
                    true
                );
            } else {
                // add an additional strict route based on the base route and current activity
                $strictRoute = $routes->cloneRoute($route);
                $strictRoute->setPath(str_replace(self::ACTIVITY_PLACEHOLDER, $activity, $strictRoute->getPath()));
                $strictRoute->setDefault(self::ACTIVITY_ATTRIBUTE, $activity);
                $this->completeRouteRequirements($strictRoute);
                $routes->insert(
                    $routes->generateRouteName($routeName),
                    $strictRoute,
                    $routeName,
                    true
                );
            }
        }
    }

    /**
     * Adds not filled requirements for the given route
     *
     * @param Route $route
     */
    protected function completeRouteRequirements(Route $route)
    {
        if (null === $route->getRequirement(self::ACTIVITY_ID_ATTRIBUTE)
            && $this->hasAttribute($route, self::ACTIVITY_ID_PLACEHOLDER)
        ) {
            $route->setRequirement(self::ACTIVITY_ID_ATTRIBUTE, '\d+');
        }
        if (null === $route->getRequirement(self::ENTITY_ATTRIBUTE)
            && $this->hasAttribute($route, self::ENTITY_PLACEHOLDER)
        ) {
            $route->setRequirement(self::ENTITY_ATTRIBUTE, '\w+');
        }
        if (null === $route->getRequirement(self::ENTITY_ID_ATTRIBUTE)
            && $this->hasAttribute($route, self::ENTITY_ID_PLACEHOLDER)
        ) {
            $route->setRequirement(self::ENTITY_ID_ATTRIBUTE, '[^/]+');
        }
    }

    /**
     * Checks if a route has the given attribute
     *
     * @param Route  $route
     * @param string $placeholder
     *
     * @return bool
     */
    protected function hasAttribute(Route $route, $placeholder)
    {
        return false !== strpos($route->getPath(), $placeholder);
    }
}

{'fraction_non_alphanumeric': 0.1162827515237869, 'fraction_numerical': 0.0029288371724847623, 'mean_word_length': 2.2620707461915828, 'pattern_counts': {'":': 1, '<': 5, '<?xml version=': 0, '>': 83, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 5}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3024213', 'n_tokens_mistral': 3455, 'n_tokens_neox': 3378, 'n_words': 584}