ここの情報は古いです。ご理解頂いた上でお取り扱いください。

source: OpenPNE/trunk/webapp/lib/OpenPNE/Validator.php @ 6227

Last change on this file since 6227 was 6227, checked in by ogawa, 15 years ago

#2173:PHP4で全角スペースが削除されない場合があったのを修正

File size: 12.0 KB
Line 
1<?php
2/**
3 * @copyright 2005-2008 OpenPNE Project
4 * @license   http://www.php.net/license/3_01.txt PHP License 3.01
5 */
6
7/**
8 * ユーザー入力値バリデータクラス
9 */
10class OpenPNE_Validator
11{
12    /**
13     * @var array 検証ルール
14     * @access private
15     */
16    var $rules = array();
17
18    /**
19     * @var array 検証済みリクエストパラメタ
20     * @access private
21     */
22    var $params = array();
23
24    /**
25     * @var array エラー
26     * @access private
27     */
28    var $errors = array();
29
30    /**
31     * @var array 検証対象リクエストパラメタ
32     * @access private
33     */
34    var $requests = array();
35
36    /**
37     * @var string デフォルトフィルター
38     */
39    var $default_filter = 'ntrim,rtrim,mysqltext';
40
41    /**
42     * バリデータの初期化
43     *
44     * @param array $rules
45     * @param array $requests
46     */
47    function OpenPNE_Validator($rules = array(), $requests = array())
48    {
49        $this->rules = $rules;
50        if ($requests) {
51            $this->requests = $requests;
52        } else {
53            $this->requests = $_REQUEST;
54        }
55    }
56
57    /**
58     * ルールの追加
59     *
60     * @access public
61     * @param array $rules
62     */
63    function addRules($rules)
64    {
65        $this->rules = array_merge($this->rules, (array)$rules);
66    }
67
68    /**
69     * ルールをiniファイルから追加
70     *
71     * @access public
72     * @param string $ini_path
73     */
74    function addIniSetting($ini_path)
75    {
76        if (!is_readable($ini_path) ||
77            !$rules = parse_ini_file($ini_path, true)) {
78
79            return false;
80        }
81
82        $this->addRules($rules);
83        return true;
84    }
85
86    /**
87     * (検証済み)リクエストパラメータを取得
88     *
89     * @access public
90     * @return array
91     */
92    function getParams()
93    {
94        return $this->params;
95    }
96
97    /**
98     * エラー情報を取得
99     *
100     * @access public
101     * @return array
102     */
103    function getErrors()
104    {
105        return $this->errors;
106    }
107
108    /**
109     * (検証前の)リクエストパラメータを追加
110     *
111     * @access public
112     * @param array $requests
113     */
114    function addRequests($requests)
115    {
116        $this->requests = array_merge($this->requests, (array)$requests);
117    }
118
119    /**
120     * パラメータに検証済みの値をセット
121     *
122     * @access private
123     * @param string $key
124     * @param string $value
125     */
126    function _setParam($key, $value)
127    {
128        $this->params[$key] = $value;
129    }
130
131    /**
132     * エラー情報を設定
133     *
134     * @access private
135     * @param string $key
136     * @param string $msg エラーメッセージ
137     */
138    function _setError($key, $msg)
139    {
140        $this->errors[$key] = $msg;
141    }
142
143    /**
144     * validate
145     *
146     * @access public
147     * @return boolean エラーが発生しなかったかどうか
148     */
149    function validate()
150    {
151        foreach ($this->rules as $key => $rule) {
152            $rule = $this->_initRule($key, $rule);
153
154            $values = array();
155            if (isset($this->requests[$key])) {
156                if (!is_array($this->requests[$key])) {
157                    $values = array($this->requests[$key]);
158                } else {
159                    $values = $this->requests[$key];
160                }
161            }
162
163            if (empty($rule['is_array'])) {
164                $reqval = array_shift($values);
165                $result = $this->_filter($reqval, $rule['pre_filter']);
166
167                // 必須項目チェック
168                if (is_null($result) || $result === '') {
169                    if (!empty($rule['required'])) {
170                        if (isset($rule['required_error'])) {
171                            $error = $rule['required_error'];
172                        } else {
173                            $error = "{$rule['caption']}を入力してください";
174                        }
175                        $this->_setError($key, $error);
176                    } else {
177                        if (isset($rule['default'])) {
178                            $result = $rule['default'];
179                        } else {
180                            $result = null;
181                        }
182                    }
183                } else {
184                    $this->_validate($key, $result, $rule);
185                }
186            } else {
187                $result = array();
188                $empty = true;
189                foreach ($values as $k => $value) {
190                    $value = $this->_filter($value, $rule['pre_filter']);
191                    if (is_null($value) || $value === '') {
192                        continue;
193                    }
194
195                    $this->_validate($key, $value, $rule);
196                    $result[$k] = $value;
197                    $empty = false;
198                }
199                if ($empty) {
200                    if (!empty($rule['required'])) {
201                        if (isset($rule['required_error'])) {
202                            $error = $rule['required_error'];
203                        } else {
204                            $error = "{$rule['caption']}を入力してください";
205                        }
206                        $this->_setError($key, $error);
207                    } else {
208                        if (isset($rule['default'])) {
209                            $result = array($rule['default']);
210                        } else {
211                            $result = array();
212                        }
213                    }
214                }
215            }
216
217            $this->_setParam($key, $result);
218        }
219
220        return empty($this->errors);
221    }
222
223    /**
224     * 検証ルールの初期化
225     *
226     * @access private
227     * @param string $key
228     * @param array $rule
229     * @return array 初期化済み検証ルール
230     */
231    function _initRule($key, $rule)
232    {
233        if (!isset($rule['caption'])) {
234            $rule['caption'] = $key;
235        }
236
237        if (!isset($rule['pre_filter'])) {
238            $rule['pre_filter'] = $this->default_filter;
239        }
240
241        if (empty($rule['type'])) {
242            $rule['type'] = 'string';
243        }
244
245        if ($rule['type'] == 'int') {
246            $rule['pre_filter'] = $rule['pre_filter'] . ',intval';
247        }
248
249        return $rule;
250    }
251
252    /**
253     * _filter
254     *
255     * @access private
256     * @param string $value
257     * @param string $filter
258     * @return string フィルターを通した値
259     */
260    function _filter($value, $filter)
261    {
262        $filters = explode(',', $filter);
263        foreach ($filters as $filter) {
264            if (!empty($filter)) {
265                switch ($filter) {
266                case 'trim':
267                    if (OPENPNE_TRIM_DOUBLEBYTE_SPACE) {
268                        // 全角スペースに対応
269                        $value = preg_replace('/^[\s ]+/u', '', $value);
270                        $value = preg_replace('/[\s ]+$/u', '', $value);
271                    } else {
272                        $value = trim($value);
273                    }
274                    break;
275                case 'ltrim':
276                    if (OPENPNE_TRIM_DOUBLEBYTE_SPACE) {
277                        // 全角スペースに対応
278                        $value = preg_replace('/^[\s ]+/u', '', $value);
279                    } else {
280                        $value = ltrim($value);
281                    }
282                    break;
283                case 'rtrim':
284                    if (OPENPNE_TRIM_DOUBLEBYTE_SPACE) {
285                        // 全角スペースに対応
286                        $value = preg_replace('/[\s ]+$/u', '', $value);
287                    } else {
288                        $value = rtrim($value);
289                    }
290                    break;
291                case 'ntrim':
292                    // NULL バイト・制御文字(HT,LF,NBSP以外)をすべて削除
293                    $value = preg_replace("/[\x{0}-\x{08}\x{0b}-\x{1f}\x{7f}-\x{9f}\x{ad}]/u", '', $value);
294                    break;
295                case 'mysqltext':
296                    if (is_string($value) && strlen($value) > 65535) {
297                        $value = mb_strcut($value, 0, 65535);
298                    }
299                    break;
300                case 'intval':
301                    if (is_numeric($value)) {
302                        $value = (int)$value;
303                    }
304                    break;
305                }
306            }
307        }
308        return $value;
309    }
310
311    /**
312     * _validate
313     *
314     * @access private
315     * @param string $key
316     * @param string $reqval
317     * @param array $rule
318     * @return boolean
319     */
320    function _validate($key, $reqval, $rule)
321    {
322        // 型チェック
323        switch (strtolower($rule['type'])) {
324        case 'int':
325            if (!is_numeric($reqval)) {
326                if (isset($rule['type_error'])) {
327                    $error = $rule['type_error'];
328                } else {
329                    $error = "{$rule['caption']}は数値で入力してください";
330                }
331                $this->_setError($key, $error);
332                return false;
333            }
334            break;
335        case 'bool':
336            if ($reqval != '0' && $reqval != '1') {
337                if (isset($rule['type_error'])) {
338                    $error = $rule['type_error'];
339                } else {
340                    $error = "{$rule['caption']}の値が不正です";
341                }
342                $this->_setError($key, $error);
343                return false;
344            }
345            break;
346        case 'string':
347            break;
348        case 'regexp':
349            if (isset($rule['regexp']) && !preg_match($rule['regexp'], $reqval)) {
350                if (isset($rule['type_error'])) {
351                    $error = $rule['type_error'];
352                } else {
353                    $error = "{$rule['caption']}を正しく入力してください";
354                }
355                $this->_setError($key, $error);
356                return false;
357            }
358            break;
359        default:
360            $error = "{$rule['type']}は未定義の型です";
361            $this->_setError($key, $error);
362            return false;
363        }
364
365        // min/max チェック
366        switch ($rule['type']) {
367        case 'int':
368            // min
369            if (isset($rule['min']) && $reqval < intval($rule['min'])) {
370                if (isset($rule['min_error'])) {
371                    $error = $rule['min_error'];
372                } else {
373                    $error = "{$rule['caption']}{$rule['min']}以上の数値で入力してください";
374                }
375                $this->_setError($key, $error);
376                return false;
377            }
378            // max
379            if (isset ($rule['max']) && $reqval > $rule['max']) {
380                if (isset($rule['max_error'])) {
381                    $error = $rule['max_error'];
382                } else {
383                    $error = "{$rule['caption']}{$rule['max']}以下の数値で入力してください";
384                }
385                $this->_setError($key, $error);
386                return false;
387            }
388            break;
389        case 'string':
390        case 'regexp':
391            // min
392            if (isset($rule['min']) && (mb_strwidth($reqval, 'UTF-8') < $rule['min'])) {
393                if (isset($rule['min_error'])) {
394                    $error = $rule['min_error'];
395                } else {
396                    $error = "{$rule['caption']}は半角{$rule['min']}文字以上で入力してください";
397                }
398                $this->_setError($key, $error);
399                return false;
400            }
401            // max
402            if (isset($rule['max']) && (mb_strwidth($reqval, 'UTF-8') > $rule['max'])) {
403                if (isset($rule['max_error'])) {
404                    $error = $rule['max_error'];
405                } else {
406                    $error = "{$rule['caption']}は半角{$rule['max']}文字以内で入力してください";
407                }
408                $this->_setError($key, $error);
409                return false;
410            }
411            break;
412        }
413
414        return true;
415    }
416}
417
418?>
Note: See TracBrowser for help on using the repository browser.