Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 25 additions & 13 deletions controller/admin_controller.php
Original file line number Diff line number Diff line change
Expand Up @@ -555,16 +555,14 @@ public function add_rule($language, $parent_id = 0)
* @param int $rule_id The rule identifier to edit
* @return void
* @access public
* @throws \phpbb\boardrules\exception\base If the rule does not exist or stored rule data is invalid
* @throws \phpbb\boardrules\exception\base If stored rule data is invalid
*/
public function edit_rule($rule_id)
{
// Add form key
add_form_key('add_edit_rule');

// Initiate and load the rule entity
/* @var $entity \phpbb\boardrules\entity\rule */
$entity = $this->container->get('phpbb.boardrules.entity')->load($rule_id);
$entity = $this->load_rule($rule_id);

// Collect the form data
$data = array(
Expand Down Expand Up @@ -778,13 +776,10 @@ protected function add_edit_rule_data($entity, $data)
* @param int $rule_id The rule identifier to delete
* @return void
* @access public
* @throws \phpbb\boardrules\exception\out_of_bounds If the rule does not exist
*/
public function delete_rule($rule_id)
{
// Initiate and load the rule entity
/* @var $entity \phpbb\boardrules\entity\rule */
$entity = $this->container->get('phpbb.boardrules.entity')->load($rule_id);
$entity = $this->load_rule($rule_id);

// Use a confirmation box routine when deleting a rule
if (confirm_box(true))
Expand All @@ -811,7 +806,7 @@ public function delete_rule($rule_id)
$is_cat = (int) ($entity->get_right_id() - $entity->get_left_id() > 1);

// Request confirmation from the user to delete the rule
confirm_box(false, $this->lang->lang('ACP_DELETE_RULE_CONFIRM', $is_cat), build_hidden_fields(array(
confirm_box(false, $this->lang->lang($is_cat ? 'ACP_DELETE_RULE_CATEGORY_CONFIRM' : 'ACP_DELETE_RULE_CONFIRM'), build_hidden_fields(array(
'mode' => 'manage',
'action' => 'delete',
'rule_id' => $rule_id,
Expand All @@ -831,10 +826,11 @@ public function delete_rule($rule_id)
* @param int $amount The number of places to move the rule
* @return void
* @access public
* @throws \phpbb\boardrules\exception\out_of_bounds If the rule does not exist after moving
*/
public function move_rule($rule_id, $direction, $amount = 1)
{
$moved = false;

// If the link hash is invalid, stop and show an error message to the user
if (!check_link_hash($this->request->variable('hash', ''), $direction . $rule_id))
{
Expand Down Expand Up @@ -862,9 +858,7 @@ public function move_rule($rule_id, $direction, $amount = 1)
$json_response->send(array('success' => $moved));
}

// Initiate and load the rule entity for no AJAX request
/* @var $entity \phpbb\boardrules\entity\rule */
$entity = $this->container->get('phpbb.boardrules.entity')->load($rule_id);
$entity = $this->load_rule($rule_id);

// Use a redirect to reload the current page
redirect("{$this->u_action}&language={$entity->get_language()}&parent_id={$entity->get_parent_id()}");
Expand Down Expand Up @@ -920,6 +914,24 @@ public function set_page_url($u_action)
$this->u_action = $u_action;
}

/**
* Load a rule or display a recoverable ACP error when it no longer exists.
*
* @param int $rule_id Rule identifier
* @return \phpbb\boardrules\entity\rule_interface
*/
protected function load_rule($rule_id)
{
try
{
return $this->container->get('phpbb.boardrules.entity')->load($rule_id);
}
catch (\phpbb\boardrules\exception\out_of_bounds $e)
{
trigger_error($e->get_message($this->lang) . adm_back_link($this->u_action), E_USER_WARNING);
}
}

/**
* Assign installed language options and return their dashboard data.
*
Expand Down
12 changes: 6 additions & 6 deletions controller/main_controller.php
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,11 @@ public function display()

$item_depth = count($open_categories);

// Build a stable compound number from sibling positions at every nesting level
$compound_counters = array_slice($compound_counters, 0, $item_depth + 1);
$compound_counters[$item_depth] = isset($compound_counters[$item_depth]) ? $compound_counters[$item_depth] + 1 : 1;
$compound_number = implode('.', $compound_counters);

if ($entity->get_right_id() - $entity->get_left_id() > 1)
{
// Rule categories
Expand All @@ -131,7 +136,7 @@ public function display()
{
// Rules
$is_category = false;
$anchor = $entity->get_anchor() ?: $this->lang->lang('BOARDRULES_RULE_ANCHOR', ($cat_counter - 1) . $rule_counter);
$anchor = $entity->get_anchor() ?: $this->lang->lang('BOARDRULES_RULE_ANCHOR', $item_depth ? ($cat_counter - 1) . $rule_counter : $compound_number);

// Increment rule counter
$rule_counter++;
Expand All @@ -141,11 +146,6 @@ public function display()
// one-based display depth; rules use the containing category count.
$depth = $is_category ? $item_depth + 1 : $item_depth;

// Build a stable compound number from sibling positions at every nesting level
$compound_counters = array_slice($compound_counters, 0, $item_depth + 1);
$compound_counters[$item_depth] = isset($compound_counters[$item_depth]) ? $compound_counters[$item_depth] + 1 : 1;
$compound_number = implode('.', $compound_counters);

// Assign values to template vars for this rule entity
$this->template->assign_block_vars('rules', array(
'TITLE' => $entity->get_title(),
Expand Down
70 changes: 33 additions & 37 deletions entity/rule.php
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,8 @@ public function load($id)
*
* Used when the data is already loaded externally.
* Any existing data on this rule is over-written.
* All data is validated and an exception is thrown if any data is invalid.
* Required fields and basic data types are validated. Values already loaded
* from storage are not passed through write-time transformations again.
*
* @param array $data Data array, typically from the database
* @return rule_interface $this object for chaining calls; load()->set()->save()
Expand All @@ -111,7 +112,7 @@ public function import($data)
'rule_parent_id' => 'integer',
'rule_parents' => 'string',
'rule_anchor' => 'string',
'rule_title' => 'set_title', // call set_title()
'rule_title' => 'string',

// We do not pass to set_message() as generate_text_for_storage would run twice
'rule_message' => 'string',
Expand Down Expand Up @@ -273,10 +274,13 @@ public function set_title($title)
// Enforce a string
$title = (string) $title;

$title = $this->encode_unicode_for_storage($title);
// MSSQL string literals cannot safely preserve every BMP character.
$title = strpos($this->db->get_sql_layer(), 'mssql') === 0
? utf8_encode_ncr($title)
: utf8_encode_ucr($title);

// Limit both the displayed and stored title lengths to the column size.
if (truncate_string($title, 200, 200) !== $title)
// Enforce the database column length after storage encoding.
if (utf8_strlen($title) > 200)
{
throw new \phpbb\boardrules\exception\unexpected_value(array('title', 'TOO_LONG'));
}
Expand All @@ -287,22 +291,6 @@ public function set_title($title)
return $this;
}

/**
* Encode Unicode characters that cannot be stored safely by the DBMS.
*
* @param string $text
* @return string
*/
protected function encode_unicode_for_storage($text)
{
if (strpos($this->db->get_sql_layer(), 'mssql') === 0)
{
return utf8_encode_ncr($text);
}

return utf8_encode_ucr($text);
}

/**
* Get message for edit
*
Expand Down Expand Up @@ -497,31 +485,39 @@ public function set_anchor($anchor)
{
// Enforce a string
$anchor = (string) $anchor;
$rule_id = $this->get_id();

// Anchors must begin with a letter and contain only URL-friendly
// letters, marks, numbers, hyphens, and underscores. Four-byte
// characters are rejected even when their Unicode category matches.
if ($anchor !== '' && !preg_match('/^(?!.*[\x{10000}-\x{10FFFF}])\p{L}[\p{L}\p{M}\p{N}_-]*$/u', $anchor))
// Existing anchors may predate current validation rules.
if ($rule_id && $this->get_anchor() === $anchor)
{
throw new \phpbb\boardrules\exception\unexpected_value(array('anchor', 'ILLEGAL_CHARACTERS'));
return $this;
}

// Limit both the displayed and stored anchor lengths to the column size.
if (truncate_string($anchor, 255, 255) !== $anchor)
if ($anchor !== '')
{
throw new \phpbb\boardrules\exception\unexpected_value(array('anchor', 'TOO_LONG'));
}
// HTML5 IDs allow broader values, but these are also URL fragments.
// Restrict them to BMP letters, marks, numbers, hyphens, and underscores.
if (!preg_match('/^(?!.*[\x{10000}-\x{10FFFF}])[\p{L}\p{N}_-][\p{L}\p{M}\p{N}_-]*$/u', $anchor))
{
throw new \phpbb\boardrules\exception\unexpected_value(array('anchor', 'ILLEGAL_CHARACTERS'));
}

// Make sure rule anchors are unique for the current language
// Test if new page and anchor field has data or...
// if existing page and anchor field has new data not equal to existing anchor data
if ((!$this->get_id() && $anchor !== '') || ($this->get_id() && $anchor !== '' && $this->get_anchor() !== $anchor))
{
if (utf8_strlen($anchor) > 255)
{
throw new \phpbb\boardrules\exception\unexpected_value(array('anchor', 'TOO_LONG'));
}

// Make sure the anchor is unique for the current language.
$sql = 'SELECT 1
FROM ' . $this->boardrules_table . "
WHERE rule_anchor = '" . $this->db->sql_escape($anchor) . "'
AND rule_id <> " . $this->get_id() .
($this->get_language() ? " AND rule_language = '" . $this->db->sql_escape($this->get_language()) . "'" : '');
AND rule_id <> " . $rule_id;
$language = $this->get_language();
if ($language !== '')
{
$sql .= " AND rule_language = '" . $this->db->sql_escape($language) . "'";
}

$result = $this->db->sql_query_limit($sql, 1);
$row = $this->db->sql_fetchrow($result);
$this->db->sql_freeresult($result);
Expand Down
2 changes: 1 addition & 1 deletion exception/base.php
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ class base extends \Exception
* @param \Exception|null $previous
* @access public
*/
public function __construct($message = null, $code = 0, \Exception $previous = null)
public function __construct($message = null, $code = 0, ?\Exception $previous = null)
{
parent::__construct();

Expand Down
8 changes: 3 additions & 5 deletions language/ar/boardrules_acp.php
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@
'ACP_BOARDRULES_DRAFT_NOTICE' => 'هذه القوانين غير مرئية للمستخدمين. يرى المستخدمون حالياً القوانين المكتوبة باللغة الافتراضية للمنتدى.',
'ACP_BOARDRULES_DRAFT_DEFAULT_NOTICE' => 'هذه القوانين غير مرئية للمستخدمين. انشرها لإتاحة قوانين المنتدى الافتراضية.',
'ACP_BOARDRULES_COPY_RULESET' => 'نسخ مجموعة قوانين اللغة',
'ACP_BOARDRULES_COPY_RULESET_EXPLAIN' => 'انسخ كل الفئات والقوانين إلى <strong>%s</strong>. ستُضاف القوانين المنسوخة بعد أي قوانين موجودة، وستظل مجموعة القوانين الكاملة في اللغة الهدف مسودة حتى تنشرها.',
'ACP_BOARDRULES_COPY_RULESET_EXPLAIN' => 'انسخ كل الفئات والقوانين إلى <strong>%s</strong>. ستُضاف القوانين المنسوخة بعد أي قوانين موجودة، وسيتم تعيين مجموعة القوانين الكاملة في اللغة الهدف كمسودة حتى تنشرها.',
'ACP_BOARDRULES_COPY_APPEND' => 'إضافة إلى القوانين الموجودة',
'ACP_BOARDRULES_COPY_APPEND_EXPLAIN' => array(
1 => 'تحتوي اللغة الهدف حالياً على %d قانون. سيبقى دون تغيير، وستُضاف القوانين المنسوخة بعده. ستُضاف لاحقة رقمية إلى المراسي المنسوخة المتعارضة.',
Expand Down Expand Up @@ -152,10 +152,8 @@
'ACP_RULE_MESSAGE_EXPLAIN' => 'محتوى كل قانون على حده يظهر في صفحة القوانين ( يتم تعطيل هذا الخيار في الأقسام ).',
'ACP_RULE_MESSAGE_DISABLED' => 'هذا القسم يحتوي على قوانين , وبالتالي يتم تعطيل المحتوى ( محرر الكتابة ).',
'ACP_ADD_RULE' => 'إنشاء قانون جديد ',
'ACP_DELETE_RULE_CONFIRM' => array(
0 => 'متأكد أنك تريد حذف هذا القانون ؟',
1 => 'متأكد أنك تريد حذف هذا القانون ؟<br />تحذير : حذف قسم يعني حذف جميع القوانين الموجودة فيه أيضاً.',
),
'ACP_DELETE_RULE_CONFIRM' => 'متأكد أنك تريد حذف هذا القانون ؟',
'ACP_DELETE_RULE_CATEGORY_CONFIRM' => 'متأكد أنك تريد حذف هذا القانون ؟<br />تحذير : حذف قسم يعني حذف جميع القوانين الموجودة فيه أيضاً.',
'ACP_RULE_ADDED' => 'تم إضافة القانون بنجاح.',
'ACP_RULE_DELETED' => 'تم حذف القانون بنجاح.',
'ACP_RULE_EDITED' => 'تم تعديل القانون بنجاح.',
Expand Down
8 changes: 3 additions & 5 deletions language/bg/boardrules_acp.php
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@
'ACP_BOARDRULES_DRAFT_NOTICE' => 'Тези правила не са видими за потребителите. В момента потребителите виждат правилата на езика по подразбиране на форума.',
'ACP_BOARDRULES_DRAFT_DEFAULT_NOTICE' => 'Тези правила не са видими за потребителите. Публикувайте ги, за да направите правилата по подразбиране на форума достъпни.',
'ACP_BOARDRULES_COPY_RULESET' => 'Копирай набора от правила на езика',
'ACP_BOARDRULES_COPY_RULESET_EXPLAIN' => 'Копира всяка категория и правило в <strong>%s</strong>. Копираните правила се добавят след съществуващите, а пълният целеви набор остава чернова, докато не го публикувате.',
'ACP_BOARDRULES_COPY_RULESET_EXPLAIN' => 'Копира всяка категория и правило в <strong>%s</strong>. Копираните правила се добавят след съществуващите, а пълният целеви набор ще бъде зададен като чернова, докато не го публикувате.',
'ACP_BOARDRULES_COPY_APPEND' => 'Добави към съществуващите правила',
'ACP_BOARDRULES_COPY_APPEND_EXPLAIN' => array(
1 => 'В момента целта съдържа %d правило. То ще остане непроменено, а копираните правила ще бъдат добавени след него. Конфликтните копирани котви ще получат цифров суфикс.',
Expand Down Expand Up @@ -136,10 +136,8 @@
'ACP_RULE_MESSAGE_EXPLAIN' => 'Съобщението на Правилото се показва на страницата на правилата за всяко правило (Категориите не показват съобщение за правилото).',
'ACP_RULE_MESSAGE_DISABLED' => 'Тази категория съдържа правила, които текстовият редактор е забранил.',
'ACP_ADD_RULE' => 'Създай ново правило',
'ACP_DELETE_RULE_CONFIRM' => array(
0 => 'Сигурни ли сте, че искате да изтриете това правило?',
1 => 'Сигурни ли сте, че искате да изтриете това правило?<br />Предупреждение: Премахвайки категория правила, ще премахнете и всички правила, които тя съдържа.',
),
'ACP_DELETE_RULE_CONFIRM' => 'Сигурни ли сте, че искате да изтриете това правило?',
'ACP_DELETE_RULE_CATEGORY_CONFIRM' => 'Сигурни ли сте, че искате да изтриете това правило?<br />Предупреждение: Премахвайки категория правила, ще премахнете и всички правила, които тя съдържа.',
'ACP_RULE_ADDED' => 'Правилото успешно добавено.',
'ACP_RULE_DELETED' => 'Правилото успешно изтрито.',
'ACP_RULE_EDITED' => 'Правилото успешно редактирано.',
Expand Down
8 changes: 3 additions & 5 deletions language/cs/boardrules_acp.php
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@
'ACP_BOARDRULES_DRAFT_NOTICE' => 'Tato pravidla nejsou pro uživatele viditelná. Uživatelé nyní vidí pravidla ve výchozím jazyce fóra.',
'ACP_BOARDRULES_DRAFT_DEFAULT_NOTICE' => 'Tato pravidla nejsou pro uživatele viditelná. Zveřejněte je, aby byla výchozí pravidla fóra dostupná.',
'ACP_BOARDRULES_COPY_RULESET' => 'Kopírovat jazykovou sadu pravidel',
'ACP_BOARDRULES_COPY_RULESET_EXPLAIN' => 'Zkopíruje všechny kategorie a pravidla do <strong>%s</strong>. Zkopírovaná pravidla se přidají za stávající pravidla a celá cílová sada zůstane konceptem, dokud ji nezveřejníte.',
'ACP_BOARDRULES_COPY_RULESET_EXPLAIN' => 'Zkopíruje všechny kategorie a pravidla do <strong>%s</strong>. Zkopírovaná pravidla se přidají za stávající pravidla a celá cílová sada bude nastavena jako koncept, dokud ji nezveřejníte.',
'ACP_BOARDRULES_COPY_APPEND' => 'Přidat ke stávajícím pravidlům',
'ACP_BOARDRULES_COPY_APPEND_EXPLAIN' => array(
1 => 'Cíl nyní obsahuje %d pravidlo. Zůstane beze změny a zkopírovaná pravidla budou přidána za něj. Konfliktní zkopírované odkazy dostanou číselnou příponu.',
Expand Down Expand Up @@ -140,10 +140,8 @@
'ACP_RULE_MESSAGE_EXPLAIN' => 'Obsah pravidla je zobrazen u každého z pravidel (toto pole je u kategorií ignorováno).',
'ACP_RULE_MESSAGE_DISABLED' => 'Toto je kategorie pravidel, proto není možné pravidlo upravovat.',
'ACP_ADD_RULE' => 'Vytvořit nové pravidlo',
'ACP_DELETE_RULE_CONFIRM' => array(
0 => 'Opravdu chcete smazat toto pravidlo?',
1 => 'Opravdu chcete smazat toto pravidlo?<br />Varování: Smazáním kategorie odstraníte také všechna vnořená pravidla.',
),
'ACP_DELETE_RULE_CONFIRM' => 'Opravdu chcete smazat toto pravidlo?',
'ACP_DELETE_RULE_CATEGORY_CONFIRM' => 'Opravdu chcete smazat toto pravidlo?<br />Varování: Smazáním kategorie odstraníte také všechna vnořená pravidla.',
'ACP_RULE_ADDED' => 'Pravidlo úspěšně přidáno.',
'ACP_RULE_DELETED' => 'Pravidlo úspěšně odstraněno.',
'ACP_RULE_EDITED' => 'Pravidlo úspěšně upraveno.',
Expand Down
Loading