You are not logged in.

Announcement

 Téléchargez la dernière version stable de GLPI      -     Et vous, que pouvez vous faire pour le projet GLPI ? :  Contribuer
 Download last stable version of GLPI                      -     What can you do for GLPI ? :  Contribute

#1 2015-09-10 13:06:48

ckiendl
Member
Registered: 2015-09-10
Posts: 2

[0.85.4] Plugins cannot have print CSS (with patch)

The HTML helper class fundamentally enables the system to add print style sheets by making use of the second parameter, an options array, of HTML::css.

The plugin segment of HTML::includeHeader in the current stable release, however, precludes the usage of this parameter by simply taking the given path and dropping it into HTML::css, without any parameters:

echo Html::css($CFG_GLPI["root_doc"]."/plugins/$plugin/$file");

HTML::css, in turn, automatically assumes screen CSS, because it was told nothing else:

      if (!isset($options['media'])) {
         $options['media'] = 'screen';
      }

This unnecessarily prevents plugins from adding a print representation of themselves, which is especially annoying for report plugins.

In order to work around this, I have added the following patch to my own installation:

--- inc/html.class.dist.php    2015-09-07 12:44:13.000000000 +0200
+++ inc/html.class.php    2015-09-10 11:19:42.000000000 +0200
@@ -1027,18 +1027,34 @@
 
       // Add specific css for plugins
       if (isset($PLUGIN_HOOKS['add_css']) && count($PLUGIN_HOOKS['add_css'])) {
-
+         /*
+            expected structure per element:
+            $css_files[0..N]['path'] -> relative path to CSS file, as before
+            $css_files[0..N]['options'] -> array of options suitable for Html:css
+         */
+         $css_files = array();
+         
          foreach ($PLUGIN_HOOKS["add_css"] as $plugin => $files) {
-            if (is_array($files)) {
-               foreach ($files as $file) {
-                  if (file_exists(GLPI_ROOT."/plugins/$plugin/$file")) {
-                     echo Html::css($CFG_GLPI["root_doc"]."/plugins/$plugin/$file");
+            if (is_array($files)) { // either multiple paths or a single path with options
+               if((count($files) === 2) && (!is_array($files[0]) && !array_key_exists(0, $files[1]))) { // single path with options
+                  array_push($css_files, array('path' => $files[0], 'options' => $files[1]));
+               } else { // multiple paths
+                  foreach ($files as $file) {
+                     if(is_array($file)) { // path with options
+                        array_push($css_files, array('path' => $file[0], 'options' => $file[1]));
+                     } else { // path only
+                        array_push($css_files, array('path' => $file, 'options' => array()));
+                     }
                   }
                }
-            } else {
-               if (file_exists(GLPI_ROOT."/plugins/$plugin/$files")) {
-                  echo Html::css($CFG_GLPI["root_doc"]."/plugins/$plugin/$files");
-               }
+            } else { // case where exclusively one path is given
+               array_push($css_files, array('path' => $files, 'options' => array()));
+            }
+         }
+         
+         foreach($css_files as $css) {
+            if (file_exists(GLPI_ROOT."/plugins/$plugin/$css[path]")) {
+               echo Html::css($CFG_GLPI["root_doc"]."/plugins/$plugin/$css[path]", $css['options']);
             }
          }
       }

The current stable code does a simple check: If the contents of $PLUGIN_HOOKS["add_css"]["pluginname"] are an array, it treats them like a list of CSS files, otherwise it treats it as a single path.

My patch expands this behavior with further array checks, allowing the plugin writer to add an options array to his/her plugin CSS. e.g.:

$PLUGIN_HOOKS['add_css']['pluginname'] = array('front/pluginname.css', array('front/pluginname.print.css', array('media' => 'print')));

This code would add one screen style sheet and one print style sheet.
Since the second parameter, the array, is only passed through to HTML::css, the developer should be able to set all other attributes as well.

The updated code might look wild on first glance, but it's actually a very simple chain of checks:

  • Is this an array or not?

  • If not, just treat it as a path.

  • If so, is it a single path with an options array, or is it a list of multiple paths?

  • If it's a single path, process it with its options array

  • If they're multiple paths, do the same check for each element (raw path vs. path with options array) and process them accordingly

This code would be a lot prettier by adding a class or some similar rigid construct for this, because it'd take the guess/checkwork out of the array processing, but this is the only place where that processing is done, and this way, the patch is limited to a few lines in one file.

The example case above is my personal use case. It works, and I'll honestly say it's the only one I care about - i.e. I didn't test any other constellations.
I have written my patch against the latest stable release (0.85.4), as that is what I have installed.

I will check back in case there are any questions, but I'm mostly providing this because I assume I'm not the only one who ran into that problem, so it might help someone else.

P.S.: The captcha is highly annoying.

Offline

#2 2015-12-17 13:58:45

ckiendl
Member
Registered: 2015-09-10
Posts: 2

Re: [0.85.4] Plugins cannot have print CSS (with patch)

Corrected patch, again as a diff to the same stock html.class.php:

--- html.class.dist.php    2015-09-07 12:44:13.000000000 +0200
+++ html.class.php    2015-12-17 12:23:14.000000000 +0100
@@ -1027,19 +1027,37 @@
 
       // Add specific css for plugins
       if (isset($PLUGIN_HOOKS['add_css']) && count($PLUGIN_HOOKS['add_css'])) {
+         /*
+            expected structure per element:
+            $css_files[0..N]['path'] -> relative path to CSS file, as before
+            $css_files[0..N]['options'] -> array of options suitable for Html:css
+         */
+         $css_files = array();
 
          foreach ($PLUGIN_HOOKS["add_css"] as $plugin => $files) {
-            if (is_array($files)) {
-               foreach ($files as $file) {
-                  if (file_exists(GLPI_ROOT."/plugins/$plugin/$file")) {
-                     echo Html::css($CFG_GLPI["root_doc"]."/plugins/$plugin/$file");
+            if (is_array($files)) { // either multiple paths or a single path with options
+               if((count($files) === 2) && (!is_array($files[0]) && !array_key_exists(0, $files[1]))) { // single path with options
+                  array_push($css_files, array('path' => $files[0], 'options' => $files[1]));
+               } else { // multiple paths
+                  foreach ($files as $file) {
+                     if(is_array($file)) { // path with options
+                        array_push($css_files, array('path' => $file[0], 'options' => $file[1]));
+                     } else { // path only
+                        array_push($css_files, array('path' => $file, 'options' => array()));
+                     }
                   }
                }
-            } else {
-               if (file_exists(GLPI_ROOT."/plugins/$plugin/$files")) {
-                  echo Html::css($CFG_GLPI["root_doc"]."/plugins/$plugin/$files");
+            } else { // case where exclusively one path is given
+               array_push($css_files, array('path' => $files, 'options' => array()));
+            }
+            
+            foreach($css_files as $css) {
+               if (file_exists(GLPI_ROOT."/plugins/$plugin/$css[path]")) {
+                  echo Html::css($CFG_GLPI["root_doc"]."/plugins/$plugin/$css[path]", $css['options']);
                }
             }
+            
+            $css_files = array();
          }
       }
 

Offline

Board footer

Powered by FluxBB