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