@@ -24,55 +24,55 @@ |
||
24 | 24 | * Class LifespansChartModule |
25 | 25 | */ |
26 | 26 | class LifespansChartModule extends AbstractModule implements ModuleChartInterface { |
27 | - /** |
|
28 | - * How should this module be labelled on tabs, menus, etc.? |
|
29 | - * |
|
30 | - * @return string |
|
31 | - */ |
|
32 | - public function getTitle() { |
|
33 | - return /* I18N: Name of a module/chart */ I18N::translate('Lifespans'); |
|
34 | - } |
|
27 | + /** |
|
28 | + * How should this module be labelled on tabs, menus, etc.? |
|
29 | + * |
|
30 | + * @return string |
|
31 | + */ |
|
32 | + public function getTitle() { |
|
33 | + return /* I18N: Name of a module/chart */ I18N::translate('Lifespans'); |
|
34 | + } |
|
35 | 35 | |
36 | - /** |
|
37 | - * A sentence describing what this module does. |
|
38 | - * |
|
39 | - * @return string |
|
40 | - */ |
|
41 | - public function getDescription() { |
|
42 | - return /* I18N: Description of the “LifespansChart” module */ I18N::translate('A chart of individuals’ lifespans.'); |
|
43 | - } |
|
36 | + /** |
|
37 | + * A sentence describing what this module does. |
|
38 | + * |
|
39 | + * @return string |
|
40 | + */ |
|
41 | + public function getDescription() { |
|
42 | + return /* I18N: Description of the “LifespansChart” module */ I18N::translate('A chart of individuals’ lifespans.'); |
|
43 | + } |
|
44 | 44 | |
45 | - /** |
|
46 | - * What is the default access level for this module? |
|
47 | - * |
|
48 | - * Some modules are aimed at admins or managers, and are not generally shown to users. |
|
49 | - * |
|
50 | - * @return int |
|
51 | - */ |
|
52 | - public function defaultAccessLevel() { |
|
53 | - return Auth::PRIV_PRIVATE; |
|
54 | - } |
|
45 | + /** |
|
46 | + * What is the default access level for this module? |
|
47 | + * |
|
48 | + * Some modules are aimed at admins or managers, and are not generally shown to users. |
|
49 | + * |
|
50 | + * @return int |
|
51 | + */ |
|
52 | + public function defaultAccessLevel() { |
|
53 | + return Auth::PRIV_PRIVATE; |
|
54 | + } |
|
55 | 55 | |
56 | - /** |
|
57 | - * Return a menu item for this chart. |
|
58 | - * |
|
59 | - * @return Menu|null |
|
60 | - */ |
|
61 | - public function getChartMenu(Individual $individual) { |
|
62 | - return new Menu( |
|
63 | - $this->getTitle(), |
|
64 | - 'lifespan.php', |
|
65 | - 'menu-chart-lifespan', |
|
66 | - array('rel' => 'nofollow') |
|
67 | - ); |
|
68 | - } |
|
56 | + /** |
|
57 | + * Return a menu item for this chart. |
|
58 | + * |
|
59 | + * @return Menu|null |
|
60 | + */ |
|
61 | + public function getChartMenu(Individual $individual) { |
|
62 | + return new Menu( |
|
63 | + $this->getTitle(), |
|
64 | + 'lifespan.php', |
|
65 | + 'menu-chart-lifespan', |
|
66 | + array('rel' => 'nofollow') |
|
67 | + ); |
|
68 | + } |
|
69 | 69 | |
70 | - /** |
|
71 | - * Return a menu item for this chart - for use in individual boxes. |
|
72 | - * |
|
73 | - * @return Menu|null |
|
74 | - */ |
|
75 | - public function getBoxChartMenu(Individual $individual) { |
|
76 | - return null; |
|
77 | - } |
|
70 | + /** |
|
71 | + * Return a menu item for this chart - for use in individual boxes. |
|
72 | + * |
|
73 | + * @return Menu|null |
|
74 | + */ |
|
75 | + public function getBoxChartMenu(Individual $individual) { |
|
76 | + return null; |
|
77 | + } |
|
78 | 78 | } |
@@ -23,13 +23,15 @@ discard block |
||
23 | 23 | /** |
24 | 24 | * Class LifespansChartModule |
25 | 25 | */ |
26 | -class LifespansChartModule extends AbstractModule implements ModuleChartInterface { |
|
26 | +class LifespansChartModule extends AbstractModule implements ModuleChartInterface |
|
27 | +{ |
|
27 | 28 | /** |
28 | 29 | * How should this module be labelled on tabs, menus, etc.? |
29 | 30 | * |
30 | 31 | * @return string |
31 | 32 | */ |
32 | - public function getTitle() { |
|
33 | + public function getTitle() |
|
34 | + { |
|
33 | 35 | return /* I18N: Name of a module/chart */ I18N::translate('Lifespans'); |
34 | 36 | } |
35 | 37 | |
@@ -38,7 +40,8 @@ discard block |
||
38 | 40 | * |
39 | 41 | * @return string |
40 | 42 | */ |
41 | - public function getDescription() { |
|
43 | + public function getDescription() |
|
44 | + { |
|
42 | 45 | return /* I18N: Description of the “LifespansChart” module */ I18N::translate('A chart of individuals’ lifespans.'); |
43 | 46 | } |
44 | 47 | |
@@ -49,7 +52,8 @@ discard block |
||
49 | 52 | * |
50 | 53 | * @return int |
51 | 54 | */ |
52 | - public function defaultAccessLevel() { |
|
55 | + public function defaultAccessLevel() |
|
56 | + { |
|
53 | 57 | return Auth::PRIV_PRIVATE; |
54 | 58 | } |
55 | 59 | |
@@ -58,7 +62,8 @@ discard block |
||
58 | 62 | * |
59 | 63 | * @return Menu|null |
60 | 64 | */ |
61 | - public function getChartMenu(Individual $individual) { |
|
65 | + public function getChartMenu(Individual $individual) |
|
66 | + { |
|
62 | 67 | return new Menu( |
63 | 68 | $this->getTitle(), |
64 | 69 | 'lifespan.php', |
@@ -72,7 +77,8 @@ discard block |
||
72 | 77 | * |
73 | 78 | * @return Menu|null |
74 | 79 | */ |
75 | - public function getBoxChartMenu(Individual $individual) { |
|
80 | + public function getBoxChartMenu(Individual $individual) |
|
81 | + { |
|
76 | 82 | return null; |
77 | 83 | } |
78 | 84 | } |
@@ -19,100 +19,100 @@ |
||
19 | 19 | * Temporary class to migrate to Symfony-based sessions, which need PHP 5.4. |
20 | 20 | */ |
21 | 21 | class Session { |
22 | - /** |
|
23 | - * Start a session |
|
24 | - * |
|
25 | - * @param array $config |
|
26 | - */ |
|
27 | - public static function start(array $config = array()) { |
|
28 | - $default_config = array( |
|
29 | - 'use_cookies' => 1, |
|
30 | - 'name' => 'WT_SESSION', |
|
31 | - 'cookie_lifetime' => 0, |
|
32 | - 'gc_maxlifetime' => 7200, |
|
33 | - 'gc_probability' => 1, |
|
34 | - 'gc_divisor' => 100, |
|
35 | - 'cookie_path' => '', |
|
36 | - 'cookie_httponly' => true, |
|
37 | - ); |
|
38 | - session_register_shutdown(); |
|
39 | - foreach ($config + $default_config as $key => $value) { |
|
40 | - ini_set('session.' . $key, $value); |
|
41 | - } |
|
42 | - session_start(); |
|
43 | - } |
|
22 | + /** |
|
23 | + * Start a session |
|
24 | + * |
|
25 | + * @param array $config |
|
26 | + */ |
|
27 | + public static function start(array $config = array()) { |
|
28 | + $default_config = array( |
|
29 | + 'use_cookies' => 1, |
|
30 | + 'name' => 'WT_SESSION', |
|
31 | + 'cookie_lifetime' => 0, |
|
32 | + 'gc_maxlifetime' => 7200, |
|
33 | + 'gc_probability' => 1, |
|
34 | + 'gc_divisor' => 100, |
|
35 | + 'cookie_path' => '', |
|
36 | + 'cookie_httponly' => true, |
|
37 | + ); |
|
38 | + session_register_shutdown(); |
|
39 | + foreach ($config + $default_config as $key => $value) { |
|
40 | + ini_set('session.' . $key, $value); |
|
41 | + } |
|
42 | + session_start(); |
|
43 | + } |
|
44 | 44 | |
45 | - /** |
|
46 | - * Read a value from the session |
|
47 | - * |
|
48 | - * @param string $name |
|
49 | - * @param mixed $default |
|
50 | - * |
|
51 | - * @return mixed |
|
52 | - */ |
|
53 | - public static function get($name, $default = null) { |
|
54 | - if (isset($_SESSION[$name])) { |
|
55 | - return $_SESSION[$name]; |
|
56 | - } else { |
|
57 | - return $default; |
|
58 | - } |
|
59 | - } |
|
45 | + /** |
|
46 | + * Read a value from the session |
|
47 | + * |
|
48 | + * @param string $name |
|
49 | + * @param mixed $default |
|
50 | + * |
|
51 | + * @return mixed |
|
52 | + */ |
|
53 | + public static function get($name, $default = null) { |
|
54 | + if (isset($_SESSION[$name])) { |
|
55 | + return $_SESSION[$name]; |
|
56 | + } else { |
|
57 | + return $default; |
|
58 | + } |
|
59 | + } |
|
60 | 60 | |
61 | - /** |
|
62 | - * Write a value to the session |
|
63 | - * |
|
64 | - * @param string $name |
|
65 | - * @param mixed $value |
|
66 | - */ |
|
67 | - public static function put($name, $value) { |
|
68 | - $_SESSION[$name] = $value; |
|
69 | - } |
|
61 | + /** |
|
62 | + * Write a value to the session |
|
63 | + * |
|
64 | + * @param string $name |
|
65 | + * @param mixed $value |
|
66 | + */ |
|
67 | + public static function put($name, $value) { |
|
68 | + $_SESSION[$name] = $value; |
|
69 | + } |
|
70 | 70 | |
71 | - /** |
|
72 | - * Remove a value from the session |
|
73 | - * |
|
74 | - * @param string $name |
|
75 | - */ |
|
76 | - public static function forget($name) { |
|
77 | - unset($_SESSION[$name]); |
|
78 | - } |
|
71 | + /** |
|
72 | + * Remove a value from the session |
|
73 | + * |
|
74 | + * @param string $name |
|
75 | + */ |
|
76 | + public static function forget($name) { |
|
77 | + unset($_SESSION[$name]); |
|
78 | + } |
|
79 | 79 | |
80 | - /** |
|
81 | - * Does a session variable exist? |
|
82 | - * |
|
83 | - * @param string $name |
|
84 | - * |
|
85 | - * @return bool |
|
86 | - */ |
|
87 | - public static function has($name) { |
|
88 | - return isset($_SESSION[$name]); |
|
89 | - } |
|
80 | + /** |
|
81 | + * Does a session variable exist? |
|
82 | + * |
|
83 | + * @param string $name |
|
84 | + * |
|
85 | + * @return bool |
|
86 | + */ |
|
87 | + public static function has($name) { |
|
88 | + return isset($_SESSION[$name]); |
|
89 | + } |
|
90 | 90 | |
91 | - /** |
|
92 | - * Remove all stored data from the session. |
|
93 | - */ |
|
94 | - public static function clear() { |
|
95 | - $_SESSION = array(); |
|
96 | - } |
|
91 | + /** |
|
92 | + * Remove all stored data from the session. |
|
93 | + */ |
|
94 | + public static function clear() { |
|
95 | + $_SESSION = array(); |
|
96 | + } |
|
97 | 97 | |
98 | - /** |
|
99 | - * After any change in authentication level, we should use a new session ID. |
|
100 | - * |
|
101 | - * @param bool $destroy |
|
102 | - */ |
|
103 | - public static function regenerate($destroy = false) { |
|
104 | - if ($destroy) { |
|
105 | - self::clear(); |
|
106 | - } |
|
107 | - session_regenerate_id($destroy); |
|
108 | - } |
|
98 | + /** |
|
99 | + * After any change in authentication level, we should use a new session ID. |
|
100 | + * |
|
101 | + * @param bool $destroy |
|
102 | + */ |
|
103 | + public static function regenerate($destroy = false) { |
|
104 | + if ($destroy) { |
|
105 | + self::clear(); |
|
106 | + } |
|
107 | + session_regenerate_id($destroy); |
|
108 | + } |
|
109 | 109 | |
110 | - /** |
|
111 | - * Set an explicit session ID. Typically used for search robots. |
|
112 | - * |
|
113 | - * @param string $id |
|
114 | - */ |
|
115 | - public static function setId($id) { |
|
116 | - session_id($id); |
|
117 | - } |
|
110 | + /** |
|
111 | + * Set an explicit session ID. Typically used for search robots. |
|
112 | + * |
|
113 | + * @param string $id |
|
114 | + */ |
|
115 | + public static function setId($id) { |
|
116 | + session_id($id); |
|
117 | + } |
|
118 | 118 | } |
@@ -18,13 +18,15 @@ discard block |
||
18 | 18 | /** |
19 | 19 | * Temporary class to migrate to Symfony-based sessions, which need PHP 5.4. |
20 | 20 | */ |
21 | -class Session { |
|
21 | +class Session |
|
22 | +{ |
|
22 | 23 | /** |
23 | 24 | * Start a session |
24 | 25 | * |
25 | 26 | * @param array $config |
26 | 27 | */ |
27 | - public static function start(array $config = array()) { |
|
28 | + public static function start(array $config = array()) |
|
29 | + { |
|
28 | 30 | $default_config = array( |
29 | 31 | 'use_cookies' => 1, |
30 | 32 | 'name' => 'WT_SESSION', |
@@ -50,7 +52,8 @@ discard block |
||
50 | 52 | * |
51 | 53 | * @return mixed |
52 | 54 | */ |
53 | - public static function get($name, $default = null) { |
|
55 | + public static function get($name, $default = null) |
|
56 | + { |
|
54 | 57 | if (isset($_SESSION[$name])) { |
55 | 58 | return $_SESSION[$name]; |
56 | 59 | } else { |
@@ -64,7 +67,8 @@ discard block |
||
64 | 67 | * @param string $name |
65 | 68 | * @param mixed $value |
66 | 69 | */ |
67 | - public static function put($name, $value) { |
|
70 | + public static function put($name, $value) |
|
71 | + { |
|
68 | 72 | $_SESSION[$name] = $value; |
69 | 73 | } |
70 | 74 | |
@@ -73,7 +77,8 @@ discard block |
||
73 | 77 | * |
74 | 78 | * @param string $name |
75 | 79 | */ |
76 | - public static function forget($name) { |
|
80 | + public static function forget($name) |
|
81 | + { |
|
77 | 82 | unset($_SESSION[$name]); |
78 | 83 | } |
79 | 84 | |
@@ -84,14 +89,16 @@ discard block |
||
84 | 89 | * |
85 | 90 | * @return bool |
86 | 91 | */ |
87 | - public static function has($name) { |
|
92 | + public static function has($name) |
|
93 | + { |
|
88 | 94 | return isset($_SESSION[$name]); |
89 | 95 | } |
90 | 96 | |
91 | 97 | /** |
92 | 98 | * Remove all stored data from the session. |
93 | 99 | */ |
94 | - public static function clear() { |
|
100 | + public static function clear() |
|
101 | + { |
|
95 | 102 | $_SESSION = array(); |
96 | 103 | } |
97 | 104 | |
@@ -100,7 +107,8 @@ discard block |
||
100 | 107 | * |
101 | 108 | * @param bool $destroy |
102 | 109 | */ |
103 | - public static function regenerate($destroy = false) { |
|
110 | + public static function regenerate($destroy = false) |
|
111 | + { |
|
104 | 112 | if ($destroy) { |
105 | 113 | self::clear(); |
106 | 114 | } |
@@ -112,7 +120,8 @@ discard block |
||
112 | 120 | * |
113 | 121 | * @param string $id |
114 | 122 | */ |
115 | - public static function setId($id) { |
|
123 | + public static function setId($id) |
|
124 | + { |
|
116 | 125 | session_id($id); |
117 | 126 | } |
118 | 127 | } |
@@ -25,511 +25,511 @@ |
||
25 | 25 | * Generate lists for indilist.php and famlist.php |
26 | 26 | */ |
27 | 27 | class QueryName { |
28 | - /** |
|
29 | - * Get a list of initial letters, for lists of names. |
|
30 | - * |
|
31 | - * @param string $locale Return the alphabet for this locale |
|
32 | - * |
|
33 | - * @return string[] |
|
34 | - */ |
|
35 | - private static function getAlphabetForLocale($locale) { |
|
36 | - switch ($locale) { |
|
37 | - case 'ar': |
|
38 | - return array( |
|
39 | - 'ا', 'ب', 'ت', 'ث', 'ج', 'ح', 'خ', 'د', 'ذ', 'ر', 'ز', 'س', 'ش', 'ص', 'ض', 'ط', 'ظ', 'ع', 'غ', 'ف', 'ق', 'ك', 'ل', 'م', 'ن', 'ه', 'و', 'ي', 'آ', 'ة', 'ى', 'ی', |
|
40 | - ); |
|
41 | - case 'cs': |
|
42 | - return array( |
|
43 | - 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'CH', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', |
|
44 | - ); |
|
45 | - case 'da': |
|
46 | - case 'nb': |
|
47 | - case 'nn': |
|
48 | - return array( |
|
49 | - 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'Æ', 'Ø', 'Å', |
|
50 | - ); |
|
51 | - case 'el': |
|
52 | - return array( |
|
53 | - 'Α', 'Β', 'Γ', 'Δ', 'Ε', 'Ζ', 'Η', 'Θ', 'Ι', 'Κ', 'Λ', 'Μ', 'Ν', 'Ξ', 'Ο', 'Π', 'Ρ', 'Σ', 'Τ', 'Υ', 'Φ', 'Χ', 'Ψ', 'Ω', |
|
54 | - ); |
|
55 | - case 'es': |
|
56 | - return array( |
|
57 | - 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'Ñ', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', |
|
58 | - ); |
|
59 | - case 'et': |
|
60 | - return array( |
|
61 | - 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'Š', 'Z', 'Ž', 'T', 'U', 'V', 'W', 'Õ', 'Ä', 'Ö', 'Ü', 'X', 'Y', |
|
62 | - ); |
|
63 | - case 'fi': |
|
64 | - case 'sv': |
|
65 | - return array( |
|
66 | - 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'Å', 'Ä', 'Ö', |
|
67 | - ); |
|
68 | - case 'he': |
|
69 | - return array( |
|
70 | - 'א', 'ב', 'ג', 'ד', 'ה', 'ו', 'ז', 'ח', 'ט', 'י', 'כ', 'ל', 'מ', 'נ', 'ס', 'ע', 'פ', 'צ', 'ק', 'ר', 'ש', 'ת', |
|
71 | - ); |
|
72 | - case 'hu': |
|
73 | - return array( |
|
74 | - 'A', 'B', 'C', 'CS', 'D', 'DZ', 'DZS', 'E', 'F', 'G', 'GY', 'H', 'I', 'J', 'K', 'L', 'LY', 'M', 'N', 'NY', 'O', 'Ö', 'P', 'Q', 'R', 'S', 'SZ', 'T', 'TY', 'U', 'Ü', 'V', 'W', 'X', 'Y', 'Z', 'ZS', |
|
75 | - ); |
|
76 | - case 'lt': |
|
77 | - return array( |
|
78 | - 'A', 'Ą', 'B', 'C', 'Č', 'D', 'E', 'Ę', 'Ė', 'F', 'G', 'H', 'I', 'Y', 'Į', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'R', 'S', 'Š', 'T', 'U', 'Ų', 'Ū', 'V', 'Z', 'Ž', |
|
79 | - ); |
|
80 | - case 'nl': |
|
81 | - return array( |
|
82 | - 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'IJ', |
|
83 | - ); |
|
84 | - case 'pl': |
|
85 | - return array( |
|
86 | - 'A', 'B', 'C', 'Ć', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'Ł', 'M', 'N', 'O', 'Ó', 'P', 'Q', 'R', 'S', 'Ś', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'Ź', 'Ż', |
|
87 | - ); |
|
88 | - case 'ro': |
|
89 | - return array( |
|
90 | - 'A', 'Ă', 'Â', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'Î', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'Ş', 'T', 'Ţ', 'U', 'V', 'W', 'X', 'Y', 'Z', |
|
91 | - ); |
|
92 | - case 'ru': |
|
93 | - return array( |
|
94 | - 'А', 'Б', 'В', 'Г', 'Д', 'Е', 'Ё', 'Ж', 'З', 'И', 'Й', 'К', 'Л', 'М', 'Н', 'О', 'П', 'Р', 'С', 'Т', 'У', 'Ф', 'Х', 'Ц', 'Ч', 'Ш', 'Щ', 'Ъ', 'Ы', 'Ь', 'Э', 'Ю', 'Я', |
|
95 | - ); |
|
96 | - case 'sk': |
|
97 | - return array( |
|
98 | - 'A', 'Á', 'Ä', 'B', 'C', 'Č', 'D', 'Ď', 'E', 'É', 'F', 'G', 'H', 'I', 'Í', 'J', 'K', 'L', 'Ľ', 'Ĺ', 'M', 'N', 'Ň', 'O', 'Ó', 'Ô', 'P', 'Q', 'R', 'Ŕ', 'S', 'Š', 'T', 'Ť', 'U', 'Ú', 'V', 'W', 'X', 'Y', 'Ý', 'Z', 'Ž', |
|
99 | - ); |
|
100 | - case 'sl': |
|
101 | - return array( |
|
102 | - 'A', 'B', 'C', 'Č', 'Ć', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'Š', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'Ž', |
|
103 | - ); |
|
104 | - case 'sr': |
|
105 | - return array( |
|
106 | - 'A', 'B', 'C', 'Č', 'Ć', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'Š', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'Ž', |
|
107 | - ); |
|
108 | - case 'tr': |
|
109 | - return array( |
|
110 | - 'A', 'B', 'C', 'Ç', 'D', 'E', 'F', 'G', 'Ğ', 'H', 'I', 'İ', 'J', 'K', 'L', 'M', 'N', 'O', 'Ö', 'P', 'R', 'S', 'Ş', 'T', 'U', 'Ü', 'V', 'Y', 'Z', |
|
111 | - ); |
|
112 | - default: |
|
113 | - return array( |
|
114 | - 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', |
|
115 | - ); |
|
116 | - } |
|
117 | - } |
|
118 | - |
|
119 | - /** |
|
120 | - * Get the initial letter of a name, taking care of multi-letter sequences and equivalences. |
|
121 | - * |
|
122 | - * @param string $name |
|
123 | - * |
|
124 | - * @return string |
|
125 | - */ |
|
126 | - public static function initialLetter($name) { |
|
127 | - $name = I18N::strtoupper($name); |
|
128 | - switch (WT_LOCALE) { |
|
129 | - case 'cs': |
|
130 | - if (substr($name, 0, 2) == 'CH') { |
|
131 | - return 'CH'; |
|
132 | - } |
|
133 | - break; |
|
134 | - case 'da': |
|
135 | - case 'nb': |
|
136 | - case 'nn': |
|
137 | - if (substr($name, 0, 2) == 'AA') { |
|
138 | - return 'Å'; |
|
139 | - } |
|
140 | - break; |
|
141 | - case 'hu': |
|
142 | - if (substr($name, 0, 2) == 'CS') { |
|
143 | - return 'CS'; |
|
144 | - } elseif (substr($name, 0, 3) == 'DZS') { |
|
145 | - return 'DZS'; |
|
146 | - } elseif (substr($name, 0, 2) == 'DZ') { |
|
147 | - return 'DZ'; |
|
148 | - } elseif (substr($name, 0, 2) == 'GY') { |
|
149 | - return 'GY'; |
|
150 | - } elseif (substr($name, 0, 2) == 'LY') { |
|
151 | - return 'LY'; |
|
152 | - } elseif (substr($name, 0, 2) == 'NY') { |
|
153 | - return 'NY'; |
|
154 | - } elseif (substr($name, 0, 2) == 'SZ') { |
|
155 | - return 'SZ'; |
|
156 | - } elseif (substr($name, 0, 2) == 'TY') { |
|
157 | - return 'TY'; |
|
158 | - } elseif (substr($name, 0, 2) == 'ZS') { |
|
159 | - return 'ZS'; |
|
160 | - } |
|
161 | - break; |
|
162 | - case 'nl': |
|
163 | - if (substr($name, 0, 2) == 'IJ') { |
|
164 | - return 'IJ'; |
|
165 | - } |
|
166 | - break; |
|
167 | - } |
|
168 | - // No special rules - just take the first character |
|
169 | - return mb_substr($name, 0, 1); |
|
170 | - } |
|
171 | - |
|
172 | - /** |
|
173 | - * Generate SQL to match a given letter, taking care of cases that |
|
174 | - * are not covered by the collation setting. |
|
175 | - * |
|
176 | - * We must consider: |
|
177 | - * potential substrings, such as Czech "CH" and "C" |
|
178 | - * equivalent letters, such as Danish "AA" and "Å" |
|
179 | - * |
|
180 | - * We COULD write something that handles all languages generically, |
|
181 | - * but its performance would most likely be poor. |
|
182 | - * |
|
183 | - * For languages that don't appear in this list, we could write |
|
184 | - * simpler versions of the surnameAlpha() and givenAlpha() functions, |
|
185 | - * but it gives no noticable improvement in performance. |
|
186 | - * |
|
187 | - * @param string $field |
|
188 | - * @param string $letter |
|
189 | - * |
|
190 | - * @return string |
|
191 | - */ |
|
192 | - private static function getInitialSql($field, $letter) { |
|
193 | - switch (WT_LOCALE) { |
|
194 | - case 'cs': |
|
195 | - switch ($letter) { |
|
196 | - case 'C': return $field . " LIKE 'C%' COLLATE " . I18N::collation() . " AND " . $field . " NOT LIKE 'CH%' COLLATE " . I18N::collation(); |
|
197 | - } |
|
198 | - break; |
|
199 | - case 'da': |
|
200 | - case 'nb': |
|
201 | - case 'nn': |
|
202 | - switch ($letter) { |
|
203 | - // AA gets listed under Å |
|
204 | - case 'A': return $field . " LIKE 'A%' COLLATE " . I18N::collation() . " AND " . $field . " NOT LIKE 'AA%' COLLATE " . I18N::collation(); |
|
205 | - case 'Å': return "(" . $field . " LIKE 'Å%' COLLATE " . I18N::collation() . " OR " . $field . " LIKE 'AA%' COLLATE " . I18N::collation() . ")"; |
|
206 | - } |
|
207 | - break; |
|
208 | - case 'hu': |
|
209 | - switch ($letter) { |
|
210 | - case 'C': return $field . " LIKE 'C%' COLLATE " . I18N::collation() . " AND " . $field . " NOT LIKE 'CS%' COLLATE " . I18N::collation(); |
|
211 | - case 'D': return $field . " LIKE 'D%' COLLATE " . I18N::collation() . " AND " . $field . " NOT LIKE 'DZ%' COLLATE " . I18N::collation(); |
|
212 | - case 'DZ': return $field . " LIKE 'DZ%' COLLATE " . I18N::collation() . " AND " . $field . " NOT LIKE 'DZS%' COLLATE " . I18N::collation(); |
|
213 | - case 'G': return $field . " LIKE 'G%' COLLATE " . I18N::collation() . " AND " . $field . " NOT LIKE 'GY%' COLLATE " . I18N::collation(); |
|
214 | - case 'L': return $field . " LIKE 'L%' COLLATE " . I18N::collation() . " AND " . $field . " NOT LIKE 'LY%' COLLATE " . I18N::collation(); |
|
215 | - case 'N': return $field . " LIKE 'N%' COLLATE " . I18N::collation() . " AND " . $field . " NOT LIKE 'NY%' COLLATE " . I18N::collation(); |
|
216 | - case 'S': return $field . " LIKE 'S%' COLLATE " . I18N::collation() . " AND " . $field . " NOT LIKE 'SZ%' COLLATE " . I18N::collation(); |
|
217 | - case 'T': return $field . " LIKE 'T%' COLLATE " . I18N::collation() . " AND " . $field . " NOT LIKE 'TY%' COLLATE " . I18N::collation(); |
|
218 | - case 'Z': return $field . " LIKE 'Z%' COLLATE " . I18N::collation() . " AND " . $field . " NOT LIKE 'ZS%' COLLATE " . I18N::collation(); |
|
219 | - } |
|
220 | - break; |
|
221 | - case 'nl': |
|
222 | - switch ($letter) { |
|
223 | - case 'I': return $field . " LIKE 'I%' COLLATE " . I18N::collation() . " AND " . $field . " NOT LIKE 'IJ%' COLLATE " . I18N::collation(); |
|
224 | - } |
|
225 | - break; |
|
226 | - } |
|
227 | - |
|
228 | - // Easy cases: the MySQL collation rules take care of it |
|
229 | - return "$field LIKE CONCAT('@'," . Database::quote($letter) . ",'%') COLLATE " . I18N::collation() . " ESCAPE '@'"; |
|
230 | - } |
|
231 | - |
|
232 | - /** |
|
233 | - * Get a list of initial surname letters for indilist.php and famlist.php |
|
234 | - * |
|
235 | - * @param Tree $tree Find surnames from this tree |
|
236 | - * @param bool $marnm if set, include married names |
|
237 | - * @param bool $fams if set, only consider individuals with FAMS records |
|
238 | - * @param bool $totals if set, count the number of names beginning with each letter |
|
239 | - * |
|
240 | - * @return int[] |
|
241 | - */ |
|
242 | - public static function surnameAlpha(Tree $tree, $marnm, $fams, $totals = true) { |
|
243 | - $alphas = array(); |
|
244 | - |
|
245 | - $sql = |
|
246 | - "SELECT COUNT(n_id)" . |
|
247 | - " FROM `##name` " . |
|
248 | - ($fams ? " JOIN `##link` ON (n_id=l_from AND n_file=l_file AND l_type='FAMS') " : "") . |
|
249 | - " WHERE n_file=" . $tree->getTreeId() . |
|
250 | - ($marnm ? "" : " AND n_type!='_MARNM'"); |
|
251 | - |
|
252 | - // Fetch all the letters in our alphabet, whether or not there |
|
253 | - // are any names beginning with that letter. It looks better to |
|
254 | - // show the full alphabet, rather than omitting rare letters such as X |
|
255 | - foreach (self::getAlphabetForLocale(WT_LOCALE) as $letter) { |
|
256 | - $count = 1; |
|
257 | - if ($totals) { |
|
258 | - $count = Database::prepare($sql . " AND " . self::getInitialSql('n_surn', $letter))->fetchOne(); |
|
259 | - } |
|
260 | - $alphas[$letter] = $count; |
|
261 | - } |
|
262 | - |
|
263 | - // Now fetch initial letters that are not in our alphabet, |
|
264 | - // including "@" (for "@N.N.") and "" for no surname. |
|
265 | - $sql = |
|
266 | - "SELECT initial, count FROM (SELECT UPPER(LEFT(n_surn, 1)) AS initial, COUNT(n_id) AS count" . |
|
267 | - " FROM `##name` " . |
|
268 | - ($fams ? " JOIN `##link` ON n_id = l_from AND n_file = l_file AND l_type = 'FAMS' " : "") . |
|
269 | - " WHERE n_file = :tree_id AND n_surn <> ''" . |
|
270 | - ($marnm ? "" : " AND n_type != '_MARNM'"); |
|
271 | - |
|
272 | - $args = array( |
|
273 | - 'tree_id' => $tree->getTreeId(), |
|
274 | - ); |
|
275 | - |
|
276 | - foreach (self::getAlphabetForLocale(WT_LOCALE) as $n => $letter) { |
|
277 | - $sql .= " AND n_surn COLLATE :collate_" . $n . " NOT LIKE :letter_" . $n; |
|
278 | - $args['collate_' . $n] = I18N::collation(); |
|
279 | - $args['letter_' . $n] = $letter . '%'; |
|
280 | - } |
|
281 | - $sql .= " GROUP BY UPPER(LEFT(n_surn, 1))) AS subquery ORDER BY initial = '', initial = '@', initial"; |
|
282 | - foreach (Database::prepare($sql)->execute($args)->fetchAssoc() as $alpha => $count) { |
|
283 | - $alphas[$alpha] = $count; |
|
284 | - } |
|
285 | - |
|
286 | - // Names with no surname |
|
287 | - $sql = |
|
288 | - "SELECT COUNT(n_id)" . |
|
289 | - " FROM `##name` " . |
|
290 | - ($fams ? " JOIN `##link` ON n_id = l_from AND n_file = l_file AND l_type = 'FAMS' " : "") . |
|
291 | - " WHERE n_file = :tree_id AND n_surn = ''" . |
|
292 | - ($marnm ? "" : " AND n_type != '_MARNM'"); |
|
293 | - |
|
294 | - $args = array( |
|
295 | - 'tree_id' => $tree->getTreeId(), |
|
296 | - ); |
|
297 | - |
|
298 | - $num_none = Database::prepare($sql)->execute($args)->fetchOne(); |
|
299 | - if ($num_none) { |
|
300 | - // Special code to indicate "no surname" |
|
301 | - $alphas[','] = $num_none; |
|
302 | - } |
|
303 | - |
|
304 | - return $alphas; |
|
305 | - } |
|
306 | - |
|
307 | - /** |
|
308 | - * Get a list of initial given name letters for indilist.php and famlist.php |
|
309 | - * |
|
310 | - * @param Tree $tree Find names in this tree |
|
311 | - * @param string $surn if set, only consider people with this surname |
|
312 | - * @param string $salpha if set, only consider surnames starting with this letter |
|
313 | - * @param bool $marnm if set, include married names |
|
314 | - * @param bool $fams if set, only consider individuals with FAMS records |
|
315 | - * |
|
316 | - * @return int[] |
|
317 | - */ |
|
318 | - public static function givenAlpha(Tree $tree, $surn, $salpha, $marnm, $fams) { |
|
319 | - $alphas = array(); |
|
320 | - |
|
321 | - $sql = |
|
322 | - "SELECT COUNT(DISTINCT n_id)" . |
|
323 | - " FROM `##name`" . |
|
324 | - ($fams ? " JOIN `##link` ON (n_id=l_from AND n_file=l_file AND l_type='FAMS') " : "") . |
|
325 | - " WHERE n_file=" . $tree->getTreeId() . " " . |
|
326 | - ($marnm ? "" : " AND n_type!='_MARNM'"); |
|
327 | - |
|
328 | - if ($surn) { |
|
329 | - $sql .= " AND n_surn=" . Database::quote($surn) . " COLLATE '" . I18N::collation() . "'"; |
|
330 | - } elseif ($salpha == ',') { |
|
331 | - $sql .= " AND n_surn=''"; |
|
332 | - } elseif ($salpha == '@') { |
|
333 | - $sql .= " AND n_surn='@N.N.'"; |
|
334 | - } elseif ($salpha) { |
|
335 | - $sql .= " AND " . self::getInitialSql('n_surn', $salpha); |
|
336 | - } else { |
|
337 | - // All surnames |
|
338 | - $sql .= " AND n_surn NOT IN ('', '@N.N.')"; |
|
339 | - } |
|
340 | - |
|
341 | - // Fetch all the letters in our alphabet, whether or not there |
|
342 | - // are any names beginning with that letter. It looks better to |
|
343 | - // show the full alphabet, rather than omitting rare letters such as X |
|
344 | - foreach (self::getAlphabetForLocale(WT_LOCALE) as $letter) { |
|
345 | - $count = Database::prepare($sql . " AND " . self::getInitialSql('n_givn', $letter))->fetchOne(); |
|
346 | - $alphas[$letter] = $count; |
|
347 | - } |
|
348 | - |
|
349 | - // Now fetch initial letters that are not in our alphabet, |
|
350 | - // including "@" (for "@N.N.") and "" for no surname |
|
351 | - $sql = |
|
352 | - "SELECT initial, total FROM (SELECT UPPER(LEFT(n_givn, 1)) AS initial, COUNT(DISTINCT n_id) AS total" . |
|
353 | - " FROM `##name` " . |
|
354 | - ($fams ? " JOIN `##link` ON (n_id = l_from AND n_file = l_file AND l_type = 'FAMS') " : "") . |
|
355 | - " WHERE n_file = :tree_id" . |
|
356 | - ($marnm ? "" : " AND n_type != '_MARNM'"); |
|
357 | - |
|
358 | - $args = array( |
|
359 | - 'tree_id' => $tree->getTreeId(), |
|
360 | - ); |
|
361 | - |
|
362 | - if ($surn) { |
|
363 | - $sql .= " AND n_surn COLLATE :collate_1 = :surn"; |
|
364 | - $args['collate_1'] = I18N::collation(); |
|
365 | - $args['surn'] = $surn; |
|
366 | - } elseif ($salpha === ',') { |
|
367 | - $sql .= " AND n_surn = ''"; |
|
368 | - } elseif ($salpha === '@') { |
|
369 | - $sql .= " AND n_surn = '@N.N.'"; |
|
370 | - } elseif ($salpha) { |
|
371 | - $sql .= " AND " . self::getInitialSql('n_surn', $salpha); |
|
372 | - } else { |
|
373 | - // All surnames |
|
374 | - $sql .= " AND n_surn NOT IN ('', '@N.N.')"; |
|
375 | - } |
|
376 | - |
|
377 | - foreach (self::getAlphabetForLocale(WT_LOCALE) as $letter) { |
|
378 | - $sql .= " AND n_givn NOT LIKE '" . $letter . "%' COLLATE " . I18N::collation(); |
|
379 | - } |
|
380 | - $sql .= " GROUP BY UPPER(LEFT(n_givn, 1))) AS subquery ORDER BY initial = '@', initial = '', initial"; |
|
381 | - |
|
382 | - foreach (Database::prepare($sql)->execute($args)->fetchAssoc() as $alpha => $count) { |
|
383 | - $alphas[$alpha] = $count; |
|
384 | - } |
|
385 | - |
|
386 | - return $alphas; |
|
387 | - } |
|
388 | - |
|
389 | - /** |
|
390 | - * Get a list of actual surnames and variants, based on a "root" surname. |
|
391 | - * |
|
392 | - * @param Tree $tree only fetch individuals from this tree |
|
393 | - * @param string $surn if set, only fetch people with this surname |
|
394 | - * @param string $salpha if set, only consider surnames starting with this letter |
|
395 | - * @param bool $marnm if set, include married names |
|
396 | - * @param bool $fams if set, only consider individuals with FAMS records |
|
397 | - * |
|
398 | - * @return array |
|
399 | - */ |
|
400 | - public static function surnames(Tree $tree, $surn, $salpha, $marnm, $fams) { |
|
401 | - $sql = |
|
402 | - "SELECT n2.n_surn, n1.n_surname, n1.n_id" . |
|
403 | - " FROM `##name` n1 " . |
|
404 | - ($fams ? " JOIN `##link` ON n_id = l_from AND n_file = l_file AND l_type = 'FAMS' " : "") . |
|
405 | - " JOIN (SELECT n_surn COLLATE :collate_0 AS n_surn, n_file FROM `##name`" . |
|
406 | - " WHERE n_file = :tree_id" . |
|
407 | - ($marnm ? "" : " AND n_type != '_MARNM'"); |
|
408 | - |
|
409 | - $args = array( |
|
410 | - 'tree_id' => $tree->getTreeId(), |
|
411 | - 'collate_0' => I18N::collation(), |
|
412 | - ); |
|
413 | - |
|
414 | - if ($surn) { |
|
415 | - $sql .= " AND n_surn COLLATE :collate_1 = :surn"; |
|
416 | - $args['collate_1'] = I18N::collation(); |
|
417 | - $args['surn'] = $surn; |
|
418 | - } elseif ($salpha === ',') { |
|
419 | - $sql .= " AND n_surn = ''"; |
|
420 | - } elseif ($salpha === '@') { |
|
421 | - $sql .= " AND n_surn = '@N.N.'"; |
|
422 | - } elseif ($salpha) { |
|
423 | - $sql .= " AND " . self::getInitialSql('n_surn', $salpha); |
|
424 | - } else { |
|
425 | - // All surnames |
|
426 | - $sql .= " AND n_surn NOT IN ('', '@N.N.')"; |
|
427 | - } |
|
428 | - $sql .= " GROUP BY n_surn COLLATE :collate_2, n_file) AS n2 ON (n1.n_surn = n2.n_surn COLLATE :collate_3 AND n1.n_file = n2.n_file)"; |
|
429 | - $args['collate_2'] = I18N::collation(); |
|
430 | - $args['collate_3'] = I18N::collation(); |
|
431 | - |
|
432 | - $list = array(); |
|
433 | - foreach (Database::prepare($sql)->execute($args)->fetchAll() as $row) { |
|
434 | - $list[I18N::strtoupper($row->n_surn)][$row->n_surname][$row->n_id] = true; |
|
435 | - } |
|
436 | - |
|
437 | - return $list; |
|
438 | - } |
|
439 | - |
|
440 | - /** |
|
441 | - * Fetch a list of individuals with specified names |
|
442 | - * |
|
443 | - * To search for unknown names, use $surn="@N.N.", $salpha="@" or $galpha="@" |
|
444 | - * To search for names with no surnames, use $salpha="," |
|
445 | - * |
|
446 | - * @param Tree $tree only fetch individuals from this tree |
|
447 | - * @param string $surn if set, only fetch people with this surname |
|
448 | - * @param string $salpha if set, only fetch surnames starting with this letter |
|
449 | - * @param string $galpha if set, only fetch given names starting with this letter |
|
450 | - * @param bool $marnm if set, include married names |
|
451 | - * @param bool $fams if set, only fetch individuals with FAMS records |
|
452 | - * |
|
453 | - * @return Individual[] |
|
454 | - */ |
|
455 | - public static function individuals(Tree $tree, $surn, $salpha, $galpha, $marnm, $fams) { |
|
456 | - $sql = |
|
457 | - "SELECT i_id AS xref, i_gedcom AS gedcom, n_full " . |
|
458 | - "FROM `##individuals` " . |
|
459 | - "JOIN `##name` ON n_id = i_id AND n_file = i_file " . |
|
460 | - ($fams ? "JOIN `##link` ON n_id = l_from AND n_file = l_file AND l_type = 'FAMS' " : "") . |
|
461 | - "WHERE n_file = :tree_id " . |
|
462 | - ($marnm ? "" : "AND n_type != '_MARNM'"); |
|
463 | - |
|
464 | - $args = array( |
|
465 | - 'tree_id' => $tree->getTreeId(), |
|
466 | - ); |
|
467 | - |
|
468 | - if ($surn) { |
|
469 | - $sql .= " AND n_surn COLLATE :collate_1 = :surn"; |
|
470 | - $args['collate_1'] = I18N::collation(); |
|
471 | - $args['surn'] = $surn; |
|
472 | - } elseif ($salpha === ',') { |
|
473 | - $sql .= " AND n_surn = ''"; |
|
474 | - } elseif ($salpha === '@') { |
|
475 | - $sql .= " AND n_surn = '@N.N.'"; |
|
476 | - } elseif ($salpha) { |
|
477 | - $sql .= " AND " . self::getInitialSql('n_surn', $salpha); |
|
478 | - } else { |
|
479 | - // All surnames |
|
480 | - $sql .= " AND n_surn NOT IN ('', '@N.N.')"; |
|
481 | - } |
|
482 | - if ($galpha) { |
|
483 | - $sql .= " AND " . self::getInitialSql('n_givn', $galpha); |
|
484 | - } |
|
485 | - |
|
486 | - $sql .= " ORDER BY CASE n_surn WHEN '@N.N.' THEN 1 ELSE 0 END, n_surn COLLATE :collate_2, CASE n_givn WHEN '@P.N.' THEN 1 ELSE 0 END, n_givn COLLATE :collate_3"; |
|
487 | - $args['collate_2'] = I18N::collation(); |
|
488 | - $args['collate_3'] = I18N::collation(); |
|
489 | - |
|
490 | - $list = array(); |
|
491 | - $rows = Database::prepare($sql)->execute($args)->fetchAll(); |
|
492 | - foreach ($rows as $row) { |
|
493 | - $person = Individual::getInstance($row->xref, $tree, $row->gedcom); |
|
494 | - // The name from the database may be private - check the filtered list... |
|
495 | - foreach ($person->getAllNames() as $n => $name) { |
|
496 | - if ($name['fullNN'] == $row->n_full) { |
|
497 | - $person->setPrimaryName($n); |
|
498 | - // We need to clone $person, as we may have multiple references to the |
|
499 | - // same person in this list, and the "primary name" would otherwise |
|
500 | - // be shared amongst all of them. |
|
501 | - $list[] = clone $person; |
|
502 | - break; |
|
503 | - } |
|
504 | - } |
|
505 | - } |
|
506 | - |
|
507 | - return $list; |
|
508 | - } |
|
509 | - |
|
510 | - /** |
|
511 | - * Fetch a list of families with specified names |
|
512 | - * |
|
513 | - * To search for unknown names, use $surn="@N.N.", $salpha="@" or $galpha="@" |
|
514 | - * To search for names with no surnames, use $salpha="," |
|
515 | - * |
|
516 | - * @param Tree $tree only fetch individuals from this tree |
|
517 | - * @param string $surn if set, only fetch people with this surname |
|
518 | - * @param string $salpha if set, only fetch surnames starting with this letter |
|
519 | - * @param string $galpha if set, only fetch given names starting with this letter |
|
520 | - * @param bool $marnm if set, include married names |
|
521 | - * |
|
522 | - * @return Family[] |
|
523 | - */ |
|
524 | - public static function families(Tree $tree, $surn, $salpha, $galpha, $marnm) { |
|
525 | - $list = array(); |
|
526 | - foreach (self::individuals($tree, $surn, $salpha, $galpha, $marnm, true) as $indi) { |
|
527 | - foreach ($indi->getSpouseFamilies() as $family) { |
|
528 | - $list[$family->getXref()] = $family; |
|
529 | - } |
|
530 | - } |
|
531 | - usort($list, '\Fisharebest\Webtrees\GedcomRecord::compare'); |
|
532 | - |
|
533 | - return $list; |
|
534 | - } |
|
28 | + /** |
|
29 | + * Get a list of initial letters, for lists of names. |
|
30 | + * |
|
31 | + * @param string $locale Return the alphabet for this locale |
|
32 | + * |
|
33 | + * @return string[] |
|
34 | + */ |
|
35 | + private static function getAlphabetForLocale($locale) { |
|
36 | + switch ($locale) { |
|
37 | + case 'ar': |
|
38 | + return array( |
|
39 | + 'ا', 'ب', 'ت', 'ث', 'ج', 'ح', 'خ', 'د', 'ذ', 'ر', 'ز', 'س', 'ش', 'ص', 'ض', 'ط', 'ظ', 'ع', 'غ', 'ف', 'ق', 'ك', 'ل', 'م', 'ن', 'ه', 'و', 'ي', 'آ', 'ة', 'ى', 'ی', |
|
40 | + ); |
|
41 | + case 'cs': |
|
42 | + return array( |
|
43 | + 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'CH', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', |
|
44 | + ); |
|
45 | + case 'da': |
|
46 | + case 'nb': |
|
47 | + case 'nn': |
|
48 | + return array( |
|
49 | + 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'Æ', 'Ø', 'Å', |
|
50 | + ); |
|
51 | + case 'el': |
|
52 | + return array( |
|
53 | + 'Α', 'Β', 'Γ', 'Δ', 'Ε', 'Ζ', 'Η', 'Θ', 'Ι', 'Κ', 'Λ', 'Μ', 'Ν', 'Ξ', 'Ο', 'Π', 'Ρ', 'Σ', 'Τ', 'Υ', 'Φ', 'Χ', 'Ψ', 'Ω', |
|
54 | + ); |
|
55 | + case 'es': |
|
56 | + return array( |
|
57 | + 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'Ñ', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', |
|
58 | + ); |
|
59 | + case 'et': |
|
60 | + return array( |
|
61 | + 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'Š', 'Z', 'Ž', 'T', 'U', 'V', 'W', 'Õ', 'Ä', 'Ö', 'Ü', 'X', 'Y', |
|
62 | + ); |
|
63 | + case 'fi': |
|
64 | + case 'sv': |
|
65 | + return array( |
|
66 | + 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'Å', 'Ä', 'Ö', |
|
67 | + ); |
|
68 | + case 'he': |
|
69 | + return array( |
|
70 | + 'א', 'ב', 'ג', 'ד', 'ה', 'ו', 'ז', 'ח', 'ט', 'י', 'כ', 'ל', 'מ', 'נ', 'ס', 'ע', 'פ', 'צ', 'ק', 'ר', 'ש', 'ת', |
|
71 | + ); |
|
72 | + case 'hu': |
|
73 | + return array( |
|
74 | + 'A', 'B', 'C', 'CS', 'D', 'DZ', 'DZS', 'E', 'F', 'G', 'GY', 'H', 'I', 'J', 'K', 'L', 'LY', 'M', 'N', 'NY', 'O', 'Ö', 'P', 'Q', 'R', 'S', 'SZ', 'T', 'TY', 'U', 'Ü', 'V', 'W', 'X', 'Y', 'Z', 'ZS', |
|
75 | + ); |
|
76 | + case 'lt': |
|
77 | + return array( |
|
78 | + 'A', 'Ą', 'B', 'C', 'Č', 'D', 'E', 'Ę', 'Ė', 'F', 'G', 'H', 'I', 'Y', 'Į', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'R', 'S', 'Š', 'T', 'U', 'Ų', 'Ū', 'V', 'Z', 'Ž', |
|
79 | + ); |
|
80 | + case 'nl': |
|
81 | + return array( |
|
82 | + 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'IJ', |
|
83 | + ); |
|
84 | + case 'pl': |
|
85 | + return array( |
|
86 | + 'A', 'B', 'C', 'Ć', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'Ł', 'M', 'N', 'O', 'Ó', 'P', 'Q', 'R', 'S', 'Ś', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'Ź', 'Ż', |
|
87 | + ); |
|
88 | + case 'ro': |
|
89 | + return array( |
|
90 | + 'A', 'Ă', 'Â', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'Î', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'Ş', 'T', 'Ţ', 'U', 'V', 'W', 'X', 'Y', 'Z', |
|
91 | + ); |
|
92 | + case 'ru': |
|
93 | + return array( |
|
94 | + 'А', 'Б', 'В', 'Г', 'Д', 'Е', 'Ё', 'Ж', 'З', 'И', 'Й', 'К', 'Л', 'М', 'Н', 'О', 'П', 'Р', 'С', 'Т', 'У', 'Ф', 'Х', 'Ц', 'Ч', 'Ш', 'Щ', 'Ъ', 'Ы', 'Ь', 'Э', 'Ю', 'Я', |
|
95 | + ); |
|
96 | + case 'sk': |
|
97 | + return array( |
|
98 | + 'A', 'Á', 'Ä', 'B', 'C', 'Č', 'D', 'Ď', 'E', 'É', 'F', 'G', 'H', 'I', 'Í', 'J', 'K', 'L', 'Ľ', 'Ĺ', 'M', 'N', 'Ň', 'O', 'Ó', 'Ô', 'P', 'Q', 'R', 'Ŕ', 'S', 'Š', 'T', 'Ť', 'U', 'Ú', 'V', 'W', 'X', 'Y', 'Ý', 'Z', 'Ž', |
|
99 | + ); |
|
100 | + case 'sl': |
|
101 | + return array( |
|
102 | + 'A', 'B', 'C', 'Č', 'Ć', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'Š', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'Ž', |
|
103 | + ); |
|
104 | + case 'sr': |
|
105 | + return array( |
|
106 | + 'A', 'B', 'C', 'Č', 'Ć', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'Š', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'Ž', |
|
107 | + ); |
|
108 | + case 'tr': |
|
109 | + return array( |
|
110 | + 'A', 'B', 'C', 'Ç', 'D', 'E', 'F', 'G', 'Ğ', 'H', 'I', 'İ', 'J', 'K', 'L', 'M', 'N', 'O', 'Ö', 'P', 'R', 'S', 'Ş', 'T', 'U', 'Ü', 'V', 'Y', 'Z', |
|
111 | + ); |
|
112 | + default: |
|
113 | + return array( |
|
114 | + 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', |
|
115 | + ); |
|
116 | + } |
|
117 | + } |
|
118 | + |
|
119 | + /** |
|
120 | + * Get the initial letter of a name, taking care of multi-letter sequences and equivalences. |
|
121 | + * |
|
122 | + * @param string $name |
|
123 | + * |
|
124 | + * @return string |
|
125 | + */ |
|
126 | + public static function initialLetter($name) { |
|
127 | + $name = I18N::strtoupper($name); |
|
128 | + switch (WT_LOCALE) { |
|
129 | + case 'cs': |
|
130 | + if (substr($name, 0, 2) == 'CH') { |
|
131 | + return 'CH'; |
|
132 | + } |
|
133 | + break; |
|
134 | + case 'da': |
|
135 | + case 'nb': |
|
136 | + case 'nn': |
|
137 | + if (substr($name, 0, 2) == 'AA') { |
|
138 | + return 'Å'; |
|
139 | + } |
|
140 | + break; |
|
141 | + case 'hu': |
|
142 | + if (substr($name, 0, 2) == 'CS') { |
|
143 | + return 'CS'; |
|
144 | + } elseif (substr($name, 0, 3) == 'DZS') { |
|
145 | + return 'DZS'; |
|
146 | + } elseif (substr($name, 0, 2) == 'DZ') { |
|
147 | + return 'DZ'; |
|
148 | + } elseif (substr($name, 0, 2) == 'GY') { |
|
149 | + return 'GY'; |
|
150 | + } elseif (substr($name, 0, 2) == 'LY') { |
|
151 | + return 'LY'; |
|
152 | + } elseif (substr($name, 0, 2) == 'NY') { |
|
153 | + return 'NY'; |
|
154 | + } elseif (substr($name, 0, 2) == 'SZ') { |
|
155 | + return 'SZ'; |
|
156 | + } elseif (substr($name, 0, 2) == 'TY') { |
|
157 | + return 'TY'; |
|
158 | + } elseif (substr($name, 0, 2) == 'ZS') { |
|
159 | + return 'ZS'; |
|
160 | + } |
|
161 | + break; |
|
162 | + case 'nl': |
|
163 | + if (substr($name, 0, 2) == 'IJ') { |
|
164 | + return 'IJ'; |
|
165 | + } |
|
166 | + break; |
|
167 | + } |
|
168 | + // No special rules - just take the first character |
|
169 | + return mb_substr($name, 0, 1); |
|
170 | + } |
|
171 | + |
|
172 | + /** |
|
173 | + * Generate SQL to match a given letter, taking care of cases that |
|
174 | + * are not covered by the collation setting. |
|
175 | + * |
|
176 | + * We must consider: |
|
177 | + * potential substrings, such as Czech "CH" and "C" |
|
178 | + * equivalent letters, such as Danish "AA" and "Å" |
|
179 | + * |
|
180 | + * We COULD write something that handles all languages generically, |
|
181 | + * but its performance would most likely be poor. |
|
182 | + * |
|
183 | + * For languages that don't appear in this list, we could write |
|
184 | + * simpler versions of the surnameAlpha() and givenAlpha() functions, |
|
185 | + * but it gives no noticable improvement in performance. |
|
186 | + * |
|
187 | + * @param string $field |
|
188 | + * @param string $letter |
|
189 | + * |
|
190 | + * @return string |
|
191 | + */ |
|
192 | + private static function getInitialSql($field, $letter) { |
|
193 | + switch (WT_LOCALE) { |
|
194 | + case 'cs': |
|
195 | + switch ($letter) { |
|
196 | + case 'C': return $field . " LIKE 'C%' COLLATE " . I18N::collation() . " AND " . $field . " NOT LIKE 'CH%' COLLATE " . I18N::collation(); |
|
197 | + } |
|
198 | + break; |
|
199 | + case 'da': |
|
200 | + case 'nb': |
|
201 | + case 'nn': |
|
202 | + switch ($letter) { |
|
203 | + // AA gets listed under Å |
|
204 | + case 'A': return $field . " LIKE 'A%' COLLATE " . I18N::collation() . " AND " . $field . " NOT LIKE 'AA%' COLLATE " . I18N::collation(); |
|
205 | + case 'Å': return "(" . $field . " LIKE 'Å%' COLLATE " . I18N::collation() . " OR " . $field . " LIKE 'AA%' COLLATE " . I18N::collation() . ")"; |
|
206 | + } |
|
207 | + break; |
|
208 | + case 'hu': |
|
209 | + switch ($letter) { |
|
210 | + case 'C': return $field . " LIKE 'C%' COLLATE " . I18N::collation() . " AND " . $field . " NOT LIKE 'CS%' COLLATE " . I18N::collation(); |
|
211 | + case 'D': return $field . " LIKE 'D%' COLLATE " . I18N::collation() . " AND " . $field . " NOT LIKE 'DZ%' COLLATE " . I18N::collation(); |
|
212 | + case 'DZ': return $field . " LIKE 'DZ%' COLLATE " . I18N::collation() . " AND " . $field . " NOT LIKE 'DZS%' COLLATE " . I18N::collation(); |
|
213 | + case 'G': return $field . " LIKE 'G%' COLLATE " . I18N::collation() . " AND " . $field . " NOT LIKE 'GY%' COLLATE " . I18N::collation(); |
|
214 | + case 'L': return $field . " LIKE 'L%' COLLATE " . I18N::collation() . " AND " . $field . " NOT LIKE 'LY%' COLLATE " . I18N::collation(); |
|
215 | + case 'N': return $field . " LIKE 'N%' COLLATE " . I18N::collation() . " AND " . $field . " NOT LIKE 'NY%' COLLATE " . I18N::collation(); |
|
216 | + case 'S': return $field . " LIKE 'S%' COLLATE " . I18N::collation() . " AND " . $field . " NOT LIKE 'SZ%' COLLATE " . I18N::collation(); |
|
217 | + case 'T': return $field . " LIKE 'T%' COLLATE " . I18N::collation() . " AND " . $field . " NOT LIKE 'TY%' COLLATE " . I18N::collation(); |
|
218 | + case 'Z': return $field . " LIKE 'Z%' COLLATE " . I18N::collation() . " AND " . $field . " NOT LIKE 'ZS%' COLLATE " . I18N::collation(); |
|
219 | + } |
|
220 | + break; |
|
221 | + case 'nl': |
|
222 | + switch ($letter) { |
|
223 | + case 'I': return $field . " LIKE 'I%' COLLATE " . I18N::collation() . " AND " . $field . " NOT LIKE 'IJ%' COLLATE " . I18N::collation(); |
|
224 | + } |
|
225 | + break; |
|
226 | + } |
|
227 | + |
|
228 | + // Easy cases: the MySQL collation rules take care of it |
|
229 | + return "$field LIKE CONCAT('@'," . Database::quote($letter) . ",'%') COLLATE " . I18N::collation() . " ESCAPE '@'"; |
|
230 | + } |
|
231 | + |
|
232 | + /** |
|
233 | + * Get a list of initial surname letters for indilist.php and famlist.php |
|
234 | + * |
|
235 | + * @param Tree $tree Find surnames from this tree |
|
236 | + * @param bool $marnm if set, include married names |
|
237 | + * @param bool $fams if set, only consider individuals with FAMS records |
|
238 | + * @param bool $totals if set, count the number of names beginning with each letter |
|
239 | + * |
|
240 | + * @return int[] |
|
241 | + */ |
|
242 | + public static function surnameAlpha(Tree $tree, $marnm, $fams, $totals = true) { |
|
243 | + $alphas = array(); |
|
244 | + |
|
245 | + $sql = |
|
246 | + "SELECT COUNT(n_id)" . |
|
247 | + " FROM `##name` " . |
|
248 | + ($fams ? " JOIN `##link` ON (n_id=l_from AND n_file=l_file AND l_type='FAMS') " : "") . |
|
249 | + " WHERE n_file=" . $tree->getTreeId() . |
|
250 | + ($marnm ? "" : " AND n_type!='_MARNM'"); |
|
251 | + |
|
252 | + // Fetch all the letters in our alphabet, whether or not there |
|
253 | + // are any names beginning with that letter. It looks better to |
|
254 | + // show the full alphabet, rather than omitting rare letters such as X |
|
255 | + foreach (self::getAlphabetForLocale(WT_LOCALE) as $letter) { |
|
256 | + $count = 1; |
|
257 | + if ($totals) { |
|
258 | + $count = Database::prepare($sql . " AND " . self::getInitialSql('n_surn', $letter))->fetchOne(); |
|
259 | + } |
|
260 | + $alphas[$letter] = $count; |
|
261 | + } |
|
262 | + |
|
263 | + // Now fetch initial letters that are not in our alphabet, |
|
264 | + // including "@" (for "@N.N.") and "" for no surname. |
|
265 | + $sql = |
|
266 | + "SELECT initial, count FROM (SELECT UPPER(LEFT(n_surn, 1)) AS initial, COUNT(n_id) AS count" . |
|
267 | + " FROM `##name` " . |
|
268 | + ($fams ? " JOIN `##link` ON n_id = l_from AND n_file = l_file AND l_type = 'FAMS' " : "") . |
|
269 | + " WHERE n_file = :tree_id AND n_surn <> ''" . |
|
270 | + ($marnm ? "" : " AND n_type != '_MARNM'"); |
|
271 | + |
|
272 | + $args = array( |
|
273 | + 'tree_id' => $tree->getTreeId(), |
|
274 | + ); |
|
275 | + |
|
276 | + foreach (self::getAlphabetForLocale(WT_LOCALE) as $n => $letter) { |
|
277 | + $sql .= " AND n_surn COLLATE :collate_" . $n . " NOT LIKE :letter_" . $n; |
|
278 | + $args['collate_' . $n] = I18N::collation(); |
|
279 | + $args['letter_' . $n] = $letter . '%'; |
|
280 | + } |
|
281 | + $sql .= " GROUP BY UPPER(LEFT(n_surn, 1))) AS subquery ORDER BY initial = '', initial = '@', initial"; |
|
282 | + foreach (Database::prepare($sql)->execute($args)->fetchAssoc() as $alpha => $count) { |
|
283 | + $alphas[$alpha] = $count; |
|
284 | + } |
|
285 | + |
|
286 | + // Names with no surname |
|
287 | + $sql = |
|
288 | + "SELECT COUNT(n_id)" . |
|
289 | + " FROM `##name` " . |
|
290 | + ($fams ? " JOIN `##link` ON n_id = l_from AND n_file = l_file AND l_type = 'FAMS' " : "") . |
|
291 | + " WHERE n_file = :tree_id AND n_surn = ''" . |
|
292 | + ($marnm ? "" : " AND n_type != '_MARNM'"); |
|
293 | + |
|
294 | + $args = array( |
|
295 | + 'tree_id' => $tree->getTreeId(), |
|
296 | + ); |
|
297 | + |
|
298 | + $num_none = Database::prepare($sql)->execute($args)->fetchOne(); |
|
299 | + if ($num_none) { |
|
300 | + // Special code to indicate "no surname" |
|
301 | + $alphas[','] = $num_none; |
|
302 | + } |
|
303 | + |
|
304 | + return $alphas; |
|
305 | + } |
|
306 | + |
|
307 | + /** |
|
308 | + * Get a list of initial given name letters for indilist.php and famlist.php |
|
309 | + * |
|
310 | + * @param Tree $tree Find names in this tree |
|
311 | + * @param string $surn if set, only consider people with this surname |
|
312 | + * @param string $salpha if set, only consider surnames starting with this letter |
|
313 | + * @param bool $marnm if set, include married names |
|
314 | + * @param bool $fams if set, only consider individuals with FAMS records |
|
315 | + * |
|
316 | + * @return int[] |
|
317 | + */ |
|
318 | + public static function givenAlpha(Tree $tree, $surn, $salpha, $marnm, $fams) { |
|
319 | + $alphas = array(); |
|
320 | + |
|
321 | + $sql = |
|
322 | + "SELECT COUNT(DISTINCT n_id)" . |
|
323 | + " FROM `##name`" . |
|
324 | + ($fams ? " JOIN `##link` ON (n_id=l_from AND n_file=l_file AND l_type='FAMS') " : "") . |
|
325 | + " WHERE n_file=" . $tree->getTreeId() . " " . |
|
326 | + ($marnm ? "" : " AND n_type!='_MARNM'"); |
|
327 | + |
|
328 | + if ($surn) { |
|
329 | + $sql .= " AND n_surn=" . Database::quote($surn) . " COLLATE '" . I18N::collation() . "'"; |
|
330 | + } elseif ($salpha == ',') { |
|
331 | + $sql .= " AND n_surn=''"; |
|
332 | + } elseif ($salpha == '@') { |
|
333 | + $sql .= " AND n_surn='@N.N.'"; |
|
334 | + } elseif ($salpha) { |
|
335 | + $sql .= " AND " . self::getInitialSql('n_surn', $salpha); |
|
336 | + } else { |
|
337 | + // All surnames |
|
338 | + $sql .= " AND n_surn NOT IN ('', '@N.N.')"; |
|
339 | + } |
|
340 | + |
|
341 | + // Fetch all the letters in our alphabet, whether or not there |
|
342 | + // are any names beginning with that letter. It looks better to |
|
343 | + // show the full alphabet, rather than omitting rare letters such as X |
|
344 | + foreach (self::getAlphabetForLocale(WT_LOCALE) as $letter) { |
|
345 | + $count = Database::prepare($sql . " AND " . self::getInitialSql('n_givn', $letter))->fetchOne(); |
|
346 | + $alphas[$letter] = $count; |
|
347 | + } |
|
348 | + |
|
349 | + // Now fetch initial letters that are not in our alphabet, |
|
350 | + // including "@" (for "@N.N.") and "" for no surname |
|
351 | + $sql = |
|
352 | + "SELECT initial, total FROM (SELECT UPPER(LEFT(n_givn, 1)) AS initial, COUNT(DISTINCT n_id) AS total" . |
|
353 | + " FROM `##name` " . |
|
354 | + ($fams ? " JOIN `##link` ON (n_id = l_from AND n_file = l_file AND l_type = 'FAMS') " : "") . |
|
355 | + " WHERE n_file = :tree_id" . |
|
356 | + ($marnm ? "" : " AND n_type != '_MARNM'"); |
|
357 | + |
|
358 | + $args = array( |
|
359 | + 'tree_id' => $tree->getTreeId(), |
|
360 | + ); |
|
361 | + |
|
362 | + if ($surn) { |
|
363 | + $sql .= " AND n_surn COLLATE :collate_1 = :surn"; |
|
364 | + $args['collate_1'] = I18N::collation(); |
|
365 | + $args['surn'] = $surn; |
|
366 | + } elseif ($salpha === ',') { |
|
367 | + $sql .= " AND n_surn = ''"; |
|
368 | + } elseif ($salpha === '@') { |
|
369 | + $sql .= " AND n_surn = '@N.N.'"; |
|
370 | + } elseif ($salpha) { |
|
371 | + $sql .= " AND " . self::getInitialSql('n_surn', $salpha); |
|
372 | + } else { |
|
373 | + // All surnames |
|
374 | + $sql .= " AND n_surn NOT IN ('', '@N.N.')"; |
|
375 | + } |
|
376 | + |
|
377 | + foreach (self::getAlphabetForLocale(WT_LOCALE) as $letter) { |
|
378 | + $sql .= " AND n_givn NOT LIKE '" . $letter . "%' COLLATE " . I18N::collation(); |
|
379 | + } |
|
380 | + $sql .= " GROUP BY UPPER(LEFT(n_givn, 1))) AS subquery ORDER BY initial = '@', initial = '', initial"; |
|
381 | + |
|
382 | + foreach (Database::prepare($sql)->execute($args)->fetchAssoc() as $alpha => $count) { |
|
383 | + $alphas[$alpha] = $count; |
|
384 | + } |
|
385 | + |
|
386 | + return $alphas; |
|
387 | + } |
|
388 | + |
|
389 | + /** |
|
390 | + * Get a list of actual surnames and variants, based on a "root" surname. |
|
391 | + * |
|
392 | + * @param Tree $tree only fetch individuals from this tree |
|
393 | + * @param string $surn if set, only fetch people with this surname |
|
394 | + * @param string $salpha if set, only consider surnames starting with this letter |
|
395 | + * @param bool $marnm if set, include married names |
|
396 | + * @param bool $fams if set, only consider individuals with FAMS records |
|
397 | + * |
|
398 | + * @return array |
|
399 | + */ |
|
400 | + public static function surnames(Tree $tree, $surn, $salpha, $marnm, $fams) { |
|
401 | + $sql = |
|
402 | + "SELECT n2.n_surn, n1.n_surname, n1.n_id" . |
|
403 | + " FROM `##name` n1 " . |
|
404 | + ($fams ? " JOIN `##link` ON n_id = l_from AND n_file = l_file AND l_type = 'FAMS' " : "") . |
|
405 | + " JOIN (SELECT n_surn COLLATE :collate_0 AS n_surn, n_file FROM `##name`" . |
|
406 | + " WHERE n_file = :tree_id" . |
|
407 | + ($marnm ? "" : " AND n_type != '_MARNM'"); |
|
408 | + |
|
409 | + $args = array( |
|
410 | + 'tree_id' => $tree->getTreeId(), |
|
411 | + 'collate_0' => I18N::collation(), |
|
412 | + ); |
|
413 | + |
|
414 | + if ($surn) { |
|
415 | + $sql .= " AND n_surn COLLATE :collate_1 = :surn"; |
|
416 | + $args['collate_1'] = I18N::collation(); |
|
417 | + $args['surn'] = $surn; |
|
418 | + } elseif ($salpha === ',') { |
|
419 | + $sql .= " AND n_surn = ''"; |
|
420 | + } elseif ($salpha === '@') { |
|
421 | + $sql .= " AND n_surn = '@N.N.'"; |
|
422 | + } elseif ($salpha) { |
|
423 | + $sql .= " AND " . self::getInitialSql('n_surn', $salpha); |
|
424 | + } else { |
|
425 | + // All surnames |
|
426 | + $sql .= " AND n_surn NOT IN ('', '@N.N.')"; |
|
427 | + } |
|
428 | + $sql .= " GROUP BY n_surn COLLATE :collate_2, n_file) AS n2 ON (n1.n_surn = n2.n_surn COLLATE :collate_3 AND n1.n_file = n2.n_file)"; |
|
429 | + $args['collate_2'] = I18N::collation(); |
|
430 | + $args['collate_3'] = I18N::collation(); |
|
431 | + |
|
432 | + $list = array(); |
|
433 | + foreach (Database::prepare($sql)->execute($args)->fetchAll() as $row) { |
|
434 | + $list[I18N::strtoupper($row->n_surn)][$row->n_surname][$row->n_id] = true; |
|
435 | + } |
|
436 | + |
|
437 | + return $list; |
|
438 | + } |
|
439 | + |
|
440 | + /** |
|
441 | + * Fetch a list of individuals with specified names |
|
442 | + * |
|
443 | + * To search for unknown names, use $surn="@N.N.", $salpha="@" or $galpha="@" |
|
444 | + * To search for names with no surnames, use $salpha="," |
|
445 | + * |
|
446 | + * @param Tree $tree only fetch individuals from this tree |
|
447 | + * @param string $surn if set, only fetch people with this surname |
|
448 | + * @param string $salpha if set, only fetch surnames starting with this letter |
|
449 | + * @param string $galpha if set, only fetch given names starting with this letter |
|
450 | + * @param bool $marnm if set, include married names |
|
451 | + * @param bool $fams if set, only fetch individuals with FAMS records |
|
452 | + * |
|
453 | + * @return Individual[] |
|
454 | + */ |
|
455 | + public static function individuals(Tree $tree, $surn, $salpha, $galpha, $marnm, $fams) { |
|
456 | + $sql = |
|
457 | + "SELECT i_id AS xref, i_gedcom AS gedcom, n_full " . |
|
458 | + "FROM `##individuals` " . |
|
459 | + "JOIN `##name` ON n_id = i_id AND n_file = i_file " . |
|
460 | + ($fams ? "JOIN `##link` ON n_id = l_from AND n_file = l_file AND l_type = 'FAMS' " : "") . |
|
461 | + "WHERE n_file = :tree_id " . |
|
462 | + ($marnm ? "" : "AND n_type != '_MARNM'"); |
|
463 | + |
|
464 | + $args = array( |
|
465 | + 'tree_id' => $tree->getTreeId(), |
|
466 | + ); |
|
467 | + |
|
468 | + if ($surn) { |
|
469 | + $sql .= " AND n_surn COLLATE :collate_1 = :surn"; |
|
470 | + $args['collate_1'] = I18N::collation(); |
|
471 | + $args['surn'] = $surn; |
|
472 | + } elseif ($salpha === ',') { |
|
473 | + $sql .= " AND n_surn = ''"; |
|
474 | + } elseif ($salpha === '@') { |
|
475 | + $sql .= " AND n_surn = '@N.N.'"; |
|
476 | + } elseif ($salpha) { |
|
477 | + $sql .= " AND " . self::getInitialSql('n_surn', $salpha); |
|
478 | + } else { |
|
479 | + // All surnames |
|
480 | + $sql .= " AND n_surn NOT IN ('', '@N.N.')"; |
|
481 | + } |
|
482 | + if ($galpha) { |
|
483 | + $sql .= " AND " . self::getInitialSql('n_givn', $galpha); |
|
484 | + } |
|
485 | + |
|
486 | + $sql .= " ORDER BY CASE n_surn WHEN '@N.N.' THEN 1 ELSE 0 END, n_surn COLLATE :collate_2, CASE n_givn WHEN '@P.N.' THEN 1 ELSE 0 END, n_givn COLLATE :collate_3"; |
|
487 | + $args['collate_2'] = I18N::collation(); |
|
488 | + $args['collate_3'] = I18N::collation(); |
|
489 | + |
|
490 | + $list = array(); |
|
491 | + $rows = Database::prepare($sql)->execute($args)->fetchAll(); |
|
492 | + foreach ($rows as $row) { |
|
493 | + $person = Individual::getInstance($row->xref, $tree, $row->gedcom); |
|
494 | + // The name from the database may be private - check the filtered list... |
|
495 | + foreach ($person->getAllNames() as $n => $name) { |
|
496 | + if ($name['fullNN'] == $row->n_full) { |
|
497 | + $person->setPrimaryName($n); |
|
498 | + // We need to clone $person, as we may have multiple references to the |
|
499 | + // same person in this list, and the "primary name" would otherwise |
|
500 | + // be shared amongst all of them. |
|
501 | + $list[] = clone $person; |
|
502 | + break; |
|
503 | + } |
|
504 | + } |
|
505 | + } |
|
506 | + |
|
507 | + return $list; |
|
508 | + } |
|
509 | + |
|
510 | + /** |
|
511 | + * Fetch a list of families with specified names |
|
512 | + * |
|
513 | + * To search for unknown names, use $surn="@N.N.", $salpha="@" or $galpha="@" |
|
514 | + * To search for names with no surnames, use $salpha="," |
|
515 | + * |
|
516 | + * @param Tree $tree only fetch individuals from this tree |
|
517 | + * @param string $surn if set, only fetch people with this surname |
|
518 | + * @param string $salpha if set, only fetch surnames starting with this letter |
|
519 | + * @param string $galpha if set, only fetch given names starting with this letter |
|
520 | + * @param bool $marnm if set, include married names |
|
521 | + * |
|
522 | + * @return Family[] |
|
523 | + */ |
|
524 | + public static function families(Tree $tree, $surn, $salpha, $galpha, $marnm) { |
|
525 | + $list = array(); |
|
526 | + foreach (self::individuals($tree, $surn, $salpha, $galpha, $marnm, true) as $indi) { |
|
527 | + foreach ($indi->getSpouseFamilies() as $family) { |
|
528 | + $list[$family->getXref()] = $family; |
|
529 | + } |
|
530 | + } |
|
531 | + usort($list, '\Fisharebest\Webtrees\GedcomRecord::compare'); |
|
532 | + |
|
533 | + return $list; |
|
534 | + } |
|
535 | 535 | } |
@@ -34,85 +34,85 @@ discard block |
||
34 | 34 | */ |
35 | 35 | private static function getAlphabetForLocale($locale) { |
36 | 36 | switch ($locale) { |
37 | - case 'ar': |
|
38 | - return array( |
|
39 | - 'ا', 'ب', 'ت', 'ث', 'ج', 'ح', 'خ', 'د', 'ذ', 'ر', 'ز', 'س', 'ش', 'ص', 'ض', 'ط', 'ظ', 'ع', 'غ', 'ف', 'ق', 'ك', 'ل', 'م', 'ن', 'ه', 'و', 'ي', 'آ', 'ة', 'ى', 'ی', |
|
40 | - ); |
|
41 | - case 'cs': |
|
42 | - return array( |
|
43 | - 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'CH', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', |
|
44 | - ); |
|
45 | - case 'da': |
|
46 | - case 'nb': |
|
47 | - case 'nn': |
|
48 | - return array( |
|
49 | - 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'Æ', 'Ø', 'Å', |
|
50 | - ); |
|
51 | - case 'el': |
|
52 | - return array( |
|
53 | - 'Α', 'Β', 'Γ', 'Δ', 'Ε', 'Ζ', 'Η', 'Θ', 'Ι', 'Κ', 'Λ', 'Μ', 'Ν', 'Ξ', 'Ο', 'Π', 'Ρ', 'Σ', 'Τ', 'Υ', 'Φ', 'Χ', 'Ψ', 'Ω', |
|
54 | - ); |
|
55 | - case 'es': |
|
56 | - return array( |
|
57 | - 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'Ñ', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', |
|
58 | - ); |
|
59 | - case 'et': |
|
60 | - return array( |
|
61 | - 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'Š', 'Z', 'Ž', 'T', 'U', 'V', 'W', 'Õ', 'Ä', 'Ö', 'Ü', 'X', 'Y', |
|
62 | - ); |
|
63 | - case 'fi': |
|
64 | - case 'sv': |
|
65 | - return array( |
|
66 | - 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'Å', 'Ä', 'Ö', |
|
67 | - ); |
|
68 | - case 'he': |
|
69 | - return array( |
|
70 | - 'א', 'ב', 'ג', 'ד', 'ה', 'ו', 'ז', 'ח', 'ט', 'י', 'כ', 'ל', 'מ', 'נ', 'ס', 'ע', 'פ', 'צ', 'ק', 'ר', 'ש', 'ת', |
|
71 | - ); |
|
72 | - case 'hu': |
|
73 | - return array( |
|
74 | - 'A', 'B', 'C', 'CS', 'D', 'DZ', 'DZS', 'E', 'F', 'G', 'GY', 'H', 'I', 'J', 'K', 'L', 'LY', 'M', 'N', 'NY', 'O', 'Ö', 'P', 'Q', 'R', 'S', 'SZ', 'T', 'TY', 'U', 'Ü', 'V', 'W', 'X', 'Y', 'Z', 'ZS', |
|
75 | - ); |
|
76 | - case 'lt': |
|
77 | - return array( |
|
78 | - 'A', 'Ą', 'B', 'C', 'Č', 'D', 'E', 'Ę', 'Ė', 'F', 'G', 'H', 'I', 'Y', 'Į', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'R', 'S', 'Š', 'T', 'U', 'Ų', 'Ū', 'V', 'Z', 'Ž', |
|
79 | - ); |
|
80 | - case 'nl': |
|
81 | - return array( |
|
82 | - 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'IJ', |
|
83 | - ); |
|
84 | - case 'pl': |
|
85 | - return array( |
|
86 | - 'A', 'B', 'C', 'Ć', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'Ł', 'M', 'N', 'O', 'Ó', 'P', 'Q', 'R', 'S', 'Ś', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'Ź', 'Ż', |
|
87 | - ); |
|
88 | - case 'ro': |
|
89 | - return array( |
|
90 | - 'A', 'Ă', 'Â', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'Î', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'Ş', 'T', 'Ţ', 'U', 'V', 'W', 'X', 'Y', 'Z', |
|
91 | - ); |
|
92 | - case 'ru': |
|
93 | - return array( |
|
94 | - 'А', 'Б', 'В', 'Г', 'Д', 'Е', 'Ё', 'Ж', 'З', 'И', 'Й', 'К', 'Л', 'М', 'Н', 'О', 'П', 'Р', 'С', 'Т', 'У', 'Ф', 'Х', 'Ц', 'Ч', 'Ш', 'Щ', 'Ъ', 'Ы', 'Ь', 'Э', 'Ю', 'Я', |
|
95 | - ); |
|
96 | - case 'sk': |
|
97 | - return array( |
|
98 | - 'A', 'Á', 'Ä', 'B', 'C', 'Č', 'D', 'Ď', 'E', 'É', 'F', 'G', 'H', 'I', 'Í', 'J', 'K', 'L', 'Ľ', 'Ĺ', 'M', 'N', 'Ň', 'O', 'Ó', 'Ô', 'P', 'Q', 'R', 'Ŕ', 'S', 'Š', 'T', 'Ť', 'U', 'Ú', 'V', 'W', 'X', 'Y', 'Ý', 'Z', 'Ž', |
|
99 | - ); |
|
100 | - case 'sl': |
|
101 | - return array( |
|
102 | - 'A', 'B', 'C', 'Č', 'Ć', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'Š', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'Ž', |
|
103 | - ); |
|
104 | - case 'sr': |
|
105 | - return array( |
|
106 | - 'A', 'B', 'C', 'Č', 'Ć', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'Š', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'Ž', |
|
107 | - ); |
|
108 | - case 'tr': |
|
109 | - return array( |
|
110 | - 'A', 'B', 'C', 'Ç', 'D', 'E', 'F', 'G', 'Ğ', 'H', 'I', 'İ', 'J', 'K', 'L', 'M', 'N', 'O', 'Ö', 'P', 'R', 'S', 'Ş', 'T', 'U', 'Ü', 'V', 'Y', 'Z', |
|
111 | - ); |
|
112 | - default: |
|
113 | - return array( |
|
114 | - 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', |
|
115 | - ); |
|
37 | + case 'ar': |
|
38 | + return array( |
|
39 | + 'ا', 'ب', 'ت', 'ث', 'ج', 'ح', 'خ', 'د', 'ذ', 'ر', 'ز', 'س', 'ش', 'ص', 'ض', 'ط', 'ظ', 'ع', 'غ', 'ف', 'ق', 'ك', 'ل', 'م', 'ن', 'ه', 'و', 'ي', 'آ', 'ة', 'ى', 'ی', |
|
40 | + ); |
|
41 | + case 'cs': |
|
42 | + return array( |
|
43 | + 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'CH', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', |
|
44 | + ); |
|
45 | + case 'da': |
|
46 | + case 'nb': |
|
47 | + case 'nn': |
|
48 | + return array( |
|
49 | + 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'Æ', 'Ø', 'Å', |
|
50 | + ); |
|
51 | + case 'el': |
|
52 | + return array( |
|
53 | + 'Α', 'Β', 'Γ', 'Δ', 'Ε', 'Ζ', 'Η', 'Θ', 'Ι', 'Κ', 'Λ', 'Μ', 'Ν', 'Ξ', 'Ο', 'Π', 'Ρ', 'Σ', 'Τ', 'Υ', 'Φ', 'Χ', 'Ψ', 'Ω', |
|
54 | + ); |
|
55 | + case 'es': |
|
56 | + return array( |
|
57 | + 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'Ñ', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', |
|
58 | + ); |
|
59 | + case 'et': |
|
60 | + return array( |
|
61 | + 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'Š', 'Z', 'Ž', 'T', 'U', 'V', 'W', 'Õ', 'Ä', 'Ö', 'Ü', 'X', 'Y', |
|
62 | + ); |
|
63 | + case 'fi': |
|
64 | + case 'sv': |
|
65 | + return array( |
|
66 | + 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'Å', 'Ä', 'Ö', |
|
67 | + ); |
|
68 | + case 'he': |
|
69 | + return array( |
|
70 | + 'א', 'ב', 'ג', 'ד', 'ה', 'ו', 'ז', 'ח', 'ט', 'י', 'כ', 'ל', 'מ', 'נ', 'ס', 'ע', 'פ', 'צ', 'ק', 'ר', 'ש', 'ת', |
|
71 | + ); |
|
72 | + case 'hu': |
|
73 | + return array( |
|
74 | + 'A', 'B', 'C', 'CS', 'D', 'DZ', 'DZS', 'E', 'F', 'G', 'GY', 'H', 'I', 'J', 'K', 'L', 'LY', 'M', 'N', 'NY', 'O', 'Ö', 'P', 'Q', 'R', 'S', 'SZ', 'T', 'TY', 'U', 'Ü', 'V', 'W', 'X', 'Y', 'Z', 'ZS', |
|
75 | + ); |
|
76 | + case 'lt': |
|
77 | + return array( |
|
78 | + 'A', 'Ą', 'B', 'C', 'Č', 'D', 'E', 'Ę', 'Ė', 'F', 'G', 'H', 'I', 'Y', 'Į', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'R', 'S', 'Š', 'T', 'U', 'Ų', 'Ū', 'V', 'Z', 'Ž', |
|
79 | + ); |
|
80 | + case 'nl': |
|
81 | + return array( |
|
82 | + 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'IJ', |
|
83 | + ); |
|
84 | + case 'pl': |
|
85 | + return array( |
|
86 | + 'A', 'B', 'C', 'Ć', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'Ł', 'M', 'N', 'O', 'Ó', 'P', 'Q', 'R', 'S', 'Ś', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'Ź', 'Ż', |
|
87 | + ); |
|
88 | + case 'ro': |
|
89 | + return array( |
|
90 | + 'A', 'Ă', 'Â', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'Î', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'Ş', 'T', 'Ţ', 'U', 'V', 'W', 'X', 'Y', 'Z', |
|
91 | + ); |
|
92 | + case 'ru': |
|
93 | + return array( |
|
94 | + 'А', 'Б', 'В', 'Г', 'Д', 'Е', 'Ё', 'Ж', 'З', 'И', 'Й', 'К', 'Л', 'М', 'Н', 'О', 'П', 'Р', 'С', 'Т', 'У', 'Ф', 'Х', 'Ц', 'Ч', 'Ш', 'Щ', 'Ъ', 'Ы', 'Ь', 'Э', 'Ю', 'Я', |
|
95 | + ); |
|
96 | + case 'sk': |
|
97 | + return array( |
|
98 | + 'A', 'Á', 'Ä', 'B', 'C', 'Č', 'D', 'Ď', 'E', 'É', 'F', 'G', 'H', 'I', 'Í', 'J', 'K', 'L', 'Ľ', 'Ĺ', 'M', 'N', 'Ň', 'O', 'Ó', 'Ô', 'P', 'Q', 'R', 'Ŕ', 'S', 'Š', 'T', 'Ť', 'U', 'Ú', 'V', 'W', 'X', 'Y', 'Ý', 'Z', 'Ž', |
|
99 | + ); |
|
100 | + case 'sl': |
|
101 | + return array( |
|
102 | + 'A', 'B', 'C', 'Č', 'Ć', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'Š', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'Ž', |
|
103 | + ); |
|
104 | + case 'sr': |
|
105 | + return array( |
|
106 | + 'A', 'B', 'C', 'Č', 'Ć', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'Š', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'Ž', |
|
107 | + ); |
|
108 | + case 'tr': |
|
109 | + return array( |
|
110 | + 'A', 'B', 'C', 'Ç', 'D', 'E', 'F', 'G', 'Ğ', 'H', 'I', 'İ', 'J', 'K', 'L', 'M', 'N', 'O', 'Ö', 'P', 'R', 'S', 'Ş', 'T', 'U', 'Ü', 'V', 'Y', 'Z', |
|
111 | + ); |
|
112 | + default: |
|
113 | + return array( |
|
114 | + 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', |
|
115 | + ); |
|
116 | 116 | } |
117 | 117 | } |
118 | 118 | |
@@ -126,44 +126,44 @@ discard block |
||
126 | 126 | public static function initialLetter($name) { |
127 | 127 | $name = I18N::strtoupper($name); |
128 | 128 | switch (WT_LOCALE) { |
129 | - case 'cs': |
|
130 | - if (substr($name, 0, 2) == 'CH') { |
|
131 | - return 'CH'; |
|
132 | - } |
|
133 | - break; |
|
134 | - case 'da': |
|
135 | - case 'nb': |
|
136 | - case 'nn': |
|
137 | - if (substr($name, 0, 2) == 'AA') { |
|
138 | - return 'Å'; |
|
139 | - } |
|
140 | - break; |
|
141 | - case 'hu': |
|
142 | - if (substr($name, 0, 2) == 'CS') { |
|
143 | - return 'CS'; |
|
144 | - } elseif (substr($name, 0, 3) == 'DZS') { |
|
145 | - return 'DZS'; |
|
146 | - } elseif (substr($name, 0, 2) == 'DZ') { |
|
147 | - return 'DZ'; |
|
148 | - } elseif (substr($name, 0, 2) == 'GY') { |
|
149 | - return 'GY'; |
|
150 | - } elseif (substr($name, 0, 2) == 'LY') { |
|
151 | - return 'LY'; |
|
152 | - } elseif (substr($name, 0, 2) == 'NY') { |
|
153 | - return 'NY'; |
|
154 | - } elseif (substr($name, 0, 2) == 'SZ') { |
|
155 | - return 'SZ'; |
|
156 | - } elseif (substr($name, 0, 2) == 'TY') { |
|
157 | - return 'TY'; |
|
158 | - } elseif (substr($name, 0, 2) == 'ZS') { |
|
159 | - return 'ZS'; |
|
160 | - } |
|
161 | - break; |
|
162 | - case 'nl': |
|
163 | - if (substr($name, 0, 2) == 'IJ') { |
|
164 | - return 'IJ'; |
|
165 | - } |
|
166 | - break; |
|
129 | + case 'cs': |
|
130 | + if (substr($name, 0, 2) == 'CH') { |
|
131 | + return 'CH'; |
|
132 | + } |
|
133 | + break; |
|
134 | + case 'da': |
|
135 | + case 'nb': |
|
136 | + case 'nn': |
|
137 | + if (substr($name, 0, 2) == 'AA') { |
|
138 | + return 'Å'; |
|
139 | + } |
|
140 | + break; |
|
141 | + case 'hu': |
|
142 | + if (substr($name, 0, 2) == 'CS') { |
|
143 | + return 'CS'; |
|
144 | + } elseif (substr($name, 0, 3) == 'DZS') { |
|
145 | + return 'DZS'; |
|
146 | + } elseif (substr($name, 0, 2) == 'DZ') { |
|
147 | + return 'DZ'; |
|
148 | + } elseif (substr($name, 0, 2) == 'GY') { |
|
149 | + return 'GY'; |
|
150 | + } elseif (substr($name, 0, 2) == 'LY') { |
|
151 | + return 'LY'; |
|
152 | + } elseif (substr($name, 0, 2) == 'NY') { |
|
153 | + return 'NY'; |
|
154 | + } elseif (substr($name, 0, 2) == 'SZ') { |
|
155 | + return 'SZ'; |
|
156 | + } elseif (substr($name, 0, 2) == 'TY') { |
|
157 | + return 'TY'; |
|
158 | + } elseif (substr($name, 0, 2) == 'ZS') { |
|
159 | + return 'ZS'; |
|
160 | + } |
|
161 | + break; |
|
162 | + case 'nl': |
|
163 | + if (substr($name, 0, 2) == 'IJ') { |
|
164 | + return 'IJ'; |
|
165 | + } |
|
166 | + break; |
|
167 | 167 | } |
168 | 168 | // No special rules - just take the first character |
169 | 169 | return mb_substr($name, 0, 1); |
@@ -191,37 +191,37 @@ discard block |
||
191 | 191 | */ |
192 | 192 | private static function getInitialSql($field, $letter) { |
193 | 193 | switch (WT_LOCALE) { |
194 | - case 'cs': |
|
195 | - switch ($letter) { |
|
196 | - case 'C': return $field . " LIKE 'C%' COLLATE " . I18N::collation() . " AND " . $field . " NOT LIKE 'CH%' COLLATE " . I18N::collation(); |
|
197 | - } |
|
194 | + case 'cs': |
|
195 | + switch ($letter) { |
|
196 | + case 'C': return $field . " LIKE 'C%' COLLATE " . I18N::collation() . " AND " . $field . " NOT LIKE 'CH%' COLLATE " . I18N::collation(); |
|
197 | + } |
|
198 | 198 | break; |
199 | - case 'da': |
|
200 | - case 'nb': |
|
201 | - case 'nn': |
|
202 | - switch ($letter) { |
|
203 | - // AA gets listed under Å |
|
204 | - case 'A': return $field . " LIKE 'A%' COLLATE " . I18N::collation() . " AND " . $field . " NOT LIKE 'AA%' COLLATE " . I18N::collation(); |
|
205 | - case 'Å': return "(" . $field . " LIKE 'Å%' COLLATE " . I18N::collation() . " OR " . $field . " LIKE 'AA%' COLLATE " . I18N::collation() . ")"; |
|
206 | - } |
|
199 | + case 'da': |
|
200 | + case 'nb': |
|
201 | + case 'nn': |
|
202 | + switch ($letter) { |
|
203 | + // AA gets listed under Å |
|
204 | + case 'A': return $field . " LIKE 'A%' COLLATE " . I18N::collation() . " AND " . $field . " NOT LIKE 'AA%' COLLATE " . I18N::collation(); |
|
205 | + case 'Å': return "(" . $field . " LIKE 'Å%' COLLATE " . I18N::collation() . " OR " . $field . " LIKE 'AA%' COLLATE " . I18N::collation() . ")"; |
|
206 | + } |
|
207 | 207 | break; |
208 | - case 'hu': |
|
209 | - switch ($letter) { |
|
210 | - case 'C': return $field . " LIKE 'C%' COLLATE " . I18N::collation() . " AND " . $field . " NOT LIKE 'CS%' COLLATE " . I18N::collation(); |
|
211 | - case 'D': return $field . " LIKE 'D%' COLLATE " . I18N::collation() . " AND " . $field . " NOT LIKE 'DZ%' COLLATE " . I18N::collation(); |
|
212 | - case 'DZ': return $field . " LIKE 'DZ%' COLLATE " . I18N::collation() . " AND " . $field . " NOT LIKE 'DZS%' COLLATE " . I18N::collation(); |
|
213 | - case 'G': return $field . " LIKE 'G%' COLLATE " . I18N::collation() . " AND " . $field . " NOT LIKE 'GY%' COLLATE " . I18N::collation(); |
|
214 | - case 'L': return $field . " LIKE 'L%' COLLATE " . I18N::collation() . " AND " . $field . " NOT LIKE 'LY%' COLLATE " . I18N::collation(); |
|
215 | - case 'N': return $field . " LIKE 'N%' COLLATE " . I18N::collation() . " AND " . $field . " NOT LIKE 'NY%' COLLATE " . I18N::collation(); |
|
216 | - case 'S': return $field . " LIKE 'S%' COLLATE " . I18N::collation() . " AND " . $field . " NOT LIKE 'SZ%' COLLATE " . I18N::collation(); |
|
217 | - case 'T': return $field . " LIKE 'T%' COLLATE " . I18N::collation() . " AND " . $field . " NOT LIKE 'TY%' COLLATE " . I18N::collation(); |
|
218 | - case 'Z': return $field . " LIKE 'Z%' COLLATE " . I18N::collation() . " AND " . $field . " NOT LIKE 'ZS%' COLLATE " . I18N::collation(); |
|
219 | - } |
|
208 | + case 'hu': |
|
209 | + switch ($letter) { |
|
210 | + case 'C': return $field . " LIKE 'C%' COLLATE " . I18N::collation() . " AND " . $field . " NOT LIKE 'CS%' COLLATE " . I18N::collation(); |
|
211 | + case 'D': return $field . " LIKE 'D%' COLLATE " . I18N::collation() . " AND " . $field . " NOT LIKE 'DZ%' COLLATE " . I18N::collation(); |
|
212 | + case 'DZ': return $field . " LIKE 'DZ%' COLLATE " . I18N::collation() . " AND " . $field . " NOT LIKE 'DZS%' COLLATE " . I18N::collation(); |
|
213 | + case 'G': return $field . " LIKE 'G%' COLLATE " . I18N::collation() . " AND " . $field . " NOT LIKE 'GY%' COLLATE " . I18N::collation(); |
|
214 | + case 'L': return $field . " LIKE 'L%' COLLATE " . I18N::collation() . " AND " . $field . " NOT LIKE 'LY%' COLLATE " . I18N::collation(); |
|
215 | + case 'N': return $field . " LIKE 'N%' COLLATE " . I18N::collation() . " AND " . $field . " NOT LIKE 'NY%' COLLATE " . I18N::collation(); |
|
216 | + case 'S': return $field . " LIKE 'S%' COLLATE " . I18N::collation() . " AND " . $field . " NOT LIKE 'SZ%' COLLATE " . I18N::collation(); |
|
217 | + case 'T': return $field . " LIKE 'T%' COLLATE " . I18N::collation() . " AND " . $field . " NOT LIKE 'TY%' COLLATE " . I18N::collation(); |
|
218 | + case 'Z': return $field . " LIKE 'Z%' COLLATE " . I18N::collation() . " AND " . $field . " NOT LIKE 'ZS%' COLLATE " . I18N::collation(); |
|
219 | + } |
|
220 | 220 | break; |
221 | - case 'nl': |
|
222 | - switch ($letter) { |
|
223 | - case 'I': return $field . " LIKE 'I%' COLLATE " . I18N::collation() . " AND " . $field . " NOT LIKE 'IJ%' COLLATE " . I18N::collation(); |
|
224 | - } |
|
221 | + case 'nl': |
|
222 | + switch ($letter) { |
|
223 | + case 'I': return $field . " LIKE 'I%' COLLATE " . I18N::collation() . " AND " . $field . " NOT LIKE 'IJ%' COLLATE " . I18N::collation(); |
|
224 | + } |
|
225 | 225 | break; |
226 | 226 | } |
227 | 227 |
@@ -24,7 +24,8 @@ discard block |
||
24 | 24 | /** |
25 | 25 | * Generate lists for indilist.php and famlist.php |
26 | 26 | */ |
27 | -class QueryName { |
|
27 | +class QueryName |
|
28 | +{ |
|
28 | 29 | /** |
29 | 30 | * Get a list of initial letters, for lists of names. |
30 | 31 | * |
@@ -32,7 +33,8 @@ discard block |
||
32 | 33 | * |
33 | 34 | * @return string[] |
34 | 35 | */ |
35 | - private static function getAlphabetForLocale($locale) { |
|
36 | + private static function getAlphabetForLocale($locale) |
|
37 | + { |
|
36 | 38 | switch ($locale) { |
37 | 39 | case 'ar': |
38 | 40 | return array( |
@@ -123,7 +125,8 @@ discard block |
||
123 | 125 | * |
124 | 126 | * @return string |
125 | 127 | */ |
126 | - public static function initialLetter($name) { |
|
128 | + public static function initialLetter($name) |
|
129 | + { |
|
127 | 130 | $name = I18N::strtoupper($name); |
128 | 131 | switch (WT_LOCALE) { |
129 | 132 | case 'cs': |
@@ -189,7 +192,8 @@ discard block |
||
189 | 192 | * |
190 | 193 | * @return string |
191 | 194 | */ |
192 | - private static function getInitialSql($field, $letter) { |
|
195 | + private static function getInitialSql($field, $letter) |
|
196 | + { |
|
193 | 197 | switch (WT_LOCALE) { |
194 | 198 | case 'cs': |
195 | 199 | switch ($letter) { |
@@ -239,7 +243,8 @@ discard block |
||
239 | 243 | * |
240 | 244 | * @return int[] |
241 | 245 | */ |
242 | - public static function surnameAlpha(Tree $tree, $marnm, $fams, $totals = true) { |
|
246 | + public static function surnameAlpha(Tree $tree, $marnm, $fams, $totals = true) |
|
247 | + { |
|
243 | 248 | $alphas = array(); |
244 | 249 | |
245 | 250 | $sql = |
@@ -315,7 +320,8 @@ discard block |
||
315 | 320 | * |
316 | 321 | * @return int[] |
317 | 322 | */ |
318 | - public static function givenAlpha(Tree $tree, $surn, $salpha, $marnm, $fams) { |
|
323 | + public static function givenAlpha(Tree $tree, $surn, $salpha, $marnm, $fams) |
|
324 | + { |
|
319 | 325 | $alphas = array(); |
320 | 326 | |
321 | 327 | $sql = |
@@ -397,7 +403,8 @@ discard block |
||
397 | 403 | * |
398 | 404 | * @return array |
399 | 405 | */ |
400 | - public static function surnames(Tree $tree, $surn, $salpha, $marnm, $fams) { |
|
406 | + public static function surnames(Tree $tree, $surn, $salpha, $marnm, $fams) |
|
407 | + { |
|
401 | 408 | $sql = |
402 | 409 | "SELECT n2.n_surn, n1.n_surname, n1.n_id" . |
403 | 410 | " FROM `##name` n1 " . |
@@ -452,7 +459,8 @@ discard block |
||
452 | 459 | * |
453 | 460 | * @return Individual[] |
454 | 461 | */ |
455 | - public static function individuals(Tree $tree, $surn, $salpha, $galpha, $marnm, $fams) { |
|
462 | + public static function individuals(Tree $tree, $surn, $salpha, $galpha, $marnm, $fams) |
|
463 | + { |
|
456 | 464 | $sql = |
457 | 465 | "SELECT i_id AS xref, i_gedcom AS gedcom, n_full " . |
458 | 466 | "FROM `##individuals` " . |
@@ -521,7 +529,8 @@ discard block |
||
521 | 529 | * |
522 | 530 | * @return Family[] |
523 | 531 | */ |
524 | - public static function families(Tree $tree, $surn, $salpha, $galpha, $marnm) { |
|
532 | + public static function families(Tree $tree, $surn, $salpha, $galpha, $marnm) |
|
533 | + { |
|
525 | 534 | $list = array(); |
526 | 535 | foreach (self::individuals($tree, $surn, $salpha, $galpha, $marnm, true) as $indi) { |
527 | 536 | foreach ($indi->getSpouseFamilies() as $family) { |
@@ -23,132 +23,132 @@ |
||
23 | 23 | * Generate lists of files for admin_media.php |
24 | 24 | */ |
25 | 25 | class QueryMedia { |
26 | - /** |
|
27 | - * Generate a list of all the folders in the current tree - for the media list. |
|
28 | - * |
|
29 | - * @return string[] |
|
30 | - */ |
|
31 | - public static function folderList() { |
|
32 | - global $WT_TREE; |
|
33 | - |
|
34 | - $folders = Database::prepare( |
|
35 | - "SELECT LEFT(m_filename, CHAR_LENGTH(m_filename) - CHAR_LENGTH(SUBSTRING_INDEX(m_filename, '/', -1))) AS media_path" . |
|
36 | - " FROM `##media`" . |
|
37 | - " WHERE m_file = ?" . |
|
38 | - " AND m_filename NOT LIKE 'http://%'" . |
|
39 | - " AND m_filename NOT LIKE 'https://%'" . |
|
40 | - " GROUP BY 1" . |
|
41 | - " ORDER BY 1" |
|
42 | - )->execute(array($WT_TREE->getTreeId()))->fetchOneColumn(); |
|
43 | - |
|
44 | - if (!$folders || reset($folders) != '') { |
|
45 | - array_unshift($folders, ''); |
|
46 | - } |
|
47 | - |
|
48 | - return array_combine($folders, $folders); |
|
49 | - } |
|
50 | - |
|
51 | - /** |
|
52 | - * Generate a list of all folders from all the trees - for the media admin. |
|
53 | - * |
|
54 | - * @return array |
|
55 | - */ |
|
56 | - public static function folderListAll() { |
|
57 | - $folders = Database::prepare( |
|
58 | - "SELECT LEFT(m_filename, CHAR_LENGTH(m_filename) - CHAR_LENGTH(SUBSTRING_INDEX(m_filename, '/', -1))) AS media_path" . |
|
59 | - " FROM `##media`" . |
|
60 | - " WHERE m_filename NOT LIKE 'http://%'" . |
|
61 | - " AND m_filename NOT LIKE 'https://%'" . |
|
62 | - " GROUP BY 1" . |
|
63 | - " ORDER BY 1" |
|
64 | - )->execute()->fetchOneColumn(); |
|
65 | - |
|
66 | - if ($folders) { |
|
67 | - return array_combine($folders, $folders); |
|
68 | - } else { |
|
69 | - return array(); |
|
70 | - } |
|
71 | - } |
|
72 | - |
|
73 | - /** |
|
74 | - * Generate a filtered, sourced, privacy-checked list of media objects - for the media list. |
|
75 | - * |
|
76 | - * @param string $folder folder to search |
|
77 | - * @param string $subfolders either "include" or "exclude" |
|
78 | - * @param string $sort either "file" or "title" |
|
79 | - * @param string $filter optional search string |
|
80 | - * @param string $form_type option OBJE/FILE/FORM/TYPE |
|
81 | - * |
|
82 | - * @throws \Exception |
|
83 | - * |
|
84 | - * @return Media[] |
|
85 | - */ |
|
86 | - public static function mediaList($folder, $subfolders, $sort, $filter, $form_type) { |
|
87 | - global $WT_TREE; |
|
88 | - |
|
89 | - // All files in the folder, plus external files |
|
90 | - $sql = |
|
91 | - "SELECT m_id AS xref, m_gedcom AS gedcom" . |
|
92 | - " FROM `##media`" . |
|
93 | - " WHERE m_file=?"; |
|
94 | - $args = array( |
|
95 | - $WT_TREE->getTreeId(), |
|
96 | - ); |
|
97 | - |
|
98 | - // Only show external files when we are looking at the root folder |
|
99 | - if ($folder == '') { |
|
100 | - $sql_external = " OR m_filename LIKE 'http://%' OR m_filename LIKE 'https://%'"; |
|
101 | - } else { |
|
102 | - $sql_external = ""; |
|
103 | - } |
|
104 | - |
|
105 | - // Include / exclude subfolders (but always include external) |
|
106 | - switch ($subfolders) { |
|
107 | - case 'include': |
|
108 | - $sql .= " AND (m_filename LIKE CONCAT(?, '%') $sql_external)"; |
|
109 | - $args[] = Filter::escapeLike($folder); |
|
110 | - break; |
|
111 | - case 'exclude': |
|
112 | - $sql .= " AND (m_filename LIKE CONCAT(?, '%') AND m_filename NOT LIKE CONCAT(?, '%/%') $sql_external)"; |
|
113 | - $args[] = Filter::escapeLike($folder); |
|
114 | - $args[] = Filter::escapeLike($folder); |
|
115 | - break; |
|
116 | - default: |
|
117 | - throw new \Exception('Bad argument (subfolders=' . $subfolders . ') in QueryMedia::mediaList()'); |
|
118 | - } |
|
119 | - |
|
120 | - // Apply search terms |
|
121 | - if ($filter) { |
|
122 | - $sql .= " AND (SUBSTRING_INDEX(m_filename, '/', -1) LIKE CONCAT('%', ?, '%') OR m_titl LIKE CONCAT('%', ?, '%'))"; |
|
123 | - $args[] = Filter::escapeLike($filter); |
|
124 | - $args[] = Filter::escapeLike($filter); |
|
125 | - } |
|
126 | - |
|
127 | - if ($form_type) { |
|
128 | - $sql .= " AND (m_gedcom LIKE CONCAT('%\n3 TYPE ', ?, '%'))"; |
|
129 | - $args[] = $form_type; |
|
130 | - } |
|
131 | - |
|
132 | - switch ($sort) { |
|
133 | - case 'file': |
|
134 | - $sql .= " ORDER BY m_filename"; |
|
135 | - break; |
|
136 | - case 'title': |
|
137 | - $sql .= " ORDER BY m_titl"; |
|
138 | - break; |
|
139 | - default: |
|
140 | - throw new \Exception('Bad argument (sort=' . $sort . ') in QueryMedia::mediaList()'); |
|
141 | - } |
|
142 | - |
|
143 | - $rows = Database::prepare($sql)->execute($args)->fetchAll(); |
|
144 | - $list = array(); |
|
145 | - foreach ($rows as $row) { |
|
146 | - $media = Media::getInstance($row->xref, $WT_TREE, $row->gedcom); |
|
147 | - if ($media->canShow()) { |
|
148 | - $list[] = $media; |
|
149 | - } |
|
150 | - } |
|
151 | - |
|
152 | - return $list; |
|
153 | - } |
|
26 | + /** |
|
27 | + * Generate a list of all the folders in the current tree - for the media list. |
|
28 | + * |
|
29 | + * @return string[] |
|
30 | + */ |
|
31 | + public static function folderList() { |
|
32 | + global $WT_TREE; |
|
33 | + |
|
34 | + $folders = Database::prepare( |
|
35 | + "SELECT LEFT(m_filename, CHAR_LENGTH(m_filename) - CHAR_LENGTH(SUBSTRING_INDEX(m_filename, '/', -1))) AS media_path" . |
|
36 | + " FROM `##media`" . |
|
37 | + " WHERE m_file = ?" . |
|
38 | + " AND m_filename NOT LIKE 'http://%'" . |
|
39 | + " AND m_filename NOT LIKE 'https://%'" . |
|
40 | + " GROUP BY 1" . |
|
41 | + " ORDER BY 1" |
|
42 | + )->execute(array($WT_TREE->getTreeId()))->fetchOneColumn(); |
|
43 | + |
|
44 | + if (!$folders || reset($folders) != '') { |
|
45 | + array_unshift($folders, ''); |
|
46 | + } |
|
47 | + |
|
48 | + return array_combine($folders, $folders); |
|
49 | + } |
|
50 | + |
|
51 | + /** |
|
52 | + * Generate a list of all folders from all the trees - for the media admin. |
|
53 | + * |
|
54 | + * @return array |
|
55 | + */ |
|
56 | + public static function folderListAll() { |
|
57 | + $folders = Database::prepare( |
|
58 | + "SELECT LEFT(m_filename, CHAR_LENGTH(m_filename) - CHAR_LENGTH(SUBSTRING_INDEX(m_filename, '/', -1))) AS media_path" . |
|
59 | + " FROM `##media`" . |
|
60 | + " WHERE m_filename NOT LIKE 'http://%'" . |
|
61 | + " AND m_filename NOT LIKE 'https://%'" . |
|
62 | + " GROUP BY 1" . |
|
63 | + " ORDER BY 1" |
|
64 | + )->execute()->fetchOneColumn(); |
|
65 | + |
|
66 | + if ($folders) { |
|
67 | + return array_combine($folders, $folders); |
|
68 | + } else { |
|
69 | + return array(); |
|
70 | + } |
|
71 | + } |
|
72 | + |
|
73 | + /** |
|
74 | + * Generate a filtered, sourced, privacy-checked list of media objects - for the media list. |
|
75 | + * |
|
76 | + * @param string $folder folder to search |
|
77 | + * @param string $subfolders either "include" or "exclude" |
|
78 | + * @param string $sort either "file" or "title" |
|
79 | + * @param string $filter optional search string |
|
80 | + * @param string $form_type option OBJE/FILE/FORM/TYPE |
|
81 | + * |
|
82 | + * @throws \Exception |
|
83 | + * |
|
84 | + * @return Media[] |
|
85 | + */ |
|
86 | + public static function mediaList($folder, $subfolders, $sort, $filter, $form_type) { |
|
87 | + global $WT_TREE; |
|
88 | + |
|
89 | + // All files in the folder, plus external files |
|
90 | + $sql = |
|
91 | + "SELECT m_id AS xref, m_gedcom AS gedcom" . |
|
92 | + " FROM `##media`" . |
|
93 | + " WHERE m_file=?"; |
|
94 | + $args = array( |
|
95 | + $WT_TREE->getTreeId(), |
|
96 | + ); |
|
97 | + |
|
98 | + // Only show external files when we are looking at the root folder |
|
99 | + if ($folder == '') { |
|
100 | + $sql_external = " OR m_filename LIKE 'http://%' OR m_filename LIKE 'https://%'"; |
|
101 | + } else { |
|
102 | + $sql_external = ""; |
|
103 | + } |
|
104 | + |
|
105 | + // Include / exclude subfolders (but always include external) |
|
106 | + switch ($subfolders) { |
|
107 | + case 'include': |
|
108 | + $sql .= " AND (m_filename LIKE CONCAT(?, '%') $sql_external)"; |
|
109 | + $args[] = Filter::escapeLike($folder); |
|
110 | + break; |
|
111 | + case 'exclude': |
|
112 | + $sql .= " AND (m_filename LIKE CONCAT(?, '%') AND m_filename NOT LIKE CONCAT(?, '%/%') $sql_external)"; |
|
113 | + $args[] = Filter::escapeLike($folder); |
|
114 | + $args[] = Filter::escapeLike($folder); |
|
115 | + break; |
|
116 | + default: |
|
117 | + throw new \Exception('Bad argument (subfolders=' . $subfolders . ') in QueryMedia::mediaList()'); |
|
118 | + } |
|
119 | + |
|
120 | + // Apply search terms |
|
121 | + if ($filter) { |
|
122 | + $sql .= " AND (SUBSTRING_INDEX(m_filename, '/', -1) LIKE CONCAT('%', ?, '%') OR m_titl LIKE CONCAT('%', ?, '%'))"; |
|
123 | + $args[] = Filter::escapeLike($filter); |
|
124 | + $args[] = Filter::escapeLike($filter); |
|
125 | + } |
|
126 | + |
|
127 | + if ($form_type) { |
|
128 | + $sql .= " AND (m_gedcom LIKE CONCAT('%\n3 TYPE ', ?, '%'))"; |
|
129 | + $args[] = $form_type; |
|
130 | + } |
|
131 | + |
|
132 | + switch ($sort) { |
|
133 | + case 'file': |
|
134 | + $sql .= " ORDER BY m_filename"; |
|
135 | + break; |
|
136 | + case 'title': |
|
137 | + $sql .= " ORDER BY m_titl"; |
|
138 | + break; |
|
139 | + default: |
|
140 | + throw new \Exception('Bad argument (sort=' . $sort . ') in QueryMedia::mediaList()'); |
|
141 | + } |
|
142 | + |
|
143 | + $rows = Database::prepare($sql)->execute($args)->fetchAll(); |
|
144 | + $list = array(); |
|
145 | + foreach ($rows as $row) { |
|
146 | + $media = Media::getInstance($row->xref, $WT_TREE, $row->gedcom); |
|
147 | + if ($media->canShow()) { |
|
148 | + $list[] = $media; |
|
149 | + } |
|
150 | + } |
|
151 | + |
|
152 | + return $list; |
|
153 | + } |
|
154 | 154 | } |
@@ -104,17 +104,17 @@ discard block |
||
104 | 104 | |
105 | 105 | // Include / exclude subfolders (but always include external) |
106 | 106 | switch ($subfolders) { |
107 | - case 'include': |
|
108 | - $sql .= " AND (m_filename LIKE CONCAT(?, '%') $sql_external)"; |
|
109 | - $args[] = Filter::escapeLike($folder); |
|
110 | - break; |
|
111 | - case 'exclude': |
|
112 | - $sql .= " AND (m_filename LIKE CONCAT(?, '%') AND m_filename NOT LIKE CONCAT(?, '%/%') $sql_external)"; |
|
113 | - $args[] = Filter::escapeLike($folder); |
|
114 | - $args[] = Filter::escapeLike($folder); |
|
115 | - break; |
|
116 | - default: |
|
117 | - throw new \Exception('Bad argument (subfolders=' . $subfolders . ') in QueryMedia::mediaList()'); |
|
107 | + case 'include': |
|
108 | + $sql .= " AND (m_filename LIKE CONCAT(?, '%') $sql_external)"; |
|
109 | + $args[] = Filter::escapeLike($folder); |
|
110 | + break; |
|
111 | + case 'exclude': |
|
112 | + $sql .= " AND (m_filename LIKE CONCAT(?, '%') AND m_filename NOT LIKE CONCAT(?, '%/%') $sql_external)"; |
|
113 | + $args[] = Filter::escapeLike($folder); |
|
114 | + $args[] = Filter::escapeLike($folder); |
|
115 | + break; |
|
116 | + default: |
|
117 | + throw new \Exception('Bad argument (subfolders=' . $subfolders . ') in QueryMedia::mediaList()'); |
|
118 | 118 | } |
119 | 119 | |
120 | 120 | // Apply search terms |
@@ -130,14 +130,14 @@ discard block |
||
130 | 130 | } |
131 | 131 | |
132 | 132 | switch ($sort) { |
133 | - case 'file': |
|
134 | - $sql .= " ORDER BY m_filename"; |
|
135 | - break; |
|
136 | - case 'title': |
|
137 | - $sql .= " ORDER BY m_titl"; |
|
138 | - break; |
|
139 | - default: |
|
140 | - throw new \Exception('Bad argument (sort=' . $sort . ') in QueryMedia::mediaList()'); |
|
133 | + case 'file': |
|
134 | + $sql .= " ORDER BY m_filename"; |
|
135 | + break; |
|
136 | + case 'title': |
|
137 | + $sql .= " ORDER BY m_titl"; |
|
138 | + break; |
|
139 | + default: |
|
140 | + throw new \Exception('Bad argument (sort=' . $sort . ') in QueryMedia::mediaList()'); |
|
141 | 141 | } |
142 | 142 | |
143 | 143 | $rows = Database::prepare($sql)->execute($args)->fetchAll(); |
@@ -22,13 +22,15 @@ discard block |
||
22 | 22 | /** |
23 | 23 | * Generate lists of files for admin_media.php |
24 | 24 | */ |
25 | -class QueryMedia { |
|
25 | +class QueryMedia |
|
26 | +{ |
|
26 | 27 | /** |
27 | 28 | * Generate a list of all the folders in the current tree - for the media list. |
28 | 29 | * |
29 | 30 | * @return string[] |
30 | 31 | */ |
31 | - public static function folderList() { |
|
32 | + public static function folderList() |
|
33 | + { |
|
32 | 34 | global $WT_TREE; |
33 | 35 | |
34 | 36 | $folders = Database::prepare( |
@@ -53,7 +55,8 @@ discard block |
||
53 | 55 | * |
54 | 56 | * @return array |
55 | 57 | */ |
56 | - public static function folderListAll() { |
|
58 | + public static function folderListAll() |
|
59 | + { |
|
57 | 60 | $folders = Database::prepare( |
58 | 61 | "SELECT LEFT(m_filename, CHAR_LENGTH(m_filename) - CHAR_LENGTH(SUBSTRING_INDEX(m_filename, '/', -1))) AS media_path" . |
59 | 62 | " FROM `##media`" . |
@@ -83,7 +86,8 @@ discard block |
||
83 | 86 | * |
84 | 87 | * @return Media[] |
85 | 88 | */ |
86 | - public static function mediaList($folder, $subfolders, $sort, $filter, $form_type) { |
|
89 | + public static function mediaList($folder, $subfolders, $sort, $filter, $form_type) |
|
90 | + { |
|
87 | 91 | global $WT_TREE; |
88 | 92 | |
89 | 93 | // All files in the folder, plus external files |
@@ -19,92 +19,92 @@ |
||
19 | 19 | * A GEDCOM note (NOTE) object. |
20 | 20 | */ |
21 | 21 | class Note extends GedcomRecord { |
22 | - const RECORD_TYPE = 'NOTE'; |
|
23 | - const URL_PREFIX = 'note.php?nid='; |
|
22 | + const RECORD_TYPE = 'NOTE'; |
|
23 | + const URL_PREFIX = 'note.php?nid='; |
|
24 | 24 | |
25 | - /** |
|
26 | - * Get the text contents of the note |
|
27 | - * |
|
28 | - * @return string|null |
|
29 | - */ |
|
30 | - public function getNote() { |
|
31 | - if (preg_match('/^0 @' . WT_REGEX_XREF . '@ NOTE ?(.*(?:\n1 CONT ?.*)*)/', $this->gedcom . $this->pending, $match)) { |
|
32 | - return preg_replace("/\n1 CONT ?/", "\n", $match[1]); |
|
33 | - } else { |
|
34 | - return null; |
|
35 | - } |
|
36 | - } |
|
25 | + /** |
|
26 | + * Get the text contents of the note |
|
27 | + * |
|
28 | + * @return string|null |
|
29 | + */ |
|
30 | + public function getNote() { |
|
31 | + if (preg_match('/^0 @' . WT_REGEX_XREF . '@ NOTE ?(.*(?:\n1 CONT ?.*)*)/', $this->gedcom . $this->pending, $match)) { |
|
32 | + return preg_replace("/\n1 CONT ?/", "\n", $match[1]); |
|
33 | + } else { |
|
34 | + return null; |
|
35 | + } |
|
36 | + } |
|
37 | 37 | |
38 | - /** |
|
39 | - * Each object type may have its own special rules, and re-implement this function. |
|
40 | - * |
|
41 | - * @param int $access_level |
|
42 | - * |
|
43 | - * @return bool |
|
44 | - */ |
|
45 | - protected function canShowByType($access_level) { |
|
46 | - // Hide notes if they are attached to private records |
|
47 | - $linked_ids = Database::prepare( |
|
48 | - "SELECT l_from FROM `##link` WHERE l_to=? AND l_file=?" |
|
49 | - )->execute(array( |
|
50 | - $this->xref, $this->tree->getTreeId(), |
|
51 | - ))->fetchOneColumn(); |
|
52 | - foreach ($linked_ids as $linked_id) { |
|
53 | - $linked_record = GedcomRecord::getInstance($linked_id, $this->tree); |
|
54 | - if ($linked_record && !$linked_record->canShow($access_level)) { |
|
55 | - return false; |
|
56 | - } |
|
57 | - } |
|
38 | + /** |
|
39 | + * Each object type may have its own special rules, and re-implement this function. |
|
40 | + * |
|
41 | + * @param int $access_level |
|
42 | + * |
|
43 | + * @return bool |
|
44 | + */ |
|
45 | + protected function canShowByType($access_level) { |
|
46 | + // Hide notes if they are attached to private records |
|
47 | + $linked_ids = Database::prepare( |
|
48 | + "SELECT l_from FROM `##link` WHERE l_to=? AND l_file=?" |
|
49 | + )->execute(array( |
|
50 | + $this->xref, $this->tree->getTreeId(), |
|
51 | + ))->fetchOneColumn(); |
|
52 | + foreach ($linked_ids as $linked_id) { |
|
53 | + $linked_record = GedcomRecord::getInstance($linked_id, $this->tree); |
|
54 | + if ($linked_record && !$linked_record->canShow($access_level)) { |
|
55 | + return false; |
|
56 | + } |
|
57 | + } |
|
58 | 58 | |
59 | - // Apply default behaviour |
|
60 | - return parent::canShowByType($access_level); |
|
61 | - } |
|
59 | + // Apply default behaviour |
|
60 | + return parent::canShowByType($access_level); |
|
61 | + } |
|
62 | 62 | |
63 | - /** |
|
64 | - * Generate a private version of this record |
|
65 | - * |
|
66 | - * @param int $access_level |
|
67 | - * |
|
68 | - * @return string |
|
69 | - */ |
|
70 | - protected function createPrivateGedcomRecord($access_level) { |
|
71 | - return '0 @' . $this->xref . '@ NOTE ' . I18N::translate('Private'); |
|
72 | - } |
|
63 | + /** |
|
64 | + * Generate a private version of this record |
|
65 | + * |
|
66 | + * @param int $access_level |
|
67 | + * |
|
68 | + * @return string |
|
69 | + */ |
|
70 | + protected function createPrivateGedcomRecord($access_level) { |
|
71 | + return '0 @' . $this->xref . '@ NOTE ' . I18N::translate('Private'); |
|
72 | + } |
|
73 | 73 | |
74 | - /** |
|
75 | - * Fetch data from the database |
|
76 | - * |
|
77 | - * @param string $xref |
|
78 | - * @param int $tree_id |
|
79 | - * |
|
80 | - * @return null|string |
|
81 | - */ |
|
82 | - protected static function fetchGedcomRecord($xref, $tree_id) { |
|
83 | - return Database::prepare( |
|
84 | - "SELECT o_gedcom FROM `##other` WHERE o_id = :xref AND o_file = :tree_id AND o_type = 'NOTE'" |
|
85 | - )->execute(array( |
|
86 | - 'xref' => $xref, |
|
87 | - 'tree_id' => $tree_id, |
|
88 | - ))->fetchOne(); |
|
89 | - } |
|
74 | + /** |
|
75 | + * Fetch data from the database |
|
76 | + * |
|
77 | + * @param string $xref |
|
78 | + * @param int $tree_id |
|
79 | + * |
|
80 | + * @return null|string |
|
81 | + */ |
|
82 | + protected static function fetchGedcomRecord($xref, $tree_id) { |
|
83 | + return Database::prepare( |
|
84 | + "SELECT o_gedcom FROM `##other` WHERE o_id = :xref AND o_file = :tree_id AND o_type = 'NOTE'" |
|
85 | + )->execute(array( |
|
86 | + 'xref' => $xref, |
|
87 | + 'tree_id' => $tree_id, |
|
88 | + ))->fetchOne(); |
|
89 | + } |
|
90 | 90 | |
91 | - /** |
|
92 | - * Create a name for this note - apply (and remove) markup, then take |
|
93 | - * a maximum of 100 characters from the first line. |
|
94 | - */ |
|
95 | - public function extractNames() { |
|
96 | - $text = $this->getNote(); |
|
91 | + /** |
|
92 | + * Create a name for this note - apply (and remove) markup, then take |
|
93 | + * a maximum of 100 characters from the first line. |
|
94 | + */ |
|
95 | + public function extractNames() { |
|
96 | + $text = $this->getNote(); |
|
97 | 97 | |
98 | - if ($text) { |
|
99 | - switch ($this->getTree()->getPreference('FORMAT_TEXT')) { |
|
100 | - case 'markdown': |
|
101 | - $text = Filter::markdown($text); |
|
102 | - $text = Filter::unescapeHtml($text); |
|
103 | - break; |
|
104 | - } |
|
98 | + if ($text) { |
|
99 | + switch ($this->getTree()->getPreference('FORMAT_TEXT')) { |
|
100 | + case 'markdown': |
|
101 | + $text = Filter::markdown($text); |
|
102 | + $text = Filter::unescapeHtml($text); |
|
103 | + break; |
|
104 | + } |
|
105 | 105 | |
106 | - list($text) = explode("\n", $text); |
|
107 | - $this->addName('NOTE', strlen($text) > 100 ? mb_substr($text, 0, 100) . I18N::translate('…') : $text, $this->getGedcom()); |
|
108 | - } |
|
109 | - } |
|
106 | + list($text) = explode("\n", $text); |
|
107 | + $this->addName('NOTE', strlen($text) > 100 ? mb_substr($text, 0, 100) . I18N::translate('…') : $text, $this->getGedcom()); |
|
108 | + } |
|
109 | + } |
|
110 | 110 | } |
@@ -97,10 +97,10 @@ |
||
97 | 97 | |
98 | 98 | if ($text) { |
99 | 99 | switch ($this->getTree()->getPreference('FORMAT_TEXT')) { |
100 | - case 'markdown': |
|
101 | - $text = Filter::markdown($text); |
|
102 | - $text = Filter::unescapeHtml($text); |
|
103 | - break; |
|
100 | + case 'markdown': |
|
101 | + $text = Filter::markdown($text); |
|
102 | + $text = Filter::unescapeHtml($text); |
|
103 | + break; |
|
104 | 104 | } |
105 | 105 | |
106 | 106 | list($text) = explode("\n", $text); |
@@ -18,7 +18,8 @@ discard block |
||
18 | 18 | /** |
19 | 19 | * A GEDCOM note (NOTE) object. |
20 | 20 | */ |
21 | -class Note extends GedcomRecord { |
|
21 | +class Note extends GedcomRecord |
|
22 | +{ |
|
22 | 23 | const RECORD_TYPE = 'NOTE'; |
23 | 24 | const URL_PREFIX = 'note.php?nid='; |
24 | 25 | |
@@ -27,7 +28,8 @@ discard block |
||
27 | 28 | * |
28 | 29 | * @return string|null |
29 | 30 | */ |
30 | - public function getNote() { |
|
31 | + public function getNote() |
|
32 | + { |
|
31 | 33 | if (preg_match('/^0 @' . WT_REGEX_XREF . '@ NOTE ?(.*(?:\n1 CONT ?.*)*)/', $this->gedcom . $this->pending, $match)) { |
32 | 34 | return preg_replace("/\n1 CONT ?/", "\n", $match[1]); |
33 | 35 | } else { |
@@ -42,7 +44,8 @@ discard block |
||
42 | 44 | * |
43 | 45 | * @return bool |
44 | 46 | */ |
45 | - protected function canShowByType($access_level) { |
|
47 | + protected function canShowByType($access_level) |
|
48 | + { |
|
46 | 49 | // Hide notes if they are attached to private records |
47 | 50 | $linked_ids = Database::prepare( |
48 | 51 | "SELECT l_from FROM `##link` WHERE l_to=? AND l_file=?" |
@@ -67,7 +70,8 @@ discard block |
||
67 | 70 | * |
68 | 71 | * @return string |
69 | 72 | */ |
70 | - protected function createPrivateGedcomRecord($access_level) { |
|
73 | + protected function createPrivateGedcomRecord($access_level) |
|
74 | + { |
|
71 | 75 | return '0 @' . $this->xref . '@ NOTE ' . I18N::translate('Private'); |
72 | 76 | } |
73 | 77 | |
@@ -79,7 +83,8 @@ discard block |
||
79 | 83 | * |
80 | 84 | * @return null|string |
81 | 85 | */ |
82 | - protected static function fetchGedcomRecord($xref, $tree_id) { |
|
86 | + protected static function fetchGedcomRecord($xref, $tree_id) |
|
87 | + { |
|
83 | 88 | return Database::prepare( |
84 | 89 | "SELECT o_gedcom FROM `##other` WHERE o_id = :xref AND o_file = :tree_id AND o_type = 'NOTE'" |
85 | 90 | )->execute(array( |
@@ -92,7 +97,8 @@ discard block |
||
92 | 97 | * Create a name for this note - apply (and remove) markup, then take |
93 | 98 | * a maximum of 100 characters from the first line. |
94 | 99 | */ |
95 | - public function extractNames() { |
|
100 | + public function extractNames() |
|
101 | + { |
|
96 | 102 | $text = $this->getNote(); |
97 | 103 | |
98 | 104 | if ($text) { |
@@ -19,74 +19,74 @@ |
||
19 | 19 | * Measure page popularity. |
20 | 20 | */ |
21 | 21 | class HitCounter { |
22 | - /** |
|
23 | - * Count the number of times this page has been viewed. |
|
24 | - * |
|
25 | - * @param Tree $tree |
|
26 | - * @param string $page |
|
27 | - * @param string $parameter |
|
28 | - * |
|
29 | - * @return int |
|
30 | - */ |
|
31 | - public static function countHit(Tree $tree, $page, $parameter) { |
|
32 | - // Don't increment the counter while we stay on the same page. |
|
33 | - if ( |
|
34 | - Session::get('last_tree_id') === $tree->getTreeId() && |
|
35 | - Session::get('last_page') === $page && |
|
36 | - Session::get('last_parameter') === $parameter |
|
37 | - ) { |
|
38 | - return Session::get('last_count'); |
|
39 | - } |
|
22 | + /** |
|
23 | + * Count the number of times this page has been viewed. |
|
24 | + * |
|
25 | + * @param Tree $tree |
|
26 | + * @param string $page |
|
27 | + * @param string $parameter |
|
28 | + * |
|
29 | + * @return int |
|
30 | + */ |
|
31 | + public static function countHit(Tree $tree, $page, $parameter) { |
|
32 | + // Don't increment the counter while we stay on the same page. |
|
33 | + if ( |
|
34 | + Session::get('last_tree_id') === $tree->getTreeId() && |
|
35 | + Session::get('last_page') === $page && |
|
36 | + Session::get('last_parameter') === $parameter |
|
37 | + ) { |
|
38 | + return Session::get('last_count'); |
|
39 | + } |
|
40 | 40 | |
41 | - $page_count = self::getCount($tree, $page, $parameter); |
|
41 | + $page_count = self::getCount($tree, $page, $parameter); |
|
42 | 42 | |
43 | - if ($page_count === 0) { |
|
44 | - Database::prepare( |
|
45 | - "INSERT INTO `##hit_counter` (gedcom_id, page_name, page_parameter, page_count)" . |
|
46 | - " VALUES (:tree_id, :page, :parameter, 1)" |
|
47 | - )->execute(array( |
|
48 | - 'tree_id' => $tree->getTreeId(), |
|
49 | - 'page' => $page, |
|
50 | - 'parameter' => $parameter, |
|
51 | - )); |
|
52 | - } else { |
|
53 | - Database::prepare( |
|
54 | - "UPDATE `##hit_counter` SET page_count = page_count + 1" . |
|
55 | - " WHERE gedcom_id = :tree_id AND page_name = :page AND page_parameter = :parameter" |
|
56 | - )->execute(array( |
|
57 | - 'tree_id' => $tree->getTreeId(), |
|
58 | - 'page' => $page, |
|
59 | - 'parameter' => $parameter, |
|
60 | - )); |
|
61 | - } |
|
43 | + if ($page_count === 0) { |
|
44 | + Database::prepare( |
|
45 | + "INSERT INTO `##hit_counter` (gedcom_id, page_name, page_parameter, page_count)" . |
|
46 | + " VALUES (:tree_id, :page, :parameter, 1)" |
|
47 | + )->execute(array( |
|
48 | + 'tree_id' => $tree->getTreeId(), |
|
49 | + 'page' => $page, |
|
50 | + 'parameter' => $parameter, |
|
51 | + )); |
|
52 | + } else { |
|
53 | + Database::prepare( |
|
54 | + "UPDATE `##hit_counter` SET page_count = page_count + 1" . |
|
55 | + " WHERE gedcom_id = :tree_id AND page_name = :page AND page_parameter = :parameter" |
|
56 | + )->execute(array( |
|
57 | + 'tree_id' => $tree->getTreeId(), |
|
58 | + 'page' => $page, |
|
59 | + 'parameter' => $parameter, |
|
60 | + )); |
|
61 | + } |
|
62 | 62 | |
63 | - $page_count++; |
|
63 | + $page_count++; |
|
64 | 64 | |
65 | - Session::put('last_tree_id', $tree->getTreeId()); |
|
66 | - Session::put('last_page', $page); |
|
67 | - Session::put('last_parameter', $parameter); |
|
68 | - Session::put('last_count', $page_count); |
|
65 | + Session::put('last_tree_id', $tree->getTreeId()); |
|
66 | + Session::put('last_page', $page); |
|
67 | + Session::put('last_parameter', $parameter); |
|
68 | + Session::put('last_count', $page_count); |
|
69 | 69 | |
70 | - return $page_count; |
|
71 | - } |
|
70 | + return $page_count; |
|
71 | + } |
|
72 | 72 | |
73 | - /** |
|
74 | - * How many times has a page been viewed |
|
75 | - * |
|
76 | - * @param Tree $tree |
|
77 | - * @param string $page |
|
78 | - * @param string $parameter |
|
79 | - * |
|
80 | - * @return int |
|
81 | - */ |
|
82 | - public static function getCount(Tree $tree, $page, $parameter) { |
|
83 | - return (int) Database::prepare( |
|
84 | - "SELECT page_count FROM `##hit_counter`" . |
|
85 | - " WHERE gedcom_id = :tree_id AND page_name = :page AND page_parameter = :parameter" |
|
86 | - )->execute(array( |
|
87 | - 'tree_id' => $tree->getTreeId(), |
|
88 | - 'page' => $page, |
|
89 | - 'parameter' => $parameter, |
|
90 | - ))->fetchOne(); |
|
91 | - } |
|
73 | + /** |
|
74 | + * How many times has a page been viewed |
|
75 | + * |
|
76 | + * @param Tree $tree |
|
77 | + * @param string $page |
|
78 | + * @param string $parameter |
|
79 | + * |
|
80 | + * @return int |
|
81 | + */ |
|
82 | + public static function getCount(Tree $tree, $page, $parameter) { |
|
83 | + return (int) Database::prepare( |
|
84 | + "SELECT page_count FROM `##hit_counter`" . |
|
85 | + " WHERE gedcom_id = :tree_id AND page_name = :page AND page_parameter = :parameter" |
|
86 | + )->execute(array( |
|
87 | + 'tree_id' => $tree->getTreeId(), |
|
88 | + 'page' => $page, |
|
89 | + 'parameter' => $parameter, |
|
90 | + ))->fetchOne(); |
|
91 | + } |
|
92 | 92 | } |
@@ -18,7 +18,8 @@ discard block |
||
18 | 18 | /** |
19 | 19 | * Measure page popularity. |
20 | 20 | */ |
21 | -class HitCounter { |
|
21 | +class HitCounter |
|
22 | +{ |
|
22 | 23 | /** |
23 | 24 | * Count the number of times this page has been viewed. |
24 | 25 | * |
@@ -28,7 +29,8 @@ discard block |
||
28 | 29 | * |
29 | 30 | * @return int |
30 | 31 | */ |
31 | - public static function countHit(Tree $tree, $page, $parameter) { |
|
32 | + public static function countHit(Tree $tree, $page, $parameter) |
|
33 | + { |
|
32 | 34 | // Don't increment the counter while we stay on the same page. |
33 | 35 | if ( |
34 | 36 | Session::get('last_tree_id') === $tree->getTreeId() && |
@@ -79,7 +81,8 @@ discard block |
||
79 | 81 | * |
80 | 82 | * @return int |
81 | 83 | */ |
82 | - public static function getCount(Tree $tree, $page, $parameter) { |
|
84 | + public static function getCount(Tree $tree, $page, $parameter) |
|
85 | + { |
|
83 | 86 | return (int) Database::prepare( |
84 | 87 | "SELECT page_count FROM `##hit_counter`" . |
85 | 88 | " WHERE gedcom_id = :tree_id AND page_name = :page AND page_parameter = :parameter" |
@@ -19,14 +19,14 @@ |
||
19 | 19 | * Class Html - Add HTML markup to elements consistently. |
20 | 20 | */ |
21 | 21 | class Html { |
22 | - /** |
|
23 | - * Filenames are (almost?) always LTR, even on RTL systems. |
|
24 | - * |
|
25 | - * @param string $filename |
|
26 | - * |
|
27 | - * @return string |
|
28 | - */ |
|
29 | - public static function filename($filename) { |
|
30 | - return '<samp class="filename" dir="ltr">' . Filter::escapeHtml($filename) . '</samp>'; |
|
31 | - } |
|
22 | + /** |
|
23 | + * Filenames are (almost?) always LTR, even on RTL systems. |
|
24 | + * |
|
25 | + * @param string $filename |
|
26 | + * |
|
27 | + * @return string |
|
28 | + */ |
|
29 | + public static function filename($filename) { |
|
30 | + return '<samp class="filename" dir="ltr">' . Filter::escapeHtml($filename) . '</samp>'; |
|
31 | + } |
|
32 | 32 | } |
@@ -18,7 +18,8 @@ discard block |
||
18 | 18 | /** |
19 | 19 | * Class Html - Add HTML markup to elements consistently. |
20 | 20 | */ |
21 | -class Html { |
|
21 | +class Html |
|
22 | +{ |
|
22 | 23 | /** |
23 | 24 | * Filenames are (almost?) always LTR, even on RTL systems. |
24 | 25 | * |
@@ -26,7 +27,8 @@ discard block |
||
26 | 27 | * |
27 | 28 | * @return string |
28 | 29 | */ |
29 | - public static function filename($filename) { |
|
30 | + public static function filename($filename) |
|
31 | + { |
|
30 | 32 | return '<samp class="filename" dir="ltr">' . Filter::escapeHtml($filename) . '</samp>'; |
31 | 33 | } |
32 | 34 | } |
@@ -23,160 +23,160 @@ |
||
23 | 23 | * The clouds theme. |
24 | 24 | */ |
25 | 25 | class CloudsTheme extends AbstractTheme implements ThemeInterface { |
26 | - /** |
|
27 | - * Where are our CSS, JS and other assets? |
|
28 | - * |
|
29 | - * @return string A relative path, such as "themes/foo/" |
|
30 | - */ |
|
31 | - public function assetUrl() { |
|
32 | - return 'themes/clouds/css-1.7.8/'; |
|
33 | - } |
|
34 | - |
|
35 | - /** |
|
36 | - * Add markup to a flash message. |
|
37 | - * |
|
38 | - * @param \stdClass $message |
|
39 | - * |
|
40 | - * @return string |
|
41 | - */ |
|
42 | - protected function flashMessageContainer(\stdClass $message) { |
|
43 | - // This theme uses jQueryUI markup. |
|
44 | - switch ($message->status) { |
|
45 | - case 'danger': |
|
46 | - return '<p class="ui-state-error">' . $message->text . '</p>'; |
|
47 | - default: |
|
48 | - return '<p class="ui-state-highlight">' . $message->text . '</p>'; |
|
49 | - } |
|
50 | - } |
|
51 | - |
|
52 | - /** |
|
53 | - * Format the contents of a variable-height home-page block. |
|
54 | - * |
|
55 | - * @param string $id |
|
56 | - * @param string $title |
|
57 | - * @param string $class |
|
58 | - * @param string $content |
|
59 | - * |
|
60 | - * @return string |
|
61 | - */ |
|
62 | - public function formatBlock($id, $title, $class, $content) { |
|
63 | - return |
|
64 | - '<div id="' . $id . '" class="block" >' . |
|
65 | - '<table class="blockheader"><tr><td class="blockh1"></td><td class="blockh2">' . |
|
66 | - '<div class="blockhc"><b>' . $title . '</b></div>' . |
|
67 | - '</td><td class="blockh3"></td></tr></table>' . |
|
68 | - '<div class="blockcontent normal_inner_block ' . $class . '">' . $content . '</div>' . |
|
69 | - '</div>'; |
|
70 | - } |
|
71 | - |
|
72 | - /** |
|
73 | - * Create a search field and submit button for the quick search form in the header. |
|
74 | - * |
|
75 | - * @return string |
|
76 | - */ |
|
77 | - protected function formQuickSearchFields() { |
|
78 | - return |
|
79 | - '<input type="search" name="query" size="15" placeholder="' . I18N::translate('Search') . '">' . |
|
80 | - '<input class="search-icon" type="image" src="' . $this->assetUrl() . 'images/go.png" alt="' . I18N::translate('Search') . '" title="' . I18N::translate('Search') . '">'; |
|
81 | - } |
|
82 | - |
|
83 | - /** |
|
84 | - * Allow themes to add extra scripts to the page footer. |
|
85 | - * |
|
86 | - * @return string |
|
87 | - */ |
|
88 | - public function hookFooterExtraJavascript() { |
|
89 | - return |
|
90 | - '<script src="' . WT_JQUERY_COLORBOX_URL . '"></script>' . |
|
91 | - '<script src="' . WT_JQUERY_WHEELZOOM_URL . '"></script>' . |
|
92 | - '<script>' . |
|
93 | - 'activate_colorbox();' . |
|
94 | - 'jQuery.extend(jQuery.colorbox.settings, {' . |
|
95 | - ' width: "85%",' . |
|
96 | - ' height: "85%",' . |
|
97 | - ' transition: "none",' . |
|
98 | - ' slideshowStart: "' . I18N::translate('Play') . '",' . |
|
99 | - ' slideshowStop: "' . I18N::translate('Stop') . '",' . |
|
100 | - ' title: function() { return jQuery(this).data("title"); }' . |
|
101 | - '});' . |
|
102 | - '</script>'; |
|
103 | - } |
|
104 | - |
|
105 | - /** |
|
106 | - * Misecellaneous dimensions, fonts, styles, etc. |
|
107 | - * |
|
108 | - * @param string $parameter_name |
|
109 | - * |
|
110 | - * @return string|int|float |
|
111 | - */ |
|
112 | - public function parameter($parameter_name) { |
|
113 | - $parameters = array( |
|
114 | - 'chart-background-f' => 'e9daf1', |
|
115 | - 'chart-background-m' => 'b1cff0', |
|
116 | - 'chart-spacing-x' => 4, |
|
117 | - 'distribution-chart-high-values' => '95b8e0', |
|
118 | - 'distribution-chart-low-values' => 'c8e7ff', |
|
119 | - ); |
|
120 | - |
|
121 | - if (array_key_exists($parameter_name, $parameters)) { |
|
122 | - return $parameters[$parameter_name]; |
|
123 | - } else { |
|
124 | - return parent::parameter($parameter_name); |
|
125 | - } |
|
126 | - } |
|
127 | - |
|
128 | - /** |
|
129 | - * Create the primary menu. |
|
130 | - * |
|
131 | - * @param Menu[] $menus |
|
132 | - * |
|
133 | - * @return string |
|
134 | - */ |
|
135 | - protected function primaryMenuContent(array $menus) { |
|
136 | - $html = ''; |
|
137 | - |
|
138 | - foreach ($menus as $menu) { |
|
139 | - // Create an inert menu - to use as a label |
|
140 | - $tmp = new Menu($menu->getLabel(), ''); |
|
141 | - |
|
142 | - // Insert the label into the submenu |
|
143 | - $submenus = $menu->getSubmenus(); |
|
144 | - array_unshift($submenus, $tmp); |
|
145 | - $menu->setSubmenus($submenus); |
|
146 | - |
|
147 | - $html .= $menu->getMenuAsList(); |
|
148 | - } |
|
149 | - |
|
150 | - return $html; |
|
151 | - } |
|
152 | - |
|
153 | - /** |
|
154 | - * A list of CSS files to include for this page. |
|
155 | - * |
|
156 | - * @return string[] |
|
157 | - */ |
|
158 | - protected function stylesheets() { |
|
159 | - return array( |
|
160 | - 'themes/clouds/jquery-ui-1.11.2/jquery-ui.css', |
|
161 | - $this->assetUrl() . 'style.css', |
|
162 | - ); |
|
163 | - } |
|
164 | - |
|
165 | - /** |
|
166 | - * A fixed string to identify this theme, in settings, etc. |
|
167 | - * |
|
168 | - * @return string |
|
169 | - */ |
|
170 | - public function themeId() { |
|
171 | - return 'clouds'; |
|
172 | - } |
|
173 | - |
|
174 | - /** |
|
175 | - * What is this theme called? |
|
176 | - * |
|
177 | - * @return string |
|
178 | - */ |
|
179 | - public function themeName() { |
|
180 | - return /* I18N: Name of a theme. */ I18N::translate('clouds'); |
|
181 | - } |
|
26 | + /** |
|
27 | + * Where are our CSS, JS and other assets? |
|
28 | + * |
|
29 | + * @return string A relative path, such as "themes/foo/" |
|
30 | + */ |
|
31 | + public function assetUrl() { |
|
32 | + return 'themes/clouds/css-1.7.8/'; |
|
33 | + } |
|
34 | + |
|
35 | + /** |
|
36 | + * Add markup to a flash message. |
|
37 | + * |
|
38 | + * @param \stdClass $message |
|
39 | + * |
|
40 | + * @return string |
|
41 | + */ |
|
42 | + protected function flashMessageContainer(\stdClass $message) { |
|
43 | + // This theme uses jQueryUI markup. |
|
44 | + switch ($message->status) { |
|
45 | + case 'danger': |
|
46 | + return '<p class="ui-state-error">' . $message->text . '</p>'; |
|
47 | + default: |
|
48 | + return '<p class="ui-state-highlight">' . $message->text . '</p>'; |
|
49 | + } |
|
50 | + } |
|
51 | + |
|
52 | + /** |
|
53 | + * Format the contents of a variable-height home-page block. |
|
54 | + * |
|
55 | + * @param string $id |
|
56 | + * @param string $title |
|
57 | + * @param string $class |
|
58 | + * @param string $content |
|
59 | + * |
|
60 | + * @return string |
|
61 | + */ |
|
62 | + public function formatBlock($id, $title, $class, $content) { |
|
63 | + return |
|
64 | + '<div id="' . $id . '" class="block" >' . |
|
65 | + '<table class="blockheader"><tr><td class="blockh1"></td><td class="blockh2">' . |
|
66 | + '<div class="blockhc"><b>' . $title . '</b></div>' . |
|
67 | + '</td><td class="blockh3"></td></tr></table>' . |
|
68 | + '<div class="blockcontent normal_inner_block ' . $class . '">' . $content . '</div>' . |
|
69 | + '</div>'; |
|
70 | + } |
|
71 | + |
|
72 | + /** |
|
73 | + * Create a search field and submit button for the quick search form in the header. |
|
74 | + * |
|
75 | + * @return string |
|
76 | + */ |
|
77 | + protected function formQuickSearchFields() { |
|
78 | + return |
|
79 | + '<input type="search" name="query" size="15" placeholder="' . I18N::translate('Search') . '">' . |
|
80 | + '<input class="search-icon" type="image" src="' . $this->assetUrl() . 'images/go.png" alt="' . I18N::translate('Search') . '" title="' . I18N::translate('Search') . '">'; |
|
81 | + } |
|
82 | + |
|
83 | + /** |
|
84 | + * Allow themes to add extra scripts to the page footer. |
|
85 | + * |
|
86 | + * @return string |
|
87 | + */ |
|
88 | + public function hookFooterExtraJavascript() { |
|
89 | + return |
|
90 | + '<script src="' . WT_JQUERY_COLORBOX_URL . '"></script>' . |
|
91 | + '<script src="' . WT_JQUERY_WHEELZOOM_URL . '"></script>' . |
|
92 | + '<script>' . |
|
93 | + 'activate_colorbox();' . |
|
94 | + 'jQuery.extend(jQuery.colorbox.settings, {' . |
|
95 | + ' width: "85%",' . |
|
96 | + ' height: "85%",' . |
|
97 | + ' transition: "none",' . |
|
98 | + ' slideshowStart: "' . I18N::translate('Play') . '",' . |
|
99 | + ' slideshowStop: "' . I18N::translate('Stop') . '",' . |
|
100 | + ' title: function() { return jQuery(this).data("title"); }' . |
|
101 | + '});' . |
|
102 | + '</script>'; |
|
103 | + } |
|
104 | + |
|
105 | + /** |
|
106 | + * Misecellaneous dimensions, fonts, styles, etc. |
|
107 | + * |
|
108 | + * @param string $parameter_name |
|
109 | + * |
|
110 | + * @return string|int|float |
|
111 | + */ |
|
112 | + public function parameter($parameter_name) { |
|
113 | + $parameters = array( |
|
114 | + 'chart-background-f' => 'e9daf1', |
|
115 | + 'chart-background-m' => 'b1cff0', |
|
116 | + 'chart-spacing-x' => 4, |
|
117 | + 'distribution-chart-high-values' => '95b8e0', |
|
118 | + 'distribution-chart-low-values' => 'c8e7ff', |
|
119 | + ); |
|
120 | + |
|
121 | + if (array_key_exists($parameter_name, $parameters)) { |
|
122 | + return $parameters[$parameter_name]; |
|
123 | + } else { |
|
124 | + return parent::parameter($parameter_name); |
|
125 | + } |
|
126 | + } |
|
127 | + |
|
128 | + /** |
|
129 | + * Create the primary menu. |
|
130 | + * |
|
131 | + * @param Menu[] $menus |
|
132 | + * |
|
133 | + * @return string |
|
134 | + */ |
|
135 | + protected function primaryMenuContent(array $menus) { |
|
136 | + $html = ''; |
|
137 | + |
|
138 | + foreach ($menus as $menu) { |
|
139 | + // Create an inert menu - to use as a label |
|
140 | + $tmp = new Menu($menu->getLabel(), ''); |
|
141 | + |
|
142 | + // Insert the label into the submenu |
|
143 | + $submenus = $menu->getSubmenus(); |
|
144 | + array_unshift($submenus, $tmp); |
|
145 | + $menu->setSubmenus($submenus); |
|
146 | + |
|
147 | + $html .= $menu->getMenuAsList(); |
|
148 | + } |
|
149 | + |
|
150 | + return $html; |
|
151 | + } |
|
152 | + |
|
153 | + /** |
|
154 | + * A list of CSS files to include for this page. |
|
155 | + * |
|
156 | + * @return string[] |
|
157 | + */ |
|
158 | + protected function stylesheets() { |
|
159 | + return array( |
|
160 | + 'themes/clouds/jquery-ui-1.11.2/jquery-ui.css', |
|
161 | + $this->assetUrl() . 'style.css', |
|
162 | + ); |
|
163 | + } |
|
164 | + |
|
165 | + /** |
|
166 | + * A fixed string to identify this theme, in settings, etc. |
|
167 | + * |
|
168 | + * @return string |
|
169 | + */ |
|
170 | + public function themeId() { |
|
171 | + return 'clouds'; |
|
172 | + } |
|
173 | + |
|
174 | + /** |
|
175 | + * What is this theme called? |
|
176 | + * |
|
177 | + * @return string |
|
178 | + */ |
|
179 | + public function themeName() { |
|
180 | + return /* I18N: Name of a theme. */ I18N::translate('clouds'); |
|
181 | + } |
|
182 | 182 | } |
@@ -42,10 +42,10 @@ |
||
42 | 42 | protected function flashMessageContainer(\stdClass $message) { |
43 | 43 | // This theme uses jQueryUI markup. |
44 | 44 | switch ($message->status) { |
45 | - case 'danger': |
|
46 | - return '<p class="ui-state-error">' . $message->text . '</p>'; |
|
47 | - default: |
|
48 | - return '<p class="ui-state-highlight">' . $message->text . '</p>'; |
|
45 | + case 'danger': |
|
46 | + return '<p class="ui-state-error">' . $message->text . '</p>'; |
|
47 | + default: |
|
48 | + return '<p class="ui-state-highlight">' . $message->text . '</p>'; |
|
49 | 49 | } |
50 | 50 | } |
51 | 51 |
@@ -22,13 +22,15 @@ discard block |
||
22 | 22 | /** |
23 | 23 | * The clouds theme. |
24 | 24 | */ |
25 | -class CloudsTheme extends AbstractTheme implements ThemeInterface { |
|
25 | +class CloudsTheme extends AbstractTheme implements ThemeInterface |
|
26 | +{ |
|
26 | 27 | /** |
27 | 28 | * Where are our CSS, JS and other assets? |
28 | 29 | * |
29 | 30 | * @return string A relative path, such as "themes/foo/" |
30 | 31 | */ |
31 | - public function assetUrl() { |
|
32 | + public function assetUrl() |
|
33 | + { |
|
32 | 34 | return 'themes/clouds/css-1.7.8/'; |
33 | 35 | } |
34 | 36 | |
@@ -39,7 +41,8 @@ discard block |
||
39 | 41 | * |
40 | 42 | * @return string |
41 | 43 | */ |
42 | - protected function flashMessageContainer(\stdClass $message) { |
|
44 | + protected function flashMessageContainer(\stdClass $message) |
|
45 | + { |
|
43 | 46 | // This theme uses jQueryUI markup. |
44 | 47 | switch ($message->status) { |
45 | 48 | case 'danger': |
@@ -59,7 +62,8 @@ discard block |
||
59 | 62 | * |
60 | 63 | * @return string |
61 | 64 | */ |
62 | - public function formatBlock($id, $title, $class, $content) { |
|
65 | + public function formatBlock($id, $title, $class, $content) |
|
66 | + { |
|
63 | 67 | return |
64 | 68 | '<div id="' . $id . '" class="block" >' . |
65 | 69 | '<table class="blockheader"><tr><td class="blockh1"></td><td class="blockh2">' . |
@@ -74,7 +78,8 @@ discard block |
||
74 | 78 | * |
75 | 79 | * @return string |
76 | 80 | */ |
77 | - protected function formQuickSearchFields() { |
|
81 | + protected function formQuickSearchFields() |
|
82 | + { |
|
78 | 83 | return |
79 | 84 | '<input type="search" name="query" size="15" placeholder="' . I18N::translate('Search') . '">' . |
80 | 85 | '<input class="search-icon" type="image" src="' . $this->assetUrl() . 'images/go.png" alt="' . I18N::translate('Search') . '" title="' . I18N::translate('Search') . '">'; |
@@ -85,7 +90,8 @@ discard block |
||
85 | 90 | * |
86 | 91 | * @return string |
87 | 92 | */ |
88 | - public function hookFooterExtraJavascript() { |
|
93 | + public function hookFooterExtraJavascript() |
|
94 | + { |
|
89 | 95 | return |
90 | 96 | '<script src="' . WT_JQUERY_COLORBOX_URL . '"></script>' . |
91 | 97 | '<script src="' . WT_JQUERY_WHEELZOOM_URL . '"></script>' . |
@@ -109,7 +115,8 @@ discard block |
||
109 | 115 | * |
110 | 116 | * @return string|int|float |
111 | 117 | */ |
112 | - public function parameter($parameter_name) { |
|
118 | + public function parameter($parameter_name) |
|
119 | + { |
|
113 | 120 | $parameters = array( |
114 | 121 | 'chart-background-f' => 'e9daf1', |
115 | 122 | 'chart-background-m' => 'b1cff0', |
@@ -132,7 +139,8 @@ discard block |
||
132 | 139 | * |
133 | 140 | * @return string |
134 | 141 | */ |
135 | - protected function primaryMenuContent(array $menus) { |
|
142 | + protected function primaryMenuContent(array $menus) |
|
143 | + { |
|
136 | 144 | $html = ''; |
137 | 145 | |
138 | 146 | foreach ($menus as $menu) { |
@@ -155,7 +163,8 @@ discard block |
||
155 | 163 | * |
156 | 164 | * @return string[] |
157 | 165 | */ |
158 | - protected function stylesheets() { |
|
166 | + protected function stylesheets() |
|
167 | + { |
|
159 | 168 | return array( |
160 | 169 | 'themes/clouds/jquery-ui-1.11.2/jquery-ui.css', |
161 | 170 | $this->assetUrl() . 'style.css', |
@@ -167,7 +176,8 @@ discard block |
||
167 | 176 | * |
168 | 177 | * @return string |
169 | 178 | */ |
170 | - public function themeId() { |
|
179 | + public function themeId() |
|
180 | + { |
|
171 | 181 | return 'clouds'; |
172 | 182 | } |
173 | 183 | |
@@ -176,7 +186,8 @@ discard block |
||
176 | 186 | * |
177 | 187 | * @return string |
178 | 188 | */ |
179 | - public function themeName() { |
|
189 | + public function themeName() |
|
190 | + { |
|
180 | 191 | return /* I18N: Name of a theme. */ I18N::translate('clouds'); |
181 | 192 | } |
182 | 193 | } |
@@ -26,173 +26,173 @@ |
||
26 | 26 | * The colors theme. |
27 | 27 | */ |
28 | 28 | class ColorsTheme extends CloudsTheme implements ThemeInterface { |
29 | - /** @var string[] A list of color palettes */ |
|
30 | - protected $palettes; |
|
29 | + /** @var string[] A list of color palettes */ |
|
30 | + protected $palettes; |
|
31 | 31 | |
32 | - /** @var string Which of the color palettes to use on this page */ |
|
33 | - protected $palette; |
|
32 | + /** @var string Which of the color palettes to use on this page */ |
|
33 | + protected $palette; |
|
34 | 34 | |
35 | - /** |
|
36 | - * Where are our CSS, JS and other assets? |
|
37 | - * |
|
38 | - * @return string A relative path, such as "themes/foo/" |
|
39 | - */ |
|
40 | - public function assetUrl() { |
|
41 | - return 'themes/colors/css-1.7.8/'; |
|
42 | - } |
|
35 | + /** |
|
36 | + * Where are our CSS, JS and other assets? |
|
37 | + * |
|
38 | + * @return string A relative path, such as "themes/foo/" |
|
39 | + */ |
|
40 | + public function assetUrl() { |
|
41 | + return 'themes/colors/css-1.7.8/'; |
|
42 | + } |
|
43 | 43 | |
44 | - /** |
|
45 | - * Add markup to the secondary menu. |
|
46 | - * |
|
47 | - * @return string |
|
48 | - */ |
|
49 | - protected function formatSecondaryMenu() { |
|
50 | - return |
|
51 | - '<ul class="secondary-menu">' . |
|
52 | - implode('', $this->secondaryMenu()) . |
|
53 | - '<li>' . |
|
54 | - $this->formQuickSearch() . |
|
55 | - '</li>' . |
|
56 | - '</ul>'; |
|
57 | - } |
|
44 | + /** |
|
45 | + * Add markup to the secondary menu. |
|
46 | + * |
|
47 | + * @return string |
|
48 | + */ |
|
49 | + protected function formatSecondaryMenu() { |
|
50 | + return |
|
51 | + '<ul class="secondary-menu">' . |
|
52 | + implode('', $this->secondaryMenu()) . |
|
53 | + '<li>' . |
|
54 | + $this->formQuickSearch() . |
|
55 | + '</li>' . |
|
56 | + '</ul>'; |
|
57 | + } |
|
58 | 58 | |
59 | - /** |
|
60 | - * Create the contents of the <header> tag. |
|
61 | - * |
|
62 | - * @return string |
|
63 | - */ |
|
64 | - protected function headerContent() { |
|
65 | - return |
|
66 | - //$this->accessibilityLinks() . |
|
67 | - $this->formatTreeTitle() . |
|
68 | - $this->formatSecondaryMenu(); |
|
69 | - } |
|
59 | + /** |
|
60 | + * Create the contents of the <header> tag. |
|
61 | + * |
|
62 | + * @return string |
|
63 | + */ |
|
64 | + protected function headerContent() { |
|
65 | + return |
|
66 | + //$this->accessibilityLinks() . |
|
67 | + $this->formatTreeTitle() . |
|
68 | + $this->formatSecondaryMenu(); |
|
69 | + } |
|
70 | 70 | |
71 | - /** |
|
72 | - * Create resources for the colors theme. |
|
73 | - */ |
|
74 | - public function hookAfterInit() { |
|
75 | - $this->palettes = array( |
|
76 | - 'aquamarine' => /* I18N: The name of a colour-scheme */ I18N::translate('Aqua Marine'), |
|
77 | - 'ash' => /* I18N: The name of a colour-scheme */ I18N::translate('Ash'), |
|
78 | - 'belgianchocolate' => /* I18N: The name of a colour-scheme */ I18N::translate('Belgian Chocolate'), |
|
79 | - 'bluelagoon' => /* I18N: The name of a colour-scheme */ I18N::translate('Blue Lagoon'), |
|
80 | - 'bluemarine' => /* I18N: The name of a colour-scheme */ I18N::translate('Blue Marine'), |
|
81 | - 'coffeeandcream' => /* I18N: The name of a colour-scheme */ I18N::translate('Coffee and Cream'), |
|
82 | - 'coldday' => /* I18N: The name of a colour-scheme */ I18N::translate('Cold Day'), |
|
83 | - 'greenbeam' => /* I18N: The name of a colour-scheme */ I18N::translate('Green Beam'), |
|
84 | - 'mediterranio' => /* I18N: The name of a colour-scheme */ I18N::translate('Mediterranio'), |
|
85 | - 'mercury' => /* I18N: The name of a colour-scheme */ I18N::translate('Mercury'), |
|
86 | - 'nocturnal' => /* I18N: The name of a colour-scheme */ I18N::translate('Nocturnal'), |
|
87 | - 'olivia' => /* I18N: The name of a colour-scheme */ I18N::translate('Olivia'), |
|
88 | - 'pinkplastic' => /* I18N: The name of a colour-scheme */ I18N::translate('Pink Plastic'), |
|
89 | - 'sage' => /* I18N: The name of a colour-scheme */ I18N::translate('Sage'), |
|
90 | - 'shinytomato' => /* I18N: The name of a colour-scheme */ I18N::translate('Shiny Tomato'), |
|
91 | - 'tealtop' => /* I18N: The name of a colour-scheme */ I18N::translate('Teal Top'), |
|
92 | - ); |
|
93 | - uasort($this->palettes, '\Fisharebest\Webtrees\I18N::strcasecmp'); |
|
71 | + /** |
|
72 | + * Create resources for the colors theme. |
|
73 | + */ |
|
74 | + public function hookAfterInit() { |
|
75 | + $this->palettes = array( |
|
76 | + 'aquamarine' => /* I18N: The name of a colour-scheme */ I18N::translate('Aqua Marine'), |
|
77 | + 'ash' => /* I18N: The name of a colour-scheme */ I18N::translate('Ash'), |
|
78 | + 'belgianchocolate' => /* I18N: The name of a colour-scheme */ I18N::translate('Belgian Chocolate'), |
|
79 | + 'bluelagoon' => /* I18N: The name of a colour-scheme */ I18N::translate('Blue Lagoon'), |
|
80 | + 'bluemarine' => /* I18N: The name of a colour-scheme */ I18N::translate('Blue Marine'), |
|
81 | + 'coffeeandcream' => /* I18N: The name of a colour-scheme */ I18N::translate('Coffee and Cream'), |
|
82 | + 'coldday' => /* I18N: The name of a colour-scheme */ I18N::translate('Cold Day'), |
|
83 | + 'greenbeam' => /* I18N: The name of a colour-scheme */ I18N::translate('Green Beam'), |
|
84 | + 'mediterranio' => /* I18N: The name of a colour-scheme */ I18N::translate('Mediterranio'), |
|
85 | + 'mercury' => /* I18N: The name of a colour-scheme */ I18N::translate('Mercury'), |
|
86 | + 'nocturnal' => /* I18N: The name of a colour-scheme */ I18N::translate('Nocturnal'), |
|
87 | + 'olivia' => /* I18N: The name of a colour-scheme */ I18N::translate('Olivia'), |
|
88 | + 'pinkplastic' => /* I18N: The name of a colour-scheme */ I18N::translate('Pink Plastic'), |
|
89 | + 'sage' => /* I18N: The name of a colour-scheme */ I18N::translate('Sage'), |
|
90 | + 'shinytomato' => /* I18N: The name of a colour-scheme */ I18N::translate('Shiny Tomato'), |
|
91 | + 'tealtop' => /* I18N: The name of a colour-scheme */ I18N::translate('Teal Top'), |
|
92 | + ); |
|
93 | + uasort($this->palettes, '\Fisharebest\Webtrees\I18N::strcasecmp'); |
|
94 | 94 | |
95 | - // If we've selected a new palette, and we are logged in, set this value as a default. |
|
96 | - if (isset($_GET['themecolor']) && array_key_exists($_GET['themecolor'], $this->palettes)) { |
|
97 | - // Request to change color |
|
98 | - $this->palette = $_GET['themecolor']; |
|
99 | - Auth::user()->setPreference('themecolor', $this->palette); |
|
100 | - if (Auth::isAdmin()) { |
|
101 | - Site::setPreference('DEFAULT_COLOR_PALETTE', $this->palette); |
|
102 | - } |
|
103 | - unset($_GET['themecolor']); |
|
104 | - // Rember that we have selected a value |
|
105 | - Session::put('subColor', $this->palette); |
|
106 | - } |
|
107 | - // If we are logged in, use our preference |
|
108 | - $this->palette = Auth::user()->getPreference('themecolor'); |
|
109 | - // If not logged in or no preference, use one we selected earlier in the session? |
|
110 | - if (!$this->palette) { |
|
111 | - $this->palette = Session::get('subColor'); |
|
112 | - } |
|
113 | - // We haven't selected one this session? Use the site default |
|
114 | - if (!$this->palette) { |
|
115 | - $this->palette = Site::getPreference('DEFAULT_COLOR_PALETTE'); |
|
116 | - } |
|
117 | - // Make sure our selected palette actually exists |
|
118 | - if (!array_key_exists($this->palette, $this->palettes)) { |
|
119 | - $this->palette = 'ash'; |
|
120 | - } |
|
121 | - } |
|
95 | + // If we've selected a new palette, and we are logged in, set this value as a default. |
|
96 | + if (isset($_GET['themecolor']) && array_key_exists($_GET['themecolor'], $this->palettes)) { |
|
97 | + // Request to change color |
|
98 | + $this->palette = $_GET['themecolor']; |
|
99 | + Auth::user()->setPreference('themecolor', $this->palette); |
|
100 | + if (Auth::isAdmin()) { |
|
101 | + Site::setPreference('DEFAULT_COLOR_PALETTE', $this->palette); |
|
102 | + } |
|
103 | + unset($_GET['themecolor']); |
|
104 | + // Rember that we have selected a value |
|
105 | + Session::put('subColor', $this->palette); |
|
106 | + } |
|
107 | + // If we are logged in, use our preference |
|
108 | + $this->palette = Auth::user()->getPreference('themecolor'); |
|
109 | + // If not logged in or no preference, use one we selected earlier in the session? |
|
110 | + if (!$this->palette) { |
|
111 | + $this->palette = Session::get('subColor'); |
|
112 | + } |
|
113 | + // We haven't selected one this session? Use the site default |
|
114 | + if (!$this->palette) { |
|
115 | + $this->palette = Site::getPreference('DEFAULT_COLOR_PALETTE'); |
|
116 | + } |
|
117 | + // Make sure our selected palette actually exists |
|
118 | + if (!array_key_exists($this->palette, $this->palettes)) { |
|
119 | + $this->palette = 'ash'; |
|
120 | + } |
|
121 | + } |
|
122 | 122 | |
123 | - /** |
|
124 | - * Generate a list of items for the user menu. |
|
125 | - * |
|
126 | - * @return Menu[] |
|
127 | - */ |
|
128 | - protected function secondaryMenu() { |
|
129 | - return array_filter(array( |
|
130 | - $this->menuPendingChanges(), |
|
131 | - $this->menuMyPages(), |
|
132 | - $this->menuFavorites(), |
|
133 | - $this->menuThemes(), |
|
134 | - $this->menuPalette(), |
|
135 | - $this->menuLanguages(), |
|
136 | - $this->menuLogin(), |
|
137 | - $this->menuLogout(), |
|
138 | - )); |
|
139 | - } |
|
123 | + /** |
|
124 | + * Generate a list of items for the user menu. |
|
125 | + * |
|
126 | + * @return Menu[] |
|
127 | + */ |
|
128 | + protected function secondaryMenu() { |
|
129 | + return array_filter(array( |
|
130 | + $this->menuPendingChanges(), |
|
131 | + $this->menuMyPages(), |
|
132 | + $this->menuFavorites(), |
|
133 | + $this->menuThemes(), |
|
134 | + $this->menuPalette(), |
|
135 | + $this->menuLanguages(), |
|
136 | + $this->menuLogin(), |
|
137 | + $this->menuLogout(), |
|
138 | + )); |
|
139 | + } |
|
140 | 140 | |
141 | - /** |
|
142 | - * Create a menu of palette options |
|
143 | - * |
|
144 | - * @return Menu |
|
145 | - */ |
|
146 | - protected function menuPalette() { |
|
147 | - if ($this->tree && Site::getPreference('ALLOW_USER_THEMES') && $this->tree->getPreference('ALLOW_THEME_DROPDOWN')) { |
|
148 | - $menu = new Menu(/* I18N: A colour scheme */ |
|
149 | - I18N::translate('Palette'), '#', 'menu-color'); |
|
141 | + /** |
|
142 | + * Create a menu of palette options |
|
143 | + * |
|
144 | + * @return Menu |
|
145 | + */ |
|
146 | + protected function menuPalette() { |
|
147 | + if ($this->tree && Site::getPreference('ALLOW_USER_THEMES') && $this->tree->getPreference('ALLOW_THEME_DROPDOWN')) { |
|
148 | + $menu = new Menu(/* I18N: A colour scheme */ |
|
149 | + I18N::translate('Palette'), '#', 'menu-color'); |
|
150 | 150 | |
151 | - foreach ($this->palettes as $palette_id => $palette_name) { |
|
152 | - $menu->addSubmenu(new Menu( |
|
153 | - $palette_name, |
|
154 | - '#', |
|
155 | - 'menu-color-' . $palette_id . ($this->palette === $palette_id ? ' active' : ''), |
|
156 | - array( |
|
157 | - 'onclick' => 'document.location=\'' . Functions::getQueryUrl(array('themecolor' => $palette_id), '&') . '\'', |
|
158 | - ) |
|
159 | - )); |
|
160 | - } |
|
151 | + foreach ($this->palettes as $palette_id => $palette_name) { |
|
152 | + $menu->addSubmenu(new Menu( |
|
153 | + $palette_name, |
|
154 | + '#', |
|
155 | + 'menu-color-' . $palette_id . ($this->palette === $palette_id ? ' active' : ''), |
|
156 | + array( |
|
157 | + 'onclick' => 'document.location=\'' . Functions::getQueryUrl(array('themecolor' => $palette_id), '&') . '\'', |
|
158 | + ) |
|
159 | + )); |
|
160 | + } |
|
161 | 161 | |
162 | - return $menu; |
|
163 | - } else { |
|
164 | - return null; |
|
165 | - } |
|
166 | - } |
|
162 | + return $menu; |
|
163 | + } else { |
|
164 | + return null; |
|
165 | + } |
|
166 | + } |
|
167 | 167 | |
168 | - /** |
|
169 | - * A list of CSS files to include for this page. |
|
170 | - * |
|
171 | - * @return string[] |
|
172 | - */ |
|
173 | - protected function stylesheets() { |
|
174 | - return array( |
|
175 | - 'themes/colors/jquery-ui-1.11.2/jquery-ui.css', |
|
176 | - $this->assetUrl() . 'style.css', |
|
177 | - $this->assetUrl() . 'palette/' . $this->palette . '.css', |
|
178 | - ); |
|
179 | - } |
|
168 | + /** |
|
169 | + * A list of CSS files to include for this page. |
|
170 | + * |
|
171 | + * @return string[] |
|
172 | + */ |
|
173 | + protected function stylesheets() { |
|
174 | + return array( |
|
175 | + 'themes/colors/jquery-ui-1.11.2/jquery-ui.css', |
|
176 | + $this->assetUrl() . 'style.css', |
|
177 | + $this->assetUrl() . 'palette/' . $this->palette . '.css', |
|
178 | + ); |
|
179 | + } |
|
180 | 180 | |
181 | - /** |
|
182 | - * A fixed string to identify this theme, in settings, etc. |
|
183 | - * |
|
184 | - * @return string |
|
185 | - */ |
|
186 | - public function themeId() { |
|
187 | - return 'colors'; |
|
188 | - } |
|
181 | + /** |
|
182 | + * A fixed string to identify this theme, in settings, etc. |
|
183 | + * |
|
184 | + * @return string |
|
185 | + */ |
|
186 | + public function themeId() { |
|
187 | + return 'colors'; |
|
188 | + } |
|
189 | 189 | |
190 | - /** |
|
191 | - * What is this theme called? |
|
192 | - * |
|
193 | - * @return string |
|
194 | - */ |
|
195 | - public function themeName() { |
|
196 | - return /* I18N: Name of a theme. */ I18N::translate('colors'); |
|
197 | - } |
|
190 | + /** |
|
191 | + * What is this theme called? |
|
192 | + * |
|
193 | + * @return string |
|
194 | + */ |
|
195 | + public function themeName() { |
|
196 | + return /* I18N: Name of a theme. */ I18N::translate('colors'); |
|
197 | + } |
|
198 | 198 | } |
@@ -25,7 +25,8 @@ discard block |
||
25 | 25 | /** |
26 | 26 | * The colors theme. |
27 | 27 | */ |
28 | -class ColorsTheme extends CloudsTheme implements ThemeInterface { |
|
28 | +class ColorsTheme extends CloudsTheme implements ThemeInterface |
|
29 | +{ |
|
29 | 30 | /** @var string[] A list of color palettes */ |
30 | 31 | protected $palettes; |
31 | 32 | |
@@ -37,7 +38,8 @@ discard block |
||
37 | 38 | * |
38 | 39 | * @return string A relative path, such as "themes/foo/" |
39 | 40 | */ |
40 | - public function assetUrl() { |
|
41 | + public function assetUrl() |
|
42 | + { |
|
41 | 43 | return 'themes/colors/css-1.7.8/'; |
42 | 44 | } |
43 | 45 | |
@@ -46,7 +48,8 @@ discard block |
||
46 | 48 | * |
47 | 49 | * @return string |
48 | 50 | */ |
49 | - protected function formatSecondaryMenu() { |
|
51 | + protected function formatSecondaryMenu() |
|
52 | + { |
|
50 | 53 | return |
51 | 54 | '<ul class="secondary-menu">' . |
52 | 55 | implode('', $this->secondaryMenu()) . |
@@ -61,7 +64,8 @@ discard block |
||
61 | 64 | * |
62 | 65 | * @return string |
63 | 66 | */ |
64 | - protected function headerContent() { |
|
67 | + protected function headerContent() |
|
68 | + { |
|
65 | 69 | return |
66 | 70 | //$this->accessibilityLinks() . |
67 | 71 | $this->formatTreeTitle() . |
@@ -71,7 +75,8 @@ discard block |
||
71 | 75 | /** |
72 | 76 | * Create resources for the colors theme. |
73 | 77 | */ |
74 | - public function hookAfterInit() { |
|
78 | + public function hookAfterInit() |
|
79 | + { |
|
75 | 80 | $this->palettes = array( |
76 | 81 | 'aquamarine' => /* I18N: The name of a colour-scheme */ I18N::translate('Aqua Marine'), |
77 | 82 | 'ash' => /* I18N: The name of a colour-scheme */ I18N::translate('Ash'), |
@@ -125,7 +130,8 @@ discard block |
||
125 | 130 | * |
126 | 131 | * @return Menu[] |
127 | 132 | */ |
128 | - protected function secondaryMenu() { |
|
133 | + protected function secondaryMenu() |
|
134 | + { |
|
129 | 135 | return array_filter(array( |
130 | 136 | $this->menuPendingChanges(), |
131 | 137 | $this->menuMyPages(), |
@@ -143,7 +149,8 @@ discard block |
||
143 | 149 | * |
144 | 150 | * @return Menu |
145 | 151 | */ |
146 | - protected function menuPalette() { |
|
152 | + protected function menuPalette() |
|
153 | + { |
|
147 | 154 | if ($this->tree && Site::getPreference('ALLOW_USER_THEMES') && $this->tree->getPreference('ALLOW_THEME_DROPDOWN')) { |
148 | 155 | $menu = new Menu(/* I18N: A colour scheme */ |
149 | 156 | I18N::translate('Palette'), '#', 'menu-color'); |
@@ -170,7 +177,8 @@ discard block |
||
170 | 177 | * |
171 | 178 | * @return string[] |
172 | 179 | */ |
173 | - protected function stylesheets() { |
|
180 | + protected function stylesheets() |
|
181 | + { |
|
174 | 182 | return array( |
175 | 183 | 'themes/colors/jquery-ui-1.11.2/jquery-ui.css', |
176 | 184 | $this->assetUrl() . 'style.css', |
@@ -183,7 +191,8 @@ discard block |
||
183 | 191 | * |
184 | 192 | * @return string |
185 | 193 | */ |
186 | - public function themeId() { |
|
194 | + public function themeId() |
|
195 | + { |
|
187 | 196 | return 'colors'; |
188 | 197 | } |
189 | 198 | |
@@ -192,7 +201,8 @@ discard block |
||
192 | 201 | * |
193 | 202 | * @return string |
194 | 203 | */ |
195 | - public function themeName() { |
|
204 | + public function themeName() |
|
205 | + { |
|
196 | 206 | return /* I18N: Name of a theme. */ I18N::translate('colors'); |
197 | 207 | } |
198 | 208 | } |