List all Contexts and Link to their Site Start (and pull other settings as well)

Ok, I actually asked this question 9 years ago and we came up with a nice solution. However, I need to make it better this time around. One key difference is that I don’t want to have to define the contexts up-front. I simply want to loop through the existing ones (minus web, mgr).

Situation: I have a site with several sub-folder contexts and I want to create an index page that lists them all. Listing is easy. But digging into their settings and pulling out custom settings like “Context Name” and their site_start have proved challenging because of the nested array that gets produced when you query the collection.

Here’s what I’ve got so far. Note: $x is the desired variable site_start

<?php
$contexts = $modx->getCollection('modContext', array('key:NOT IN' => array('web', 'mgr')));
$ctxSettings = $modx->getCollection('modContextSetting', array('key:NOT IN' => array('web', 'mgr')));

foreach ( $ctxSettings as $key => $value ) {
     
}
foreach ( $contexts as $context ) {
   $listContext .= "<li class='city'><a href='". $x  ."'>" . $context->get('key') . "</a></li>";
}
return $listContext;

And what I need to end up with is something like the following. Note: “Context Name” is a custom setting that I’ve created.

<li><a href="(site start value)" title="Context description">Context Name</a></li>

Has anyone done this without the use of an Extra? Is there an Extra that just handles all of it?

Maybe something like this works:

<?php
$contexts = $modx->getCollection('modContext', array('key:NOT IN' => array('web', 'mgr')));
foreach ( $contexts as $context ) {
    $settings = $context->getMany('ContextSettings');
    $site_start_url = '';
    foreach ( $settings as $setting ) {
        if ($setting->get('key') == 'site_start'){
            $site_start = $setting->get('value');
            $site_start_url = $modx->makeUrl($site_start);
        }
    }
    $listContext .= "<li class='city'><a href='". $site_start_url  ."'>" . $context->get('key') . "</a></li>";
}
return $listContext;
1 Like

Wow, Harry – thanks! It works perfectly.

Maybe you can point me to how I’d use this to grab other settings. Is using an if statement the best way to do that?

Example: I have a custom setting called context_name that I’d like to put in this link in place of the current key output.

$context->getMany('ContextSettings'); returns all the context settings. So code like this should work:

$settings = $context->getMany('ContextSettings');
$site_start_url = '';
$context_name = '';
foreach ( $settings as $setting ) {
	$setting_key = $setting->get('key');
	if ($setting_key == 'site_start'){
		$site_start = $setting->get('value');
		$site_start_url = $modx->makeUrl($site_start);
	} elseif ($setting_key == 'context_name'){
		$context_name = $setting->get('value');
	}
}
$listContext .= "<li class='city'><a href='". $site_start_url  ."'>" . $context_name . "</a></li>";

You can also query only specific settings by defining a second parameter (like you did with the contexts).

$settings = $context->getMany('ContextSettings', array('key:IN' => array('site_start', 'context_name')));

Thanks a lot! I’d never used ContextSettings before. That saves a lot of additional work.

you could make it a bit more flexible and load all settings into an array and use a tpl - chunk

<?php
$tpl = $modx->getOption('tpl',$scriptProperties,'');
$contexts = $modx->getCollection('modContext', array('key:NOT IN' => array('web', 'mgr')));
foreach ( $contexts as $context ) {
    $settings = $context->toArray();
    $c_settings = $context->getMany('ContextSettings');
    $site_start_url = '';
    foreach ( $c_settings as $setting ) {
        $settings[$setting->get('key')] = $setting->get('value');
    }
    $listContext .= $modx->getChunk($tpl,$settings);
}
return $listContext;

and have a tpl - chunk like:

<li class='city'><a href="[[~[[+site_start]]]]">[[+context_name]]</a></li>
3 Likes

Thanks, Bruno! That’s an awesome idea

This topic was automatically closed 2 days after discussion ended and a solution was marked. New replies are no longer allowed. You can open a new topic by clicking the link icon below the original post or solution and selecting “+ New Topic”.