HEX
Server: Microsoft-IIS/8.5
System: Windows NT YDAWBH120 6.3 build 9600 (Windows Server 2012 R2 Standard Edition) AMD64
User: tentjecom_web (0)
PHP: 7.4.14
Disabled: NONE
Upload Files
File: D:/HostingSpaces/SBogers10/stafa.komma.pro/app/Komma/Routes/RouteService.php
<?php

namespace App\Komma\Routes;


use App\Helpers\KommaHelpers;
use App\Komma\Kms\Core\AbstractTranslationModel;
use App\Komma\Kms\Core\HasRoutesInterface;
use App\Komma\Kms\Core\AbstractTranslatableModel;
use App\Komma\Kms\Core\HouseKeeping\CanDoHousekeepingInterface;
use App\Komma\Kms\Core\Tree\NestedSets\Nodes\TreeModelInterface;
use App\Komma\Globalization\Languages\Models\Language;
use App\Komma\Pages\Models\Page;
use App\Komma\Pages\Models\PageTranslation;
use App\Komma\Routes\Models\RedirectRoute;
use App\Komma\Routes\Models\Route;
use App\Komma\Sites\Models\Site;
use App\Komma\Sites\SiteServiceInterface;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Query\Builder;

/**
 * Class RouteService
 *
 * Can create routes for AbstractTranslationModels that are part of a given AbstractTranslatable model.
 * But currently this routeservice is typed more concretely to the Page model (that is a AbstractTranslatable model)
 * and it's PageTranslations (that are AbstractTranslationModels)
 *
 * @package App\Komma\Routes
 */
final class RouteService extends AbstractRouteService implements CanDoHousekeepingInterface
{
    /** @var SiteServiceInterface $siteService */
    private $siteService;

    /**
     * For which class this model works for
     *
     * @var string $forModelName
     */
    protected $forModelName;

    public function __construct()
    {
        $this->siteService = app(SiteServiceInterface::class);

        static::setRouteClassName(Route::class);
        static::setRedirectRouteClassName(RedirectRoute::class);
    }

    /**
     * Creates or updates routes for the specified Page's translations if needed.
     * Important to know is that you need to run this method after the translation has been saved.
     *
     * @param Page $model
     * @param int $redirectCode one of the HTTPStatusCode_308 constants from RedirectRouteModelInterface. Defaults to RedirectRouteModelInterface::HTTPStatusCode_308
     * @return RouteService true on success. An array when one or more translation routes (RouteModelInterface) could not be saved because the RouteModelInterface alias already exists
     */
    public function createOrUpdateRoutesForModelsTranslationsIfChanged(Page $model, int $redirectCode = RedirectRouteModelInterface::HTTPStatusCode_308): AbstractRouteService
    {
        /** @var AbstractTranslatableModel $model */
        $translations = $model->translations()->get();

        //We need to make sure that each translation has a language and routes method. If not trow an exception
        $this->verifyThatEachHasTranslationIsAnAbstractTranslationModel($translations);

        //Process routes for the models translations
        $translations->each(function (PageTranslation $translation) use ($redirectCode, $model, &$existingRouteFails) {

            /** @var PageTranslation|AbstractTranslationModel|HasRoutesInterface $translation */
            /** @var Language $language */
            if ( ! is_a($translation, HasRoutesInterface::class)) return;

            // Don't make a route for an empty translation, because they shouldn't even exist
            if ($translation->name === '') return;

            $language = $translation->language()->get()->first();
            $newRouteAliasStringForCurrentTranslation = $this->createRouteAliasString($language, $model, $translation);

            //Get route and redirect route
            /** @var RouteModelInterface $currentTranslationRoute */
            $currentTranslationRoute = $translation->route()->first();

            $this->createOrUpdateRouteForTranslationIfChanged($translation, $newRouteAliasStringForCurrentTranslation, $currentTranslationRoute, $model->site);
        });

        //Process routes for the children of the model if it is a tree model interface
        if(is_a($model, TreeModelInterface::class)) {
            /** @var $model AbstractTranslatableModel|TreeModelInterface $children */
            $children = collect($model->findChildren());
            $children->each(function(TreeModelInterface $child) {
                $this->createOrUpdateRoutesForModelsTranslationsIfChanged($child);
            });
        }

        return $this;
    }

