1
0
mirror of https://github.com/processwire/processwire.git synced 2025-08-09 16:26:59 +02:00

Updates to support multiple template selections for Page fields per @apeisa and @niklam PR #22, plus bump version to 3.0.44

This commit is contained in:
Ryan Cramer
2016-12-09 14:16:04 -05:00
parent 880810c6bb
commit f0212dcc9c
4 changed files with 128 additions and 42 deletions

View File

@@ -45,7 +45,7 @@ class ProcessWire extends Wire {
* Reversion revision number * Reversion revision number
* *
*/ */
const versionRevision = 43; const versionRevision = 44;
/** /**
* Version suffix string (when applicable) * Version suffix string (when applicable)

View File

@@ -133,10 +133,14 @@ class FieldtypePage extends FieldtypeMulti implements Module, ConfigurableModule
$template = null; $template = null;
$template_id = $field->get('template_id'); $template_id = $field->get('template_id');
$template_ids = $field->get('template_ids');
$derefAsPage = $field->get('derefAsPage'); $derefAsPage = $field->get('derefAsPage');
$allowUnpub = $field->get('allowUnpub'); $allowUnpub = $field->get('allowUnpub');
if($template_id) $template = $this->wire('templates')->get($template_id); if(empty($template_ids) || count($template_ids) <= 1) {
// we only use $template optimization if only one template selected
if($template_id) $template = $this->wire('templates')->get($template_id);
}
// handle $value if it's blank, Page, or PageArray // handle $value if it's blank, Page, or PageArray
if($derefAsPage > 0) { if($derefAsPage > 0) {
@@ -385,7 +389,8 @@ class FieldtypePage extends FieldtypeMulti implements Module, ConfigurableModule
$result = false; $result = false;
$parent_id = $field->get('parent_id'); $parent_id = $field->get('parent_id');
$template_id = $field->get('template_id'); $template_id = $field->get('template_ids');
if(empty($template_id)) $template_id = $field->get('template_id');
if(Selectors::stringHasOperator($value)) { if(Selectors::stringHasOperator($value)) {
// selector string // selector string
@@ -434,7 +439,7 @@ class FieldtypePage extends FieldtypeMulti implements Module, ConfigurableModule
if(!$result->id) $result = $this->wire('pages')->get("parent_id=$parentIDs, name=" . if(!$result->id) $result = $this->wire('pages')->get("parent_id=$parentIDs, name=" .
$this->wire('sanitizer')->selectorValue($this->wire('sanitizer')->pageNameUTF8($value))); $this->wire('sanitizer')->selectorValue($this->wire('sanitizer')->pageNameUTF8($value)));
} else if($template_id) { } else if(!empty($template_id)) {
// set by title // set by title
$templateIDs = is_array($template_id) ? implode('|', $template_id) : $template_id; $templateIDs = is_array($template_id) ? implode('|', $template_id) : $template_id;
$result = $this->wire('pages')->get("templates_id=$templateIDs, title=" . $this->wire('sanitizer')->selectorValue($value)); $result = $this->wire('pages')->get("templates_id=$templateIDs, title=" . $this->wire('sanitizer')->selectorValue($value));
@@ -787,7 +792,8 @@ class FieldtypePage extends FieldtypeMulti implements Module, ConfigurableModule
$value = $this->wire('sanitizer')->selectorValue($value); $value = $this->wire('sanitizer')->selectorValue($value);
$findPagesSelector = $field->get('findPagesSelector'); $findPagesSelector = $field->get('findPagesSelector');
$parent_id = $field->get('parent_id'); $parent_id = $field->get('parent_id');
$template_id = $field->get('template_id'); $template_id = $field->get('template_ids');
if(empty($template_id)) $template_id = $field->get('template_id');
if(in_array($subfield, $this->nativeNames)) { if(in_array($subfield, $this->nativeNames)) {
// fine then, we can handle that here when needed (like !=) // fine then, we can handle that here when needed (like !=)
@@ -902,7 +908,8 @@ class FieldtypePage extends FieldtypeMulti implements Module, ConfigurableModule
$subfields = array(); $subfields = array();
$fieldgroups = array(); $fieldgroups = array();
$template_id = $field->get('template_id'); $template_id = $field->get('template_ids');
if(empty($template_id)) $template_id = $field->get('template_id');
$parent_id = $field->get('parent_id'); $parent_id = $field->get('parent_id');
if($template_id) { if($template_id) {
@@ -1028,18 +1035,19 @@ class FieldtypePage extends FieldtypeMulti implements Module, ConfigurableModule
// convert parent ID to parent path // convert parent ID to parent path
$data['parent_id'] = $this->wire('pages')->get((int) $data['parent_id'])->path; $data['parent_id'] = $this->wire('pages')->get((int) $data['parent_id'])->path;
} }
if(!empty($data['template_id'])) { foreach(array('template_id', 'template_ids') as $key) {
if(is_array($data['template_id'])) { if(empty($data[$key])) continue;
if(is_array($data[$key])) {
// convert array of template ids to template names // convert array of template ids to template names
foreach($data['template_id'] as $key => $id) { foreach($data[$key] as $k => $id) {
if(ctype_digit("$id")) continue; if(ctype_digit("$id")) continue;
$template = $this->wire('templates')->get((int) $id); $template = $this->wire('templates')->get((int) $id);
if($template) $data['template_id'][$key] = $template->name; if($template) $data[$key][$k] = $template->name;
} }
} else if(ctype_digit("$data[template_id]")) { } else if(ctype_digit((string) $data[$key])) {
// convert template id to template name // convert template id to template name
$template = $this->wire('templates')->get((int) $data['template_id']); $template = $this->wire('templates')->get((int) $data[$key]);
if($template) $data['template_id'] = $template->name; if($template) $data[$key] = $template->name;
} }
} }
return $data; return $data;
@@ -1071,23 +1079,24 @@ class FieldtypePage extends FieldtypeMulti implements Module, ConfigurableModule
$data['parent_id'] = $id; $data['parent_id'] = $id;
} }
// template // template
if(!empty($data['template_id'])) { foreach(array('template_id', 'template_ids') as $property) {
if(empty($data[$property])) continue;
// template_id can be an id or array of IDs, but we will be importing a template name or array of them // template_id can be an id or array of IDs, but we will be importing a template name or array of them
$errors = array(); $errors = array();
$isArray = is_array($data['template_id']); $isArray = is_array($data[$property]);
if(!$isArray) $data['template_id'] = array($data['template_id']); if(!$isArray) $data[$property] = array($data[$property]);
foreach($data['template_id'] as $key => $name) { foreach($data[$property] as $key => $name) {
if(ctype_digit("$name")) continue; if(ctype_digit("$name")) continue;
// we have a template name rather than id // we have a template name rather than id
$template = $this->wire('templates')->get($this->wire('sanitizer')->name($name)); $template = $this->wire('templates')->get($this->wire('sanitizer')->name($name));
if($template) { if($template) {
$data['template_id'][$key] = $template->id; $data[$property][$key] = $template->id;
} else { } else {
$errors[] = $this->_('Unable to find template') . " - $name."; $errors[] = $this->_('Unable to find template') . " - $name.";
} }
} }
if(!$isArray) $data['template_id'] = reset($data['template_id']); if(!$isArray) $data[$property] = reset($data[$property]);
if(count($errors)) $data['errors']['template_id'] = implode(" \n", $errors); if(count($errors)) $data['errors'][$property] = implode(" \n", $errors);
} }
return $data; return $data;
} }

View File

@@ -11,6 +11,7 @@
* Can be accessed from $this or from $field: * Can be accessed from $this or from $field:
* *
* @property int $template_id * @property int $template_id
* @property array $template_ids
* @property int $parent_id * @property int $parent_id
* @property string $inputfield * @property string $inputfield
* @property string $labelFieldName Field name to use for label (note: this will be "." if $labelFieldFormat is in use). * @property string $labelFieldName Field name to use for label (note: this will be "." if $labelFieldFormat is in use).
@@ -70,6 +71,7 @@ class InputfieldPage extends Inputfield implements ConfigurableModule {
protected static $defaultConfig = array( protected static $defaultConfig = array(
'parent_id' => 0, 'parent_id' => 0,
'template_id' => 0, 'template_id' => 0,
'template_ids' => array(),
'inputfield' => '', 'inputfield' => '',
'labelFieldName' => '', 'labelFieldName' => '',
'labelFieldFormat' => '', 'labelFieldFormat' => '',
@@ -142,7 +144,7 @@ class InputfieldPage extends Inputfield implements ConfigurableModule {
* *
* @param array|string $class * @param array|string $class
* @param string $property * @param string $property
* @return $this * @return InputfieldPage|Inputfield
* *
*/ */
public function addClass($class, $property = 'class') { public function addClass($class, $property = 'class') {
@@ -159,7 +161,7 @@ class InputfieldPage extends Inputfield implements ConfigurableModule {
* *
* @param array|string $key * @param array|string $key
* @param array|int|string $value * @param array|int|string $value
* @return $this * @return InputfieldPage|Inputfield
* *
*/ */
public function setAttribute($key, $value) { public function setAttribute($key, $value) {
@@ -228,6 +230,8 @@ class InputfieldPage extends Inputfield implements ConfigurableModule {
$findPagesSelector = $field->get('findPagesSelector'); $findPagesSelector = $field->get('findPagesSelector');
$parent_id = $field->get('parent_id'); $parent_id = $field->get('parent_id');
$template_id = $field->get('template_id'); $template_id = $field->get('template_id');
$template_ids = $field->get('template_ids');
if(!is_array($template_ids)) $template_ids = array();
if($findPagesSelector) { if($findPagesSelector) {
$selector = $findPagesSelector; $selector = $findPagesSelector;
@@ -269,9 +273,21 @@ class InputfieldPage extends Inputfield implements ConfigurableModule {
} }
} }
if($template_id && $page->template->id != $template_id) { $hasRequiredTemplate = true;
if(!empty($template_ids)) {
if($template_id && !in_array($template_id, $template_ids)) {
array_unshift($template_ids, $template_id);
}
$hasRequiredTemplate = in_array($page->template->id, $template_ids);
} else if($template_id) {
$hasRequiredTemplate = $page->template->id == $template_id;
}
if(!$hasRequiredTemplate) {
$valid = false; $valid = false;
if($editPage) $editPage->set('_isValidPage', "Page $page does not have required template $template_id"); $requiredTemplate = empty($template_ids) ? $template_id : implode(',', $template_ids);
if($editPage) {
$editPage->set('_isValidPage', "Page $page does not have required template(s): $requiredTemplate");
}
} }
return $valid; return $valid;
@@ -296,6 +312,15 @@ class InputfieldPage extends Inputfield implements ConfigurableModule {
return true; return true;
} }
public function getSetting($key) {
$value = parent::getSetting($key);
if(empty($value) && $key == 'template_id') {
$templateIDs = parent::getSetting('template_ids');
if(!empty($templateIDs)) $value = reset($templateIDs);
}
return $value;
}
/** /**
* Return PageArray of selectable pages for this input * Return PageArray of selectable pages for this input
* *
@@ -308,6 +333,7 @@ class InputfieldPage extends Inputfield implements ConfigurableModule {
$lockedModes = array(Inputfield::collapsedNoLocked, Inputfield::collapsedYesLocked); $lockedModes = array(Inputfield::collapsedNoLocked, Inputfield::collapsedYesLocked);
$statusUnder = $this->allowUnpub ? Page::statusTrash : Page::statusUnpublished; $statusUnder = $this->allowUnpub ? Page::statusTrash : Page::statusUnpublished;
$children = null; $children = null;
$templateIDs = $this->getTemplateIDs(true);
if($this->configMode) { if($this->configMode) {
$children = $this->wire('pages')->newPageArray(); $children = $this->wire('pages')->newPageArray();
@@ -335,15 +361,15 @@ class InputfieldPage extends Inputfield implements ConfigurableModule {
} else if($this->parent_id) { } else if($this->parent_id) {
$parent = $this->wire('pages')->get($this->parent_id); $parent = $this->wire('pages')->get($this->parent_id);
if($parent) { if($parent) {
if($this->template_id) { if($templateIDs) {
$children = $parent->children("templates_id={$this->template_id}, check_access=0, status<$statusUnder"); $children = $parent->children("templates_id=$templateIDs, check_access=0, status<$statusUnder");
} else { } else {
$children = $parent->children("check_access=0, status<$statusUnder"); $children = $parent->children("check_access=0, status<$statusUnder");
} }
} }
} else if($this->template_id) { } else if($templateIDs) {
$children = $this->pages->find("templates_id={$this->template_id}, check_access=0, status<$statusUnder"); $children = $this->pages->find("templates_id=$templateIDs, check_access=0, status<$statusUnder");
} else { } else {
$children = $this->wire('pages')->newPageArray(); $children = $this->wire('pages')->newPageArray();
@@ -356,6 +382,25 @@ class InputfieldPage extends Inputfield implements ConfigurableModule {
return $children; return $children;
} }
/**
* Return array or string of configured template IDs
*
* @param bool $getString Specify true to return a 1|2|3 style string rather than an array
* @return array|string
*
*/
public function getTemplateIDs($getString = false) {
$templateIDs = $this->getSetting('template_ids');
$templateID = $this->getSetting('template_id');
if(empty($templateIDs)) {
if(empty($templateID)) return $getString ? '' : array();
$templateIDs = array($templateID);
} else {
if(!in_array($templateID, $templateIDs)) array_unshift($templateIDs, $templateID);
}
return $getString ? implode('|', $templateIDs) : $templateIDs;
}
/** /**
* Populate any variables in findPagesSelector * Populate any variables in findPagesSelector
* *
@@ -369,6 +414,7 @@ class InputfieldPage extends Inputfield implements ConfigurableModule {
// if an $inputfield is passed in, then we want to retrieve dependent values directly // if an $inputfield is passed in, then we want to retrieve dependent values directly
// from the form, rather than from the $page // from the form, rather than from the $page
/** @var InputfieldWrapper $form */
if($inputfield) { if($inputfield) {
// locate the $form // locate the $form
$n = 0; $n = 0;
@@ -480,6 +526,7 @@ class InputfieldPage extends Inputfield implements ConfigurableModule {
$parent_id = $this->getSetting('parent_id'); $parent_id = $this->getSetting('parent_id');
$template_id = $this->getSetting('template_id'); $template_id = $this->getSetting('template_id');
$template_ids = $this->getTemplateIDs();
$findPagesCode = $this->getSetting('findPagesCode'); $findPagesCode = $this->getSetting('findPagesCode');
$findPagesSelector = $this->getSetting('findPagesSelector'); $findPagesSelector = $this->getSetting('findPagesSelector');
$labelFieldName = $this->getSetting('labelFieldName'); $labelFieldName = $this->getSetting('labelFieldName');
@@ -494,6 +541,7 @@ class InputfieldPage extends Inputfield implements ConfigurableModule {
} }
if($template_id) $inputfield->template_id = $template_id; if($template_id) $inputfield->template_id = $template_id;
if(!empty($template_ids)) $inputfield->template_ids = $template_ids;
if($findPagesSelector) { if($findPagesSelector) {
$inputfield->findPagesSelector = self::getFindPagesSelector($page, $findPagesSelector); $inputfield->findPagesSelector = self::getFindPagesSelector($page, $findPagesSelector);
@@ -801,7 +849,7 @@ class InputfieldPage extends Inputfield implements ConfigurableModule {
foreach($titles as $title) { foreach($titles as $title) {
// check if there is an existing page using this title // check if there is an existing page using this title
$selector = "include=all, templates_id={$this->template_id}, title=" . $this->wire('sanitizer')->selectorValue($title); $selector = "include=all, templates_id=$template_id, title=" . $this->wire('sanitizer')->selectorValue($title);
$existingPage = $parent->child($selector); $existingPage = $parent->child($selector);
if($existingPage->id) { if($existingPage->id) {
// use existing page // use existing page
@@ -865,6 +913,7 @@ class InputfieldPage extends Inputfield implements ConfigurableModule {
} else if($value instanceof PageArray) { } else if($value instanceof PageArray) {
// derefAsPageArray // derefAsPageArray
/** @var PageArray $value */
if(!count($value)) return true; if(!count($value)) return true;
} else { } else {
@@ -907,12 +956,32 @@ class InputfieldPage extends Inputfield implements ConfigurableModule {
$field = $this->modules->get('InputfieldSelect'); $field = $this->modules->get('InputfieldSelect');
$field->setAttribute('name', 'template_id'); $field->setAttribute('name', 'template_id');
$field->label = $this->_('Template of selectable page(s)'); $field->label = $this->_('Template of selectable page(s)');
$field->attr('value', (int) $this->template_id);
$field->description = $this->_('Select the template of the pages that are selectable. May be used instead of, or in addition to, the parent above. NOTE: Not compatible with PageListSelect input field types.'); // Description for Template of selectable pages $field->description = $this->_('Select the template of the pages that are selectable. May be used instead of, or in addition to, the parent above. NOTE: Not compatible with PageListSelect input field types.'); // Description for Template of selectable pages
foreach($this->templates as $template) $field->addOption($template->id, $template->name); foreach($this->templates as $template) {
$field->addOption($template->id, $template->name);
}
$field->attr('value', $this->getSetting('template_id'));
$field->collapsed = Inputfield::collapsedBlank; $field->collapsed = Inputfield::collapsedBlank;
$fieldset->append($field); $fieldset->append($field);
$templateIDs = $this->getTemplateIDs();
/** @var InputfieldAsmSelect $field */
$field = $this->modules->get('InputfieldAsmSelect');
$field->attr('name', 'template_ids');
$field->label = $this->_('Need more templates? Select them here');
$field->description = $this->_('Optionally select multiple templates to use for page selections.');
$field->description .= ' ' . $this->_('This may not be supported by all input types.');
foreach($this->templates as $template) {
$field->addOption($template->id, $template->name);
}
$field->attr('value', $templateIDs);
$field->collapsed = Inputfield::collapsedBlank;
$field->showIf = 'template_id!=0';
if(count($templateIDs) == 1 && reset($templateIDs) == $this->getSetting('template_id')) {
$field->collapsed = Inputfield::collapsedYes;
}
$fieldset->append($field);
/** @var InputfieldText $field */ /** @var InputfieldText $field */
$field = $this->modules->get('InputfieldText'); $field = $this->modules->get('InputfieldText');
$field->attr('name', 'findPagesSelector'); $field->attr('name', 'findPagesSelector');

View File

@@ -10,6 +10,7 @@
* *
* @property int $parent_id Limit results to this parent, or if combined with findPagesSelector, the search is performed as $pages->get($parent_id)->find() rather than $pages->find(). * @property int $parent_id Limit results to this parent, or if combined with findPagesSelector, the search is performed as $pages->get($parent_id)->find() rather than $pages->find().
* @property int $template_id Limit results to pages using this template. * @property int $template_id Limit results to pages using this template.
* @property array $template_ids Limit results to pages using this templates (alternate to the single template_id).
* @property string $labelFieldName Field to display in the results. (default=title) * @property string $labelFieldName Field to display in the results. (default=title)
* @property string $labelFieldFormat Format string to display in the results, overrides labelFieldName when used (default=blank). * @property string $labelFieldFormat Format string to display in the results, overrides labelFieldName when used (default=blank).
* @property string $searchFields Field(s) to search for text. Separate multiple by a space. (default=title) * @property string $searchFields Field(s) to search for text. Separate multiple by a space. (default=title)
@@ -49,6 +50,7 @@ class InputfieldPageAutocomplete extends Inputfield implements InputfieldHasArra
// limit results to pages using this template // limit results to pages using this template
$this->set('template_id', 0); $this->set('template_id', 0);
$this->set('template_ids', array());
// field to display in the results // field to display in the results
$this->set('labelFieldName', 'title'); $this->set('labelFieldName', 'title');
@@ -259,7 +261,11 @@ _OUT;
else $value = array(); else $value = array();
foreach($value as $k => $v) { foreach($value as $k => $v) {
$value[$k] = (int) $v; if(empty($v)) {
unset($value[$k]);
} else {
$value[$k] = (int) $v;
}
} }
$this->attr('value', $value); $this->attr('value', $value);
@@ -287,7 +293,9 @@ _OUT;
} }
} }
if($this->template_id) { if(count($this->template_ids)) {
$selector .= ",templates_id=" . implode('|', $this->template_ids);
} else if($this->template_id) {
$selector .= ",templates_id={$this->template_id}"; $selector .= ",templates_id={$this->template_id}";
} }