Completed
Push — master ( ced7ff...ebdeb1 )
by Nazar
04:13
created

Text::set()   B

Complexity

Conditions 5
Paths 5

Size

Total Lines 48
Code Lines 24

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 16
CRAP Score 5.0984

Importance

Changes 2
Bugs 0 Features 0
Metric Value
cc 5
eloc 24
c 2
b 0
f 0
nc 5
nop 4
dl 0
loc 48
ccs 16
cts 19
cp 0.8421
crap 5.0984
rs 8.551
1
<?php
2
/**
3
 * @package   CleverStyle Framework
4
 * @author    Nazar Mokrynskyi <[email protected]>
5
 * @copyright Copyright (c) 2011-2016, Nazar Mokrynskyi
6
 * @license   MIT License, see license.txt
7
 */
8
namespace cs;
9
10
/**
11
 * @method static $this instance($check = false)
12
 */
13
class Text {
14
	use Singleton;
15
	/**
16
	 * Gets text on current language
17
	 *
18
	 * @param int      $database
19
	 * @param int|null $id             Getting may be done with group and label or with id
20
	 * @param bool     $store_in_cache If `true` - text will be stored in cache
21
	 *
22
	 * @return false|string
23
	 */
24 2
	function get ($database, $id = null, $store_in_cache = false) {
25 2
		$Cache     = Cache::instance();
26 2
		$L         = Language::instance();
27 2
		$id        = (int)$id;
28 2
		$cache_key = "texts/$database/{$id}_$L->clang";
29 2
		if ($store_in_cache && ($text = $Cache->$cache_key) !== false) {
30 2
			return $text;
31
		}
32 2
		$text = $this->get_text_by_id($database, $L->clang, $id);
33 2
		if ($text === false) {
34
			return false;
35
		}
36 2
		if ($store_in_cache) {
37 2
			$Cache->$cache_key = $text;
38
		}
39 2
		return $text;
40
	}
41
	/**
42
	 * @param int    $database
43
	 * @param string $clang
44
	 * @param int    $id
45
	 *
46
	 * @return false|string
47
	 */
48 2
	protected function get_text_by_id ($database, $clang, $id) {
49 2
		$cdb  = DB::instance()->db($database);
50 2
		$text = $cdb->qf(
51
			"SELECT `d`.`text`
52
			FROM `[prefix]texts` AS `t`
53
				LEFT JOIN `[prefix]texts_data` AS `d`
54
			ON `t`.`id` = `d`.`id`
55
			WHERE
56 2
				`t`.`id`	= $id AND
57
				`d`.`lang`	= '%s'
58 2
			LIMIT 1",
59
			$clang
60
		);
61 2
		if (!$text) {
62 2
			$text = $cdb->qf(
63
				"SELECT `d`.`text`
64
				FROM `[prefix]texts` AS `t`
65
					LEFT JOIN `[prefix]texts_data` AS `d`
66
				ON `t`.`id` = `d`.`id`
67 2
				WHERE `t`.`id` = $id
68 2
				LIMIT 1"
69
			);
70
		}
71 2
		return $text;
72
	}
73
	/**
74
	 * Search for text regardless language
75
	 *
76
	 * @param int    $database
77
	 * @param string $group
78
	 * @param string $label
79
	 * @param string $text
80
	 *
81
	 * @return array[]|false Array of items `['id' => id, 'lang' => lang]` on success, `false` otherwise
82
	 */
83
	function search ($database, $group, $label, $text) {
84
		return DB::instance()->db($database)->qfa(
85
			"SELECT
86
				`t`.`id`,
87
				`d`.`lang`
88
			FROM `[prefix]texts` AS `t`
89
				INNER JOIN `[prefix]texts_data` AS `d`
90
			ON `t`.`id` = `d`.`id`
91
			WHERE
92
				`t`.`group`		= '%s' AND
93
				`t`.`label`		= '%s' AND
94
				`d`.`text_md5`	= '%s'",
95
			$group,
96
			$label,
97
			md5($text)
98
		);
99
	}
100
	/**
101
	 * Sets text on current language
102
	 *
103
	 * @param int    $database
104
	 * @param string $group
105
	 * @param string $label
106
	 * @param string $text
107
	 *
108
	 * @return false|string If multilingual support enabled or was enabled and then disabled but translations remains - returns {¶<i>id</i>}, otherwise returns
109
	 *                      original text
110
	 */
111 2
	function set ($database, $group, $label, $text) {
112 2
		$Cache  = Cache::instance();
113 2
		$Config = Config::instance();
114 2
		$L      = Language::instance();
115 2
		$cdb    = DB::instance()->db_prime($database);
116
		/**
117
		 * Security check, do not allow to silently substitute text from another item
118
		 */
119 2
		if (preg_match('/^\{¶(\d+)\}$/', $text)) {
120
			return false;
121
		}
122
		// Find existing text id
123 2
		$id = $cdb->qfs(
124
			"SELECT `id`
125
			FROM `[prefix]texts`
126
			WHERE
127
				`label`	= '%s' AND
128
				`group`	= '%s'
129 2
			LIMIT 1",
130
			$label,
131
			$group
132
		);
133 2
		if (!$id) {
134
			// If not found - either return text directly or add new text entry and obtain id
135 2
			if (!$Config->core['multilingual']) {
136
				return $text;
137
			} else {
138 2
				$cdb->q(
139
					"INSERT INTO `[prefix]texts`
140
						(
141
							`label`,
142
							`group`
143
						) VALUES (
144
							'%s',
145
							'%s'
146 2
						)",
147
					$label,
148
					$group
149
				);
150 2
				$id = $cdb->id();
151 2
				if (!$id) {
152
					return $text;
153
				}
154
			}
155
		}
156 2
		$Cache->del("texts/$database/{$id}_$L->clang");
157 2
		return $this->set_text($id, $text, $cdb, (bool)$Config->core['multilingual'], $L->clang);
1 ignored issue
show
Bug introduced by
It seems like $cdb defined by \cs\DB::instance()->db_prime($database) on line 115 can also be of type object<cs\False_class>; however, cs\Text::set_text() does only seem to accept object<cs\DB\_Abstract>, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
158
	}
159
	/**
160
	 * @param int          $id
161
	 * @param string       $text
162
	 * @param DB\_Abstract $cdb
163
	 * @param bool         $multilingual
164
	 * @param string       $clang
165
	 *
166
	 * @return mixed
167
	 */
168 2
	protected function set_text ($id, $text, $cdb, $multilingual, $clang) {
169 2
		$exists_for_current_language = $cdb->qfs(
170
			"SELECT `id`
171
			FROM `[prefix]texts_data`
172
			WHERE
173
				`id`	= '%s' AND
174
				`lang`	= '%s'
175 2
			LIMIT 1",
176
			$id,
177
			$clang
178
		);
179 2
		if ($exists_for_current_language) {
180
			if ($cdb->q(
181
				"UPDATE `[prefix]texts_data`
182
				SET
183
					`text`		= '%s',
184
					`text_md5`	= '%s'
185
				WHERE
186
					`id` = '%s' AND
187
					`lang` = '%s'",
188
				$text,
189
				md5($text),
190
				$id,
191
				$clang
192
			)
193
			) {
194
				return "{¶$id}";
195
			}
196 2
		} elseif ($multilingual) {
197 2
			if ($cdb->q(
198
				"INSERT INTO `[prefix]texts_data`
199
					(
200
						`id`,
201
						`id_`,
202
						`lang`,
203
						`text`,
204
						`text_md5`
205
					) VALUES (
206
						'%s',
207
						'%s',
208
						'%s',
209
						'%s',
210
						'%s'
211 2
					)",
212
				$id,
213 2
				"{¶$id}",
214
				$clang,
215
				$text,
216
				md5($text)
217
			)
218
			) {
219 2
				return "{¶$id}";
220
			}
221
		}
222
		return $text;
223
	}
224
	/**
225
	 * Deletes text on all languages
226
	 *
227
	 * @param int    $database
228
	 * @param string $group
229
	 * @param string $label
230
	 *
231
	 * @return bool
232
	 */
233
	function del ($database, $group, $label) {
234
		$Cache = Cache::instance();
235
		$cdb   = DB::instance()->db_prime($database);
236
		$id    = $cdb->qfs(
237
			[
238
				"SELECT `id`
239
				FROM `[prefix]texts`
240
				WHERE
241
					`group`	= '%s' AND
242
					`label`	= '%s'
243
				LIMIT 1",
244
				$group,
245
				$label
246
			]
247
		);
248
		if ($id) {
249
			$L = Language::instance();
250
			$Cache->del("texts/$database/{$id}_$L->clang");
251
			return $cdb->q(
252
				[
253
					"DELETE FROM `[prefix]texts`
254
					WHERE `id` = '%s'",
255
					"DELETE FROM `[prefix]texts_data`
256
					WHERE `id` = '%s'"
257
				],
258
				$id
259
			);
260
		}
261
		return true;
262
	}
263
	/**
264
	 * Process text, and replace {¶([0-9]+)} on real text, is used before showing multilingual information
265
	 *
266
	 * @param int             $database
267
	 * @param string|string[] $data
268
	 * @param bool            $store_in_cache If <b>true</b> - text will be stored in cache
269
	 *
270
	 * @return string|string[]
1 ignored issue
show
Documentation introduced by
Should the return type not be array|string? Also, consider making the array more specific, something like array<String>, or String[].

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

If the return type contains the type array, this check recommends the use of a more specific type like String[] or array<String>.

Loading history...
271
	 */
272 36
	function process ($database, $data, $store_in_cache = false) {
273 36
		if (is_array($data)) {
274
			foreach ($data as &$d) {
275
				$d = $this->process($database, $d);
276
			}
277
			return $data;
278
		}
279 36
		return preg_replace_callback(
280 36
			'/^\{¶(\d+)\}$/',
281 36
			function ($input) use ($database, $store_in_cache) {
282 2
				return $this->get($database, $input[1], $store_in_cache);
283 36
			},
284
			$data
285
		);
286
	}
287
}
288