    /**
     * Creates or updates a route for the PageTranslation
     *
     * @param AbstractTranslationModel|PageTranslation $translation
     * @param string $newRouteAliasStringTranslation
     * @param RouteModelInterface $currentTranslationRoute
     * @param Site|null $site
     * @throws \ReflectionException
     */
    private function createOrUpdateRouteForTranslationIfChanged(PageTranslation $translation, string $newRouteAliasStringTranslation, RouteModelInterface $currentTranslationRoute = null, Site $site = null)
    {
        /** @var AbstractTranslatableModel $model */
        $model = $translation->translatable()->first();

        $routeWithNewAliasQuery = $this->getRouteClassName()::where('alias', '=', $newRouteAliasStringTranslation);
        if($site) $routeWithNewAliasQuery->where('site_id', $site->id);

        $routeWithNewAlias = $routeWithNewAliasQuery->first();

        $translationRedirectRouteWithNewAliasQuery = $translation->redirectRoutes()->where('alias', '=', $newRouteAliasStringTranslation);
        if($site) $translationRedirectRouteWithNewAliasQuery->where('site_id', $site->id);

        $translationRedirectRouteWithNewAlias = $translationRedirectRouteWithNewAliasQuery->first();

        //skip this iteration. Route did not change
        if ($currentTranslationRoute && $this->removeNumberSuffixIfPresent($currentTranslationRoute->alias) == $this->removeNumberSuffixIfPresent($newRouteAliasStringTranslation)) return;

        // Handle different the of situations between both route types.
        // When the new route is already in the redirect table we need to swap the detail of the current regular route
        if ($currentTranslationRoute && $translationRedirectRouteWithNewAlias) {
            $translationRedirectRouteWithNewAlias->alias = $currentTranslationRoute->alias;
            $currentTranslationRoute->alias = $newRouteAliasStringTranslation;

            $translationRedirectRouteWithNewAlias->save();
            $currentTranslationRoute->save();
        } // When the new route does exist as a regular route we create a new redirect route containing the regular route's details. We then give the already existing regular route the new details
        elseif ($currentTranslationRoute && ! $translationRedirectRouteWithNewAlias) {
            $redirectRoute = $this->createRedirectRouteFromRouteAndRedirectCode($currentTranslationRoute,
                $this->getRedirectRouteClassName()::Http11PermanentCachedByDefault);
            $redirectRoute->site_id = $model->site_id;

            $currentTranslationRoute->alias = $newRouteAliasStringTranslation;

            //Check if there already is an redirect route with the same alias
            $possibleExistingRouteRedirectRouteQuery = $this->getRedirectRouteClassName()::where('alias', '=', $currentTranslationRoute->alias);
            if($site) $possibleExistingRouteRedirectRouteQuery->where('site_id', $model->site_id);

            $possibleExistingRouteRedirectRoute = $possibleExistingRouteRedirectRouteQuery->first();

            if ($possibleExistingRouteRedirectRoute) {
                \Log::warning('Deleted redirect route with alias "' . $newRouteAliasStringTranslation . '". Because a new one with the same alias needed to be created.');
                $possibleExistingRouteRedirectRoute->delete();
            }

            $redirectRoute->save();
            $currentTranslationRoute->save();
        }//Else if the new route exists as redirect route but not as regular route, we only log this result. The redirect route works but could be improved by storing him as regular route
        elseif ( ! $currentTranslationRoute && $translationRedirectRouteWithNewAlias) {
            //                dd('2');
            $route = $this->createRoute($newRouteAliasStringTranslation, $model, $translation);

            $translationRedirectRouteWithNewAlias->delete();
            $route->save();
            $translationRedirectRouteWithNewAlias = null;
        }//Else if when the route does not exist on both route types we create it as regular route
        elseif ( ! $currentTranslationRoute && ! $routeWithNewAlias && ! $translationRedirectRouteWithNewAlias) {
            //                dd('3');
            $route = $this->createRoute($newRouteAliasStringTranslation, $model, $translation);

            $route->save();
        }
    }

    /**
     * Removes the number suffix from a string.
     * @param string $string The subject
     * @param string $delimiter Character that separates the number from the rest.
     * @return string
     */
    private function removeNumberSuffixIfPresent(string $string, string $delimiter = '-')
    {
        $shrapnel = explode($delimiter, $string);
        $potentialNumber = last($shrapnel);
        if ( ! is_numeric($potentialNumber)) {
            return $string;
        }
        array_pop($shrapnel);

        return implode($delimiter, $shrapnel);
    }

