diff --git a/assets/images/drag.png b/assets/images/drag.png index 2aed13b..4934e84 100644 Binary files a/assets/images/drag.png and b/assets/images/drag.png differ diff --git a/assets/js/dash/cache.js b/assets/js/dash/cache.js index cb5d825..6c704d9 100644 --- a/assets/js/dash/cache.js +++ b/assets/js/dash/cache.js @@ -14,8 +14,8 @@ var dash_cache_select = function() { if (!selected || !selected.length || selected.length!=1) return; desk_post(url('dash/system/info'),{'type':'cache','file':selected[0].data, 'token':token()}, this.bind(this, function(response){ if (response && response.length>0) { - $(this.element).find('.cache-infobar').append('
'+t('Information')+':
'); - $(this.element).find('.cache-infobar').append('
'); + $(this.element).find('.cache-infobar').append('
'+t('Information')+':
'); + $(this.element).find('.cache-infobar').append('
'); for (var i=0; i'+response[i]+''); } diff --git a/assets/js/dash/comments.js b/assets/js/dash/comments.js index f007b1a..d42e29d 100644 --- a/assets/js/dash/comments.js +++ b/assets/js/dash/comments.js @@ -19,8 +19,8 @@ var dash_comments_select = function() { if (!selected || !selected.length || selected.length!=1) return; desk_post(url('dash/comments/info'),{'type':'comment','item':selected[0].data, 'token':token()}, this.bind(this, function(response){ if (response && response.length>0) { - $(this.element).find('.comment-infobar').append('
'+t('Information')+':
'); - $(this.element).find('.comment-infobar').append('
'); + $(this.element).find('.comment-infobar').append('
'+t('Information')+':
'); + $(this.element).find('.comment-infobar').append('
'); for (var i=0; i'+response[i]+''); } diff --git a/assets/js/dash/files.js b/assets/js/dash/files.js index 1e87405..439ce0d 100644 --- a/assets/js/dash/files.js +++ b/assets/js/dash/files.js @@ -64,8 +64,8 @@ var dash_files_select = function() { if (!selected || !selected.length || selected.length!=1) return; desk_post(url('dash/files/info'),{'dirroot':this.options.data.root,'file':selected[0].data, 'token':token()}, this.bind(this, function(response){ if (response && response.length>0) { - $(this.element).find('.filemanager-infobar').append('
'+t('Information')+':
'); - $(this.element).find('.filemanager-infobar').append('
'); + $(this.element).find('.filemanager-infobar').append('
'+t('Information')+':
'); + $(this.element).find('.filemanager-infobar').append('
'); for (var i=0; i'+response[i]+''); } diff --git a/assets/js/dash/logs.js b/assets/js/dash/logs.js index a2c5b4b..4c13ca6 100644 --- a/assets/js/dash/logs.js +++ b/assets/js/dash/logs.js @@ -23,8 +23,8 @@ var dash_logs_select = function() { if (!selected || !selected.length || selected.length!=1) return; desk_post(url('dash/system/info'),{'type':'logs','file':selected[0].data, 'token':token()}, this.bind(this, function(response){ if (response && response.length>0) { - $(this.element).find('.logs-infobar').append('
'+t('Information')+':
'); - $(this.element).find('.logs-infobar').append('
'); + $(this.element).find('.logs-infobar').append('
'+t('Information')+':
'); + $(this.element).find('.logs-infobar').append('
'); for (var i=0; i'+response[i]+''); } diff --git a/assets/js/dash/records.js b/assets/js/dash/records.js index 7484bf1..c88cd7c 100644 --- a/assets/js/dash/records.js +++ b/assets/js/dash/records.js @@ -94,8 +94,8 @@ var dash_records_select = function() { if (!selected || !selected.length || selected.length!=1) return; desk_post(url('dash/records/info'),{'item':selected[0].data, 'token':token()}, this.bind(this, function(response){ if (response && typeof(response.info)!="undefined" && response.info.length>0) { - $(this.element).find('.record-infobar').append('
'+t('Information')+':
'); - $(this.element).find('.record-infobar').append('
'); + $(this.element).find('.record-infobar').append('
'+t('Information')+':
'); + $(this.element).find('.record-infobar').append('
'); for (var i=0; i'+response.info[i]+''); } diff --git a/assets/js/dash/users.js b/assets/js/dash/users.js index 8a37c05..ea41510 100644 --- a/assets/js/dash/users.js +++ b/assets/js/dash/users.js @@ -56,8 +56,8 @@ var dash_users_select = function() { if (!selected || !selected.length || selected.length!=1) return; desk_post(url('dash/users/info'),{'user_id':selected[0].data, 'token':token()}, this.bind(this, function(response){ if (response && response.length>0) { - $(this.element).find('.user-infobar').append('
'+t('Information')+':
'); - $(this.element).find('.user-infobar').append('
'); + $(this.element).find('.user-infobar').append('
'+t('Information')+':
'); + $(this.element).find('.user-infobar').append('
'); for (var i=0; i'+response[i]+''); diff --git a/assets/js/eform/dash.js b/assets/js/eform/dash.js index ba10573..3b9da53 100644 --- a/assets/js/eform/dash.js +++ b/assets/js/eform/dash.js @@ -14,8 +14,8 @@ var dash_eform_select = function() { if (!selected || !selected.length || selected.length!=1) return; desk_post(url('eform/dash/info'),{'item':selected[0].data, 'token':token()}, this.bind(this, function(response){ if (response && response.length>0) { - $(this.element).find('.eform-infobar').append('
'+t('Information')+':
'); - $(this.element).find('.eform-infobar').append('
'); + $(this.element).find('.eform-infobar').append('
'+t('Information')+':
'); + $(this.element).find('.eform-infobar').append('
'); for (var i=0; i'+response[i]+''); } diff --git a/assets/js/fields/dash.js b/assets/js/fields/dash.js new file mode 100644 index 0000000..e4f5d1a --- /dev/null +++ b/assets/js/fields/dash.js @@ -0,0 +1,286 @@ +var dash_fields_group_load = function() { + for (var i=0; i this.dragStartY) { + $(this.content).find('#'+this.dragOverItem).parent('li').after(tmp); + } else { + $(this.content).find('#'+this.dragOverItem).parent('li').before(tmp); + } + $(this.content).find('li.tmp-drag-fields-item').replaceWith($(this.content).find('#'+this.dragStartItem).parent('li')); + this.dragReplaced = true; + } + })); + $(this.element).bind('drop',this.bind(this,function(e){ + if (this.isDisabled()) return; + var dragged = []; + var orders = []; + for (var i=0; i1 && orders.length>1) { + desk_window_request(this, url('fields/dash/groupdrag'),{'items':dragged,'orders':orders}); + } + })); + $(this.content).bind('dragend',this.bind(this,function(e){ + $(this.content).find('#'+this.dragStartItem).parent('li').css('opacity',1); + this.isContentDragging = false; + this.dragStartY = null; + this.dragStartItem = null; + this.dragOverItem = null; + this.dragReplaced = false; + $(this.content).find('li.tmp-drag-fields-item').remove(); + })); +}; + +var dash_fields_group_fields = function() { + var selected = this.getSelectedContentItems(); + if (selected && selected.length==1) { + var data = {'items':[selected[0].data]}; + desk_call(dash_fields_fields_wnd, null, { + 'data':data + }); + } +}; + +var dash_fields_item_create = function() { + var data = { + 'data': { + 'items': [], + 'group_id': this.options.data.items[0] + }, + 'reload': this.className, + 'onClose':function(){ + desk_window_reload_all(this.options.reload); + } + }; + desk_call(dash_fields_field_wnd, null, data); +}; + +var dash_fields_item_edit = function() { + var selected = this.getSelectedContentItems(); + if (selected && selected.length==1) { + var data = { + 'data':{ + 'items': [selected[0].data], + 'group_id': this.options.data.items[0] + }, + 'reload': this.className, + 'onClose':function(){ + desk_window_reload_all(this.options.reload); + } + }; + desk_call(dash_fields_field_wnd, null, data); + } +}; + +var dash_fields_field_form_init = function() { + $(this.content).find('select.field-types-select').eq(0).change(this.bind(this, function(){ + var val = $(this.content).find('select.field-types-select').eq(0).val(); + if (val == 'radio' || val == 'select') { + $(this.content).find('.form_field_values_wrapper').show(); + desk_call(dash_fields_field_values_init, this); + } else { + $(this.content).find('.form_field_values_wrapper').hide(); + } + })); + var values = $(this.content).find('input.field-values-hidden').eq(0).val(); + if (values.length>0) { + $(this.content).find('.form_field_values_wrapper').show(); + desk_call(dash_fields_field_values_init, this); + var vals = values.split(','); + for (var i=0; i'+w.html()+''); + $(this.content).find('input.field-values-input').last().val(vals[i]); + } + $(this.content).find('.field-values-input-wrapper').eq(0).remove(); + desk_call(dash_fields_field_values_init, this); + } +}; + +var dash_fields_field_values_init = function() { + var total = $(this.content).find('input.field-values-input').length; + $(this.content).find('input.field-values-input').each(function(index){ + if (!$(this).parent().hasClass('field-values-input-wrapper')) { + $(this).wrap('
'); + } + $(this).parent('.field-values-input-wrapper').children('.field-values-input-remove').remove(); + $(this).parent('.field-values-input-wrapper').children('.field-values-input-add').remove(); + if (index'); + } else { + $(this).parent('.field-values-input-wrapper').append(''); + } + }); + $(this.content).find('.field-values-input-add').unbind('click').click(this.bind(this, function(){ + var w = $(this.content).find('.field-values-input-wrapper').eq(0); + $(w).parent().append('
'+w.html()+'
'); + $(this.content).find('input.field-values-input').last().val(''); + desk_call(dash_fields_field_values_init, this); + })); + $(this.content).find('.field-values-input-remove').unbind('click').click(function(){ + $(this).parent('.field-values-input-wrapper').remove(); + }); +}; + +var dash_fields_fields_load = function() { + for (var i=0; i this.dragStartY) { + $(this.content).find('#'+this.dragOverItem).parent('li').after(tmp); + } else { + $(this.content).find('#'+this.dragOverItem).parent('li').before(tmp); + } + $(this.content).find('li.tmp-drag-fields-item').replaceWith($(this.content).find('#'+this.dragStartItem).parent('li')); + this.dragReplaced = true; + } + })); + $(this.element).bind('drop',this.bind(this,function(e){ + if (this.isDisabled()) return; + var dragged = []; + var orders = []; + for (var i=0; i1 && orders.length>1) { + desk_window_request(this, url('fields/dash/fielddrag'),{'items':dragged,'orders':orders}); + } + })); + $(this.content).bind('dragend',this.bind(this,function(e){ + $(this.content).find('#'+this.dragStartItem).parent('li').css('opacity',1); + this.isContentDragging = false; + this.dragStartY = null; + this.dragStartItem = null; + this.dragOverItem = null; + this.dragReplaced = false; + $(this.content).find('li.tmp-drag-fields-item').remove(); + })); +}; \ No newline at end of file diff --git a/assets/js/forum/dash.js b/assets/js/forum/dash.js index 6e89c56..3ff4228 100644 --- a/assets/js/forum/dash.js +++ b/assets/js/forum/dash.js @@ -400,8 +400,8 @@ var dash_forum_topics_select = function() { if (!selected || !selected.length || selected.length!=1) return; desk_post(url('forum/dash/topicinfo'),{'topic_id':selected[0].data, 'token':token()}, this.bind(this, function(response){ if (response && response.length>0) { - $(this.element).find('.topics-infobar').append('
'+t('Information')+':
'); - $(this.element).find('.topics-infobar').append('
'); + $(this.element).find('.topics-infobar').append('
'+t('Information')+':
'); + $(this.element).find('.topics-infobar').append('
'); for (var i=0; i'+response[i]+''); diff --git a/assets/js/vote/dash.js b/assets/js/vote/dash.js index b4cb54d..bf10482 100644 --- a/assets/js/vote/dash.js +++ b/assets/js/vote/dash.js @@ -26,8 +26,8 @@ var dash_votes_select = function() { if (!selected || !selected.length || selected.length!=1) return; desk_post(url('vote/dash/info'),{'item':selected[0].data, 'token':token()}, this.bind(this, function(response){ if (response && response.length>0) { - $(this.element).find('.vote-infobar').append('
'+t('Information')+':
'); - $(this.element).find('.vote-infobar').append('
'); + $(this.element).find('.vote-infobar').append('
'+t('Information')+':
'); + $(this.element).find('.vote-infobar').append('
'); for (var i=0; i'+response[i]+''); } diff --git a/dash/dash.php b/dash/dash.php index 58121db..30d72fc 100644 --- a/dash/dash.php +++ b/dash/dash.php @@ -255,6 +255,7 @@ class Dash { $this->addPanelGroup($this->_panel_settings_group); } if (!empty($this->_panel_modules_group['rel'])) { + usort($this->_panel_modules_group['rel'], array($this, 'sortPanelModuleItems')); $this->addPanelGroup($this->_panel_modules_group); } } @@ -270,6 +271,13 @@ class Dash { public function getPanelItems() { return $this->_panel_items; } + + public static function sortPanelModuleItems($a, $b) { + if (!is_array($a) || !is_array($b)) return 0; + if (!array_key_exists('label', $a) || !array_key_exists('label', $b)) return 0; + if ($a['label'] == $b['label']) return 0; + return $a['label'] < $b['label'] ? -1 : 1; + } public function getPanelCallbacks() { return $this->_panel_callbacks; diff --git a/dash/models/records.php b/dash/models/records.php index 7e489b1..5ef93de 100644 --- a/dash/models/records.php +++ b/dash/models/records.php @@ -563,11 +563,13 @@ class Records extends Model { $record = new Zira\Models\Record($id); if (!$record->loaded()) return array(); + /** if ($record->front_page) { $info[] = ' ' . Zira\Locale::t('ID: %s', $record->id); } else { $info[] = ' ' . Zira\Locale::t('ID: %s', $record->id); } + **/ //$info[] = ' ' . Zira\Helper::html($record->title); $info[] = ' ' . Zira\Locale::t('Rating: %s', Zira\Helper::html($record->rating)); $info[] = ' ' . Zira\Locale::t('Comments: %s', Zira\Helper::html($record->comments)); diff --git a/dash/windows/modules.php b/dash/windows/modules.php index 790e330..4d2debd 100644 --- a/dash/windows/modules.php +++ b/dash/windows/modules.php @@ -155,7 +155,7 @@ class Modules extends Window { if (array_key_exists('name', $meta['meta'])) $name = Zira\Locale::tm($meta['meta']['name'], $module); if (array_key_exists('description', $meta['meta'])) $description = Zira\Locale::tm($meta['meta']['description'], $module); if (array_key_exists('author', $meta['meta'])) $author = $meta['meta']['author']; - if (array_key_exists('version', $meta['meta'])) $version = $meta['meta']['version']; + //if (array_key_exists('version', $meta['meta'])) $version = $meta['meta']['version']; } } @@ -166,6 +166,15 @@ class Modules extends Window { $items[]=$this->createBodyFileItem($title, $description, $key, null, false, array('activated'=>in_array($key, $active_modules),'installable'=>count($tables)>0,'installed'=>$installed)); } + usort($items, array($this, 'sortModules')); + $this->setBodyItems($items); } + + public static function sortModules($a, $b) { + if (!is_array($a) || !is_array($b)) return 0; + if (!array_key_exists('title', $a) || !array_key_exists('title', $b)) return 0; + if ($a['title'] == $b['title']) return 0; + return $a['title'] < $b['title'] ? -1 : 1; + } } \ No newline at end of file diff --git a/fields/controllers/dash.php b/fields/controllers/dash.php new file mode 100644 index 0000000..01d6f0c --- /dev/null +++ b/fields/controllers/dash.php @@ -0,0 +1,46 @@ +getGroupsWindowModel()->drag($items, $orders); + Zira\Page::render($response); + } + } + + public function fielddrag() { + if (Zira\Request::isPost()) { + $items = Zira\Request::post('items'); + $orders = Zira\Request::post('orders'); + $response = $this->getFieldsWindowModel()->drag($items, $orders); + Zira\Page::render($response); + } + } +} \ No newline at end of file diff --git a/fields/fields.php b/fields/fields.php new file mode 100644 index 0000000..45f748b --- /dev/null +++ b/fields/fields.php @@ -0,0 +1,39 @@ +isPanelEnabled() && Zira\Permission::check(Zira\Permission::TO_ACCESS_DASHBOARD) && Zira\Permission::check(Zira\Permission::TO_CHANGE_LAYOUT)) { + Dash\Dash::loadDashLanguage(); + Dash\Dash::getInstance()->addPanelModulesGroupItem('glyphicon glyphicon-tags', Zira\Locale::tm('Extra fields', 'fields', null, Dash\Dash::getDashLanguage()), null, 'fieldGroupsWindow()'); + Dash\Dash::getInstance()->registerModuleWindowClass('fieldGroupsWindow', 'Fields\Windows\Groups', 'Fields\Models\Groups'); + Dash\Dash::getInstance()->registerModuleWindowClass('fieldGroupWindow', 'Fields\Windows\Group', 'Fields\Models\Groups'); + Dash\Dash::getInstance()->registerModuleWindowClass('fieldsItemWindow', 'Fields\Windows\Fields', 'Fields\Models\Fields'); + Dash\Dash::getInstance()->registerModuleWindowClass('fieldItemWindow', 'Fields\Windows\Field', 'Fields\Models\Fields'); + Dash\Dash::unloadDashLanguage(); + } + } +} \ No newline at end of file diff --git a/fields/forms/field.php b/fields/forms/field.php new file mode 100644 index 0000000..d657d33 --- /dev/null +++ b/fields/forms/field.php @@ -0,0 +1,99 @@ +_id); + } + + protected function _init() + { + $this->setRenderPanel(false); + $this->setFormClass('form-horizontal dash-window-form'); + } + + protected function _render() + { + $types = \Fields\Models\Field::getTypes(); + foreach($types as $var=>$val) { + $types[$var] = Locale::tm($val, 'eform'); + } + $html = $this->open(); + $html .= $this->input(Locale::t('Title').'*', 'title'); + $html .= $this->textarea(Locale::t('Description'), 'description'); + $html .= $this->select(Locale::tm('Type','fields').'*', 'field_type', $types, array('class'=>'form-control field-types-select')); + $html .= Zira\Helper::tag_open('div', array('class'=>'form_field_values_wrapper', 'style'=>'display:none')); + $html .= $this->input(Locale::tm('Field values','fields').'*', 'form_field_values[]', array('class'=>'form-control field-values-input', 'id'=>'')); + $html .= Zira\Helper::tag_close('div'); + $html .= $this->checkbox(Locale::tm('add to record description','fields'), 'preview', null, false); + $html .= $this->checkbox(Locale::tm('field is active','fields'), 'active', null, false); + $html .= $this->hidden('id'); + $html .= $this->hidden('field_group_id'); + $html .= $this->hidden('field_values', array('class'=>'field-values-hidden')); + $html .= $this->close(); + return $html; + } + + protected function _validate() { + $validator = $this->getValidator(); + + $validator->registerCustom(array(get_class(), 'checkGroup'), array('field_group_id'), Locale::t('An error occurred')); + $validator->registerCustom(array(get_class(), 'checkType'), array('field_type'), Locale::t('Invalid value "%s"',Locale::t('Type'))); + + $validator->registerString('title',null,255,true,Locale::t('Invalid value "%s"',Locale::t('Title'))); + $validator->registerNoTags('title',Locale::t('Invalid value "%s"',Locale::t('Title'))); + $validator->registerUtf8('title',Locale::t('Invalid value "%s"',Locale::t('Title'))); + + $validator->registerNoTags('description',Locale::t('Invalid value "%s"',Locale::t('Description'))); + $validator->registerUtf8('description',Locale::t('Invalid value "%s"',Locale::t('Description'))); + + $type = $this->getValue('field_type'); + if ($type == 'radio' || $type == 'select') { + $validator->registerCustom(array(get_class(), 'checkValues'), 'form_field_values', Locale::t('Invalid value "%s"', Locale::t('Field values'))); + } + } + + public static function checkGroup($group_id) { + $group = new \Fields\Models\Group($group_id); + return $group->loaded(); + } + + public static function checkType($type) { + $types = \Fields\Models\Field::getTypes(); + return array_key_exists($type, $types); + } + + public static function checkValues($values) { + if (!is_array($values)) return false; + $co = 0; + foreach($values as $value) { + if (strpos($value, '"')!==false) return false; + if (strpos($value, ',')!==false) return false; + if (preg_match('/[<][a-z\/][^>]*[>]/si', $value)) return false; + if (Zira\Helper::utf8BadMatch($value)) return false; + if (!empty($value)) $co++; + } + return $co>0; + } +} \ No newline at end of file diff --git a/fields/forms/group.php b/fields/forms/group.php new file mode 100644 index 0000000..b0749e8 --- /dev/null +++ b/fields/forms/group.php @@ -0,0 +1,92 @@ +_id); + } + + protected function _init() + { + $this->setRenderPanel(false); + $this->setFormClass('form-horizontal dash-window-form'); + } + + protected function _render() + { + $placeholders = \Fields\Models\Group::getPlaceholders(); + $categories = array(Zira\Category::ROOT_CATEGORY_ID => Locale::t('All pages')) + Zira\Models\Category::getArray(); + + $html = $this->open(); + $html .= $this->input(Locale::t('Title').'*', 'title'); + $html .= $this->textarea(Locale::t('Description'), 'description'); + $html .= $this->select(Locale::t('Placeholder').'*','placeholder',$placeholders); + if (count(Zira\Config::get('languages'))<2) { + $html .= $this->hidden('language'); + } else { + $languagesArr = array_merge(array(''=>Locale::t('All languages')), Locale::getLanguagesArray()); + $html .= $this->select(Locale::t('Language').'*','language',$languagesArr, array('class'=>'form-control language-select')); + } + $html .= $this->select(Locale::t('Category'),'category_id',$categories); + $html .= $this->checkbox(Locale::tm('group is active','fields'), 'active', null, false); + $html .= $this->hidden('id'); + $html .= $this->close(); + return $html; + } + + protected function _validate() { + $validator = $this->getValidator(); + + $validator->registerString('title',null,255,true,Locale::t('Invalid value "%s"',Locale::t('Title'))); + $validator->registerNoTags('title',Locale::t('Invalid value "%s"',Locale::t('Title'))); + $validator->registerUtf8('title',Locale::t('Invalid value "%s"',Locale::t('Title'))); + + $validator->registerNoTags('description',Locale::t('Invalid value "%s"',Locale::t('Description'))); + $validator->registerUtf8('description',Locale::t('Invalid value "%s"',Locale::t('Description'))); + + $validator->registerString('placeholder', null, 255, true, Locale::t('Invalid value "%s"',Locale::t('Placeholder'))); + $validator->registerCustom(array(get_class(), 'checkPlaceholder'), 'placeholder', Locale::t('Invalid value "%s"',Locale::t('Placeholder'))); + + + $validator->registerCustom(array(get_class(), 'checkLanguage'), 'language', Locale::t('An error occurred')); + $validator->registerCustom(array(get_class(), 'checkCategory'), 'category_id', Locale::t('An error occurred')); + } + + public static function checkPlaceholder($placeholder) { + $placeholders = \Fields\Models\Group::getPlaceholders(); + return array_key_exists($placeholder, $placeholders); + } + + public static function checkLanguage($language) { + if (empty($language)) return true; + return in_array($language , Zira\Config::get('languages')); + } + + public static function checkCategory($category_id) { + if (!is_numeric($category_id)) return false; + if ($category_id==Zira\Category::ROOT_CATEGORY_ID) return true; + $category = new Zira\Models\Category($category_id); + return $category->loaded(); + } +} \ No newline at end of file diff --git a/fields/install/fieldgroup.php b/fields/install/fieldgroup.php new file mode 100644 index 0000000..c51656c --- /dev/null +++ b/fields/install/fieldgroup.php @@ -0,0 +1,51 @@ +_table); + } + + public function getFields() { + return array( + 'id' => Field::primary(), + 'title' => Field::string(true), + 'description' => Field::string(false), + 'placeholder' => Field::string(true), + 'category_id' => Field::int(true, true), + 'language' => Field::string(false), + 'sort_order' => Field::int(true, false, 0), + 'active' => Field::int(true, true, 0), + 'tpl' => Field::string(false) + ); + } + + public function getKeys() { + return array( + 'search' => array('sort_order', 'active', 'category_id', 'language') + ); + } + + public function getUnique() { + return array( + + ); + } + + public function getDefaults() { + return array( + + ); + } +} \ No newline at end of file diff --git a/fields/install/fielditem.php b/fields/install/fielditem.php new file mode 100644 index 0000000..74b8dee --- /dev/null +++ b/fields/install/fielditem.php @@ -0,0 +1,51 @@ +_table); + } + + public function getFields() { + return array( + 'id' => Field::primary(), + 'field_group_id' => Field::int(true, true), + 'field_type' => Field::string(true), + 'field_values' => Field::text(), + 'title' => Field::string(true), + 'description' => Field::string(false), + 'sort_order' => Field::int(true, false, 0), + 'active' => Field::int(true, true, 0), + 'preview' => Field::int(true, true, 0) + ); + } + + public function getKeys() { + return array( + 'search' => array('sort_order', 'active', 'field_group_id') + ); + } + + public function getUnique() { + return array( + + ); + } + + public function getDefaults() { + return array( + + ); + } +} \ No newline at end of file diff --git a/fields/install/fieldvalue.php b/fields/install/fieldvalue.php new file mode 100644 index 0000000..902988e --- /dev/null +++ b/fields/install/fieldvalue.php @@ -0,0 +1,49 @@ +_table); + } + + public function getFields() { + return array( + 'id' => Field::primary(), + 'record_id' => Field::int(true, true), + 'field_item_id' => Field::int(true, true), + 'field_group_id' => Field::int(true, true), + 'content' => Field::text(), + 'mark' => Field::string(true), + 'date_added' => Field::datetime(true) + ); + } + + public function getKeys() { + return array( + 'search' => array('record_id') + ); + } + + public function getUnique() { + return array( + + ); + } + + public function getDefaults() { + return array( + + ); + } +} \ No newline at end of file diff --git a/fields/models/field.php b/fields/models/field.php new file mode 100644 index 0000000..3f37084 --- /dev/null +++ b/fields/models/field.php @@ -0,0 +1,51 @@ + 'Text field', + 'textarea' => 'Text area', + 'checkbox' => 'Check box', + 'radio' => 'Radio button', + 'select' => 'Select dropdown', + 'file' => 'File', + 'image' => 'Image', + 'link' => 'URL address', + 'html' => 'HTML code' + ); + + public static function getTable() { + return self::$table; + } + + public static function getPk() { + return self::$pk; + } + + public static function getAlias() { + return self::$alias; + } + + public static function getReferences() { + return array( + + ); + } + + public static function getTypes() { + return self::$_types; + } +} \ No newline at end of file diff --git a/fields/models/fields.php b/fields/models/fields.php new file mode 100644 index 0000000..5514e8c --- /dev/null +++ b/fields/models/fields.php @@ -0,0 +1,118 @@ + Zira\Locale::t('Permission denied')); + } + + $form = new \Fields\Forms\Field(); + if ($form->isValid()) { + $id = (int)$form->getValue('id'); + + if ($id) { + $field = new \Fields\Models\Field($id); + if (!$field->loaded()) return array('error' => Zira\Locale::t('An error occurred')); + } else { + $max_order = \Fields\Models\Field::getCollection()->max('sort_order')->get('mx'); + $field = new \Fields\Models\Field(); + $field->sort_order = ++$max_order; + } + $field->title = $form->getValue('title'); + $field->description = $form->getValue('description'); + $field->field_group_id = $form->getValue('field_group_id'); + $field->field_type = $form->getValue('field_type'); + + $form_field_values = $form->getValue('form_field_values'); + if (is_array($form_field_values) && !empty($form_field_values)) { + $_field_values = ''; + foreach($form_field_values as $form_field_value) { + if (empty($form_field_value)) continue; + if (strlen($_field_values)>0) $_field_values .= ','; + $_field_values .= $form_field_value; + } + if (empty($_field_values)) $_field_values = null; + $field->field_values = $_field_values; + } else { + $field->field_values = null; + } + + $field->preview = (int)$form->getValue('preview') ? 1 : 0; + $field->active = (int)$form->getValue('active') ? 1 : 0; + + $field->save(); + + return array('message'=>Zira\Locale::t('Successfully saved'), 'close'=>true); + } else { + return array('error'=>$form->getError()); + } + } + + public function delete($data) { + if (empty($data) || !is_array($data)) return array('error' => Zira\Locale::t('An error occurred')); + if (!Permission::check(Permission::TO_CHANGE_LAYOUT)) { + return array('error'=>Zira\Locale::t('Permission denied')); + } + + foreach($data as $field_id) { + $field = new \Fields\Models\Field($field_id); + if (!$field->loaded()) { + return array('error' => Zira\Locale::t('An error occurred')); + } + // deleting active field is not allowed + if ($field->active) { + return array('error' => Zira\Locale::tm('Cannot delete active field', 'fields')); + } + $field->delete(); + + \Fields\Models\Value::getCollection() + ->where('field_item_id','=',$field_id) + ->delete() + ->execute(); + } + + return array('reload' => $this->getJSClassName()); + } + + public function drag($items, $orders) { + if (empty($items) || !is_array($items) || count($items)<2 || empty($orders) || !is_array($orders) || count($orders)<2 || count($items)!=count($orders)) { + return array('error' => Zira\Locale::t('An error occurred')); + } + if (!Permission::check(Permission::TO_CHANGE_LAYOUT)) { + return array('error'=>Zira\Locale::t('Permission denied')); + } + + $_items = array(); + $_orders = array(); + foreach($items as $id) { + $_item = new \Fields\Models\Field($id); + if (!$_item->loaded()) { + return array('error' => Zira\Locale::t('An error occurred')); + } + $_items []= $_item; + $_orders []= $_item->sort_order; + } + foreach($orders as $order) { + if (!in_array($order, $_orders)) { + return array('error' => Zira\Locale::t('An error occurred')); + } + } + foreach($_items as $index=>$item) { + $item->sort_order = intval($orders[$index]); + $item->save(); + } + + return array('reload'=>$this->getJSClassName()); + } +} \ No newline at end of file diff --git a/fields/models/group.php b/fields/models/group.php new file mode 100644 index 0000000..a1e36b3 --- /dev/null +++ b/fields/models/group.php @@ -0,0 +1,45 @@ + Zira\Locale::t('Left sidebar'), + Zira\View::VAR_SIDEBAR_RIGHT => Zira\Locale::t('Right sidebar'), + Zira\View::VAR_CONTENT_TOP => Zira\Locale::t('Before content'), + Zira\View::VAR_CONTENT => Zira\Locale::t('Content'), + Zira\View::VAR_CONTENT_BOTTOM => Zira\Locale::t('After content') + ); + } +} \ No newline at end of file diff --git a/fields/models/groups.php b/fields/models/groups.php new file mode 100644 index 0000000..1cd488d --- /dev/null +++ b/fields/models/groups.php @@ -0,0 +1,118 @@ + Zira\Locale::t('Permission denied')); + } + + $form = new Fields\Forms\Group(); + if ($form->isValid()) { + $id = (int)$form->getValue('id'); + + if ($id) { + $group = new Fields\Models\Group($id); + if (!$group->loaded()) return array('error' => Zira\Locale::t('An error occurred')); + } else { + $max_order = Fields\Models\Group::getCollection()->max('sort_order')->get('mx'); + $group = new Fields\Models\Group(); + $group->sort_order = ++$max_order; + } + $group->title = $form->getValue('title'); + $group->description = $form->getValue('description'); + $group->placeholder = $form->getValue('placeholder'); + $group->category_id = (int)$form->getValue('category_id'); + $language = $form->getValue('language'); + if (empty($language)) $language = null; + $group->language = $language; + $group->active = (int)$form->getValue('active') ? 1 : 0; + + $group->save(); + + return array('message'=>Zira\Locale::t('Successfully saved'), 'close'=>true); + } else { + return array('error'=>$form->getError()); + } + } + + public function delete($data) { + if (empty($data) || !is_array($data)) return array('error' => Zira\Locale::t('An error occurred')); + if (!Permission::check(Permission::TO_CHANGE_LAYOUT)) { + return array('error'=>Zira\Locale::t('Permission denied')); + } + + foreach($data as $group_id) { + $group = new Fields\Models\Group($group_id); + if (!$group->loaded()) { + return array('error' => Zira\Locale::t('An error occurred')); + }; + + // deleting non-empty group is not allowed + $co = Fields\Models\Field::getCollection() + ->count() + ->where('field_group_id','=',$group_id) + ->get('co'); + + if ($co>0) return array('error' => Zira\Locale::tm('Cannot delete group that have fields', 'fields')); + + $group->delete(); + + /** + Fields\Models\Field::getCollection() + ->where('field_group_id','=',$group_id) + ->delete() + ->execute(); + + Fields\Models\Value::getCollection() + ->where('field_group_id','=',$group_id) + ->delete() + ->execute(); + */ + } + + return array('reload' => $this->getJSClassName()); + } + + public function drag($items, $orders) { + if (empty($items) || !is_array($items) || count($items)<2 || empty($orders) || !is_array($orders) || count($orders)<2 || count($items)!=count($orders)) { + return array('error' => Zira\Locale::t('An error occurred')); + } + if (!Permission::check(Permission::TO_CHANGE_LAYOUT)) { + return array('error'=>Zira\Locale::t('Permission denied')); + } + + $_items = array(); + $_orders = array(); + foreach($items as $id) { + $_item = new Fields\Models\Group($id); + if (!$_item->loaded()) { + return array('error' => Zira\Locale::t('An error occurred')); + } + $_items []= $_item; + $_orders []= $_item->sort_order; + } + foreach($orders as $order) { + if (!in_array($order, $_orders)) { + return array('error' => Zira\Locale::t('An error occurred')); + } + } + foreach($_items as $index=>$item) { + $item->sort_order = intval($orders[$index]); + $item->save(); + } + + return array('reload'=>$this->getJSClassName()); + } +} \ No newline at end of file diff --git a/fields/models/value.php b/fields/models/value.php new file mode 100644 index 0000000..6574035 --- /dev/null +++ b/fields/models/value.php @@ -0,0 +1,35 @@ +setIconClass(self::$_icon_class); + $this->setTitle(Zira\Locale::t(self::$_title)); + $this->setSidebarEnabled(false); + + $this->setSaveActionEnabled(true); + } + + public function create() { + $this->setOnLoadJSCallback( + $this->createJSCallback( + 'desk_window_form_init(this);'. + 'desk_call(dash_fields_field_form_init, this);' + ) + ); + } + + public function load() { + $group_id = Zira\Request::post('group_id'); + if (empty($group_id)) return array('error' => Zira\Locale::t('An error occurred')); + if (!empty($this->item)) $this->item=intval($this->item); + if (!Permission::check(Permission::TO_CHANGE_LAYOUT)) { + return array('error' => Zira\Locale::t('Permission denied')); + } + + $group = new \Fields\Models\Group($group_id); + if (!$group->loaded()) return array('error' => Zira\Locale::t('An error occurred')); + + $form = new \Fields\Forms\Field(); + if (!empty($this->item)) { + $field = new \Fields\Models\Field($this->item); + if (!$field->loaded()) return array('error' => Zira\Locale::t('An error occurred')); + $form->setValues($field->toArray()); + $this->setTitle(Zira\Locale::tm(self::$_title,'fields').' - '.$group->title.' - '.$field->title); + } else { + $form->setValues(array( + 'field_group_id' => $group->id, + 'active'=>1 + )); + $this->setTitle(Zira\Locale::tm('New record extra field','fields').' - '.$group->title); + } + + $this->setBodyContent($form); + } +} \ No newline at end of file diff --git a/fields/windows/fields.php b/fields/windows/fields.php new file mode 100644 index 0000000..744c49d --- /dev/null +++ b/fields/windows/fields.php @@ -0,0 +1,87 @@ +setIconClass(self::$_icon_class); + $this->setTitle(Zira\Locale::t(self::$_title)); + $this->setViewSwitcherEnabled(false); + $this->setSelectionLinksEnabled(true); + $this->setSidebarEnabled(false); + $this->setBodyViewListVertical(true); + + $this->setOnCreateItemJSCallback( + $this->createJSCallback('desk_call(dash_fields_item_create, this)') + ); + + $this->setOnEditItemJSCallback( + $this->createJSCallback('desk_call(dash_fields_item_edit, this)') + ); + + $this->setDeleteActionEnabled(true); + } + + public function create() { + $this->addDefaultToolbarItem( + $this->createToolbarButton(Zira\Locale::tm('Add field', 'fields'), Zira\Locale::tm('Add field', 'fields'), 'glyphicon glyphicon-plus-sign', 'desk_call(dash_fields_item_create, this)', 'create') + ); + + $this->setOnOpenJSCallback( + $this->createJSCallback( + 'desk_call(dash_fields_fields_drag, this);' + ) + ); + + $this->addDefaultOnLoadScript( + 'desk_call(dash_fields_fields_load, this);' + ); + + $this->setData(array( + 'items' => array($this->item) + )); + } + + public function load() { + if (!empty($this->item)) $this->item=intval($this->item); + else return array('error'=>Zira\Locale::t('An error occurred')); + if (!Permission::check(Permission::TO_CHANGE_LAYOUT)) { + $this->setBodyItems(array()); + return array('error'=>Zira\Locale::t('Permission denied')); + } + + $group = new \Fields\Models\Group($this->item); + if (!$group->loaded()) return array('error' => Zira\Locale::t('An error occurred')); + + $query = \Fields\Models\Field::getCollection(); + $query->where('field_group_id', '=', $group->id); + $query->order_by('sort_order', 'asc'); + $rows = $query->get(); + + $items = array(); + foreach($rows as $row) { + $items[]=$this->createBodyItem(Zira\Helper::html($row->title), Zira\Helper::html($row->description), Zira\Helper::imgUrl('drag.png'), $row->id, null, false, array('activated'=>$row->active,'sort_order'=>$row->sort_order)); + } + + $this->setBodyItems($items); + + $this->setTitle(Zira\Locale::tm(self::$_title,'fields').' - '.$group->title); + } +} \ No newline at end of file diff --git a/fields/windows/group.php b/fields/windows/group.php new file mode 100644 index 0000000..9ca8943 --- /dev/null +++ b/fields/windows/group.php @@ -0,0 +1,60 @@ +setIconClass(self::$_icon_class); + $this->setTitle(Zira\Locale::t(self::$_title)); + $this->setSidebarEnabled(false); + + $this->setSaveActionEnabled(true); + } + + public function create() { + $this->setOnLoadJSCallback( + $this->createJSCallback( + 'desk_window_form_init(this);' + ) + ); + } + + public function load() { + if (!empty($this->item)) $this->item=intval($this->item); + if (!Permission::check(Permission::TO_CHANGE_LAYOUT)) { + return array('error' => Zira\Locale::t('Permission denied')); + } + + $form = new \Fields\Forms\Group(); + if (!empty($this->item)) { + $group = new \Fields\Models\Group($this->item); + if (!$group->loaded()) return array('error' => Zira\Locale::t('An error occurred')); + $form->setValues($group->toArray()); + $this->setTitle(Zira\Locale::tm(self::$_title,'fields').' - '.$group->title); + } else { + $form->setValues(array( + 'placeholder' => Zira\View::VAR_CONTENT, + 'active'=>1 + )); + $this->setTitle(Zira\Locale::tm('New extra field group','fields')); + } + + $this->setBodyContent($form); + } +} \ No newline at end of file diff --git a/fields/windows/groups.php b/fields/windows/groups.php new file mode 100644 index 0000000..a53daf4 --- /dev/null +++ b/fields/windows/groups.php @@ -0,0 +1,122 @@ +setIconClass(self::$_icon_class); + $this->setTitle(Zira\Locale::t(self::$_title)); + $this->setViewSwitcherEnabled(false); + $this->setSelectionLinksEnabled(true); + $this->setSidebarEnabled(true); + $this->setBodyViewListVertical(true); + + $this->setCreateActionWindowClass(\Fields\Windows\Group::getClass()); + $this->setEditActionWindowClass(\Fields\Windows\Group::getClass()); + + $this->setDeleteActionEnabled(true); + } + + public function create() { + $this->addDefaultMenuDropdownItem( + $this->createMenuDropdownSeparator() + ); + $this->addDefaultMenuDropdownItem( + $this->createMenuDropdownItem(Zira\Locale::tm('Group fields', 'fields'), 'glyphicon glyphicon-tags', 'desk_call(dash_fields_group_fields, this);', 'edit', true, array('typo'=>'groupfields')) + ); + + $this->addDefaultContextMenuItem( + $this->createContextMenuSeparator() + ); + $this->addDefaultContextMenuItem( + $this->createContextMenuItem(Zira\Locale::tm('Group fields', 'fields'), 'glyphicon glyphicon-tags', 'desk_call(dash_fields_group_fields, this);', 'edit', true, array('typo'=>'groupfields')) + ); + + $this->setOnOpenJSCallback( + $this->createJSCallback( + 'desk_call(dash_fields_group_drag, this);' + ) + ); + + $this->addDefaultOnLoadScript( + 'desk_call(dash_fields_group_load, this);' + ); + + $this->setData(array( + 'language' => '' + )); + + $this->addVariables(array( + 'dash_fields_blank_src' => Zira\Helper::imgUrl('blank.png'), + 'dash_fields_fields_wnd' => Dash::getInstance()->getWindowJSName(\Fields\Windows\Fields::getClass()), + 'dash_fields_field_wnd' => Dash::getInstance()->getWindowJSName(\Fields\Windows\Field::getClass()) + )); + + $this->includeJS('fields/dash'); + } + + public function load() { + if (!Permission::check(Permission::TO_CHANGE_LAYOUT)) { + $this->setData(array( + 'language' => '' + )); + $this->setBodyItems(array()); + return array('error'=>Zira\Locale::t('Permission denied')); + } + + $language= (string)Zira\Request::post('language'); + if (!empty($language) && !in_array($language, Zira\Config::get('languages'))) { + $language = ''; + } + + $query = \Fields\Models\Group::getCollection(); + if (!empty($language)) { + $query->where('language', '=', $language); + } + $query->order_by('sort_order', 'asc'); + + $rows = $query->get(); + + $items = array(); + foreach($rows as $row) { + $items[]=$this->createBodyItem(Zira\Helper::html($row->title), Zira\Helper::html($row->description), Zira\Helper::imgUrl('drag.png'), $row->id, 'desk_call(dash_fields_group_fields, this);', false, array('activated'=>$row->active,'sort_order'=>$row->sort_order)); + } + + $this->setBodyItems($items); + + $menu = array( + $this->createMenuItem($this->getDefaultMenuTitle(), $this->getDefaultMenuDropdown()) + ); + + if (count(Zira\Config::get('languages'))>1) { + $langMenu = array(); + foreach(Zira\Locale::getLanguagesArray() as $lang_key=>$lang_name) { + if (!empty($language) && $language==$lang_key) $icon = 'glyphicon glyphicon-ok'; + else $icon = 'glyphicon glyphicon-filter'; + $langMenu []= $this->createMenuDropdownItem($lang_name, $icon, 'desk_call(dash_fields_group_language, this, element);', 'language', false, array('language'=>$lang_key)); + } + $menu []= $this->createMenuItem(Zira\Locale::t('Languages'), $langMenu); + } + + $this->setMenuItems($menu); + + $this->setData(array( + 'language' => $language + )); + } +} \ No newline at end of file diff --git a/forum/forum.php b/forum/forum.php index 8c3f02c..2aaa482 100644 --- a/forum/forum.php +++ b/forum/forum.php @@ -137,7 +137,7 @@ class Forum { $messages = \Forum\Models\Message::getNewMessagesCount(); if ($messages == 0) return false; return array( - 'message'=>Zira\Locale::t('%s forum messages was posted', $messages), + 'message'=>Zira\Locale::tm('%s forum messages was posted', 'forum', $messages), 'callback'=>Dash\Dash::getInstance()->getWindowJSName(\Forum\Windows\Forums::getClass()) ); } diff --git a/languages/ru/fields.php b/languages/ru/fields.php new file mode 100644 index 0000000..8a05fd4 --- /dev/null +++ b/languages/ru/fields.php @@ -0,0 +1,29 @@ + 'Экстра поля', + 'Record extra fields' => 'Дополнительные поля записей', + 'Extra field groups' => 'Группы дополнительных полей', + 'New extra field group' => 'Новая группа экстра полей', + 'Extra field group' => 'Группа экстра полей', + 'New record extra field' => 'Новое экстра поле записи', + 'Record extra field' => 'Экстра поле записи', + 'group is active' => 'группа активна', + 'field is active' => 'поле активно', + 'Cannot delete group that have fields' => 'Невозможно удалить группу, которая имеет поля', + 'Cannot delete active field' => 'Невозможно удалить активное поле', + 'Group fields' => 'Поля группы', + 'Add field' => 'Добавить поле', + 'Text field' => 'Текстовая строка', + 'File' => 'Файл', + 'Check box' => 'Галочка', + 'Radio button' => 'Переключатель', + 'Text area' => 'Текстовое поле', + 'Select dropdown' => 'Выпадающий список', + 'Image' => 'Изображение', + 'URL address' => 'URL адрес', + 'HTML code' => 'HTML код', + 'Type' => 'Тип', + 'Field values' => 'Значения поля', + 'add to record description' => 'добавить в описание записи' +); \ No newline at end of file diff --git a/themes/bulaksu/assets/css/desk.css b/themes/bulaksu/assets/css/desk.css index 87e7f1e..ebaf65c 100644 --- a/themes/bulaksu/assets/css/desk.css +++ b/themes/bulaksu/assets/css/desk.css @@ -486,7 +486,7 @@ body.dashboard-window-sidebar-resizing { border-bottom: 1px solid #EDEDF6; border-top: 1px solid #B3B6D1; padding: 0px; - margin: 7px 14px; + margin: 3px 14px; } .dashboard-window .dashboard-window-sidebar .dashboard-sidebar-content-wrapper ul { list-style-type: none; diff --git a/themes/dark/assets/css/desk.css b/themes/dark/assets/css/desk.css index 32b7be6..b7313de 100644 --- a/themes/dark/assets/css/desk.css +++ b/themes/dark/assets/css/desk.css @@ -66,7 +66,7 @@ body.dashboard-window-sidebar-resizing { min-height: 70px; background-color: #C1C5D1; border: 1px solid #99A5BA; - border: 1px solid rgb(143, 155, 162); + border: 1px solid rgb(191, 191, 198); box-shadow: 0px 0px 4px rgba(85, 70, 113, 0.41), inset 0px 0px 3px #CCC9DB; border-top-left-radius: 10px; border-top-right-radius: 10px; @@ -86,8 +86,8 @@ body.dashboard-window-sidebar-resizing { } .dashboard-window-focused { background-color: #BEBDDB; - background-color: rgb(201, 204, 210); - box-shadow: 0px 0px 4px rgba(85, 70, 113, 0.41), 0px 0px 3px #CCC9DB inset; + background-color: rgb(203, 203, 203); + box-shadow: 0px 0px 4px rgba(203, 191, 227, 0.4), 0px 0px 3px #F2F1F3 inset; } .dashboard-window-maximized.dashboard-window-focused { background-color: #D7D7E1; @@ -209,8 +209,9 @@ body.dashboard-window-sidebar-resizing { .dashboard-window .dashboard-window-footer { position: relative; width: 100%; - height: 16px; - border-top: 1px solid #efefef; + height: 14px; + border-top: 1px solid #ddd; + background: #ddd; overflow: hidden; -webkit-touch-callout: none; -webkit-user-select: none; @@ -220,7 +221,8 @@ body.dashboard-window-sidebar-resizing { user-select: none; } .dashboard-window-focused .dashboard-window-footer { - border-top: 1px solid #F1F6F6; + border-top: 1px solid #e0e2ed; + background: #e0e2ed; } .dashboard-window .dashboard-window-header .dashboard-window-title { display: block; @@ -494,7 +496,7 @@ body.dashboard-window-sidebar-resizing { border-bottom: 1px solid #EDEDF6; border-top: 1px solid #B3B6D1; padding: 0px; - margin: 7px 14px; + margin: 3px 14px; } .dashboard-window .dashboard-window-sidebar .dashboard-sidebar-content-wrapper ul { list-style-type: none; @@ -649,8 +651,8 @@ body.dashboard-window-sidebar-resizing { } .dashboard-window .dashboard-window-footer .dashboard-footer-content-wrapper { margin: 0px 10px; - color: #434A5F; - text-shadow: none; + color: #878890; + text-shadow: 0px 1px #fff; font-size: 12px; line-height: 12px; white-space: nowrap; diff --git a/themes/default/assets/css/desk.css b/themes/default/assets/css/desk.css index ad5db15..b28af22 100644 --- a/themes/default/assets/css/desk.css +++ b/themes/default/assets/css/desk.css @@ -486,7 +486,7 @@ body.dashboard-window-sidebar-resizing { border-bottom: 1px solid #EDEDF6; border-top: 1px solid #B3B6D1; padding: 0px; - margin: 7px 14px; + margin: 3px 14px; } .dashboard-window .dashboard-window-sidebar .dashboard-sidebar-content-wrapper ul { list-style-type: none; diff --git a/zira/zira.php b/zira/zira.php index d5ef0e1..18a021d 100644 --- a/zira/zira.php +++ b/zira/zira.php @@ -10,7 +10,7 @@ namespace Zira; use Dash\Dash; class Zira { - const VERSION = '1.1.0'; + const VERSION = '1.2.0'; private static $_instance; public static function getInstance() {