<commit_before><?php

namespace MandarinMedien\MMCmfRoutingBundle\Entity;

use Doctrine\ORM\EntityManager;
use Doctrine\ORM\Query\ResultSetMapping;
use MandarinMedien\MMCmfNodeBundle\Entity\Node;
use utilphp\util;

/**
 * Class NodeRouteManager
 *
 * Handles the generating, persisting and updating of NodeRoutes
 *
 * @package MandarinMedien\MMCmfRoutingBundle\Entity
 */
class NodeRouteManager
{

    /**
     * @var EntityManager
     */
    protected $manager;


    /**
     * NodeRouteManager constructor.
     * @param EntityManager $manager
     */
    public function __construct(EntityManager $manager)
    {
        $this->manager = $manager;
    }


    /**
     * generates a AutoNodeRoute for a given Node
     *
     * @param Node $node
     * @return AutoNodeRoute
     */
    public function generateAutoNodeRoute(Node $node)
    {

        $repository = $this->manager->getRepository(AutoNodeRoute::class);

        $route = (new AutoNodeRoute())
            ->setRoute('/' . $this->slugify($node))
            ->setNode($node);

        /**
         * @var Node $parent
         */
        while (!is_null($parent = $node->getParent())) {
            $route->setRoute($this->getAutoNodeRoute($parent) . $route->getRoute());
            $node = $parent;
        }

        // add incrementor if route exists
        $route->setRoute(
            $route->getRoute().($this->getIncrement($route->getRoute()) ?: '')
        );


        return $route;
    }


    /**
     * get updated AutoNodeRoutes recursive
     *
     * @param Node $node
     * @param null|string $base
     * @return NodeRoute[]
     */
    public function getAutoNodeRoutesRecursive(Node &$node, $base = null)
    {
        $routeObjects = array();

        $route = null;
        $routes = $node->getRoutes();

        // update the AutoNodeRoutes of current Node
        if(count($routes)>0) {

            foreach($routes as $route) {

                if($route instanceof AutoNodeRoute) {

                    $route->setRoute(
                        $base   ? $base . '/' . util::slugify($node->getName())
                                : $this->generateAutoNodeRoute($node)->getRoute()
                    );

                    array_push($routeObjects, $route);

                    // recursive loop
                    foreach($node->getNodes() as $node) {
                        $routeObjects = array_merge(
                            $this->getAutoNodeRoutesRecursive($node, $route->getRoute()),
                            $routeObjects
                        );
                    }
                }
            }
        }


        return $routeObjects;
    }


    /**
     * generate an url-friendly string from Node::name
     * @param Node $node
     * @return string
     */
    public function slugify(Node $node)
    {
        return util::slugify($node->getName());
    }


    /**
     * return the AutoNodeRoute::route of the given Node entity
     * @param Node $node
     * @return string
     */
    protected function getAutoNodeRoute(Node $node)
    {
        foreach($node->getRoutes() as $route) {
            if($route instanceof AutoNodeRoute) {
                return $route->getRoute();
            }
        }
    }


    /**
     * check if the generated route already exists and return the count
     * @param string $route route string to check
     * @return int increment value
     */
    protected function getIncrement($route)
    {

        $mapper = new ResultSetMapping();
        $mapper->addScalarResult('count', 'count');

        $builder = $this->manager->createNativeQuery(
            'SELECT count(*) as count FROM node_route WHERE route REGEXP ?',
            $mapper
        )
        ->setParameter('1', $route."[0-9]*$");

        return (int) $builder->getSingleScalarResult();
    }

}<commit_msg>improved increment of NodeRoute::route<commit_after><?php

namespace MandarinMedien\MMCmfRoutingBundle\Entity;

use Doctrine\ORM\EntityManager;
use Doctrine\ORM\Query\ResultSetMapping;
use MandarinMedien\MMCmfNodeBundle\Entity\Node;
use MandarinMedien\MMCmfNodeBundle\Entity\NodeInterface;
use utilphp\util;

/**
 * Class NodeRouteManager
 *
 * Handles the generating, persisting and updating of NodeRoutes
 *
 * @package MandarinMedien\MMCmfRoutingBundle\Entity
 */
class NodeRouteManager
{

    /**
     * @var EntityManager
     */
    protected $manager;


    /**
     * NodeRouteManager constructor.
     * @param EntityManager $manager
     */
    public function __construct(EntityManager $manager)
    {
        $this->manager = $manager;
    }