    /**
     * Check if the given route alias only is defined once in either RouteModelInterface and RedirectRouteModelInterface instances.
     * If not throw a RunTimeException
     *
     * @param string $alias
     * @return void
     * @throws \RuntimeException
     */
    private static function checkRouteTableIntegrityForAlias(string $alias = '')
    {
        $redirectRouteClassName = self::getRedirectRouteClassName();
        $routeClassName = self::getRouteClassName();

        //If no alias was given, we check all aliases.
        if($alias == '') {
            //Go and check all route aliases
            $routeClassName::all(['alias'])->each(function($route) {
                self::checkRouteTableIntegrityForAlias($route->alias);
            });

            $redirectRouteClassName::all(['alias'])->each(function($route) {
                self::checkRouteTableIntegrityForAlias($route->alias);
            });
            return;
        }

        //Return all routes with the given alias and group them by site_id
        $routesWithAlias = $routeClassName::get(['id', 'alias', 'site_id'])->where('alias', '=', $alias)->groupBy('site_id');
        $redirectRoutes = $redirectRouteClassName::get(['id', 'alias', 'site_id'])->where('alias', '=', $alias)->groupBy('site_id');

        $routesWithAlias->each(function(Collection $routesCollection, $site_id) use ($routeClassName, $alias) {
            if($routesCollection->count() > 1) {
                throw new \RuntimeException('Check your "' . (new $routeClassName)->getTable() . '" table. It contains multiple routes with alias "' . $alias . '" and the same site_id of "'.$site_id.'". which is not allowed.');
            }
        });

        $redirectRoutes->each(function(Collection $routesCollection, $site_id) use ($redirectRouteClassName, $alias) {
            if($routesCollection->count() > 1) {
                throw new \RuntimeException('Check your "' . (new $redirectRouteClassName)->getTable() . '" table. It contains multiple routes with alias "' . $alias . '" and the same site_id of "'.$site_id.'". which is not allowed.');
            }
        });

        $routesWithAlias->each(function(Collection $routesCollection, $site_id) use ($redirectRoutes, $alias, $redirectRouteClassName, $routeClassName) {
            $redirectRoutesCollectionForCurrentRouteSiteId = $redirectRoutes->get($site_id);
            if($redirectRoutesCollectionForCurrentRouteSiteId && $redirectRoutesCollectionForCurrentRouteSiteId->count() > 0) {
                throw new \RuntimeException('Check your "' . (new $redirectRouteClassName)->getTable() . '" and "' . (new $routeClassName)->getTable() . '" tables. They both contain a route with alias "' . $alias . '" and site_id "'.$site_id.'" which is not allowed. Only one in both tables combined is allowed.');
            }
        });


//        if ($redirectRoutesWithNewAliasCount + $routesWithNewAliasCount > 1) {
//            throw new \RuntimeException('Check your "' . (new $redirectRouteClassName)->getTable() . '" and "' . (new $routeClassName)->getTable() . '" tables. They both contain a "' . $alias . '" which is not allowed. Only one in both tables combined is allowed');
//        }
    }

    /**
     * Creates a route model (does not save it to the database)
     *
     * If you give it the AbstractTranslatableModel model it will update the route attribute to the appropiate value.
     * If you give it the AbstractTranslationModel model it will update the routable_id and routable_type attributes so
     * that the AbstractTranslationModel instance is associated with it
     *
     * @param string $alias The alias for the route.
     * @param AbstractTranslatableModel|Page|null $model
     * @param AbstractTranslationModel|PageTranslation|null $translationModel
     * @return RouteModelInterface
     */
    private function createRoute(string $alias, Page $model, PageTranslation $translationModel): RouteModelInterface
    {
        $routeClass = $this->getRouteClassName();
        /** @var RouteModelInterface|Route $routeModel */
        $routeModel = new $routeClass;
        $routeModel->route = ($model) ? $this->generateRealRouteForModel($model) : '';
        $routeModel->alias = $alias;
        $routeModel->language_id = $translationModel->language()->get(['id'])->first()->id;
        $routeModel->site()->associate($model->site_id);
        $routeModel->pageTranslation()->associate($translationModel);

        return $routeModel;
    }

    /**
     * Generates a real route for a model that should be compatible with the routes listed
     * with php artisan route:list.
     * Example: when you pass a page model, it will return: pages/4 if the page id is 4.
     *
     * @param Model $model
     * @return string
     */
    private function generateRealRouteForModel(Model $model)
    {
        $shortName = KommaHelpers::getShortNameFromClass($model);

        $shortName = strtolower($shortName);
        $pluralShortName = str_plural($shortName);

        return $pluralShortName . '/' . $model->id;
    }

