'Page Name', 'version' => 106, 'summary' => 'Text input validated as a ProcessWire Page name field', 'permanent' => true, ); } public static $defaultReplacements = array( 'æ' => 'ae', 'å' => 'a', 'ä' => 'a', 'ã' => 'a', 'ß' => 'ss', 'ö' => 'o', 'ü' => 'u', 'đ' => 'dj', 'ж' => 'zh', 'х' => 'kh', 'ц' => 'tc', 'ч' => 'ch', 'ш' => 'sh', 'щ' => 'shch', 'ю' => 'iu', 'я' => 'ia', ':' => '-', ',' => '-', 'à' => 'a', 'á' => 'a', 'â' => 'a', 'è' => 'e', 'é' => 'e', 'ë' => 'e', 'ê' => 'e', 'ě' => 'e', 'ì' => 'i', 'í' => 'i', 'ï' => 'i', 'î' => 'i', 'ı' => 'i', 'İ' => 'i', 'ğ' => 'g', 'õ' => 'o', 'ò' => 'o', 'ó' => 'o', 'ô' => 'o', 'ø' => 'o', 'ù' => 'u', 'ú' => 'u', 'û' => 'u', 'ů' => 'u', 'ñ' => 'n', 'ç' => 'c', 'č' => 'c', 'ć' => 'c', 'Ç' => 'c', 'ď' => 'd', 'ĺ' => 'l', 'ľ' => 'l', 'ń' => 'n', 'ň' => 'n', 'ŕ' => 'r', 'ř' => 'r', 'š' => 's', 'ş' => 's', 'Ş' => 's', 'ť' => 't', 'ý' => 'y', 'ž' => 'z', 'а' => 'a', 'б' => 'b', 'в' => 'v', 'г' => 'g', 'д' => 'd', 'е' => 'e', 'ё' => 'e', 'з' => 'z', 'и' => 'i', 'й' => 'i', 'к' => 'k', 'л' => 'l', 'м' => 'm', 'н' => 'n', 'о' => 'o', 'п' => 'p', 'р' => 'r', 'с' => 's', 'т' => 't', 'у' => 'u', 'ф' => 'f', 'ы' => 'y', 'э' => 'e', 'ę' => 'e', 'ą' => 'a', 'ś' => 's', 'ł' => 'l', 'ż' => 'z', 'ź' => 'z', ); /** * Whether or not the system has LanguageSupportPageNames module installed * * @var bool * */ protected $hasLanguagePageNames = false; public function init() { parent::init(); $this->label = $this->_('Name'); // Field label for 'Name' $this->icon = 'angle-double-right'; $this->set('editPage', null); // page being edited, when available $this->set('parentPage', null); // parent of page being edited, when available $this->set('languageSupportLabel', ''); $this->set('slashUrls', 1); // whether a trailing slash should be shown in the URL preview // disable autocomplete for page name with custom attribute value $this->attr('autocomplete', 'pw-page-name'); // optional checkbox associated with the input, for use with language support $this->set('checkboxName', ''); // leave blank to disable $this->set('checkboxLabel', ''); $this->set('checkboxValue', ''); $this->set('checkboxChecked', false); $this->set('checkboxSuffix', ''); if($this->wire('config')->pageNameCharset === 'UTF8') { // no need to indicate input limitations $this->set('sanitizeMethod', 'pageNameUTF8'); $this->description = ''; } else { $this->description = $this->_("Any combination of letters (a-z), numbers (0-9), dashes or underscores (no spaces)."); // Field description describing what characters are allowed $this->set('sanitizeMethod', 'pageName'); } $this->hasLanguagePageNames = $this->wire()->modules->isInstalled('LanguageSupportPageNames'); $this->removeClass('InputfieldNoBorder', 'wrapClass'); } public function ___render() { $config = $this->wire()->config; $url = ''; $out = ''; $box = ''; $user = $this->wire()->user; $languages = $this->wire()->languages; $sanitizer = $this->wire()->sanitizer; $editable = $this->attr('disabled') ? false : true; $template = $this->editPage ? $this->editPage->template : null; $noLang = $template && $template->noLang; if($this->parentPage) { if($noLang && $languages && !$user->language->isDefault()) { // if noLang active for page edited by non-default user, ensure we use default language url $languages->setDefault(); $url = $this->parentPage->path; $languages->unsetDefault(); } else { $url = $this->parentPage->path; } if($this->hasLanguagePageNames && $this->parentPage->id == $config->rootPageID) { if($user->language->isDefault()) { $parentName = $this->parentPage->name; if(!trim($url, '/')) $url = ($parentName === Pages::defaultRootName ? "" : $parentName); } } } if($noLang) $languages = false; if($editable && $languages && $this->hasLanguagePageNames && !$languages->editable($user->language)) $editable = false; if($this->languageSupportLabel) { if($this->checkboxName) { $checked = $this->checkboxChecked ? " checked='checked'" : ''; $disabled = $editable ? '' : " disabled='disabled'"; $name = $sanitizer->entities($this->checkboxName); $value = $sanitizer->entities($this->checkboxValue); $label = $sanitizer->entities($this->checkboxLabel); $adminTheme = $this->wire()->adminTheme; $checkboxClass = $adminTheme ? $adminTheme->getClass('input-checkbox') : ''; $box = ""; } $label = $sanitizer->entities($this->languageSupportLabel); if(!$editable) $label = "$label"; $id = $sanitizer->entities($this->attr('id')); $out .= "
" . ""; } $value = $this->attr('value'); $link = ''; $slashUrls = (int) $this->slashUrls; if(strlen($value) && $this->hasLanguagePageNames) { $link = trim($url, '/') . "/$value" . ($slashUrls ? '/' : ''); $link = $config->urls->root . ltrim($link, '/'); $link = ""; } $p = "\n

"; if($link) $p .= $link; $p .= rtrim($url, '/') . "/"; if($link) $p .= ""; $p .= "

"; $out .= $p; $disabled = $this->attr('disabled'); if(!$editable) $this->attr('disabled', 'disabled'); $out .= parent::___render(); if(!$editable && !$disabled) $this->removeAttr('disabled'); // restore previous state if($this->languageSupportLabel) $out .= $box . "
"; // make the replacements part of the JS config $charset = $config->pageNameCharset; if($charset == 'UTF8') { $replacements = array(':' => '-', ',' => '-'); $whitelist = $this->config->pageNameWhitelist; } else { $replacements = empty($this->replacements) ? self::$defaultReplacements : $this->replacements; $whitelist = ''; } $config->js($this->className(), array( 'replacements' => $replacements, 'charset' => $charset, 'whitelist' => $whitelist )); return $out; } public function ___processInput(WireInputData $input) { if($this->attr('disabled')) return $this; $languages = $this->wire()->languages; if($this->editPage && $this->editPage->template->noLang) $languages = false; if($languages && $this->hasLanguagePageNames) { $user = $this->wire()->user; if(!$languages->editable($user->language)) return $this; $return = parent::___processInput($input); $process = $this->wire()->process; if($process instanceof WirePageEditor && $process->getPage()->id == $this->wire()->config->rootPageID) { if(!strlen($this->attr('value'))) { $this->attr('value', Pages::defaultRootName); } } } else { $return = parent::___processInput($input); } return $return; } static public function replacementStringToArray($str) { $r = preg_split('/[\r\n]+/', $str); $a = array(); foreach($r as $value) { if(!strpos($value, '=')) continue; list($k, $v) = explode('=', $value); $a[trim($k)] = trim($v); } return $a; } static public function replacementArrayToString(array $a) { $str = ''; foreach($a as $k => $v) $str .= "$k=$v\n"; return rtrim($str); } public function getModuleConfigInputfields(array $data) { $modules = $this->wire()->modules; $fields = $this->wire(new InputfieldWrapper()); if($this->wire()->config->pageNameCharset === 'UTF8') { $this->message($this->_('Character replacements configuration is disabled because $config->pageNameCharset is UTF8.')); return $fields; } $modules->addHookBefore('saveModuleConfigData', null, 'InputfieldPageName_saveModuleConfigData'); $name = 'replacements'; if(empty($data[$name])) $data[$name] = self::$defaultReplacements; if(is_array($data[$name])) { // data already in right save format, but need it to be a string for editing $replacements = self::replacementArrayToString($data[$name]); } else { // data is a string so they must have just saved, but we want to save the array version instead $replacements = $data[$name]; $data[$name] = self::replacementStringToArray($replacements); } /** @var InputfieldTextarea $field */ $field = $modules->get("InputfieldTextarea"); $field->attr('name', $name); $field->attr('value', $replacements); $field->attr('rows', 15); $field->label = $this->_('Character replacements'); $field->description = $this->_('Enter the replacements that will occur when a user is entering characters into a page name field. Enter one replacement per line in key=value format. Meaning, on each new line, enter the character(s) you want to replace followed by an equals sign "=" and the ascii character(s) you want to replace with.'); // Character replacements description $field->notes = $this->_('The replacement value for each must be one or more of: a-z, 0-9, dash, underscore or period.'); // Character replacements notes $fields->append($field); return $fields; } /** * Get default replacements setting * * @return array * @since 3.0.170 * */ public static function getDefaultReplacements() { return self::$defaultReplacements; } } function InputfieldPageName_saveModuleConfigData(HookEvent $event) { $arguments = $event->arguments; if($arguments[0] != 'InputfieldPageName') return; $data = $arguments[1]; $name = 'replacements'; if(!is_array($data[$name])) $data[$name] = InputfieldPageName::replacementStringToArray($data[$name]); $arguments[1] = $data; $event->arguments = $arguments; }