/** * * unite settings class. * @version 1.1 * */ class UniteSettingsRev{ const COLOR_OUTPUT_FLASH = "flash"; const COLOR_OUTPUT_HTML = "html"; //------------------------------------------------------------ const RELATED_NONE = ""; const TYPE_TEXT = "text"; const TYPE_COLOR = "color"; const TYPE_DATE = "date"; const TYPE_SELECT = "list"; const TYPE_CHECKBOX = "checkbox"; const TYPE_RADIO = "radio"; const TYPE_TEXTAREA = "textarea"; const TYPE_STATIC_TEXT = "statictext"; const TYPE_HR = "hr"; const TYPE_CUSTOM = "custom"; const ID_PREFIX = ""; const TYPE_CONTROL = "control"; const TYPE_BUTTON = "button"; const TYPE_MULTIPLE_TEXT = "multitext"; const TYPE_IMAGE = "image"; const TYPE_CHECKLIST = "checklist"; //------------------------------------------------------------ //set data types const DATATYPE_NUMBER = "number"; const DATATYPE_NUMBEROREMTY = "number_empty"; const DATATYPE_STRING = "string"; const DATATYPE_FREE = "free"; const CONTROL_TYPE_ENABLE = "enable"; const CONTROL_TYPE_DISABLE = "disable"; const CONTROL_TYPE_SHOW = "show"; const CONTROL_TYPE_HIDE = "hide"; //additional parameters that can be added to settings. const PARAM_TEXTSTYLE = "textStyle"; const PARAM_ADDPARAMS = "addparams"; //additional text after the field const PARAM_ADDTEXT = "addtext"; //additional text after the field const PARAM_ADDTEXT_BEFORE_ELEMENT = "addtext_before_element"; //additional text after the field const PARAM_CELLSTYLE = "cellStyle"; //additional text after the field //view defaults: protected $defaultText = "Enter value"; protected $sap_size = 5; //other variables: protected $HRIdCounter = 0; //counter of hr id protected $arrSettings = array(); protected $arrSections = array(); protected $arrIndex = array(); //index of name->index of the settings. protected $arrSaps = array(); //controls: protected $arrControls = array(); //array of items that controlling others (hide/show or enabled/disabled) protected $arrBulkControl = array(); //bulk cotnrol array. if not empty, every settings will be connected with control. //custom functions: protected $customFunction_afterSections = null; protected $colorOutputType = self::COLOR_OUTPUT_HTML; //----------------------------------------------------------------------------------------------- // constructor public function __construct(){ } //----------------------------------------------------------------------------------------------- // get where query according relatedTo and relatedID. private function getWhereQuery(){ $where = "relatedTo='".$this->relatedTo."' and relatedID='".$this->relatedID."'"; return($where); } //----------------------------------------------------------------------------------------------- //set type of color output public function setColorOutputType($type){ $this->colorOutputType = $type; } //----------------------------------------------------------------------------------------------- //set the related to/id for saving/restoring settings. public function setRelated($relatedTo,$relatedID){ $this->relatedTo = $relatedTo; $this->relatedID = $relatedID; } //----------------------------------------------------------------------------------------------- //modify the data before save private function modifySettingsData($arrSettings){ foreach($arrSettings as $key=>$content){ switch(getType($content)){ case "string": //replace the unicode line break (sometimes left after json) $content = str_replace("u000a","\n",$content); $content = str_replace("u000d","",$content); break; case "object": case "array": $content = UniteFunctionsRev::convertStdClassToArray($content); break; } $arrSettings[$key] = $content; } return($arrSettings); } //----------------------------------------------------------------------------------------------- // add the section value to the setting private function checkAndAddSectionAndSap($setting){ //add section if(!empty($this->arrSections)){ $sectionKey = count($this->arrSections)-1; $setting["section"] = $sectionKey; $section = $this->arrSections[$sectionKey]; $sapKey = count($section["arrSaps"])-1; $setting["sap"] = $sapKey; } else{ //please impliment add sap normal!!! - without sections } return($setting); } //----------------------------------------------------------------------------------------------- // validate items parameter. throw exception on error private function validateParamItems($arrParams){ if(!isset($arrParams["items"])) throw new Exception("no select items presented"); if(!is_array($arrParams["items"])) throw new Exception("the items parameter should be array"); //if(empty($arrParams["items"])) throw new Exception("the items array should not be empty"); } //----------------------------------------------------------------------------------------------- //add this setting to index private function addSettingToIndex($name){ $this->arrIndex[$name] = count($this->arrSettings)-1; } //----------------------------------------------------------------------------------------------- //get types array from all the settings: protected function getArrTypes(){ $arrTypesAssoc = array(); $arrTypes = array(); foreach($this->arrSettings as $setting){ $type = $setting["type"]; if(!isset($arrTypesAssoc[$type])) $arrTypes[] = $type; $arrTypesAssoc[$type] = ""; } return($arrTypes); } /** * * modify the values of settings array */ private function modifySettingsValues(){ } /** * * get settings array */ public function getArrSettings(){ return($this->arrSettings); } /** * * get the keys of the settings */ public function getArrSettingNames(){ $arrKeys = array(); $arrNames = array(); foreach($this->arrSettings as $setting){ $name = UniteFunctionsRev::getVal($setting, "name"); if(!empty($name)) $arrNames[] = $name; } return($arrNames); } /** * * get the keys of the settings */ public function getArrSettingNamesAndTitles(){ $arrKeys = array(); $arrNames = array(); foreach($this->arrSettings as $setting){ $name = UniteFunctionsRev::getVal($setting, "name"); $title = UniteFunctionsRev::getVal($setting, "text"); if(!empty($name)) $arrNames[$name] = $title; } return($arrNames); } /** * * get sections */ public function getArrSections(){ return($this->arrSections); } /** * * get controls */ public function getArrControls(){ return($this->arrControls); } /** * * set settings array */ public function setArrSettings($arrSettings){ $this->arrSettings = $arrSettings; } //----------------------------------------------------------------------------------------------- //get number of settings public function getNumSettings(){ $counter = 0; foreach($this->arrSettings as $setting){ switch($setting["type"]){ case self::TYPE_HR: case self::TYPE_STATIC_TEXT: break; default: $counter++; break; } } return($counter); } //private function //----------------------------------------------------------------------------------------------- // add radio group public function addRadio($name,$arrItems,$text = "",$defaultItem="",$arrParams = array()){ $params = array("items"=>$arrItems); $params = array_merge($params,$arrParams); $this->add($name,$defaultItem,$text,self::TYPE_RADIO,$params); } //----------------------------------------------------------------------------------------------- //add text area control public function addTextArea($name,$defaultValue,$text,$arrParams = array()){ $this->add($name,$defaultValue,$text,self::TYPE_TEXTAREA,$arrParams); } //----------------------------------------------------------------------------------------------- //add button control public function addButton($name,$value,$arrParams = array()){ $this->add($name,$value,"",self::TYPE_BUTTON,$arrParams); } //----------------------------------------------------------------------------------------------- // add checkbox element public function addCheckbox($name,$defaultValue = false,$text = "",$arrParams = array()){ $this->add($name,$defaultValue,$text,self::TYPE_CHECKBOX,$arrParams); } //----------------------------------------------------------------------------------------------- //add text box element public function addTextBox($name,$defaultValue = "",$text = "",$arrParams = array()){ $this->add($name,$defaultValue,$text,self::TYPE_TEXT,$arrParams); } //----------------------------------------------------------------------------------------------- //add multiple text box element public function addMultipleTextBox($name,$defaultValue = "",$text = "",$arrParams = array()){ $this->add($name,$defaultValue,$text,self::TYPE_MULTIPLE_TEXT,$arrParams); } //----------------------------------------------------------------------------------------------- //add image selector public function addImage($name,$defaultValue = "",$text = "",$arrParams = array()){ $this->add($name,$defaultValue,$text,self::TYPE_IMAGE,$arrParams); } //----------------------------------------------------------------------------------------------- //add color picker setting public function addColorPicker($name,$defaultValue = "",$text = "",$arrParams = array()){ $this->add($name,$defaultValue,$text,self::TYPE_COLOR,$arrParams); } //----------------------------------------------------------------------------------------------- //add date picker setting public function addDatePicker($name,$defaultValue = "",$text = "",$arrParams = array()){ $this->add($name,$defaultValue,$text,self::TYPE_DATE,$arrParams); } //----------------------------------------------------------------------------------------------- //add date picker setting public function addCodemirror($name,$defaultValue = "",$text = "",$arrParams = array()){ $this->add($name,$defaultValue,$text,'codemirror',$arrParams); } /** * * add custom setting */ public function addCustom($customType,$name,$defaultValue = "",$text = "",$arrParams = array()){ $params = array(); $params["custom_type"] = $customType; $params = array_merge($params,$arrParams); $this->add($name,$defaultValue,$text,self::TYPE_CUSTOM,$params); } //----------------------------------------------------------------------------------------------- //add horezontal sap public function addHr($name="",$params=array()){ $setting = array(); $setting["type"] = self::TYPE_HR; //set item name $itemName = ""; if($name != "") $itemName = $name; else{ //generate hr id $this->HRIdCounter++; $itemName = "hr".$this->HRIdCounter; } $setting["id"] = self::ID_PREFIX.$itemName; $setting["id_row"] = $setting["id"]."_row"; //addsection and sap keys $setting = $this->checkAndAddSectionAndSap($setting); $this->checkAddBulkControl($itemName); $setting = array_merge($params,$setting); $this->arrSettings[] = $setting; //add to settings index $this->addSettingToIndex($itemName); } //----------------------------------------------------------------------------------------------- //add static text public function addStaticText($text,$name="",$params=array()){ $setting = array(); $setting["type"] = self::TYPE_STATIC_TEXT; //set item name $itemName = ""; if($name != "") $itemName = $name; else{ //generate hr id $this->HRIdCounter++; $itemName = "textitem".$this->HRIdCounter; } $setting["id"] = self::ID_PREFIX.$itemName; $setting["id_row"] = $setting["id"]."_row"; $setting["text"] = $text; $this->checkAddBulkControl($itemName); $params = array_merge($params,$setting); //addsection and sap keys $setting = $this->checkAndAddSectionAndSap($setting); $this->arrSettings[] = $setting; //add to settings index $this->addSettingToIndex($itemName); } /** * add select setting */ public function addSelect($name,$arrItems,$text,$defaultItem="",$arrParams=array()){ $params = array("items"=>$arrItems); $params = array_merge($params,$arrParams); $this->add($name,$defaultItem,$text,self::TYPE_SELECT,$params); } /** * add select setting */ public function addChecklist($name,$arrItems,$text,$defaultItem="",$arrParams=array()){ $params = array("items"=>$arrItems); $params = array_merge($params,$arrParams); $this->add($name,$defaultItem,$text,self::TYPE_CHECKLIST,$params); } /** * * add saporator */ public function addSap($text, $name="", $opened = false, $icon=""){ if(empty($text)) UniteFunctionsRev::throwError("sap $name must have a text"); //create sap array $sap = array(); $sap["name"] = $name; $sap["text"] = $text; $sap["icon"] = $icon; if($opened == true) $sap["opened"] = true; //add sap to current section if(!empty($this->arrSections)){ $lastSection = end($this->arrSections); $section_keys = array_keys($this->arrSections); $lastSectionKey = end($section_keys); $arrSaps = $lastSection["arrSaps"]; $arrSaps[] = $sap; $this->arrSections[$lastSectionKey]["arrSaps"] = $arrSaps; $sap_keys = array_keys($arrSaps); $sapKey = end($sap_keys); } else{ $this->arrSaps[] = $sap; } } //----------------------------------------------------------------------------------------------- //get sap data: public function getSap($sapKey,$sectionKey=-1){ //get sap without sections: if($sectionKey == -1) return($this->arrSaps[$sapKey]); if(!isset($this->arrSections[$sectionKey])) throw new Exception("Sap on section:".$sectionKey." doesn't exists"); $arrSaps = $this->arrSections[$sectionKey]["arrSaps"]; if(!isset($arrSaps[$sapKey])) throw new Exception("Sap with key:".$sapKey." doesn't exists"); $sap = $arrSaps[$sapKey]; return($sap); } //----------------------------------------------------------------------------------------------- // add a new section. Every settings from now on will be related to this section public function addSection($label,$name=""){ if(!empty($this->arrSettings) && empty($this->arrSections)) UniteFunctionsRev::throwError("You should add first section before begin to add settings. (section: $text)"); if(empty($label)) UniteFunctionsRev::throwError("You have some section without text"); $arrSection = array( "text"=>$label, "arrSaps"=>array(), "name"=>$name ); $this->arrSections[] = $arrSection; } //----------------------------------------------------------------------------------------------- //add setting, may be in different type, of values protected function add($name,$defaultValue = "",$text = "",$type = self::TYPE_TEXT,$arrParams = array()){ //validation: if(empty($name)) throw new Exception("Every setting should have a name!"); switch($type){ case self::TYPE_RADIO: case self::TYPE_SELECT: $this->validateParamItems($arrParams); break; case self::TYPE_CHECKBOX: if(!is_bool($defaultValue)) throw new Exception("The checkbox value should be boolean"); break; } //validate name: if(isset($this->arrIndex[$name])) throw new Exception("Duplicate setting name:".$name); $this->checkAddBulkControl($name); //set defaults: if($text == "") $text = $this->defaultText; $setting = array(); $setting["name"] = $name; $setting["id"] = self::ID_PREFIX.$name; $setting["id_service"] = $setting["id"]."_service"; $setting["id_row"] = $setting["id"]."_row"; $setting["type"] = $type; $setting["text"] = $text; $setting["value"] = $defaultValue; $setting = array_merge($setting,$arrParams); //set datatype if(!isset($setting["datatype"])){ $datatype = self::DATATYPE_STRING; switch ($type){ case self::TYPE_TEXTAREA: $datatype = self::DATATYPE_FREE; break; default: $datatype = self::DATATYPE_STRING; break; } $setting["datatype"] = $datatype; } //addsection and sap keys $setting = $this->checkAndAddSectionAndSap($setting); $this->arrSettings[] = $setting; //add to settings index $this->addSettingToIndex($name); } //----------------------------------------------------------------------------------------------- //add a item that controlling visibility of enabled/disabled of other. public function addControl($control_item_name,$controlled_item_name,$control_type,$value){ UniteFunctionsRev::validateNotEmpty($control_item_name,"control parent"); UniteFunctionsRev::validateNotEmpty($controlled_item_name,"control child"); UniteFunctionsRev::validateNotEmpty($control_type,"control type"); UniteFunctionsRev::validateNotEmpty($value,"control value"); $arrControl = array(); if(isset($this->arrControls[$control_item_name])) $arrControl = $this->arrControls[$control_item_name]; $arrControl[] = array("name"=>$controlled_item_name,"type"=>$control_type,"value"=>$value); $this->arrControls[$control_item_name] = $arrControl; } //----------------------------------------------------------------------------------------------- //start control of all settings that comes after this function (between startBulkControl and endBulkControl) public function startBulkControl($control_item_name,$control_type,$value){ $this->arrBulkControl = array("control_name"=>$control_item_name,"type"=>$control_type,"value"=>$value); } //----------------------------------------------------------------------------------------------- //end bulk control public function endBulkControl(){ $this->arrBulkControl = array(); } //----------------------------------------------------------------------------------------------- //build name->(array index) of the settings. private function buildArrSettingsIndex(){ $this->arrIndex = array(); foreach($this->arrSettings as $key=>$value) if(isset($value["name"])) $this->arrIndex[$value["name"]] = $key; } //----------------------------------------------------------------------------------------------- // set sattes of the settings (enabled/disabled, visible/invisible) by controls public function setSettingsStateByControls(){ foreach($this->arrControls as $control_name => $arrControlled){ //take the control value if(!isset($this->arrIndex[$control_name])) throw new Exception("There is not sutch control setting: '$control_name'"); $index = $this->arrIndex[$control_name]; $parentValue = strtolower($this->arrSettings[$index]["value"]); //set child (controlled) attributes foreach($arrControlled as $controlled){ if(!isset($this->arrIndex[$controlled["name"]])) throw new Exception("There is not sutch controlled setting: '".$controlled["name"]."'"); $indexChild = $this->arrIndex[$controlled["name"]]; $child = $this->arrSettings[$indexChild]; $value = strtolower($controlled["value"]); switch($controlled["type"]){ case self::CONTROL_TYPE_ENABLE: if($value != $parentValue) $child["disabled"] = true; break; case self::CONTROL_TYPE_DISABLE: if($value == $parentValue) $child["disabled"] = true; break; case self::CONTROL_TYPE_SHOW: if($value != $parentValue) $child["hidden"] = true; break; case self::CONTROL_TYPE_HIDE: if($value == $parentValue) $child["hidden"] = true; break; } $this->arrSettings[$indexChild] = $child; } }//end foreach } //----------------------------------------------------------------------------------------------- //check that bulk control is available , and add some element to it. private function checkAddBulkControl($name){ //add control if(!empty($this->arrBulkControl)) $this->addControl($this->arrBulkControl["control_name"],$name,$this->arrBulkControl["type"],$this->arrBulkControl["value"]); } //----------------------------------------------------------------------------------------------- //set custom function that will be run after sections will be drawen public function setCustomDrawFunction_afterSections($func){ $this->customFunction_afterSections = $func; } /** * * parse options from xml field * @param $field */ private function getOptionsFromXMLField($field,$fieldName){ $arrOptions = array(); $arrField = (array)$field; $options = UniteFunctionsRev::getVal($arrField, "option"); if(empty($options)) return($arrOptions); foreach($options as $option){ if(gettype($option) == "string") UniteFunctionsRev::throwError("Wrong options type: ".$option." in field: $fieldName"); $attribs = $option->attributes(); $optionValue = (string)UniteFunctionsRev::getVal($attribs, "value"); $optionText = (string)UniteFunctionsRev::getVal($attribs, "text"); //validate options: UniteFunctionsRev::validateNotEmpty($optionValue,"option value"); UniteFunctionsRev::validateNotEmpty($optionText,"option text"); $arrOptions[$optionValue] = $optionText; } return($arrOptions); } /** * * load settings from xml file */ public function loadXMLFile($filepath){ if(!file_exists($filepath)) UniteFunctionsRev::throwError("File: '$filepath' not exists!!!"); $obj = simplexml_load_file($filepath); if(empty($obj)) UniteFunctionsRev::throwError("Wrong xml file format: $filepath"); $fieldsets = $obj->fieldset; if(!@count($obj->fieldset)){ $fieldsets = array($fieldsets); } $this->addSection("Xml Settings"); foreach($fieldsets as $fieldset){ //Add Section $attribs = $fieldset->attributes(); $sapName = (string)UniteFunctionsRev::getVal($attribs, "name"); $sapLabel = (string)UniteFunctionsRev::getVal($attribs, "label"); $sapIcon = (string)UniteFunctionsRev::getVal($attribs, "icon"); UniteFunctionsRev::validateNotEmpty($sapName,"sapName"); UniteFunctionsRev::validateNotEmpty($sapLabel,"sapLabel"); $this->addSap($sapLabel,$sapName,false,$sapIcon); //--- add fields $fieldset = (array)$fieldset; $fields = $fieldset["field"]; if(is_array($fields) == false) $fields = array($fields); foreach($fields as $field){ $attribs = $field->attributes(); $fieldType = (string)UniteFunctionsRev::getVal($attribs, "type"); $fieldName = (string)UniteFunctionsRev::getVal($attribs, "name"); $fieldLabel = (string)UniteFunctionsRev::getVal($attribs, "label"); $fieldDefaultValue = (string)UniteFunctionsRev::getVal($attribs, "default"); //all other params will be added to "params array". $arrMustParams = array("type","name","label","default"); $arrParams = array(); foreach($attribs as $key=>$value){ $key = (string)$key; $value = (string)$value; //skip must params: if(in_array($key, $arrMustParams)) continue; $arrParams[$key] = $value; } $options = $this->getOptionsFromXMLField($field,$fieldName); //validate must fields: UniteFunctionsRev::validateNotEmpty($fieldType,"type"); //validate name if($fieldType != self::TYPE_HR && $fieldType != self::TYPE_CONTROL && $fieldType != "bulk_control_start" && $fieldType != "bulk_control_end") UniteFunctionsRev::validateNotEmpty($fieldName,"name"); switch ($fieldType){ case self::TYPE_CHECKBOX: $fieldDefaultValue = UniteFunctionsRev::strToBool($fieldDefaultValue); $this->addCheckbox($fieldName,$fieldDefaultValue,$fieldLabel,$arrParams); break; case self::TYPE_COLOR: $this->addColorPicker($fieldName,$fieldDefaultValue,$fieldLabel,$arrParams); break; case self::TYPE_HR: $this->addHr(); break; case self::TYPE_TEXT: $this->addTextBox($fieldName,$fieldDefaultValue,$fieldLabel,$arrParams); break; case self::TYPE_MULTIPLE_TEXT: $this->addMultipleTextBox($fieldName,$fieldDefaultValue,$fieldLabel,$arrParams); break; case self::TYPE_STATIC_TEXT: $this->addStaticText($fieldLabel, $fieldName, $arrParams); break; case self::TYPE_IMAGE: $this->addImage($fieldName,$fieldDefaultValue,$fieldLabel,$arrParams); break; case self::TYPE_SELECT: $this->addSelect($fieldName, $options, $fieldLabel,$fieldDefaultValue,$arrParams); break; case self::TYPE_CHECKBOX: $this->addChecklist($fieldName, $options, $fieldLabel,$fieldDefaultValue,$arrParams); break; case self::TYPE_RADIO: $this->addRadio($fieldName, $options, $fieldLabel,$fieldDefaultValue,$arrParams); break; case self::TYPE_TEXTAREA: $this->addTextArea($fieldName, $fieldDefaultValue, $fieldLabel, $arrParams); break; case self::TYPE_CUSTOM: $this->add($fieldName, $fieldDefaultValue, $fieldLabel, self::TYPE_CUSTOM, $arrParams); break; case self::TYPE_BUTTON: $this->addButton($fieldName, $fieldDefaultValue, $arrParams); break; case self::TYPE_CONTROL: $parent = UniteFunctionsRev::getVal($arrParams, "parent"); $child = UniteFunctionsRev::getVal($arrParams, "child"); $ctype = UniteFunctionsRev::getVal($arrParams, "ctype"); $value = UniteFunctionsRev::getVal($arrParams, "value"); $this->addControl($parent, $child, $ctype, $value); break; case "bulk_control_start": $parent = UniteFunctionsRev::getVal($arrParams, "parent"); $ctype = UniteFunctionsRev::getVal($arrParams, "ctype"); $value = UniteFunctionsRev::getVal($arrParams, "value"); $this->startBulkControl($parent, $ctype, $value); break; case "bulk_control_end": $this->endBulkControl(); break; case "codemirror": $this->addCodemirror($fieldName,$fieldDefaultValue,$fieldLabel,$arrParams); break; default: UniteFunctionsRev::throwError("wrong type: $fieldType"); break; } } } } /** * * get titles and descriptions array */ public function getArrTextFromAllSettings(){ $arr = array(); $arrUnits = array(); //get saps array: foreach($this->arrSections as $section){ $arrSaps = UniteFunctionsRev::getVal($section, "arrSaps"); if(empty($arrSaps)) continue; foreach($arrSaps as $sap){ $text = $sap["text"]; if(!empty($text)) $arr[] = $text; } } foreach($this->arrSettings as $setting){ $text = UniteFunctionsRev::getVal($setting, "text"); $desc = UniteFunctionsRev::getVal($setting, "description"); $unit = UniteFunctionsRev::getVal($setting, "unit"); if(!empty($text)) $arr[] = $text; if(!empty($desc)) $arr[] = $desc; if(!empty($unit)){ if(!isset($arrUnits[$unit])) $arr[] = $unit; $arrUnits[$unit] = true; } $items = UniteFunctionsRev::getVal($setting, "items"); if(!empty($items)){ foreach($items as $item){ if(!isset($arrUnits[$item])) $arr[] = $item; $arrUnits[$item] = true; } } } return($arr); } /** * * get setting array by name */ public function getSettingByName($name){ //if index present if(!empty($this->arrIndex)){ if(array_key_exists($name, $this->arrIndex) == false) UniteFunctionsRev::throwError("setting $name not found"); $index = $this->arrIndex[$name]; $setting = $this->arrSettings[$index]; return($setting); } //if no index foreach($this->arrSettings as $setting){ $settingName = UniteFunctionsRev::getVal($setting, "name"); if($settingName == $name) return($setting); } UniteFunctionsRev::throwError("Setting with name: $name don't exists"); } /** * * get value of some setting * @param $name */ public function getSettingValue($name,$default=""){ $setting = $this->getSettingByName($name); $value = UniteFunctionsRev::getVal($setting, "value",$default); return($value); } /** * * update setting array by name */ public function updateArrSettingByName($name,$setting){ foreach($this->arrSettings as $key => $settingExisting){ $settingName = UniteFunctionsRev::getVal($settingExisting,"name"); if($settingName == $name){ $this->arrSettings[$key] = $setting; return(false); } } UniteFunctionsRev::throwError("Setting with name: $name don't exists"); } /** * * update default value in the setting */ public function updateSettingValue($name,$value){ $setting = $this->getSettingByName($name); $setting["value"] = $value; $this->updateArrSettingByName($name, $setting); } /** * * modify some value by it's datatype */ public function modifyValueByDatatype($value,$datatype){ if(is_array($value)){ foreach($value as $key => $val){ $value[$key] = $this->modifyValueByDatatypeFunc($val,$datatype); } }else{ $value = $this->modifyValueByDatatypeFunc($value,$datatype); } return($value); } /** * * modify some value by it's datatype */ public function modifyValueByDatatypeFunc($value,$datatype){ switch($datatype){ case self::DATATYPE_STRING: $value = strip_tags($value, ''); break; case self::DATATYPE_NUMBER: $value = floatval($value); //turn every string to float if(!is_numeric($value)) $value = 0; break; case self::DATATYPE_NUMBEROREMTY: $value = trim($value); if($value !== "") $value = floatval($value); //turn every string to float break; } return $value; } /** * * set values from array of stored settings elsewhere. */ public function setStoredValues($arrValues){ foreach($this->arrSettings as $key=>$setting){ $name = UniteFunctionsRev::getVal($setting, "name"); //type consolidation $type = UniteFunctionsRev::getVal($setting, "type"); $datatype = UniteFunctionsRev::getVal($setting, "datatype"); //skip custom type $customType = UniteFunctionsRev::getVal($setting, "custom_type"); if(!empty($customType)) continue; if(array_key_exists($name, $arrValues)){ $value = $arrValues[$name]; $value = $this->modifyValueByDatatype($value, $datatype); $this->arrSettings[$key]["value"] = $value; $arrValues[$name] = $value; } }//end foreach return($arrValues); } /** * get setting values. replace from stored ones if given */ public function getArrValues(){ $arrSettingsOutput = array(); //modify settings by type foreach($this->arrSettings as $setting){ if($setting["type"] == self::TYPE_HR ||$setting["type"] == self::TYPE_STATIC_TEXT) continue; $value = $setting["value"]; //modify value by type switch($setting["type"]){ case self::TYPE_COLOR: $value = strtolower($value); //set color output type if($this->colorOutputType == self::COLOR_OUTPUT_FLASH) $value = str_replace("#","0x",$value); break; case self::TYPE_CHECKBOX: if($value == true) $value = "true"; else $value = "false"; break; } //remove lf if(isset($setting["remove_lf"])){ $value = str_replace("\n","",$value); $value = str_replace("\r\n","",$value); } $arrSettingsOutput[$setting["name"]] = $value; } return($arrSettingsOutput); } /** * Update values from post meta */ public function updateValuesFromPostMeta($postID){ //update setting values array from meta $arrNames = $this->getArrSettingNames(); $arrValues = array(); $arrMeta = get_post_meta($postID); if(!empty($arrMeta) && is_array($arrMeta)){ foreach($arrNames as $name){ if(array_key_exists($name, $arrMeta) == false) continue; $value = get_post_meta($postID, $name,true); $arrValues[$name] = $value; } } //dmp($postID);dmp($arrValues);exit(); $this->setStoredValues($arrValues); } } ?> class UniteImageViewRev{ private $pathCache; private $pathImages; private $urlImages; private $filename = null; private $maxWidth = null; private $maxHeight = null; private $type = null; private $effect = null; private $effect_arg1 = null; private $effect_arg2 = null; const EFFECT_BW = "bw"; const EFFECT_BRIGHTNESS = "bright"; const EFFECT_CONTRAST = "contrast"; const EFFECT_EDGE = "edge"; const EFFECT_EMBOSS = "emboss"; const EFFECT_BLUR = "blur"; const EFFECT_BLUR3 = "blur3"; const EFFECT_MEAN = "mean"; const EFFECT_SMOOTH = "smooth"; const EFFECT_DARK = "dark"; const TYPE_EXACT = "exact"; const TYPE_EXACT_TOP = "exacttop"; private $jpg_quality = 81; public function __construct($pathCache,$pathImages,$urlImages){ $this->pathCache = $pathCache; $this->pathImages = $pathImages; $this->urlImages = $urlImages; } /** * * set jpg quality output */ public function setJPGQuality($quality){ $this->jpg_quality = $quality; } /** * * get thumb url */ public static function getUrlThumb($urlBase, $filename,$width=null,$height=null,$exact=false,$effect=null,$effect_param=null){ $filename = urlencode($filename); $url = $urlBase."&img=$filename"; if(!empty($width)) $url .= "&w=".$width; if(!empty($height)) $url .= "&h=".$height; if($exact == true){ $url .= "&t=".self::TYPE_EXACT; } if(!empty($effect)){ $url .= "&e=".$effect; if(!empty($effect_param)) $url .= "&ea1=".$effect_param; } return($url); } /** * * throw error */ private function throwError($message,$code=null){ UniteFunctionsRev::throwError($message,$code); } /** * * get filename for thumbnail save / retrieve * TODO: do input validations - security measures */ private function getThumbFilename(){ $info = pathInfo($this->filename); //add dirname as postfix (if exists) $postfix = ""; $dirname = UniteFunctionsRev::getVal($info, "dirname"); if(!empty($dirname)){ $postfix = str_replace("/", "-", $dirname); } $ext = $info["extension"]; $name = $info["filename"]; $width = ceil($this->maxWidth); $height = ceil($this->maxHeight); $thumbFilename = $name."_".$width."x".$height; if(!empty($this->type)) $thumbFilename .= "_" . $this->type; if(!empty($this->effect)){ $thumbFilename .= "_e" . $this->effect; if(!empty($this->effect_arg1)){ $thumbFilename .= "x" . $this->effect_arg1; } } //add postfix if(!empty($postfix)) $thumbFilename .= "_".$postfix; $thumbFilename .= ".".$ext; return($thumbFilename); } //------------------------------------------------------------------------------------------ // get thumbnail fielpath by parameters. private function getThumbFilepath(){ $filename = $this->getThumbFilename(); $filepath = $this->pathCache .$filename; return($filepath); } //------------------------------------------------------------------------------------------ // ouptput emtpy image code. private function outputEmptyImageCode(){ echo "empty image"; exit(); } //------------------------------------------------------------------------------------------ // outputs image and exit. private function outputImage($filepath){ $info = UniteFunctionsRev::getPathInfo($filepath); $ext = $info["extension"]; //$filetime = filemtime($filepath); $ext = strtolower($ext); if($ext == "jpg") $ext = "jpeg"; $numExpires = 31536000; //one year $strExpires = @date('D, d M Y H:i:s',time()+$numExpires); //$strModified = @date('D, d M Y H:i:s',$filetime); $contents = file_get_contents($filepath); $filesize = strlen($contents); /*header("Last-Modified: $strModified GMT");*/ header("Expires: $strExpires GMT"); header("Cache-Control: public"); header("Content-Type: image/$ext"); header("Content-Length: $filesize"); echo $contents; exit(); } //------------------------------------------------------------------------------------------ // get src image from filepath according the image type private function getGdSrcImage($filepath,$type){ // create the image $src_img = false; switch($type){ case IMAGETYPE_JPEG: $src_img = @imagecreatefromjpeg($filepath); break; case IMAGETYPE_PNG: $src_img = @imagecreatefrompng($filepath); break; case IMAGETYPE_GIF: $src_img = @imagecreatefromgif($filepath); break; case IMAGETYPE_BMP: $src_img = @imagecreatefromwbmp($filepath); break; default: $this->throwError("wrong image format, can't resize"); break; } if($src_img == false){ $this->throwError("Can't resize image"); } return($src_img); } //------------------------------------------------------------------------------------------ // save gd image to some filepath. return if success or not private function saveGdImage($dst_img,$filepath,$type){ $successSaving = false; switch($type){ case IMAGETYPE_JPEG: $successSaving = imagejpeg($dst_img,$filepath,$this->jpg_quality); break; case IMAGETYPE_PNG: $successSaving = imagepng($dst_img,$filepath); break; case IMAGETYPE_GIF: $successSaving = imagegif($dst_img,$filepath); break; case IMAGETYPE_BMP: $successSaving = imagewbmp($dst_img,$filepath); break; } return($successSaving); } //------------------------------------------------------------------------------------------ // crop image to specifix height and width , and save it to new path private function cropImageSaveNew($filepath,$filepathNew){ $imgInfo = getimagesize($filepath); $imgType = $imgInfo[2]; $src_img = $this->getGdSrcImage($filepath,$imgType); $width = imageSX($src_img); $height = imageSY($src_img); //crop the image from the top $startx = 0; $starty = 0; //find precrop width and height: $percent = $this->maxWidth / $width; $newWidth = $this->maxWidth; $newHeight = ceil($percent * $height); if($this->type == "exact"){ //crop the image from the middle $startx = 0; $starty = ($newHeight-$this->maxHeight)/2 / $percent; } if($newHeight < $this->maxHeight){ //by width $percent = $this->maxHeight / $height; $newHeight = $this->maxHeight; $newWidth = ceil($percent * $width); if($this->type == "exact"){ //crop the image from the middle $startx = ($newWidth - $this->maxWidth) /2 / $percent; //the startx is related to big image $starty = 0; } } //resize the picture: $tmp_img = ImageCreateTrueColor($newWidth,$newHeight); $this->handleTransparency($tmp_img,$imgType,$newWidth,$newHeight); imagecopyresampled($tmp_img,$src_img,0,0,$startx,$starty,$newWidth,$newHeight,$width,$height); $this->handleImageEffects($tmp_img); //crop the picture: $dst_img = ImageCreateTrueColor($this->maxWidth,$this->maxHeight); $this->handleTransparency($dst_img,$imgType,$this->maxWidth,$this->maxHeight); imagecopy($dst_img, $tmp_img, 0, 0, 0, 0, $newWidth, $newHeight); //save the picture $is_saved = $this->saveGdImage($dst_img,$filepathNew,$imgType); imagedestroy($dst_img); imagedestroy($src_img); imagedestroy($tmp_img); return($is_saved); } //------------------------------------------------------------------------------------------ // if the images are png or gif - handle image transparency private function handleTransparency(&$dst_img,$imgType,$newWidth,$newHeight){ //handle transparency: if($imgType == IMAGETYPE_PNG || $imgType == IMAGETYPE_GIF){ imagealphablending($dst_img, false); imagesavealpha($dst_img,true); $transparent = imagecolorallocatealpha($dst_img, 255, 255, 255, 127); imagefilledrectangle($dst_img, 0, 0, $newWidth, $newHeight, $transparent); } } //------------------------------------------------------------------------------------------ // handle image effects private function handleImageEffects(&$imgHandle){ if(empty($this->effect)) return(false); switch($this->effect){ case self::EFFECT_BW: if(defined("IMG_FILTER_GRAYSCALE")) imagefilter($imgHandle,IMG_FILTER_GRAYSCALE); break; case self::EFFECT_BRIGHTNESS: if(defined("IMG_FILTER_BRIGHTNESS")){ if(!is_numeric($this->effect_arg1)) $this->effect_arg1 = 50; //set default value UniteFunctionsRev::validateNumeric($this->effect_arg1,"'ea1' argument"); imagefilter($imgHandle,IMG_FILTER_BRIGHTNESS,$this->effect_arg1); } break; case self::EFFECT_DARK: if(defined("IMG_FILTER_BRIGHTNESS")){ if(!is_numeric($this->effect_arg1)) $this->effect_arg1 = -50; //set default value UniteFunctionsRev::validateNumeric($this->effect_arg1,"'ea1' argument"); imagefilter($imgHandle,IMG_FILTER_BRIGHTNESS,$this->effect_arg1); } break; case self::EFFECT_CONTRAST: if(defined("IMG_FILTER_CONTRAST")){ if(!is_numeric($this->effect_arg1)) $this->effect_arg1 = -5; //set default value imagefilter($imgHandle,IMG_FILTER_CONTRAST,$this->effect_arg1); } break; case self::EFFECT_EDGE: if(defined("IMG_FILTER_EDGEDETECT")) imagefilter($imgHandle,IMG_FILTER_EDGEDETECT); break; case self::EFFECT_EMBOSS: if(defined("IMG_FILTER_EMBOSS")) imagefilter($imgHandle,IMG_FILTER_EMBOSS); break; case self::EFFECT_BLUR: $this->effect_Blur($imgHandle,5); /* if(defined("IMG_FILTER_GAUSSIAN_BLUR")) imagefilter($imgHandle,IMG_FILTER_GAUSSIAN_BLUR); */ break; case self::EFFECT_MEAN: if(defined("IMG_FILTER_MEAN_REMOVAL")) imagefilter($imgHandle,IMG_FILTER_MEAN_REMOVAL); break; case self::EFFECT_SMOOTH: if(defined("IMG_FILTER_SMOOTH")){ if(!is_numeric($this->effect_arg1)) $this->effect_arg1 = 15; //set default value imagefilter($imgHandle,IMG_FILTER_SMOOTH,$this->effect_arg1); } break; case self::EFFECT_BLUR3: $this->effect_Blur($imgHandle,5); break; default: $this->throwError("Effect not supported: ".$this->effect.""); break; } } private function effect_Blur(&$gdimg, $radius=0.5) { // Taken from Torstein Hרnsi's phpUnsharpMask (see phpthumb.unsharp.php) $radius = round(max(0, min($radius, 50)) * 2); if (!$radius) { return false; } $w = ImageSX($gdimg); $h = ImageSY($gdimg); if ($imgBlur = ImageCreateTrueColor($w, $h)) { // Gaussian blur matrix: // 1 2 1 // 2 4 2 // 1 2 1 // Move copies of the image around one pixel at the time and merge them with weight // according to the matrix. The same matrix is simply repeated for higher radii. for ($i = 0; $i < $radius; $i++) { ImageCopy ($imgBlur, $gdimg, 0, 0, 1, 1, $w - 1, $h - 1); // up left ImageCopyMerge($imgBlur, $gdimg, 1, 1, 0, 0, $w, $h, 50.00000); // down right ImageCopyMerge($imgBlur, $gdimg, 0, 1, 1, 0, $w - 1, $h, 33.33333); // down left ImageCopyMerge($imgBlur, $gdimg, 1, 0, 0, 1, $w, $h - 1, 25.00000); // up right ImageCopyMerge($imgBlur, $gdimg, 0, 0, 1, 0, $w - 1, $h, 33.33333); // left ImageCopyMerge($imgBlur, $gdimg, 1, 0, 0, 0, $w, $h, 25.00000); // right ImageCopyMerge($imgBlur, $gdimg, 0, 0, 0, 1, $w, $h - 1, 20.00000); // up ImageCopyMerge($imgBlur, $gdimg, 0, 1, 0, 0, $w, $h, 16.666667); // down ImageCopyMerge($imgBlur, $gdimg, 0, 0, 0, 0, $w, $h, 50.000000); // center ImageCopy ($gdimg, $imgBlur, 0, 0, 0, 0, $w, $h); } return true; } return false; } //------------------------------------------------------------------------------------------ // resize image and save it to new path private function resizeImageSaveNew($filepath,$filepathNew){ $imgInfo = getimagesize($filepath); $imgType = $imgInfo[2]; $src_img = $this->getGdSrcImage($filepath,$imgType); $width = imageSX($src_img); $height = imageSY($src_img); $newWidth = $width; $newHeight = $height; //find new width if($height > $this->maxHeight){ $procent = $this->maxHeight / $height; $newWidth = ceil($width * $procent); $newHeight = $this->maxHeight; } //if the new width is grater than max width, find new height, and remain the width. if($newWidth > $this->maxWidth){ $procent = $this->maxWidth / $newWidth; $newHeight = ceil($newHeight * $procent); $newWidth = $this->maxWidth; } //if the image don't need to be resized, just copy it from source to destanation. if($newWidth == $width && $newHeight == $height && empty($this->effect)){ $success = copy($filepath,$filepathNew); if($success == false) $this->throwError("can't copy the image from one path to another"); } else{ //else create the resized image, and save it to new path: $dst_img = ImageCreateTrueColor($newWidth,$newHeight); $this->handleTransparency($dst_img,$imgType,$newWidth,$newHeight); //copy the new resampled image: imagecopyresampled($dst_img,$src_img,0,0,0,0,$newWidth,$newHeight,$width,$height); $this->handleImageEffects($dst_img); $is_saved = $this->saveGdImage($dst_img,$filepathNew,$imgType); imagedestroy($dst_img); } imagedestroy($src_img); return(true); } /** * * set image effect */ public function setEffect($effect,$arg1 = ""){ $this->effect = $effect; $this->effect_arg1 = $arg1; } private function showImageByID($fileID, $maxWidth=-1, $maxHeight=-1, $type=""){ $fileID = intval($fileID); if($fileID == 0) $this->throwError("image not found"); $img = wp_get_attachment_image_src( $fileID, 'thumb' ); if(empty($img)) $this->throwError("image not found"); $this->outputImage($img[0]); exit(); } //------------------------------------------------------------------------------------------ //return image private function showImage($filename,$maxWidth=-1,$maxHeight=-1,$type=""){ if(empty($filename)) $this->throwError("image filename not found"); //validate input if($type == self::TYPE_EXACT || $type == self::TYPE_EXACT_TOP){ if($maxHeight == -1) $this->throwError("image with exact type must have height!"); if($maxWidth == -1) $this->throwError("image with exact type must have width!"); } $filepath = $this->pathImages.$filename; if(!is_file($filepath)) $this->outputEmptyImageCode(); //if gd library doesn't exists - output normal image without resizing. if(function_exists("gd_info") == false) $this->throwError("php must support GD Library"); //check conditions for output original image if(empty($this->effect)){ if((is_numeric($maxWidth) == false || is_numeric($maxHeight) == false)) outputImage($filepath); if($maxWidth == -1 && $maxHeight == -1) $this->outputImage($filepath); } if($maxWidth == -1) $maxWidth = 1000000; if($maxHeight == -1) $maxHeight = 100000; //init variables $this->filename = $filename; $this->maxWidth = $maxWidth; $this->maxHeight = $maxHeight; $this->type = $type; $filepathNew = $this->getThumbFilepath(); if(is_file($filepathNew)){ $this->outputImage($filepathNew); exit(); } try{ if($type == self::TYPE_EXACT || $type == self::TYPE_EXACT_TOP){ $isSaved = $this->cropImageSaveNew($filepath,$filepathNew); } else $isSaved = $this->resizeImageSaveNew($filepath,$filepathNew); if($isSaved == false){ $this->outputImage($filepath); exit(); } }catch(Exception $e){ $this->outputImage($filepath); } if(is_file($filepathNew)) $this->outputImage($filepathNew); else $this->outputImage($filepath); exit(); } /** * * show image from get params */ public function showImageFromGet(){ //$imageFilename = UniteFunctionsRev::getGetVar("img"); $imageID = intval(UniteFunctionsRev::getGetVar("img")); $maxWidth = UniteFunctionsRev::getGetVar("w",-1); $maxHeight = UniteFunctionsRev::getGetVar("h",-1); $type = UniteFunctionsRev::getGetVar("t",""); //set effect $effect = UniteFunctionsRev::getGetVar("e"); $effectArgument1 = UniteFunctionsRev::getGetVar("ea1"); if(!empty($effect)) $this->setEffect($effect,$effectArgument1); $this->showImageByID($imageID); echo 'sechs
'; //$this->showImage($imageFilename,$maxWidth,$maxHeight,$type); } //------------------------------------------------------------------------------------------ // download image, change size and name if needed. public function downloadImage($filename){ $filepath = $this->urlImages."/".$filename; if(!is_file($filepath)) { echo "file doesn't exists"; exit(); } $this->outputImageForDownload($filepath,$filename); } //------------------------------------------------------------------------------------------ // output image for downloading private function outputImageForDownload($filepath,$filename,$mimeType=""){ $contents = file_get_contents($filepath); $filesize = strlen($contents); if($mimeType == ""){ $info = UniteFunctionsRev::getPathInfo($filepath); $ext = $info["extension"]; $mimeType = "image/$ext"; } header("Content-Type: $mimeType"); header("Content-Disposition: attachment; filename=\"$filename\""); header("Content-Length: $filesize"); echo $contents; exit(); } /** * * validate type * @param unknown_type $type */ public function validateType($type){ switch($type){ case self::TYPE_EXACT: case self::TYPE_EXACT_TOP: break; default: $this->throwError("Wrong image type: ".$type); break; } } } ?>