    /**
     * Creates an instance of a RedirectRouteModelInterface based on an instance of RouteModelInterface.
     * And then returns the RedirectRouteModelInterface
     *
     * @param RouteModelInterface $route
     * @param int $redirectCode
     * @return RedirectRouteModelInterface;
     * @throws \ReflectionException
     */
    private function createRedirectRouteFromRouteAndRedirectCode(RouteModelInterface $route, int $redirectCode): RedirectRouteModelInterface
    {
        $attributes = $route->toArray();

        $redirectRouteClassName = $this->getRedirectRouteClassName();
        /** @var RedirectRouteModelInterface|RedirectRoute $redirectRoute */
        $redirectRoute = new $redirectRouteClassName();

        $redirectRoute->fill($attributes);

        if ( ! $this->getRedirectRouteClassName()::isValidRedirectCode($redirectCode)) {
            throw new \InvalidArgumentException("The redirect code '" . $redirectCode . "' was not a valid one. It must be one of the constants defined in the RedirectRouteModelInterface.");
        }
        $redirectRoute->redirect_code = $redirectCode;

        return $redirectRoute;
    }

    /**
     * Returns a route alias string for an instance that extends the AbstractTranslationModel class
     *
     * @param Language $language
     * @param AbstractTranslatableModel|Page $model
     * @param AbstractTranslationModel|PageTranslation $translation
     * @return string
     * @see AbstractTranslationModel
     */
    private function createRouteAliasString(Language $language, Page $model, AbstractTranslationModel $translation): string
    {
        $availableLanguages = $this->siteService->getSiteLanguages();
        $defaultLanguageId = $this->siteService->getCurrentSite()->default_language_id;

        if (count($availableLanguages) == 0) {
            throw new \RuntimeException("Site has no language");
        }

        // Check if model has EloquentNodeInterface
        if (is_a($model, TreeModelInterface::class)) {

            // Handles the route creating for eloquent nodes
            $potentialRoute = $this->createPotentialRouteForEloquentNode($language, $model, $translation, $availableLanguages, $defaultLanguageId);
        }// Shouldn't be used, because only pages are using this function
        else {
            if (count($availableLanguages) == 1) {
                $potentialRoute = '/' . str_slug($translation->name);
            }else {
                if ($translation->slug == 'home') {
                    $potentialRoute = '/' . $language->iso_2;
                }else {
                    $potentialRoute = '/' . $language->iso_2 . '/' . $translation->slug;
                }
            }
        }

        $sitesIds = $this->siteService->getSiteIdsForModel($model, false);

        $alreadyExistsQuery = $this->getRouteClassName()::where('alias', '=', $potentialRoute);
        if($sitesIds) $alreadyExistsQuery->whereIn('site_id', $sitesIds);
        $alreadyExists = $alreadyExistsQuery->first();

        if ($alreadyExists) {
            $suffixedRoutes = $this->getRouteClassName()::where('alias', 'like', $potentialRoute . '-%')
                ->where('page_translation_id', '!=', $translation->id)
                ->where('site_id', $model->site_id)
                ->get(['alias']);
            if ($suffixedRoutes->count() > 0) {
                $highestNumber = null;
                $suffixedRoutes->each(function ($suffixedRoute) use (&$highestNumber) {
                    $kaboomedAlias = explode('-', $suffixedRoute->alias);
                    $number = end($kaboomedAlias);

                    if (is_numeric($number)) {
                        $currentNumber = intval($number);
                        if ($highestNumber < $currentNumber) {
                            $highestNumber = $currentNumber;
                        }
                    }
                });

//                dd('is suffixed. '.$highestNumber);
                $potentialRoute .= ($highestNumber) ? '-' . ($highestNumber + 1) : '-1';
            }else {
//                dd('is not suffixed');
                $potentialRoute .= '-1';
            }
        }

//        dd('halt');
        return $potentialRoute;
    }