    /**
     * generates a AutoNodeRoute for a given Node
     *
     * @param NodeInterface $node
     * @return AutoNodeRoute
     */
    public function generateAutoNodeRoute(NodeInterface $node)
    {

        $repository = $this->manager->getRepository(AutoNodeRoute::class);

        $route = (new AutoNodeRoute())
            ->setRoute('/' . $this->slugify($node))
            ->setNode($node);

        /**
         * @var Node $parent
         */
        while (!is_null($parent = $node->getParent())) {
            $route->setRoute($this->getAutoNodeRoute($parent) . $route->getRoute());
            $node = $parent;
        }

        // add increment if route exists
        $route->setRoute(
            $route->getRoute().$this->getIncrement($route->getRoute())
        );


        //var_dump($route->getRoute());

        return $route;
    }


    /**
     * get updated AutoNodeRoutes recursive
     *
     * @param NodeInterface $node
     * @param null|string $base
     * @return NodeRoute[]
     */
    public function getAutoNodeRoutesRecursive(NodeInterface &$node, $base = null, &$routeObjects = array())
    {

        $route = $this->getAutoNodeRoute($node);

        if($route) {


            $route->setRoute(
                $base ? $base . '/' . util::slugify($node->getName())
                    : $this->generateAutoNodeRoute($node)->getRoute()
            );

            // add soft Increment
            $route->setRoute($route->getRoute().$this->softIncrement($route, $routeObjects));


            $routeObjects[] = $route;


            // recursive loop
            foreach ($node->getNodes() as $subnode) {
                $this->getAutoNodeRoutesRecursive($subnode, $this->getAutoNodeRoute($node)->getRoute(), $routeObjects);
            }
        }


        return $routeObjects;
    }


    /**
     * generate an url-friendly string from Node::name
     * @param Node $node
     * @return string
     */
    public function slugify(Node $node)
    {
        return util::slugify($node->getName());
    }


    /**
     * return the AutoNodeRoute::route of the given Node entity
     * @param NodeInterface $node
     * @return AutoNodeRoute
     */
    protected function getAutoNodeRoute(NodeInterface $node)
    {
        foreach($node->getRoutes() as $route) {
            if($route instanceof AutoNodeRoute) {
                return $route;
            }
        }
    }


    /**
     * check if the generated route already exists and return the count
     * @param string $route route string to check
     * @return string increment value in parenthesis
     */
    protected function getIncrement($route)
    {

       // var_dump($route);

        $mapper = new ResultSetMapping();
        $mapper->addScalarResult('route', 'route');


        $builder = $this->manager->createNativeQuery(
            'SELECT route FROM node_route WHERE route REGEXP ?',
            $mapper
        )
        ->setParameter('1', $this->prepareMysqlRegexp($route));

        //var_dump($builder->getArrayResult());


        $i = 0;
        foreach($builder->getArrayResult() as $_route)
        {

            if(preg_match('#\(([0-9])*\)$#', $_route['route'], $matches)) {
                $i = (int) $matches[1] == $i  ? (int) $matches[1]+1 : $i;
            } else {
                $i++;
            }
        }

        return ($i ? "($i)" : '');
    }


    /**
     * get increment values based on given NodeRoute[]
     * @param AutoNodeRoute $route
     * @param AutoNodeRoute[] $routes
     * @return string increment value in parenthesis
     */
    public function softIncrement($route, array $routes)
    {

        // flat the route array
        $flatten = array_map(function($route) {
            return $route->getRoute();
        }, $routes);

        $i = 0;

        array_walk($routes, function($_route) use($route, &$i) {

            $search = "#".addcslashes(preg_replace('/\([0-9]+\)*$/', "", $route),'()').'(\([0-9]+\))*$#';

            if(preg_match($search, $_route->getRoute(), $matches)) {
                if(count($matches) == 2) {
                    $i = (int)$matches[1] == $i ? (int)$matches[1] + 1 : $i;
                } else {
                    $i++;
                }
            };
        });

        return ($i ? "($i)" : '');
    }


    /**
     * create regexp for mysql query
     * @param $string NodeRoute::route
     * @return string
     */
    protected function prepareMysqlRegexp($string)
    {
        $regexp = $string;

        // first remove trailing increment
        $regexp = preg_replace('/\([0-9]\)$/', "", $regexp);

        // escape existing parenthesis
        $regexp = preg_replace('(\(|\))', '\\\\${0}', $regexp);

        // append matching mysql matching pattern
        $regexp .= "([[.left-parenthesis.]][0-9]*[[.right-parenthesis.]])*$";

        return $regexp;

    }


}
{'fraction_non_alphanumeric': 0.1403324216284452, 'fraction_numerical': 0.002629917946560067, 'mean_word_length': 1.9216349108789184, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 72, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 1, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4981456', 'n_tokens_mistral': 2747, 'n_tokens_neox': 2634, 'n_words': 567}