_fetchModifiedLinkHook - Required hook that is run when * preparing revert links for properties * * @author Blue Static * @copyright Copyright (c)2002 - 2007, Blue Static * @package ISSO * */ class BSPrinterCss { /** * CSS block list * @var array */ private $descriptors = array(); /** * Master data set * @var array */ private $masterdata = array(); /** * Cutomized data set * @var array */ private $customdata = array(); /** * Valid properties that can be used in CSS * @var array */ private $properties = array( 'background' => 'background', 'color' => 'color', 'font-style' => 'font_style', 'font-size' => 'font_size', 'font-family' => 'font_family', 'text-decoration' => 'text_decoration' ); /** * Hook ran in _fetchModifiedLink; takes three params: $descriptor, $property, $name * @var string */ private $modifiedLinkHook = ':undefined:'; // ################################################################### /** * Constructor */ public function __construct() { BSApp::RequiredModules(array('Db', 'Printer')); } // ################################################################### /** * Sets the function callback that creates a link for modified properties * in the CSS blocks display. It should have the signature: * public string _M(string $descriptor, string $property, string $name) * * @param string Callback function */ public function setModifiedLinkHook($callback) { $this->modifiedLinkHook = $callback; } // ################################################################### /** * Adds a CSS information block to the array for later use * * @param string Block title to display in thead * @param string CSS class/descriptor/element name * @param bool Show the link CSS information */ public function addBlock($title, $descriptor, $dolink) { if (isset($this->descriptors["$descriptor"])) { trigger_error('The descriptor "' . $descriptor . '" already exists'); return; } $this->descriptors["$descriptor"] = array( 'title' => $title, 'descriptor' => $descriptor, 'dolink' => $dolink ); } // ################################################################### /** * Sets a master data key for a given descriptor and property * * @param string Descriptor * @param string Property * @param string Value */ public function setMasterData($descriptor, $property, $value) { $this->masterdata["$descriptor"]["$property"] = $value; } // ################################################################### /** * Sets a custom data key for a given descriptor and property * * @param string Descriptor * @param string Property * @param string Value */ public function setCustomData($descriptor, $property, $value) { $this->customdata["$descriptor"]["$property"] = $value; } // ################################################################### /** * Generates the HTML needed to output the CSS editing blocks; this is * done in the form of using BSPrinter */ public function printEditor() { $lang = array( 'standard_css_attributes' => _('Standard CSS Attributes'), 'extra_css_attributes' => _('Extra CSS Attributes'), 'links_normal' => _('Normal CSS Links'), 'links_visited' => _('Visited CSS Links'), 'links_hover' => _('Hover CSS Links'), 'background' => _('Background'), 'font_color' => _('Font Color'), 'font_style' => _('Font Style'), 'font_size' => _('Font Size'), 'font_family' => _('Font Family'), 'text_decoration' => _('Text Decoration'), 'css_selector' => _('CSS Selector'), 'save_css' => _('Save CSS') ); foreach ($this->descriptors AS $descriptor) { $value = array(); $status = array(); $desc = $descriptor['descriptor']; $table = new BSPrinterRootElementTable(); $head = new BSPrinterTableElement(new BSPrinterLabelElement($descriptor['title'])); $head->setCssClass('tcat'); $table->addHeadingChild($head); foreach ($this->properties AS $prop => $name) { $value["$name"] = $this->_fetchValue($descriptor['descriptor'], $prop); $status["$name"] = $this->_fetchModifiedStatus($descriptor['descriptor'], $prop); } $value['extra'] = $this->_fetchValue($descriptor['descriptor'], 'extra'); $html = "
$lang[standard_css_attributes]
" . $this->_fetchModifiedLink($desc, 'background', $lang['background']) . "
" . $this->_fetchModifiedLink($desc, 'color', $lang['font_color']) . "
" . $this->_fetchModifiedLink($desc, 'font-style', $lang['font_style']) . "
" . $this->_fetchModifiedLink($desc, 'font-size', $lang['font_size']) . "
" . $this->_fetchModifiedLink($desc, 'font-family', $lang['font_family']) . "
" . $this->_fetchModifiedLink($desc, 'extra', $lang['extra_css_attributes']) . "
"; if ($descriptor['dolink']) { foreach (array('a:link' => 'a_link', 'a:visited' => 'a_visited', 'a:hover' => 'a_hover') AS $sel => $selname) { foreach (array('background' => 'background', 'color' => 'color', 'text-decoration' => 'text_decoration') AS $prop => $name) { $value["{$selname}_{$name}"] = $this->_fetchValue($descriptor['descriptor'] . ' ' . $sel, $prop); $status["{$selname}_{$name}"] = $this->_fetchModifiedStatus($descriptor['descriptor'] . ' ' . $sel, $prop); } } $html .= "
$lang[links_normal]
" . $this->_fetchModifiedLink($desc . ' a:link', 'background', $lang['background']) . "
" . $this->_fetchModifiedLink($desc . ' a:link', 'color', $lang['font_color']) . "
" . $this->_fetchModifiedLink($desc . ' a:link', 'text-decoration', $lang['text_decoration']) . "
$lang[links_visited]
" . $this->_fetchModifiedLink($desc . ' a:visited', 'background', $lang['background']) . "
" . $this->_fetchModifiedLink($desc . ' a:visited', 'color', $lang['font_color']) . "
" . $this->_fetchModifiedLink($desc . ' a:visited', 'text-decoration', $lang['text_decoration']) . "
$lang[links_hover]
" . $this->_fetchModifiedLink($desc . ' a:hover', 'background', $lang['background']) . "
" . $this->_fetchModifiedLink($desc . ' a:hover', 'color', $lang['font_color']) . "
" . $this->_fetchModifiedLink($desc . ' a:hover', 'text-decoration', $lang['text_decoration']) . "
"; } $row = new BSPrinterTableElement(new BSPrinterLabelElement($html)); $row->setCssClass('alt2'); $table->addChild($row); $row = new BSPrinterTableElement(new BSPrinterLabelElement('
' . $lang['css_selector'] . ': ' . $descriptor['descriptor'] . '
')); $row->setCssClass('tfoot'); $row->setStyle(array('text-align' => 'right')); $table->addChild($row) echo $table->paint(); } } // ################################################################### /** * Returns the value of a given descriptor and property by comparing * the mater set and custom set then returning the right one * * @param string Descriptor * @param string Property * * @return string Value of the given property */ private function _fetchValue($descriptor, $property) { if (!isset($this->customdata["$descriptor"]["$property"])) { return $this->masterdata["$descriptor"]["$property"]; } else { return $this->customdata["$descriptor"]["$property"]; } } // ################################################################### /** * Returns the state modified state (false for untouched and true * for modified) from the descriptor-property value between the master * set and the custom set of data * * @param string Descriptor * @param string Property * * @return bool Modified from the master value? */ private function _fetchModifiedStatus($descriptor, $property) { return ($this->masterdata["$descriptor"]["$property"] != $this->customdata["$descriptor"]["$property"] AND isset($this->customdata["$descriptor"]["$property"])); } // ################################################################### /** * Fetches a link that shows a revert link for a given property * that uses AJAX to revert when clicked * * @param string Descriptor * @param string Property * @param string Nominalized text * * @return string Output HTML */ private function _fetchModifiedLink($descriptor, $property, $name) { $status = $this->_fetchModifiedStatus($descriptor, $property); if ($status) { if (is_callable($this->modifiedLinkHook)) { return call_user_func($this->modifiedLinkHook, $descriptor, $property, $name); } else { trigger_error('BSPrinterCss::_fetchModifiedLink() needs to have the fetchModifiedLinkHook( $descriptor , $property , $name ) defined'); } } else { return $name; } } // ################################################################### /** * Generates an array of queries that should be run on your database to * update CSS changes. All of the queries have sprintf() markers that * need to be evaluated: * * %1$s - Database table * %2$s - styleid field * %3$s - descriptor field * %4$s - property field * %5$s - value field * %6$d - Styleid value * * @param array Array of user-inputted information to be transformed into queries * * @return array Queries that need to be evaluated then ran */ public function fetchChangeQuery($data) { $queries[0] = '--- RESERVED FOR LATER USE ---'; $deletes = array(); foreach ($this->descriptors AS $descriptor => $opts) { $dolink = $opts['dolink']; if ($dolink) { $loops = array('', ' a:link', ' a:visited', ' a:hover'); } else { $loops = array(''); } foreach ($loops AS $sel) { foreach ($data["$descriptor$sel"] AS $prop => $value) { // the given value matches the master -- no change if ($this->masterdata["$descriptor$sel"]["$prop"] == $value) { continue; } // the given matches the custom -- no change else if (isset($this->customdata["$descriptor$sel"]["$prop"]) AND $this->customdata["$descriptor$sel"]["$prop"] == $value) { continue; } // no matching, it's new else { $value = str_replace('%', '%%', $value); $deletes[] = "%3\$s = '" . $this->_escape($descriptor . $sel) . "' AND %4\$s = '" . $this->_escape($prop) . "'"; $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) . "')"; } } } } if (sizeof($deletes) < 1) { $queries[0] = '##'; } else { $queries[0] = "DELETE FROM %1\$s WHERE styleid = %6\$d AND ((" . implode(') OR (', $deletes) . "))"; } return $queries; } // ################################################################### /** * Wrapper for BSDb->escapeString() * * @param string Unprotected string * * @return string Sanitized string */ private function _escape($string) { return BSApp::GetType('Db')->escapeString($string); } // ################################################################### /** * Generates a linkable/usable CSS stylehseet content file; this can * be outputted to the browser * * @return string CSS output */ public function fetchCssOutput() { $data = array(); foreach ($this->descriptors AS $descriptor => $opts) { $dolink = $opts['dolink']; if ($dolink) { $loops = array('', ' a:link', ' a:visited', ' a:hover'); } else { $loops = array(''); } foreach ($loops AS $sel) { foreach ($this->masterdata["$descriptor$sel"] AS $prop => $value) { $data["$descriptor$sel"]["$prop"] = $value; } if (is_array($this->customdata["$descriptor$sel"])) { foreach ($this->customdata["$descriptor$sel"] AS $prop => $value) { $data["$descriptor$sel"]["$prop"] = $value; } } } } $output = '/* CSS Style Sheet (generated by BSPrinterCss $Revision$) */'; foreach ($data AS $selector => $props) { $output .= "\n\n$selector\n{"; foreach ($props AS $name => $value) { if ($name != 'extra' AND $value != '') { $output .= str_replace('"', '"', "\n\t$name: $value;"); } } if ($props['extra']) { $extra = explode("\n", BSFunctions::ConvertLineBreaks($props['extra'])); foreach ($extra AS $prop) { $output .= "\n\t$prop"; } } $output .= "\n}"; } return $output; } } ?>