    /**
     * Returns a possible route alias string for an instance that extends the AbstractTranslationModel and has an EloquentNodeInterface
     *
     * @param Language $language
     * @param AbstractTranslatableModel|Page $model
     * @param AbstractTranslationModel|PageTranslation $translation
     * @param array $availableLanguages
     * @param integer $defaultLanguageId
     * @return string
     */
    private function createPotentialRouteForEloquentNode(Language $language, Page $model, PageTranslation $translation, $availableLanguages, $defaultLanguageId): string
    {
        $parent = $model->getParent();

        // Check if model is direct parent of root
        if ($parent->lft == '1') {

            // If this language is the default language and the translation slug is home
            // Then we name this route the root
            if($language->id === $defaultLanguageId && $translation->slug == 'home'){
                return '/';
            }

            //Then do as normal
            // If doesn't have multiple language then just slugify the name
            if (count($availableLanguages) == 1) {
                return '/' . str_slug($translation->name);
            }else {
                // Else we add a prefix of the iso_2
                // With an exception on home because that is just the iso_2 alone
                if ($translation->slug == 'home') {
                    return $potentialRoute = '/' . $language->iso_2;
                }else {
                    return '/' . $language->iso_2 . '/' . $translation->slug;
                }
            }
        }else { // Then model is a sub model so generate route by alias
            // Load parent translation
            $parentTranslation = $parent->translations->where('language_id', '=', $language->id)->first();

            $parentTranslationRoute = $parentTranslation->route;
            if(!$parentTranslationRoute) throw new \RuntimeException('Parent translation with id '.$parentTranslation->id.' did not have a route.');

            // Sub model route is parent route with slugify name
            return $parentTranslationRoute->alias . '/' . str_slug($translation->name);
        }
    }


    /**
     * Returns the route whom alias is /
     *
     * @throws \RuntimeException when the route does not exist
     * @return Route $route The Root route;
     */
    public function getRootRoute(): RouteModelInterface
    {
        /** @var Builder $route */
        $route = (new $this->getRouteClassName())->where('alias', '/');
        if ( ! $route) {
            throw new \RuntimeException("The root route does not exist. This is a route with alias '/'");
        }

        return $route->get()->first();
    }

    /**
     * Check that all translations in the collection are AbstractTranslationModel instances.
     * This means that they have a routes and language method at least.
     *
     * @see HasLanguageAndRoutesInterface
     * @see HasTranslationsInterface
     * @param Collection $translations A Collection with AbstractTranslationModel implementations
     * @throws \RuntimeException
     * @return void
     */
    private function verifyThatEachHasTranslationIsAnAbstractTranslationModel(Collection $translations)
    {
        $translations->each(function ($translation) {
            if ( ! is_a($translation, AbstractTranslationModel::class)) {
                throw new \RuntimeException("One of the translations wasn't an AbstractTranslationModel implementation while it must be one.");
            }
        });
    }

    /**
     * Returns the redirect route (if any) with the specified alias or
     * if that not exists it returns the regular route or if that does not exists null
     *
     * @param string $alias
     * @param Site $site
     * @param string $routeInterfaceNameToReturn if null it will try to find a RouteRedirectModelInterface or a RouteModelInterface if the RouteRedirectModelInterface does not exist.
     * You can search for a specific type by passing either RouteRedirectModelInterface::class or RouteModelInterface::class
     * @param bool $mustBeActive The route must link to an active routeable (true) or we don't care (false)
     * @return RedirectRouteModelInterface|RouteModelInterface|null
     */
    public function getRouteByAlias(string $alias, Site $site, bool $mustBeActive = true, string $routeInterfaceNameToReturn = null): ?Model
    {
        $routes = null;

        if($routeInterfaceNameToReturn == null) {
            /** @var RouteModelInterface $route */
            $redirectRoutes = $this->getRedirectRouteClassName()::where('alias', $alias)
                ->orderBy('updated_at', 'desc')
                ->where('site_id', $site->id)
                ->get();
            if ($redirectRoutes->count() == 0) {
                $regularRoutes = $this->getRouteClassName()::where('alias', $alias)
                    ->orderBy('updated_at', 'desc')
                    ->where('site_id', $site->id)
                    ->get();
                if ($regularRoutes->count() > 0) $routes = $regularRoutes;
            } else {
                $routes = $redirectRoutes;
            }
        }
        elseif($routeInterfaceNameToReturn == RedirectRouteModelInterface::class)
        {
            $redirectRoutes = $this->getRedirectRouteClassName()::where('alias', $alias)
                ->orderBy('updated_at', 'desc')
                ->where('site_id', $site->id)
                ->get();
            if ($redirectRoutes->count() == 0) return null;
            $routes = $redirectRoutes;
        }
        elseif($routeInterfaceNameToReturn == RouteModelInterface::class)
        {
            $regularRoutes = $this->getRedirectRouteClassName()
                ->orderBy('updated_at', 'desc')
                ->where('site_id', $site->id)
                ->get();
            if ($regularRoutes->count() == 0) return null;
            $routes = $regularRoutes;
        } else {
            throw new \InvalidArgumentException("The routeType argument must be either null, RouteRedirectModelInterface::class or RouteModelInterface::class");
        }

        if($routes)
        {
            if($mustBeActive == false) return $routes->first();

            //check if one of the routeables is active and return the first
            foreach($routes as $route){

                /** @var RouteModelInterface $route */
                $routeable = $route->pageTranslation()->first()->translatable;
                if(!is_a($routeable, AbstractTranslatableModel::class)) throw new \RuntimeException('The model returned with the "routable" method from a RedirectRouteModelInterface implementation "'.get_class($route).'" did not return the expected model that extends the AbstractTranslatableModel.');

                /** @var AbstractTranslatableModel $routeable */
                if(isset($routeable->active) && $routeable->active && $routeable->id != false){
                    return $route;
                } //Skip this iteration
            }
        }

        return null;
    }

