From f52c3f54c9e749c4d8e7ec2cf793424b4ea79abe Mon Sep 17 00:00:00 2001 From: Ryan Cramer Date: Fri, 16 Mar 2018 10:24:46 -0400 Subject: [PATCH] Fix issue processwire/processwire-issues#322 where certain scenario could allow collision of language-specific page names --- .../LanguageSupportPageNames.module | 60 +++++++++++++++++++ 1 file changed, 60 insertions(+) diff --git a/wire/modules/LanguageSupport/LanguageSupportPageNames.module b/wire/modules/LanguageSupport/LanguageSupportPageNames.module index 01182e87..55cd74e6 100644 --- a/wire/modules/LanguageSupport/LanguageSupportPageNames.module +++ b/wire/modules/LanguageSupport/LanguageSupportPageNames.module @@ -557,9 +557,17 @@ class LanguageSupportPageNames extends WireData implements Module, ConfigurableM // set language page name $name = $inputfield->attr('name') . $language; $value = $sanitizer->pageNameUTF8($input->$name); + + // if it matches the value for the default language, avoid double storing it if($value === $page->name) $value = ''; + + // if it matches the value already on the page, then no need to go further $key = "name$language"; if($value == $page->get($key)) continue; + + // @todo uncomment in dev branch + // if(!$this->checkLanguagePageName($language, $page, $value, $inputfield)) continue; + if($page->id) { $page->set($key, $value); } else { @@ -568,6 +576,58 @@ class LanguageSupportPageNames extends WireData implements Module, ConfigurableM } } + /** + * Check changed page name for given language + * + * @param Language $language + * @param Page $page + * @param string $value New page name + * @param Wire|null $errorTarget Object to send error to (Inputfield likely) + * @return bool True if all good, false if not + * + */ + public function checkLanguagePageName(Language $language, Page $page, $value, Wire $errorTarget = null) { + // verify that it does not conflict with another page inheriting name from default language + $isValid = true; + $nameKey = "name$language->id"; + + if(!strlen($value)) return true; + + $sql = + "SELECT id, name, $nameKey FROM pages " . + "WHERE parent_id=:parent_id " . + "AND id!=:id " . + "AND (" . + "(name=:newName AND $nameKey IS NULL) " . // default name matches and lang name inherits it (is null) + "OR ($nameKey=:newName2)" . // or lang name is same as requested one + ")"; + + $query = $this->wire('database')->prepare($sql); + $query->bindValue(':parent_id', $page->parent_id, \PDO::PARAM_INT); + $query->bindValue(':newName', $value); + $query->bindValue(':newName2', $value); + $query->bindValue(':id', $page->id, \PDO::PARAM_INT); + + try { + $query->execute(); + $row = $query->fetch(\PDO::FETCH_ASSOC); + if($row) { + $isValid = false; + if($errorTarget) $errorTarget->error(sprintf( + $this->_('A sibling page (id=%1$d) is already using name "%2$s" for language: %3$s'), + $row['id'], $value, $language->get('title|name') + )); + } + } catch(\Exception $e) { + $this->error($e->getMessage()); + $isValid = false; + } + + $query->closeCursor(); + + return $isValid; + } + /** * Hook into PageFinder::getQuery to add language status check *