1
0
mirror of https://github.com/processwire/processwire.git synced 2025-08-15 11:14:12 +02:00

Code improvements to ProcessPageEdit link module, plus add feature request processwire/processwire-requests#477

This commit is contained in:
Ryan Cramer
2023-02-03 14:00:31 -05:00
parent b1313438ea
commit e86eb7fcf8

View File

@@ -5,7 +5,7 @@
* *
* Provides the link capability as used by the rich text editor. * Provides the link capability as used by the rich text editor.
* *
* ProcessWire 3.x, Copyright 2016 by Ryan Cramer * ProcessWire 3.x, Copyright 2023 by Ryan Cramer
* https://processwire.com * https://processwire.com
* *
* @property string $relOptions * @property string $relOptions
@@ -109,18 +109,22 @@ class ProcessPageEditLink extends Process implements ConfigurableModule {
* *
*/ */
public function init() { public function init() {
$input = $this->wire()->input;
$pages = $this->wire()->pages;
$modules = $this->wire()->modules;
$sanitizer = $this->wire()->sanitizer;
$this->startLabel = $this->_('Choose page'); $this->startLabel = $this->_('Choose page');
$this->modules->get("ProcessPageList"); $modules->get('ProcessPageList');
$id = (int) $this->input->get('id'); $id = (int) $input->get('id');
$this->langID = (int) $this->input->get('lang'); $this->langID = (int) $input->get('lang');
if($id) $this->page = $this->pages->get($id); if($id) $this->page = $pages->get($id);
if($this->page && $this->page->id && !$this->user->hasPermission("page-view", $this->page)) { if($this->page && $this->page->id && !$this->wire()->user->hasPermission("page-view", $this->page)) {
throw new WireException("You don't have access to this page"); throw new WireException("You don't have access to this page");
} }
if(!$this->page) $this->page = $this->wire('pages')->newNullPage(); if(!$this->page) $this->page = $pages->newNullPage();
$this->config->js('ProcessPageEditLink', array( $this->wire()->config->js('ProcessPageEditLink', array(
'selectStartLabel' => $this->startLabel, 'selectStartLabel' => $this->startLabel,
'langID' => $this->langID, 'langID' => $this->langID,
'pageID' => $id, 'pageID' => $id,
@@ -129,9 +133,9 @@ class ProcessPageEditLink extends Process implements ConfigurableModule {
'rootParentUrl' => $this->page->rootParent->url, 'rootParentUrl' => $this->page->rootParent->url,
'slashUrls' => $this->page->template ? $this->page->template->slashUrls : 1, 'slashUrls' => $this->page->template ? $this->page->template->slashUrls : 1,
'urlType' => $this->urlType, 'urlType' => $this->urlType,
'extLinkRel' => $this->wire('sanitizer')->names($this->extLinkRel), 'extLinkRel' => $sanitizer->names($this->extLinkRel),
'extLinkTarget' => $this->extLinkTarget, 'extLinkTarget' => $this->extLinkTarget,
'extLinkClass' => $this->wire('sanitizer')->names($this->extLinkClass), 'extLinkClass' => $sanitizer->names($this->extLinkClass),
'noLinkTextEdit' => (int) $this->noLinkTextEdit 'noLinkTextEdit' => (int) $this->noLinkTextEdit
)); ));
@@ -146,8 +150,13 @@ class ProcessPageEditLink extends Process implements ConfigurableModule {
*/ */
public function ___execute() { public function ___execute() {
if($this->wire('input')->get('href')) { $sanitizer = $this->wire()->sanitizer;
$currentValue = $this->wire('sanitizer')->url($this->wire('input')->get('href'), array( $modules = $this->wire()->modules;
$config = $this->wire()->config;
$input = $this->wire()->input;
if($input->get('href')) {
$currentValue = $sanitizer->url($input->get('href'), array(
'stripQuotes' => false, 'stripQuotes' => false,
'allowIDN' => true, 'allowIDN' => true,
)); ));
@@ -155,15 +164,15 @@ class ProcessPageEditLink extends Process implements ConfigurableModule {
$currentValue = ''; $currentValue = '';
} }
$currentText = $this->wire()->input->get('text'); $currentText = $input->get('text');
$currentText = $currentText === null ? '' : $this->wire()->sanitizer->text($currentText); $currentText = $currentText === null ? '' : $this->wire()->sanitizer->text($currentText);
/** @var InputfieldForm $form */ /** @var InputfieldForm $form */
$form = $this->modules->get("InputfieldForm"); $form = $modules->get("InputfieldForm");
$form->attr('id', 'ProcessPageEditLinkForm'); $form->attr('id', 'ProcessPageEditLinkForm');
//$form->description = $this->_("Enter a URL, select a page, or select a file to link:"); // Headline //$form->description = $this->_("Enter a URL, select a page, or select a file to link:"); // Headline
$this->wire('modules')->get('JqueryWireTabs'); $modules->get('JqueryWireTabs');
/** @var InputfieldWrapper $fieldset */ /** @var InputfieldWrapper $fieldset */
$fieldset = $this->wire(new InputfieldWrapper()); $fieldset = $this->wire(new InputfieldWrapper());
@@ -175,7 +184,7 @@ class ProcessPageEditLink extends Process implements ConfigurableModule {
// link text editing disabled // link text editing disabled
} else if($currentText) { } else if($currentText) {
/** @var InputfieldText $field */ /** @var InputfieldText $field */
$field = $this->modules->get("InputfieldText"); $field = $modules->get("InputfieldText");
$field->label = $this->_('Link text'); $field->label = $this->_('Link text');
$field->icon = 'pencil-square'; $field->icon = 'pencil-square';
$field->attr('id+name', 'link_text'); $field->attr('id+name', 'link_text');
@@ -184,13 +193,13 @@ class ProcessPageEditLink extends Process implements ConfigurableModule {
} }
/** @var InputfieldPageAutocomplete $field */ /** @var InputfieldPageAutocomplete $field */
$field = $this->modules->get("InputfieldPageAutocomplete"); $field = $modules->get("InputfieldPageAutocomplete");
$field->label = $this->_('Link to URL'); $field->label = $this->_('Link to URL');
$field->attr('id+name', 'link_page_url'); $field->attr('id+name', 'link_page_url');
$field->icon = 'external-link-square'; $field->icon = 'external-link-square';
$field->description = $this->_('Enter a URL, email address, anchor, or enter word(s) to find a page.'); $field->description = $this->_('Enter a URL, email address, anchor, or enter word(s) to find a page.');
$field->labelFieldName = 'url'; $field->labelFieldName = 'url';
if($this->wire('modules')->isInstalled('PagePaths') && !$this->wire('languages')) { if($modules->isInstalled('PagePaths') && !$this->wire('languages')) {
$field->searchFields = 'path title'; $field->searchFields = 'path title';
} else { } else {
$field->searchFields = 'name title'; $field->searchFields = 'name title';
@@ -202,22 +211,22 @@ class ProcessPageEditLink extends Process implements ConfigurableModule {
$field->disableChars = '/:.#'; $field->disableChars = '/:.#';
$field->useAndWords = true; $field->useAndWords = true;
$field->findPagesSelector = $field->findPagesSelector =
"has_parent!=" . $this->wire('config')->adminRootPageID . ", " . "has_parent!=" . $config->adminRootPageID . ", " .
"id!=" . $this->wire('config')->http404PageID; "id!=" . $config->http404PageID;
if($currentValue) $field->attr('value', $currentValue); if($currentValue) $field->attr('value', $currentValue);
$fieldset->add($field); $fieldset->add($field);
if(is_array($this->wire('input')->get('anchors'))) { if(is_array($input->get('anchors'))) {
$field->columnWidth = 60; $field->columnWidth = 60;
/** @var InputfieldSelect $field */ /** @var InputfieldSelect $field */
$field = $this->modules->get('InputfieldSelect'); $field = $modules->get('InputfieldSelect');
$field->columnWidth = 40; $field->columnWidth = 40;
$field->attr('id+name', 'link_page_anchor'); $field->attr('id+name', 'link_page_anchor');
$field->label = $this->_('Select Anchor'); $field->label = $this->_('Select Anchor');
$field->description = $this->_('Anchors found in the text you are editing.'); $field->description = $this->_('Anchors found in the text you are editing.');
$field->icon = 'flag'; $field->icon = 'flag';
foreach($this->wire('input')->get('anchors') as $anchor) { foreach($input->get->array('anchors') as $anchor) {
$anchor = '#' . $this->wire('sanitizer')->text($anchor); $anchor = '#' . $sanitizer->text($anchor);
if(strlen($anchor)) $field->addOption($anchor); if(strlen($anchor)) $field->addOption($anchor);
if($currentValue && $currentValue == $anchor) $field->attr('value', $currentValue); if($currentValue && $currentValue == $anchor) $field->attr('value', $currentValue);
} }
@@ -225,7 +234,7 @@ class ProcessPageEditLink extends Process implements ConfigurableModule {
} }
/** @var InputfieldInteger $field */ /** @var InputfieldInteger $field */
$field = $this->modules->get('InputfieldInteger'); $field = $modules->get('InputfieldInteger');
$field->attr('id+name', 'link_page_id'); $field->attr('id+name', 'link_page_id');
$field->label = $this->_("Select Page"); $field->label = $this->_("Select Page");
$field->set('startLabel', $this->startLabel); $field->set('startLabel', $this->startLabel);
@@ -234,7 +243,8 @@ class ProcessPageEditLink extends Process implements ConfigurableModule {
$fieldset->add($field); $fieldset->add($field);
if($this->page->numChildren) { if($this->page->numChildren) {
$field = $this->modules->get('InputfieldInteger'); /** @var InputfieldInteger $field */
$field = $modules->get('InputfieldInteger');
$field->attr('id+name', 'child_page_id'); $field->attr('id+name', 'child_page_id');
$field->label = $this->_("Select Child Page"); $field->label = $this->_("Select Child Page");
$field->description = $this->_('This is the same as "Select Page" above, but may quicker to use if linking to children of the current page.'); $field->description = $this->_('This is the same as "Select Page" above, but may quicker to use if linking to children of the current page.');
@@ -246,24 +256,26 @@ class ProcessPageEditLink extends Process implements ConfigurableModule {
$fieldset->append($this->getFilesField()); $fieldset->append($this->getFilesField());
/** @var InputfieldWrapper $fieldset */
$fieldset = $this->wire(new InputfieldWrapper()); $fieldset = $this->wire(new InputfieldWrapper());
$fieldset->attr('title', $this->_('Attributes')); $fieldset->attr('title', $this->_('Attributes'));
$fieldset->attr('id', 'link_attributes'); $fieldset->attr('id', 'link_attributes');
$fieldset->addClass('WireTab'); $fieldset->addClass('WireTab');
$form->append($fieldset); $form->append($fieldset);
$field = $this->modules->get('InputfieldText'); /** @var InputfieldText $field */
$field = $modules->get('InputfieldText');
$field->attr('id+name', 'link_title'); $field->attr('id+name', 'link_title');
$field->label = $this->_('Title'); $field->label = $this->_('Title');
$field->description = $this->_('Additional text to describe link.'); $field->description = $this->_('Additional text to describe link.');
if($this->wire('input')->get('title')) { if($input->get('title')) {
$field->attr('value', $this->wire('sanitizer')->text($this->wire('input')->get('title'))); $field->attr('value', $sanitizer->text($input->get('title')));
} }
$fieldset->add($field); $fieldset->add($field);
if($this->targetOptions) { if($this->targetOptions) {
/** @var InputfieldSelect $field */ /** @var InputfieldSelect $field */
$field = $this->modules->get('InputfieldSelect'); $field = $modules->get('InputfieldSelect');
$field->attr('id+name', 'link_target'); $field->attr('id+name', 'link_target');
$field->label = $this->_('Target'); $field->label = $this->_('Target');
$field->description = $this->_('Where this link will open.'); $field->description = $this->_('Where this link will open.');
@@ -273,7 +285,8 @@ class ProcessPageEditLink extends Process implements ConfigurableModule {
} }
if($this->relOptions) { if($this->relOptions) {
$field = $this->modules->get('InputfieldSelect'); /** @var InputfieldSelect $field */
$field = $modules->get('InputfieldSelect');
$field->attr('id+name', 'link_rel'); $field->attr('id+name', 'link_rel');
$field->label = $this->_('Rel'); $field->label = $this->_('Rel');
$field->description = $this->_('Relationship of link to document.'); $field->description = $this->_('Relationship of link to document.');
@@ -284,7 +297,7 @@ class ProcessPageEditLink extends Process implements ConfigurableModule {
if($this->classOptions) { if($this->classOptions) {
/** @var InputfieldCheckboxes $field */ /** @var InputfieldCheckboxes $field */
$field = $this->modules->get('InputfieldCheckboxes'); $field = $modules->get('InputfieldCheckboxes');
$field->attr('id+name', 'link_class'); $field->attr('id+name', 'link_class');
$field->label = $this->_('Class'); $field->label = $this->_('Class');
$field->description = $this->_('Additional classes that can affect the look or behavior of the link.'); $field->description = $this->_('Additional classes that can affect the look or behavior of the link.');
@@ -293,10 +306,10 @@ class ProcessPageEditLink extends Process implements ConfigurableModule {
$fieldset->add($field); $fieldset->add($field);
} }
if($this->wire('user')->isSuperuser()) $fieldset->notes = if($this->wire()->user->isSuperuser()) $fieldset->notes =
sprintf( sprintf(
$this->_('You may customize available attributes shown above in the %s module settings.'), $this->_('You may customize available attributes shown above in the %s module settings.'),
"[ProcessPageEditLink](" . $this->wire('config')->urls->admin . "module/edit?name=ProcessPageEditLink)" "[ProcessPageEditLink](" . $config->urls->admin . "module/edit?name=ProcessPageEditLink)"
); );
return $form->render() . "<p class='detail ui-priority-secondary'><code id='link_markup'></code></p>"; return $form->render() . "<p class='detail ui-priority-secondary'><code id='link_markup'></code></p>";
@@ -310,9 +323,11 @@ class ProcessPageEditLink extends Process implements ConfigurableModule {
*/ */
protected function addSelectOptions(InputfieldSelect $field, $attrName, $optionsText) { protected function addSelectOptions(InputfieldSelect $field, $attrName, $optionsText) {
$isExisting = $this->wire('input')->get('href') != ''; $input = $this->wire()->input;
$existingValue = $this->wire('sanitizer')->text($this->wire('input')->get($attrName)); $isExisting = $input->get('href') != '';
$existingValue = explode(' ', $existingValue); $existingValueStr = $this->wire()->sanitizer->text($input->get($attrName));
$existingValueArray = strlen($existingValueStr) ? explode(' ', $existingValueStr) : array();
$values = array();
if($field instanceof InputfieldRadios) { if($field instanceof InputfieldRadios) {
$field->addOption('', $this->_('None')); $field->addOption('', $this->_('None'));
@@ -323,33 +338,38 @@ class ProcessPageEditLink extends Process implements ConfigurableModule {
$isDefault = strpos($value, '+') !== false; $isDefault = strpos($value, '+') !== false;
if($isDefault) $value = trim($value, '+'); if($isDefault) $value = trim($value, '+');
$attr = array(); $attr = array();
if(($isDefault && !$isExisting) || in_array($value, $existingValue)) {
if($field instanceof InputfieldCheckboxes) {
$attr['checked'] = 'checked';
} else {
$attr['selected'] = 'selected';
}
}
$value = trim($value, '+ '); $value = trim($value, '+ ');
$label = ''; $label = '';
if(strpos($value, '=') !== false) { if(strpos($value, '=') !== false) {
list($value, $label) = explode('=', $value); list($value, $label) = explode('=', $value, 2);
$value = trim($value); $value = trim($value);
$label = trim($label); $label = trim($label);
} else { } else {
if($value == '_blank') $label = $this->_('open in new window'); if($value == '_blank') $label = $this->_('open in new window');
if($value == 'nofollow') $label = $this->_('tell search engines not to follow'); if($value == 'nofollow') $label = $this->_('tell search engines not to follow');
} }
if($label) { if(strpos($label, '"') === 0 || strpos($label, "'") === 0) {
$label = trim($label, "\"'");
} else if($label) {
$label = "$value ($label)"; $label = "$value ($label)";
} else { } else {
$label = $value; $label = $value;
} }
$field->addOption($value, $label, $attr); if(($isDefault && !$isExisting) || (in_array($value, $existingValueArray) || $existingValueStr === $value)) {
if($field instanceof InputfieldCheckboxes) {
$attr['checked'] = 'checked';
} else {
$attr['selected'] = 'selected';
} }
} }
$field->addOption($value, $label, $attr);
$values[] = $value;
}
}
/** /**
* Return JSON containing files list for ajax use * Return JSON containing files list for ajax use
* *
@@ -424,7 +444,7 @@ class ProcessPageEditLink extends Process implements ConfigurableModule {
*/ */
protected function getFilesField() { protected function getFilesField() {
/** @var InputfieldSelect $field */ /** @var InputfieldSelect $field */
$field = $this->modules->get("InputfieldSelect"); $field = $this->wire()->modules->get("InputfieldSelect");
$field->label = $this->_("Select File"); $field->label = $this->_("Select File");
$field->attr('id+name', 'link_page_file'); $field->attr('id+name', 'link_page_file');
$files = $this->getFiles(); $files = $this->getFiles();
@@ -442,29 +462,43 @@ class ProcessPageEditLink extends Process implements ConfigurableModule {
public function getModuleConfigInputfields(array $data) { public function getModuleConfigInputfields(array $data) {
$modules = $this->wire()->modules;
$sanitizer = $this->wire()->sanitizer;
$data = array_merge(self::getDefaultSettings(), $data); $data = array_merge(self::getDefaultSettings(), $data);
/** @var InputfieldWrapper $inputfields */
$inputfields = $this->wire(new InputfieldWrapper()); $inputfields = $this->wire(new InputfieldWrapper());
$fieldset = $this->wire('modules')->get('InputfieldFieldset'); /** @var InputfieldFieldset $fieldset */
$fieldset = $modules->get('InputfieldFieldset');
$fieldset->label = $this->_('Attribute options'); $fieldset->label = $this->_('Attribute options');
$fieldset->description = $this->_('Enter one attribute value per line. The user will be able to select these as options when adding links. To make an option selected by default (for new links), precede it with a plus "+".'); $fieldset->description =
$this->_('Enter one of attribute `value`, `value=label`, or `value="label"` per line (see notes for details).') . ' ' .
$this->_('The user will be able to select these as options when adding links.') . ' ' .
$this->_('To make an option selected by default (for new links), precede the value with a plus “+”.');
$fieldset->detail =
$this->_('To include labels, specify `value=label` to show **“value (label)”** for each selectable option.') . ' ' .
$this->_('Or specify `value="label"` (label in quotes) to show just **“label”** (hiding the value) for each selectable option.');
$fieldset->icon = 'sliders'; $fieldset->icon = 'sliders';
$f = $this->wire('modules')->get('InputfieldTextarea'); /** @var InputfieldTextarea $f */
$f = $modules->get('InputfieldTextarea');
$f->attr('name', 'classOptions'); $f->attr('name', 'classOptions');
$f->label = 'class'; $f->label = 'class';
$f->attr('value', $data['classOptions']); $f->attr('value', $data['classOptions']);
$f->columnWidth = 34; $f->columnWidth = 34;
$fieldset->add($f); $fieldset->add($f);
$f = $this->wire('modules')->get('InputfieldTextarea'); /** @var InputfieldTextarea $f */
$f = $modules->get('InputfieldTextarea');
$f->attr('name', 'relOptions'); $f->attr('name', 'relOptions');
$f->label = 'rel'; $f->label = 'rel';
$f->attr('value', $data['relOptions']); $f->attr('value', $data['relOptions']);
$f->columnWidth = 33; $f->columnWidth = 33;
$fieldset->add($f); $fieldset->add($f);
$f = $this->wire('modules')->get('InputfieldTextarea'); /** @var InputfieldTextarea $f */
$f = $modules->get('InputfieldTextarea');
$f->attr('name', 'targetOptions'); $f->attr('name', 'targetOptions');
$f->label = 'target'; $f->label = 'target';
$f->attr('value', $data['targetOptions']); $f->attr('value', $data['targetOptions']);
@@ -472,31 +506,35 @@ class ProcessPageEditLink extends Process implements ConfigurableModule {
$fieldset->add($f); $fieldset->add($f);
$inputfields->add($fieldset); $inputfields->add($fieldset);
$fieldset = $this->wire('modules')->get('InputfieldFieldset'); /** @var InputfieldFieldset $fieldset */
$fieldset = $modules->get('InputfieldFieldset');
$fieldset->label = $this->_('External link attributes'); $fieldset->label = $this->_('External link attributes');
$fieldset->description = $this->_('Specify the default selected attributed that will be automatically populated when an external link is detected.'); $fieldset->description = $this->_('Specify the default selected attributed that will be automatically populated when an external link is detected.');
$fieldset->description .= ' ' . $this->_('If used, the value must be one you have predefined above.'); $fieldset->description .= ' ' . $this->_('If used, the value must be one you have predefined above.');
$fieldset->icon = 'external-link'; $fieldset->icon = 'external-link';
$fieldset->collapsed = Inputfield::collapsedBlank; $fieldset->collapsed = Inputfield::collapsedBlank;
$f = $this->wire('modules')->get('InputfieldText'); /** @var InputfieldText $f */
$f = $modules->get('InputfieldText');
$f->attr('name', 'extLinkClass'); $f->attr('name', 'extLinkClass');
$f->label = 'class'; $f->label = 'class';
$f->attr('value', $this->wire('sanitizer')->names($data['extLinkClass'])); $f->attr('value', $sanitizer->names($data['extLinkClass']));
$f->required = false; $f->required = false;
$f->columnWidth = 34; $f->columnWidth = 34;
$fieldset->add($f); $fieldset->add($f);
$f = $this->wire('modules')->get('InputfieldText'); /** @var InputfieldText $f */
$f = $modules->get('InputfieldText');
$f->attr('name', 'extLinkRel'); $f->attr('name', 'extLinkRel');
$f->notes = $this->_('Example: Specifying **nofollow** would make external links default to be not followed by search engines.'); $f->notes = $this->_('Example: Specifying **nofollow** would make external links default to be not followed by search engines.');
$f->label = 'rel'; $f->label = 'rel';
$f->required = false; $f->required = false;
$f->attr('value', $this->wire('sanitizer')->names($data['extLinkRel'])); $f->attr('value', $sanitizer->names($data['extLinkRel']));
$f->columnWidth = 33; $f->columnWidth = 33;
$fieldset->add($f); $fieldset->add($f);
$f = $this->wire('modules')->get('InputfieldName'); /** @var InputfieldName $f */
$f = $modules->get('InputfieldName');
$f->attr('name', 'extLinkTarget'); $f->attr('name', 'extLinkTarget');
$f->label = 'target'; $f->label = 'target';
$f->notes = $this->_('Example: Specifying **_blank** would make external links default to open in a new window.'); $f->notes = $this->_('Example: Specifying **_blank** would make external links default to open in a new window.');
@@ -506,7 +544,8 @@ class ProcessPageEditLink extends Process implements ConfigurableModule {
$fieldset->add($f); $fieldset->add($f);
$inputfields->add($fieldset); $inputfields->add($fieldset);
$f = $this->wire('modules')->get('InputfieldRadios'); /** @var InputfieldRadios $f */
$f = $modules->get('InputfieldRadios');
$f->attr('name', 'urlType'); $f->attr('name', 'urlType');
$f->label = $this->_('URL type for page links'); $f->label = $this->_('URL type for page links');
$f->addOption(self::urlTypeAbsolute, $this->_('Full/absolute path from root (default)')); $f->addOption(self::urlTypeAbsolute, $this->_('Full/absolute path from root (default)'));
@@ -518,7 +557,7 @@ class ProcessPageEditLink extends Process implements ConfigurableModule {
$inputfields->add($f); $inputfields->add($f);
/** @var InputfieldCheckbox $f */ /** @var InputfieldCheckbox $f */
$f = $this->wire()->modules->get('InputfieldCheckbox'); $f = $modules->get('InputfieldCheckbox');
$f->attr('name', 'noLinkTextEdit'); $f->attr('name', 'noLinkTextEdit');
$f->label = $this->_('Disable link text edit feature?'); $f->label = $this->_('Disable link text edit feature?');
$f->description = $this->_('Disables the “Edit Link Text” feature, enabling you to support links that can contain existing markup.'); $f->description = $this->_('Disables the “Edit Link Text” feature, enabling you to support links that can contain existing markup.');
@@ -531,7 +570,5 @@ class ProcessPageEditLink extends Process implements ConfigurableModule {
return $inputfields; return $inputfields;
} }
} }