Add a menu item

Hi,

how can i add an item in the left menu?

Is there a guide for developers?

Thanks

Full disclosure - the guide is not great and needs improving.

If you are going to contribute your change back to the core Xibo - then there are some processes to follow so that we can integrate your change smoothly. See Contributing to Xibo

If you are developing something for private use - the short answer is that you need to create a theme, which provides an alternative authed.twig in which you can add a new menu item. There is a theme guide here: http://xibo.org.uk/manual-tempel/en/advanced_theme.html

If you are doing that and your link is anything other than an external resource, you will most likely need to provide a route and Controller in order to implement your link. There are 2 ways to do that,

  • Develop in a library and include your controllers via composer
  • Use the /custom folder and code in the Xibo\Custom namespace to have your classes auto-loaded

In either case you will need to add routes via Middleware, which can be done in your web/settings.php file via the $middleware array.

I am doing some work on the user manual at present and will try to improve the article today

1 Like

Thank you Dan.
For this moment it is for a private use, to understand how xibo works.

I have created a new template, and in the authed.twig file added:
{% if currentUser.routeViewable("/test") %} <li class="sidebar-list"><a href="{{ urlFor("test.view") }}">{% trans "Test" %}</a></li> {% endif %}

I want to create a test page with text or buttons.
Now i have to create a controller to manage this page? If yes, how can i create a controller through composer? is there a composer guide or example to create a simple test page?

Many Thanks

I’ll update the manual with an example early next week. Essentially you:

  • Create a Middleware class in the custom folder under the \Xibo\Custom namespace
  • Create a Controller class in the custom folder under the \Xibo\Custom namespace
  • Alter your settings.php file and add to the $middleware array a new instance of your Middleware class
  • In your Middleware class you add your routes, mapped to your Controllers and add your Controllers to the DI ($app->container)

If you are sticking within the Xibo “framework” you could extend the Base controller.

I’ve added some additional information to the manual (which will be published with 1.8.0-rc1) related to creating controllers/routes/etc.

You can see it in its source markdown format here:

I hope to add more to it as time allows, but it will provide a basic example for hooking up a custom route. Feedback welcome (i’ll use any questions to refine the document further)

Many thanks Dan.
Please verify links, because they link an incorrect URL.

Each page links a .html page instead a .md
ex:

The links seem to work for me?

Unfortunately - you won’t be able to navigate around the MD file until we publish it in the final manual. You can either find the corresponding file in the source list, or build the manual yourself by cloning the repository (navigating manually is probably easier!).

1 Like

Ok Dan.

I trying this guide: https://github.com/dasgarner/xibo-manual/blob/develop/source/en/advanced_extending.md
but it shows an “Unexpected Error”.

I followd these steps:

  • I created MyController.php and MyMiddleware.php into Xibo\custom folder
  • in the authed.twig file in Xibo\views i added a new menu voice into the “Advanced” sidebar:
{% if currentUser.routeViewable("/test") %}
                            <li class="sidebar-list"><a href="{{ urlFor("test.view") }}">{% trans "Test" %}</a></li>
                        {% endif %}
  • i added in the setting.php file the additional middleware:
    $middleware = [new \Xibo\Custom\MyMiddleware()];

this is the MyMiddleware.php file:

<?php
namespace Xibo\Custom;

use Slim\Middleware;

class MyMiddleware extends Middleware
{
    public function call()
    {
        $app = $this->getApplication();

        // Register some new routes
        $app->get('/test/view', '\Xibo\Custom\MyController:testView')->setName('test.view');

        // Register a new controller with DI
        // This Controller uses the CMS standard set of dependencies. Your controller can
        // use any dependencies it requires.
        // If you want to inject Factory objects, be wary of circular references.
        $app->container->singleton('\Xibo\Custom\MyController', function($container) {
            return new \Xibo\Custom\MyController(
                $container->logService,
                $container->sanitizerService,
                $container->state,
                $container->user,
                $container->helpService,
                $container->dateService,
                $container->configService
            );
        });

        // Next middleware
        $this->next->call();
    }
}

and this is the MyController.php:

<?php
namespace Xibo\Custom;

use Xibo\Controller\Base;
use Xibo\Service\ConfigServiceInterface;
use Xibo\Service\DateServiceInterface;
use Xibo\Service\LogServiceInterface;
use Xibo\Service\SanitizerServiceInterface;

class MyController extends Base
{

