From c9c81c1a1448012ee88c128ca68be08a4b1e266e Mon Sep 17 00:00:00 2001
From: Chris Hallberg <crhallberg@gmail.com>
Date: Thu, 3 Jul 2014 13:13:54 -0400
Subject: [PATCH] LESS/SCSS support.

---
 .../src/VuFindTheme/Initializer.php           |  8 +-
 .../src/VuFindTheme/ResourceContainer.php     | 69 ++++++++++++++++-
 .../src/VuFindTheme/View/Helper/HeadLink.php  | 74 ++++++++++++++++++-
 .../View/Helper/HeadThemeResources.php        | 18 ++++-
 4 files changed, 164 insertions(+), 5 deletions(-)

diff --git a/module/VuFindTheme/src/VuFindTheme/Initializer.php b/module/VuFindTheme/src/VuFindTheme/Initializer.php
index 751ef013c21..36035ee2481 100644
--- a/module/VuFindTheme/src/VuFindTheme/Initializer.php
+++ b/module/VuFindTheme/src/VuFindTheme/Initializer.php
@@ -337,6 +337,12 @@ class Initializer
             $templatePathStack[] = $this->tools->getBaseDir() . "/$key/templates";
 
             // Add CSS and JS dependencies:
+            if (isset($currentThemeInfo['less'])) {
+                $resources->addLessCss($currentThemeInfo['less']);
+            }
+            if (isset($currentThemeInfo['scss'])) {
+                $resources->addSassCss($currentThemeInfo['scss']);
+            }
             if (isset($currentThemeInfo['css'])) {
                 $resources->addCss($currentThemeInfo['css']);
             }
@@ -366,4 +372,4 @@ class Initializer
             }
         }
     }
-}
\ No newline at end of file
+}
diff --git a/module/VuFindTheme/src/VuFindTheme/ResourceContainer.php b/module/VuFindTheme/src/VuFindTheme/ResourceContainer.php
index 0743a3e28d5..c133505d868 100644
--- a/module/VuFindTheme/src/VuFindTheme/ResourceContainer.php
+++ b/module/VuFindTheme/src/VuFindTheme/ResourceContainer.php
@@ -38,6 +38,20 @@ namespace VuFindTheme;
  */
 class ResourceContainer
 {
+    /**
+     * Less CSS files
+     *
+     * @var array
+     */
+    protected $less = array();
+    
+    /**
+     * Sass CSS files
+     *
+     * @var array
+     */
+    protected $sass = array();
+
     /**
      * CSS files
      *
@@ -73,6 +87,40 @@ class ResourceContainer
      */
     protected $generator = '';
 
+    /**
+     * Add a Less CSS file.
+     *
+     * @param array|string $css Less CSS file (or array of Less CSS files) to add
+     *
+     * @return void
+     */
+    public function addLessCss($less)
+    {
+        if (!is_array($less) && !is_a($less, 'Traversable')) {
+            $less = array($less);
+        }
+        foreach ($less as $current) {
+            $this->less[] = $current;
+        }
+    }
+
+    /**
+     * Add a Sass CSS file.
+     *
+     * @param array|string $css Less CSS file (or array of Less CSS files) to add
+     *
+     * @return void
+     */
+    public function addSassCss($sass)
+    {
+        if (!is_array($sass) && !is_a($less, 'Traversable')) {
+            $sass = array($sass);
+        }
+        foreach ($sass as $current) {
+            $this->sass[] = $current;
+        }
+    }
+
     /**
      * Add a CSS file.
      *
@@ -109,6 +157,25 @@ class ResourceContainer
         }
     }
 
+    /**
+     * Get Less CSS files.
+     *
+     * @return array
+     */
+    public function getLessCss()
+    {
+        return array_unique($this->less);
+    }
+    /**
+     * Get Sass CSS files.
+     *
+     * @return array
+     */
+    public function getSassCss()
+    {
+        return array_unique($this->sass);
+    }
+
     /**
      * Get CSS files.
      *
@@ -194,4 +261,4 @@ class ResourceContainer
     {
         return $this->generator;
     }
-}
\ No newline at end of file
+}
diff --git a/module/VuFindTheme/src/VuFindTheme/View/Helper/HeadLink.php b/module/VuFindTheme/src/VuFindTheme/View/Helper/HeadLink.php
index 41f95a45583..52f908827ab 100644
--- a/module/VuFindTheme/src/VuFindTheme/View/Helper/HeadLink.php
+++ b/module/VuFindTheme/src/VuFindTheme/View/Helper/HeadLink.php
@@ -76,4 +76,76 @@ class HeadLink extends \Zend\View\Helper\HeadLink
 
         return parent::itemToString($item);
     }
-}
\ No newline at end of file
+
+    /**
+     * Compile a less file to css and add to css folder
+     *
+     * @param string $file path to less file
+     *
+     * @return void
+     */
+    public function addLessStylesheet($file)
+    {
+        $relPath = 'less/' . $file;
+        $urlHelper = $this->getView()->plugin('url');
+        $currentTheme = $this->themeInfo->findContainingTheme($relPath);
+        $home = APPLICATION_PATH . "/themes/$currentTheme/";
+        $cssDirectory = $urlHelper('home') . "themes/$currentTheme/css/less/";
+
+        try {
+            $less_files = array(
+                APPLICATION_PATH . '/themes/' . $currentTheme . '/' . $relPath
+                    => $cssDirectory
+            );
+            $themeParents = array_keys($this->themeInfo->getThemeInfo());
+            $directories = array();
+            foreach ($themeParents as $theme) {
+                $directories[APPLICATION_PATH . '/themes/' . $theme . '/less/']
+                    = $cssDirectory;
+            }
+            $css_file_name = \Less_Cache::Get(
+                $less_files,
+                array(
+                    'cache_dir' => $home . 'css/less/',
+                    'cache_method' => false,
+                    'compress' => true,
+                    'import_dirs' => $directories
+                )
+            );
+            $this->prependStylesheet($cssDirectory . $css_file_name);
+        } catch (\Exception $e) {
+            error_log($e->getMessage());
+            list($fileName, ) = explode('.', $file);
+            $this->prependStylesheet($urlHelper('home') . "themes/$currentTheme/css/" . $fileName . '.css');
+        }
+    }
+
+    /**
+     * Compile a scss file to css and add to css folder
+     *
+     * @param string $file path to scss file
+     *
+     * @return void
+     */
+    public function addSassStylesheet($file)
+    {
+        $relPath = 'scss/' . $file;
+        $themeParents = array_keys($this->themeInfo->getThemeInfo());
+        $currentTheme = $themeParents[0];
+        $home = APPLICATION_PATH . "/themes/$currentTheme/";
+        list($fileName, ) = explode('.', $file);
+        $outputFile = $home . 'css/scss/' . $fileName . '.css';
+        $urlHelper = $this->getView()->plugin('url');
+
+        $scss = new \scssc();
+        $paths = array();
+        foreach ($themeParents as $theme) {
+            $paths[] = APPLICATION_PATH . '/themes/' . $theme . '/scss/';
+        }
+        $scss->setImportPaths($paths);
+        $scss->setFormatter('scss_formatter_compressed');
+        $css = $scss->compile('@import "' . $file . '"');
+        $int = file_put_contents($outputFile, $css);
+        $this->prependStylesheet($urlHelper('home') . "themes/$currentTheme/css/scss/" . $fileName . '.css');
+    }
+}
diff --git a/module/VuFindTheme/src/VuFindTheme/View/Helper/HeadThemeResources.php b/module/VuFindTheme/src/VuFindTheme/View/Helper/HeadThemeResources.php
index 50fa6a71c4b..8e274faf518 100644
--- a/module/VuFindTheme/src/VuFindTheme/View/Helper/HeadThemeResources.php
+++ b/module/VuFindTheme/src/VuFindTheme/View/Helper/HeadThemeResources.php
@@ -74,9 +74,11 @@ class HeadThemeResources extends \Zend\View\Helper\AbstractHelper
             $headMeta()->appendName('Generator', $generator);
         }
 
+        // Convenient shortcut to view helper:
+        $headLink = $this->getView()->plugin('headlink');
+
         // Load CSS (make sure we prepend them in the appropriate order; theme
         // resources should load before extras added by individual templates):
-        $headLink = $this->getView()->plugin('headlink');
         foreach (array_reverse($this->container->getCss()) as $current) {
             $parts = explode(':', $current);
             $headLink()->prependStylesheet(
@@ -85,6 +87,18 @@ class HeadThemeResources extends \Zend\View\Helper\AbstractHelper
                 isset($parts[2]) ? trim($parts[2]) : false
             );
         }
+        
+        // Compile and load LESS (make sure we prepend them in the appropriate order
+        // theme resources should load before extras added by individual templates):
+        foreach (array_reverse($this->container->getLessCss()) as $current) {
+            $headLink()->addLessStylesheet($current);
+        }
+
+        // Compile and load SASS (make sure we prepend them in the appropriate order
+        // theme resources should load before extras added by individual templates):
+        foreach (array_reverse($this->container->getSassCss()) as $current) {
+            $headLink()->addSassStylesheet($current);
+        }
 
         // Load Javascript (same ordering considerations as CSS, above):
         $headScript = $this->getView()->plugin('headscript');
@@ -108,4 +122,4 @@ class HeadThemeResources extends \Zend\View\Helper\AbstractHelper
             ));
         }
     }
-}
\ No newline at end of file
+}
-- 
GitLab