├── 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