    public function __construct($log, $sanitizerService, $state, $user, $help, $date, $config)
    {
        $this->setCommonDependencies($log, $sanitizerService, $state, $user, $help, $date, $config);
    }

    public function testView()
    {
        // Call to render the template
        $this->getState()->template = 'about-page'; /* temporary page to test */
        $this->getState()->setData([]); /* Data array to provide to the template */
    }
}

Where am I doing wrong?
Thank you very much for your help and patience :slight_smile:

Hi Dan,

Did you try the tutorial? Because me and Cix have some troubles in order to add a menu item and make it works.
Could you please confirm it works by your side?

Many Thanks,

Osvaldo

I did indeed create the classes and register the middleware, etc to make sure it could be loaded without error. However it is not a “complete” article as such. It assumes that you have a custom theme and in the view path of that theme you have twig-template-name-without-extension.twig which is the example response I am returning in the example.

If you edit testView() in the controller and change the method to be:

$this->setNoOutput(true);
echo 'String Output';

Then you will see “String Output” in the browser when you visit that page.

I’ve adjusted the article text to make this clear and added a section on Twig. Ultimately the theme section could do with some work - but I hope for now it is sufficient to look at one of the system pages to see how it works.

I’m trying to log the middleware like this:

class MyMiddleware extends Middleware
{
    public function call()
    {
        $myfile = fopen("log123.txt", "w") or die("Unable to open file!");
        $txt = "Prima\n";
        fwrite($myfile, $txt);

        $app = $this->getApplication();



        // Register some new routes
        $app->get('/test/view', '\Xibo\Custom\Test:testView')->setName('test.view');

        $txt = "Dopo\n";
        fwrite($myfile, $txt);
        fclose($myfile);

        // Register a new controller with DI
        // This Controller uses the CMS standard set of dependencies. Your controller can
        // use any dependencies it requires.
        // If you want to inject Factory objects, be wary of circular references.
        $app->container->singleton('\Xibo\Custom\Test', function($container) {
            return new \Xibo\Custom\Test(
                $container->logService,
                $container->sanitizerService,
                $container->state,
                $container->user,
                $container->helpService,
                $container->dateService,
                $container->configService
            );
        });

        // Next middleware
        $this->next->call();
    }
}

but it can’t enter into the middleware constructor… the log file is not created
But in settings.php i’ve added

$middleware = [new \Xibo\Custom\MyMiddleware()];

without errors…

Perhaps it would be best to remove your middleware from settings.php, switch the CMS to test mode (in Settings) and then put your middleware back.

If you want to log to file you can add an additional log handler in settings.php:

$logHandlers = [new \Monolog\Handler\StreamHandler(PROJECT_ROOT . '/log.txt')];

You can log in middleware with:

$app->logService->debug('Message');

Without an error message it is difficult to help you

Dan, this is the log from the CMS:

[2016-08-09 08:28:26] WEB.ERROR: Missing argument 2 for Xibo\Custom\Test::__construct(), called in /var/www/cms/vendor/akrabat/rka-slim-controller/RKA/Slim.php on line 59 and defined Exception Type: ErrorException [] {"uid":"54ed1a3","method":"GET","route":"/test/view","userId":1}

this is the constructor for my controller:

public function __construct($log, $sanitizerService, $state, $user, $help, $date, $config)
{
$this->setCommonDependencies($log, $sanitizerService, $state, $user, $help, $date, $config);
}

Any suggestions?

Can i send you a zip of my project, or can you send me a working project with these custom controllers?

Thank you very much

This means that your class cannot be found in the $app->container and you should check the names of the classes you’ve added vs their actual names.

Sorry but I don’t have time to do that at the moment - you can paste your code between 3 backticks

Hi Dan,

What does it mean “$app->container and you should check the names of the classes you’ve added vs their actual names.” ?

We are trying to start simple Test controller class. The class name is Test, the filename is Test.php. We are using the same convention used by you for the Help controller class.

Could you please revise the tutorial and try it by your side?

Many Thanks,

Osvaldo

Dan,

i changed the controller name in ‘MyTest’ in all the project.

Now, the error is:

[2016-08-09 09:05:20] WEB.ERROR: An exception has been thrown during the rendering of a template ("Named route not found for name: test.view") in "authed.twig" at line 118. Exception Type: Twig_Error_Runtime [] {"uid":"610e147","method":"GET","route":"/dashboard/status","userId":1}

As I said before, I have already done so and if those files are take and created exactly as described then everything fits together as intended.

