Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Combining with a module that adds custom items #143

Open
JayBox325 opened this issue Jan 28, 2025 · 2 comments
Open

Combining with a module that adds custom items #143

JayBox325 opened this issue Jan 28, 2025 · 2 comments
Labels

Comments

@JayBox325
Copy link

JayBox325 commented Jan 28, 2025

Question

I have got a unique multi-site setup where each site has a different 'homepage' single, but my platform could end up with 15/20 or more sites, so in an attempt to limit how complex my permissions management could get and to try to simplify the onboarding process of a new site, I have written a module that automates adding a link to the singles associated with that site to the global sidebar.

Your 'Expanded Singles' plugin didn't work for me as we're not using the secondary sidebar, and hosting everything in the global sidebar.

The benefits of this module mean I can have just one 'outlets' Navigation layout that is associated with one 'outlet' user group, whereas if I don't use my module.

In order to get the AX I'm looking for, I'd need to create a new site, a new user group, a new single and a new navigation layout for each outlet which will become hard to maintain, whereas if I can just dynamically add the singles to the top, this will save a lot of work. Here is my module that finds the singles for the current site and adds them to the sidebar, but when I enable the Navigation plugin, it replaces this item, too. Is it going to be possible to combine them?

<?php

namespace sidebarsingle;

use Craft;
use craft\events\RegisterCpNavItemsEvent;
use craft\models\Section;
use yii\base\Event;
use craft\elements\Entry;

class Module extends \yii\base\Module
{
    public function __construct($id, $parent = null, array $config = [])
    {
        parent::__construct($id, $parent, $config);

        // Attach the event handler when the module is initialized
        Craft::$app->onInit(function () {
            $this->registerEventHandlers();
        });
    }

    private function registerEventHandlers()
    {
        // Listen for the CP navigation item registration event
        Event::on(
            \craft\web\twig\variables\Cp::class,
            \craft\web\twig\variables\Cp::EVENT_REGISTER_CP_NAV_ITEMS,
            function (RegisterCpNavItemsEvent $event) {
                // Fetch all singles for the current site
                $singles = $this->getCurrentSiteSingles();

                // Add a navigation item for each single
                foreach ($singles as $single) {
                    array_unshift($event->navItems, [
                        'url' => 'entries/' . $single->section->handle . '/' . $single->id . '-' . $single->slug, // URL for the single
                        'label' => 'Landing Page',
                        'icon' => '@appicons/house.svg', // Optional icon
                    ]);
                };

            }
        );
    }

    /**
     * Fetch all singles for the current site
     *
     * @return array The singles for the current site
     */
    private function getCurrentSiteSingles()
    {
        // Get the currently active site
        $currentSiteHandle = Craft::$app->getRequest()->getParam('site', Craft::$app->getSites()->getCurrentSite());
        $currentSite = Craft::$app->getSites()->getSiteByHandle($currentSiteHandle);

        if ($currentSite) {
            // Get the current site's ID
            $currentSiteId = $currentSite->id;

            // Fetch all singles
            $singles = Craft::$app->entries->getSectionsByType(Section::TYPE_SINGLE);

            // Find the single for the current site and return it
            $singlesForCurrentSite = array_filter($singles, function ($single) use ($currentSiteId) {
                return in_array($currentSiteId, $single->getSiteIds());
            });

            // Fetch the associated entries to get the slugs
            $entries = [];
            foreach ($singlesForCurrentSite as $single) {
                $entry = Entry::find()
                    ->sectionId($single->id) // Filter by the section ID
                    ->siteId($currentSiteId) // Ensure it's for the current site
                    ->one();

                if ($entry) {
                    $entries[] = $entry;
                }
            }

            return $entries;

        } else {
            echo 'Error: Active site not found.';
            return [];
        }
    }
}

Thanks!

Additional context

No response

@engram-design
Copy link
Member

So that's going to be tricky, as we're essentially competing over the Cp::EVENT_REGISTER_CP_NAV_ITEMS event. We'll probably need to introduce our own event that while similar, allows you to modify CP Nav's overridden navigations.

@JayBox325
Copy link
Author

JayBox325 commented Jan 29, 2025

Ok, that makes sense. This probably means I'll need to stick with the default navigation to allow this feature, which is a shame. Unless there'd be a way for me to use my module to update the URL of the Landing Page item to configure it to be that Site's "homepage" single dynamically, which isn't perfect, but may be the solution for now.

I have tried to just replace the first item in the navigation with my desired URL, but no dice:

if ($landingSingle && !empty($event->navItems)) {
    // Modify the first nav item
    $event->navItems[0]['url'] = 'entries/' . $landingSingle->section->handle . '/' . $landingSingle->id . '-' . $landingSingle->slug;
}

UPDATE: I have resolved this for now, by adding the desired single URL to the body tag as a data attribute, then using the Control Panel JS plugin, I'm just taking the contents of this attribute and using them as the Landing Page navigation item set by the CP Nav plugin. So this works for now... but if there was a way to dynamically override items from within the CP Nav that would be amazing to have it all done server-side.

This means my admin now looks like this:

Image

This could potentially be a plugin idea to remove the potentially needless second sidebar navigation within Entries, as almost everything in the CraftCMS eco-system is an entry now.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants