initial commit
[namibia] / public / min / lib / Minify / Source.php
1 <?php
2 /**
3  * Class Minify_Source  
4  * @package Minify
5  */
6
7 /** 
8  * A content source to be minified by Minify. 
9  * 
10  * This allows per-source minification options and the mixing of files with
11  * content from other sources.
12  * 
13  * @package Minify
14  * @author Stephen Clay <steve@mrclay.org>
15  */
16 class Minify_Source {
17
18     /**
19      * @var int time of last modification
20      */
21     public $lastModified = null;
22     
23     /**
24      * @var callback minifier function specifically for this source.
25      */
26     public $minifier = null;
27     
28     /**
29      * @var array minification options specific to this source.
30      */
31     public $minifyOptions = null;
32
33     /**
34      * @var string full path of file
35      */
36     public $filepath = null;
37     
38     /**
39      * @var string HTTP Content Type (Minify requires one of the constants Minify::TYPE_*)
40      */
41     public $contentType = null;
42     
43     /**
44      * Create a Minify_Source
45      * 
46      * In the $spec array(), you can either provide a 'filepath' to an existing
47      * file (existence will not be checked!) or give 'id' (unique string for 
48      * the content), 'content' (the string content) and 'lastModified' 
49      * (unixtime of last update).
50      * 
51      * As a shortcut, the controller will replace "//" at the beginning
52      * of a filepath with $_SERVER['DOCUMENT_ROOT'] . '/'.
53      *
54      * @param array $spec options
55      */
56     public function __construct($spec)
57     {
58         if (isset($spec['filepath'])) {
59             if (0 === strpos($spec['filepath'], '//')) {
60                 $spec['filepath'] = $_SERVER['DOCUMENT_ROOT'] . substr($spec['filepath'], 1);
61             }
62             $segments = explode('.', $spec['filepath']);
63             $ext = strtolower(array_pop($segments));
64             switch ($ext) {
65             case 'js'   : $this->contentType = 'application/x-javascript';
66                           break;
67             case 'css'  : $this->contentType = 'text/css';
68                           break;
69             case 'htm'  : // fallthrough
70             case 'html' : $this->contentType = 'text/html';
71                           break;
72             }
73             $this->filepath = $spec['filepath'];
74             $this->_id = $spec['filepath'];
75             $this->lastModified = filemtime($spec['filepath'])
76                 // offset for Windows uploaders with out of sync clocks
77                 + round(Minify::$uploaderHoursBehind * 3600);
78         } elseif (isset($spec['id'])) {
79             $this->_id = 'id::' . $spec['id'];
80             if (isset($spec['content'])) {
81                 $this->_content = $spec['content'];
82             } else {
83                 $this->_getContentFunc = $spec['getContentFunc'];
84             }
85             $this->lastModified = isset($spec['lastModified'])
86                 ? $spec['lastModified']
87                 : time();
88         }
89         if (isset($spec['contentType'])) {
90             $this->contentType = $spec['contentType'];
91         }
92         if (isset($spec['minifier'])) {
93             $this->minifier = $spec['minifier'];
94         }
95         if (isset($spec['minifyOptions'])) {
96             $this->minifyOptions = $spec['minifyOptions'];
97         }
98     }
99     
100     /**
101      * Get content
102      *
103      * @return string
104      */
105     public function getContent()
106     {
107         $content = (null !== $this->filepath)
108             ? file_get_contents($this->filepath)
109             : ((null !== $this->_content)
110                 ? $this->_content
111                 : call_user_func($this->_getContentFunc, $this->_id)
112             );
113         // remove UTF-8 BOM if present
114         return (pack("CCC",0xef,0xbb,0xbf) === substr($content, 0, 3))
115             ? substr($content, 3)
116             : $content;
117     }
118     
119     /**
120      * Get id
121      *
122      * @return string
123      */
124     public function getId()
125     {
126         return $this->_id;
127     }
128     
129     /**
130      * Verifies a single minification call can handle all sources
131      *
132      * @param array $sources Minify_Source instances
133      * 
134      * @return bool true iff there no sources with specific minifier preferences.
135      */
136     public static function haveNoMinifyPrefs($sources)
137     {
138         foreach ($sources as $source) {
139             if (null !== $source->minifier
140                 || null !== $source->minifyOptions) {
141                 return false;
142             }
143         }
144         return true;
145     }
146     
147     /**
148      * Get unique string for a set of sources
149      *
150      * @param array $sources Minify_Source instances
151      * 
152      * @return string
153      */
154     public static function getDigest($sources)
155     {
156         foreach ($sources as $source) {
157             $info[] = array(
158                 $source->_id, $source->minifier, $source->minifyOptions
159             );
160         }
161         return md5(serialize($info));
162     }
163     
164     /**
165      * Get content type from a group of sources
166      * 
167      * This is called if the user doesn't pass in a 'contentType' options  
168      * 
169      * @param array $sources Minify_Source instances
170      * 
171      * @return string content type. e.g. 'text/css'
172      */
173     public static function getContentType($sources)
174     {
175         foreach ($sources as $source) {
176             if ($source->contentType !== null) {
177                 return $source->contentType;
178             }
179         }
180         return 'text/plain';
181     }
182     
183     protected $_content = null;
184     protected $_getContentFunc = null;
185     protected $_id = null;
186 }
187