Hook is now done like the one in ISSO.Template so we have consistency
[isso.git] / printer_css.php
1 <?php
2 /*=====================================================================*\
3 || ###################################################################
4 || # Iris Studios Shared Object Framework [#]issoversion[#]
5 || # Copyright ©2002-[#]year[#] Iris Studios, Inc.
6 || #
7 || # This program is free software; you can redistribute it and/or modify
8 || # it under the terms of the GNU General Public License as published by
9 || # the Free Software Foundation; version [#]gpl[#] of the License.
10 || #
11 || # This program is distributed in the hope that it will be useful, but
12 || # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 || # or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14 || # more details.
15 || #
16 || # You should have received a copy of the GNU General Public License along
17 || # with this program; if not, write to the Free Software Foundation, Inc.,
18 || # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
19 || ###################################################################
20 \*=====================================================================*/
21
22 /**
23 * Printer - CSS Blocks
24 * printer_css.php
25 *
26 * @package ISSO
27 */
28
29 /**
30 * Printer - CSS Blocks
31 *
32 * This framework works in conjunction with ISSO.Printer to create a unique
33 * CSS editor enviornment.
34 *
35 * @author Iris Studios, Inc.
36 * @copyright Copyright ©2002 - [#]year[#], Iris Studios, Inc.
37 * @version $Revision$
38 * @package ISSO
39 *
40 */
41 class Printer_CSS
42 {
43 /**
44 * Framework registry object
45 * @var object
46 * @access private
47 */
48 var $registry = null;
49
50 /**
51 * CSS block list
52 * @var array
53 * @access private
54 */
55 var $descriptors = array();
56
57 /**
58 * Master data set
59 * @var array
60 * @access private
61 */
62 var $masterdata = array();
63
64 /**
65 * Cutomized data set
66 * @var array
67 * @access private
68 */
69 var $customdata = array();
70
71 /**
72 * Valid properties that can be used in CSS
73 * @var array
74 * @access private
75 */
76 var $properties = array(
77 'background' => 'background',
78 'color' => 'color',
79 'font-style' => 'font_style',
80 'font-size' => 'font_size',
81 'font-family' => 'font_family',
82 'text-decoration' => 'text_decoration'
83 );
84
85 // ###################################################################
86 /**
87 * Constructor
88 */
89 function __construct(&$registry)
90 {
91 $this->registry =& $registry;
92 }
93
94 // ###################################################################
95 /**
96 * (PHP 4) Constructor
97 */
98 function Printer_CSS(&$registry)
99 {
100 $this->__construct($registry);
101 }
102
103 // ###################################################################
104 /**
105 * Adds a CSS information block to the array for later use
106 *
107 * @access public
108 *
109 * @param string Block title to display in thead
110 * @param string CSS class/descriptor/element name
111 * @param bool Show the link CSS information
112 */
113 function add_block($title, $descriptor, $dolink)
114 {
115 if (isset($this->descriptors["$descriptor"]))
116 {
117 trigger_error('The descriptor `' . $descriptor . '` already exists', E_USER_WARNING);
118 return;
119 }
120
121 $this->descriptors["$descriptor"] = array(
122 'title' => $title,
123 'descriptor' => $descriptor,
124 'dolink' => $dolink
125 );
126 }
127
128 // ###################################################################
129 /**
130 * Sets a master data key for a given descriptor and property
131 *
132 * @access public
133 *
134 * @param string Descriptor
135 * @param string Property
136 * @param string Value
137 */
138 function set_master_data($descriptor, $property, $value)
139 {
140 $this->masterdata["$descriptor"]["$property"] = $value;
141 }
142
143 // ###################################################################
144 /**
145 * Sets a custom data key for a given descriptor and property
146 *
147 * @access public
148 *
149 * @param string Descriptor
150 * @param string Property
151 * @param string Value
152 */
153 function set_custom_data($descriptor, $property, $value)
154 {
155 $this->customdata["$descriptor"]["$property"] = $value;
156 }
157
158 // ###################################################################
159 /**
160 * Generates the HTML needed to output the CSS editing blocks; this is
161 * done in the form of using ISSO.Printer
162 *
163 * @access public
164 */
165 function generate_blocks()
166 {
167 $print =& $this->registry->modules['printer'];
168
169 $lang = array(
170 'standard_css_attributes' => $this->registry->modules['localize']->string('Standard CSS Attributes'),
171 'extra_css_attributes' => $this->registry->modules['localize']->string('Extra CSS Attributes'),
172
173 'links_normal' => $this->registry->modules['localize']->string('Normal CSS Links'),
174 'links_visited' => $this->registry->modules['localize']->string('Visited CSS Links'),
175 'links_hover' => $this->registry->modules['localize']->string('Hover CSS Links'),
176
177 'background' => $this->registry->modules['localize']->string('Background'),
178 'font_color' => $this->registry->modules['localize']->string('Font Color'),
179 'font_style' => $this->registry->modules['localize']->string('Font Style'),
180 'font_size' => $this->registry->modules['localize']->string('Font Size'),
181 'font_family' => $this->registry->modules['localize']->string('Font Family'),
182
183 'text_decoration' => $this->registry->modules['localize']->string('Text Decoration'),
184
185 'css_selector' => $this->registry->modules['localize']->string('CSS Selector'),
186 'save_css' => $this->registry->modules['localize']->string('Save CSS')
187 );
188
189 foreach ($this->descriptors AS $descriptor)
190 {
191 $value = array();
192 $status = array();
193
194 $desc = $descriptor['descriptor'];
195
196 $print->table_start();
197 $print->table_head($descriptor['title']);
198
199 foreach ($this->properties AS $prop => $name)
200 {
201 $value["$name"] = $this->fetch_value($descriptor['descriptor'], $prop);
202 $status["$name"] = $this->fetch_modified_status($descriptor['descriptor'], $prop);
203 }
204
205 $value['extra'] = $this->fetch_value($descriptor['descriptor'], 'extra');
206
207 $html = "<table cellspacing=\"0\" cellpadding=\"4\" border=\"0\" width=\"100%\">
208 <tr valign=\"top\">
209 <td width=\"50%\">
210 <fieldset>
211 <legend><strong>$lang[standard_css_attributes]</strong></legend>
212
213 <table cellspacing=\"0\" cellpadding=\"2\" border=\"0\" width=\"100%\">
214 <tr>
215 <td width=\"45%\">" . $this->fetch_modified_link($desc, 'background', $lang['background']) . "</td>
216 <td><input name=\"css[$descriptor[descriptor]][background]\" class=\"input\" style=\"width: 100%\" value=\"$value[background]\" /></td>
217 </tr>
218 <tr>
219 <td width=\"45%\">" . $this->fetch_modified_link($desc, 'color', $lang['font_color']) . "</td>
220 <td><input name=\"css[$descriptor[descriptor]][color]\" class=\"input\" style=\"width: 100%\" value=\"$value[color]\" /></td>
221 </tr>
222 <tr>
223 <td width=\"45%\">" . $this->fetch_modified_link($desc, 'font-style', $lang['font_style']) . "</td>
224 <td><input name=\"css[$descriptor[descriptor]][font-style]\" class=\"input\" style=\"width: 100%\" value=\"$value[font_style]\" /></td>
225 </tr>
226 <tr>
227 <td width=\"45%\">" . $this->fetch_modified_link($desc, 'font-size', $lang['font_size']) . "</td>
228 <td><input name=\"css[$descriptor[descriptor]][font-size]\" class=\"input\" style=\"width: 100%\" value=\"$value[font_size]\" /></td>
229 </tr>
230 <tr>
231 <td width=\"45%\">" . $this->fetch_modified_link($desc, 'font-family', $lang['font_family']) . "</td>
232 <td><input name=\"css[$descriptor[descriptor]][font-family]\" class=\"input\" style=\"width: 100%\" value=\"$value[font_family]\" /></td>
233 </tr>
234 </table>
235 </fieldset>
236 </td>
237
238 <td>
239 <fieldset style=\"height: 115px\">
240 <legend><strong>" . $this->fetch_modified_link($desc, 'extra', $lang['extra_css_attributes']) . "</strong></legend>
241 <textarea name=\"css[$descriptor[descriptor]][extra]\" style=\"width: 100%; height: 90%\">$value[extra]</textarea>
242 </fieldset>
243 </td>
244 </tr>
245 </table>";
246 if ($descriptor['dolink'])
247 {
248 foreach (array('a:link' => 'a_link', 'a:visited' => 'a_visited', 'a:hover' => 'a_hover') AS $sel => $selname)
249 {
250 foreach (array('background' => 'background', 'color' => 'color', 'text-decoration' => 'text_decoration') AS $prop => $name)
251 {
252 $value["{$selname}_{$name}"] = $this->fetch_value($descriptor['descriptor'] . ' ' . $sel, $prop);
253 $status["{$selname}_{$name}"] = $this->fetch_modified_status($descriptor['descriptor'] . ' ' . $sel, $prop);
254 }
255 }
256
257 $html .= "
258
259 <table cellspacing=\"0\" cellpadding=\"4\" border=\"0\" width=\"100%\">
260 <tr valign=\"top\">
261 <td width=\"33%\">
262 <fieldset>
263 <legend><strong>$lang[links_normal]</strong></legend>
264
265 <table cellspacing=\"0\" cellpadding=\"2\" border=\"0\" width=\"100%\">
266 <tr>
267 <td width=\"45%\">" . $this->fetch_modified_link($desc . ' a:link', 'background', $lang['background']) . "</td>
268 <td><input name=\"css[$descriptor[descriptor] a:link][background]\" class=\"input\" style=\"width: 100%\" value=\"$value[a_link_background]\" /></td>
269 </tr>
270 <tr>
271 <td width=\"45%\">" . $this->fetch_modified_link($desc . ' a:link', 'color', $lang['font_color']) . "</td>
272 <td><input name=\"css[$descriptor[descriptor] a:link][color]\" class=\"input\" style=\"width: 100%\" value=\"$value[a_link_color]\" /></td>
273 </tr>
274 <tr>
275 <td width=\"45%\">" . $this->fetch_modified_link($desc . ' a:link', 'text-decoration', $lang['text_decoration']) . "</td>
276 <td><input name=\"css[$descriptor[descriptor] a:link][text-decoration]\" class=\"input\" style=\"width: 100%\" value=\"$value[a_link_text_decoration]\" /></td>
277 </tr>
278 </table>
279 </fieldset>
280 </td>
281
282 <td width=\"33%\">
283 <fieldset>
284 <legend><strong>$lang[links_visited]</strong></legend>
285
286 <table cellspacing=\"0\" cellpadding=\"2\" border=\"0\" width=\"100%\">
287 <tr>
288 <td width=\"45%\">" . $this->fetch_modified_link($desc . ' a:visited', 'background', $lang['background']) . "</td>
289 <td><input name=\"css[$descriptor[descriptor] a:visited][background]\" class=\"input\" style=\"width: 100%\" value=\"$value[a_visited_background]\" /></td>
290 </tr>
291 <tr>
292 <td width=\"45%\">" . $this->fetch_modified_link($desc . ' a:visited', 'color', $lang['font_color']) . "</td>
293 <td><input name=\"css[$descriptor[descriptor] a:visited][color]\" class=\"input\" style=\"width: 100%\" value=\"$value[a_visited_color]\" /></td>
294 </tr>
295 <tr>
296 <td width=\"45%\">" . $this->fetch_modified_link($desc . ' a:visited', 'text-decoration', $lang['text_decoration']) . "</td>
297 <td><input name=\"css[$descriptor[descriptor] a:visited][text-decoration]\" class=\"input\" style=\"width: 100%\" value=\"$value[a_visited_text_decoration]\" /></td>
298 </tr>
299 </table>
300 </fieldset>
301 </td>
302
303 <td width=\"33%\">
304 <fieldset>
305 <legend><strong>$lang[links_hover]</strong></legend>
306
307 <table cellspacing=\"0\" cellpadding=\"2\" border=\"0\" width=\"100%\">
308 <tr>
309 <td width=\"45%\">" . $this->fetch_modified_link($desc . ' a:hover', 'background', $lang['background']) . "</td>
310 <td><input name=\"css[$descriptor[descriptor] a:hover][background]\" class=\"input\" style=\"width: 100%\" value=\"$value[a_hover_background]\" /></td>
311 </tr>
312 <tr>
313 <td width=\"45%\">" . $this->fetch_modified_link($desc . ' a:hover', 'color', $lang['font_color']) . "</td>
314 <td><input name=\"css[$descriptor[descriptor] a:hover][color]\" class=\"input\" style=\"width: 100%\" value=\"$value[a_hover_color]\" /></td>
315 </tr>
316 <tr>
317 <td width=\"45%\">" . $this->fetch_modified_link($desc . ' a:hover', 'text-decoration', $lang['text_decoration']) . "</td>
318 <td><input name=\"css[$descriptor[descriptor] a:hover][text-decoration]\" class=\"input\" style=\"width: 100%\" value=\"$value[a_hover_text_decoration]\" /></td>
319 </tr>
320 </table>
321 </fieldset>
322 </td>
323 </tr>
324 </table>";
325 }
326
327 $print->row_span($html, 'alt2', 'left', 1);
328
329 $print->row_span('
330 <div class="alt1" style="border: inset 1px; padding: 2px 5px 2px 5px; float: left">' . $lang['css_selector'] . ': <code>' . $descriptor['descriptor'] . '</code></div>
331 <input type="submit" name="submit" value="' . $lang['save_css'] . '" class="button" />', 'tfoot', 'right', 1);
332
333 $print->table_end();
334 }
335 }
336
337 // ###################################################################
338 /**
339 * Returns the value of a given descriptor and property by comparing
340 * the mater set and custom set then returning the right one
341 *
342 * @access private
343 *
344 * @param string Descriptor
345 * @param string Property
346 *
347 * @return string Value of the given property
348 */
349 function fetch_value($descriptor, $property)
350 {
351 if (!isset($this->customdata["$descriptor"]["$property"]))
352 {
353 return $this->masterdata["$descriptor"]["$property"];
354 }
355 else
356 {
357 return $this->customdata["$descriptor"]["$property"];
358 }
359 }
360
361 // ###################################################################
362 /**
363 * Returns the state modified state (false for untouched and true
364 * for modified) from the descriptor-property value between the master
365 * set and the custom set of data
366 *
367 * @access private
368 *
369 * @param string Descriptor
370 * @param string Property
371 *
372 * @return bool Modified from the master value?
373 */
374 function fetch_modified_status($descriptor, $property)
375 {
376 if ($this->masterdata["$descriptor"]["$property"] != $this->customdata["$descriptor"]["$property"] AND isset($this->customdata["$descriptor"]["$property"]))
377 {
378 return true;
379 }
380
381 return false;
382 }
383
384 // ###################################################################
385 /**
386 * Fetches a link that shows a revert link for a given property
387 * that uses AJAX to revert when clicked
388 *
389 * @access private
390 *
391 * @param string Descriptor
392 * @param string Property
393 * @param string Nominalized text
394 *
395 * @return string Output HTML
396 */
397 function fetch_modified_link($descriptor, $property, $name)
398 {
399 $status = $this->fetch_modified_status($descriptor, $property);
400
401 if ($status)
402 {
403 return '<em>' . $name . '</em>';
404 }
405 else
406 {
407 return $name;
408 }
409 }
410
411 // ###################################################################
412 /**
413 * Generates an array of queries that should be run on your database to
414 * update CSS changes. All of the queries have sprintf() markers that
415 * need to be evaluated:
416 *
417 * %1$s - Database table
418 * %2$s - styleid field
419 * %3$s - descriptor field
420 * %4$s - property field
421 * %5$s - value field
422 * %6$d - Styleid value
423 *
424 * @access public
425 *
426 * @param array Array of user-inputted information to be transformed into queries
427 *
428 * @return array Queries that need to be evaluated then ran
429 */
430 function generate_change_query($data)
431 {
432 $queries[0] = '--- RESERVED FOR LATER USE ---';
433
434 $deletes = array();
435
436 foreach ($this->descriptors AS $descriptor => $opts)
437 {
438 $dolink = $opts['dolink'];
439
440 if ($dolink)
441 {
442 $loops = array('', ' a:link', ' a:visited', ' a:hover');
443 }
444 else
445 {
446 $loops = array('');
447 }
448
449 foreach ($loops AS $sel)
450 {
451 foreach ($data["$descriptor$sel"] AS $prop => $value)
452 {
453 // the given value matches the master -- no change
454 if ($this->masterdata["$descriptor$sel"]["$prop"] == $value)
455 {
456 continue;
457 }
458 // the given matches the custom -- no change
459 else if (isset($this->customdata["$descriptor$sel"]["$prop"]) AND $this->customdata["$descriptor$sel"]["$prop"] == $value)
460 {
461 continue;
462 }
463 // no matching, it's new
464 else
465 {
466 $deletes[] = "%3\$s = '" . $this->escape($descriptor . $sel) . "' AND %4\$s = '" . $this->escape($prop) . "'";
467 $queries[] = "INSERT INTO %1\$s (%2\$s, %3\$s, %4\$s, %5\$s) VALUES (%6\$d, '" . $this->escape($descriptor . $sel) . "', '" . $this->escape($prop) . "', '" . $this->escape($value) . "')";
468 }
469 }
470 }
471 }
472
473 if (sizeof($deletes) < 1)
474 {
475 $queries[0] = '##';
476 }
477 else
478 {
479 $queries[0] = "DELETE FROM %1\$s WHERE styleid = %6\$d AND ((" . implode(') OR (', $deletes) . "))";
480 }
481
482 return $queries;
483 }
484
485 // ###################################################################
486 /**
487 * Wrapper for $this->registry->modules[ISSO_DB_LAYER]->escape_string()
488 *
489 * @access private
490 *
491 * @param string Unprotected string
492 *
493 * @return string Sanitized string
494 */
495 function escape($string)
496 {
497 return $this->registry->modules[ISSO_DB_LAYER]->escape_string($string);
498 }
499
500 // ###################################################################
501 /**
502 * Generates a linkable/usable CSS stylehseet content file; this can
503 * be outputted to the browser
504 *
505 * @access public
506 *
507 * @return string CSS output
508 */
509 function generate_css_output()
510 {
511 $data = array();
512
513 foreach ($this->descriptors AS $descriptor => $opts)
514 {
515 $dolink = $opts['dolink'];
516
517 if ($dolink)
518 {
519 $loops = array('', ' a:link', ' a:visited', ' a:hover');
520 }
521 else
522 {
523 $loops = array('');
524 }
525
526 foreach ($loops AS $sel)
527 {
528 foreach ($this->masterdata["$descriptor$sel"] AS $prop => $value)
529 {
530 $data["$descriptor$sel"]["$prop"] = $value;
531 }
532 if (is_array($this->customdata["$descriptor$sel"]))
533 {
534 foreach ($this->customdata["$descriptor$sel"] AS $prop => $value)
535 {
536 $data["$descriptor$sel"]["$prop"] = $value;
537 }
538 }
539 }
540 }
541
542 $output = '/* CSS Style Sheet (generated by ISSO.Printer.CSS $Revision$) */';
543
544 foreach ($data AS $selector => $props)
545 {
546 $output .= "\n\n$selector\n{";
547 foreach ($props AS $name => $value)
548 {
549 if ($name != 'extra' AND $value != '')
550 {
551 $output .= "\n\t$name: $value;";
552 }
553 }
554
555 if ($props['extra'])
556 {
557 $extra = explode("\n", $this->registry->modules['functions']->convert_line_breaks($props['extra']));
558
559 foreach ($extra AS $prop)
560 {
561 $output .= "\n\t$prop";
562 }
563 }
564
565 $output .= "\n}";
566 }
567
568 return $output;
569 }
570 }
571
572 /*=====================================================================*\
573 || ###################################################################
574 || # $HeadURL$
575 || # $Id$
576 || ###################################################################
577 \*=====================================================================*/
578 ?>