You can send me your custom classes and I will take a look - you just need to paste their contents between 3 backticks ` so that they render correctly.

Thank you Dan.

Then, i have created 2 files:
MyMiddleware.php and MyTest.php that is the controller.

this is the MyMiddleware file

<?php
namespace Xibo\Custom;

use Slim\Middleware;

/**
 * Class MyMiddleware
 * @package Xibo\custom
 *
 * Included by instantiation in `settings.php`
 */
class MyMiddleware extends Middleware
{
    public function call()
    {
        $app = $this->getApplication();

        // Register some new routes
        $app->get('/mytest/view', '\Xibo\Custom\MyTest:testView')->setName('mytest.view');

        // Register a new controller with DI
        // This Controller uses the CMS standard set of dependencies. Your controller can
        // use any dependencies it requires.
        // If you want to inject Factory objects, be wary of circular references.
        $app->container->singleton('\Xibo\Custom\MyTest', function($container) {
            return new \Xibo\Custom\MyTest(
                $container->logService,
                $container->sanitizerService,
                $container->state,
                $container->user,
                $container->helpService,
                $container->dateService,
                $container->configService
            );
        });

        // Next middleware
        $this->next->call();
    }
}

and this is the MyTest.php file:

<?php
namespace Xibo\Custom;

use Xibo\Controller\Base;
use Xibo\Service\ConfigServiceInterface;
use Xibo\Service\DateServiceInterface;
use Xibo\Service\LogServiceInterface;
use Xibo\Service\SanitizerServiceInterface;

/**
 * Class MyController
 * @package Xibo\Custom
 */
class MyTest extends Base
{
    /**
     * Set common dependencies.
     * @param LogServiceInterface $log
     * @param SanitizerServiceInterface $sanitizerService
     * @param \Xibo\Helper\ApplicationState $state
     * @param \Xibo\Entity\User $user
     * @param \Xibo\Service\HelpServiceInterface $help
     * @param DateServiceInterface $date
     * @param ConfigServiceInterface $config
     */
    public function __construct($log, $sanitizerService, $state, $user, $help, $date, $config)
    {
        $this->setCommonDependencies($log, $sanitizerService, $state, $user, $help, $date, $config);
    }

    /**
     * Display Page for Test View
     */
    public function testView()
    {
        // Call to render the template
        //$this->getState()->template = 'about-page';
        //$this->getState()->setData([]); /* Data array to provide to the template */
        $this->setNoOutput(true);
        echo 'String Output';
    }
}

in the authed.twig file i’ve added the new menu section into the ‘Advanced’ sidebar :

{% if currentUser.routeViewable("/mytest") %}
                            <li class="sidebar-list"><a href="{{ urlFor("mytest.view") }}">{% trans "Test" %}</a></li>
                        {% endif %}

this is the settings.php file:

<?php

/*
 * Xibo - Digital Signage - http://www.xibo.org.uk
 *
 * This file is part of Xibo - and is automatically generated by the installer
 *
 * You should not need to edit this file, unless your SQL connection details have changed.
 */

defined('XIBO') or die(__("Sorry, you are not allowed to directly access this page.") . "<br />" . __("Please press the back button in your browser."));

global $dbhost;
global $dbuser;
global $dbpass;
global $dbname;

$dbhost = 'mysql';
$dbuser = 'xxxxxxxxx';
$dbpass = 'xxxxxxxxx';
$dbname = 'xxxxxxxxx';

define('SECRET_KEY', 'xxxxxxxxx');

// Additional Monolog handlers/processors to be registered
$logHandlers = [new \Monolog\Handler\StreamHandler(PROJECT_ROOT . '/log12.txt')];
// $logProcessors = [];

try {
// Additional middleware
    $middleware = [new \Xibo\Custom\MyMiddleware()];
// $authentication = ;
}
catch (Exception $e){
    $app->logService->debug('Message: ', $e->getMessage());
}

But when i try to open the CMS it shows this error:
[2016-08-09 10:04:20] WEB.ERROR: An exception has been thrown during the rendering of a template ("Named route not found for name: mytest.view") in "authed.twig" at line 118. Exception Type: Twig_Error_Runtime [] {"uid":"fd93c9d","method":"GET","route":"/dashboard/status","userId":1}

Where are we doing wrong?

That is not the name you have used when you registered the route, see:

$app->get('/mytest/view', '\Xibo\Custom\MyTest:testView')->setName('mytest.view');

You called it “mytest.view”

Thanks,
Dan