mirror of
https://github.com/processwire/processwire.git
synced 2025-08-08 15:57:01 +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:
@@ -45,7 +45,7 @@ class ProcessWire extends Wire {
|
||||
* Reversion revision number
|
||||
*
|
||||
*/
|
||||
const versionRevision = 43;
|
||||
const versionRevision = 44;
|
||||
|
||||
/**
|
||||
* Version suffix string (when applicable)
|
||||
|
@@ -133,10 +133,14 @@ class FieldtypePage extends FieldtypeMulti implements Module, ConfigurableModule
|
||||
|
||||
$template = null;
|
||||
$template_id = $field->get('template_id');
|
||||
$template_ids = $field->get('template_ids');
|
||||
$derefAsPage = $field->get('derefAsPage');
|
||||
$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
|
||||
if($derefAsPage > 0) {
|
||||
@@ -385,7 +389,8 @@ class FieldtypePage extends FieldtypeMulti implements Module, ConfigurableModule
|
||||
|
||||
$result = false;
|
||||
$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)) {
|
||||
// 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=" .
|
||||
$this->wire('sanitizer')->selectorValue($this->wire('sanitizer')->pageNameUTF8($value)));
|
||||
|
||||
} else if($template_id) {
|
||||
} else if(!empty($template_id)) {
|
||||
// set by title
|
||||
$templateIDs = is_array($template_id) ? implode('|', $template_id) : $template_id;
|
||||
$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);
|
||||
$findPagesSelector = $field->get('findPagesSelector');
|
||||
$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)) {
|
||||
// fine then, we can handle that here when needed (like !=)
|
||||
@@ -902,7 +908,8 @@ class FieldtypePage extends FieldtypeMulti implements Module, ConfigurableModule
|
||||
|
||||
$subfields = 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');
|
||||
|
||||
if($template_id) {
|
||||
@@ -1028,18 +1035,19 @@ class FieldtypePage extends FieldtypeMulti implements Module, ConfigurableModule
|
||||
// convert parent ID to parent path
|
||||
$data['parent_id'] = $this->wire('pages')->get((int) $data['parent_id'])->path;
|
||||
}
|
||||
if(!empty($data['template_id'])) {
|
||||
if(is_array($data['template_id'])) {
|
||||
foreach(array('template_id', 'template_ids') as $key) {
|
||||
if(empty($data[$key])) continue;
|
||||
if(is_array($data[$key])) {
|
||||
// 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;
|
||||
$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
|
||||
$template = $this->wire('templates')->get((int) $data['template_id']);
|
||||
if($template) $data['template_id'] = $template->name;
|
||||
$template = $this->wire('templates')->get((int) $data[$key]);
|
||||
if($template) $data[$key] = $template->name;
|
||||
}
|
||||
}
|
||||
return $data;
|
||||
@@ -1071,23 +1079,24 @@ class FieldtypePage extends FieldtypeMulti implements Module, ConfigurableModule
|
||||
$data['parent_id'] = $id;
|
||||
}
|
||||
// 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
|
||||
$errors = array();
|
||||
$isArray = is_array($data['template_id']);
|
||||
if(!$isArray) $data['template_id'] = array($data['template_id']);
|
||||
foreach($data['template_id'] as $key => $name) {
|
||||
if(ctype_digit("$name")) continue;
|
||||
$isArray = is_array($data[$property]);
|
||||
if(!$isArray) $data[$property] = array($data[$property]);
|
||||
foreach($data[$property] as $key => $name) {
|
||||
if(ctype_digit("$name")) continue;
|
||||
// we have a template name rather than id
|
||||
$template = $this->wire('templates')->get($this->wire('sanitizer')->name($name));
|
||||
if($template) {
|
||||
$data['template_id'][$key] = $template->id;
|
||||
$data[$property][$key] = $template->id;
|
||||
} else {
|
||||
$errors[] = $this->_('Unable to find template') . " - $name.";
|
||||
}
|
||||
}
|
||||
if(!$isArray) $data['template_id'] = reset($data['template_id']);
|
||||
if(count($errors)) $data['errors']['template_id'] = implode(" \n", $errors);
|
||||
if(!$isArray) $data[$property] = reset($data[$property]);
|
||||
if(count($errors)) $data['errors'][$property] = implode(" \n", $errors);
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
|
@@ -11,6 +11,7 @@
|
||||
* Can be accessed from $this or from $field:
|
||||
*
|
||||
* @property int $template_id
|
||||
* @property array $template_ids
|
||||
* @property int $parent_id
|
||||
* @property string $inputfield
|
||||
* @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(
|
||||
'parent_id' => 0,
|
||||
'template_id' => 0,
|
||||
'template_ids' => array(),
|
||||
'inputfield' => '',
|
||||
'labelFieldName' => '',
|
||||
'labelFieldFormat' => '',
|
||||
@@ -142,7 +144,7 @@ class InputfieldPage extends Inputfield implements ConfigurableModule {
|
||||
*
|
||||
* @param array|string $class
|
||||
* @param string $property
|
||||
* @return $this
|
||||
* @return InputfieldPage|Inputfield
|
||||
*
|
||||
*/
|
||||
public function addClass($class, $property = 'class') {
|
||||
@@ -159,7 +161,7 @@ class InputfieldPage extends Inputfield implements ConfigurableModule {
|
||||
*
|
||||
* @param array|string $key
|
||||
* @param array|int|string $value
|
||||
* @return $this
|
||||
* @return InputfieldPage|Inputfield
|
||||
*
|
||||
*/
|
||||
public function setAttribute($key, $value) {
|
||||
@@ -211,7 +213,7 @@ class InputfieldPage extends Inputfield implements ConfigurableModule {
|
||||
*
|
||||
*/
|
||||
public static function isValidPage(Page $page, $field, Page $editPage = null) {
|
||||
|
||||
|
||||
if(!$field instanceof Field) $field = $page->wire('fields')->get($field);
|
||||
if(!$field instanceof Field) throw new WireException('isValidPage requires a valid Field or field name');
|
||||
|
||||
@@ -228,6 +230,8 @@ class InputfieldPage extends Inputfield implements ConfigurableModule {
|
||||
$findPagesSelector = $field->get('findPagesSelector');
|
||||
$parent_id = $field->get('parent_id');
|
||||
$template_id = $field->get('template_id');
|
||||
$template_ids = $field->get('template_ids');
|
||||
if(!is_array($template_ids)) $template_ids = array();
|
||||
|
||||
if($findPagesSelector) {
|
||||
$selector = $findPagesSelector;
|
||||
@@ -268,10 +272,22 @@ class InputfieldPage extends Inputfield implements ConfigurableModule {
|
||||
$valid = $reflector->implementsInterface('InputfieldPageListSelection');
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
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;
|
||||
@@ -295,6 +311,15 @@ class InputfieldPage extends Inputfield implements ConfigurableModule {
|
||||
// ensures it accepts any config value (like those for delegate inputfields)
|
||||
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
|
||||
@@ -308,6 +333,7 @@ class InputfieldPage extends Inputfield implements ConfigurableModule {
|
||||
$lockedModes = array(Inputfield::collapsedNoLocked, Inputfield::collapsedYesLocked);
|
||||
$statusUnder = $this->allowUnpub ? Page::statusTrash : Page::statusUnpublished;
|
||||
$children = null;
|
||||
$templateIDs = $this->getTemplateIDs(true);
|
||||
|
||||
if($this->configMode) {
|
||||
$children = $this->wire('pages')->newPageArray();
|
||||
@@ -335,15 +361,15 @@ class InputfieldPage extends Inputfield implements ConfigurableModule {
|
||||
} else if($this->parent_id) {
|
||||
$parent = $this->wire('pages')->get($this->parent_id);
|
||||
if($parent) {
|
||||
if($this->template_id) {
|
||||
$children = $parent->children("templates_id={$this->template_id}, check_access=0, status<$statusUnder");
|
||||
if($templateIDs) {
|
||||
$children = $parent->children("templates_id=$templateIDs, check_access=0, status<$statusUnder");
|
||||
} else {
|
||||
$children = $parent->children("check_access=0, status<$statusUnder");
|
||||
}
|
||||
}
|
||||
|
||||
} else if($this->template_id) {
|
||||
$children = $this->pages->find("templates_id={$this->template_id}, check_access=0, status<$statusUnder");
|
||||
} else if($templateIDs) {
|
||||
$children = $this->pages->find("templates_id=$templateIDs, check_access=0, status<$statusUnder");
|
||||
|
||||
} else {
|
||||
$children = $this->wire('pages')->newPageArray();
|
||||
@@ -354,7 +380,26 @@ class InputfieldPage extends Inputfield implements ConfigurableModule {
|
||||
}
|
||||
|
||||
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
|
||||
@@ -369,6 +414,7 @@ class InputfieldPage extends Inputfield implements ConfigurableModule {
|
||||
|
||||
// if an $inputfield is passed in, then we want to retrieve dependent values directly
|
||||
// from the form, rather than from the $page
|
||||
/** @var InputfieldWrapper $form */
|
||||
if($inputfield) {
|
||||
// locate the $form
|
||||
$n = 0;
|
||||
@@ -480,6 +526,7 @@ class InputfieldPage extends Inputfield implements ConfigurableModule {
|
||||
|
||||
$parent_id = $this->getSetting('parent_id');
|
||||
$template_id = $this->getSetting('template_id');
|
||||
$template_ids = $this->getTemplateIDs();
|
||||
$findPagesCode = $this->getSetting('findPagesCode');
|
||||
$findPagesSelector = $this->getSetting('findPagesSelector');
|
||||
$labelFieldName = $this->getSetting('labelFieldName');
|
||||
@@ -494,6 +541,7 @@ class InputfieldPage extends Inputfield implements ConfigurableModule {
|
||||
}
|
||||
|
||||
if($template_id) $inputfield->template_id = $template_id;
|
||||
if(!empty($template_ids)) $inputfield->template_ids = $template_ids;
|
||||
|
||||
if($findPagesSelector) {
|
||||
$inputfield->findPagesSelector = self::getFindPagesSelector($page, $findPagesSelector);
|
||||
@@ -801,7 +849,7 @@ class InputfieldPage extends Inputfield implements ConfigurableModule {
|
||||
foreach($titles as $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);
|
||||
if($existingPage->id) {
|
||||
// use existing page
|
||||
@@ -865,6 +913,7 @@ class InputfieldPage extends Inputfield implements ConfigurableModule {
|
||||
|
||||
} else if($value instanceof PageArray) {
|
||||
// derefAsPageArray
|
||||
/** @var PageArray $value */
|
||||
if(!count($value)) return true;
|
||||
|
||||
} else {
|
||||
@@ -901,17 +950,37 @@ class InputfieldPage extends Inputfield implements ConfigurableModule {
|
||||
$field->attr('value', (int) $this->parent_id);
|
||||
$field->description = $this->_('Select the parent of the pages that are selectable.');
|
||||
$field->required = false;
|
||||
$fieldset->append($field);
|
||||
$fieldset->append($field);
|
||||
|
||||
/** @var InputfieldSelect $field */
|
||||
$field = $this->modules->get('InputfieldSelect');
|
||||
$field->setAttribute('name', 'template_id');
|
||||
$field->setAttribute('name', 'template_id');
|
||||
$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
|
||||
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;
|
||||
$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 */
|
||||
$field = $this->modules->get('InputfieldText');
|
||||
|
@@ -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 $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 $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)
|
||||
@@ -48,7 +49,8 @@ class InputfieldPageAutocomplete extends Inputfield implements InputfieldHasArra
|
||||
$this->set('parent_id', 0);
|
||||
|
||||
// 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
|
||||
$this->set('labelFieldName', 'title');
|
||||
@@ -259,7 +261,11 @@ _OUT;
|
||||
else $value = array();
|
||||
|
||||
foreach($value as $k => $v) {
|
||||
$value[$k] = (int) $v;
|
||||
if(empty($v)) {
|
||||
unset($value[$k]);
|
||||
} else {
|
||||
$value[$k] = (int) $v;
|
||||
}
|
||||
}
|
||||
|
||||
$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}";
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user