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