src/Charcoal/Object/RoutableTrait.php
protected function generateObjectRoute($slug = null, array $data = [])
    {
        if (!$slug) {
            $slug = $this->generateSlug();
        }

        if ($slug instanceof Translation) {
            $slugs = $slug->data();
        } else {
            throw new InvalidArgumentException(sprintf(
                '[%s] slug parameter must be an instance of %s, received %s',
                get_called_class().'::'.__FUNCTION__,
                Translation::class,
                is_object($slug) ? get_class($slug) : gettype($slug)
            ));
        }

        if (!is_array($data)) {
            $data = [];
        }

        $origLang = $this->translator()->getLocale();
        foreach ($slugs as $lang => $slug) {
            if (!in_array($lang, $this->translator()->availableLocales())) {
                continue;
            }
            $this->translator()->setLocale($lang);

            $newRoute = $this->createRouteObject();
            $oldRoute = $this->getLatestObjectRoute();

            $defaultData = [
                // Not used, might be too much.
                'route_template'      => $this->templateIdent(),
                'route_options'       => $this->routeOptions(),
                'route_options_ident' => $this->routeOptionsIdent(),
            ];

            $immutableData = [
                'lang'                => $lang,
                'slug'                => $slug,
                'route_obj_type'      => $this->objType(),
                'route_obj_id'        => $this->id(),
                'active'              => true,
            ];

            $newData = array_merge($defaultData, $data, $immutableData);

            // Unchanged but sync extra properties
            if ($slug === $oldRoute->slug()) {
                $oldRoute->setData([
                    'route_template'      => $newData['route_template'],
                    'route_options'       => $newData['route_options'],
                    'route_options_ident' => $newData['route_options_ident'],
                ]);
                $oldRoute->update([ 'route_template', 'route_options' ]);

                continue;
            }

            $newRoute->setData($newData);

            if (!$newRoute->isSlugUnique()) {
                $newRoute->generateUniqueSlug();
            }

            if ($newRoute->id()) {
                $newRoute->update();
            } else {
                $newRoute->save();
            }
        }

        $this->translator()->setLocale($origLang);
    }
protected function generateObjectRoute($slug = null, array $data = [])
    {
        if (!$slug) {
            $slug = $this->generateSlug();
        }

        if ($slug instanceof Translation) {
            $slugs = $slug->data();
        } else {
            throw new InvalidArgumentException(sprintf(
                '[%s] slug parameter must be an instance of %s, received %s',
                get_called_class().'::'.__FUNCTION__,
                Translation::class,
                is_object($slug) ? get_class($slug) : gettype($slug)
            ));
        }

        if (!is_array($data)) {
            $data = [];
        }

        $origLang = $this->translator()->getLocale();
        foreach ($slugs as $lang => $slug) {
            if (!in_array($lang, $this->translator()->availableLocales())) {
                continue;
            }
            $this->translator()->setLocale($lang);

            $newRoute = $this->createRouteObject();
            $oldRoute = $this->getLatestObjectRoute();

            $defaultData = [
                // Not used, might be too much.
                'route_template'      => $this->templateIdent(),
                'route_options'       => $this->routeOptions(),
                'route_options_ident' => $this->routeOptionsIdent(),
            ];

            $immutableData = [
                'lang'                => $lang,
                'slug'                => $slug,
                'route_obj_type'      => $this->objType(),
                'route_obj_id'        => $this->id(),
                'active'              => true,
            ];

            $newData = array_merge($defaultData, $data, $immutableData);

            // Unchanged but sync extra properties
            if ($slug === $oldRoute->slug()) {
                $oldRoute->setData([
                    'route_template'      => $newData['route_template'],
                    'route_options'       => $newData['route_options'],
                    'route_options_ident' => $newData['route_options_ident'],
                ]);
                $oldRoute->update([ 'route_template', 'route_options' ]);

                continue;
            }

            $newRoute->setData($newData);

            if (!$newRoute->isSlugUnique()) {
                $newRoute->generateUniqueSlug();
            }

            if ($newRoute->id()) {
                $newRoute->update();
            } else {
                $newRoute->save();
            }
        }

        $this->translator()->setLocale($origLang);
    }
Route generation.

Saves all routes to {@see \Charcoal\Object\ObjectRoute}.

@param  mixed $slug Slug by langs.
@param  array $data Object route custom data.
@throws InvalidArgumentException If the slug is invalid.
@return void