Description
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
Activity
engram-design commentedon Jan 29, 2025
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 commentedon 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:
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:
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.