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