    /**
     * Deletes all routes for a model. If it is a AbstractTranslatableModel, for example a page, it will also delete the routes for the translations if you set the second property to true.
     * If it is a AbstractTranslationModel, for example a page translations it will look at its translatable first and then delete al routes for the translatable and translations too if you set the second property to true.
     *
     * @param Model|AbstractTranslationModel|PageTranslation|Page $theModel
     * @return void
     */
    public function deleteRoutesForModel(Model $theModel): void
    {
        if(!is_a($theModel, PageTranslation::class)) return;

        /** @var AbstractTranslatableModel $model */
        $model = null;

        /** @var AbstractTranslatableModel $translations */
        $translations = null;

        if (is_a($theModel, AbstractTranslationModel::class)) {
            $model = $theModel->translatable();
            if ($model) {
                $translations = ($model->translations());
            }
        }else {

            $model = $theModel;
            $translations = $model->translations();
        }

        $translations->each(function ($translation) use ($model) {
            if ( ! is_a($translation, HasRoutesInterface::class)) {
                return;
            }

            /** @var AbstractTranslationModel $translation */

            $routableId = $translation->id;

            $this->getRedirectRouteClassName()::where([
                'page_translation_id'   => $routableId,
                'site_id' => $model->site_id
            ])->delete();

            $this->getRouteClassName()::where([
                'page_translation_id'   => $routableId,
                'site_id' => $model->site_id
            ])->delete();
        });

        return;
    }

    /**
     * Generates a route string for saving a new or existing route. And generates the correct http verb for it.
     *
     * @param int|null $modelId In a route of /kms/default/pages/89 the modelId is 89. Referencing to a page for example.
     * @param string $slug In a route of /kms/default/pages/89 the slug is 'pages'. default is the site name
     * @return array with 2 keys. route and method.
     */
    public function getSaveRoute(string $slug, int $modelId = null)
    {
        $site = $this->siteService->getCurrentSite();

        //If we have a modelId, then we need to update (PUT) the model. Else we need to store (POST) a new model.
        $route = ($modelId) ? strtolower($slug) . '.update' : strtolower($slug) . '.store';
        $method = ($modelId) ? 'PUT' : 'POST';

        //Set route parameters
        $routeParameters = [];
        if ($site->exists) {
            $routeParameters['site'] = $site->slug;
        }
        $modelName = KommaHelpers::getShortNameFromClass($this->forModelName, true);
        if ($modelId) {
            $routeParameters[$modelName] = $modelId;
        } //example key is 'page' value = 89

//        dd($route, $routeParameters);
        return [
            'route' => route($route, $routeParameters),
            'method' => $method
        ];
    }

    /**
     * For which model class the service works for
     *
     * @param string $forModelName
     */
    public function setForModelName(string $forModelName)
    {
        $this->forModelName = $forModelName;
    }


    /**
     * Does some housekeeping by removing old routes.
     * Should be triggered by cron jobs via a houseKeeperService
     */
    public static function doHouseKeeping()
    {
        static::setRouteClassName(Route::class);
        static::setRedirectRouteClassName(RedirectRoute::class);

        $result = '';

        try {
            self::checkRouteTableIntegrityForAlias();
        } catch (\RuntimeException $e) {
            $result .= $e->getMessage().PHP_EOL;
        }
        return $result;
    }
}