Commit 3b7aeda1 by LiuJunYi

导入会员

parent c4ff573e
<?php
namespace app\admin\controller;
use cocolait\extend\Excel;
use think\Exception;
use app\common\model\VipRelation as VipRelationModel;
class VipRelation extends AuthBase
{
/**
* 导入列表
*/
public function index()
{
$list = VipRelationModel::order('id','desc')->paginate();
return $this->fetch('',compact('list'));
}
public function excel()
{
try {
$file = request()->file('file')->getInfo();
//获取导入的数据
$data = Excel::excelFileToArray($file['tmp_name'], pathinfo($file['name'], PATHINFO_EXTENSION));
unset($data[0]);
$params = [];
foreach ($data as $k => $v) {
$arr = [
'nickname' => $v[0],
'mobile' => $v[1],
'wx_number' => $v[2],
'vip_expire' => str_replace('_','/',$v[3]),
'address' => $v[4],
];
array_push($params, $arr);
}
$model = new VipRelationModel();
$model->saveAll($params);
return json(['code' => 0, 'msg' => '导入成功']);
} catch (Exception $e) {
return json(['code' => 1, 'msg' => $e->getMessage()]);
}
}
}
\ No newline at end of file
{layout name="public/layout_main"}
<link rel="stylesheet" href="/static/layui/css/layui.css">
<section class="wrapper" >
<h3 style="margin-top: 15px;"><i class="fa fa-angle-right"></i> 用户管理</h3>
<!-- 分割线 -->
<hr>
<div class="row margin-bottom">
<div class="col-md-12">
<!--<form class="form-inline pull-left" method="GET" action="{:url('admin/user/index')}" >-->
<!--<div class="form-group margin-right">-->
<!--<input class="form-control" type="text" name="phone" id="phone" value="{:input('phone')}" placeholder="手机号"/>-->
<!--</div>-->
<!--<div class="form-group margin-right">-->
<!--<input class="form-control" type="text" name="nickname" id="nickname" value="{:input('nickname')}" placeholder="昵称"/>-->
<!--</div>-->
<!--<div class="form-group margin-right">-->
<!--<select name="is_vip" id="is_vip" class="form-control">-->
<!--<option value="">是否会员</option>-->
<!--<option value="1" {if condition="input('is_vip')==1"}selected{/if}>会员</option>-->
<!--<option value="0" {if condition="input('is_vip')==='0'"}selected{/if}>非会员</option>-->
<!--</select>-->
<!--</div>-->
<!--<div class="form-group margin-right">-->
<!--<label for="">注册时间:</label>-->
<!--<input class="form-control" type="date" name="start_time" id="start_time" value="{:input('start_time')}" placeholder="起始"/>-->
<!--&#45;&#45;-->
<!--<input class="form-control" type="date" name="end_time" id="end_time" value="{:input('end_time')}" placeholder="结束"/>-->
<!--</div>-->
<!--<button type="submit" class="btn btn-primary">搜索</button>-->
<!--</form>-->
<button type="button" class="layui-btn pull-right" id="excel"><i class="layui-icon"></i>导入会员列表</button>
</div>
</div>
<div class="row">
<div class="col-md-12">
<div class="table-responsive">
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>ID</th>
<th>用户名</th>
<th>手机号</th>
<th>微信号</th>
<th>地址</th>
<th>会员到期时间</th>
<th>是否关联</th>
</tr>
</thead>
<tbody>
{foreach $list as $v}
<tr>
<td>{$v.id}</td>
<td>{$v.nickname}</td>
<td>{$v.mobile}</td>
<td>{$v.wx_number}</td>
<td>{$v.address}</td>
<td>{$v.vip_expire}</td>
<td>{$v.relation}</td>
</tr>
{/foreach}
</tbody>
</table>
</div>
</div>
</div>
<div class="row">
<div class="col-md-12">
{$list->render()}
</div>
</div>
</section>
<script src="/static/layui/layui.js"></script>
<script type="text/javascript">
layui.use(['jquery','layer','upload'],function () {
var $ = layui.jquery
,layer = layui.layer
,upload = layui.upload;
//指定允许上传的文件类型
upload.render({
elem: '#excel'
,url: "{:url('excel')}"
,accept: 'file' //普通文件
,done: function(res){
console.log(res)
}
});
});
</script>
...@@ -47,15 +47,9 @@ class Project extends Base ...@@ -47,15 +47,9 @@ class Project extends Base
if (input('?post.type')) $map['type'] = input('post.type/d'); if (input('?post.type')) $map['type'] = input('post.type/d');
//根据分类 //根据分类
if (input('?post.catalog_id')) $map['catalog_id'] = input('post.catalog_id'); if (input('?post.catalog_id')) $map['catalog_id'] = input('post.catalog_id');
//根据地区分类/国内国外
if (input('post.region_type')) {
$map['region_type'] = input('post.region_type');
} else {
if (input('?post.city')) $map['city'] = input('post.city');
}
//根据标签划分 //根据标签划分
if (input('?post.tags')) { if (input('?post.tags')) {
$tags = []; $tags = [];
$tagArray = json_decode(input('post.tags'), true); $tagArray = json_decode(input('post.tags'), true);
if ($tagArray) { if ($tagArray) {
if (count($tagArray) == 1) { if (count($tagArray) == 1) {
...@@ -74,6 +68,25 @@ class Project extends Base ...@@ -74,6 +68,25 @@ class Project extends Base
} }
$project = ProjectModel::all(function ($query) use ($map, $p, $page) { $project = ProjectModel::all(function ($query) use ($map, $p, $page) {
$query->where($map) $query->where($map)
->where(function ($query) {
//地域
if (input('level_1')) {
$query->where('level_1', input('level_1'));
}
if (input('level_2')) {
$query->where('level_2', input('level_2'));
}
if (input('level_3')) {
$query->where('level_3', input('level_3'));
}
if (input('sort') == 'id') {
$query->order('id', 'desc');
} elseif (input('price') == 'price') {
$query->order('price');
} else {
$query->order('sort', 'desc')->order('id', 'desc');
}
})
->order('sort', 'desc') ->order('sort', 'desc')
->page($p, $page); ->page($p, $page);
}); });
...@@ -218,6 +231,9 @@ class Project extends Base ...@@ -218,6 +231,9 @@ class Project extends Base
public function guides($p = 1, $page = 8) public function guides($p = 1, $page = 8)
{ {
$guides = GuideModel::all(function ($query) use ($p, $page) { $guides = GuideModel::all(function ($query) use ($p, $page) {
if(input('title')){
$query->where('title','like','%'.input('title').'%');
}
$query->order('sort', 'desc')->order('id', 'desc') $query->order('sort', 'desc')->order('id', 'desc')
->page($p, $page); ->page($p, $page);
}); });
...@@ -232,11 +248,11 @@ class Project extends Base ...@@ -232,11 +248,11 @@ class Project extends Base
* @param int pid 活动/商家id * @param int pid 活动/商家id
* @return json * @return json
*/ */
public function collect($pid = 0) public function collect($pid = 0)
{ {
if (empty($pid)) return ['code' => 1, 'msg' => '缺少参数pid']; if (empty($pid)) return ['code' => 1, 'msg' => '缺少参数pid'];
$uid = $this->userinfo[0]; $uid = $this->userinfo[0];
$data = UserCollectionModel::get(['uid' => $uid, 'pid' => $pid]); $data = UserCollectionModel::get(['uid' => $uid, 'pid' => $pid]);
$project = ProjectModel::get($pid); $project = ProjectModel::get($pid);
if (!$project) return ['code' => 1, 'msg' => '活动或该商家不存在']; if (!$project) return ['code' => 1, 'msg' => '活动或该商家不存在'];
if ($data) { if ($data) {
...@@ -271,10 +287,10 @@ class Project extends Base ...@@ -271,10 +287,10 @@ class Project extends Base
*/ */
public function searchCondition() public function searchCondition()
{ {
$data['type'] = [['id' => 1, 'name' => '活动'], ['id' => 2, 'name' => '商家']]; $data['type'] = [['id' => 1, 'name' => '活动'], ['id' => 2, 'name' => '商家']];
$data['catalog_id'] = collection(CatalogsModel::order('sort', 'desc')->select())->visible(['id', 'name'])->toArray(); $data['catalog_id'] = collection(CatalogsModel::order('sort', 'desc')->select())->visible(['id', 'name'])->toArray();
$data['city'] = collection(CitysModel::order('sort', 'desc')->select())->visible(['id', 'name'])->toArray(); $data['city'] = collection(CitysModel::order('sort', 'desc')->select())->visible(['id', 'name'])->toArray();
$data['tags'] = collection(TagsModel::order('sort', 'desc')->select())->visible(['id', 'name'])->toArray(); $data['tags'] = collection(TagsModel::order('sort', 'desc')->select())->visible(['id', 'name'])->toArray();
if (!$data) return ['code' => 1, 'msg' => '没有更多']; if (!$data) return ['code' => 1, 'msg' => '没有更多'];
array_unshift($data['type'], ['id' => '0', 'name' => "全部项目"]); array_unshift($data['type'], ['id' => '0', 'name' => "全部项目"]);
array_unshift($data['catalog_id'], ['id' => '0', 'name' => "全部分类"]); array_unshift($data['catalog_id'], ['id' => '0', 'name' => "全部分类"]);
...@@ -302,16 +318,16 @@ class Project extends Base ...@@ -302,16 +318,16 @@ class Project extends Base
// 是否过期 // 是否过期
$endTime = strtotime($project['sign_endtime']); $endTime = strtotime($project['sign_endtime']);
// 正常 // 正常
$project['status'] = 0; $project['status'] = 0;
$project['status_text'] = '立即报名'; $project['status_text'] = '立即报名';
if (strtotime($project['sign_endtime']) < time()) { if (strtotime($project['sign_endtime']) < time()) {
// 已过期 // 已过期
$project['status'] = 1; $project['status'] = 1;
$project['status_text'] = '预约下次'; $project['status_text'] = '预约下次';
} else { } else {
if (intval($project['sign_limits']) <= intval($project['sign_num'])) { if (intval($project['sign_limits']) <= intval($project['sign_num'])) {
// 已售罄 // 已售罄
$project['status'] = 2; $project['status'] = 2;
$project['status_text'] = '已售罄'; $project['status_text'] = '已售罄';
} }
} }
...@@ -366,7 +382,7 @@ class Project extends Base ...@@ -366,7 +382,7 @@ class Project extends Base
'pid' => 'require', 'pid' => 'require',
'expectation_time' => 'require', 'expectation_time' => 'require',
]); ]);
$res = $validate->check(input('post.')); $res = $validate->check(input('post.'));
if (!$res) return ['code' => 1, 'msg' => $validate->getError()]; if (!$res) return ['code' => 1, 'msg' => $validate->getError()];
if (!ProjectModel::get(input('post.pid'))) { if (!ProjectModel::get(input('post.pid'))) {
return ['code' => 1, 'msg' => '该活动不存在']; return ['code' => 1, 'msg' => '该活动不存在'];
......
<?php
namespace app\common\model;
class VipRelation extends BaseModel
{
// 设置当前模型对应的完整数据表名称
protected $table = 'mr_vip_relation';
protected $type = [
'vip_expire' => 'datetime',
];
public function getRelationAttr($v,$data)
{
$arr = ['未关联','已关联'];
return $arr[$data['is_relation']];
}
}
\ No newline at end of file
...@@ -21,7 +21,8 @@ ...@@ -21,7 +21,8 @@
"qiniu/php-sdk": "^7.1", "qiniu/php-sdk": "^7.1",
"jiguang/jmessage": "1.0.*", "jiguang/jmessage": "1.0.*",
"phpoffice/phpexcel": "^1.8", "phpoffice/phpexcel": "^1.8",
"topthink/think-captcha":"1.0.7" "topthink/think-captcha":"1.0.7",
"cocolait/excel": "^2.0"
}, },
"extra": { "extra": {
"think-path": "thinkphp" "think-path": "thinkphp"
......
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
# excel
PHP excel表格处理
## 链接
- 博客:http://www.mgchen.com
- github:https://github.com/cocolait
- gitee:http://gitee.com/cocolait
# 安装
```php
composer require cocolait/excel
```
# 版本要求
> PHP >= 5.3
# 使用说明
> 该扩展包适用于任何框架
# 使用案例
```php
<?php
// 加载包 如果你使用的框架已经支持自动加载composer了 这行那么就可以省略了
require "vendor/autoload.php"
// excel表格处理
// 导入Excel文件
$data = \cocolait\extend\Excel::importExcel('上传文件名称','上传文件目录');
// 导出Excel文件
$data = \cocolait\extend\Excel::exportExcel('文件名称','设置Excel表格第一行的显示','需要导出的所有数据');
// Excel转换Array
$data = \cocolait\extend\Excel::excelFileToArray('Excel文件全路径','文件后缀 默认是 xls');
```
\ No newline at end of file
{
"name": "cocolait/excel",
"description": "PHP excel表格处理",
"type": "library",
"homepage": "http://www.mgchen.com/",
"require": {
"php": ">=5.3.0",
"siriusphp/upload": "^2.1",
"phpoffice/phpexcel": "1.8.*"
},
"license": "Apache-2.0",
"authors": [
{
"name": "cocolait",
"email": "enkipen@qq.com"
}
],
"repositories": {
"packagist": {
"type": "composer",
"url": "https://packagist.phpcomposer.com"
}
},
"config": {
"preferred-install": "dist"
},
"minimum-stability": "stable",
"autoload" : {
"psr-4" : {
"cocolait\\extend\\" : "src/"
}
}
}
\ No newline at end of file
<?php
namespace cocolait\extend;
/**
* Excel表格处理
* Created by PhpStorm.
* User: Cocolait
* Date: 2018/05/17
* Time: 15:30
* 博 客:http://www.mgchen.com
*/
final class Excel{
/**
* 上传依赖包下载 composer require siriusphp/upload:^2.1
* 导入Excel文件
* @param string $input_Name 上传文件名称 示例 <input type="file" name="excel"/>
* @param string $dir 上传文件目录
* @return array
* @throws \Exception
*/
public static function importExcel($input_Name = 'excel',$dir = '') {
if (!$dir) {
$dir = "./uploads/excel" . "/" . date('Ymd');
}
if (!file_exists($dir)) {
if (!self::directory($dir)) {
return ['error'=>'1','msg'=>"无法创建目录:" . $dir];
};
}
//引入Composer第三方扩展上传类
$uploadHandler = new \Sirius\Upload\Handler($dir);
$uploadHandler->addRule('extension', ['allowed' => ['xls', 'xlsx']], '只能上传后缀为(.xls, .xlsx)文件');
$uploadHandler->addRule('size', ['max' => '10M'], '文件最大上传为10M');
$result = $uploadHandler->process($_FILES[$input_Name]);
if ($result->isValid()) {
try {
$result->confirm(); // 删除后缀.lock文件
$ext = substr(strrchr($result->name,'.'),1);
$filename = $dir . "/" . $result->name;
$data = self::excelFileToArray($filename, $ext);
if(count($data)==0 && $ext=='xlsx'){
return ['error' => 1,'msg'=>'内容为空或文件格式无效,建议转换为xls格式再次重试'];
}
//写入文件
return ['error'=>0,'msg'=> '上传成功 ^_^','url' => $filename,'file_name' => $result->name];
} catch (\Exception $e) {
$result->clear();
throw $e;
}
} else {
$message = $result->getMessages();
$error = '';
foreach ($message as $v) {
$error = $v->template;
}
return ['error' => 1,'msg'=> $error];
}
}
/**
* 导出Excel文件
* @param string $fileName 文件名称
* @param array $excelColumnItem 设置Excel表格第一行的显示
* @param array $data 载入表格的所有数据
* @return bool
* @throws \PHPExcel_Exception
* @throws \PHPExcel_Reader_Exception
* 运用实例
* $excelColumnItem = ['用户名','邮箱','个性签名'];
* $fileName = '后台用户信息表';
* $testData = Db::name('admin')->field(['username','email','signature'])->select();
* $data = [];
foreach ($testData as $k => $v){
$excelData[$k]['username'] = $v['username'];
$excelData[$k]['email'] = $v['email'];
$excelData[$k]['signature'] = $v['signature'];
}
外部调用 : \Cocolait\CpExcel::exportExcel($fileName,$excelColumnItem,$data);
生成表格
* 处理表格中 银行卡号或者数字长度问题 可用 chunk_split()函数进行处理,其实就是分割数字字符,不懂得自行查询php;
* chunk_split(string 要分割的字符 , int 分割位数, string 分割字符);
* 使用案例 chunk_split('201701061051',4," ");已4位数字分割,中间已空格隔开。
*/
public static function exportExcel($fileName = '', $excelColumnItem = [], $data = []){
$date = date("Y_m_d", time());
$fileName .= "_{$date}.xls";
$objPHPExcel = new \PHPExcel();
$objPHPExcel->getProperties();
// 设置表头
$key = ord("A");
foreach ($excelColumnItem as $v) {
$colum = chr($key);
$objPHPExcel->setActiveSheetIndex(0)->setCellValue($colum . '1', $v);
$objPHPExcel->setActiveSheetIndex(0)->setCellValue($colum . '1', $v);
$key += 1;
}
$column = 2;
$objActSheet = $objPHPExcel->getActiveSheet();
foreach ($data as $key => $rows) {// 行写入
$span = ord("A");
foreach ($rows as $keyName => $value) {// 列写入
$j = chr($span);
$objActSheet->setCellValue($j . $column, $value);
$span ++;
}
$column ++;
}
$fileName = iconv("utf-8", "gb2312", $fileName);
// 重命名表
$objPHPExcel->setActiveSheetIndex(0);
header('Content-Type: application/vnd.ms-excel');
header("Content-Disposition: attachment;filename=\"$fileName\"");
header('Cache-Control: max-age=0');
$objWriter = \PHPExcel_IOFactory::createWriter($objPHPExcel, 'Excel5');
$objWriter->save('php://output');//文件通过浏览器下载
return true;
}
/**
* Excel文件转换为数组数据
* @param String $filePath Excel文件全路径[文件名称]
* @param string $exts 文件后缀 默认是 xls
* @return array
* @throws \PHPExcel_Exception
*/
public static function excelFileToArray($filePath, $exts = 'xls')
{
if (!in_array($exts,['xls','xlsx'])) {
return ['error' => 1, 'msg' => '只支持‘xls,xlsx’类型的格式'];
}
// 检测后缀,实例化具体操作类
if ($exts == 'xls') {
$PHPReader = new \PHPExcel_Reader_Excel5();
} else if ($exts == 'xlsx') {
//偶尔不wps另存为的xlsx文件
$PHPReader = new \PHPExcel_Reader_Excel2007();
}
// 读取Excel文件
$PHPExcel = $PHPReader->load($filePath);
// 获取表中的第一个工作表,如果要获取第二个,把0改为1,依次类推
$currentSheet = $PHPExcel->getSheet(0);
// 获取总列数
$allColumn = $currentSheet->getHighestColumn();
// 获取总行数
$allRow = $currentSheet->getHighestRow();
//循环读取数据,默认编码是utf8
$data = [];
// 循环获取表中的数据,$currentRow表示当前行,从哪行开始读取数据,索引值从0开始
for($currentRow = 1;$currentRow<=$allRow;$currentRow++)
{
// 从哪列开始,A表示第一列
for($currentColumn='A';$currentColumn<=$allColumn;$currentColumn++)
{
// 数据坐标
$address = $currentColumn.$currentRow;
// 获取单元格的值
$v = $currentSheet->getCell($address)->getValue();
// 匹配http/https
$preg_url = "/^((http|https):\/\/)+[\w-_.]+(\/[\w-_]+)*\/?$/";
// 过滤时间
if (preg_match("/^[0-9]{5}.[0-9]{1,20}$/",$v) && strrpos($v,'.') && \PHPExcel_Shared_Date::isDateTime($currentSheet->getCell($address))) {
// 匹配时间并且进行格式化
$data[$currentRow-1][$currentColumn] = gmdate("Y/m/d H:i", \PHPExcel_Shared_Date::ExcelToPHP($v));
} else if (preg_match($preg_url,$v)) {
// 匹配url
$data[$currentRow-1][$currentColumn] = "<a href='$v'>$v</a>";
} else {
$data[$currentRow-1][$currentColumn] = $v;
}
}
}
//处理空白数组
$res = [];
if ($data) {
foreach($data as $k => $v) {
$res[] = array_values($v);
}
}
return $res;
}
/**
* 抛出异常
* @param $error
* @throws \Exception
*/
protected static function throwException($error)
{
throw new \Exception($error);
}
/**
* 递归创建目录
* @param $dir
* @return bool
*/
protected static function directory($dir)
{
return is_dir ($dir) or self::directory(dirname($dir)) and mkdir ($dir, 0777);
}
}
\ No newline at end of file
...@@ -374,10 +374,14 @@ class ClassLoader ...@@ -374,10 +374,14 @@ class ClassLoader
$first = $class[0]; $first = $class[0];
if (isset($this->prefixLengthsPsr4[$first])) { if (isset($this->prefixLengthsPsr4[$first])) {
foreach ($this->prefixLengthsPsr4[$first] as $prefix => $length) { $subPath = $class;
if (0 === strpos($class, $prefix)) { while (false !== $lastPos = strrpos($subPath, '\\')) {
foreach ($this->prefixDirsPsr4[$prefix] as $dir) { $subPath = substr($subPath, 0, $lastPos);
if (file_exists($file = $dir . DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $length))) { $search = $subPath . '\\';
if (isset($this->prefixDirsPsr4[$search])) {
$pathEnd = DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $lastPos + 1);
foreach ($this->prefixDirsPsr4[$search] as $dir) {
if (file_exists($file = $dir . $pathEnd)) {
return $file; return $file;
} }
} }
......
Copyright (c) 2016 Nils Adermann, Jordi Boggiano Copyright (c) Nils Adermann, Jordi Boggiano
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal
......
...@@ -9,6 +9,9 @@ return array( ...@@ -9,6 +9,9 @@ return array(
'think\\composer\\' => array($vendorDir . '/topthink/think-installer/src'), 'think\\composer\\' => array($vendorDir . '/topthink/think-installer/src'),
'think\\captcha\\' => array($vendorDir . '/topthink/think-captcha/src'), 'think\\captcha\\' => array($vendorDir . '/topthink/think-captcha/src'),
'think\\' => array($baseDir . '/thinkphp/library/think'), 'think\\' => array($baseDir . '/thinkphp/library/think'),
'cocolait\\extend\\' => array($vendorDir . '/cocolait/excel/src'),
'Sirius\\Validation\\' => array($vendorDir . '/siriusphp/validation/src'),
'Sirius\\Upload\\' => array($vendorDir . '/siriusphp/upload/src'),
'Qiniu\\' => array($vendorDir . '/qiniu/php-sdk/src/Qiniu'), 'Qiniu\\' => array($vendorDir . '/qiniu/php-sdk/src/Qiniu'),
'JMessage\\' => array($vendorDir . '/jiguang/jmessage/src/JMessage'), 'JMessage\\' => array($vendorDir . '/jiguang/jmessage/src/JMessage'),
); );
...@@ -18,6 +18,15 @@ class ComposerStaticInit6a7a2aa86217a80f5a5c162d0365f49c ...@@ -18,6 +18,15 @@ class ComposerStaticInit6a7a2aa86217a80f5a5c162d0365f49c
'think\\captcha\\' => 14, 'think\\captcha\\' => 14,
'think\\' => 6, 'think\\' => 6,
), ),
'c' =>
array (
'cocolait\\extend\\' => 16,
),
'S' =>
array (
'Sirius\\Validation\\' => 18,
'Sirius\\Upload\\' => 14,
),
'Q' => 'Q' =>
array ( array (
'Qiniu\\' => 6, 'Qiniu\\' => 6,
...@@ -41,6 +50,18 @@ class ComposerStaticInit6a7a2aa86217a80f5a5c162d0365f49c ...@@ -41,6 +50,18 @@ class ComposerStaticInit6a7a2aa86217a80f5a5c162d0365f49c
array ( array (
0 => __DIR__ . '/../..' . '/thinkphp/library/think', 0 => __DIR__ . '/../..' . '/thinkphp/library/think',
), ),
'cocolait\\extend\\' =>
array (
0 => __DIR__ . '/..' . '/cocolait/excel/src',
),
'Sirius\\Validation\\' =>
array (
0 => __DIR__ . '/..' . '/siriusphp/validation/src',
),
'Sirius\\Upload\\' =>
array (
0 => __DIR__ . '/..' . '/siriusphp/upload/src',
),
'Qiniu\\' => 'Qiniu\\' =>
array ( array (
0 => __DIR__ . '/..' . '/qiniu/php-sdk/src/Qiniu', 0 => __DIR__ . '/..' . '/qiniu/php-sdk/src/Qiniu',
......
[ [
{ {
"name": "topthink/think-installer", "name": "cocolait/excel",
"version": "v1.0.12", "version": "2.0",
"version_normalized": "1.0.12.0", "version_normalized": "2.0.0.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/top-think/think-installer.git", "url": "https://github.com/cocolait/excel.git",
"reference": "1be326e68f63de4e95977ed50f46ae75f017556d" "reference": "56fa31e98518cbad4c31148242e8a6093da576aa"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/top-think/think-installer/zipball/1be326e68f63de4e95977ed50f46ae75f017556d", "url": "https://api.github.com/repos/cocolait/excel/zipball/56fa31e98518cbad4c31148242e8a6093da576aa",
"reference": "1be326e68f63de4e95977ed50f46ae75f017556d", "reference": "56fa31e98518cbad4c31148242e8a6093da576aa",
"shasum": "" "shasum": "",
"mirrors": [
{
"url": "https://dl.laravel-china.org/%package%/%reference%.%type%",
"preferred": true
}
]
}, },
"require": { "require": {
"composer-plugin-api": "^1.0" "php": ">=5.3.0",
}, "phpoffice/phpexcel": "1.8.*",
"require-dev": { "siriusphp/upload": "^2.1"
"composer/composer": "1.0.*@dev"
},
"time": "2017-05-27T06:58:09+00:00",
"type": "composer-plugin",
"extra": {
"class": "think\\composer\\Plugin"
}, },
"time": "2018-05-17T02:11:32+00:00",
"type": "library",
"installation-source": "dist", "installation-source": "dist",
"autoload": { "autoload": {
"psr-4": { "psr-4": {
"think\\composer\\": "src" "cocolait\\extend\\": "src/"
} }
}, },
"notification-url": "https://packagist.org/downloads/", "notification-url": "https://packagist.org/downloads/",
...@@ -37,10 +39,12 @@ ...@@ -37,10 +39,12 @@
], ],
"authors": [ "authors": [
{ {
"name": "yunwuxin", "name": "cocolait",
"email": "448901948@qq.com" "email": "enkipen@qq.com"
} }
] ],
"description": "PHP excel表格处理",
"homepage": "http://www.mgchen.com/"
}, },
{ {
"name": "jiguang/jmessage", "name": "jiguang/jmessage",
...@@ -55,7 +59,13 @@ ...@@ -55,7 +59,13 @@
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/jpush/jmessage-api-php-client/zipball/690bec9b0783bed479b17ea7b8cd75e861e13164", "url": "https://api.github.com/repos/jpush/jmessage-api-php-client/zipball/690bec9b0783bed479b17ea7b8cd75e861e13164",
"reference": "690bec9b0783bed479b17ea7b8cd75e861e13164", "reference": "690bec9b0783bed479b17ea7b8cd75e861e13164",
"shasum": "" "shasum": "",
"mirrors": [
{
"url": "https://dl.laravel-china.org/%package%/%reference%.%type%",
"preferred": true
}
]
}, },
"require": { "require": {
"ext-curl": "*", "ext-curl": "*",
...@@ -101,7 +111,13 @@ ...@@ -101,7 +111,13 @@
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/PHPOffice/PHPExcel/zipball/372c7cbb695a6f6f1e62649381aeaa37e7e70b32", "url": "https://api.github.com/repos/PHPOffice/PHPExcel/zipball/372c7cbb695a6f6f1e62649381aeaa37e7e70b32",
"reference": "372c7cbb695a6f6f1e62649381aeaa37e7e70b32", "reference": "372c7cbb695a6f6f1e62649381aeaa37e7e70b32",
"shasum": "" "shasum": "",
"mirrors": [
{
"url": "https://dl.laravel-china.org/%package%/%reference%.%type%",
"preferred": true
}
]
}, },
"require": { "require": {
"ext-xml": "*", "ext-xml": "*",
...@@ -149,6 +165,177 @@ ...@@ -149,6 +165,177 @@
"abandoned": "phpoffice/phpspreadsheet" "abandoned": "phpoffice/phpspreadsheet"
}, },
{ {
"name": "qiniu/php-sdk",
"version": "v7.2.3",
"version_normalized": "7.2.3.0",
"source": {
"type": "git",
"url": "https://github.com/qiniu/php-sdk.git",
"reference": "67852ba9cdd7f48e0e080961abebafee134fb329"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/qiniu/php-sdk/zipball/67852ba9cdd7f48e0e080961abebafee134fb329",
"reference": "67852ba9cdd7f48e0e080961abebafee134fb329",
"shasum": "",
"mirrors": [
{
"url": "https://dl.laravel-china.org/%package%/%reference%.%type%",
"preferred": true
}
]
},
"require": {
"php": ">=5.3.3"
},
"require-dev": {
"phpunit/phpunit": "~4.0",
"squizlabs/php_codesniffer": "~2.3"
},
"time": "2018-02-20T13:59:54+00:00",
"type": "library",
"installation-source": "dist",
"autoload": {
"psr-4": {
"Qiniu\\": "src/Qiniu"
},
"files": [
"src/Qiniu/functions.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Qiniu",
"email": "sdk@qiniu.com",
"homepage": "http://www.qiniu.com"
}
],
"description": "Qiniu Resource (Cloud) Storage SDK for PHP",
"homepage": "http://developer.qiniu.com/",
"keywords": [
"cloud",
"qiniu",
"sdk",
"storage"
]
},
{
"name": "siriusphp/upload",
"version": "2.1.1",
"version_normalized": "2.1.1.0",
"source": {
"type": "git",
"url": "https://github.com/siriusphp/upload.git",
"reference": "1bfd8b1f228ec419424c8acd1ccd86d53541ad94"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/siriusphp/upload/zipball/1bfd8b1f228ec419424c8acd1ccd86d53541ad94",
"reference": "1bfd8b1f228ec419424c8acd1ccd86d53541ad94",
"shasum": "",
"mirrors": [
{
"url": "https://dl.laravel-china.org/%package%/%reference%.%type%",
"preferred": true
}
]
},
"require": {
"php": ">=5.3",
"siriusphp/validation": "~2.1"
},
"require-dev": {
"phpunit/phpunit": "~4.8"
},
"suggest": {
"knplabs/gaufrette": "Alternative filesystem abstraction library for upload destinations",
"league/flysystem": "To upload to different destinations, not just to the local file system"
},
"time": "2017-07-31T08:18:59+00:00",
"type": "library",
"installation-source": "dist",
"autoload": {
"psr-4": {
"Sirius\\Upload\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Adrian Miu",
"email": "adrian@adrianmiu.ro"
}
],
"description": "Framework agnostic upload library",
"keywords": [
"file",
"form",
"upload",
"validation"
]
},
{
"name": "siriusphp/validation",
"version": "2.2.2",
"version_normalized": "2.2.2.0",
"source": {
"type": "git",
"url": "https://github.com/siriusphp/validation.git",
"reference": "f8d5fd657dfd5f9e33bfafab2439ea6e19f3240c"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/siriusphp/validation/zipball/f8d5fd657dfd5f9e33bfafab2439ea6e19f3240c",
"reference": "f8d5fd657dfd5f9e33bfafab2439ea6e19f3240c",
"shasum": "",
"mirrors": [
{
"url": "https://dl.laravel-china.org/%package%/%reference%.%type%",
"preferred": true
}
]
},
"require": {
"php": ">=5.3"
},
"require-dev": {
"phpunit/phpunit": "^3.7"
},
"time": "2018-06-01T11:55:44+00:00",
"type": "library",
"installation-source": "dist",
"autoload": {
"psr-4": {
"Sirius\\Validation\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Adrian Miu",
"email": "adrian@adrianmiu.ro"
}
],
"description": "Data validation library. Validate arrays, array objects, domain models etc using a simple API. Easily add your own validators on top of the already dozens built-in validation rules",
"keywords": [
"form",
"modeling",
"sanitization",
"security",
"validation"
]
},
{
"name": "topthink/framework", "name": "topthink/framework",
"version": "v5.0.15", "version": "v5.0.15",
"version_normalized": "5.0.15.0", "version_normalized": "5.0.15.0",
...@@ -159,9 +346,15 @@ ...@@ -159,9 +346,15 @@
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://files.phpcomposer.com/files/top-think/framework/7c1375791fe8772e33282ee8611ea465dc215fca.zip", "url": "https://api.github.com/repos/top-think/framework/zipball/7c1375791fe8772e33282ee8611ea465dc215fca",
"reference": "7c1375791fe8772e33282ee8611ea465dc215fca", "reference": "7c1375791fe8772e33282ee8611ea465dc215fca",
"shasum": "" "shasum": "",
"mirrors": [
{
"url": "https://dl.laravel-china.org/%package%/%reference%.%type%",
"preferred": true
}
]
}, },
"require": { "require": {
"php": ">=5.4.0", "php": ">=5.4.0",
...@@ -202,83 +395,86 @@ ...@@ -202,83 +395,86 @@
] ]
}, },
{ {
"name": "qiniu/php-sdk", "name": "topthink/think-captcha",
"version": "v7.2.3", "version": "v1.0.7",
"version_normalized": "7.2.3.0", "version_normalized": "1.0.7.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/qiniu/php-sdk.git", "url": "https://github.com/top-think/think-captcha.git",
"reference": "67852ba9cdd7f48e0e080961abebafee134fb329" "reference": "0c55455df26a1626a60d0dc35d2d89002b741d44"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://files.phpcomposer.com/files/qiniu/php-sdk/67852ba9cdd7f48e0e080961abebafee134fb329.zip", "url": "https://api.github.com/repos/top-think/think-captcha/zipball/0c55455df26a1626a60d0dc35d2d89002b741d44",
"reference": "67852ba9cdd7f48e0e080961abebafee134fb329", "reference": "0c55455df26a1626a60d0dc35d2d89002b741d44",
"shasum": "" "shasum": "",
}, "mirrors": [
"require": { {
"php": ">=5.3.3" "url": "https://dl.laravel-china.org/%package%/%reference%.%type%",
}, "preferred": true
"require-dev": { }
"phpunit/phpunit": "~4.0", ]
"squizlabs/php_codesniffer": "~2.3"
}, },
"time": "2018-02-20T13:59:54+00:00", "time": "2016-07-06T01:47:11+00:00",
"type": "library", "type": "library",
"installation-source": "dist", "installation-source": "dist",
"autoload": { "autoload": {
"psr-4": { "psr-4": {
"Qiniu\\": "src/Qiniu" "think\\captcha\\": "src/"
}, },
"files": [ "files": [
"src/Qiniu/functions.php" "src/helper.php"
] ]
}, },
"notification-url": "https://packagist.org/downloads/", "notification-url": "https://packagist.org/downloads/",
"license": [ "license": [
"MIT" "Apache-2.0"
], ],
"authors": [ "authors": [
{ {
"name": "Qiniu", "name": "yunwuxin",
"email": "sdk@qiniu.com", "email": "448901948@qq.com"
"homepage": "http://www.qiniu.com"
} }
], ],
"description": "Qiniu Resource (Cloud) Storage SDK for PHP", "description": "captcha package for thinkphp5"
"homepage": "http://developer.qiniu.com/",
"keywords": [
"cloud",
"qiniu",
"sdk",
"storage"
]
}, },
{ {
"name": "topthink/think-captcha", "name": "topthink/think-installer",
"version": "v1.0.7", "version": "v1.0.12",
"version_normalized": "1.0.7.0", "version_normalized": "1.0.12.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/top-think/think-captcha.git", "url": "https://github.com/top-think/think-installer.git",
"reference": "0c55455df26a1626a60d0dc35d2d89002b741d44" "reference": "1be326e68f63de4e95977ed50f46ae75f017556d"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://files.phpcomposer.com/files/top-think/think-captcha/0c55455df26a1626a60d0dc35d2d89002b741d44.zip", "url": "https://api.github.com/repos/top-think/think-installer/zipball/1be326e68f63de4e95977ed50f46ae75f017556d",
"reference": "0c55455df26a1626a60d0dc35d2d89002b741d44", "reference": "1be326e68f63de4e95977ed50f46ae75f017556d",
"shasum": "" "shasum": "",
"mirrors": [
{
"url": "https://dl.laravel-china.org/%package%/%reference%.%type%",
"preferred": true
}
]
},
"require": {
"composer-plugin-api": "^1.0"
},
"require-dev": {
"composer/composer": "1.0.*@dev"
},
"time": "2017-05-27T06:58:09+00:00",
"type": "composer-plugin",
"extra": {
"class": "think\\composer\\Plugin"
}, },
"time": "2016-07-06T01:47:11+00:00",
"type": "library",
"installation-source": "dist", "installation-source": "dist",
"autoload": { "autoload": {
"psr-4": { "psr-4": {
"think\\captcha\\": "src/" "think\\composer\\": "src"
}, }
"files": [
"src/helper.php"
]
}, },
"notification-url": "https://packagist.org/downloads/", "notification-url": "https://packagist.org/downloads/",
"license": [ "license": [
...@@ -289,7 +485,6 @@ ...@@ -289,7 +485,6 @@
"name": "yunwuxin", "name": "yunwuxin",
"email": "448901948@qq.com" "email": "448901948@qq.com"
} }
], ]
"description": "captcha package for thinkphp5"
} }
] ]
/vendor/
composer.phar
composer.lock
examples/config.php
The MIT License (MIT)
Copyright (c) 2015 极光推送/IM JPush/JMesage
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
# JMessage API PHP Client
这是 JMessage REST API 的 PHP 版本封装开发包,是由极光推送官方提供的,一般支持最新的 API 功能。
对应的 REST API 文档: https://docs.jiguang.cn/jmessage/server/rest_api_im/
> 支持的 PHP 版本: 5.4 ~ 5.6.x, 7
## Installation
#### 使用 Composer 安装
- 在项目中的 `composer.json` 文件中添加 jmessage 依赖:
```json
"require": {
"jiguang/jmessage": "1.0.*"
}
```
- 执行 `$ php composer.phar install``$ composer install` 进行安装。
#### 直接下载源码安装
> 直接下载源代码也是一种安装 SDK 的方法,不过因为有版本更新的维护问题,所以这种安装方式**十分不推荐**,但由于种种原因导致无法使用 Composer,所以我们也提供了这种情况下的备选方案。
- 下载源代码包,解压到项目中
- 在项目中引入 autoload(在源码根目录下):
```php
require 'path_to_sdk/autoload.php';
```
## Usage
* [JMessage Client](https://github.com/jpush/jmessage-api-php-client/blob/master/docs/GUIDE.md#jmessage-client)
* [User 用户](https://github.com/jpush/jmessage-api-php-client/blob/master/docs/GUIDE.md#user-用户)
* [Admin 管理员](https://github.com/jpush/jmessage-api-php-client/blob/master/docs/GUIDE.md#admin-管理员)
* [Blacklist 黑名单](https://github.com/jpush/jmessage-api-php-client/blob/master/docs/GUIDE.md#blacklist-黑名单)
* [Group 群组](https://github.com/jpush/jmessage-api-php-client/blob/master/docs/GUIDE.md#group-群组)
* [Friend 好友](https://github.com/jpush/jmessage-api-php-client/blob/master/docs/GUIDE.md#friend-好友)
* [Resource 媒体资源](https://github.com/jpush/jmessage-api-php-client/blob/master/docs/GUIDE.md#resource-媒体资源)
* [发送消息](https://github.com/jpush/jmessage-api-php-client/blob/master/docs/GUIDE.md#发送消息)
* [跨应用](https://github.com/jpush/jmessage-api-php-client/blob/master/docs/CROSS.md#cross-跨应用)
## Examples
**注意: 这只是使用样例, 不应该直接用于实际环境中!!**
在项目的 [examples](https://github.com/jpush/jmessage-api-php-client/tree/master/examples) 文件夹中有简单的使用示例代码, 开发者可以参考其中的样例快速了解该库的使用方法。
**注:所下载的样例代码不可马上使用,需要在 `examples/config.php` 文件中填入相关的必要参数,或者设置相关环境变量,不进行这个操作则示例运行会失败。**另外为保护开发者隐私 `examples/config.php` 文件不在版本控制中,需要使用如下命令手动复制:
```php
$ cp examples/config.php.example examples/config.php
```
**示例简单使用方法**
若要运行 friend_examples.php 中的示例代码:
```bash
# 假定当前目录为 JMessage 源码所在的根目录
$ php examples/friend_examples.php
```
> 当然也可编辑相关的示例文件,更改参数查看执行效果
## ErrorCode
JMessage 服务器端报的错误码。有可能出现在返回值中,可在这里查询含义: https://docs.jiguang.cn/jmessage/client/im_errorcode_server/
## Contributing
Bug reports and pull requests are welcome on GitHub at https://github.com/jpush/jmessage-api-php-client.
## License
The library is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
<?php
function classLoader($class)
{
$path = str_replace('\\', DIRECTORY_SEPARATOR, $class);
$file = __DIR__ . '/src/' . $path . '.php';
if (file_exists($file)) {
require_once $file;
}
}
spl_autoload_register('classLoader');
{
"name": "jiguang/jmessage",
"type": "library",
"version": "1.0.4",
"description": "JMessage's officially supported PHP client library for accessing JMessage APIs.",
"keywords": ["jiguang", "jmessage", "API Client"],
"homepage": "https://github.com/jpush/jmessage-api-php-client",
"license": "MIT",
"authors": [
{
"name": "JiGuang",
"email": "support@jpush.cn",
"homepage": "https://www.jiguang.cn"
}
],
"require": {
"php": ">=5.4",
"ext-curl": "*"
},
"autoload" : {
"psr-4": {"JMessage\\": "src/JMessage/"}
}
}
# Cross 跨应用
* [JMessage Client](#jmessage-client)
* [跨应用管理群组成员](#跨应用管理群组成员)
* [注册用户](#注册用户)
* [跨应用添加成员](#跨应用添加成员)
* [跨应用移除成员](#跨应用移除成员)
* [跨应用更新群组成员](#跨应用更新群组成员)
* [跨应用获取群组成员列表](#跨应用获取群组成员列表)
* [跨应用管理黑名单](#跨应用管理黑名单)
* [跨应用获取黑名单列表](#跨应用获取黑名单列表)
* [跨应用添加黑名单](#跨应用添加黑名单)
* [跨应用移除黑名单](#跨应用移除黑名单)
* [跨应用批量添加黑名单](#跨应用批量添加黑名单)
* [跨应用批量移除黑名单](#跨应用批量移除黑名单)
* [跨应用免打扰设置](#跨应用免打扰设置)
* [跨应用单聊免打扰设置](#跨应用单聊免打扰设置)
* [跨应用群聊免打扰设置](#跨应用群聊免打扰设置)
* [跨应用好友管理](#跨应用好友管理)
* [跨应用添加好友](#跨应用添加好友)
* [跨应用移除好友](#跨应用移除好友)
* [跨应用更新好友备注](#跨应用更新好友备注)
* [跨应用批量更新好友备注](#跨应用批量更新好友备注)
## JMessage Client
```php
use JMessage\JMessage;
$appKey = 'xxxx';
$masterSecret = 'xxxx';
$client = new JMessage($appKey, $masterSecret);
```
## 跨应用管理群组成员
```php
use JMessage\Cross\Member;
$member = new Member($client);
```
### 跨应用添加成员
```php
$member->add($gid, $appKey, array $usernames)
```
**参数:**
> $gid:表示要添加成员的群组 gid
> $appKey:表示用户所属的 appKey
> $usernames:表示要添加到群组的用户数组
**示例:**
```php
# 跨应用把 appKey 为 'xxxxxx' 的应用下的用户 'username0' 和 'username1' 添加到群组 gid 为 'xxxx' 的群组中
$gid = 'xxxx';
$appKey = 'xxxxxx';
$usernames = ['username0', 'username1'];
$response = $member->add($gid, $appKey, $usernames);
```
### 跨应用移除成员
```php
$member->remove($gid, $appKey, array $usernames);
```
**参数:**
> $gid:表示要移除成员的群组 gid
> $appKey:表示用户所属的 appKey
> $usernames:表示要从群组移除的用户数组
**示例:**
```php
# 跨应用从群组 gid 为 'xxxx' 的群组中把 appKey 为 'xxxxxx' 的应用下的用户 'username0' 和 'username1' 移除
$gid = 'xxxx';
$appKey = 'xxxxxx';
$usernames = ['username0', 'username1'];
$response = $member->remove($gid, $appKey, $usernames);
```
### 跨应用更新群组成员
> 跨应用管理成员的设置参数比较复杂,建议使用上面所述的 2 个方法
```php
$member->update($gid, array $options);
```
**参数:**
> $gid:表示要添加成员的群组 gid
> $options:表示批量添加成员的选项数组
**示例:**
```php
# 跨应用管理群组 'xxxx' 中的成员
$gid = 'xxxx';
$appKey0 => 'appkey_0';
$add0 = ['username0', 'username1'];
$remove0 = ['username2', 'username3'];
$appKey1 = 'appkey_1';
$add1 = ['username4', 'username5'];
$remove1 = ['username6', 'username7'];
$options0 = [
[
'appKey' => $appKey0,
'add' => $add0,
'remove' => $remove0
],[
'appKey' => $appKey1,
'add' => $add1,
'remove' => $remove1]
];
# or
$options1 = [
[
'appKey' => 'appkey_0',
'add' => ['username0', 'username1'],
'remove' => ['username2', 'username3']
], [
'appKey' => 'appkey_1',
'add' => ['username4', 'username5'],
'remove' => ['username6', 'username7']
]
];
$response = $member->update($gid, $options1);
```
### 跨应用获取群组成员列表
```php
$member->listAll($gid);
```
**参数:**
> $gid:表示群组 gid
**示例:**
```php
# 跨应用获取群组 gid 为 'xxxx' 的群组的成员列表
$gid = 'xxxx';
$response = $member->listAll($gid);
```
## 跨应用管理黑名单
```php
use JMessage\Cross\Blacklist;
$blacklist = new Blacklist($client);
```
### 跨应用获取黑名单列表
```php
$blacklist->listAll($user);
```
**参数:**
> $user:表示要跨应用获取其黑名单列表的用户
**示例:**
```php
# 跨应用获取用户 'jiguang' 的黑名单列表
$user = 'jiguang';
$response = $blacklist->listAll($user);
```
### 跨应用添加黑名单
```php
$blacklist->add($user, $appKey, array $usernames);
```
**参数:**
> $user:表示要跨应用管理其黑名单的用户
> $appKey:表示用户所属的 appKey
> $usernames:表示要添加进黑名单的用户的数组
**示例:**
```php
# 跨应用把用户 'username0' 和 'username1' 添加到用户 'jiguang' 的黑名单列表中
$user = 'jiguang';
$appKey = 'xxxxxx';
$username = ['username0', 'username1'];
$response = $blacklist->add($user, $appKey, $usernames);
```
### 跨应用移除黑名单
```php
$blacklist->remove($user, $appKey, array $usernames);
```
**参数:**
> $user:表示要跨应用管理其黑名单的用户
> $appKey:表示用户所属的 appKey
> $usernames:表示要从黑名单移除的用户的数组
**示例:**
```php
# 跨应用把用户 'username0' 和 'username1' 从用户 'jiguang' 的黑名单列表中移除
$user = 'jiguang';
$appKey = 'xxxxxx';
$username = ['username0', 'username1'];
$response = $blacklist->remove($user, $appKey, $usernames);
```
### 跨应用批量添加黑名单
```php
$blacklist->batchAdd($user, array $options);
```
**参数:**
> $user:表示要跨应用批量管理其黑名单的用户
> $options:表示跨应用批量添加黑名单的选项数组
**示例:**
```php
# 跨应用把应用 ‘appKey0’ 中的用户 'username0' 和 'username1' 以及应用 ‘appKey1’ 中的用户 'username2' 和 'username3' 添加到用户 'jiguang' 的黑名单列表中
$user = 'jiguang';
$options = [
'appKey' => 'appKey0',
'usernames' => ['username0', 'username1']
],[
'appKey' => 'appKey1',
'usernames' => ['username2', 'username3']
];
$response = $blacklist->add($user, $options);
```
### 跨应用批量移除黑名单
```php
$blacklist->batchRemove($user, array $options);
```
**参数:**
> $user:表示要跨应用批量管理其黑名单的用户
> $options:表示跨应用批量移除黑名单的选项数组
**示例:**
```php
# 跨应用把应用 ‘appKey0’ 中的用户 'username0' 和 'username1' 以及应用 ‘appKey1’ 中的用户 'username2' 和 'username3' 从用户 'jiguang' 的黑名单列表中移除
$user = 'jiguang';
$options = [
'appKey' => 'appKey0',
'usernames' => ['username0', 'username1']
],[
'appKey' => 'appKey1',
'usernames' => ['username2', 'username3']
];
$response = $blacklist->batchRemove($user, $options);
```
## 跨应用免打扰设置
```php
use JMessage\Cross\Nodisturb;
$nodisturb = new Nodisturb($client);
```
### 跨应用单聊免打扰设置
```php
$nodisturb->single($user, $appKey, array $options);
```
**参数:**
> $user:表示要设置跨应用单聊免打扰的用户
> $appKey:表示用户所属的 appKey
> $options:表示设置跨应用单聊免打扰的选项数组,支持键名 'add' 或 'remove' 表示添加或移除
**示例:**
```php
$user = 'jiguang';
$appKey = 'xxxxxx';
$add = ['username0', 'username1'];
$remove = ['username2', 'username3'];
$options = ['add' => $add, 'remove' => $remove ];
# 用户 'jiguang' 跨应用对 'xxxxxx' 应用下的用户 'username0', 'username1' 添加单聊免打扰,且同时对 'username2', 'username3' 移除单聊免打扰
$response = $nodisturb->single($user, $appKey, ['add' => $add, 'remove' => $remove ]);
# 用户 'jiguang' 跨应用仅对 'xxxxxx' 应用下的用户 'username0', 'username1' 添加单聊免打扰
$response = $nodisturb->single($user, $appKey, ['add' => $add]);
# 用户 'jiguang' 跨应用仅对 'xxxxxx' 应用下的用户 'username2', 'username3' 移除单聊免打扰
$response = $nodisturb->single($user, $appKey, ['remove' => $remove ]);
```
### 跨应用群聊免打扰设置
```php
$nodisturb->group($user, $appKey, array $options);
```
**参数:**
> $user:表示要设置跨应用群聊免打扰的用户
> $appKey:表示群组所属的 appKey
> $options:表示设置跨应用群聊免打扰的选项数组,支持键名 'add' 或 'remove' 表示添加或移除
**示例:**
```php
# 用户 'jiguang' 跨应用对 'xxxxxx' 应用下的群组 'gid0', 'gid1' 添加群聊免打扰,且同时对 'gid2', 'gid3' 移除群聊免打扰
$user = 'jiguang';
$appKey = 'xxxxxx';
$options = [
'add' => ['gid0', 'gid1'],
'remove' =>['gid2', 'gid3']
]
$response = $nodisturb->group($user, $appKey, $options);
```
## 跨应用好友管理
```php
use JMessage\Cross\Friend;
$friend = new Friend($client);
```
### 跨应用添加好友
```php
$friend->add($user, $appKey, array $friendnames);
```
**参数:**
> $user:表示要跨应用管理好友的用户
> $appKey:表示好友所属的 appKey
> $friendnames:表示要添加的好友数组
**示例:**
```php
# 用户 'jiguang' 跨应用把应用 'xxxxxx' 下的用户 'username0', 'username1' 添加为好友
$user = 'jiguang';
$appKey = 'xxxxxx';
$friendnames = ['username0', 'username1'];
$response = $friend->add($user, $appKey, $friendnames);
```
### 跨应用移除好友
```php
$friend->remove($user, $appKey, array $friendnames);
```
**参数:**
> $user:表示要跨应用管理好友的用户
> $appKey:表示好友所属的 appKey
> $friendnames:表示要移除的好友数组
**示例:**
```php
# 用户 'jiguang' 跨应用把应用 'xxxxxx' 下的用户 'username0', 'username1' 从好友列表移除
$user = 'jiguang';
$appKey = 'xxxxxx';
$friendnames = ['username0', 'username1'];
$response = $friend->remove($user, $appKey, $friendnames);
```
### 跨应用更新好友备注
```php
$friend->updateNotename($user, $appKey, $friendname, array $options);
```
**参数:**
> $user:表示要跨应用管理好友的用户
> $appKey:表示好友所属的 appKey
> $friendname:表示要更新备注的好友
> $options:表示跨应用更新好友备注的选项数组,支持键名 'note_name' 或 'others' 表示备注或其他备注信息
**示例:**
```php
# 用户 'jiguang' 跨应用更新应用 'xxxxxx' 下的用户 'username0' 的备注为 'u00'
$user = 'jiguang';
$appKey = 'xxxxxx';
$friendname = 'username0';
$options = ['note_name' => 'u00'];
$response = $friend->updateNotename($user, $appKey, $usernames, $options);
```
### 跨应用批量更新好友备注
```php
$friend->batchUpdateNotename($user, array $options);
```
**参数:**
> $user:表示要跨应用管理好友的用户
> $options:表示跨应用批量更新好友备注的选项数组
**示例:**
```php
# 用户 'jiguang' 跨应用更新应用 'appKey0' 下的好友 'username0' 的备注为 'uu00',
# 同时更新应用 'appKey1' 下的好友 'username1' 的其他备注信息为 'nothing to go'
$user = 'jiguang';
$options = [
[
'appKey' => 'appKey0',
'username' => 'username0',
'note_name' => 'uu00'
],[
'appKey' => 'appKey1',
'username' => 'username1',
'others' => 'nothing to go'
]
];
$response = $friend->batchUpdateNotename($user, $options);
```
# 目录
* [JMessage Client](#jmessage-client)
* [User 用户](#user-用户)
* [注册用户](#注册用户)
* [批量注册用户](#批量注册用户)
* [获取用户列表](#获取用户列表)
* [获取用户信息](#获取用户信息)
* [更新用户信息](#更新用户信息)
* [查询用户在线状态](#查询用户在线状态)
* [修改密码](#修改密码)
* [删除用户](#删除用户)
* [获取用户的群组列表](#获取用户的群组列表)
* [添加单聊免打扰](#添加单聊免打扰)
* [移除单聊免打扰](#移除单聊免打扰)
* [添加群聊免打扰](#添加群聊免打扰)
* [移除群聊免打扰](#移除群聊免打扰)
* [开启全局免打扰](#开启全局免打扰)
* [关闭全局免打扰](#关闭全局免打扰)
* [Admin 管理员](#admin-管理员)
* [管理员注册](#管理员注册)
* [获取应用管理员列表](#获取应用管理员列表)
* [Blacklist 黑名单](#blacklist-黑名单)
* [黑名单列表](#黑名单列表)
* [添加黑名单](#添加黑名单)
* [移除黑名单](#移除黑名单)
* [Group 群组](#group-群组)
* [创建群组](#创建群组)
* [获取群组详情](#获取群组详情)
* [更新群组信息(群名 or 群描述)](#更新群组信息群名-or-群描述)
* [删除群组](#删除群组)
* [更新群组成员](#更新群组成员)
* [添加群组成员](#添加群组成员)
* [移除群组成员](#移除群组成员)
* [获取群组成员列表](#获取群组成员列表)
* [Friend 好友](#friend-好友)
* [获取好友列表](#获取好友列表)
* [添加好友](#添加好友)
* [删除好友](#删除好友)
* [更新好友备注](#更新好友备注)
* [Resource 媒体资源](#resource-媒体资源)
* [资源上传](#资源上传)
* [资源下载](#资源下载)
* [发送消息](#发送消息)
* [发送文本消息](#发送文本消息)
* [发送图片消息](#发送图片消息)
* [发送自定义消息](#发送自定义消息)
## JMessage Client
```php
use JMessage\JMessage;
$appKey = 'xxxx';
$masterSecret = 'xxxx';
$client = new JMessage($appKey, $masterSecret);
```
## User 用户
```php
use JMessage\IM\User;
$user = new User($client);
```
### 注册单个用户
```php
$user->register($username, $password);
```
**参数:**
> $username: 表示用户名
> $password: 表示密码
**示例:**
```php
$username = 'jiguang';
$password = 'password';
$response = $user->register($username, $password);
```
### 批量注册用户
批量注册用户到极光 IM 服务器,一次批量注册最多支持 500 个用户。
```php
$user->batchRegister(array $users);
```
**参数:**
> $users: 表示将要注册的用户的信息的数组
**示例:**
```php
# 批量注册三个用户
$users = [
['username' => 'username0', 'password' => 'password0'],
['username' => 'username1', 'password' => 'password1'],
['username' => 'jiguang', 'password' => 'password']
];
$response = $user->batchRegister($users);
```
### 获取用户列表
```php
$user->listAll($start, $count);
```
**参数:**
> $start: 开始的记录数
> $count: 要获取的记录个数
**示例:**
```php
# 获取从编号 2 开始的 100 个记录的用户列表
$response = $user->listAll(2, 100);
```
### 获取用户信息
```php
$user->show($username);
```
**参数:**
> $username: 表示想要获取用户信息的用户名。
**示例:**
```php
$username = 'jiguang';
$response = $user->show($username);
```
### 更新用户信息
```php
$user->update($username, array $options);
```
**参数:**
> $username: 表示想要更新其信息的用户的用户名
> $options: 更新选项数组,表示需要更新的用户信息和值。支持 **nickname**、**avatar**、**birthday**、**signature**、**gender**、**region**、**address** 中的一个或多个
参数 | 意义 | 说明
--- | --- | ---
nickname | (选填)用户昵称 | 不支持的字符:英文字符: \n \r\n
avatar | (选填)头像 | 需要填上从文件上传接口获得的 media_id
birthday | (选填)生日 | example: 1990-01-24 yyyy-MM-dd
signature |(选填)签名 | 支持的字符:全部,包括 Emoji
gender | (选填) 性别 | 0 - 未知, 1 - 男 ,2 - 女
region | (选填)地区 | 支持的字符:全部,包括 Emoji
address | (选填)地址 | 支持的字符:全部,包括 Emoji
**示例:**
```php
# 更新用户名为 'jiguang' 的用户的 niackname 和 gender
$username = 'jiguang';
$nickname = 'jpush';
$response = $user->update($username, ['nickname' => $nickname 'gender' => 2]);
```
### 查询用户在线状态
```php
$user->stat($username)
```
**参数:**
> $username: 表示想要查询在线状态的用户的用户名
**示例:**
```php
$username = 'jiguang';
$response = $user->stat($username);
```
### 修改密码
```php
$user->updatePassword($username, $password);
```
**参数:**
> $username: 表示想要修改密码的用户的用户名
> $password: 新密码
**示例:**
```php
$username = 'jiguang';
$new_password = 'newpassword';
$response = $user->updatePassword($username, $new_password);
```
### 删除用户
```php
$user->delete($username);
```
**参数:**
> $username: 表示想要删除的用户的用户名
**示例:**
```php
# 删除用户名为 'jiguang' 的用户
$username = 'jiguang';
$response = $user->delete($username);
```
### 获取用户的群组列表
```php
$user->groups($username);
```
**参数:**
> $username: 表示想要获取其群组列表的用户
**示例:**
```php
# 获取用户 'jiguang' 的群组列表
$username = 'jiguang';
$response = $user->groups($username);
```
### 添加单聊免打扰
```php
$user->addSingleNodisturb($touser, array $usernames);
```
**参数:**
> $touser: 表示要设置免打扰的当前用户
> $usernames: 表示要被添加单聊免打扰的用户名数组
**示例:**
```php
# 用户 'jiguang' 添加对用户 'username0' 和 'username1' 的单聊免打扰
$touser = 'jiguang';
$usernames = ['username0', 'username1'];
$response = $user->addSingleNodisturb($touser, $usernames);
```
### 移除单聊免打扰
```php
$user->removeSingleNodisturb($touser, array $usernames);
```
**参数:**
> $touser: 表示要设置免打扰的当前用户
> $usernames: 表示要被移除单聊免打扰的用户名数组
**示例:**
```php
# 用户 'jiguang' 移除对用户 'username0' 和 'username1' 的单聊免打扰
$touser = 'jiguang';
$usernames = ['username0', 'username1'];
$response = $user->removeSingleNodisturb($touser, $usernames);
```
### 添加群聊免打扰
```php
$user->addGroupNodisturb($touser, array $gids);
```
**参数:**
> $touser: 表示要被设置免打扰的当前用户
> $gids: 表示要被添加群聊免打扰的群组的 gid 数组
**示例:**
```php
# 用户 'jiguang' 添加对群组 'gid0' 和 'gid1' 的群聊免打扰
$touser = 'jiguang';
$gid = ['gid0', 'gid1'];
$response = $user->addGroupNodisturb($touser, $gids);
```
### 移除群聊免打扰
```php
$user->removeGroupNodisturb($touser, array $gids);
```
**参数:**
> $touser: 表示要设置免打扰的当前用户
> $gids: 表示要被移除群聊免打扰的群组的 gid 数组
**示例:**
```php
# 用户 'jiguang' 移除对群组 'gid0' 和 'gid1' 的群聊免打扰
$touser = 'jiguang';
$gid = ['gid0', 'gid1'];
$response = $user->removeGroupNodisturb($touser, $gids);
```
### 开启全局免打扰
```php
$user->openGlobalNodisturb($touser);
```
**参数:**
> $touser: 表示要开启全局免打扰的用户
**示例:**
```php
# 用户 'jiguang' 开启全局免打扰
$touser = 'jiguang';
$response = $user->openGlobalNodisturb($touser);
```
### 关闭全局免打扰
```php
$user->closeGlobalNodisturb($touser);
```
**参数:**
> $touser: 表示要关闭全局免打扰的用户
**示例:**
```php
# 用户 'jiguang' 关闭全局免打扰
$touser = 'jiguang';
$response = $user->closeGlobalNodisturb($touser);
```
### 自定义免打扰
> 自定义免打扰的设置参数比较复杂,建议使用上面所述的 6 个方法设置免打扰
```php
$user->nodisturb($touser, array $options);
```
**参数:**
> $touser: 表示要设置自定义免打扰的用户
> $options: 自定义免打扰设置项数组
**示例:**
```php
# 自定义用户 'jiguang' 的免打扰设置
# 添加用户 $user0 和 $user1 的单聊免打扰,移除用户 $user2 和 $user3 的单聊免打扰
# 添加群组 $gid0 和 $gid1 的群聊免打扰,移除群组 $gid2 和 $gid3 的群聊免打扰
# 关闭全局免打扰
$username = 'jiguang';
$options = [
"single" => [
"add" => [$user0, $user1],
"remove" => [$user2, $user3]
],
"group" => [
"add" => [$gid0, $gid1],
"remove" => [$gid2, $gid3]
],
"global" => 0
];
$response = $user->nodisturb($touser, $options);
```
## Admin 管理员
```php
use JMessage\IM\Admin;
$admin = new Admin($client);
```
### 管理员注册
```php
$admin->register(array $info);
```
**参数:**
> $info: 表示想要注册的管理员信息
**示例:**
```php
$info = [
'username' => 'admin',
'password' => 'password'
];
$response = $admin->register($info);
```
### 获取应用管理员列表
```php
$admin->listAll($start, $count);
```
**参数:**
> $start: 起始记录位置 从 0 开始
> $count: 查询条数 最多支持 500 条
**示例:**
```php
# 获取从编号 2 开始的 10 个记录的管理员 admin 列表
$response = $admin->listAll(2, 10);
```
## Blacklist 黑名单
```php
use JMessage\IM\Blacklist;
$blacklist = new Blacklist($client);
```
### 黑名单列表
```php
$blacklist->listAll($user);
```
**参数:**
> $user:表示当前用户
**示例:**
```php
# 获取当前用户 'jiguang' 的黑名单列表
$user = 'jiguang';
$response = $blacklist->listAll($user);
```
### 添加黑名单
```php
$blacklist->add($user, array $usernames);
```
**参数:**
> $user:表示当前用户
> $usernames:表示要加入到当前用户黑名单中的用户名数组
**示例:**
```php
# 把用户 'username0' 和 'username1' 添加到 'jiguang' 的黑名单中
$user = 'jiguang';
$username = ['username0', 'username1'];
$response = $blacklist->add($user. $username);
```
### 移除黑名单
```php
$blacklist->remove($user, array $usernames);
```
**参数:**
> $user:表示当前用户
> $usernames:表示要从当前用户的黑名单中移除的用户名数组
**示例:**
```php
# 把用户 'username0' 和 'username1' 从 'jiguang' 的黑名单中移除
$user = 'jiguang';
$username = ['username0', 'username1'];
$response = $blacklist->remove($user $username);
```
## Group 群组
```php
use JMessage\IM\Group;
$group = new Group($client);
```
### 创建群组
```php
$group->create($owner, $name, $desc, array $members = [])
```
**参数:**
> $owner: 表示群主的用名
> $name: 表示群组的名字
> $desc: 表示群组描述
> $members: 表示群组成员的用户名数组
**示例:**
```php
# 创建一个群名为 'jiguang group' 群主为 'jiguang' 的群
$owner = 'jiguang';
$members = ['username0', 'username1'];
$name = 'jiguang';
$desc 'jiguang group for developer';
$response = $group->create($owner, $name, $desc, $members);
```
### 获取群组详情
```php
$group->show($gid);
```
**参数:**
> $gid: 群组 ID, 由创建群组时分配
**示例:**
```php
# 获取群组 ID 为 12345 的群组的详情
$gid = 12345;
$response = $group->show($gid);
```
### 更新群组信息(群名 or 群描述)
```php
$group->update($gid, $name, $desc)
```
**参数:**
> $gid: 群组 ID, 由创建群组时分配
> $name: 新的群名
> $desc: 新的群描述
**示例:**
```php
$gid = 12345;
$name = 'new name';
$desc = 'new desc';
# 只更新群组 ID 为 12345 的群组的群名
$response = $group->update($gid, $name);
# 只更新群组 ID 为 12345 的群组的群描述
$response = $group->update($gid, null, $desc);
# 更新群组 ID 为 12345 的群组的群名和群描述
$response = $group->update($gid, $name, $desc);
```
### 删除群组
```php
$group->delete($gid);
```
**参数:**
> $gid: 群组 ID, 由创建群组时分配
**示例:**
```php
# 删除群组 ID 为 12345 的群组
$gid = 12345;
$response = $group->delete($gid);
```
### 更新群组成员
#### 添加群组成员
```php
$response = $group->addMembers($gid, array $usernames);
```
**参数:**
> $gid: 群组 ID, 由创建群组时分配
> $usernames: 表示要添加到群组的用户数组
**示例:**
```php
# 添加用户 'username0', 'username1' 到群组 ID 为 12345 的群组
$gid = 12345;
$usernames = ['username0', 'username1'];
$response = $group->addMembers($gid, $usernames);
```
#### 移除群组成员
```php
$group->removeMembers($gid, array $usernames);
```
**参数:**
> $gid: 群组 ID, 由创建群组时分配
> $usernames: 表示要从群组中移除的用户数组
**示例:**
```php
# 把用户 'username0', 'username1' 从群组 ID 为 12345 的群组中移除
$gid = 12345;
$usernames = ['username0', 'username1'];
$response = $group->removeMembers($gid, $usernames);
```
#### 更新群组成员
> 建议使用上面所述的 2 个方法分别添加和移除群组成员。
```php
$group->updateMembers($gid, array $options)
```
**参数:**
> $gid: 群组 ID, 由创建群组时分配
> $options: 表示更新群组选项
**示例:**
```php
# 添加用户 'username0', 'username1' 到群组 ID 为 12345 的群组, 同时把用户 'username2', 'username3' 从群组 ID 为 12345 的群组中移除
$gid = 12345;
$add = ['username0', 'username1'];
$remove = ['username2', 'username3'];
$response = $group->updateMembers($gid, [ 'add' => $add, 'remove' => $remove ]);
```
### 获取群组成员列表
```php
$group->members($gid);
```
**参数:**
> $gid: 群组 ID, 由创建群组时分配
**示例:**
```php
# 获取群组 ID 为 12345 的群组的成员列表
$gid = 12345;
$response = $group->members($gid);
```
## Friend 好友
```php
use JMessage\IM\Friend;
$friend = new Friend($client);
```
### 获取好友列表
```php
$friend->listAll($user);
```
**参数:**
> $user: 表示要获取其好友列表的用户
**示例:**
```php
# 获取用户 'jiguang' 的好友列表
$user = 'jiguang';
$response = $friend->listAll($user);
```
### 添加好友
```php
$friend->add($user, array $friends);
```
**参数:**
> $user: 表示要添加好友的用户
> $friends: 表示要被添加到好友列表的用户数组
**示例:**
```php
# 用户 'jiguang' 把用户 'username0', 'username1' 添加为好友
$user = 'jiguang';
$friends = ['username0', 'username1'];
$response = $friend->add($user, $friends);
```
### 删除好友
```php
$friend->remove($user, array $friends);
```
**参数:**
> $user: 表示要移除好友的用户
> $friends: 表示要被从好友列表移除的用户数组
**示例:**
```php
# 用户 'jiguang' 删除好友 'username0', 'username1'
$user = 'jiguang';
$friends = ['username0', 'username1'];
$response = $friend->remove($user, $friends);
```
### 更新好友备注
```php
$group->updateNotename($user, array $options);
```
**参数:**
> $user: 表示要更新好友备注的用户
> $options: 表示更新好友备注的选项数组
**示例:**
```php
# 用户 'jiguang' 更新好友 'username0', 'username1' 的好友备注
$user = 'jiguang';
$options = [
[
'username' => 'username0',
'note_name' => 'username0_alias',
'others' => 'good friend'
], [
'username' => 'username1',
'note_name' => 'username1_alias',
'others' => 'normal friend'
]
];
$response = $friend->updateNotename($user, $options);
```
## Resource 媒体资源
```php
use JMessage\IM\Resourse;
$resource = new Resource($client);
```
### 资源上传
```php
$resource->upload($type, $path)
```
**参数:**
> $type: 表示要上传的资源类型,仅支持 'image' 和 'file' 两种资源
> $path: 表示要上传的资源的全路径
**示例:**
```php
$path = '/home/user/www/jiguang.png';
# 把图片 'jiguang.png' 作为图片上传
$response = $resource->upload('image', $path);
# 把图片 'jiguang.png' 作为文件上传
$response = $resource->upload('file', $path);
```
### 资源下载
```php
$resource->download($mediaId)
```
**参数:**
> $mediaId: 表示资源的 mediaId,包括用户的 avatar 字段,资源上传之后返回
**示例:**
```php
$mediaId = 'xxxx';
$response = $resource->download($mediaId);
```
## 发送消息
```php
use JMessage\IM\Message;
$message = new Message($client);
```
### 发送文本消息
```php
$message->sendText($version, array $from, array $target, array $msg);
```
**参数:**
> $version: 版本号
> $from: 发送者信息数组
> $target: 接受者信息数组
> $msg: 消息体数组
**发送者信息数组 $from 说明:**
键 | 是否必须 | 含义
--- | --- | ---
type | 是 | 发送消息者身份 当前只限 admin 用户,必须先注册 admin 用户
id | 是 | 发送者的用户名
name | 否 | 发送者展示名
**接受者信息数组 $target 说明:**
键 | 是否必须 | 含义
--- | --- | ---
type | 是 | 发送目标类型, 'single' - 个人,'group' - 群组
id | 是 | 目标 id, 'single' 填 username 'group' 填 Group Id
name | 否 | 接受者展示名
**消息体数组 $msg 说明:**
键 | 是否必须 | 含义
--- | --- | ---
text | 是 | 消息内容
extras | 否 | 接受一个自定义键值对数组
### 发送图片消息
```php
$message->sendImage($version, array $from, array $target, array $msg);
```
**参数:**
> $version: 版本号,目前是1
> $from: 发送者信息数组(说明同上)
> $target: 接受者信息数组(说明同上)
> $msg: 消息体数组
**消息体数组 $msg 说明:**
键 | 是否必须 | 含义
--- | --- | ---
mediaId | 是 | 文件上传之后服务器端所返回的 key,用于之后生成下载的 url
mediaCrc32 | 是 | 文件的 crc32 校验码,用于下载大图的校验
width | 是 | 图片原始宽度
height | 是 | 图片原始高度
format | 是 | 图片格式
fsize | 是 | 文件大小(字节数)
extras | 否 | 接受一个自定义键值对数组
### 发送自定义消息
```php
$message->sendCustom($version, array $from, array $target, array $msg);
```
**参数:**
> $version: 版本号
> $from: 发送者信息数组(说明同上)
> $target: 接受者信息数组(说明同上)
> $msg: 消息体数组,接受一个自定义键值对数组
<?php
require __DIR__ . '/../config.php';
use JMessage\IM\Admin;
$admin = new Admin($jm);
$info = [
'username' => 'admin',
'password' => 'password'
];
$response = $admin->register($info);
print_r($response);
<?php
require __DIR__ . '/../config.php';
use JMessage\IM\Admin;
$admin = new Admin($jm);
$response = $admin->listAll();
print_r($response);
<?php
require __DIR__ . '/../vendor/autoload.php';
use JMessage\JMessage;
$appKey = 'xxxx';
$masterSecret = 'xxxx';
$jm = new JMessage($appKey, $masterSecret);
<?php
require __DIR__ . '/config.php';
use JMessage\IM\Friend;
$friend = new Friend($jm);
$user = 'user_0';
$friends = ['user_1', 'user_2'];
echo "list friends: \n";
$response = $friend->listAll($user);
print_r($response);
echo "\n";
echo "add friends: \n";
$response = $friend->add($user, $friends);
print_r($response);
echo "\n";
echo "list friends: \n";
$response = $friend->listAll($user);
print_r($response);
echo "\n";
echo "update notename of friends: \n";
$response = $friend->updateNotename($user, [
[
'username' => 'user_1',
'note_name' => 'user_1_alias',
'others' => 'good friend'
], [
'username' => 'user_2',
'note_name' => 'user_2_alias',
'others' => 'normal friend'
]
]);
print_r($response);
echo "\n";
echo "list friends: \n";
$response = $friend->listAll($user);
print_r($response);
echo "\n";
echo "remove friends: \n";
$response = $friend->remove($user, $friends);
print_r($response);
echo "\n";
<?php
require __DIR__ . '/config.php';
use JMessage\IM\Group;
$group = new Group($jm);
$owner = 'user_0';
$name = 'jiguang';
// $members = ['user_1', 'user_2', 'user_3'];
$members = [];
$mems = ['user_4', 'user_5'];
$desc = 'jiguang gtoup';
echo "create group: \n";
$response = $group->create($owner, $name, $desc, $members);
print_r($response);
echo "\n";
$gid = $response['body']['gid'];
echo "show group: \n";
$response = $group->show($gid);
print_r($response);
echo "\n";
echo "update group: \n";
$name = 'new jiguang';
$desc = 'new jiguang gtoup';
$response = $group->update($gid, $name, $desc);
print_r($response);
echo "\n";
echo "group list: \n";
$response = $group->listAll(0, 10);
print_r($response);
echo "\n";
#### members start
echo "list members in group: \n";
$response = $group->members($gid);
print_r($response);
echo "\n";
echo "add members to group: \n";
$response = $group->addMembers($gid, $mems);
print_r($response);
echo "\n";
echo "list members in group: \n";
$response = $group->members($gid);
print_r($response);
echo "\n";
echo "remove members from group: \n";
$response = $group->removeMembers($gid, $mems);
print_r($response);
echo "\n";
echo "list members in group: \n";
$response = $group->members($gid);
print_r($response);
echo "\n";
#### members end
echo "delete group: \n";
$response = $group->delete($gid);
print_r($response);
echo "\n";
<?php
require __DIR__ . '/config.php';
use JMessage\IM\Report;
$report = new Report($jm);
$response = $report->getMessages(0, 100);
print_r($response);
$response = $report->getUserMessages('user_0', 0, 100);
print_r($response);
<?php
require __DIR__ . '/config.php';
use JMessage\IM\Resource;
$rescource = new Resource($jm);
$image = __DIR__ . '/jiguang.png';
echo "upload image: \n";
$response = $rescource->upload('image', $image);
print_r($response);
echo "\n";
echo "upload file: \n";
$response = $rescource->upload('file', $image);
print_r($response);
echo "\n";
$mediaId = $response['body']['media_id'];
echo "download file: \n";
$response = $rescource->download($mediaId);
print_r($response);
echo "\n";
<?php
require __DIR__ . '/../config.php';
use JMessage\IM\Blacklist;
$blacklist = new Blacklist($jm);
$user = 'user_0';
echo "add blacklist: \n";
$response = $blacklist->add($user, ['user_1']);
print_r($response);
echo "\n";
echo "get blacklists: \n";
$response = $blacklist->listAll($user);
print_r($response);
echo "\n";
echo "remove blacklist: \n";
$response = $blacklist->remove($user, ['user_1']);
print_r($response);
echo "\n";
echo "get blacklists: \n";
$response = $blacklist->listAll($user);
print_r($response);
echo "\n";
<?php
require __DIR__ . '/../config.php';
use JMessage\IM\User;
$user = new User($jm);
$username = 'user_0';
echo "add single nodisturb: \n";
$response = $user->addSingleNodisturb($username, ['user_1']);
print_r($response);
echo "\n";
echo "remove single nodisturb: \n";
$response = $user->removeSingleNodisturb($username, ['user_1']);
print_r($response);
echo "\n";
echo "open global nodisturb: \n";
$response = $user->openGlobalNodisturb($username);
print_r($response);
echo "\n";
echo "close global nodisturb: \n";
$response = $user->closeGlobalNodisturb($username);
print_r($response);
echo "\n";
// 自定义免打扰的设置参数比较复杂,建议使用上面所述的 6 种方式设置免打扰。
// echo "custom nodisturb setting: \n";
// $touser = 'user';
// $user0 = 'user_0';
// $user1 = 'user_1';
// $user2 = 'user_2';
// $user3 = 'user_3';
// $gid0 = '10000';
// $gid1 = '10001';
// $gid2 = '10002';
// $gid3 = '10003';
// $options = [
// "single" => [
// "add" => [$user0, $user1],
// "remove" => [$user2, $user3],
// ],
// "group" => [
// "add" => [$gid0, $gid1],
// "remove" => [$gid2, $gid3],
// ],
// "global" => 1
// ];
// $response = $user->nodisturb($touser, $options);
// print_r($response);
// echo "\n";
<?php
require __DIR__ . '/../config.php';
use JMessage\IM\User;
$user = new User($jm);
$users = [
['username' => 'user_0', 'password' => 'password'],
['username' => 'user_1', 'password' => 'password'],
['username' => 'user_2', 'password' => 'password'],
['username' => 'user_3', 'password' => 'password'],
['username' => 'user_4', 'password' => 'password'],
['username' => 'user_5', 'password' => 'password'],
['username' => 'user_6', 'password' => 'password'],
['username' => 'user_7', 'password' => 'password'],
['username' => 'user_8', 'password' => 'password'],
['username' => 'user_9', 'password' => 'password'],
['username' => 'user_10', 'password' => 'password']
];
$response = $user->batchRegister($users);
print_r($response);
$username = 'username_20';
$password = 'password';
$response = $user->register($username, $password);
print_r($response);
<?php
require __DIR__ . '/../config.php';
use JMessage\IM\User;
$user = new User($jm);
$username = 'user_0';
echo "get users list: \n";
$response = $user->listAll(0, 100);
print_r($response);
echo "\n";
echo "get user info: \n";
$response = $user->show($username);
print_r($response);
echo "\n";
echo "update user info: \n";
$response = $user->update($username, ['nickname' => 'user_nickname_0', 'gender' => 2]);
print_r($response);
echo "\n";
echo "get user stat: \n";
$response = $user->stat($username);
print_r($response);
echo "\n";
echo "change user password: \n";
$response = $user->updatePassword($username, 'password_0');
print_r($response);
echo "\n";
// echo "delete user: \n";
// $response = $user->delete('user_10');
// print_r($response);
// echo "\n";
echo "get user's groups: \n";
$response = $user->groups($username);
print_r($response);
echo "\n";
<?php
namespace JMessage\Cross;
use JMessage\IM;
class Blacklist extends IM {
const BASE_URI = 'https://api.im.jpush.cn/v1/cross/users/';
public function add($user, $appKey, array $usernames) {
$body = [[
'appKey' => $appKey,
'usernames' => $usernames
]];
return $this->batchAdd($user, $body);
}
public function batchAdd($user, array $options) {
$uri = self::BASE_URI . $user . '/blacklist';
$body = $options;
$response = $this->put($uri, $body);
return $response;
}
public function remove($user, $appKey, array $usernames) {
$body = [[
'appKey' => $appKey,
'usernames' => $usernames
]];
return $this->batchRemove($user, $body);
}
public function batchRemove($user, array $options) {
$uri = self::BASE_URI . $user . '/blacklist';
$body = $options;
$response = $this->del($uri, $body);
return $response;
}
public function listAll($user) {
$uri = self::BASE_URI . $user . '/blacklist';
$response = $this->get($uri);
return $response;
}
}
<?php
namespace JMessage\Cross;
use JMessage\IM;
class Friend extends IM {
const BASE_URI = 'https://api.im.jpush.cn/v1/cross/users/';
public function add($user, $appKey, array $friendnames) {
$uri = self::BASE_URI . $user . '/friends';
$body = [
'appKey' => $appKey,
'users' => $friendnames
];
$response = $this->post($uri, $body);
return $response;
}
public function remove($user, $appKey, array $friendnames) {
$uri = self::BASE_URI . $user . '/friends';
$body = [
'appKey' => $appKey,
'users' => $friendnames
];
$response = $this->del($uri, $body);
return $response;
}
public function updateNotename($user, $appKey, $friendname, array $options) {
$body = [
'appKey' => $appKey,
'username' => $friendname
];
if (isset($options['note_name'])) {
$body['note_name'] = $options['note_name'];
}
if (isset($options['others'])) {
$body['others'] = $options['others'];
}
return $this->batchUpdateNotename($user, [$body]);
}
public function batchUpdateNotename($user, array $options) {
$uri = self::BASE_URI . $user . '/friends';
$response = $this->put($uri, $body);
return $response;
}
}
<?php
namespace JMessage\Cross;
use JMessage\IM;
class Member extends IM {
const BASE_URI = 'https://api.im.jpush.cn/v1/cross/groups/';
public function add($gid, $appKey, array $usernames) {
$body = [[
'appKey' => $appKey,
'add' => $usernames
]];
return $this->update($gid, $body);
}
public function remove($gid, $appKey, array $usernames) {
$body = [[
'appKey' => $appKey,
'remove' => $usernames
]];
return $this->update($gid, $body);
}
public function update($gid, array $options) {
$uri = self::BASE_URI . $gid . '/members';
$body = $options;
$response = $this->post($uri, $body);
return $response;
}
public function listAll($gid) {
$uri = self::BASE_URI . $gid . '/members';
$response = $this->get($uri);
return $response;
}
}
<?php
namespace JMessage\Cross;
use JMessage\IM;
class Nodisturb extends IM {
const BASE_URI = 'https://api.im.jpush.cn/v1/cross/users/';
public function single($user, $appKey, array $options) {
$body = [ 'appKey' => $appKey ];
if (!isset($options['add'])) {
$body['single']['add'] = $options['add'];
}
if (!isset($options['remove'])) {
$body['single']['remove'] = $options['remove'];
}
return $this->nodisturb($user, [$body]);
}
public function group($user, $appKey, array $options) {
$body = [ 'appKey' => $appKey ];
if (!isset($options['add'])) {
$body['group']['add'] = $options['add'];
}
if (!isset($options['remove'])) {
$body['group']['remove'] = $options['remove'];
}
return $this->nodisturb($user, [$body]);
}
public function nodisturb($user, array $options ) {
$uri = self::BASE_URI . $user . '/nodisturb';
$body = $options;
$response = $this->post($uri, $body);
return $response;
}
}
<?php
namespace JMessage;
class Http {
private $client;
private static $_instance = null;
public function get($uri, array $query = []) {
if (!empty($query)) {
$uri = $uri . '?' . http_build_query($query);
}
return self::request($this->client, 'GET', $uri);
}
public function post($uri, array $body = []) {
return self::request($this->client, 'POST', $uri, $body);
}
public function put($uri, array $body = []) {
return self::request($this->client, 'PUT', $uri, $body);
}
public function delete($uri, array $body = []) {
return self::request($this->client, 'DELETE', $uri, $body);
}
public function upload($uri, array $body = []) {
$headers = [
'Content-Type: multipart/form-data',
'Connection: Keep-Alive'
];
return self::request($this->client, 'UPLOAD', $uri, $body, $headers);
}
public static function getInstance($client) {
if (is_null(self::$_instance) || !(self::$_instance instanceof self)) {
self::$_instance = new self($client);
}
return self::$_instance;
}
private function __construct($client) {
$this->client = $client;
}
private function __clone() {}
private static function request($client, $method, $uri, array $body = [], array $headers = []) {
$default_headers = [
'Content-Type: application/json',
'Connection: Keep-Alive'
];
$method = strtoupper($method);
$ch = curl_init();
$options = array(
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HEADER => true,
CURLOPT_HTTPHEADER => (empty($headers) ? $default_headers : $headers),
CURLOPT_USERAGENT => 'JMessage-Api-PHP-Client',
CURLOPT_CONNECTTIMEOUT => 20,
CURLOPT_TIMEOUT => 120,
CURLOPT_HTTPAUTH => CURLAUTH_BASIC,
CURLOPT_USERPWD => $client->getAuth(),
CURLOPT_URL => $uri,
CURLOPT_CUSTOMREQUEST => ('UPLOAD' == $method) ? 'POST' : $method
);
if (!empty($body)) {
if ('UPLOAD' == $method) {
if (class_exists('\CURLFile')) {
$options[CURLOPT_SAFE_UPLOAD] = true;
$options[CURLOPT_POSTFIELDS] = ['filename' => new \CURLFile($body['path'])];
} else {
# TODO
if (defined('CURLOPT_SAFE_UPLOAD')) {
$options[CURLOPT_SAFE_UPLOAD] = false;
$options[CURLOPT_POSTFIELDS] = '';
}
}
} else {
$options[CURLOPT_POSTFIELDS] = json_encode($body);
}
}
curl_setopt_array($ch, $options);
$output = curl_exec($ch);
if($output === false) {
return "Error Code:" . curl_errno($ch) . ", Error Message:".curl_error($ch);
} else {
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
$header_size = curl_getinfo($ch, CURLINFO_HEADER_SIZE);
$header_text = substr($output, 0, $header_size);
$body = substr($output, $header_size);
$headers = array();
foreach (explode("\r\n", $header_text) as $i => $line) {
if (!empty($line)) {
if ($i === 0) {
$headers[0] = $line;
} else if (strpos($line, ": ")) {
list ($key, $value) = explode(': ', $line);
$headers[$key] = $value;
}
}
}
$response['headers'] = $headers;
$response['body'] = json_decode($body, true);
$response['http_code'] = $httpCode;
}
curl_close($ch);
return $response;
}
}
<?php
namespace JMessage;
use JMessage\Http;
class IM {
private $client;
public function __construct($client) {
$this->client = Http::getInstance($client);
}
public function get($uri, array $query = []) {
return $this->client->get($uri, $query);
}
public function post($uri, array $body = []) {
return $this->client->post($uri, $body);
}
public function put($uri, array $body = []) {
return $this->client->put($uri, $body);
}
public function del($uri, array $body = []) {
return $this->client->delete($uri, $body);
}
protected function getClient() {
return $this->client;
}
}
<?php
namespace JMessage\IM;
use JMessage\IM;
class Admin extends IM {
const BASE_URI = 'https://api.im.jpush.cn/v1/admins/';
public function register(array $admin) {
$uri = self::BASE_URI;
$body = $admin;
$response = $this->post($uri, $body);
return $response;
}
public function listAll($start = 0, $count = 10) {
$uri = self::BASE_URI;
$query = [
'start' => $start,
'count' => $count
];
$response = $this->get($uri, $query);
return $response;
}
}
<?php
namespace JMessage\IM;
use JMessage\IM;
class Blacklist extends IM {
const BASE_URI = 'https://api.im.jpush.cn/v1/users/';
public function add($user, array $usernames) {
$uri = self::BASE_URI . $user . '/blacklist';
$body = $usernames;
$response = $this->put($uri, $body);
return $response;
}
public function remove($user, array $usernames) {
$uri = self::BASE_URI . $user . '/blacklist';
$body = $usernames;
$response = $this->del($uri, $body);
return $response;
}
public function listAll($user) {
$uri = self::BASE_URI . $user . '/blacklist';
$response = $this->get($uri);
return $response;
}
}
<?php
namespace JMessage\IM;
use JMessage\IM;
class Friend extends IM {
const BASE_URI = 'https://api.im.jpush.cn/v1/users/';
public function add($user, array $friends) {
$uri = self::BASE_URI . $user . '/friends';
$body = $friends;
$response = $this->post($uri, $body);
return $response;
}
public function remove($user, array $friends) {
$uri = self::BASE_URI . $user . '/friends';
$body = $friends;
$response = $this->del($uri, $body);
return $response;
}
public function updateNotename($user, array $options) {
$uri = self::BASE_URI . $user . '/friends';
$body = $options;
$response = $this->put($uri, $body);
return $response;
}
public function listAll($user) {
$uri = self::BASE_URI . $user . '/friends';
$response = $this->get($uri);
return $response;
}
}
<?php
namespace JMessage\IM;
use JMessage\IM;
class Group extends IM {
const BASE_URI = 'https://api.im.jpush.cn/v1/groups/';
public function create($owner, $name, $desc, array $members = []) {
$uri = self::BASE_URI;
$body = [
'owner_username' => $owner,
'name' => $name,
'desc' => $desc,
'members_username' => $members
];
$response = $this->post($uri, $body);
return $response;
}
public function show($gid) {
$uri = self::BASE_URI . $gid;
$response = $this->get($uri);
return $response;
}
public function update($gid, $name = null, $desc = null) {
$uri = self::BASE_URI . $gid;
$body = [];
if (!is_null($name)) { $body['name'] = $name; }
if (!is_null($desc)) { $body['desc'] = $desc; }
$response = $this->put($uri, $body);
return $response;
}
public function delete($gid) {
$uri = self::BASE_URI . $gid;
$response = $this->del($uri);
return $response;
}
public function listAll($start = 0, $count = 20) {
$uri = self::BASE_URI;
$query = [
'start' => $start,
'count' => $count
];
$response = $this->get($uri, $query);
return $response;
}
public function addMembers($gid, array $add) {
return $this->updateMembers($gid, [ 'add' => $add ]);
}
public function removeMembers($gid, array $remove) {
return $this->updateMembers($gid, [ 'remove' => $remove ]);
}
public function updateMembers($gid, array $options) {
$uri = self::BASE_URI . $gid . '/members';
$body = $options;
$response = $this->post($uri, $body);
return $response;
}
public function members($gid) {
$uri = self::BASE_URI . $gid . '/members';
$response = $this->get($uri);
return $response;
}
}
<?php
namespace JMessage\IM;
use JMessage\IM;
class Message extends IM {
const BASE_URI = 'https://api.im.jpush.cn/v1/messages';
public function sendText($version, array $from, array $target, array $msg) {
$options = [
'version' => $version,
'target_type' => $target['type'],
'from_type' => $from['type'],
'msg_type' => 'text',
'target_id' => $target['id'],
'from_id' => $from['id'],
'msg_body' => [
'text' => $msg['text']
]
];
if (isset($from['name'])) {
$options['from_name'] = $from['name'];
}
if (isset($target['name'])) {
$options['target_name'] = $target['name'];
}
if (isset($msg['extras']) && is_array($msg['extras'])) {
$options['msg_body']['extras'] = $msg['extras'];
}
return $this->send($options);
}
public function sendImage($version, array $from, array $target, array $msg) {
$options = [
'version' => $version,
'target_type' => $target['type'],
'from_type' => $from['type'],
'msg_type' => 'image',
'target_id' => $target['id'],
'from_id' => $from['id'],
'msg_body' => [
'media_id' => $msg['mediaId'],
'media_crc32' => $msg['mediaCrc32'],
'width' => $msg['width'],
'height' => $msg['height'],
'format' => $msg['format'],
'fsize' => $msg['fsize']
]
];
if (isset($from['name'])) {
$options['from_name'] = $from['name'];
}
if (isset($target['name'])) {
$options['target_name'] = $target['name'];
}
if (isset($msg['extras']) && is_array($msg['extras'])) {
$options['msg_body']['extras'] = $msg['extras'];
}
return $this->send($options);
}
public function sendCustom($version, array $from, array $target, array $msg) {
$options = [
'version' => $version,
'target_type' => $target['type'],
'from_type' => $from['type'],
'msg_type' => 'custom',
'target_id' => $target['id'],
'from_id' => $from['id'],
'msg_body' => $msg
];
if (isset($from['name'])) {
$options['from_name'] = $from['name'];
}
if (isset($target['name'])) {
$options['target_name'] = $target['name'];
}
return $this->send($options);
}
public function send($options) {
$uri = self::BASE_URI;
$body = $options;
$response = $this->post($uri, $body);
return $response;
}
}
<?php
namespace JMessage\IM;
use JMessage\IM;
class Report extends IM {
const BASE_URL = 'https://report.im.jpush.cn/v1/';
public function getMessages($start, $count, $beginTime = null, $endTime = null) {
$uri = self::BASE_URL . 'messages';
return $this->report($uri, $start, $count, $beginTime, $endTime);
}
public function getUserMessages($username, $start, $count, $beginTime = null, $endTime = null) {
$uri = self::BASE_URL . '/users/' . $username . '/messages';
return $this->report($uri, $start, $count, $beginTime, $endTime);
}
private function report($uri, $start, $count, $beginTime = null, $endTime = null) {
$query = [
'start' => $start,
'count' => $count
];
if (!is_null($beginTime)) {
$query['begin_time'] = $beginTime;
}
if (!is_null($endTime)) {
$query['end_time'] = $endTime;
}
return $this->get($uri, $query);
}
}
<?php
namespace JMessage\IM;
use JMessage\IM;
class Resource extends IM {
const BASE_URI = 'https://api.im.jpush.cn/v1/resource';
public function download($mediaId) {
$uri = self::BASE_URI;
$query = [ 'mediaId' => $mediaId ];
$response = $this->get($uri, $query);
return $response;
}
public function upload($type, $path) {
$uri = self::BASE_URI . '?' . http_build_query(['type' => $type]);
$body = ['path' => $path];
$response = $this->getClient()->upload($uri, $body);
return $response;
}
}
<?php
namespace JMessage\IM;
use JMessage\IM;
class User extends IM {
const BASE_URI = 'https://api.im.jpush.cn/v1/users/';
public function register($username, $password) {
$body = [[
'username' => $username,
'password' => $password
]];
return $this->batchRegister($body);
}
public function batchRegister(array $users) {
$uri = self::BASE_URI;
$body = $users;
$response = $this->post($uri, $body);
return $response;
}
public function show($username) {
$uri = self::BASE_URI . $username;
$response = $this->get($uri);
return $response;
}
public function update($username, array $options) {
$uri = self::BASE_URI . $username;
$body = $options;
$response = $this->put($uri, $body);
return $response;
}
public function stat($username) {
$uri = self::BASE_URI . $username . '/userstat';
$response = $this->get($uri);
return $response;
}
public function updatePassword($username, $password) {
$uri = self::BASE_URI . $username . '/password';
$response = $this->put($uri, [ 'new_password' => $password ]);
return $response;
}
public function delete($username) {
$uri = self::BASE_URI . $username;
$response = $this->del($uri);
return $response;
}
public function listAll($start = 0, $count = 10) {
$uri = self::BASE_URI;
$query = [
'start' => $start,
'count' => $count
];
$response = $this->get($uri, $query);
return $response;
}
public function groups($username) {
$uri = self::BASE_URI . $username . '/groups';
$response = $this->get($uri);
return $response;
}
############## NoDisturb
public function addSingleNodisturb($touser, array $usernames) {
$single = [ 'add' => $usernames ];
return $this->nodisturb($touser, [ 'single' => $single ]);
}
public function removeSingleNodisturb($touser, array $usernames) {
$single = [ 'remove' => $usernames ];
return $this->nodisturb($touser, [ 'single' => $single ]);
}
public function addGroupNodisturb($touser, array $gids) {
$group = [ 'add' => $gids ];
return $this->nodisturb($touser, [ 'group' => $group ]);
}
public function removeGroupNodisturb($touser, array $gids) {
$group = [ 'remove' => $gids ];
return $this->nodisturb($touser, [ 'group' => $group ]);
}
// public function setGlobalNodisturb($touser, bool $opened) {
// return $this->nodisturb($touser, [ 'global' => (int)$opened ]);
// }
public function openGlobalNodisturb($touser) {
return $this->nodisturb($touser, [ 'global' => 1 ]);
}
public function closeGlobalNodisturb($touser) {
return $this->nodisturb($touser, [ 'global' => 0 ]);
}
public function nodisturb($touser, array $options) {
$uri = self::BASE_URI . $touser . '/nodisturb';
$body = $options;
$response = $this->post($uri, $body);
return $response;
}
}
<?php
namespace JMessage;
class JMessage {
private $appKey;
private $masterSecret;
private $options;
public function __construct($appKey, $masterSecret, array $options = []) {
$this->appKey = $appKey;
$this->masterSecret = $masterSecret;
$this->options = $options;
}
public function getAuth() {
return $this->appKey . ':' . $this->masterSecret;
}
}
# CHANGELOG
## 2.0.0
- changed the `__constructor` parameters. Now you inject an optional `Sirius\Validation\ValueValidator` instance instead of an `Sirius\Validation\ErrorMessage` instance
- changed dependency to Sirius\Validation~2.0
\ No newline at end of file
The MIT License (MIT)
Copyright (c) 2014 Adrian Miu
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
# Sirius\Upload
[![Source Code](http://img.shields.io/badge/source-siriusphp/upload-blue.svg?style=flat-square)](https://github.com/siriusphp/upload)
[![Latest Version](https://img.shields.io/packagist/v/siriusphp/upload.svg?style=flat-square)](https://github.com/siriusphp/upload/releases)
[![Software License](https://img.shields.io/badge/license-MIT-brightgreen.svg?style=flat-square)](https://github.com/siriusphp/upload/blob/master/LICENSE)
[![Build Status](https://img.shields.io/travis/siriusphp/upload/master.svg?style=flat-square)](https://travis-ci.org/siriusphp/upload)
[![PHP 7 ready](http://php7ready.timesplinter.ch/siriusphp/upload/master/badge.svg)](https://travis-ci.org/siriusphp/upload)
[![Coverage Status](https://img.shields.io/scrutinizer/coverage/g/siriusphp/upload.svg?style=flat-square)](https://scrutinizer-ci.com/g/siriusphp/upload/code-structure)
[![Quality Score](https://img.shields.io/scrutinizer/g/siriusphp/upload.svg?style=flat-square)](https://scrutinizer-ci.com/g/siriusphp/upload)
[![Total Downloads](https://img.shields.io/packagist/dt/siriusphp/upload.svg?style=flat-square)](https://packagist.org/packages/siriusphp/upload)
Framework agnostic upload handler library.
## Features
1. Validates files agains usual rules: extension, file size, image size (wdith, height, ratio). It uses [Sirius Validation](http://github.com/siriusphp/validation) for this purpose.
2. Moves valid uploaded files into containers. Containers are usually local folders but you can implement your own or use other filesystem abstractions like [Gaufrette](https://github.com/KnpLabs/Gaufrette) or [Flysystem](https://github.com/FrenkyNet/Flysystem).
## Elevator pitch
```php
use Sirius\Upload\Handler as UploadHandler;
$uploadHandler = new UploadHandler('/path/to/local_folder');
// validation rules
$uploadHandler->addRule('extension', ['allowed' => ['jpg', 'jpeg', 'png']], '{label} should be a valid image (jpg, jpeg, png)', 'Profile picture');
$uploadHandler->addRule('size', ['max' => '20M'], '{label} should have less than {max}', 'Profile picture');
$result = $uploadHandler->process($_FILES['picture']); // ex: subdirectory/my_headshot.png
if ($result->isValid()) {
// do something with the image like attaching it to a model etc
try {
$profile->picture = $result->name;
$profile->save();
$result->confirm(); // this will remove the .lock file
} catch (\Exception $e) {
// something wrong happened, we don't need the uploaded files anymore
$result->clear();
throw $e;
}
} else {
// image was not moved to the container, where are error messages
$messages = $result->getMessages();
}
```
##Links
- [documentation](http://www.sirius.ro/php/sirius/upload/)
- [changelog](CHANGELOG.md)
<?php
spl_autoload_register(function ($class) {
// what namespace prefix should be recognized?
$prefix = 'Sirius\Upload\\';
// does the requested class match the namespace prefix?
$prefix_len = strlen($prefix);
if (substr($class, 0, $prefix_len) !== $prefix) {
return;
}
// strip the prefix off the class
$class = substr($class, $prefix_len);
// a partial filename
$part = str_replace('\\', DIRECTORY_SEPARATOR, $class) . '.php';
// directories where we can find classes
$dirs = array(
__DIR__ . DIRECTORY_SEPARATOR . 'src',
__DIR__ . DIRECTORY_SEPARATOR . 'tests' . DIRECTORY_SEPARATOR . 'src',
);
// go through the directories to find classes
foreach ($dirs as $dir) {
$file = $dir . DIRECTORY_SEPARATOR . $part;
if (is_readable($file)) {
require $file;
return;
}
}
});
\ No newline at end of file
{
"name": "siriusphp/upload",
"description": "Framework agnostic upload library",
"type": "library",
"license": "MIT",
"keywords": [
"form",
"upload",
"validation",
"file"
],
"authors": [
{
"name": "Adrian Miu",
"email": "adrian@adrianmiu.ro"
}
],
"require": {
"php": ">=5.3",
"siriusphp/validation": "~2.1"
},
"require-dev": {
"phpunit/phpunit": "~4.8"
},
"suggest": {
"league/flysystem": "To upload to different destinations, not just to the local file system",
"knplabs/gaufrette": "Alternative filesystem abstraction library for upload destinations"
},
"autoload": {
"psr-4": {
"Sirius\\Upload\\": "src/"
}
}
}
<?php
namespace Sirius\Upload\Container;
interface ContainerInterface
{
/**
* Check if the container is writable
*/
public function isWritable();
/**
* This will check if a file is in the container
*
* @param string $file
*/
public function has($file);
/**
* Saves the $content string as a file
*
* @param string $file
* @param string $content
*/
public function save($file, $content);
/**
* Delete the file from the container
*
* @param string $file
*/
public function delete($file);
/**
* Moves a temporary uploaded file to a destination in the container
*
* @param string $localFile local path
* @param string $destination
*/
public function moveUploadedFile($localFile, $destination);
}
<?php
namespace Sirius\Upload\Container;
class Local implements ContainerInterface
{
protected $baseDirectory;
public function __construct($baseDirectory)
{
$this->baseDirectory = $this->normalizePath($baseDirectory) . DIRECTORY_SEPARATOR;
$this->ensureDirectory($this->baseDirectory);
}
protected function normalizePath($path)
{
$path = dirname(rtrim($path, '\\/') . DIRECTORY_SEPARATOR . 'xxx');
return rtrim($path, DIRECTORY_SEPARATOR);
}
protected function ensureDirectory($directory)
{
if (!file_exists($directory)) {
mkdir($directory, 0755, true);
}
return is_dir($directory) && $this->isWritable();
}
/**
* Check if the container is writable
*/
public function isWritable()
{
return is_writable($this->baseDirectory);
}
/**
* This will check if a file is in the container
*
* @param string $file
* @return bool
*/
public function has($file)
{
return $file && file_exists($this->baseDirectory . $file);
}
/**
* Saves the $content string as a file
*
* @param string $file
* @param string $content
* @return bool
*/
public function save($file, $content)
{
$file = $this->normalizePath($file);
$dir = dirname($this->baseDirectory . $file);
if ($this->ensureDirectory($dir)) {
return (bool) file_put_contents($this->baseDirectory . $file, $content);
}
return false;
}
/**
* Delete the file from the container
*
* @param string $file
* @return bool
*/
public function delete($file)
{
$file = $this->normalizePath($file);
if (file_exists($this->baseDirectory . $file)) {
return unlink($this->baseDirectory . $file);
}
return true;
}
/**
* Moves a temporary uploaded file to a destination in the container
*
* @param string $localFile local path
* @param string $destination
* @return bool
*/
public function moveUploadedFile($localFile, $destination)
{
$dir = dirname($this->baseDirectory . $destination);
if (file_exists($localFile) && $this->ensureDirectory($dir)) {
/**
* we could use is_uploaded_file() and move_uploaded_file()
* but in case of ajax uploads that would fail
*/
if (is_readable($localFile)) {
// rename() would be good but this is better because $localFile may become 'unwritable'
$result = copy($localFile, $this->baseDirectory . $destination);
@unlink($localFile);
return $result;
}
}
return false;
}
}
<?php
namespace Sirius\Upload\Exception;
class InvalidContainerException extends \RuntimeException
{
}
<?php
namespace Sirius\Upload\Exception;
class InvalidResultException extends \RuntimeException
{
}
<?php
namespace Sirius\Upload;
use Sirius\Upload\Container\ContainerInterface;
use Sirius\Upload\Container\Local as LocalContainer;
use Sirius\Upload\Exception\InvalidContainerException;
use Sirius\Upload\Util\Arr;
use Sirius\Validation\ErrorMessage;
use Sirius\Validation\ValueValidator;
class Handler implements UploadHandlerInterface
{
// constants for constructor options
const OPTION_PREFIX = 'prefix';
const OPTION_OVERWRITE = 'overwrite';
const OPTION_AUTOCONFIRM = 'autoconfirm';
// constants for validation rules
const RULE_EXTENSION = 'extension';
const RULE_SIZE = 'size';
const RULE_IMAGE = 'image';
const RULE_IMAGE_HEIGHT = 'imageheight';
const RULE_IMAGE_WIDTH = 'imagewidth';
const RULE_IMAGE_RATIO = 'imageratio';
/**
* @var ContainerInterface
*/
protected $container;
/**
* Prefix to be added to the file.
* It can be a subfolder (if it ends with '/', a string to be used as prefix)
* or a callback that returns a string
*
* @var string|callback
*/
protected $prefix = '';
/**
* When uploading a file that has the same name as a file that is
* already in the container should it overwrite it or use another name
*
* @var boolean
*/
protected $overwrite = false;
/**
* Whether or not the uploaded files are auto confirmed
*
* @var boolean
*/
protected $autoconfirm = false;
/**
* @var \Sirius\Validation\ValueValidator
*/
protected $validator;
/**
* @var function|callback
*/
protected $sanitizerCallback;
/**
* @param $directoryOrContainer
* @param array $options
* @param ValueValidator $validator
* @throws InvalidContainerException
*/
public function __construct($directoryOrContainer, $options = array(), ValueValidator $validator = null)
{
$container = $directoryOrContainer;
if (is_string($directoryOrContainer)) {
$container = new LocalContainer($directoryOrContainer);
}
if (!$container instanceof ContainerInterface) {
throw new InvalidContainerException('Destination container for uploaded files is not valid');
}
$this->container = $container;
// create the validator
if (!$validator) {
$validator = new ValueValidator();
}
$this->validator = $validator;
// set options
$availableOptions = array(
static::OPTION_PREFIX => 'setPrefix',
static::OPTION_OVERWRITE => 'setOverwrite',
static::OPTION_AUTOCONFIRM => 'setAutoconfirm'
);
foreach ($availableOptions as $key => $method) {
if (isset($options[$key])) {
$this->{$method}($options[$key]);
}
}
}
/**
* Enable/disable upload overwrite
*
* @param bool $overwrite
* @return \Sirius\Upload\Handler
*/
public function setOverwrite($overwrite)
{
$this->overwrite = (bool) $overwrite;
return $this;
}
/**
* File prefix for the upload. Can be
* - a folder (if it ends with /)
* - a string to be used as prefix
* - a function that returns a string
*
* @param string|callable $prefix
* @return \Sirius\Upload\Handler
*/
public function setPrefix($prefix)
{
$this->prefix = $prefix;
return $this;
}
/**
* Enable/disable upload autoconfirmation
* Autoconfirmation does not require calling `confirm()`
*
* @param boolean $autoconfirm
* @return \Sirius\Upload\Handler
*/
public function setAutoconfirm($autoconfirm)
{
$this->autoconfirm = (bool) $autoconfirm;
return $this;
}
/**
* Set the sanitizer function for cleaning up the file names
*
* @param callable $callback
* @throws \InvalidArgumentException
* @return \Sirius\Upload\Handler
*/
function setSanitizerCallback($callback)
{
if (!is_callable($callback)) {
throw new \InvalidArgumentException('The $callback parameter is not a valid callable entity');
}
$this->sanitizerCallback = $callback;
return $this;
}
/**
* Add validation rule (extension|size|width|height|ratio)
*
* @param string $name
* @param mixed $options
* @param string $errorMessageTemplate
* @param string $label
* @return \Sirius\Upload\Handler
*/
public function addRule($name, $options = null, $errorMessageTemplate = null, $label = null)
{
$predefinedRules = array(
static::RULE_EXTENSION,
static::RULE_IMAGE,
static::RULE_SIZE,
static::RULE_IMAGE_WIDTH,
static::RULE_IMAGE_HEIGHT,
static::RULE_IMAGE_RATIO
);
// convert to a name that is known by the default RuleFactory
if (in_array($name, $predefinedRules)) {
$name = 'upload' . $name;
}
$this->validator->add($name, $options, $errorMessageTemplate, $label);
return $this;
}
/**
* Processes a file upload and returns an upload result file/collection
*
* @param array $files
* @return Result\Collection|Result\File
*/
public function process($files = array())
{
$files = Arr::normalizeFiles($files);
foreach ($files as $k => $file) {
$files[$k] = $this->processSingleFile($file);
}
if (count($files) == 1) {
return new Result\File(array_pop($files), $this->container);
}
return new Result\Collection($files, $this->container);
}
/**
* Processes a single uploaded file
* - sanitize the name
* - validates the file
* - if valid, moves the file to the container
*
* @param array $file
* @return array
*/
protected function processSingleFile(array $file)
{
// store it for future reference
$file['original_name'] = $file['name'];
// sanitize the file name
$file['name'] = $this->sanitizeFileName($file['name']);
$file = $this->validateFile($file);
// if there are messages the file is not valid
if (isset($file['messages']) && $file['messages']) {
return $file;
}
// add the prefix
$prefix = '';
if (is_callable($this->prefix)) {
$prefix = (string) call_user_func($this->prefix, $file['name']);
} elseif (is_string($this->prefix)) {
$prefix = (string) $this->prefix;
}
// if overwrite is not allowed, check if the file is already in the container
if (!$this->overwrite) {
if ($this->container->has($prefix . $file['name'])) {
// add the timestamp to ensure the file is unique
// method is not bulletproof but it's pretty safe
$file['name'] = time() . '_' . $file['name'];
}
}
// attempt to move the uploaded file into the container
if (!$this->container->moveUploadedFile($file['tmp_name'], $prefix . $file['name'])) {
$file['name'] = false;
return $file;
}
$file['name'] = $prefix . $file['name'];
// create the lock file if autoconfirm is disabled
if (!$this->autoconfirm) {
$this->container->save($file['name'] . '.lock', time());
}
return $file;
}
/**
* Validates a file according to the rules configured on the handler
*
* @param $file
* @return mixed
*/
protected function validateFile($file)
{
if (!$this->validator->validate($file)) {
$file['messages'] = $this->validator->getMessages();
}
return $file;
}
/**
* Sanitize the name of the uploaded file by stripping away bad characters
* and replacing "invalid" characters with underscore _
*
* @param string $name
* @return string
*/
protected function sanitizeFileName($name)
{
if ($this->sanitizerCallback) {
return call_user_func($this->sanitizerCallback, $name);
}
return preg_replace('/[^A-Za-z0-9\.]+/', '_', $name);
}
}
<?php
namespace Sirius\Upload;
use Sirius\Upload\Result\Collection;
use Sirius\Upload\Util\Arr;
class HandlerAggregate implements \IteratorAggregate
{
protected $handlers = array();
/**
* Adds a handler on the aggregate
*
* @param string $selector
* @param Handler $handler
* @return $this
*/
public function addHandler($selector, Handler $handler)
{
$this->handlers[$selector] = $handler;
return $this;
}
/**
* Processes
* @param $files
* @return Collection
*/
public function process($files)
{
$result = new Collection();
foreach ($this->handlers as $selector => $handler) {
/* @var $handler Handler */
$selectedFiles = Arr::getBySelector($files, $selector);
if (!$selectedFiles || !is_array($selectedFiles) || empty($selectedFiles)) {
continue;
}
foreach ($selectedFiles as $path => $file) {
if (is_array($file)) {
$result[$path] = $handler->process($file);
}
}
}
return $result;
}
/**
* (PHP 5 &gt;= 5.0.0)<br/>
* Retrieve an external iterator
*
* @link http://php.net/manual/en/iteratoraggregate.getiterator.php
* @return \Traversable An instance of an object implementing <b>Iterator</b> or
* <b>Traversable</b>
*/
public function getIterator()
{
return $this->handlers;
}
}
<?php
namespace Sirius\Upload\Result;
use Sirius\Upload\Container\ContainerInterface;
class Collection extends \ArrayIterator
{
public function __construct($files = array(), ContainerInterface $container = null)
{
$filesArray = array();
if (is_array($files) && !empty($files)) {
foreach ($files as $key => $file) {
$filesArray[$key] = new File($file, $container);
}
}
parent::__construct($filesArray);
}
public function clear()
{
foreach ($this as $file) {
/* @var $file \Sirius\Upload\Result\File */
$file->clear();
}
}
public function confirm()
{
foreach ($this as $file) {
/* @var $file \Sirius\Upload\Result\File */
$file->confirm();
}
}
public function isValid()
{
foreach ($this->getMessages() as $messages) {
if ($messages) {
return false;
}
}
return true;
}
public function getMessages()
{
$messages = array();
foreach ($this as $key => $file) {
/* @var $file \Sirius\Upload\Result\File */
$messages[$key] = $file->getMessages();
}
return $messages;
}
}
<?php
namespace Sirius\Upload\Result;
use Sirius\Upload\Container\ContainerInterface;
class File
{
/**
* Array containing the details of the uploaded file:
* - name (uploaded name)
* - original name
* - tmp_name
* etc
*
* @var array
*/
protected $file;
/**
* The container to which this file belongs to
* @var \Sirius\Upload\Container\ContainerInterface
*/
protected $container;
/**
* @param $file
* @param ContainerInterface $container
*/
public function __construct($file, ContainerInterface $container)
{
$this->file = $file;
$this->container = $container;
}
/**
* Returns if the uploaded file is valid
*
* @return bool
*/
public function isValid()
{
return $this->file['name'] && count($this->getMessages()) === 0;
}
/**
* Returns the validation error messages
*
* @return array
*/
public function getMessages()
{
if (isset($this->file['messages'])) {
return $this->file['messages'];
} else {
return array();
}
}
/**
* The file that was saved during process() and has a .lock file attached
* will be cleared, in case the form processing fails
*/
public function clear()
{
$this->container->delete($this->name);
$this->container->delete($this->name . '.lock');
$this->file['name'] = null;
}
/**
* Remove the .lock file attached to the file that was saved during process()
* This should happen if the form fails validation/processing
*/
public function confirm()
{
$this->container->delete($this->name . '.lock');
}
/**
* File attribute getter
*
* @param $name
* @return mixed
*/
public function __get($name)
{
if (isset($this->file[$name])) {
return $this->file[$name];
}
return null;
}
}
<?php
namespace Sirius\Upload;
interface UploadHandlerInterface
{
/**
* This function will process the files received from $_FILES,
* validate them and save them into the container.
*
* Along with the file saved into the container a .lock file should
* be added by the container save() method so, in case the form is
* not validated, the uploaded file will be removed.
*
* @param array $files
*/
public function process($files = array());
}
<?php
namespace Sirius\Upload\Util;
class Arr extends \Sirius\Validation\Util\Arr
{
public static function remapFilesArray(array $files)
{
$result = array();
foreach ($files['name'] as $k => $v) {
$result[$k] = array(
'name' => $files['name'][$k],
'type' => @$files['type'][$k],
'size' => @$files['size'][$k],
'error' => @$files['error'][$k],
'tmp_name' => $files['tmp_name'][$k]
);
}
return $result;
}
/**
* Fixes the $_FILES array problem and ensures the result is an array of files
*
* PHP's $_FILES variable is not properly formated for iteration when
* multiple files are uploaded under the same name
* @see http://www.php.net/manual/en/features.file-upload.php
*
* @param array $files
* @return array
*/
public static function normalizeFiles(array $files)
{
// The caller passed $_FILES['some_field_name']
if (isset($files['name'])) {
// we have a single file
if(!is_array($files['name'])) {
return array($files);
}
// we have list of files, which PHP messes up
else {
return Arr::remapFilesArray($files);
}
}
// The caller passed $_FILES
else {
$keys = array_keys($files);
if (isset($keys[0]) && isset($files[$keys[0]]['name'])) {
if (!is_array($files[$keys[0]]['name'])) {
// $files is in the correct format already, even in the
// case it contains a single element.
return $files;
}
// we have list of files, which PHP messes up
else {
return Arr::remapFilesArray($files[$keys[0]]);
}
}
}
// if we got here, the $file argument is wrong
return array();
}
}
; This file is for unifying the coding style for different editors and IDEs.
; More information at http://editorconfig.org
root = true
[*]
charset = utf-8
indent_size = 4
indent_style = space
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
[*.md]
trim_trailing_whitespace = false
#### 2.2.0
- added `Upload\Required` rule
- fixed upload validators when the upload was not successful
#### 2.0.0
- added the `data_selector:label` feature
- implemented default rule messages in the `RuleFactory` class. This way, if you have a custom error message for the `required` fields, you don't have to provide it to all the required fields, just set it up once in the `RuleFactory`
- implemented a way to allow validation rule options to be passed as CSV (eg: '100,200' instead of 'min=200&max=200')
#### 1.2.4
- added PHP7 to Travis CI
- fixed bug with validating non-required elements (issue #17)
#### 1.2.2
- fixed bug with the 'between' validator (pull request #16)
- added support for PHP 5.3 (tests fail but due to the short array syntax, not the inherent code in the library)
- improved documentation on how to use complex validators (ie: that have dependencies)
#### 1.2.1
- fixed bug with the required rule not working properly on empty strings
#### 1.2.0
- improved the code base on Scrutinizer CI suggestions
- removed the ValidatableTrait trait
#### 1.1.0
- Added HHVM to Travis CI
- Renamed Validator\* classes into Rule\* classes (breaking change if you used custom rule classes)
- Renamed ValidatorFactory to RuleFactory (breaking change)
The MIT License (MIT)
Copyright (c) 2013 Adrian Miu
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
<?php
spl_autoload_register(function ($class) {
// what namespace prefix should be recognized?
$prefix = 'Sirius\Validation\\';
// does the requested class match the namespace prefix?
$prefix_len = strlen($prefix);
if (substr($class, 0, $prefix_len) !== $prefix) {
return;
}
// strip the prefix off the class
$class = substr($class, $prefix_len);
// a partial filename
$part = str_replace('\\', DIRECTORY_SEPARATOR, $class) . '.php';
// directories where we can find classes
$dirs = array(
__DIR__ . DIRECTORY_SEPARATOR . 'src',
__DIR__ . DIRECTORY_SEPARATOR . 'tests' . DIRECTORY_SEPARATOR . 'src',
);
// go through the directories to find classes
foreach ($dirs as $dir) {
$file = $dir . DIRECTORY_SEPARATOR . $part;
if (is_readable($file)) {
require $file;
return;
}
}
});
{
"name": "siriusphp/validation",
"description": "Data validation library. Validate arrays, array objects, domain models etc using a simple API. Easily add your own validators on top of the already dozens built-in validation rules",
"type": "library",
"license": "MIT",
"keywords": [
"form",
"validation",
"sanitization",
"security",
"modeling"
],
"authors": [
{
"name": "Adrian Miu",
"email": "adrian@adrianmiu.ro"
}
],
"require": {
"php": ">=5.3"
},
"require-dev": {
"phpunit/phpunit": "^3.7"
},
"autoload": {
"psr-4": {
"Sirius\\Validation\\": "src/"
}
},
"scripts": {
"phpcs": [
"php phpcs.phar --standard=PSR2 ./src"
],
"phpmd": [
"php phpmd.phar ./src xml phpmd.xml"
],
"phpcbf": [
"php phpcbf.phar ./src --standard=PSR2 -w"
],
"phpcsfix": [
"php php-cs-fixer.phar fix ./src --rules=@PSR2"
]
}
}
<?xml version="1.0"?>
<ruleset name="Sirius PMD ruleset" xmlns="http://pmd.sf.net/ruleset/1.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://pmd.sf.net/ruleset/1.0.0 http://pmd.sf.net/ruleset_xml_schema.xsd"
xsi:noNamespaceSchemaLocation=" http://pmd.sf.net/ruleset_xml_schema.xsd">
<description>Sirius PMD ruleset</description>
<rule ref="rulesets/codesize.xml">
<exclude name="CyclomaticComplexity"/>
<exclude name="ExcessiveMethodLength"/>
<exclude name="NPathComplexity"/>
<exclude name="TooManyMethods"/>
<exclude name="ExcessiveClassComplexity"/>
</rule>
<rule ref="rulesets/design.xml"/>
<rule ref="rulesets/naming.xml/LongVariable">
<properties>
<property name="maximum" value="25"/>
</properties>
</rule>
<rule ref="rulesets/naming.xml">
<exclude name="LongVariable"/>
<exclude name="ShortVariable"/>
</rule>
<rule ref="rulesets/unusedcode.xml">
<exclude name="UnusedFormalParameter"/>
</rule>
</ruleset>
\ No newline at end of file
#Sirius Validation
[![Source Code](http://img.shields.io/badge/source-siriusphp/validation-blue.svg?style=flat-square)](https://github.com/siriusphp/validation)
[![Latest Version](https://img.shields.io/packagist/v/siriusphp/validation.svg?style=flat-square)](https://github.com/siriusphp/validation/releases)
[![Software License](https://img.shields.io/badge/license-MIT-brightgreen.svg?style=flat-square)](https://github.com/siriusphp/validation/blob/master/LICENSE)
[![Build Status](https://img.shields.io/travis/siriusphp/validation/master.svg?style=flat-square)](https://travis-ci.org/siriusphp/validation)
[![PHP 7 ready](http://php7ready.timesplinter.ch/siriusphp/validation/master/badge.svg)](https://travis-ci.org/siriusphp/validation)
[![Coverage Status](https://img.shields.io/scrutinizer/coverage/g/siriusphp/validation.svg?style=flat-square)](https://scrutinizer-ci.com/g/siriusphp/validation/code-structure)
[![Quality Score](https://img.shields.io/scrutinizer/g/siriusphp/validation.svg?style=flat-square)](https://scrutinizer-ci.com/g/siriusphp/validation)
[![Total Downloads](https://img.shields.io/packagist/dt/siriusphp/validation.svg?style=flat-square)](https://packagist.org/packages/siriusphp/validation)
Sirius Validation is a library for data validation. It offers:
1. [validator object](docs/validator.md)
2. [45 build-in validation rules](docs/validation_rules.md). There are validators for strings, array, numbers, emails, URLs, files and uploads
3. [validation helper](docs/helper.md) to simplify the validation of single values
Out-of-the-box, the library can handle `array`s, `ArrayObject`s and objects that have implemented the `toArray` method.
In order to validate other data containers you must create a [`DataWrapper`](https://github.com/siriusphp/validation/blob/master/src/Validation/DataWrapper/WrapperInterface.php) so that the validator be able to extract data from your object.
##Elevator pitch
```php
$validator = new \Sirius\Validation\Validator;
// add a validation rule
$validator->add('title', 'required');
// add a rule that has a list of options
$validator->add('title', 'length', array('min' => 10, 'max' => 100));
// or use JSON
$validator->add('title', 'length', '{"min": 10, "max": 100}');
// or a URL query string
$validator->add('title', 'length', 'min=10&max=100');
// or, if you know that the validator can CORECTLY parse (ie: understand) the options string
$validator->add('title', 'length', '10,100');
// add a rule with a custom error message
$validator->add('title', 'maxlength', 'max=100', 'Article title must have less than {max} characters');
// add a rule with a custom message and a label (very handy with forms)
$validator->add('title:Title', 'maxlength', 'max=100', '{label} must have less than {max} characters');
// add all of rule's configuration in a string (you'll see later why it's handy')
$validator->add('title:Title', 'maxlength(max=255)({label} must have less than {max} characters)');
// add multiple rules at once (separate using [space][pipe][space])
$validator->add('title:Title', 'required | maxlength(255) | minlength(min=10)');
// add all your rules at once
$validator->add(array(
'title:Title' => 'required | maxlength(100)({label} must have less than {max} characters)',
'content:Content' => 'required',
'source:Source' => 'website'
));
// add nested rules
$validator->add('recipients[*]:Recipients', 'email'); //all recipients must be valid email addresses
$validator->add('shipping_address[city]:City', 'MyApp\Validator\City'); // uses a custom validator to validate the shipping city
```
##Links
- [documentation](http://sirius.ro/php/sirius/validation/)
- [changelog](CHANGELOG.md)
##Known issues
In PHP 5.3 there is some problem with the SplObject storage that prevents the library to remove validation rules.
This means that in PHP 5.3, you cannot remove a validation rule from a `Validator` or `ValueValidator` object
<?php
namespace Sirius\Validation\DataWrapper;
use Sirius\Validation\Util\Arr;
use Sirius\Validation\DataWrapper\WrapperInterface;
class ArrayWrapper implements WrapperInterface
{
/**
* @var array
*/
protected $data = array();
/**
* @param array|\ArrayObject|object $data
*
* @throws \InvalidArgumentException
*/
public function __construct($data = array())
{
if (is_object($data)) {
if ($data instanceof \ArrayObject) {
$data = $data->getArrayCopy();
} elseif (method_exists($data, 'toArray')) {
$data = $data->toArray();
}
}
if (! is_array($data)) {
throw new \InvalidArgumentException('Data passed to validator is not an array or an ArrayObject');
}
$this->data = $data;
}
public function getItemValue($item)
{
return Arr::getByPath($this->data, $item);
}
public function getItemsBySelector($selector)
{
return Arr::getBySelector($this->data, $selector);
}
}
<?php
namespace Sirius\Validation\DataWrapper;
interface WrapperInterface
{
/**
* Get value from the data container using the path
*
* @param $item
*
* @return mixed
*/
public function getItemValue($item);
/**
* Get items by selector
*
* @param $selector
*
* @return array
*/
public function getItemsBySelector($selector);
}
<?php
namespace Sirius\Validation;
class ErrorMessage
{
protected $template = 'Invalid';
protected $variables = array();
public function __construct($template = '', $variables = array())
{
$this->setTemplate($template)
->setVariables($variables);
}
public function setTemplate($template)
{
$template = trim((string) $template);
if ($template) {
$this->template = (string) $template;
}
return $this;
}
public function getTemplate()
{
return $this->template;
}
public function setVariables($variables = array())
{
foreach ($variables as $k => $v) {
$this->variables[$k] = $v;
}
return $this;
}
public function getVariables()
{
return $this->variables;
}
public function __toString()
{
$result = $this->template;
foreach ($this->variables as $k => $v) {
if (strpos($result, "{{$k}}") !== false) {
$result = str_replace("{{$k}}", $v, $result);
}
}
return $result;
}
}
<?php
namespace Sirius\Validation;
use Sirius\Validation\Util\Arr;
class Helper
{
protected static $methods = array();
public static function addMethod($ruleName, $callback)
{
if (is_callable($callback)) {
self::$methods[$ruleName] = $callback;
return true;
}
return false;
}
public static function methodExists($name)
{
return method_exists(__CLASS__, $name) || array_key_exists($name, self::$methods);
}
public static function __callStatic($name, $arguments)
{
if (array_key_exists($name, self::$methods)) {
return call_user_func_array(self::$methods[$name], $arguments);
}
throw new \InvalidArgumentException(sprintf('Validation method "%s" does not exist', $name));
}
public static function callback($value, $callback, $context = array())
{
$validator = new Rule\Callback();
$validator->setOption('callback', $callback);
$validator->setContext($context);
return $validator->validate($value);
}
public static function required($value)
{
return $value !== null && trim($value) !== '';
}
public static function truthy($value)
{
return (bool) $value;
}
public static function falsy($value)
{
return ! static::truthy($value);
}
public static function number($value)
{
return $value == '0' || is_numeric($value);
}
public static function integer($value)
{
return $value == '0' || (int) $value == $value;
}
public static function lessThan($value, $max)
{
$validator = new Rule\LessThan(
array(
'max' => $max
)
);
return $validator->validate($value);
}
public static function greaterThan($value, $min)
{
$validator = new Rule\GreaterThan(
array(
'min' => $min
)
);
return $validator->validate($value);
}
public static function between($value, $min, $max)
{
$validator = new Rule\Between(
array(
'min' => $min,
'max' => $max
)
);
return $validator->validate($value);
}
public static function exactly($value, $otherValue)
{
return $value == $otherValue;
}
public static function not($value, $otherValue)
{
return ! self::exactly($value, $otherValue);
}
public static function alpha($value)
{
$validator = new Rule\Alpha();
return $validator->validate($value);
}
public static function alphanumeric($value)
{
$validator = new Rule\AlphaNumeric();
return $validator->validate($value);
}
public static function alphanumhyphen($value)
{
$validator = new Rule\AlphaNumHyphen();
return $validator->validate($value);
}
public static function minLength($value, $min)
{
$validator = new Rule\MinLength(
array(
'min' => $min
)
);
return $validator->validate($value);
}
public static function maxLength($value, $max)
{
$validator = new Rule\MaxLength(
array(
'max' => $max
)
);
return $validator->validate($value);
}
public static function length($value, $min, $max)
{
$validator = new Rule\Length(
array(
'min' => $min,
'max' => $max
)
);
return $validator->validate($value);
}
public static function setMinSize($value, $min)
{
$validator = new Rule\ArrayMinLength(
array(
'min' => $min
)
);
return $validator->validate($value);
}
public static function setMaxSize($value, $max)
{
$validator = new Rule\ArrayMaxLength(
array(
'max' => $max
)
);
return $validator->validate($value);
}
public static function setSize($value, $min, $max)
{
$validator = new Rule\ArrayLength(
array(
'min' => $min,
'max' => $max
)
);
return $validator->validate($value);
}
public static function inList($value, $values)
{
$validator = new Rule\InList(
array(
'list' => $values
)
);
return $validator->validate($value);
}
public static function notInList($value, $values)
{
$validator = new Rule\NotInList(
array(
'list' => $values
)
);
return $validator->validate($value);
}
public static function regex($value, $pattern)
{
$validator = new Rule\Regex(
array(
'pattern' => $pattern
)
);
return $validator->validate($value);
}
public static function notRegex($value, $pattern)
{
$validator = new Rule\NotRegex(
array(
'pattern' => $pattern
)
);
return $validator->validate($value);
}
public static function equalTo($value, $otherElementOrValue, $context = null)
{
if (func_num_args() == 2) {
return $value == $otherElementOrValue;
}
return $value == Arr::getByPath($context, $otherElementOrValue);
}
public static function date($value, $format = 'Y-m-d')
{
$validator = new Rule\Date(
array(
'format' => $format
)
);
return $validator->validate($value);
}
public static function dateTime($value, $format = 'Y-m-d H:i:s')
{
$validator = new Rule\DateTime(
array(
'format' => $format
)
);
return $validator->validate($value);
}
public static function time($value, $format = 'H:i:s')
{
$validator = new Rule\Time(
array(
'format' => $format
)
);
return $validator->validate($value);
}
public static function website($value)
{
$validator = new Rule\Website();
return $validator->validate($value);
}
public static function url($value)
{
$validator = new Rule\Url();
return $validator->validate($value);
}
/**
* Test if a variable is a valid IP address
*
* @param string $value
*
* @return bool
*/
public static function ipAddress($value)
{
$validator = new Rule\IpAddress();
return $validator->validate($value);
}
public static function email($value)
{
$validator = new Rule\Email();
return $validator->validate($value);
}
/**
* Test if a variable is a full name
* Criterias: at least 6 characters, 2 words
*
* @param mixed $value
*
* @return bool
*/
public static function fullName($value)
{
$validator = new Rule\FullName();
return $validator->validate($value);
}
/**
* Test if the domain of an email address is available
*
* @param string $value
*
* @return bool
*/
public static function emailDomain($value)
{
$validator = new Rule\EmailDomain();
return $validator->validate($value);
}
}
<?php
namespace Sirius\Validation\Rule;
use Sirius\Validation\DataWrapper\ArrayWrapper;
use Sirius\Validation\DataWrapper\WrapperInterface;
use Sirius\Validation\ErrorMessage;
abstract class AbstractRule
{
// default error message when there is no LABEL attached
const MESSAGE = 'Value is not valid';
// default error message when there is a LABEL attached
const LABELED_MESSAGE = '{label} is not valid';
/**
* The validation context
* This is the data set that the data being validated belongs to
* @var \Sirius\Validation\DataWrapper\WrapperInterface
*/
protected $context;
/**
* Options for the validator.
* Also passed to the error message for customization.
*
* @var array
*/
protected $options = array();
/**
* Custom error message template for the validator instance
* If you don't agree with the default messages that were provided
*
* @var string
*/
protected $messageTemplate;
/**
* Result of the last validation
*
* @var boolean
*/
protected $success = false;
/**
* Last value validated with the validator.
* Stored in order to be passed to the errorMessage so that you get error
* messages like '"abc" is not a valid email'
*
* @var mixed
*/
protected $value;
/**
* The error message prototype that will be used to generate the error message
*
* @var ErrorMessage
*/
protected $errorMessagePrototype;
/**
* Options map in case the options are passed as list instead of associative array
*
* @var array
*/
protected $optionsIndexMap = array();
public function __construct($options = array())
{
$options = $this->normalizeOptions($options);
if (is_array($options) && ! empty($options)) {
foreach ($options as $k => $v) {
$this->setOption($k, $v);
}
}
}
/**
* Method that parses the option variable and converts it into an array
* You can pass anything to a validator like:
* - a query string: 'min=3&max=5'
* - a JSON string: '{"min":3,"max":5}'
* - a CSV string: '5,true' (for this scenario the 'optionsIndexMap' property is required)
*
* @param mixed $options
*
* @return array
* @throws \InvalidArgumentException
*/
protected function normalizeOptions($options)
{
if ('0' === $options && count($this->optionsIndexMap) > 0) {
$options = array($this->optionsIndexMap[0] => '0');
}
if (! $options) {
return array();
}
if (is_array($options) && $this->arrayIsAssoc($options)) {
return $options;
}
$result = $options;
if ($options && is_string($options)) {
$startChar = substr($options, 0, 1);
if ($startChar == '{') {
$result = json_decode($options, true);
} elseif (strpos($options, '=') !== false) {
$result = $this->parseHttpQueryString($options);
} else {
$result = $this->parseCsvString($options);
}
}
if (! is_array($result)) {
throw new \InvalidArgumentException('Validator options should be an array, JSON string or query string');
}
return $result;
}
/**
* Converts a HTTP query string to an array
*
* @param $str
*
* @return array
*/
protected function parseHttpQueryString($str)
{
parse_str($str, $arr);
return $this->convertBooleanStrings($arr);
}
/**
* Converts 'true' and 'false' strings to TRUE and FALSE
*
* @param $v
*
* @return bool|array
*/
protected function convertBooleanStrings($v)
{
if (is_array($v)) {
return array_map(array( $this, 'convertBooleanStrings' ), $v);
}
if ($v === 'true') {
return true;
}
if ($v === 'false') {
return false;
}
return $v;
}
/**
* Parses a CSV string and converts the result into an "options" array
* (an associative array that contains the options for the validation rule)
*
* @param $str
*
* @return array
*/
protected function parseCsvString($str)
{
if (! isset($this->optionsIndexMap) || ! is_array($this->optionsIndexMap) || empty($this->optionsIndexMap)) {
throw new \InvalidArgumentException(sprintf(
'Class %s is missing the `optionsIndexMap` property',
get_class($this)
));
}
$options = explode(',', $str);
$result = array();
foreach ($options as $k => $v) {
if (! isset($this->optionsIndexMap[$k])) {
throw new \InvalidArgumentException(sprintf(
'Class %s does not have the index %d configured in the `optionsIndexMap` property',
get_class($this),
$k
));
}
$result[$this->optionsIndexMap[$k]] = $v;
}
return $this->convertBooleanStrings($result);
}
/**
* Checks if an array is associative (ie: the keys are not numbers in sequence)
*
* @param array $arr
*
* @return bool
*/
protected function arrayIsAssoc($arr)
{
return array_keys($arr) !== range(0, count($arr));
}
/**
* Generates a unique string to identify the validator.
* It is used to compare 2 validators so you don't add the same rule twice in a validator object
*
* @return string
*/
public function getUniqueId()
{
return get_called_class() . '|' . json_encode(ksort($this->options));
}
/**
* Set an option for the validator.
*
* The options are also be passed to the error message.
*
* @param string $name
* @param mixed $value
*
* @return \Sirius\Validation\Rule\AbstractRule
*/
public function setOption($name, $value)
{
$this->options[$name] = $value;
return $this;
}
/**
* Get an option for the validator.
*
* @param string $name
*
* @return mixed
*/
public function getOption($name)
{
if (isset($this->options[$name])) {
return $this->options[$name];
} else {
return null;
}
}
/**
* The context of the validator can be used when the validator depends on other values
* that are not known at the moment the validator is constructed
* For example, when you need to validate an email field matches another email field,
* to confirm the email address
*
* @param array|object $context
*
* @throws \InvalidArgumentException
* @return \Sirius\Validation\Rule\AbstractRule
*/
public function setContext($context = null)
{
if ($context === null) {
return $this;
}
if (is_array($context)) {
$context = new ArrayWrapper($context);
}
if (! is_object($context) || ! $context instanceof WrapperInterface) {
throw new \InvalidArgumentException(
'Validator context must be either an array or an instance
of Sirius\Validator\DataWrapper\WrapperInterface'
);
}
$this->context = $context;
return $this;
}
/**
* Custom message for this validator to used instead of the the default one
*
* @param string $messageTemplate
*
* @return \Sirius\Validation\Rule\AbstractRule
*/
public function setMessageTemplate($messageTemplate)
{
$this->messageTemplate = $messageTemplate;
return $this;
}
/**
* Retrieves the error message template (either the global one or the custom message)
*
* @return string
*/
public function getMessageTemplate()
{
if ($this->messageTemplate) {
return $this->messageTemplate;
}
if (isset($this->options['label'])) {
return constant(get_class($this) . '::LABELED_MESSAGE');
}
return constant(get_class($this) . '::MESSAGE');
}
/**
* Validates a value
*
* @param mixed $value
* @param null|mixed $valueIdentifier
*
* @return mixed
*/
abstract public function validate($value, $valueIdentifier = null);
/**
* Sets the error message prototype that will be used when returning the error message
* when validation fails.
* This option can be used when you need translation
*
* @param ErrorMessage $errorMessagePrototype
*
* @throws \InvalidArgumentException
* @return \Sirius\Validation\Rule\AbstractRule
*/
public function setErrorMessagePrototype(ErrorMessage $errorMessagePrototype)
{
$this->errorMessagePrototype = $errorMessagePrototype;
return $this;
}
/**
* Returns the error message prototype.
* It constructs one if there isn't one.
*
* @return ErrorMessage
*/
public function getErrorMessagePrototype()
{
if (! $this->errorMessagePrototype) {
$this->errorMessagePrototype = new ErrorMessage();
}
return $this->errorMessagePrototype;
}
/**
* Retrieve the error message if validation failed
*
* @return NULL|\Sirius\Validation\ErrorMessage
*/
public function getMessage()
{
if ($this->success) {
return null;
}
$message = $this->getPotentialMessage();
$message->setVariables(
array(
'value' => $this->value
)
);
return $message;
}
/**
* Retrieve the potential error message.
* Example: when you do client-side validation you need to access the "potential error message" to be displayed
*
* @return ErrorMessage
*/
public function getPotentialMessage()
{
$message = clone ($this->getErrorMessagePrototype());
$message->setTemplate($this->getMessageTemplate());
$message->setVariables($this->options);
return $message;
}
/**
* Method for determining the path to a related item.
* Eg: for `lines[5][price]` the related item `lines[*][quantity]`
* has the value identifier as `lines[5][quantity]`
*
* @param $valueIdentifier
* @param $relatedItem
*
* @return string|null
*/
protected function getRelatedValueIdentifier($valueIdentifier, $relatedItem)
{
// in case we don't have a related path
if (strpos($relatedItem, '*') === false) {
return $relatedItem;
}
// lines[*][quantity] is converted to ['lines', '*', 'quantity']
$relatedItemParts = explode('[', str_replace(']', '', $relatedItem));
// lines[5][price] is ['lines', '5', 'price']
$valueIdentifierParts = explode('[', str_replace(']', '', $valueIdentifier));
if (count($relatedItemParts) !== count($valueIdentifierParts)) {
return $relatedItem;
}
// the result should be ['lines', '5', 'quantity']
$relatedValueIdentifierParts = array();
foreach ($relatedItemParts as $index => $part) {
if ($part === '*' && isset($valueIdentifierParts[$index])) {
$relatedValueIdentifierParts[] = $valueIdentifierParts[$index];
} else {
$relatedValueIdentifierParts[] = $part;
}
}
$relatedValueIdentifier = implode('][', $relatedValueIdentifierParts) . ']';
$relatedValueIdentifier = str_replace(
$relatedValueIdentifierParts[0] . ']',
$relatedValueIdentifierParts[0],
$relatedValueIdentifier
);
return $relatedValueIdentifier;
}
}
<?php
namespace Sirius\Validation\Rule;
abstract class AbstractStringRule extends AbstractRule
{
protected function getStringLength($str)
{
if (function_exists('mb_strlen')) {
return mb_strlen(
$str,
(isset($this->options['encoding']) && $this->options['encoding']) ?
$this->options['encoding'] : mb_internal_encoding()
);
}
return strlen($str);
}
}
<?php
namespace Sirius\Validation\Rule;
class Alpha extends AbstractRule
{
const MESSAGE = 'This input can contain only letters';
const LABELED_MESSAGE = '{label} can contain only letters';
public function validate($value, $valueIdentifier = null)
{
$this->value = $value;
$this->success = (bool) ctype_alpha((string) str_replace(' ', '', $value));
return $this->success;
}
}
<?php
namespace Sirius\Validation\Rule;
class AlphaNumHyphen extends AbstractRule
{
const MESSAGE = 'This input must contain only letters, digits, spaces, hyphens and underscores';
const LABELED_MESSAGE = '{label} must contain only letters, digits, spaces, hyphens and underscores';
public function validate($value, $valueIdentifier = null)
{
$this->value = $value;
$this->success = (bool) ctype_alnum(
(string) str_replace(
array(
' ',
'_',
'-'
),
'',
$value
)
);
return $this->success;
}
}
<?php
namespace Sirius\Validation\Rule;
class AlphaNumeric extends AbstractRule
{
const MESSAGE = 'This input must contain only letters and digits';
const LABELED_MESSAGE = '{label} must contain only letters and digits';
public function validate($value, $valueIdentifier = null)
{
$this->value = $value;
$this->success = (bool) ctype_alnum((string) str_replace(' ', '', $value));
return $this->success;
}
}
<?php
namespace Sirius\Validation\Rule;
class ArrayLength extends AbstractRule
{
const OPTION_MIN = 'min';
const OPTION_MAX = 'max';
const MESSAGE = 'This input should contain between {min} and {max} items';
const LABELED_MESSAGE = '{label} should contain between {min} and {max} items';
protected $options = array();
protected $optionsIndexMap = array(
0 => self::OPTION_MIN,
1 => self::OPTION_MAX
);
public function validate($value, $valueIdentifier = null)
{
$this->value = $value;
$maxValidator = new ArrayMaxLength();
if (isset($this->options['max'])) {
$maxValidator->setOption('max', $this->options['max']);
}
$minValidator = new ArrayMinLength();
if (isset($this->options['min'])) {
$minValidator->setOption('min', $this->options['min']);
}
$this->success = $minValidator->validate($value, $valueIdentifier) && $maxValidator->validate(
$value,
$valueIdentifier
);
return $this->success;
}
}
<?php
namespace Sirius\Validation\Rule;
class ArrayMaxLength extends AbstractRule
{
const OPTION_MAX = 'max';
const MESSAGE = 'This input should contain less than {min} items';
const LABELED_MESSAGE = '{label} should contain less than {min} items';
protected $options = array();
protected $optionsIndexMap = array(
self::OPTION_MAX
);
public function validate($value, $valueIdentifier = null)
{
$this->value = $value;
if (! isset($this->options['max'])) {
$this->success = true;
} else {
$this->success = is_array($value) && count($value) <= $this->options['max'];
}
return $this->success;
}
}
<?php
namespace Sirius\Validation\Rule;
class ArrayMinLength extends AbstractRule
{
const OPTION_MIN = 'min';
const MESSAGE = 'This input should contain at least {min} items';
const LABELED_MESSAGE = '{label} should contain at least {min} items';
protected $options = array();
protected $optionsIndexMap = array(
0 => self::OPTION_MIN
);
public function validate($value, $valueIdentifier = null)
{
$this->value = $value;
if (! isset($this->options['min'])) {
$this->success = true;
} else {
$this->success = is_array($value) && count($value) >= $this->options['min'];
}
return $this->success;
}
}
<?php
namespace Sirius\Validation\Rule;
class Between extends AbstractRule
{
const OPTION_MIN = 'min';
const OPTION_MAX = 'max';
const MESSAGE = 'This input must be between {min} and {max}';
const LABELED_MESSAGE = '{label} must be between {min} and {max}';
protected $options = array();
protected $optionsIndexMap = array(
0 => self::OPTION_MIN,
1 => self::OPTION_MAX
);
public function validate($value, $valueIdentifier = null)
{
$this->value = $value;
$minValidator = new LessThan();
if (isset($this->options['max'])) {
$minValidator->setOption('max', $this->options['max']);
}
$maxValidator = new GreaterThan();
if (isset($this->options['min'])) {
$maxValidator->setOption('min', $this->options['min']);
}
$this->success = $minValidator->validate($value, $valueIdentifier) && $maxValidator->validate(
$value,
$valueIdentifier
);
return $this->success;
}
}
<?php
namespace Sirius\Validation\Rule;
class Callback extends AbstractRule
{
const OPTION_CALLBACK = 'callback';
const OPTION_ARGUMENTS = 'arguments';
const MESSAGE = 'This input does not meet the validation criteria';
const LABELED_MESSAGE = '{label} does not meet the validation criteria';
public function getUniqueId()
{
$uniqueId = get_called_class();
// the callback is a function name (eg: is_int) or a static class method (eg: MyClass::method)
if (is_string($this->options['callback'])) {
$uniqueId .= '|' . $this->options['callback'];
} elseif (is_array($this->options['callback'])) {
// the callback is an array that points to a static class method (eg: array('MyClass', 'method'))
if (is_string($this->options['callback'][0])) {
$uniqueId .= '|' . implode('::', $this->options['callback']);
} elseif (is_object($this->options['callback'][0])) {
$uniqueId .= '|' . spl_object_hash(
$this->options['callback'][0]
) . '->' . $this->options['callback'][1];
}
} elseif (is_object($this->options['callback']) && $this->options['callback'] instanceof \Closure) {
$uniqueId .= '|' . spl_object_hash($this->options['callback']);
}
if (isset($this->options['arguments'])) {
$args = (array) $this->options['arguments'];
ksort($args);
$uniqueId .= '|' . json_encode($args);
}
return $uniqueId;
}
public function validate($value, $valueIdentifier = null)
{
$this->value = $value;
if (! isset($this->options['callback']) || ! is_callable($this->options['callback'])) {
$this->success = true;
} else {
$args = (isset($this->options['arguments'])) ? (array) $this->options['arguments'] : array();
array_unshift($args, $value);
array_push($args, $valueIdentifier, $this->context);
$this->success = (bool) call_user_func_array($this->options['callback'], $args);
}
return $this->success;
}
}
<?php
namespace Sirius\Validation\Rule;
class Date extends AbstractRule
{
const OPTION_FORMAT = 'format';
const MESSAGE = 'This input must be a date having the format {format}';
const LABELED_MESSAGE = '{label} must be a date having the format {format}';
protected $options = array(
'format' => 'Y-m-d'
);
protected $optionsIndexMap = array(
0 => self::OPTION_FORMAT
);
public function validate($value, $valueIdentifier = null)
{
$this->value = $value;
$this->success = $value == date(
$this->options['format'],
$this->getTimestampFromFormatedString($value, $this->options['format'])
);
return $this->success;
}
protected function getTimestampFromFormatedString($string, $format)
{
$result = date_parse_from_format($format, $string);
return mktime(
(int) $result['hour'],
(int) $result['minute'],
(int) $result['second'],
(int) $result['month'],
(int) $result['day'],
(int) $result['year']
);
}
}
<?php
namespace Sirius\Validation\Rule;
class DateTime extends Date
{
const MESSAGE = 'This input must be a date having the format {format}';
const LABELED_MESSAGE = '{label} must be a date having the format {format}';
protected $options = array(
'format' => 'Y-m-d H:i:s'
);
}
<?php
namespace Sirius\Validation\Rule;
class Email extends AbstractRule
{
const MESSAGE = 'This input must be a valid email address';
const LABELED_MESSAGE = '{label} must be a valid email address';
public function validate($value, $valueIdentifier = null)
{
$this->value = $value;
$this->success = (filter_var((string) $value, FILTER_VALIDATE_EMAIL) !== false);
return $this->success;
}
}
<?php
namespace Sirius\Validation\Rule;
class EmailDomain extends AbstractRule
{
const MESSAGE = 'This the email address does not belong to a valid domain';
const LABELED_MESSAGE = '{label} does not belong to a valid domain';
public function validate($value, $valueIdentifier = null)
{
$value = (string) $value;
$this->value = $value;
// Check if the email domain has a valid MX record
$this->success = (bool) checkdnsrr(preg_replace('/^[^@]+@/', '', $value), 'MX');
return $this->success;
}
}
<?php
namespace Sirius\Validation\Rule;
class Equal extends AbstractRule
{
const OPTION_VALUE = 'value';
const MESSAGE = 'This input is not equal to {value}';
const LABELED_MESSAGE = '{label} is not equal to {value}';
protected $optionsIndexMap = array(
0 => self::OPTION_VALUE
);
public function validate($value, $valueIdentifier = null)
{
$this->value = $value;
if (isset($this->options[self::OPTION_VALUE])) {
$this->success = ($value == $this->options[self::OPTION_VALUE]);
} else {
$this->success = true;
}
return $this->success;
}
}
<?php
namespace Sirius\Validation\Rule\File;
use Sirius\Validation\Rule\AbstractRule;
class Extension extends AbstractRule
{
const OPTION_ALLOWED_EXTENSIONS = 'allowed';
const MESSAGE = 'The file does not have an acceptable extension ({file_extensions})';
const LABELED_MESSAGE = '{label} does not have an acceptable extension ({file_extensions})';
protected $options = array(
self::OPTION_ALLOWED_EXTENSIONS => array()
);
public function setOption($name, $value)
{
if ($name == self::OPTION_ALLOWED_EXTENSIONS) {
if (is_string($value)) {
$value = explode(',', $value);
}
$value = array_map('trim', $value);
$value = array_map('strtolower', $value);
}
return parent::setOption($name, $value);
}
public function validate($value, $valueIdentifier = null)
{
$this->value = $value;
if (! file_exists($value)) {
$this->success = false;
} else {
$extension = strtolower(substr($value, strrpos($value, '.') + 1, 10));
$this->success = is_array($this->options[self::OPTION_ALLOWED_EXTENSIONS]) && in_array(
$extension,
$this->options[self::OPTION_ALLOWED_EXTENSIONS]
);
}
return $this->success;
}
public function getPotentialMessage()
{
$message = parent::getPotentialMessage();
$fileExtensions = array_map('strtoupper', $this->options[self::OPTION_ALLOWED_EXTENSIONS]);
$message->setVariables(
array(
'file_extensions' => implode(', ', $fileExtensions)
)
);
return $message;
}
}
<?php
namespace Sirius\Validation\Rule\File;
use Sirius\Validation\Rule\AbstractRule;
class Image extends AbstractRule
{
const OPTION_ALLOWED_IMAGES = 'allowed';
const MESSAGE = 'The file is not a valid image (only {image_types} are allowed)';
const LABELED_MESSAGE = '{label} is not a valid image (only {image_types} are allowed)';
protected $options = array(
self::OPTION_ALLOWED_IMAGES => array( 'jpg', 'png', 'gif' )
);
protected $imageTypesMap = array(
IMAGETYPE_GIF => 'gif',
IMAGETYPE_JPEG => 'jpg',
IMAGETYPE_JPEG2000 => 'jpg',
IMAGETYPE_PNG => 'png',
IMAGETYPE_PSD => 'psd',
IMAGETYPE_BMP => 'bmp',
IMAGETYPE_ICO => 'ico',
);
public function setOption($name, $value)
{
if ($name == self::OPTION_ALLOWED_IMAGES) {
if (is_string($value)) {
$value = explode(',', $value);
}
$value = array_map('trim', $value);
$value = array_map('strtolower', $value);
}
return parent::setOption($name, $value);
}
public function validate($value, $valueIdentifier = null)
{
$this->value = $value;
if (! file_exists($value)) {
$this->success = false;
} else {
$imageInfo = getimagesize($value);
$extension = isset($this->imageTypesMap[$imageInfo[2]]) ? $this->imageTypesMap[$imageInfo[2]] : false;
$this->success = ($extension && in_array($extension, $this->options[self::OPTION_ALLOWED_IMAGES]));
}
return $this->success;
}
public function getPotentialMessage()
{
$message = parent::getPotentialMessage();
$imageTypes = array_map('strtoupper', $this->options[self::OPTION_ALLOWED_IMAGES]);
$message->setVariables(
array(
'image_types' => implode(', ', $imageTypes)
)
);
return $message;
}
}
<?php
namespace Sirius\Validation\Rule\File;
use Sirius\Validation\Rule\AbstractRule;
class ImageHeight extends AbstractRule
{
const OPTION_MAX = 'max';
const OPTION_MIN = 'min';
const MESSAGE = 'The file should be at least {min} pixels tall';
const LABELED_MESSAGE = '{label} should be at least {min} pixels tall';
protected $options = array(
self::OPTION_MAX => 1000000,
self::OPTION_MIN => 0,
);
public function validate($value, $valueIdentifier = null)
{
$this->value = $value;
if (!file_exists($value)) {
$this->success = false;
} else {
$imageInfo = getimagesize($value);
$height = isset($imageInfo[1]) ? $imageInfo[1] : 0;
$this->success = $height &&
$height <= $this->options[self::OPTION_MAX] &&
$height >= $this->options[self::OPTION_MIN];
}
return $this->success;
}
}
<?php
namespace Sirius\Validation\Rule\File;
use Sirius\Validation\Rule\AbstractRule;
class ImageRatio extends AbstractRule
{
// the image width/height ration;
// can be a number or a string like 4:3, 16:9
const OPTION_RATIO = 'ratio';
// how much can the image ratio diverge from the allowed ratio
const OPTION_ERROR_MARGIN = 'error_margin';
const MESSAGE = 'The image does must have a ratio (width/height) of {ratio})';
const LABELED_MESSAGE = '{label} does must have a ratio (width/height) of {ratio})';
protected $options = array(
self::OPTION_RATIO => 0,
self::OPTION_ERROR_MARGIN => 0,
);
protected function normalizeRatio($ratio)
{
if (is_numeric($ratio) || $ratio == filter_var($ratio, FILTER_SANITIZE_NUMBER_FLOAT)) {
return floatval($ratio);
}
if (strpos($ratio, ':') !== false) {
list($width, $height) = explode(':', $ratio);
return $width / $height;
}
return 0;
}
public function validate($value, $valueIdentifier = null)
{
$this->value = $value;
$ratio = $this->normalizeRatio($this->options[self::OPTION_RATIO]);
if (! file_exists($value)) {
$this->success = false;
} elseif ($ratio == 0) {
$this->success = true;
} else {
$imageInfo = getimagesize($value);
if (is_array($imageInfo)) {
$actualRatio = $imageInfo[0] / $imageInfo[1];
$this->success = abs($actualRatio - $ratio) <= $this->options[self::OPTION_ERROR_MARGIN];
} else {
// no image size computed => no valid image
return $this->success = false;
}
}
return $this->success;
}
}
<?php
namespace Sirius\Validation\Rule\File;
use Sirius\Validation\Rule\AbstractRule;
class ImageWidth extends AbstractRule
{
const OPTION_MAX = 'max';
const OPTION_MIN = 'min';
const MESSAGE = 'The image should be at least {min} pixels wide';
const LABELED_MESSAGE = '{label} should be at least {min} pixels wide';
protected $options = array(
self::OPTION_MAX => 1000000,
self::OPTION_MIN => 0,
);
public function validate($value, $valueIdentifier = null)
{
$this->value = $value;
if (! file_exists($value)) {
$this->success = false;
} else {
$imageInfo = getimagesize($value);
$width = isset($imageInfo[0]) ? $imageInfo[0] : 0;
$this->success = $width &&
$width <= $this->options[self::OPTION_MAX] &&
$width >= $this->options[self::OPTION_MIN];
}
return $this->success;
}
}
<?php
namespace Sirius\Validation\Rule\File;
use Sirius\Validation\Rule\AbstractRule;
class Size extends AbstractRule
{
const OPTION_SIZE = 'size';
const MESSAGE = 'The file should not exceed {size}';
const LABELED_MESSAGE = '{label} should not exceed {size}';
protected $options = array(
self::OPTION_SIZE => '2M'
);
protected function normalizeSize($size)
{
$units = array( 'B' => 0, 'K' => 1, 'M' => 2, 'G' => 3 );
$unit = strtoupper(substr($size, strlen($size) - 1, 1));
if (! isset($units[$unit])) {
$normalizedSize = filter_var($size, FILTER_SANITIZE_NUMBER_INT);
} else {
$size = filter_var(substr($size, 0, strlen($size) - 1), FILTER_SANITIZE_NUMBER_FLOAT);
$normalizedSize = $size * pow(1024, $units[$unit]);
}
return $normalizedSize;
}
public function validate($value, $valueIdentifier = null)
{
$this->value = $value;
if (! file_exists($value)) {
$this->success = false;
} else {
$fileSize = @filesize($value);
$limit = $this->normalizeSize($this->options[self::OPTION_SIZE]);
$this->success = $fileSize && $fileSize <= $limit;
}
return $this->success;
}
}
<?php
namespace Sirius\Validation\Rule;
class FullName extends AbstractRule
{
const MESSAGE = 'This input is not a valid full name (first name and last name)';
const LABELED_MESSAGE = '{label} is not a valid full name (first name and last name)';
/**
* This is not going to work with Asian names, http://en.wikipedia.org/wiki/Chinese_name.
*/
public function validate($value, $valueIdentifier = null)
{
$this->value = $value;
$names = explode(' ', $value);
// Each name must be at least 2 characters long.
foreach ($names as $name) {
if (mb_strlen($name) < 2) {
return $this->success = false;
}
}
// Name cannot be longer shorter than 6 characters.
return $this->success = mb_strlen($value) >= 6;
}
}
<?php
namespace Sirius\Validation\Rule;
class GreaterThan extends AbstractRule
{
const OPTION_MIN = 'min';
const OPTION_INCLUSIVE = 'inclusive';
const MESSAGE = 'This input should be greater than {min}';
const LABELED_MESSAGE = '{label} should be greater than {min}';
protected $options = array(
'inclusive' => true
);
protected $optionsIndexMap = array(
0 => self::OPTION_MIN,
1 => self::OPTION_INCLUSIVE
);
public function validate($value, $valueIdentifier = null)
{
$this->value = $value;
if (! isset($this->options['min'])) {
$this->success = true;
} else {
if ($this->options['inclusive']) {
$this->success = $value >= $this->options['min'];
} else {
$this->success = $value > $this->options['min'];
}
}
return $this->success;
}
}
<?php
namespace Sirius\Validation\Rule;
class InList extends AbstractRule
{
const OPTION_LIST = 'list';
const MESSAGE = 'This input is not one of the accepted values';
const LABELED_MESSAGE = '{label} is not one of the accepted values';
protected $optionsIndexMap = array(
0 => self::OPTION_LIST
);
public function validate($value, $valueIdentifier = null)
{
$this->value = $value;
if (! isset($this->options['list'])) {
$this->success = true;
} else {
if (is_array($this->options['list'])) {
$this->success = in_array($value, $this->options['list']);
}
}
return $this->success;
}
}
<?php
namespace Sirius\Validation\Rule;
class Integer extends AbstractRule
{
const MESSAGE = 'This input must be an integer number';
const LABELED_MESSAGE = '{label} must be an integer number';
public function validate($value, $valueIdentifier = null)
{
$this->value = $value;
$this->success = (bool) filter_var($value, FILTER_VALIDATE_INT) || (string) $value === '0';
return $this->success;
}
}
<?php
namespace Sirius\Validation\Rule;
class IpAddress extends AbstractRule
{
const MESSAGE = 'This input is not a valid IP address';
const LABELED_MESSAGE = '{label} is not a valid IP address';
public function validate($value, $valueIdentifier = null)
{
$this->value = $value;
// Do not allow private and reserved range IPs
$flags = FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE;
if (strpos($value, ':') !== false) {
$this->success = (bool) filter_var($value, FILTER_VALIDATE_IP, $flags | FILTER_FLAG_IPV6);
} else {
$this->success = (bool) filter_var($value, FILTER_VALIDATE_IP, $flags | FILTER_FLAG_IPV4);
}
return $this->success;
}
}
<?php
namespace Sirius\Validation\Rule;
class Length extends AbstractRule
{
const OPTION_MIN = 'min';
const OPTION_MAX = 'max';
const OPTION_ENCODING = 'encoding';
const MESSAGE = 'This input must be between {min} and {max} characters long';
const LABELED_MESSAGE = '{label} must be between {min} and {max} characters long';
protected $options = array();
protected $optionsIndexMap = array(
0 => self::OPTION_MIN,
1 => self::OPTION_MAX,
2 => self::OPTION_ENCODING
);
public function validate($value, $valueIdentifier = null)
{
$this->value = $value;
$maxValidator = new MinLength();
if (isset($this->options['max'])) {
$maxValidator->setOption('max', $this->options['max']);
}
$minValidator = new MaxLength();
if (isset($this->options['min'])) {
$minValidator->setOption('min', $this->options['min']);
}
$this->success = $minValidator->validate($value, $valueIdentifier) && $maxValidator->validate(
$value,
$valueIdentifier
);
return $this->success;
}
}
<?php
namespace Sirius\Validation\Rule;
class LessThan extends AbstractRule
{
const OPTION_MAX = 'max';
const OPTION_INCLUSIVE = 'inclusive';
const MESSAGE = 'This input should be less than {max}';
const LABELED_MESSAGE = '{label} should be less than {max}';
protected $options = array(
'inclusive' => true
);
protected $optionsIndexMap = array(
0 => self::OPTION_MAX,
1 => self::OPTION_INCLUSIVE
);
public function validate($value, $valueIdentifier = null)
{
$this->value = $value;
if (! isset($this->options['max'])) {
$this->success = true;
} else {
if ($this->options['inclusive']) {
$this->success = $value <= $this->options['max'];
} else {
$this->success = $value < $this->options['max'];
}
}
return $this->success;
}
}
<?php
namespace Sirius\Validation\Rule;
class Match extends AbstractRule
{
const OPTION_ITEM = 'item';
const MESSAGE = 'This input does not match {item}';
const LABELED_MESSAGE = '{label} does not match {item}';
protected $optionsIndexMap = array(
0 => self::OPTION_ITEM
);
public function validate($value, $valueIdentifier = null)
{
$this->value = $value;
if (isset($this->options[self::OPTION_ITEM])) {
$this->success = ($value == $this->context->getItemValue($this->options[self::OPTION_ITEM]));
} else {
$this->success = true;
}
return $this->success;
}
}
<?php
namespace Sirius\Validation\Rule;
class MaxLength extends AbstractStringRule
{
const OPTION_MAX = 'max';
const OPTION_ENCODING = 'encoding';
const MESSAGE = 'This input should have less than {max} characters';
const LABELED_MESSAGE = '{label} should have less than {max} characters';
protected $options = array();
protected $optionsIndexMap = array(
0 => self::OPTION_MAX,
1 => self::OPTION_ENCODING
);
public function validate($value, $valueIdentifier = null)
{
$this->value = $value;
if (! isset($this->options['max'])) {
$this->success = true;
} else {
$this->success = $this->getStringLength($value) <= $this->options['max'];
}
return $this->success;
}
}
<?php
namespace Sirius\Validation\Rule;
class MinLength extends AbstractStringRule
{
const OPTION_MIN = 'min';
const OPTION_ENCODING = 'encoding';
const MESSAGE = 'This input should have at least {min} characters';
const LABELED_MESSAGE = '{label} should have at least {min} characters';
protected $options = array();
protected $optionsIndexMap = array(
0 => self::OPTION_MIN,
1 => self::OPTION_ENCODING
);
public function validate($value, $valueIdentifier = null)
{
$this->value = $value;
if (! isset($this->options['min'])) {
$this->success = true;
} else {
$this->success = $this->getStringLength($value) >= $this->options['min'];
}
return $this->success;
}
}
<?php
namespace Sirius\Validation\Rule;
class NotInList extends InList
{
const OPTION_LIST = 'list';
const MESSAGE = 'This input is one of the forbidden values';
const LABELED_MESSAGE = '{label} is one of the forbidden values';
protected $optionsIndexMap = array(
0 => self::OPTION_LIST
);
public function validate($value, $valueIdentifier = null)
{
$this->value = $value;
if (! isset($this->options['list'])) {
$this->success = true;
} else {
if (is_array($this->options['list'])) {
$this->success = ! in_array($value, $this->options['list']);
}
}
return $this->success;
}
}
<?php
namespace Sirius\Validation\Rule;
class NotRegex extends Regex
{
const MESSAGE = 'This input should not match the regular expression {pattern}';
const LABELED_MESSAGE = '{label} Tshould not match the regular expression {pattern}';
public function validate($value, $valueIdentifier = null)
{
parent::validate($value, $valueIdentifier);
$this->success = ! $this->success;
return $this->success;
}
}
<?php
namespace Sirius\Validation\Rule;
class Number extends AbstractRule
{
const MESSAGE = 'This input must be a number';
const LABELED_MESSAGE = '{label} must be a number';
public function validate($value, $valueIdentifier = null)
{
$this->value = $value;
$this->success = (bool) filter_var($value, FILTER_VALIDATE_FLOAT) || (string) $value === '0';
return $this->success;
}
}
<?php
namespace Sirius\Validation\Rule;
class Regex extends AbstractRule
{
const OPTION_PATTERN = 'pattern';
const MESSAGE = 'This input does not match the regular expression {pattern}';
const LABELED_MESSAGE = '{label} does not match the regular expression {pattern}';
protected $optionsIndexMap = array(
0 => self::OPTION_PATTERN
);
public function validate($value, $valueIdentifier = null)
{
$this->value = $value;
if (isset($this->options['pattern'])) {
$this->success = (bool) preg_match($this->options['pattern'], $value);
} else {
$this->success = true;
}
return $this->success;
}
}
<?php
namespace Sirius\Validation\Rule;
class Required extends AbstractRule
{
const MESSAGE = 'This field is required';
const LABELED_MESSAGE = '{label} is required';
public function validate($value, $valueIdentifier = null)
{
$this->value = $value;
$this->success = ($value !== null && $value !== '');
return $this->success;
}
}
<?php
namespace Sirius\Validation\Rule;
class RequiredWhen extends Required
{
const OPTION_ITEM = 'item';
const OPTION_RULE = 'rule';
const OPTION_RULE_OPTIONS = 'rule_options';
const MESSAGE = 'This field is required';
const LABELED_MESSAGE = '{label} is required';
public function getItemRule()
{
/* @var $rule AbstractValidator */
$rule = false;
$ruleOptions = (isset($this->options[self::OPTION_RULE_OPTIONS])) ?
(array) $this->options[self::OPTION_RULE_OPTIONS] :
array();
if (is_string($this->options[self::OPTION_RULE])) {
$ruleClass = $this->options[self::OPTION_RULE];
if (class_exists($ruleClass)) {
$rule = new $ruleClass($ruleOptions);
} elseif (class_exists('Sirius\\Validation\\Rule\\' . $ruleClass)) {
$ruleClass = 'Sirius\\Validation\\Rule\\' . $ruleClass;
$rule = new $ruleClass($ruleOptions);
}
} elseif (is_object($this->options[self::OPTION_RULE])
&& $this->options[self::OPTION_RULE] instanceof AbstractRule
) {
$rule = $this->options[self::OPTION_RULE];
}
if (! $rule) {
throw new \InvalidArgumentException(
'Validator for the other item is not valid or cannot be constructed based on the data provided'
);
}
$context = $this->context ? $this->context : array();
$rule->setContext($context);
return $rule;
}
public function validate($value, $valueIdentifier = null)
{
$this->value = $value;
if (! isset($this->options[self::OPTION_ITEM])) {
$this->success = true;
} else {
$relatedItemPath = $this->getRelatedValueIdentifier($valueIdentifier, $this->options[self::OPTION_ITEM]);
$relatedItemValue = $relatedItemPath !== null ? $this->context->getItemValue($relatedItemPath) : null;
$itemRule = $this->getItemRule();
if ($itemRule->validate($relatedItemValue, $relatedItemPath)) {
$this->success = ($value !== null && trim($value) !== '');
} else {
$this->success = true;
}
}
return $this->success;
}
}
<?php
namespace Sirius\Validation\Rule;
class RequiredWith extends Required
{
const OPTION_ITEM = 'item';
const MESSAGE = 'This field is required';
const LABELED_MESSAGE = '{label} is required';
protected $optionsIndexMap = array(
0 => self::OPTION_ITEM
);
public function validate($value, $valueIdentifier = null)
{
$this->value = $value;
$relatedItemPath = $this->getRelatedValueIdentifier($valueIdentifier, $this->options[self::OPTION_ITEM]);
$relatedItemValue = $relatedItemPath !== null ? $this->context->getItemValue($relatedItemPath) : null;
if (isset($this->options[self::OPTION_ITEM]) && $relatedItemValue !== null) {
$this->success = ($value !== null && trim($value) !== '');
} else {
$this->success = true;
}
return $this->success;
}
}
<?php
namespace Sirius\Validation\Rule;
class RequiredWithout extends Required
{
const OPTION_ITEM = 'item';
const MESSAGE = 'This field is required';
const LABELED_MESSAGE = '{label} is required';
protected $optionsIndexMap = array(
0 => self::OPTION_ITEM
);
public function validate($value, $valueIdentifier = null)
{
$this->value = $value;
$relatedItemPath = $this->getRelatedValueIdentifier($valueIdentifier, $this->options[self::OPTION_ITEM]);
$relatedItemValue = $relatedItemPath !== null ? $this->context->getItemValue($relatedItemPath) : null;
if (isset($this->options[self::OPTION_ITEM]) && $relatedItemValue === null) {
$this->success = ($value !== null && trim($value) !== '');
} else {
$this->success = true;
}
return $this->success;
}
}
<?php
namespace Sirius\Validation\Rule;
class Time extends Date
{
const MESSAGE = 'This input must be a time having the format {format}';
const LABELED_MESSAGE = '{label} must be a time having the format {format}';
protected $options = array(
'format' => 'H:i:s'
);
}
<?php
namespace Sirius\Validation\Rule\Upload;
use Sirius\Validation\Rule\AbstractRule;
class Extension extends AbstractRule
{
const OPTION_ALLOWED_EXTENSIONS = 'allowed';
const MESSAGE = 'The file does not have an acceptable extension ({file_extensions})';
const LABELED_MESSAGE = '{label} does not have an acceptable extension ({file_extensions})';
protected $options = array(
self::OPTION_ALLOWED_EXTENSIONS => array()
);
public function setOption($name, $value)
{
if ($name == self::OPTION_ALLOWED_EXTENSIONS) {
if (is_string($value)) {
$value = explode(',', $value);
}
$value = array_map('trim', $value);
$value = array_map('strtolower', $value);
}
return parent::setOption($name, $value);
}
public function validate($value, $valueIdentifier = null)
{
$this->value = $value;
if (! is_array($value) || ! isset($value['tmp_name'])) {
$this->success = false;
} elseif (! file_exists($value['tmp_name'])) {
$this->success = $value['error'] === UPLOAD_ERR_NO_FILE;
} else {
$extension = strtolower(substr($value['name'], strrpos($value['name'], '.') + 1, 10));
$this->success = is_array($this->options[self::OPTION_ALLOWED_EXTENSIONS]) && in_array(
$extension,
$this->options[self::OPTION_ALLOWED_EXTENSIONS]
);
}
return $this->success;
}
public function getPotentialMessage()
{
$message = parent::getPotentialMessage();
$fileExtensions = array_map('strtoupper', $this->options[self::OPTION_ALLOWED_EXTENSIONS]);
$message->setVariables(
array(
'file_extensions' => implode(', ', $fileExtensions)
)
);
return $message;
}
}
<?php
namespace Sirius\Validation\Rule\Upload;
use Sirius\Validation\Rule\AbstractRule;
class Image extends AbstractRule
{
const OPTION_ALLOWED_IMAGES = 'allowed';
const MESSAGE = 'The file is not a valid image (only {image_types} are allowed)';
const LABELED_MESSAGE = '{label} is not a valid image (only {image_types} are allowed)';
protected $options = array(
self::OPTION_ALLOWED_IMAGES => array( 'jpg', 'png', 'gif' )
);
protected $imageTypesMap = array(
IMAGETYPE_GIF => 'gif',
IMAGETYPE_JPEG => 'jpg',
IMAGETYPE_JPEG2000 => 'jpg',
IMAGETYPE_PNG => 'png',
IMAGETYPE_PSD => 'psd',
IMAGETYPE_BMP => 'bmp',
IMAGETYPE_ICO => 'ico',
);
public function setOption($name, $value)
{
if ($name == self::OPTION_ALLOWED_IMAGES) {
if (is_string($value)) {
$value = explode(',', $value);
}
$value = array_map('trim', $value);
$value = array_map('strtolower', $value);
}
return parent::setOption($name, $value);
}
public function validate($value, $valueIdentifier = null)
{
$this->value = $value;
if (! is_array($value) || ! isset($value['tmp_name'])) {
$this->success = false;
} elseif (! file_exists($value['tmp_name'])) {
$this->success = $value['error'] === UPLOAD_ERR_NO_FILE;
} else {
$imageInfo = getimagesize($value['tmp_name']);
$extension = isset($this->imageTypesMap[$imageInfo[2]]) ? $this->imageTypesMap[$imageInfo[2]] : false;
$this->success = ($extension && in_array($extension, $this->options[self::OPTION_ALLOWED_IMAGES]));
}
return $this->success;
}
public function getPotentialMessage()
{
$message = parent::getPotentialMessage();
$imageTypes = array_map('strtoupper', $this->options[self::OPTION_ALLOWED_IMAGES]);
$message->setVariables(
array(
'image_types' => implode(', ', $imageTypes)
)
);
return $message;
}
}
<?php
namespace Sirius\Validation\Rule\Upload;
use Sirius\Validation\Rule\AbstractRule;
class ImageHeight extends AbstractRule
{
const OPTION_MAX = 'max';
const OPTION_MIN = 'min';
const MESSAGE = 'The file should be at least {min} pixels tall';
const LABELED_MESSAGE = '{label} should be at least {min} pixels tall';
protected $options = array(
self::OPTION_MAX => 1000000,
self::OPTION_MIN => 0,
);
public function validate($value, $valueIdentifier = null)
{
$this->value = $value;
if (! is_array($value) || ! isset($value['tmp_name'])) {
$this->success = false;
} elseif (! file_exists($value['tmp_name'])) {
$this->success = $value['error'] === UPLOAD_ERR_NO_FILE;
} else {
$imageInfo = getimagesize($value['tmp_name']);
$height = isset($imageInfo[1]) ? $imageInfo[1] : 0;
$this->success = $height &&
$height <= $this->options[self::OPTION_MAX] &&
$height >= $this->options[self::OPTION_MIN];
}
return $this->success;
}
}
<?php
namespace Sirius\Validation\Rule\Upload;
use Sirius\Validation\Rule\AbstractRule;
class ImageRatio extends AbstractRule
{
// the image width/height ration;
// can be a number or a string like 4:3, 16:9
const OPTION_RATIO = 'ratio';
// how much can the image ratio diverge from the allowed ratio
const OPTION_ERROR_MARGIN = 'error_margin';
const MESSAGE = 'The image does must have a ratio (width/height) of {ratio})';
const LABELED_MESSAGE = '{label} does must have a ratio (width/height) of {ratio})';
protected $options = array(
self::OPTION_RATIO => 0,
self::OPTION_ERROR_MARGIN => 0,
);
protected function normalizeRatio($ratio)
{
if (is_numeric($ratio) || $ratio == filter_var($ratio, FILTER_SANITIZE_NUMBER_FLOAT)) {
return floatval($ratio);
}
if (strpos($ratio, ':') !== false) {
list($width, $height) = explode(':', $ratio);
return $width / $height;
}
return 0;
}
public function validate($value, $valueIdentifier = null)
{
$this->value = $value;
$ratio = $this->normalizeRatio($this->options[self::OPTION_RATIO]);
if (! is_array($value) || ! isset($value['tmp_name'])) {
$this->success = false;
} elseif (! file_exists($value['tmp_name'])) {
$this->success = $value['error'] === UPLOAD_ERR_NO_FILE;
} elseif ($ratio == 0) {
$this->success = true;
} else {
$imageInfo = getimagesize($value['tmp_name']);
if (is_array($imageInfo)) {
$actualRatio = $imageInfo[0] / $imageInfo[1];
$this->success = abs($actualRatio - $ratio) <= $this->options[self::OPTION_ERROR_MARGIN];
} else {
// no image size computed => no valid image
return $this->success = false;
}
}
return $this->success;
}
}
<?php
namespace Sirius\Validation\Rule\Upload;
use Sirius\Validation\Rule\AbstractRule;
class ImageWidth extends AbstractRule
{
const OPTION_MAX = 'max';
const OPTION_MIN = 'min';
const MESSAGE = 'The image should be at least {min} pixels wide';
const LABELED_MESSAGE = '{label} should be at least {min} pixels wide';
protected $options = array(
self::OPTION_MAX => 1000000,
self::OPTION_MIN => 0,
);
public function validate($value, $valueIdentifier = null)
{
$this->value = $value;
if (! is_array($value) || ! isset($value['tmp_name'])) {
$this->success = false;
} elseif (! file_exists($value['tmp_name'])) {
$this->success = $value['error'] === UPLOAD_ERR_NO_FILE;
} else {
$imageInfo = getimagesize($value['tmp_name']);
$width = isset($imageInfo[0]) ? $imageInfo[0] : 0;
$this->success = $width &&
$width <= $this->options[self::OPTION_MAX] &&
$width >= $this->options[self::OPTION_MIN];
}
return $this->success;
}
}
<?php
/**
* Created by PhpStorm.
* User: Gumacs
* Date: 2017. 03. 07.
* Time: 16:02
*/
namespace Sirius\Validation\Rule\Upload;
use Sirius\Validation\Rule\AbstractRule;
class Required extends AbstractRule
{
const MESSAGE = 'The file is required';
const LABELED_MESSAGE = '{label} is required';
public function validate($value, $valueIdentifier = null)
{
$this->value = $value;
if (! is_array($value) || ! isset($value['tmp_name']) ||
! file_exists($value['tmp_name']) || $value['error'] !== UPLOAD_ERR_OK) {
$this->success = false;
} else {
$this->success = true;
}
return $this->success;
}
}
<?php
namespace Sirius\Validation\Rule\Upload;
use Sirius\Validation\Rule\AbstractRule;
class Size extends AbstractRule
{
const OPTION_SIZE = 'size';
const MESSAGE = 'The file should not exceed {size}';
const LABELED_MESSAGE = '{label} should not exceed {size}';
protected $options = array(
self::OPTION_SIZE => '2M'
);
protected function normalizeSize($size)
{
$units = array( 'B' => 0, 'K' => 1, 'M' => 2, 'G' => 3 );
$unit = strtoupper(substr($size, strlen($size) - 1, 1));
if (! isset($units[$unit])) {
$normalizedSize = filter_var($size, FILTER_SANITIZE_NUMBER_INT);
} else {
$size = filter_var(substr($size, 0, strlen($size) - 1), FILTER_SANITIZE_NUMBER_FLOAT);
$normalizedSize = $size * pow(1024, $units[$unit]);
}
return $normalizedSize;
}
public function validate($value, $valueIdentifier = null)
{
$this->value = $value;
if (! is_array($value) || ! isset($value['tmp_name'])) {
$this->success = false;
} elseif (! file_exists($value['tmp_name'])) {
$this->success = $value['error'] === UPLOAD_ERR_NO_FILE;
} else {
$fileSize = @filesize($value['tmp_name']);
$limit = $this->normalizeSize($this->options[self::OPTION_SIZE]);
$this->success = $fileSize && $fileSize <= $limit;
}
return $this->success;
}
}
<?php
namespace Sirius\Validation\Rule;
class Url extends AbstractRule
{
const MESSAGE = 'This input is not a valid URL';
const LABELED_MESSAGE = '{label} is not a valid URL';
public function validate($value, $valueIdentifier = null)
{
$this->value = $value;
$this->success = (bool) filter_var($value, FILTER_VALIDATE_URL, FILTER_FLAG_HOST_REQUIRED);
return $this->success;
}
}
<?php
namespace Sirius\Validation\Rule;
class Website extends AbstractRule
{
const WEBSITE_REGEX = '@^((http|https)\:)//.+$@i';
const MESSAGE = 'This input must be a valid website address';
const LABELED_MESSAGE = '{label} must be a valid website address';
public function validate($value, $valueIdentifier = null)
{
$this->value = $value;
$this->success = (substr($value, 0, 2) == '//')
|| (preg_match(static::WEBSITE_REGEX, $value) && filter_var(
$value,
FILTER_VALIDATE_URL,
FILTER_FLAG_HOST_REQUIRED
));
return $this->success;
}
}
<?php
namespace Sirius\Validation;
class RuleCollection extends \SplObjectStorage
{
public function attach($rule, $data = null)
{
if ($this->contains($rule)) {
return;
}
if ($rule instanceof Rule\Required) {
$rules = array();
foreach ($this as $r) {
$rules[] = $r;
$this->detach($r);
}
array_unshift($rules, $rule);
foreach ($rules as $r) {
parent::attach($r);
}
return;
}
return parent::attach($rule);
}
public function getHash($rule)
{
/* @var $rule Rule\AbstractValidator */
return $rule->getUniqueId();
}
}
<?php
namespace Sirius\Validation;
use Sirius\Validation\Rule\Callback as CallbackRule;
class RuleFactory
{
/**
* Validator map allows for flexibility when creating a validation rule
* You can use 'required' instead of 'required' for the name of the rule
* or 'minLength'/'minlength' instead of 'MinLength'
*
* @var array
*/
protected $validatorsMap = array();
/**
* @var array
*/
protected $errorMessages = array();
/**
* @var array
*/
protected $labeledErrorMessages = array();
/**
* Constructor
*/
public function __construct()
{
$this->registerDefaultRules();
}
/**
* Set up the default rules that come with the library
*/
protected function registerDefaultRules()
{
$rulesClasses = array(
'Alpha',
'AlphaNumeric',
'AlphaNumHyphen',
'ArrayLength',
'ArrayMaxLength',
'ArrayMinLength',
'Between',
'Callback',
'Date',
'DateTime',
'Email',
'EmailDomain',
'Equal',
'FullName',
'GreaterThan',
'InList',
'Integer',
'IpAddress',
'Length',
'LessThan',
'Match',
'MaxLength',
'MinLength',
'NotInList',
'NotRegex',
'Number',
'Regex',
'Required',
'RequiredWhen',
'RequiredWith',
'RequiredWithout',
'Time',
'Url',
'Website',
'File\Extension',
'File\Image',
'File\ImageHeight',
'File\ImageRatio',
'File\ImageWidth',
'File\Size',
'Upload\Required',
'Upload\Extension',
'Upload\Image',
'Upload\ImageHeight',
'Upload\ImageRatio',
'Upload\ImageWidth',
'Upload\Size',
);
foreach ($rulesClasses as $class) {
$fullClassName = '\\' . __NAMESPACE__ . '\Rule\\' . $class;
$name = strtolower(str_replace('\\', '', $class));
$errorMessage = constant($fullClassName . '::MESSAGE');
$labeledErrorMessage = constant($fullClassName . '::LABELED_MESSAGE');
$this->register($name, $fullClassName, $errorMessage, $labeledErrorMessage);
}
}
/**
* Register a class to be used when creating validation rules
*
* @param string $name
* @param string $class
*
* @return \Sirius\Validation\RuleFactory
*/
public function register($name, $class, $errorMessage = '', $labeledErrorMessage = '')
{
if (is_subclass_of($class, '\Sirius\Validation\Rule\AbstractRule')) {
$this->validatorsMap[$name] = $class;
}
if ($errorMessage) {
$this->errorMessages[$name] = $errorMessage;
}
if ($labeledErrorMessage) {
$this->labeledErrorMessages[$name] = $labeledErrorMessage;
}
return $this;
}
/**
* Factory method to construct a validator based on options that are used most of the times
*
* @param string|callable $name
* name of a validator class or a callable object/function
* @param string|array $options
* validator options (an array, JSON string or QUERY string)
* @param string $messageTemplate
* error message template
* @param string $label
* label of the form input field or model attribute
*
* @throws \InvalidArgumentException
* @return \Sirius\Validation\Rule\AbstractValidator
*/
public function createRule($name, $options = null, $messageTemplate = null, $label = null)
{
$validator = $this->construcRuleByNameAndOptions($name, $options);
// no message template, try to get it from the registry
if (!$messageTemplate) {
$messageTemplate = $this->getSuggestedMessageTemplate($name, !!$label);
}
if (is_string($messageTemplate) && $messageTemplate !== '') {
$validator->setMessageTemplate($messageTemplate);
}
if (is_string($label) && $label !== '') {
$validator->setOption('label', $label);
}
return $validator;
}
/**
* Set default error message for a rule
*
* @param string $rule
* @param string|null $messageWithoutLabel
* @param string|null $messageWithLabel
*
* @return $this
*/
public function setMessages($rule, $messageWithoutLabel = null, $messageWithLabel = null)
{
if ($messageWithoutLabel) {
$this->errorMessages[$rule] = $messageWithoutLabel;
}
if ($messageWithLabel) {
$this->labeledErrorMessages[$rule] = $messageWithLabel;
}
return $this;
}
/**
* Get the error message saved in the registry for a rule, where the message
* is with or without a the label
*
* @param string $name name of the rule
* @param bool $withLabel
*
* @return string|NULL
*/
protected function getSuggestedMessageTemplate($name, $withLabel)
{
$noLabelMessage = is_string($name) && isset($this->errorMessages[$name]) ? $this->errorMessages[$name] : null;
if ($withLabel) {
return is_string($name) && isset($this->labeledErrorMessages[$name]) ?
$this->labeledErrorMessages[$name] :
$noLabelMessage;
}
return $noLabelMessage;
}
/**
* @param $name
* @param $options
*
* @return CallbackRule
*/
protected function construcRuleByNameAndOptions($name, $options)
{
if (is_callable($name)) {
$validator = new CallbackRule(
array(
'callback' => $name,
'arguments' => $options
)
);
} elseif (is_string($name)) {
$name = trim($name);
// use the validator map
if (isset($this->validatorsMap[strtolower($name)])) {
$name = $this->validatorsMap[strtolower($name)];
}
// try if the validator is the name of a class in the package
if (class_exists('\Sirius\Validation\Rule\\' . $name, false)) {
$name = '\Sirius\Validation\Rule\\' . $name;
}
// at this point we should have a class that can be instanciated
if (class_exists($name) && is_subclass_of($name, '\Sirius\Validation\Rule\AbstractRule')) {
$validator = new $name($options);
}
}
if (!isset($validator)) {
throw new \InvalidArgumentException(
sprintf('Impossible to determine the validator based on the name: %s', (string) $name)
);
}
return $validator;
}
}
<?php
namespace Sirius\Validation\Util;
class Arr
{
/**
* Constant that represents the root of an array
*/
const PATH_ROOT = '/';
/**
* @param $selector
*
* @return array
*/
protected static function getSelectorParts($selector)
{
$firstOpen = strpos($selector, '[');
if ($firstOpen === false) {
return array( $selector, '' );
}
$firstClose = strpos($selector, ']');
$container = substr($selector, 0, $firstOpen);
$subselector = substr($selector, $firstOpen + 1, $firstClose - $firstOpen - 1) . substr(
$selector,
$firstClose + 1
);
return array( $container, $subselector );
}
/**
* Retrieves an element from an array via its path
* Path examples:
* key
* key[subkey]
* key[0][subkey]
*
* @param array $array
* @param string $path
*
* @return mixed
*/
public static function getByPath($array, $path = self::PATH_ROOT)
{
$path = trim($path);
if (! $path || $path == self::PATH_ROOT) {
return $array;
}
// fix the path in case it was provided as `[item][subitem]`
if (strpos($path, '[') === 0) {
$path = preg_replace('/]/', '', ltrim($path, '['), 1);
}
list($container, $subpath) = self::getSelectorParts($path);
if ($subpath === '') {
return array_key_exists($container, $array) ? $array[$container] : null;
}
return array_key_exists($container, $array) ? self::getByPath($array[$container], $subpath) : null;
}
/**
* Set values in the array by selector
*
* @example
* Arr::setBySelector($data, 'email', 'my@domain.com');
* Arr::setBySelector($data, 'addresses[0][line]', null);
* Arr::setBySelector($data, 'addresses[*][line]', null);
*
* @param array $array
* @param string $selector
* @param mixed $value
* @param bool $overwrite true if the $value should overwrite the existing value
*
* @return array
*/
public static function setBySelector($array, $selector, $value, $overwrite = false)
{
// make sure the array is an array in case we got here through a subsequent call
// so arraySetElementBySelector(array(), 'item[subitem]', 'value');
// will call arraySetElementBySelector(null, 'subitem', 'value');
if (! is_array($array)) {
$array = array();
}
list($container, $subselector) = self::getSelectorParts($selector);
if (! $subselector) {
if ($container !== '*') {
if ($overwrite === true || ! array_key_exists($container, $array)) {
$array[$container] = $value;
}
}
return $array;
}
// if we have a subselector the $array[$container] must be an array
if ($container !== '*' && ! array_key_exists($container, $array)) {
$array[$container] = array();
}
// we got here through something like *[subitem]
if ($container === '*') {
foreach ($array as $key => $v) {
$array[$key] = self::setBySelector($array[$key], $subselector, $value, $overwrite);
}
} else {
$array[$container] = self::setBySelector($array[$container], $subselector, $value, $overwrite);
}
return $array;
}
/**
* Get values in the array by selector
*
* @example
* Arr::getBySelector($data, 'email');
* Arr::getBySelector($data, 'addresses[0][line]');
* Arr::getBySelector($data, 'addresses[*][line]');
*
* @param $array
* @param $selector
*
* @return array
*/
public static function getBySelector($array, $selector)
{
if (strpos($selector, '[*]') === false) {
return array(
$selector => self::getByPath($array, $selector)
);
}
$result = array();
list($preffix, $suffix) = explode('[*]', $selector, 2);
$base = self::getByPath($array, $preffix);
if (! is_array($base)) {
$base = array();
}
// we don't have a suffix, the selector was something like path[subpath][*]
if (! $suffix) {
foreach ($base as $k => $v) {
$result["{$preffix}[{$k}]"] = $v;
}
// we have a suffix, the selector was something like path[*][item]
} else {
foreach ($base as $itemKey => $itemValue) {
if (is_array($itemValue)) {
$result["{$preffix}[{$itemKey}]{$suffix}"] = self::getByPath($itemValue, $suffix);
}
}
}
return $result;
}
}
<?php
namespace Sirius\Validation;
use Sirius\Validation\ValidatorInterface;
class Validator implements ValidatorInterface
{
const RULE_REQUIRED = 'required';
const RULE_REQUIRED_WITH = 'requiredwith';
const RULE_REQUIRED_WITHOUT = 'requiredwithout';
const RULE_REQUIRED_WHEN = 'requiredwhen';
// string rules
const RULE_ALPHA = 'alpha';
const RULE_ALPHANUMERIC = 'alphanumeric';
const RULE_ALPHANUMHYPHEN = 'alphanumhyphen';
const RULE_LENGTH = 'length';
const RULE_MAX_LENGTH = 'maxlength';
const RULE_MIN_LENGTH = 'minlength';
const RULE_FULLNAME = 'fullname';
// array rules
const RULE_ARRAY_LENGTH = 'arraylength';
const RULE_ARRAY_MIN_LENGTH = 'arrayminlength';
const RULE_ARRAY_MAX_LENGTH = 'arraymaxlength';
const RULE_IN_LIST = 'inlist';
const RULE_NOT_IN_LIST = 'notinlist';
// date rules
const RULE_DATE = 'date';
const RULE_DATETIME = 'datetime';
const RULE_TIME = 'time';
// number rules
const RULE_BETWEEN = 'between';
const RULE_GREATER_THAN = 'greaterthan';
const RULE_LESS_THAN = 'lessthan';
const RULE_NUMBER = 'number';
const RULE_INTEGER = 'integer';
// regular expression rules
const RULE_REGEX = 'regex';
const RULE_NOT_REGEX = 'notregex';
// other rules
const RULE_EMAIL = 'email';
const RULE_EMAIL_DOMAIN = 'emaildomain';
const RULE_URL = 'url';
const RULE_WEBSITE = 'website';
const RULE_IP = 'ipaddress';
const RULE_MATCH = 'match';
const RULE_EQUAL = 'equal';
const RULE_CALLBACK = 'callback';
// files rules
const RULE_FILE_EXTENSION = 'fileextension';
const RULE_FILE_SIZE = 'filesize';
const RULE_IMAGE = 'image';
const RULE_IMAGE_HEIGHT = 'imageheight';
const RULE_IMAGE_WIDTH = 'imagewidth';
const RULE_IMAGE_RATIO = 'imageratio';
// upload rules
const RULE_UPLOAD_REQUIRED = 'uploadrequired';
const RULE_UPLOAD_EXTENSION = 'uploadextension';
const RULE_UPLOAD_SIZE = 'uploadsize';
const RULE_UPLOAD_IMAGE = 'uploadimage';
const RULE_UPLOAD_IMAGE_HEIGHT = 'uploadimageheight';
const RULE_UPLOAD_IMAGE_WIDTH = 'uploadimagewidth';
const RULE_UPLOAD_IMAGE_RATIO = 'uploadimageratio';
/**
* @var boolean
*/
protected $wasValidated = false;
/**
* @var array
*/
protected $rules = array();
/**
* @var array
*/
protected $messages = array();
/**
* @var \Sirius\Validation\RuleFactory
*/
protected $ruleFactory;
/**
* @var ErrorMessage
*/
protected $errorMessagePrototype;
/**
* The object that will contain the data
*
* @var \Sirius\Validation\DataWrapper\WrapperInterface
*/
protected $dataWrapper;
public function __construct(RuleFactory $ruleFactory = null, ErrorMessage $errorMessagePrototype = null)
{
if (!$ruleFactory) {
$ruleFactory = new RuleFactory();
}
$this->ruleFactory = $ruleFactory;
if (!$errorMessagePrototype) {
$errorMessagePrototype = new ErrorMessage();
}
$this->errorMessagePrototype = $errorMessagePrototype;
}
/**
* Retrieve the rule factory
*
* @return \Sirius\Validation\RuleFactory
*/
public function getRuleFactory()
{
return $this->ruleFactory;
}
/**
* @param ErrorMessage $errorMessagePrototype
*
* @throws \InvalidArgumentException
*
* @return \Sirius\Validation\Rule\AbstractValidator
*/
public function setErrorMessagePrototype(ErrorMessage $errorMessagePrototype)
{
$this->errorMessagePrototype = $errorMessagePrototype;
return $this;
}
/**
* Retrieve the error message prototype
*
* @return ErrorMessage
*/
public function getErroMessagePrototype()
{
return $this->errorMessagePrototype;
}
/**
* @example
* // add multiple rules at once
* $validator->add(array(
* 'field_a' => 'required',
* 'field_b' => array('required', array('email', null, '{label} must be an email', 'Field B')),
* ));
*
* // add multiple rules using arrays
* $validator->add('field', array('required', 'email'));
*
* // add multiple rules using a string
* $validator->add('field', 'required | email');
*
* // add validator with options
* $validator->add('field:Label', 'minlength', array('min' => 2), '{label} should have at least {min} characters');
*
* // add validator with string and parameters as JSON string
* $validator->add('field:Label', 'minlength({"min": 2})({label} should have at least {min} characters)');
*
* // add validator with string and parameters as query string
* $validator->add('field:label', 'minlength(min=2)({label} should have at least {min} characters)');
*
* @param string|array $selector
* @param string|callback $name
* @param string|array $options
* @param string $messageTemplate
* @param string $label
*
* @throws \InvalidArgumentException
*
* @return Validator
*/
public function add($selector, $name = null, $options = null, $messageTemplate = null, $label = null)
{
// the $selector is an associative array with $selector => $rules
if (func_num_args() == 1) {
if (!is_array($selector)) {
throw new \InvalidArgumentException('If $selector is the only argument it must be an array');
}
return $this->addMultiple($selector);
}
// check if the selector is in the form of 'selector:Label'
if (strpos($selector, ':') !== false) {
list($selector, $label) = explode(':', $selector, 2);
}
$this->ensureSelectorRulesExist($selector, $label);
call_user_func(array( $this->rules[$selector], 'add' ), $name, $options, $messageTemplate, $label);
return $this;
}
/**
* @param array $selectorRulesCollection
*
* @return Validator
*/
public function addMultiple($selectorRulesCollection)
{
foreach ($selectorRulesCollection as $selector => $rules) {
// a single rule was passed for the $valueSelector
if (! is_array($rules)) {
$this->add($selector, $rules);
continue;
}
// multiple rules were passed for the same $valueSelector
foreach ($rules as $rule) {
// the rule is an array, this means it contains $name, $options, $messageTemplate, $label
if (is_array($rule)) {
array_unshift($rule, $selector);
call_user_func_array(
array(
$this,
'add'
),
$rule
);
// the rule is only the name of the validator
} else {
$this->add($selector, $rule);
}
}
}
return $this;
}
/**
* @param string $selector
* data selector
* @param mixed $name
* rule name or true if all rules should be deleted for that selector
* @param mixed $options
* rule options, necessary for rules that depend on params for their ID
*
* @return self
*/
public function remove($selector, $name = true, $options = null)
{
if (!array_key_exists($selector, $this->rules)) {
return $this;
}
/* @var $collection \Sirius\Validation\ValueValidator */
$collection = $this->rules[$selector];
$collection->remove($name, $options);
return $this;
}
/**
* The data wrapper will be used to wrap around the data passed to the validator
* This way you can validate anything, not just arrays (which is the default)
*
* @param mixed $data
*
* @return \Sirius\Validation\DataWrapper\WrapperInterface
*/
public function getDataWrapper($data = null)
{
// if $data is set reconstruct the data wrapper
if (!$this->dataWrapper || $data) {
$this->dataWrapper = new DataWrapper\ArrayWrapper($data);
}
return $this->dataWrapper;
}
public function setData($data)
{
$this->getDataWrapper($data);
$this->wasValidated = false;
// reset messages
$this->messages = array();
return $this;
}
/**
* Performs the validation
*
* @param mixed $data
* array to be validated
*
* @return boolean
*/
public function validate($data = null)
{
if ($data !== null) {
$this->setData($data);
}
// data was already validated, return the results immediately
if ($this->wasValidated === true) {
return $this->wasValidated && count($this->messages) === 0;
}
foreach ($this->rules as $selector => $valueValidator) {
foreach ($this->getDataWrapper()->getItemsBySelector($selector) as $valueIdentifier => $value) {
/* @var $valueValidator \Sirius\Validation\ValueValidator */
if (!$valueValidator->validate($value, $valueIdentifier, $this->getDataWrapper())) {
foreach ($valueValidator->getMessages() as $message) {
$this->addMessage($valueIdentifier, $message);
}
}
}
}
$this->wasValidated = true;
return $this->wasValidated && count($this->messages) === 0;
}
/**
* @param string $item
* data identifier (eg: 'email', 'addresses[0][state]')
* @param string $message
*
* @return self
*/
public function addMessage($item, $message = null)
{
if ($message === null || $message === '') {
return $this;
}
if (!array_key_exists($item, $this->messages)) {
$this->messages[$item] = array();
}
$this->messages[$item][] = $message;
return $this;
}
/**
* Clears the messages of an item
*
* @param string $item
*
* @return self
*/
public function clearMessages($item = null)
{
if (is_string($item)) {
if (array_key_exists($item, $this->messages)) {
unset($this->messages[$item]);
}
} elseif ($item === null) {
$this->messages = array();
}
return $this;
}
/**
* @param string $item
* key of the messages array (eg: 'password', 'addresses[0][line_1]')
*
* @return array
*/
public function getMessages($item = null)
{
if (is_string($item)) {
return array_key_exists($item, $this->messages) ? $this->messages[$item] : array();
}
return $this->messages;
}
public function getRules()
{
return $this->rules;
}
/**
* @param string $selector
* @param string $label
*/
protected function ensureSelectorRulesExist($selector, $label = null)
{
if (!isset($this->rules[$selector])) {
$this->rules[$selector] = new ValueValidator(
$this->getRuleFactory(),
$this->getErroMessagePrototype(),
$label
);
}
}
}
<?php
namespace Sirius\Validation;
interface ValidatorInterface
{
public function add($selector, $name = null, $options = null, $messageTemplate = null, $label = null);
public function remove($selector, $name = true, $options = null);
public function validate($data = array());
}
<?php
namespace Sirius\Validation;
use Sirius\Validation\Rule\AbstractRule;
class ValueValidator
{
/**
* The error messages generated after validation or set manually
*
* @var array
*/
protected $messages = array();
/**
* Will be used to construct the rules
*
* @var \Sirius\Validation\RuleFactory
*/
protected $ruleFactory;
/**
* The prototype that will be used to generate the error message
*
* @var \Sirius\Validation\ErrorMessage
*/
protected $errorMessagePrototype;
/**
* The rule collections for the validation
*
* @var \Sirius\Validation\RuleCollection
*/
protected $rules;
/**
* The label of the value to be validated
*
* @var string
*/
protected $label;
public function __construct(
RuleFactory $ruleFactory = null,
ErrorMessage $errorMessagePrototype = null,
$label = null
) {
if (!$ruleFactory) {
$ruleFactory = new RuleFactory();
}
$this->ruleFactory = $ruleFactory;
if (!$errorMessagePrototype) {
$errorMessagePrototype = new ErrorMessage();
}
$this->errorMessagePrototype = $errorMessagePrototype;
if ($label) {
$this->label = $label;
}
$this->rules = new RuleCollection;
}
public function setLabel($label = null)
{
$this->label = $label;
return $this;
}
/**
* Add 1 or more validation rules
*
* @example
* // add multiple rules at once
* $validator->add(array(
* 'required',
* array('required', array('email', null, '{label} must be an email', 'Field B')),
* ));
*
* // add multiple rules using a string
* $validator->add('required | email');
*
* // add validator with options
* $validator->add('minlength', array('min' => 2), '{label} should have at least {min} characters', 'Field label');
*
* // add validator with string and parameters as JSON string
* $validator->add('minlength({"min": 2})({label} should have at least {min} characters)(Field label)');
*
* // add validator with string and parameters as query string
* $validator->add('minlength(min=2)({label} should have at least {min} characters)(Field label)');
*
* @param string|callback $name
* @param string|array $options
* @param string $messageTemplate
* @param string $label
*
* @return ValueValidator
*/
public function add($name, $options = null, $messageTemplate = null, $label = null)
{
if (is_array($name) && !is_callable($name)) {
return $this->addMultiple($name);
}
if (is_string($name)) {
// rule was supplied like 'required | email'
if (strpos($name, ' | ') !== false) {
return $this->addMultiple(explode(' | ', $name));
}
// rule was supplied like this 'length(2,10)(error message template)(label)'
if (strpos($name, '(') !== false) {
list($name, $options, $messageTemplate, $label) = $this->parseRule($name);
}
}
// check for the default label
if (!$label && $this->label) {
$label = $this->label;
}
$validator = $this->ruleFactory->createRule($name, $options, $messageTemplate, $label);
return $this->addRule($validator);
}
/**
* @param array $rules
*
* @return ValueValidator
*/
public function addMultiple($rules)
{
foreach ($rules as $singleRule) {
// make sure the rule is an array (the parameters of subsequent calls);
$singleRule = is_array($singleRule) ? $singleRule : array(
$singleRule
);
call_user_func_array(
array(
$this,
'add'
),
$singleRule
);
}
return $this;
}
/**
* @param AbstractValidator $validationRule
*
* @return ValueValidator
*/
public function addRule(AbstractRule $validationRule)
{
$validationRule->setErrorMessagePrototype($this->errorMessagePrototype);
$this->rules->attach($validationRule);
return $this;
}
/**
* Remove validation rule
*
* @param mixed $name
* rule name or true if all rules should be deleted for that selector
* @param mixed $options
* rule options, necessary for rules that depend on params for their ID
*
* @throws \InvalidArgumentException
* @internal param string $selector data selector
* @return self
*/
public function remove($name = true, $options = null)
{
if ($name === true) {
$this->rules = new RuleCollection();
return $this;
}
$validator = $this->ruleFactory->createRule($name, $options);
$this->rules->detach($validator);
return $this;
}
/**
* Converts a rule that was supplied as string into a set of options that define the rule
*
* @example 'minLength({"min":2})({label} must have at least {min} characters)(Street)'
*
* will be converted into
*
* array(
* 'minLength', // validator name
* array('min' => 2'), // validator options
* '{label} must have at least {min} characters',
* 'Street' // label
* )
*
* @param string $ruleAsString
*
* @return array
*/
protected function parseRule($ruleAsString)
{
$ruleAsString = trim($ruleAsString);
$options = array();
$messageTemplate = null;
$label = null;
$name = substr($ruleAsString, 0, strpos($ruleAsString, '('));
$ruleAsString = substr($ruleAsString, strpos($ruleAsString, '('));
$matches = array();
preg_match_all('/\(([^\)]*)\)/', $ruleAsString, $matches);
if (isset($matches[1])) {
if (isset($matches[1][0]) && $matches[1][0] !== '') {
$options = $matches[1][0];
}
if (isset($matches[1][1]) && $matches[1][1]) {
$messageTemplate = $matches[1][1];
}
if (isset($matches[1][2]) && $matches[1][2]) {
$label = $matches[1][2];
}
}
return array(
$name,
$options,
$messageTemplate,
$label
);
}
public function validate($value, $valueIdentifier = null, DataWrapper\WrapperInterface $context = null)
{
$this->messages = array();
$isRequired = false;
// evaluate the required rules
/* @var $rule \Sirius\Validation\Rule\AbstractValidator */
foreach ($this->rules as $rule) {
if ($rule instanceof Rule\Required) {
$isRequired = true;
if (!$this->validateRule($rule, $value, $valueIdentifier, $context)) {
return false;
}
}
}
// avoid future rule evaluations if value is null or empty string
if ($this->isEmpty($value)) {
return true;
}
// evaluate the non-required rules
foreach ($this->rules as $rule) {
if (!($rule instanceof Rule\Required)) {
$this->validateRule($rule, $value, $valueIdentifier, $context);
// if field is required and we have an error,
// do not continue with the rest of rules
if ($isRequired && count($this->messages)) {
break;
}
}
}
return count($this->messages) === 0;
}
private function validateRule($rule, $value, $valueIdentifier, $context)
{
$rule->setContext($context);
if (!$rule->validate($value, $valueIdentifier)) {
$this->addMessage($rule->getMessage());
return false;
}
return true;
}
public function getMessages()
{
return $this->messages;
}
public function addMessage($message)
{
array_push($this->messages, $message);
return $this;
}
public function getRules()
{
return $this->rules;
}
protected function isEmpty($value)
{
return in_array($value, array(null, ''));
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment