├── README.markdown ├── addon.setup.php ├── css └── EntryTypeFieldSettings.css ├── ft.entry_type.php ├── javascript ├── EntryType.js └── EntryTypeFieldSettings.js ├── language └── english │ └── entry_type_lang.php ├── libraries └── Entry_type.php ├── src └── CreateFieldEntryTypeCommand.php └── views ├── option_row.php └── options.php /README.markdown: -------------------------------------------------------------------------------- 1 | # Entry Type 2 | 3 | An ExpressionEngine 4 add-on for hiding publish fields on a conditional basis. The Entry Type fieldtype creates a dropdown field which can hide other publish fields depending on the value chosen. 4 | 5 | Use the [`ee2`](/rsanchez/entry_type/tree/ee2) branch for an EE2 compatible version. Structure/Pages module compatibility has been removed in the EE3 version. 6 | 7 | Use the [`ee3`](/rsanchez/entry_type/tree/ee3) branch for an EE3 compatible version. 8 | 9 | ## Installation 10 | 11 | * Requires PHP 5.3 12 | * Download the addon and rename the folder to `entry_type` 13 | * Copy to `system/user/addons` 14 | * Install the addon 15 | 16 | ## Fieldtype Tags 17 | 18 | {your_field_name} 19 | 20 | The short name for the entry type selected. 21 | 22 | {your_field_name:label} 23 | 24 | The label for the entry type selected. 25 | 26 | {if {your_field_name:selected option="link"}} 27 | 28 | Check whether the specified option is selected. (Use the short name). 29 | 30 | {your_field_name all_options="yes"} 31 | {option} {option_name} {label} {selected} 32 | {/your_field_name} 33 | 34 | List all your options. 35 | 36 | ## Fieldtype Settings 37 | 38 | - Short Name - the value of the field, for use in templates and conditionals 39 | - Label - the label for the value 40 | - Hide Fields - choose the fields to hide when the specified value is chosen 41 | 42 | ## Examples 43 | 44 | Displaying different content based on entry type. 45 | 46 | {exp:channel:entries} 47 | {title}
48 | {your_entry_type_field:label}
49 | {if your_entry_type_field == 'link'} 50 | {link_url} 51 | {if:else your_entry_type_field == 'video'} 52 | {video} 53 | {if:elseif your_entry_type_field == 'image'} 54 | {image} 55 | {/if} 56 | {/exp:channel:entries} 57 | -------------------------------------------------------------------------------- /addon.setup.php: -------------------------------------------------------------------------------- 1 | 'Entry Type', 5 | 'version' => '5.0.0', 6 | 'description' => 'A fieldtype for hiding publish fields on a conditional basis.', 7 | 'namespace' => '\\', 8 | 'author' => 'Rob Sanchez', 9 | 'author_url' => 'https://github.com/rsanchez', 10 | 'docs_url' => 'https://github.com/rsanchez/entry_type', 11 | 'settings_exist' => false, 12 | 'fieldtypes' => array( 13 | 'entry_type' => array( 14 | 'name' => 'Entry Type', 15 | ), 16 | ) 17 | ); 18 | -------------------------------------------------------------------------------- /css/EntryTypeFieldSettings.css: -------------------------------------------------------------------------------- 1 | .entry_type_remove_row:before { 2 | content: '\f1f8'; 3 | color: #1f80bd; 4 | font-family: FontAwesome; 5 | display: inline-block; 6 | -webkit-font-smoothing: antialiased; 7 | font-size: 1.5em; 8 | } 9 | 10 | .entry_type_options tbody tr:last-child td { 11 | border-bottom: 1px solid #e6e6e6; 12 | } 13 | 14 | .entry_type_hide_fields { 15 | display: block; 16 | } 17 | 18 | .entry_type_add_row .icon.plus:before { 19 | content: '\f067'; 20 | } 21 | 22 | /* EE6+ specific styles. Use FA icons instead. */ 23 | body[data-ee-version] .entry_type_add_row .icon.plus:before, 24 | body[data-ee-version] .entry_type_remove_row:before { 25 | content: ""; 26 | } 27 | 28 | body[data-ee-version] .entry_type_remove_row { 29 | color: var(--ee-danger); 30 | } 31 | -------------------------------------------------------------------------------- /ft.entry_type.php: -------------------------------------------------------------------------------- 1 | 'Entry Type', 10 | 'version' => '4.0.0', 11 | ]; 12 | 13 | /** 14 | * @var bool 15 | */ 16 | public $has_array_data = true; 17 | 18 | /** 19 | * @var bool 20 | */ 21 | public $entry_manager_compatible = true; 22 | 23 | /** 24 | * @var array 25 | */ 26 | protected $fieldtypes = [ 27 | 'select' => [ 28 | 'field_text_direction' => 'ltr', 29 | 'field_pre_populate' => 'n', 30 | 'field_pre_field_id' => false, 31 | 'field_pre_channel_id' => false, 32 | 'field_list_items' => false, 33 | ], 34 | 'radio' => [ 35 | 'field_text_direction' => 'ltr', 36 | 'field_pre_populate' => 'n', 37 | 'field_pre_field_id' => false, 38 | 'field_pre_channel_id' => false, 39 | 'field_list_items' => false, 40 | ], 41 | 'fieldpack_pill' => [], 42 | ]; 43 | 44 | /** 45 | * @param mixed $data 46 | * @param array $params 47 | * @param bool $tagdata 48 | * @return string 49 | */ 50 | public function replace_tag($data, $params = [], $tagdata = false) 51 | { 52 | if ($tagdata && isset($params['all_options']) && $params['all_options'] === 'yes') { 53 | return $this->replace_all_options($data, $params, $tagdata); 54 | } 55 | 56 | return $data; 57 | } 58 | 59 | /** 60 | * @param mixed $data 61 | * @param array $params 62 | * @param bool $tagdata 63 | * @return string 64 | */ 65 | public function replace_label($data, $params = [], $tagdata = false) 66 | { 67 | foreach ($this->settings['type_options'] as $value => $option) { 68 | if ($data == $value) { 69 | return (!empty($option['label'])) ? $option['label'] : $value; 70 | } 71 | } 72 | 73 | return $data; 74 | } 75 | 76 | /** 77 | * @param mixed $data 78 | * @param array $params 79 | * @param bool $tagdata 80 | * @return string 81 | */ 82 | public function replace_selected($data, $params = [], $tagdata = false) 83 | { 84 | if (!isset($params['option'])) { 85 | return 0; 86 | } 87 | 88 | return (int) ($data == $params['option']); 89 | } 90 | 91 | /** 92 | * @param mixed $data 93 | * @param array $params 94 | * @param bool $tagdata 95 | * @return string 96 | */ 97 | public function replace_all_options($data, $params = [], $tagdata = false) 98 | { 99 | $vars = []; 100 | 101 | foreach ($this->settings['type_options'] as $value => $option) { 102 | $label = (!empty($option['label'])) ? $option['label'] : $value; 103 | 104 | $vars[] = [ 105 | 'value' => $value, 106 | 'option' => $value, 107 | 'option_value' => $value, 108 | 'option_name' => $label, 109 | 'option_label' => $label, 110 | 'label' => $label, 111 | 'selected' => (int) ($data == $value), 112 | ]; 113 | } 114 | 115 | if (!$vars) { 116 | $vars[] = []; 117 | } 118 | 119 | return ee()->TMPL->parse_variables($tagdata, $vars); 120 | } 121 | 122 | /** 123 | * @param mixed $data 124 | * @return string 125 | */ 126 | public function display_field($data) 127 | { 128 | $options = []; 129 | 130 | foreach ($this->settings['type_options'] as $value => $row) { 131 | $options[$value] = (!empty($row['label'])) ? $row['label'] : $value; 132 | } 133 | 134 | ee()->load->library('entry_type'); 135 | 136 | $channel_id = ee()->input->get_post('channel_id'); 137 | 138 | if (REQ === 'CP' && ee()->uri->segment(3) === 'create') { 139 | $channel_id = ee()->uri->segment(4); 140 | } 141 | 142 | if (!$channel_id) { 143 | $entry_id = ee()->input->get_post('entry_id'); 144 | 145 | if (REQ === 'CP' && ee()->uri->segment(4) === 'entry') { 146 | $entry_id = ee()->uri->segment(5); 147 | } 148 | 149 | if ($entry_id) { 150 | /** @var CI_DB_result $query */ 151 | $query = ee()->db->select('channel_id') 152 | ->where('entry_id', $entry_id) 153 | ->get('channel_titles'); 154 | 155 | $channel_id = $query->row('channel_id'); 156 | 157 | $query->free_result(); 158 | } else { 159 | /** @var CI_DB_result $query */ 160 | $query = ee()->db->select('channel_id') 161 | ->limit(1) 162 | ->get('channels'); 163 | 164 | $channel_id = $query->row('channel_id'); 165 | 166 | $query->free_result(); 167 | } 168 | } 169 | 170 | ee()->entry_type->init($channel_id); 171 | ee()->entry_type->add_field($this->field_name, $this->settings['type_options']); 172 | 173 | if (!empty($this->settings['fieldtype'])) { 174 | $method = 'display_field_'.$this->settings['fieldtype']; 175 | 176 | if (method_exists($this, $method)) { 177 | return $this->$method($options, $data); 178 | } elseif ($fieldtype = ee()->api_channel_fields->setup_handler($this->settings['fieldtype'], true)) { 179 | $fieldtype->field_name = $this->field_name; 180 | $fieldtype->field_id = $this->field_id; 181 | $fieldtype->settings = $this->fieldtypes[$this->settings['fieldtype']]; 182 | $fieldtype->settings['field_list_items'] = $fieldtype->settings['options'] = $options; 183 | 184 | return $fieldtype->display_field($data); 185 | } 186 | } 187 | 188 | return $this->display_field_select($options, $data); 189 | } 190 | 191 | /** 192 | * @param array $options 193 | * @param string $current_value 194 | * @return string 195 | */ 196 | private function display_field_radio(array $options = [], $current_value = '') 197 | { 198 | $output = ''; 199 | 200 | foreach($options as $value => $label) { 201 | $output .= form_label(form_radio($this->field_name, $value, $value == $current_value).NBS.$label); 202 | } 203 | 204 | return $output; 205 | } 206 | 207 | /** 208 | * @param array $options 209 | * @param string $current_value 210 | * @return string 211 | */ 212 | private function display_field_select(array $options = [], $current_value = '') 213 | { 214 | return form_dropdown($this->field_name, $options, $current_value); 215 | } 216 | 217 | /** 218 | * Given a fieldId, find out what channel(s) it's assigned to and get all the custom fields for those channels. 219 | * @param int $fieldId 220 | * @param bool $excludeFieldId 221 | */ 222 | protected function fieldsByChannel(int $fieldId, bool $excludeFieldId = false) 223 | { 224 | /** @var CI_DB_result $result */ 225 | $result = ee()->db 226 | ->select('channel_id') 227 | ->where('field_id', $fieldId) 228 | ->group_by('channel_id') 229 | ->get('channels_channel_fields'); 230 | 231 | $channelIds = array_column($result->result_array(), 'channel_id'); 232 | 233 | if (empty($channelIds)) { 234 | return []; 235 | } 236 | 237 | $channels = ee('Model')->get('Channel') 238 | ->with('CustomFields') 239 | ->filter('channel_id', 'IN', $channelIds) 240 | ->all(); 241 | 242 | $fields = []; 243 | 244 | /** @var Channel $channel */ 245 | foreach ($channels as $channel) { 246 | $customFields = $channel->getAllCustomFields(); 247 | 248 | foreach ($customFields as $customField) { 249 | $fields[$customField->field_id] = $customField->field_label; 250 | } 251 | } 252 | 253 | if ($excludeFieldId) { 254 | foreach ($fields as $field_id => $field_label) { 255 | if ($excludeFieldId == $field_id) { 256 | unset($fields[$field_id]); 257 | 258 | break; 259 | } 260 | } 261 | } 262 | 263 | return $fields; 264 | } 265 | 266 | /** 267 | * @param int|bool $group_id 268 | * @param bool $exclude_field_id 269 | * @return array|mixed 270 | */ 271 | protected function fieldsByGroup($group_id = false, bool $exclude_field_id = false) 272 | { 273 | static $cache; 274 | 275 | if ($group_id === false) { 276 | if (isset($this->settings['group_id'])) { 277 | $group_id = $this->settings['group_id']; 278 | } else { 279 | return []; 280 | } 281 | } 282 | 283 | if ($exclude_field_id === false && isset($this->field_id) && is_numeric($this->field_id)) { 284 | $exclude_field_id = $this->field_id; 285 | } 286 | 287 | if (!isset($cache[$group_id])) { 288 | ee()->load->model('field_model'); 289 | 290 | /** @var CI_DB_result $query */ 291 | $query = ee()->field_model->get_fields($group_id); 292 | 293 | $cache[$group_id] = []; 294 | 295 | foreach ($query->result() as $row) { 296 | $cache[$group_id][$row->field_id] = $row->field_label; 297 | } 298 | 299 | $query->free_result(); 300 | } 301 | 302 | $fields = $cache[$group_id]; 303 | 304 | if ($exclude_field_id) { 305 | foreach ($fields as $field_id => $field_label) { 306 | if ($exclude_field_id == $field_id) { 307 | unset($fields[$field_id]); 308 | 309 | break; 310 | } 311 | } 312 | } 313 | 314 | return $fields; 315 | } 316 | 317 | /** 318 | * @param array $settings 319 | * @return array|string 320 | */ 321 | public function display_settings($settings = []) 322 | { 323 | if (!$this->field_id) { 324 | return ['field_options_entry_type' => [ 325 | 'label' => 'field_options', 326 | 'group' => 'entry_type', 327 | 'settings' => [ 328 | [ 329 | 'title' => 'This field must first be assigned to a Field Group or Channel, then edit the field to change it\'s options.', 330 | 'fields' => [], 331 | ], 332 | ] 333 | ]]; 334 | } 335 | 336 | ee()->load->library('entry_type'); 337 | ee()->load->helper('array'); 338 | 339 | $action = ee()->uri->segment(3); 340 | 341 | if ($action === 'create') { 342 | $this->settings['group_id'] = ee()->uri->segment(4); 343 | 344 | $this->field_id = null; 345 | } else { 346 | $this->field_id = ee()->uri->segment(4); 347 | 348 | /** @var CI_DB_result $query */ 349 | $query = ee()->db->select('group_id') 350 | ->from('channel_field_groups_fields') 351 | ->where('field_id', $this->field_id) 352 | ->get(); 353 | 354 | $this->settings['group_id'] = $query->row('group_id'); 355 | } 356 | 357 | ee()->load->library('api'); 358 | ee()->legacy_api->instantiate('channel_fields'); 359 | 360 | $all_fieldtypes = ee()->api_channel_fields->fetch_all_fieldtypes(); 361 | 362 | $types = []; 363 | 364 | foreach ($all_fieldtypes as $row) { 365 | $type = strtolower(str_replace('_ft', '', $row['class'])); 366 | 367 | if (array_key_exists($type, $this->fieldtypes)) { 368 | $types[$type] = $row['name']; 369 | } 370 | } 371 | 372 | ee()->lang->loadfile('entry_type', 'entry_type'); 373 | ee()->load->helper(['array', 'html']); 374 | ee()->cp->add_js_script(['ui' => ['sortable']]); 375 | 376 | $vars['fields'] = []; 377 | 378 | if (!empty($this->settings['group_id'])) { 379 | $vars['fields'] = $this->fieldsByGroup($this->settings['group_id'], $this->field_id); 380 | } elseif (!empty($this->settings['field_id'])) { 381 | $vars['fields'] = $this->fieldsByChannel($this->settings['field_id'], $this->field_id); 382 | } 383 | 384 | if (empty($vars['fields'])) { 385 | return ['field_options_entry_type' => [ 386 | 'label' => 'field_options', 387 | 'group' => 'entry_type', 388 | 'settings' => [ 389 | [ 390 | 'title' => 'This field must first be assigned to a Field Group or Channel, then edit the field to change it\'s options.', 391 | 'fields' => [], 392 | ], 393 | ] 394 | ]]; 395 | } 396 | 397 | if (empty($settings['type_options'])) { 398 | $vars['type_options'] = [ 399 | '' => [ 400 | 'hide_fields' => [], 401 | 'label' => '', 402 | ], 403 | ]; 404 | } else { 405 | foreach ($settings['type_options'] as $value => $option) { 406 | if (!isset($option['hide_fields'])) { 407 | $settings['type_options'][$value]['hide_fields'] = []; 408 | } 409 | 410 | if (!isset($option['label'])) { 411 | $settings['type_options'][$value]['label'] = $value; 412 | } 413 | } 414 | 415 | $vars['type_options'] = $settings['type_options']; 416 | } 417 | 418 | $options = [ 419 | 'rowTemplate' => preg_replace('/[\r\n\t]/', '', ee()->load->view('option_row', ['key' => 0, 'i' => '{{INDEX}}', 'value' => '', 'label' => '', 'hide_fields' => [], 'fields' => $vars['fields']], true)), 420 | 'deleteConfirmMsg' => lang('confirm_delete_type'), 421 | ]; 422 | 423 | ee()->cp->load_package_js('EntryTypeFieldSettings'); 424 | ee()->cp->load_package_css('EntryTypeFieldSettings'); 425 | ee()->javascript->output('new EntryTypeFieldSettings(".entry_type_options", '.json_encode($options).');'); 426 | 427 | return ['field_options_entry_type' => [ 428 | 'label' => 'field_options', 429 | 'group' => 'entry_type', 430 | 'settings' => [ 431 | [ 432 | 'title' => lang('field_type'), 433 | 'fields' => [ 434 | 'entry_type_fieldtype' => [ 435 | 'type' => 'select', 436 | 'choices' => $types, 437 | 'value' => isset($settings['fieldtype']) ? $settings['fieldtype'] : null, 438 | ], 439 | ], 440 | ], 441 | [ 442 | 'title' => lang('types'), 443 | 'fields' => [ 444 | 'entry_type_type_options' => [ 445 | 'type' => 'html', 446 | 'content' => ee()->load->view('options', $vars, true), 447 | 'class' => 'options', 448 | ], 449 | ], 450 | ], 451 | ], 452 | ]]; 453 | } 454 | 455 | public function save_settings($data) 456 | { 457 | $settings['type_options'] = []; 458 | 459 | if (isset($data['entry_type_options'][0]) && is_array($data['entry_type_options'][0])) { 460 | foreach ($data['entry_type_options'][0] as $row) { 461 | if (!isset($row['value'])) { 462 | continue; 463 | } 464 | 465 | $value = $row['value']; 466 | 467 | unset($row['value']); 468 | 469 | if (empty($row['label'])) { 470 | $row['label'] = $value; 471 | } 472 | 473 | $settings['type_options'][$value] = $row; 474 | } 475 | } 476 | 477 | $settings['blank_hide_fields'] = (isset($data['entry_type_blank_hide_fields'])) ? $data['entry_type_blank_hide_fields'] : []; 478 | 479 | $settings['fieldtype'] = (isset($data['entry_type_fieldtype'])) ? $data['entry_type_fieldtype'] : 'select'; 480 | 481 | return $settings; 482 | } 483 | 484 | public function update($version = '') 485 | { 486 | return true; 487 | } 488 | } 489 | -------------------------------------------------------------------------------- /javascript/EntryType.js: -------------------------------------------------------------------------------- 1 | (function(w) { 2 | 3 | $("form.ajax-validate fieldset").each(function() { 4 | var $fieldset = $(this); 5 | var $input = $fieldset.find('[name^=field_id_]:first').each(function() { 6 | var match = this.name.match(/^field_id_(\d+)/); 7 | $fieldset.attr("id", 'hold_field_' + match[1]); 8 | }); 9 | }); 10 | 11 | var $holdFields = $("fieldset[id^=hold_field_]").filter(function() { 12 | var match = this.id.match(/^hold_field_(\d+)$/); 13 | 14 | if (match) { 15 | $(this).addClass('entry-type-field-' + match[1]); 16 | 17 | return true; 18 | } 19 | 20 | return false; 21 | }); 22 | 23 | var $tabs = $(".tab-wrap .tabs").find("li"); 24 | 25 | // add grid fields 26 | var $gridHoldFields = $('.fieldset-faux').filter(function() { 27 | var $gridField = $(this).find('.grid-field'); 28 | 29 | if ($gridField.length) { 30 | var match = $gridField.attr('id').match(/^field_id_(\d+)$/); 31 | 32 | if (match) { 33 | $(this).addClass('entry-type-field-' + match[1]); 34 | 35 | return true; 36 | } 37 | } 38 | 39 | return false; 40 | }); 41 | 42 | // Selector is very specific b/c the
on React fields has no class, and we don't want to select 43 | // a field inside of a Grid or Bloqs field on accident. We can't use .filter() b/c we need to find the child 44 | // field, then find it's parent fieldset, which we append classes to. 45 | var $reactHoldFields = []; 46 | $('.tab > fieldset > .field-instruct + .field-control > div[data-input-value]').each(function () { 47 | var $field = $(this); 48 | var $fieldset = $field.closest('fieldset'); 49 | var match = $field.attr('data-input-value').match(/^field_id_(\d+)/); 50 | 51 | if (match) { 52 | $fieldset 53 | .addClass('entry-type-field-' + match[1]); 54 | 55 | $reactHoldFields.push($fieldset); 56 | } 57 | }); 58 | 59 | $holdFields = $holdFields 60 | .add($gridHoldFields) 61 | .add($reactHoldFields) 62 | ; 63 | 64 | w.EntryType = { 65 | fields: [], 66 | change: function(event) { 67 | var value; 68 | 69 | $holdFields.not(this).each(function() { 70 | var $this = $(this); 71 | if (!$this.data("invisible")) { 72 | $this.removeClass("entry-type-hidden"); 73 | } 74 | }); 75 | 76 | for (var i = 0; i < EntryType.fields.length; i++) { 77 | if (EntryType.fields[i].callback !== null) { 78 | value = $.proxy(EntryType.fields[i].callback, EntryType.fields[i])(); 79 | 80 | if (value === null) { 81 | continue; 82 | } 83 | } else { 84 | value = (EntryType.fields[i].$input.is(":radio")) ? EntryType.fields[i].$input.filter(":checked").val() : EntryType.fields[i].$input.val(); 85 | } 86 | 87 | for (var fieldId in EntryType.fields[i].hideFields[value]) { 88 | $(".entry-type-field-" + EntryType.fields[i].hideFields[value][fieldId]).addClass("entry-type-hidden"); 89 | } 90 | } 91 | 92 | $tabs.each(function() { 93 | var tabNum = $(this).find("a").attr("rel"), 94 | $tab = $(this), 95 | $tabContents = $("div.tab." + tabNum), 96 | $visibleFields = $tabContents.find("fieldset, .fieldset-faux, .alert").filter(function() { 97 | return $(this).css("display") !== "none"; 98 | }); 99 | 100 | $tab.toggle($visibleFields.length > 0); 101 | }); 102 | }, 103 | addField: function(fieldName, hideFields, callback) { 104 | var field = { 105 | fieldName: fieldName, 106 | hideFields: hideFields || [], 107 | callback: callback || null, 108 | $input: $(":input[name=\'" + fieldName + "\']") 109 | }; 110 | 111 | if (!field.$input.data("entryType")) { 112 | field.$input.change(EntryType.change).data("entryType", true); 113 | } 114 | 115 | EntryType.fields.push(field); 116 | 117 | $.proxy(EntryType.change, field.$input)(); 118 | }, 119 | setInvisible: function(invisible) { 120 | for (var i in invisible) { 121 | $(".entry-type-field-" + invisible[i]).data("invisible", true); 122 | } 123 | } 124 | }; 125 | 126 | })(window); 127 | -------------------------------------------------------------------------------- /javascript/EntryTypeFieldSettings.js: -------------------------------------------------------------------------------- 1 | var EntryTypeFieldSettings; 2 | (function() { 3 | EntryTypeFieldSettings = function(container, options) { 4 | 5 | options = $.extend({ 6 | fieldName: "entry_type_options", 7 | sortable: true, 8 | rowTemplate: "", 9 | deleteConfirmMsg: "Are you sure you want to delete this Type?" 10 | }, options); 11 | 12 | var self = this; 13 | 14 | this.$container = $(container); 15 | this.$container.data("EntryTypeFieldSettings", this); 16 | this.$tbody = this.$container.find("tbody:first"); 17 | this.addRow = function() { 18 | self.$tbody.append(options.rowTemplate.replace(/\{\{INDEX\}\}/g, self.$tbody.find("tr").length)); 19 | }; 20 | this.removeRow = function(index) { 21 | self.$tbody.find("tr").eq(index).remove(); 22 | self.orderRows(); 23 | }; 24 | this.orderRows = function() { 25 | self.$tbody.find("tr").each(function(index){ 26 | $(this).find(":input").each(function(){ 27 | var match = $(this).attr("name").match(new RegExp("^"+options.fieldName+"\\[([a-z:\\d]+)\\]\\[\\d+\\]\\[(.*?)\\]$")); 28 | if (match) { 29 | $(this).attr("name", options.fieldName+"["+match[1]+"]["+index+"]["+match[2]+"]"); 30 | } 31 | }); 32 | }); 33 | }; 34 | 35 | this.$container.on("click", ".entry_type_add_row", self.addRow); 36 | this.$container.on("click", ".entry_type_remove_row", function(){ 37 | if (confirm(options.deleteConfirmMsg)) { 38 | self.removeRow($(this).parents("tbody").find(".entry_type_remove_row").index(this)); 39 | } 40 | }); 41 | if (options.sortable) { 42 | this.$tbody.sortable({ 43 | stop: function(e, ui) { 44 | self.orderRows(); 45 | } 46 | }).children("tr").css({cursor:"move"}); 47 | } 48 | 49 | }; 50 | })(); -------------------------------------------------------------------------------- /language/english/entry_type_lang.php: -------------------------------------------------------------------------------- 1 | 'Field Type', 5 | 'types' => 'Types', 6 | 'confirm_delete_type' => 'Are you sure you want to delete this Type?', 7 | 'hide_fields' => 'Hide Fields', 8 | 'add_type' => 'Add Type', 9 | 'type_value' => 'Short Name', 10 | 'type_label' => 'Label', 11 | ); 12 | 13 | /* End of file entry_type_lang.php */ 14 | /* Location: ./system/expressionengine/third_party/entry_type/entry_type_lang.php */ -------------------------------------------------------------------------------- /libraries/Entry_type.php: -------------------------------------------------------------------------------- 1 | session->cache('entry_type', 'display_field')) { 16 | return; 17 | } 18 | 19 | ee()->session->set_cache('entry_type', 'display_field', true); 20 | 21 | $channels = ee('Model')->get('Channel') 22 | ->with('CustomFields') 23 | ->filter('channel_id', $channelId) 24 | ->all(); 25 | 26 | /** @var Channel $channel */ 27 | foreach ($channels as $channel) { 28 | $customFields = $channel->getAllCustomFields(); 29 | 30 | foreach ($customFields as $customField) { 31 | $this->field_names[$customField->field_id] = REQ === 'CP' ? 'field_id_'.$customField->field_id : $customField->field_name; 32 | } 33 | } 34 | 35 | if (empty($this->field_names)) { 36 | return; 37 | } 38 | 39 | //fetch field widths/visibility from publish layout 40 | //$layout_group = is_numeric(ee()->input->get_post('layout_preview')) ? ee()->input->get_post('layout_preview') : ee()->session->userdata('group_id'); 41 | 42 | ee()->load->model('layout_model'); 43 | 44 | $layout_info = ee()->layout_model->get_layout_settings(array( 45 | 'site_id' => ee()->config->item('site_id'), 46 | 'channel_id' => $channelId, 47 | //'member_group' => $layout_group, 48 | )); 49 | 50 | $invisible = []; 51 | 52 | if (!empty($layout_info)) { 53 | foreach ($layout_info as $tab_fields) { 54 | foreach ($tab_fields as $field_name => $field_options) { 55 | if (strncmp($field_name, 'field_id_', 9) === 0) { 56 | $field_id = substr($field_name, 9); 57 | 58 | if (isset($field_options['visible']) && !$field_options['visible']) { 59 | $invisible[] = $field_id; 60 | } 61 | } 62 | } 63 | } 64 | } 65 | 66 | if (REQ === 'CP') { 67 | ee()->cp->load_package_js('EntryType'); 68 | } else { 69 | //for channel form 70 | ee()->cp->add_to_head(''); 71 | } 72 | 73 | ee()->cp->add_to_head(''); 74 | 75 | ee()->load->library('javascript'); 76 | 77 | ee()->javascript->output('EntryType.setInvisible('.json_encode($invisible).');'); 78 | } 79 | 80 | /** 81 | * @param string $field_name 82 | * @param array $type_options 83 | * @return mixed 84 | */ 85 | public function add_field($field_name, array $type_options = []) 86 | { 87 | $fields = []; 88 | 89 | foreach ($type_options as $value => $row) { 90 | foreach (explode('|', $value) as $val) { 91 | $fields[$val] = (isset($row['hide_fields'])) ? $row['hide_fields'] : []; 92 | } 93 | } 94 | 95 | if (is_numeric($field_name)) { 96 | $field_name = isset($this->field_names[$field_name]) ? $this->field_names[$field_name] : 'field_id_'.$field_name; 97 | } 98 | 99 | if (method_exists($this, 'add_'.$field_name.'_field')) { 100 | return $this->{'add_'.$field_name.'_field'}($fields); 101 | } 102 | 103 | // @todo - what is this used for? 104 | $callback = ''; 105 | 106 | if (method_exists($this, 'callback_'.$field_name)) { 107 | $callback = ', '.$this->{'callback_'.$field_name}(); 108 | } 109 | 110 | ee()->javascript->output('EntryType.addField('.json_encode($field_name).', '.json_encode($fields).');'); 111 | } 112 | 113 | /** 114 | * @param int $group_id 115 | * @param bool $exclude_field_id 116 | * @return array 117 | */ 118 | public function fields($group_id, $exclude_field_id = false) 119 | { 120 | $all_fields = $this->all_fields(); 121 | 122 | if (!isset($all_fields[$group_id])) { 123 | return []; 124 | } 125 | 126 | $fields = []; 127 | 128 | foreach ($all_fields[$group_id] as $field_id => $field) { 129 | $fields[$field_id] = $field['field_label']; 130 | } 131 | 132 | if ($exclude_field_id) { 133 | foreach ($fields as $field_id => $field_label) { 134 | if ($exclude_field_id == $field_id) { 135 | unset($fields[$field_id]); 136 | 137 | break; 138 | } 139 | } 140 | } 141 | 142 | return $fields; 143 | } 144 | 145 | public function all_fields() 146 | { 147 | static $cache; 148 | 149 | if (is_null($cache)) { 150 | /** @var CI_DB_result $query */ 151 | $query = ee()->db->select('field_id, field_name, field_label, field_groups.group_id, group_name') 152 | ->where('channel_fields.site_id', ee()->config->item('site_id')) 153 | ->join('field_groups', 'field_groups.group_id = channel_fields.group_id') 154 | ->order_by('field_groups.group_id, field_order') 155 | ->get('channel_fields'); 156 | 157 | $cache = []; 158 | 159 | foreach ($query->result_array() as $row) { 160 | if (!isset($cache[$row['group_id']])) { 161 | $cache[$row['group_id']] = []; 162 | } 163 | 164 | $cache[$row['group_id']][$row['field_id']] = $row; 165 | } 166 | 167 | $query->free_result(); 168 | } 169 | 170 | return $cache; 171 | } 172 | 173 | public function field_settings($field_group = false, $settings = [], $field_id = false, $key = false) 174 | { 175 | ee()->lang->loadfile('entry_type', 'entry_type'); 176 | ee()->load->helper(['array', 'html']); 177 | ee()->cp->add_js_script(['ui' => ['sortable']]); 178 | 179 | if ($field_group) { 180 | $vars['fields'] = $this->fields($field_group, $field_id); 181 | } else { 182 | $vars['fields'] = []; 183 | 184 | foreach ($this->all_fields() as $fields) { 185 | foreach ($fields as $field_id => $field) { 186 | $vars['fields'][$field_id] = $field['field_label']; 187 | } 188 | } 189 | } 190 | 191 | if (empty($settings['type_options'])) { 192 | $vars['type_options'] = [ 193 | '' => [ 194 | 'hide_fields' => [], 195 | 'label' => '', 196 | ], 197 | ]; 198 | } else { 199 | foreach ($settings['type_options'] as $value => $option) { 200 | if (!isset($option['hide_fields'])) { 201 | $settings['type_options'][$value]['hide_fields'] = []; 202 | } 203 | 204 | if (!isset($option['label'])) { 205 | $settings['type_options'][$value]['label'] = $value; 206 | } 207 | } 208 | 209 | $vars['type_options'] = $settings['type_options']; 210 | } 211 | 212 | $row_view = $key ? 'option_row_ext' : 'option_row'; 213 | 214 | $options_view = $key ? 'options_ext' : 'options'; 215 | 216 | $row_template = preg_replace('/[\r\n\t]/', '', ee()->load->view($row_view, array('key' => $key, 'i' => '{{INDEX}}', 'value' => '', 'label' => '', 'hide_fields' => [], 'fields' => $vars['fields']), true)); 217 | 218 | ee()->cp->load_package_js('EntryTypeFieldSettings'); 219 | ee()->load->library('javascript'); 220 | 221 | ee()->javascript->output(' 222 | (function() { 223 | var fieldSettings = new EntryTypeFieldSettings("#ft_entry_type", '.json_encode($row_template).'); 224 | fieldSettings.deleteConfirmMsg = '.json_encode(lang('confirm_delete_type')).'; 225 | })(); 226 | '); 227 | 228 | return ee()->load->view($options_view, $vars, true); 229 | } 230 | } 231 | -------------------------------------------------------------------------------- /src/CreateFieldEntryTypeCommand.php: -------------------------------------------------------------------------------- 1 | $this->option('fieldtype'), 44 | ); 45 | } 46 | } -------------------------------------------------------------------------------- /views/option_row.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | $field_name) : ?> 6 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /views/options.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | $data) : ?> 13 | load->view('option_row', array('i' => (string) $i, 'value' => $value, 'label' => $data['label'], 'hide_fields' => $data['hide_fields'], 'fields' => $fields), TRUE)?> 14 | 15 | 16 | 17 | 18 | 19 | 22 | 23 | 24 |
 
20 | 21 |
25 | --------------------------------------------------------------------------------