";
return $out;
}
protected function ___renderAddable() {
if(!$this->addable || !$this->parent_id || !$this->template_id) return '';
if($this->labelFieldName && $this->labelFieldName != 'title') return '';
$parent = wire('pages')->get($this->parent_id);
$test = new Page();
$test->template = wire('templates')->get($this->template_id);
$test->parent = $parent;
$test->id = -1; // prevents permissions check from failing
if(!$parent->addable($test)) return '';
if(!$test->publishable()) return '';
$inputfield = wire('modules')->get($this->inputfield);
if(!$inputfield) return '';
$key = "_{$this->name}_add_items";
if($inputfield instanceof InputfieldHasArrayValue) {
// multi value
$description = $this->_('Enter the titles of the items you want to add, one per line. They will be created and added to your selection when you save the page.');
$input = "";
} else {
// single value
$description = $this->_('Enter the title of the item you want to add. It will become selected when you save the page.');
$input = "";
}
$notes = sprintf($this->_('New pages will be added to %s'), $parent->path);
$label =" " . $this->_('Create New');
$out = "\n
";
} else if($value instanceof Page) {
$out = $value->get($labelFieldName);
} else {
$out = $value;
}
return $out;
}
public function ___processInput(WireInputData $input) {
$this->processInputMode = true;
$inputfield = $this->getInputfield();
if(!$inputfield) return $this;
$inputfield->processInput($input);
$value = $this->attr('value');
$existingValue = $value ? clone $value : '';
$newValue = null;
$value = $inputfield->value;
if(is_array($value)) {
$newValue = new PageArray();
foreach($value as $v) {
$id = (int) $v;
if(!$id) continue;
if($id > 0) {
// existing page
$page = wire('pages')->get($id);
if($page->is(Page::statusUnpublished) && !$this->allowUnpub) continue; // disallow unpublished
} else {
// placeholder for new page, to be sorted later
$page = new NullPage();
}
$newValue->add($page);
}
} else if($value) {
$newValue = wire('pages')->get((int) $value);
if($newValue->is(Page::statusUnpublished) && !$this->allowUnpub) $newValue = null; // disallow unpublished
}
$this->setAttribute('value', $newValue);
$this->processInputAddPages($input);
// if pages were added, re-sort them in case they were dragged to a different order
// an example of this would be when used with the InputfieldPageAutocomplete
if(count($this->pagesAdded) && is_array($value)) {
$sortedValue = new PageArray();
foreach($newValue as $page) {
if($page->id < 1) $page = $this->pagesAdded->shift();
if($page->id && !$sortedValue->has($page)) $sortedValue->add($page);
}
$newValue = $sortedValue;
$this->setAttribute('value', $newValue);
}
if("$newValue" != "$existingValue") {
$this->trackChange('value');
}
$this->processInputMode = false;
return $this;
}
/**
* Check for the addable pages option and process if applicable
*
*/
protected function ___processInputAddPages($input) {
$this->pagesAdded = new PageArray();
if(!$this->addable || !$this->parent_id || !$this->template_id) return;
$user = wire('user');
$key = "_{$this->name}_add_items";
$value = trim($input->$key);
if(empty($value)) return;
$parent = $this->pages->get($this->parent_id);
$sort = $parent->numChildren;
$titles = explode("\n", $value);
$publishable = false;
$n = 0;
foreach($titles as $title) {
// check if there is an existing page using this title
$existingPage = $parent->child("include=all, templates_id={$this->template_id}, title=" . $this->sanitizer->selectorValue($title));
if($existingPage->id) {
// use existing page
$this->pagesAdded->add($existingPage);
if($this->value instanceof PageArray) {
$this->value->add($existingPage);
continue;
} else {
$this->value = $existingPage;
break;
}
}
// create a new page
$page = new Page();
$page->template = $this->template_id;
$page->parent = $parent;
$page->title = trim($title);
$page->sort = $sort++;
$page->id = -1; // prevents the permissions check from failing
// on first iteration perform a page-context access check
if(!$n && (!$parent->addable($page) || !$page->publishable())) {
$this->error("No access to add {$page->template} pages to {$parent->path}");
break;
}
$page->id = 0;
try {
$page->save();
$this->message(sprintf($this->_('Added page %s'), $page->path));
if($this->value instanceof PageArray) $this->value->add($page);
else $this->value = $page;
$this->pagesAdded->add($page);
$this->trackChange('value');
$n++;
} catch(Exception $e) {
$error = sprintf($this->_('Error adding page "%s"'), $page->title);
if($user->isSuperuser()) $error .= " - " . $e->getMessage();
$this->error($error);
break;
}
if($this->value instanceof Page) break;
}
}
public function isEmpty() {
$value = $this->attr('value');
if($value instanceof Page) {
// derefAsPage
return $value->id < 1;
} else if($value instanceof PageArray) {
// derefAsPageArray
if(!count($value)) return true;
} else {
// null
return true;
}
return false;
}
public function ___getConfigInputfields() {
// let the module know it's being used for configuration purposes
$this->configMode = true;
$exampleLabel = $this->_('Example:') . ' ';
$defaultLabel = ' ' . $this->_('(default)');
$inputfields = parent::___getConfigInputfields();
$fieldset = wire('modules')->get('InputfieldFieldset');
$fieldset->label = $this->_('Selectable Pages');
$field = $this->modules->get('InputfieldPageListSelect');
$field->setAttribute('name', 'parent_id');
$field->label = $this->_('Parent of selectable page(s)');
$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);
$field = $this->modules->get('InputfieldSelect');
$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);
$field->collapsed = Inputfield::collapsedBlank;
$fieldset->append($field);
$field = $this->modules->get('InputfieldText');
$field->attr('name', 'findPagesSelector');
$field->label = $this->_('Custom selector to find selectable pages');
$field->attr('value', $this->findPagesSelector);
$field->description = $this->_('If you want to find selectable pages using a ProcessWire selector rather than selecting a parent page or template (above) then enter the selector to find the selectable pages. This selector will be passed to a $pages->find("your selector"); statement. NOTE: Not currently compatible with PageListSelect input field types.'); // Description for Custom selector to find selectable pages
$field->notes = $exampleLabel . $this->_('parent=/products/, template=product, sort=name'); // Example of Custom selector to find selectable pages
$field->collapsed = Inputfield::collapsedBlank;
$fieldset->append($field);
$field = $this->modules->get('InputfieldTextarea');
$field->attr('name', 'findPagesCode');
$field->label = $this->_('Custom PHP code to find selectable pages');
$field->attr('value', $this->findPagesCode);
$field->attr('rows', 4);
$field->description = $this->_('If you want to find selectable pages using a PHP code snippet rather than selecting a parent page or template (above) then enter the code to find the selectable pages. This statement has access to the $page and $pages API variables, where $page refers to the page being edited. The snippet should return either a PageArray or NULL. Using this is optional, and if used, it overrides the parent/template/selector fields above. NOTE: Not compatible with PageListSelect or Autocomplete input field types.'); // Description for Custom PHP to find selectable pages
$field->notes = $exampleLabel . $this->_('return $page->parent->parent->children("name=locations")->first()->children();'); // Example of Custom PHP code to find selectable pages
$field->collapsed = Inputfield::collapsedBlank;
$fieldset->append($field);
$inputfields->append($fieldset);
$field = $this->modules->get('InputfieldSelect');
$field->setAttribute('name', 'labelFieldName');
$field->setAttribute('value', $this->labelFieldName);
$field->label = $this->_('Label Field');
$field->required = true;
$field->description = $this->_('Select the page field that you want to be used in generating the labels for each selectable page.'); // Description for Label Field
if($this->fuel('fields')->get('title')) {
$field->addOption('title', 'title' . $defaultLabel);
$field->addOption('name', 'name');
$titleIsDefault = true;
} else {
$field->addOption('name', 'name' . $defaultLabel);
$titleIsDefault = false;
}
$field->addOption('path', 'path');
foreach($this->fuel('fields') as $f) {
if(!$f->type instanceof FieldtypeText) continue;
if($f->type instanceof FieldtypeTextarea) continue;
if($titleIsDefault && $f->name == 'title') continue;
$field->addOption($f->name);
}
$inputfields->append($field);
if(!$this->inputfield) $this->inputfield = 'InputfieldSelect';
$field = $this->modules->get('InputfieldSelect');
$field->setAttribute('name', 'inputfield');
$field->setAttribute('value', $this->inputfield);
$field->label = $this->_('Input field type');
$field->description = $this->_('The type of field that will be used to select a page. Select one that is consistent with the single page vs. multi-page needs you chose in the "details" tab of this field.'); // Description for Inputfield field type
$field->required = true;
$field->notes = '* ' . $this->_('Types indicated with an asterisk are for multiple page selection.') . "\n" .
'+ ' . $this->_('Types indicated with a plus assume a "parent" to be the root of a tree, rather than an immediate parent.');
foreach($this->inputfieldClasses as $class) {
$module = $this->modules->get($class);
$label = str_replace("Inputfield", '', $class);
if($module instanceof InputfieldHasArrayValue) $label .= "*";
if(is_subclass_of($module, 'InputfieldPageListSelection')) $label .= "+";
$field->addOption($class, $label);
}
$inputfields->append($field);
$inputfield = $this->getInputfield();
if($inputfield) {
// then call again, knowing the module has it's config populated
$inputfield->hasFieldtype = true; // tell it it's under control of a parent, regardless of whether this one is hasFieldtype true or not.
foreach($inputfield->___getConfigInputfields() as $f) {
if(in_array($f->name, array('required', 'collapsed', 'columnWidth')) || array_key_exists($f->name, self::$defaultConfig)) continue;
if($f->name && $inputfields->getChildByName($f->name)) continue; // if we already have the given field, skip over it to avoid duplication
$inputfields->add($f);
}
}
if($this->hasFieldtype !== false) {
$field = $this->modules->get('InputfieldCheckbox');
$field->attr('name', 'addable');
$field->attr('value', 1);
$field->label = $this->_('Allow new pages to be created from field?');
$field->description = $this->_('If checked, an option to add new page(s) will also be present if the indicated requirements are met.');
$field->notes =
$this->_('1. Both a parent and template must be selected above.') . "\n" .
$this->_('2. The editing user must have access to create/publish these pages.') . "\n" .
$this->_('3. The label-field must be set to "title (default)".');
if($this->addable) $field->attr('checked', 'checked');
else $field->collapsed = Inputfield::collapsedYes;
$inputfields->append($field);
}
$this->configMode = false; // reverse what was set at the top of this function
return $inputfields;
}
static public function getModuleConfigInputfields(array $data) {
$name = 'inputfieldClasses';
if(!isset($data[$name]) || !is_array($data[$name])) $data[$name] = self::$defaultInputfieldClasses;
$fields = new InputfieldWrapper();
$modules = Wire::getFuel('modules');
$field = $modules->get("InputfieldAsmSelect");
$field->attr('name', $name);
foreach(Wire::getFuel('modules')->find('className^=Inputfield') as $inputfield) {
$field->addOption($inputfield->className(), str_replace('Inputfield', '', $inputfield->className()));
}
$field->attr('value', $data[$name]);
$field->label = __('Inputfield modules available for page selection', __FILE__);
$field->description = __('Select the Inputfield modules that may be used for page selection. These should generally be Inputfields that allow you to select one or more options.', __FILE__); // Description
$fields->append($field);
return $fields;
}
}