diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..496ee2c --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +.DS_Store \ No newline at end of file diff --git a/assets/dynamictextgroup.fieldeditor.js b/assets/dynamictextgroup.fieldeditor.js index 1a9a466..8cc2250 100644 --- a/assets/dynamictextgroup.fieldeditor.js +++ b/assets/dynamictextgroup.fieldeditor.js @@ -61,12 +61,15 @@ renames.handles = []; $(".box", "#stage").each(function() { + var $this = $(this); var field = {}; field.label = $('.tfield', $(this)).val(); field.width = Math.round(dtgEditor.parseWidth($(this).innerWidth())*10)/10; field.options = {}; - field.options.required = $('input[name="required"]', $(this)).is(':checked'); - field.options.type = $('#fieldType', $(this)).val(); + field.options.required = $this.find('input[name="required"]', $(this)).is(':checked'); + field.options.multiline = $this.find('input[name="multiline"]', $(this)).is(':checked'); + field.options.formatter = $this.find('select[name="fieldFormatter"]', $(this)).val(); + field.options.type = $this.find('#fieldType', $(this)).val(); //if (field.options.type == 'select') field.options.selectItems = $('#selectItems', $(this)).val(); if (field.options.type == 'select') { var str = $('#customSelect', $(this)).val(); @@ -150,6 +153,7 @@ // Field Type select var fieldType = $('') .append('') + .append('') .append('') .append('') .append(''); @@ -170,16 +174,36 @@ $('email').click(function(){ $(validationRule).val('/^\\w(?:\\.?[\\w%+-]+)*@\\w(?:[\\w-]*\\.)+?[a-z]{2,}$/i'); dtgEditor.buildSchema(); return false; }).appendTo(validationRuleLabel); $('URI').click(function(){ $(validationRule).val('/^[^\\s:\\/?#]+:(?:\\/{2,3})?[^\\s.\\/?#]+(?:\\.[^\\s.\\/?#]+)*(?:\\/[^\\s?#]*\\??[^\\s?#]*(#[^\\s#]*)?)?$/'); dtgEditor.buildSchema(); return false; }).appendTo(validationRuleLabel); + // Formatter + var fieldFormatter = $('') + .append(''); + //append real formatters added in SymphonyVar + $.each(Symphony.textFormatters,function(index,value){ + fieldFormatter.append(''); + }); + + $(fieldFormatter).val(fOpts.formatter); + var fieldFormatterLabel = $('').append(fieldFormatter); + // Required checkbox var requiredBox = $(''); if (fOpts.required) $(requiredBox).attr('checked','checked'); $(requiredBox).change(function() { dtgEditor.buildSchema(); }); var requiredBoxLabel = $('').append(requiredBox).append('Required'); + + // Row Count Holder + console.log(fOpts); + var multilineBox = $(''); + if (fOpts.multiline) $(multilineBox).attr('checked','checked'); + $(multilineBox).change(function() { dtgEditor.buildSchema(); }); + var multilineBoxLabel = $('').append(multilineBox).append('Multiline'); // Append field type options var fieldTypeHolder = $('
  • ').append(fieldTypeLabel).appendTo($(options)); var selectItemsHolder = $('
  • ').append(selectItemsLabel).append(customSelectLabel).appendTo($(options)).hide(); var validationRuleHolder = $('
  • ').append(validationRuleLabel).appendTo($(options)).hide(); + var fieldFormatterHolder = $('
  • ').append(fieldFormatterLabel).appendTo($(options)).hide(); + var multilineBoxHolder = $('
  • ').append(multilineBoxLabel).appendTo($(options)).hide(); var requiredBoxHolder = $('
  • ').append(requiredBoxLabel).appendTo($(options)); // Find current field type and show appropriate options @@ -193,6 +217,14 @@ case 'text': $(validationRuleHolder).show(); $(validationRule).val(fOpts.validationRule); + $(fieldFormatterHolder).show(); + $(multilineBoxHolder).show(); + break; + case 'multilingual': + $(validationRuleHolder).show(); + $(validationRule).val(fOpts.validationRule); + $(fieldFormatterHolder).show(); + $(multilineBoxHolder).show(); break; } @@ -204,13 +236,22 @@ // clear options $(validationRuleHolder).slideUp(250); $(selectItemsHolder).slideUp(250); + $(fieldFormatterHolder).slideUp(250); + $(multilineBoxHolder).slideUp(250); // show appropriate options switch($(this).val()) { case 'select': $(selectItemsHolder).slideDown(250); break; + case 'multilingual': + $(validationRuleHolder).slideDown(250); + $(fieldFormatterHolder).slideDown(250); + $(multilineBoxHolder).slideDown(250); + break; case 'text': $(validationRuleHolder).slideDown(250); + $(fieldFormatterHolder).slideDown(250); + $(multilineBoxHolder).slideDown(250); break; case 'checkbox': break; diff --git a/assets/dynamictextgroup.publish.js b/assets/dynamictextgroup.publish.js index a681df7..4ef2670 100644 --- a/assets/dynamictextgroup.publish.js +++ b/assets/dynamictextgroup.publish.js @@ -59,7 +59,7 @@ $('.fieldtype-'+type).each(function() { var checker = $('input[type="'+type+'"]', $(this)); var checkData = $('input[type="hidden"]', $(this)); - if ($(checker).attr('checked')) { + if ($(checker).prop('checked')) { $(checkData).val('yes'); } else { $(checkData).val(''); @@ -103,6 +103,11 @@ $(this).removeClass('styled'); }); customSelect('.dtg'); + + $('.field-multilingual').on('click', 'li', function(){ + var lang_code = $(this).data('lang_code'); + $('.field-dynamictextgroup .fieldHolder.multilingual input,.field-dynamictextgroup .fieldHolder.multilingual textarea').hide().filter('.'+lang_code).show(); + }); DynamicTextGroup.parseBadItems(); DynamicTextGroup.constructed(); @@ -137,6 +142,9 @@ $(this).removeClass('styled'); }); customSelect('.create'); + var lang_code = $('.field-multilingual .tabs .active').eq(0).attr('class').substring(0,2); + console.log(lang_code); + $('.field-dynamictextgroup .fieldHolder.multilingual input,.field-dynamictextgroup .fieldHolder.multilingual textarea').hide().filter('.'+lang_code).show(); }); //$('.fields', manager).click(function() { event.stopPropagation(); }); diff --git a/extension.driver.php b/extension.driver.php index 26a2893..67ea92f 100644 --- a/extension.driver.php +++ b/extension.driver.php @@ -39,4 +39,70 @@ public function uninstall() { Symphony::Database()->query("DROP TABLE `tbl_fields_dynamictextgroup`"); } + /*------------------------------------------------------------------------------------------------*/ + /* Delegates */ + /*------------------------------------------------------------------------------------------------*/ + + public function getSubscribedDelegates(){ + return array( + array( + 'page' => '/extensions/frontend_localisation/', + 'delegate' => 'FLSavePreferences', + 'callback' => 'dFLSavePreferences' + ), + ); + } + + /*------------------------------------------------------------------------------------------------*/ + /* System preferences */ + /*------------------------------------------------------------------------------------------------*/ + + + /** + * Save options from Preferences page + * + * @param array $context + */ + public function dFLSavePreferences($context){ + $fieldTable = "tbl_fields_dynamictextgroup"; + $fields = Symphony::Database()->fetch(sprintf('SELECT `field_id` FROM `%s`', $fieldTable)); + + if( $fields ){ + // Foreach field check multilanguage values foreach language + foreach( $fields as $field ){ + $entries_table = 'tbl_entries_data_'.$field["field_id"]; + + try{ + $columns = Symphony::Database()->fetchCol('Field',"SHOW COLUMNS FROM `{$entries_table}`;"); + } + catch( DatabaseException $dbe ){ + // Field doesn't exist. Better remove it's settings + Symphony::Database()->query(sprintf( + "DELETE FROM `%s` WHERE `field_id` = %s;", + $fieldTable, $field["field_id"]) + ); + continue; + } + + $fieldObject = FieldManager::fetch($field["field_id"]); + $schema = json_decode($fieldObject->get('schema')); + foreach ($schema as $key => $schemaField) { + if ($schemaField->options->type=='multilingual'){ + // var_dump($schemaField->handle);die; + + + foreach( $context['new_langs'] as $lc ){ + // If column lang_code dosen't exist in the laguange drop columns + + if( !in_array($schemaField->handle . '-'.$lc, $columns) ){ + $fieldObject->__alterTable(1, $schemaField->handle . '-' . $lc ,$schemaField->options->multiline, $schemaField->options->formatter,$schemaField); + } + } + } + } + + } + } + } + } diff --git a/extension.meta.xml b/extension.meta.xml index 4f09f28..6ac1ddd 100644 --- a/extension.meta.xml +++ b/extension.meta.xml @@ -6,19 +6,25 @@ http://symphony-cms.com/discuss/thread/70781/ Field Types + Multilingual Brock Petrie http://www.brockpetrie.com + + Jon Mifsud + http://jonmifsud.com + - - stage - + + - Added support for Text Formatters and Text Areas + - Added support for Multilanguage interfaces (requires Frontend Localisation) + 3.0 development - 2.0 release + 2.0 release Initial release diff --git a/fields/field.dynamictextgroup.php b/fields/field.dynamictextgroup.php index 4360597..8baa8f0 100644 --- a/fields/field.dynamictextgroup.php +++ b/fields/field.dynamictextgroup.php @@ -5,9 +5,10 @@ if(!defined('__IN_SYMPHONY__')) die('

    Symphony Error

    You cannot directly access this file

    '); + require_once FACE . '/interface.importablefield.php'; require_once(EXTENSIONS . '/dynamictextgroup/lib/class.textgroup.php'); - Class fielddynamictextgroup extends Field { + Class fielddynamictextgroup extends Field implements ImportableField{ /* * * @see http://symphony-cms.com/learn/api/2.2/toolkit/field/#__construct * * */ function __construct() { @@ -48,17 +49,31 @@ function allowDatasourceParamOutput() { /* * * @see http://symphony-cms.com/learn/api/2.2/toolkit/field/#displaySettingsPanel * * */ - function displaySettingsPanel(&$wrapper, $errors=NULL) { + function displaySettingsPanel(XMLElement &$wrapper, $errors=NULL) { // Initialize field settings based on class defaults (name, placement) parent::displaySettingsPanel($wrapper, $errors); // Field Editor if ($this->get('id')) { - Administration::instance()->Page->addScriptToHead(URL . '/extensions/dynamictextgroup/assets/jquery-ui-1.10.3.custom.min.js', 101, false); - Administration::instance()->Page->addScriptToHead(URL . '/extensions/dynamictextgroup/assets/json2.js', 102, false); - Administration::instance()->Page->addScriptToHead(URL . '/extensions/dynamictextgroup/assets/dynamictextgroup.fieldeditor.js', 103, false); - Administration::instance()->Page->addStylesheetToHead(URL . '/extensions/dynamictextgroup/assets/dynamictextgroup.fieldeditor.css', 'screen', 104, false); + Administration::instance()->Page->addScriptToHead(URL . '/extensions/dynamictextgroup/assets/jquery-ui-1.10.3.custom.min.js', 2101, false); + Administration::instance()->Page->addScriptToHead(URL . '/extensions/dynamictextgroup/assets/json2.js', 2102, false); + Administration::instance()->Page->addScriptToHead(URL . '/extensions/dynamictextgroup/assets/dynamictextgroup.fieldeditor.js', 2103, false); + Administration::instance()->Page->addStylesheetToHead(URL . '/extensions/dynamictextgroup/assets/dynamictextgroup.fieldeditor.css', 'screen', 2104, false); + + + $textFormatterScriptCode = "Symphony.textFormatters = {"; + $textFormatters = TextformatterManager::listAll(); + foreach ($textFormatters as $key => $textFormatter) { + $textFormatterScriptCode.="'{$key}' : '{$textFormatter['name']}',"; + } + $textFormatterScriptCode = trim($textFormatterScriptCode, ","); + $textFormatterScriptCode.='}'; + + $textFormatterScript = new XMLElement('script',$textFormatterScriptCode,array('type'=>'text/javascript')); + + Administration::instance()->Page->addElementToHead($textFormatterScript, 2106, true); + $tblocks = 'get('schema').'\' />'; //$tblocks .= ''.$this->get('schema').''; @@ -95,7 +110,7 @@ function displaySettingsPanel(&$wrapper, $errors=NULL) { /* * * @see http://symphony-cms.com/learn/api/2.2/toolkit/field/#checkFields * * */ - function checkFields(&$errors, $checkForDuplicates=true) { + function checkFields(array &$errors, $checkForDuplicates = true) { parent::checkFields($errors, $checkForDuplicates); } @@ -155,7 +170,43 @@ function commit() { } - function __alterTable($mode, $col, $rename=NULL) { + function __alterTable($mode, $col, $rename=NULL, $multiline = null, $formatter = null,$oldFieldSchema=null) { + $type = null; + if (!isset($oldSchema)){ + $id = $this->get('id'); + $oldSchema = json_decode(Symphony::Database()->fetchVar("schema",0,"SELECT `schema` FROM `tbl_fields_" . $this->handle() . "` WHERE `field_id` = '$id' LIMIT 1")); + + if (isset($oldSchema)){ + foreach($oldSchema as $field) { + if ($rename == strtolower($field->label) || $col == strtolower($field->label)) { + $oldFieldSchema = $field; + break; + } + } + } + } + + foreach(json_decode($this->get('schema')) as $field) { + if ($rename == strtolower($field->label) || $col == strtolower($field->label)) { + $type = $field->options->type; + $multiline = $field->options->multiline; + $formatter = $field->options->formatter; + break; + } + } + + if ($type == 'multilingual'){ + foreach (FLang::getLangs() as $lang){ + $return = $this->__alterTable($mode,$col.'-'.$lang,$rename.'-'.$lang, $multiline, $formatter,$oldFieldSchema); + } + return; + } + + $fieldtype = 'varchar(255) null'; + if (isset($multiline)){ + $fieldtype = 'TEXT default NULL'; + } + // Function $mode options: // 0 = Delete column; e.g. __alterTable(0, 'badcolumn'); // 1 = Add column; e.g. __alterTable(1, 'newcolumn'); @@ -164,14 +215,32 @@ function __alterTable($mode, $col, $rename=NULL) { case 0: // Delete column Symphony::Database()->query("ALTER TABLE `tbl_entries_data_" . $this->get('id') . "` DROP COLUMN `". $col ."`"); + if (isset($oldFieldSchema->options->formatter) && $oldFieldSchema->options->formatter !='none'){ + //had a formatter so remove coloumn + Symphony::Database()->query("ALTER TABLE `tbl_entries_data_" . $this->get('id') . "` DROP COLUMN `". $col ."-formatted`"); + } break; case 1: // Add column - Symphony::Database()->query("ALTER TABLE `tbl_entries_data_" . $this->get('id') . "` ADD COLUMN `". $col ."` varchar(255) null"); + Symphony::Database()->query("ALTER TABLE `tbl_entries_data_" . $this->get('id') . "` ADD COLUMN `". $col ."` ".$fieldtype); + if (isset($formatter) && $formatter != 'none'){ + Symphony::Database()->query("ALTER TABLE `tbl_entries_data_" . $this->get('id') . "` ADD COLUMN `". $col ."-formatted` ".$fieldtype); + } break; case 2: // Rename column - Symphony::Database()->query("ALTER TABLE `tbl_entries_data_" . $this->get('id') . "` CHANGE `". $col ."` `". $rename ."` varchar(255) null"); + Symphony::Database()->query("ALTER TABLE `tbl_entries_data_" . $this->get('id') . "` CHANGE `". $col ."` `". $rename ."` ".$fieldtype); + if (isset($formatter) && $formatter != 'none' && isset($oldFieldSchema->options->formatter) && $oldFieldSchema->options->formatter !='none'){ + //has a formatter and was previously set so alter coloumn name + Symphony::Database()->query("ALTER TABLE `tbl_entries_data_" . $this->get('id') . "` CHANGE `". $col ."-formatted` `". $rename ."-formatted` ".$fieldtype); + } else if (isset($formatter) && $formatter != 'none'){ + //has a formatter (not previously) so add coloumn + Symphony::Database()->query("ALTER TABLE `tbl_entries_data_" . $this->get('id') . "` ADD COLUMN `". $col ."-formatted` ".$fieldtype); + } + else if (isset($oldFieldSchema->options->formatter) && $oldFieldSchema->options->formatter !='none'){ + //had a formatter before (not anymore) so remove previous coloumn + Symphony::Database()->query("ALTER TABLE `tbl_entries_data_" . $this->get('id') . "` DROP COLUMN `". $rename ."-formatted`"); + } break; default: return false; @@ -180,7 +249,7 @@ function __alterTable($mode, $col, $rename=NULL) { /* * * @see http://symphony-cms.com/learn/api/2.2/toolkit/field/#displayPublishPanel * * */ - function displayPublishPanel(&$wrapper, $data=NULL, $flagWithError=NULL, $fieldnamePrefix=NULL, $fieldnamePostfix=NULL) { + function displayPublishPanel(XMLElement &$wrapper, $data = NULL, $flagWithError = NULL, $fieldnamePrefix = NULL, $fieldnamePostfix = NULL, $entry_id = NULL) { // Append assets Administration::instance()->Page->addScriptToHead(URL . '/extensions/dynamictextgroup/assets/select2/select2.min.js', 101, false); @@ -209,6 +278,7 @@ function displayPublishPanel(&$wrapper, $data=NULL, $flagWithError=NULL, $fieldn )); // Populate existing entries + if ($schema != NULL) { $content = array(); if(is_array($data)) { @@ -220,7 +290,15 @@ function displayPublishPanel(&$wrapper, $data=NULL, $flagWithError=NULL, $fieldn for($i=0; $i<$entryCount; $i++) { foreach ($schema as $field) { - $entryValues[$i][] = $data[$field->handle][$i]; + if ($field->options->type == 'multilingual'){ + $values = array(); + foreach (FLang::getLangs() as $lang) { + $values[$lang] = $data[$field->handle.'-'.$lang][$i]; + } + $entryValues[$i][] = $values; + } else { + $entryValues[$i][] = $data[$field->handle][$i]; + } } $list->appendChild( Textgroup::createNewTextGroup($this->get('element_name'), $fieldCount, $entryValues[$i], 'dtg', $schema) @@ -268,7 +346,11 @@ public function checkPostFieldData($data, &$message, $entry_id=NULL){ $schema = json_decode($this->get('schema')); $sampling = $schema[0]->handle; - $entryCount = count($data[$sampling]); + if (is_array($data[$sampling])){ + $entryCount = count($data[$sampling]); + } else { + $entryCount = 1; + } $empty = true; @@ -301,6 +383,22 @@ public function checkPostFieldData($data, &$message, $entry_id=NULL){ $emptyRow = false; } break; + case 'multilanguage': + // Check if field passes any rules + $rule = $field->options->validationRule != '' ? $field->options->validationRule : false; + if ($rule && !General::validateString($data[$field->handle][$i], $rule)){ + $badValidate[] = array('handle' => $field->handle.'-holder', 'index' => $i); + } + //If textarea formatter should be here + + // Check if required subfield is empty + if ($req && $data[$field->handle][$i] == '') { + $emptyReq = true; + } else if ($data[$field->handle][$i] != '') { + $empty = false; + $emptyRow = false; + } + break; case 'select': if ($req && $data[$field->handle][$i] == '') { @@ -364,9 +462,81 @@ public function checkPostFieldData($data, &$message, $entry_id=NULL){ return self::__OK__; } + + public function getImportModes(){ + //only support array data + return array( + 'getPostdata' => ImportableField::ARRAY_VALUE, + 'xml' => ImportableField::STRING_VALUE + ); + } + + public function prepareImportValue($data, $mode, $entry_id = null){ + + if ($mode == $this->getImportModes()['xml']){ + + $schema = json_decode($this->get('schema')); + + $result = array(); + foreach ($schema as $field) { + $handle = $field->handle; + if ($field->options->type=='multilingual'){ + if (!class_exists(FLang)){ + $flExt = ExtensionManager::create('frontend_localisation'); + } + $langs = FLang::getLangs(); + //initialize frontend localisation as not initiated + if (empty($langs)){ + $flExt = ExtensionManager::create('frontend_localisation'); + $flExt->dFrontendInitialised(); + $langs = FLang::getLangs(); + } + foreach( $langs as $lang ){ + $result[$handle.'-'.$lang] = array(); + } + } else { + $result[$handle] = array(); + } + } + + if (is_array($data)) $data = current($data); + + $xml = simplexml_load_string($data); + + foreach ($xml->xpath('item') as $item) { + foreach ($schema as $field) { + $handle = $field->handle; + if ($field->options->type=='multilingual'){ + foreach( $langs as $lang ){ + $langHandle = $handle.'-'.$lang; + $result[$langHandle][] = (string)$item->$langHandle; + } + } else { + $result[$handle][] = (string)$item->$handle; + } + } + } + } else { + $result = $data; + } + + return $result; + } + + public function applyFormatting($data,$textFormatter='none') { + if (isset($textFormatter) && $textFormatter != 'none') { + $formatter = TextformatterManager::create($textFormatter); + $formatted = $formatter->run($data); + $formatted = preg_replace('/&(?![a-z]{0,4}\w{2,3};|#[x0-9a-f]{2,6};)/i', '&', $formatted); + + return trim($formatted); + } + + return General::sanitize($data); + } /* * * @see http://symphony-cms.com/learn/api/2.2/toolkit/field/#processRawFieldData * * */ - function processRawFieldData($data, &$status, $simulate=false, $entry_id=NULL) { + function processRawFieldData($data, &$status, &$message = NULL, $simulate = false, $entry_id = NULL) { $status = self::__OK__; if(!is_array($data)) return NULL; @@ -375,26 +545,60 @@ function processRawFieldData($data, &$status, $simulate=false, $entry_id=NULL) { // Check for the field with the most values $entryCount = 0; - foreach ($data as $row) if (count($row) > $entryCount) $entryCount = count($row); + foreach ($data as $row) { + if (is_array($row) && count($row) > $entryCount){ + $entryCount = count($row); + } else if ($entryCount == 0) { + $entryCount = 1; + } + } // Check for empties $empty = true; + + $schema = json_decode($this->get('schema')); + $fields = $arrayName = array(); + foreach ($schema as $key => $field) { + $fields[$field->handle] = $field; + } for($i=0; $i < $entryCount; $i++) { $emptyEntry = true; - foreach ($data as &$field) { - if (!empty($field[$i]) || $field[$i] == '0') { + foreach ($data as $key => &$field) { + + //set formatter + $formatter = $fields[$key]->options->formatter; + if(!isset($fields[$key]) && isset($fields[substr($key, 0, -3)])){ + $formatter = $fields[substr($key, 0, -3)]->options->formatter; + } + + // set blank checkboxes to no + if ($fields[$key]->options->type == 'checkbox'){ + if (!$field[$i]){ + $field[$i] = "no"; + } + } + + $trimmed = trim($field[$i]); + + if (!empty($trimmed) || $field[$i] == '0') { $empty = false; $emptyEntry = false; - //$field[$i] = str_replace("\"", """, $field[$i]); - $field[$i] = str_replace("'", "'", $field[$i]); + if (isset($formatter) && $formatter!='none'){ + $data[$key.'-formatted'][$i] = $this->applyFormatting($field[$i],$formatter); + } } else { $field[$i] = ' '; + if (isset($formatter) && $formatter!='none'){ + $data[$key.'-formatted'][$i] = ' '; + } } } if ($emptyEntry) { foreach ($data as &$field) { - unset($field[$i]); + if (is_array($field)){ + unset($field[$i]); + } } } } @@ -404,7 +608,6 @@ function processRawFieldData($data, &$status, $simulate=false, $entry_id=NULL) { } else { return $data; } - } @@ -422,7 +625,7 @@ function createTable() { /* * * @see http://symphony-cms.com/learn/api/2.2/toolkit/field/#prepareTableValue * * */ - function prepareTableValue($data, XMLElement $link=NULL) { + function prepareTableValue($data, XMLElement $link = NULL, $entry_id = NULL) { if (is_array($data)) { $keys = array_keys($data); $key = $keys[0]; @@ -441,10 +644,44 @@ function prepareTableValue($data, XMLElement $link=NULL) { /* * * @see http://symphony-cms.com/learn/api/2.2/toolkit/field/#buildSortingSQL * * */ - /* + function buildSortingSQL(&$joins, &$where, &$sort, $order='ASC') { + $field_id = $this->get('id'); + $schema = json_decode($this->get('schema')); + + $fieldHandles = array(); + foreach ($schema as $k => $v) { + $fieldHandles[$k] = $v->handle; + } + if (!in_array('sort-value', $fieldHandles) || !in_array('value', $fieldHandles)){ + $sort = " RAND()"; + return true; + } + + $joins .= " + LEFT JOIN + `tbl_entries_data_{$field_id}` AS t{$field_id}_{$this->_key} + ON + (e.id = t{$field_id}_{$this->_key}.entry_id) + "; + + $data[0] = explode(':', trim($this->cleanValue($data[0]))); + $handle = $data[0][0]; + $value = $data[0][1]; + + $where .= " + AND ( + `t{$field_id}_{$this->_key}`.`key` = 'sort-value' + ) + "; + + $sort = " + `t{$field_id}_{$this->_key}`.`value` + "; + + return true; } - */ + /* * * @see http://symphony-cms.com/learn/api/2.2/toolkit/field/#buildDSRetrivalSQL * * */ @@ -453,7 +690,7 @@ function buildSortingSQL(&$joins, &$where, &$sort, $order='ASC') { ** handle:value (e.g. first-name:Brock) ** Where 'handle' is equal to the handle of a subfield, and 'value' is equal to the input of said subfield. All entries with a matching value in this subfield will be returned. */ - public function buildDSRetrivalSQL($data, &$joins, &$where, $andOperation = false) { + public function buildDSRetrievalSQL($data, &$joins, &$where, $andOperation = false) { $field_id = $this->get('id'); if (preg_match('/.*:.*/', $data[0])) { @@ -488,12 +725,14 @@ public function groupRecords($records) { /* * * @see http://symphony-cms.com/learn/api/2.2/toolkit/field/#appendFormattedElement * * */ - public function appendFormattedElement(&$wrapper, $data, $encode = false, $mode = null, $entry_id = null) { + public function appendFormattedElement(XMLElement &$wrapper, $data, $encode = false, $mode = NULL, $entry_id = NULL) { // Get field properties and decode schema $fieldCount = $this->get('fieldcount'); $schema = json_decode($this->get('schema')); $sampling = $schema[0]->handle; - $entryCount = count($data[$sampling]); + if (is_array($data[$sampling])){ + $entryCount = count($data[$sampling]); + } // Parse data $textgroup = new XMLElement($this->get('element_name')); @@ -512,9 +751,29 @@ public function appendFormattedElement(&$wrapper, $data, $encode = false, $mode foreach ($tryjson as $key => $obj) { $node->appendChild(new XMLElement($key, $obj)); } + } else if ($field->options->type == 'multilingual'){ + $lang = FLang::getLang(); + $fieldHandle = $field->handle . '-' . $lang; + if (isset($field->options->formatter) && $field->options->formatter !='none' && isset($data[$fieldHandle.'-formatted'][$i] )){ + $fieldHandle.='-formatted'; + //data should be already sanitized/formatted + $val = $data[$fieldHandle][$i] != ' ' ? $data[$fieldHandle][$i] : ''; + } else { + //cover our ass by sanitizing the data + $val = $data[$fieldHandle][$i] != ' ' ? General::sanitize($data[$fieldHandle][$i]) : ''; + } + $node->setValue($val); } else { $val = $data[$field->handle][$i] != ' ' ? General::sanitize($data[$field->handle][$i]) : ''; $node->setValue($val); + + if (isset($field->options->formatter) && $field->options->formatter !='none' && isset($data[$field->handle . '-formatted'][$i] )){ + $fieldHandle = $field->handle . '-formatted'; + //data should be already sanitized/formatted + $val = $data[$fieldHandle][$i]; + $formattedNode = new XMLElement($field->handle,$val,array('mode'=>'formatted')); + $item->appendChild($formattedNode); + } } $item->appendChild($node); } diff --git a/lib/class.textgroup.php b/lib/class.textgroup.php index e13bd02..70deec6 100644 --- a/lib/class.textgroup.php +++ b/lib/class.textgroup.php @@ -8,14 +8,16 @@ public static function createNewTextGroup($element, $fieldCount=2, $values=NULL, if($class) { $classes[] = $class; } - // Field creator $fields = ''; for ($i=0; $i<$fieldCount; $i++) { $fieldVal = ($values != NULL && $values[$i] != ' ') ? $values[$i] : NULL; switch ($schema[$i]->options->type) { case 'text': - $fields .= self::__createTextField($element, $schema[$i]->handle, $fieldVal, $schema[$i]->label, $schema[$i]->width, $schema[$i]->options->required); + $fields .= self::__createTextField($element, $schema[$i]->handle, $fieldVal, $schema[$i]->label, $schema[$i]->width, $schema[$i]->options->required, $schema[$i]->options->multiline); + break; + case 'multilingual': + $fields .= self::__createMultilingualTextField($element, $schema[$i]->handle, $fieldVal, $schema[$i]->label, $schema[$i]->width, $schema[$i]->options->required, $schema[$i]->options->multiline); break; case 'select': $fields .= self::__createSelectField($element, $schema[$i]->handle, $fieldVal, $schema[$i]->label, $schema[$i]->width, $schema[$i]->options); @@ -39,13 +41,34 @@ public static function createNewTextGroup($element, $fieldCount=2, $values=NULL, ); } - private static function __createTextField($element, $handle, $textvalue, $label=NULL, $width=NULL, $required=NULL) { + private static function __createTextField($element, $handle, $textvalue, $label=NULL, $width=NULL, $required=NULL,$multiline=NULL) { + // Generate text field + $width = 'style="width:'. $width .'% !important;"'; + $reqLabelAppendage = $required ? ' *' : ''; + $reqclas .= $required ? ' req' : ''; + $lbl = ''; + $input = ''; + if (!isset($multiline) || !$multiline) + $input.=''; + else + $input.=''; + return ''. $lbl . $input . ''; + } + + private static function __createMultilingualTextField($element, $handle, $value, $label=NULL, $width=NULL, $required=NULL,$multiline=NULL) { // Generate text field $width = 'style="width:'. $width .'% !important;"'; $reqLabelAppendage = $required ? ' *' : ''; $reqclas .= $required ? ' req' : ''; + $input = ''; + foreach (FLang::getLangs() as $lang) { + if (!isset($multiline)) + $input.=''; + else + $input.=''; + } $lbl = ''; - return ''. $lbl .''; + return ''. $lbl . $input . ''; } private static function __createSelectField($element, $handle, $val, $label=NULL, $width=NULL, $options=NULL) { @@ -65,7 +88,7 @@ private static function __createSelectField($element, $handle, $val, $label=NULL $items = ''; if (is_string($options->selectItems)) { $items = explode(',', $options->selectItems); - $obj = ''; + $obj = []; foreach ($items as $item) { $obj[] = (object) array('id' => trim($item), 'text' => trim($item)); }