<?php /** * AbstractService.class.php * Service 层基类 * @author : zhuxun37 * @version : $Id$ * @copyright: vchangyi.com */ namespace Common\Service; use Common\Common\Cache; use Common\Common\User; use Common\Common\Attach; use Common\Model\AttrModel; abstract class AbstractService extends \Com\Service { // 属性字段表 protected $_attr = null; // 构造方法 public function __construct() { parent::__construct(); $this->_attr = new AttrModel(); } /** * 获取属性信息列表 * @author liyifei * @param bool $isAll 是否获取所有属性 false=仅前端显示的属性; true=所有属性(包括显示和不显示) * @param array $typeArr 过滤属性类型 * @param bool $isCp * @param bool $ignoreIsOpen 忽略是否开启标识 * @return array */ public function getAttrList($isAll = true, $typeArr = [], $isCp = false, $ignoreIsOpen = true) { // 所有开启的属性 if ($isCp) { $conds = ['is_open_cp' => AttrModel::ATTR_IS_OPEN_TRUE]; } elseif ($ignoreIsOpen) { $conds = ['is_open' => AttrModel::ATTR_IS_OPEN_TRUE]; } // 获取所有属性或仅前端显示的属性 if (!$isAll) { $conds['is_show'] = AttrModel::ATTR_IS_SHOW_TRUE; } // 排序条件 $orders = [ 'is_system' => 'desc', '`order`' => 'asc', 'attr_id' => 'asc', ]; $attrs = $this->_attr->list_by_conds($conds, [], $orders); // 获取配置 $settings = Cache::instance()->get('Common.AppSetting'); // 需过滤的属性类型 $result = []; foreach ($attrs as $k => $v) { if (is_array($typeArr) && in_array($v['type'], $typeArr)) { continue; } $result[$k] = $v; // 将单选、下拉框单选、多选类型的属性选项,反序列化 if ($v['type'] == AttrModel::ATTR_TYPE_RADIO || $v['type'] == AttrModel::ATTR_TYPE_DROPBOX || $v['type'] == AttrModel::ATTR_TYPE_CHECKBOX) { $result[$k]['option'] = unserialize($v['option']); } switch ($result[$k]['field_name']) { case 'memJob': if ('select' === $settings['jobMode']['value']) { $this->_getJobs($result[$k]); } else { $result[$k]['option'] = []; } break; case 'memRole': if ('select' === $settings['roleMode']['value']) { $this->_getRoles($result[$k]); } else { $result[$k]['option'] = []; } break; } } return array_values($result); } /** * 职位属性特殊处理 * @param $attr * @return bool */ protected function _getJobs(&$attr) { $jobService = new JobService(); $jobService->searchList($result, array('limit' => 1000)); $attr['type'] = (string)AttrModel::ATTR_TYPE_DROPBOX; $attr['option'] = array(); foreach ($result['list'] as $_job) { $attr['option'][] = array( 'name' => $_job['jobName'], 'value' => $_job['jobName'] ); } return true; } /** * 角色属性特殊处理 * @param $attr * @return bool */ protected function _getRoles(&$attr) { $roleService = new RoleService(); $roleService->searchList($result, I('post.')); $attr['type'] = (string)AttrModel::ATTR_TYPE_DROPBOX; $attr['option'] = array(); foreach ($result['list'] as $_job) { $attr['option'][] = array( 'name' => $_job['roleName'], 'value' => $_job['roleName'] ); } return true; } /** * 检查属性值,并返回错误信息 * @author liyifei * @param array $values 属性的键值对数组, 格式为 ['memUsername' => 'xxx', 'memMobile' => 13166666666] * @param string $require_field * @param array $needToVerify * @return array */ public function checkValue($values, $require_field = 'is_required_cp', $needToVerify = []) { $attrs = $this->getAttrList(true, array(), 'is_required_cp' == $require_field ? true : false); $errors = []; // 在职状态为离职时,离职日期不可为空(此处暂不使用常量表示离职状态) if ($values['memActive'] == 4 && strlen($values['leaveDate']) == 0) { $errors[] = '离职日期不可为空'; } foreach ($attrs as $attr) { // 只验证需要验证的字段 if (!empty($needToVerify) && !in_array($attr['field_name'], $needToVerify)) { continue; } $field_name = $attr['field_name']; $value = isset($values[$field_name]) && $values[$field_name] !== '' ? $values[$field_name] : ''; // 不验证的必填项(手机端提交表单时,不给被邀请人选择直属上级的权限,所以当直属上级为必填时,要跳过验证) $notCheckType = [ AttrModel::ATTR_TYPE_SPECIAL, AttrModel::ATTR_TYPE_LEADER ]; // 必填属性 if ($attr[$require_field] == AttrModel::ATTR_IS_REQUIRED_TRUE && $value === '' && !in_array($attr['type'], $notCheckType)) { $errors[] = $attr['attr_name'] . '-必填项值错误'; } // 验证手机号格式 if (!empty($value) && $attr['field_name'] === 'memMobile' && strlen($value) != 11) { $errors[] = $attr['attr_name'] . '-格式错误'; } // 验证邮箱格式 if (!empty($value) && $attr['field_name'] === 'memEmail' && !preg_match('/^([a-zA-Z0-9_\.\-])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})+$/', $value)) { $errors[] = $attr['attr_name'] . '-格式错误'; } // 验证账号(规则:1~32位字符、仅可用大小写字母、数字、下划线) if (!empty($value) && $attr['field_name'] === 'memUserid' && !preg_match('/^[a-zA-Z0-9_]{1,32}$/', $value)) { $errors[] = $attr['attr_name'] . '-格式错误'; } // 验证英文名(规则:1~64位字符、仅可用大小写字母、数字、下划线、点、减号、空格) if (!empty($value) && $attr['field_name'] === 'memEnglishName' && !preg_match('/^[a-zA-Z0-9_\.\-\s]{1,32}$/', $value)) { $errors[] = $attr['attr_name'] . '-格式错误'; } switch ($attr['type']) { // 单选类型 case AttrModel::ATTR_TYPE_RADIO: $key = array_column($attr['option'], 'value'); if (!in_array($value, $key) && $attr['is_required_cp'] == AttrModel::ATTR_IS_REQUIRED_TRUE) { $errors[] = $attr['attr_name'] . '-选项不存在'; } break; // 下拉框单选类型(同单选类型验证) case AttrModel::ATTR_TYPE_DROPBOX: // 防止是非必填的属性同时又是空值 if (empty($value)) { break; } $key = array_column($attr['option'], 'value'); if (!in_array($value, $key)) { $errors[] = $attr['attr_name'] . '-选项不存在'; } break; // 多选类型 case AttrModel::ATTR_TYPE_CHECKBOX: $value = unserialize($value); $key = array_column($attr['option'], 'value'); foreach ($value as $v) { if (!in_array($v['value'], $key)) { $errors[] = $attr['attr_name'] . '-选项不存在'; } } break; // 图片类型 case AttrModel::ATTR_TYPE_PICTURE: // 前端提交图片附件ID数组 $value = unserialize($value); if (!is_array($value)) { $errors[] = $attr['attr_name'] . '-格式错误'; } break; } } return $errors; } /** * 根据属性类型,格式化相应属性值 * @author liyifei * @param int $type 属性类型 * @param string|int $value 属性值 * @param array $userlist 用户列表 * @return mixed */ public function formatValueByType($type, $value, $userlist = []) { $result = ''; switch ($type) { // 图片类型,从架构获取图片信息 case AttrModel::ATTR_TYPE_PICTURE: if (!empty($value)) { $result = $this->formatImg($value); } break; // 多选类型,将值反序列化转为数组 case AttrModel::ATTR_TYPE_CHECKBOX: if (!empty($value)) { $result = array_column(unserialize($value), 'name'); } break; // 直属上级 case AttrModel::ATTR_TYPE_LEADER: if (!empty($value)) { $result = $this->formatLeader($value, $userlist); } break; default: $result = is_null($value) ? '' : $value; } return $result; } /** * 格式化直属上级、部门负责人返回值 * @author liyifei * @param string $uids 以英文逗号分隔的uid字符串,如"B4B3BA5B7F00000173E870DA6ADFEA2A,B4B3BA207F00000173E870DAB46163B0" * @param array $userlist 用户列表 * @return array */ public function formatLeader($uids, $userlist = []) { $uidArr = explode(',', $uids); $result = []; if (empty($uidArr)) { return $result; } $userServ = &User::instance(); $list = []; if (empty($userlist)) { $list = $userServ->listByUid($uidArr); } else { foreach ($uidArr as $uid) { if (isset($userlist[$uid])) { $list[] = $userlist[$uid]; } } } foreach ($list as $v) { $result[] = [ 'uid' => $v['memUid'], 'name' => $v['memUsername'], 'face' => $v['memFace'], ]; } return $result; } /** * 根据图片ID数组,获取附件Url,并格式化返回 * @author liyifei * @param array|string $atids 图片id数组 或 序列化后的附件id * @return mixed */ public function formatImg($atids) { // 非数组时,即为序列化后的附件id,需反序列化 if (!is_array($atids)) { $atids = unserialize($atids); } $result = []; $newAttach = new Attach(); $list = $newAttach->listAttachUrl($atids); foreach ($list as $v) { $result[] = [ 'id' => $v['atId'], 'url' => $v['atAttachment'], 'file_name' => $v['atFilename'], ]; } return $result; } /** * 获取筛选后的属性类型 * @author liyifei * @param array $filters 去除的属性类型 * @return array */ public function getAllAttrType($filters = []) { $allType = [ AttrModel::ATTR_TYPE_SINGLE_TEXT, AttrModel::ATTR_TYPE_MULTIPLE_TEXT, AttrModel::ATTR_TYPE_NUMBER, AttrModel::ATTR_TYPE_DATE, AttrModel::ATTR_TYPE_TIME, AttrModel::ATTR_TYPE_DATE_TIME, AttrModel::ATTR_TYPE_RADIO, AttrModel::ATTR_TYPE_CHECKBOX, AttrModel::ATTR_TYPE_ADDRESS, AttrModel::ATTR_TYPE_PICTURE, AttrModel::ATTR_TYPE_DROPBOX, AttrModel::ATTR_TYPE_SPECIAL, AttrModel::ATTR_TYPE_LEADER, ]; if (!empty($filters) && is_array($filters)) { foreach ($allType as $k => $v) { if (in_array($v, $filters)) { unset($allType[$k]); } } } return $allType; } }