Example #1
0
 /**
  * 构造函数
  *
  * @param array $config
  *
  * @return Log
  */
 function __construct(array $config = null)
 {
     $names = array('EMERG' => self::EMERG, 'ALERT' => self::ALERT, 'CRIT' => self::CRIT, 'ERR' => self::ERR, 'WARN' => self::WARN, 'NOTICE' => self::NOTICE, 'INFO' => self::INFO, 'DEBUG' => self::DEBUG);
     $arr = isset($config['log_priorities']) ? Q::normalize($config['log_priorities']) : Q::normalize(Q::getIni('log_priorities'));
     $this->_priorities = array('index' => array(), 'names' => array());
     foreach ($arr as $item) {
         if (isset($names[$item])) {
             $this->_priorities['index'][$names[$item]] = $item;
             $this->_priorities['names'][$item] = $names[$item];
         }
     }
     $dir_tmp = isset($config['log_writer_dir']) ? $config['log_writer_dir'] : Q::getIni('log_writer_dir');
     $dir = realpath($dir_tmp);
     if (empty($dir)) {
         $dir = realpath(Q::getIni('runtime_cache_dir'));
         if (empty($dir)) {
             // LC_MSG: 指定的日志文件保存目录不存在 "%s".
             throw new QLog_Exception(__('指定的日志文件保存目录不存在 "%s".', $dir_tmp));
         }
     }
     $filename = isset($config['log_writer_filename']) ? $config['log_writer_filename'] : Q::getIni('log_writer_filename');
     $this->_filename = rtrim($dir, '/\\') . DS . $filename;
     $chunk_size = isset($config['log_cache_chunk_size']) ? intval($config['log_cache_chunk_size']) : intval(Q::getIni('log_cache_chunk_size'));
     $this->_cache_chunk_size = $chunk_size * 1024;
     $this->append(__METHOD__, self::DEBUG);
 }
Example #2
0
 function UserAclRoles($user_id = '')
 {
     $show_box['title'] = '获取用户全部角色';
     $return_value = '';
     $roles_idname = array();
     $roles_id = array();
     $sp_roles = Q::ini('appini/sp_role');
     // 第一步:直接从中间表获得用户的全部角色ID
     $user_roles = UsersHaveRoles::find('user_id = ?', intval($user_id))->asArray()->getAll();
     //dump($user_roles);
     // 取出有用的ID,去除deny的ID
     foreach ($user_roles as $value) {
         if ($value['is_include']) {
             $roles_id[] = $value['role_id'];
         }
     }
     //dump ( $roles_id);
     $roles_arr = Roles::find('role_id in (?)', Q::normalize($roles_id, ","))->asArray()->getAll();
     foreach ($roles_arr as $value) {
         $roles_idname[$value['role_id']] = $value['rolename'];
     }
     //dump($roles_idname);
     if (in_array($sp_roles['REPEAL'], $roles_idname)) {
         $return_value = array($value['role_id'] => $sp_roles['REPEAL']);
         return $return_value;
     } elseif (in_array($sp_roles['FREEZE'], $roles_idname)) {
         $return_value = array($value['role_id'] => $sp_roles['FREEZE']);
         return $return_value;
     } elseif (in_array($sp_roles['UNCHECKED'], $roles_idname)) {
         $return_value = array($value['role_id'] => $sp_roles['UNCHECKED']);
         return $return_value;
     } else {
         return $roles_idname;
     }
 }
Example #3
0
 /**
  * @dataProvider normalizeProvider
  */
 function testNormalize($items, $test)
 {
     $data = array('key1', 'key2', 'key3');
     if ($test) {
         $this->assertEquals($data, Q::normalize($items, $test));
     } else {
         $this->assertEquals($data, Q::normalize($items));
     }
 }
Example #4
0
 /**
  * 允许上传的文件类型
  *
  * @param stirng $types
  * @return array
  */
 function uploadAllowedTypes($types = null)
 {
     if ($types) {
         $this->_upload_allowed_types = Q::normalize($types);
         return $this;
     } else {
         return $this->_upload_allowed_types;
     }
 }
Example #5
0
 function setTags($tags)
 {
     if (is_array($tags) || $tags instanceof Iterator) {
         $arr = array();
         foreach ($tags as $tag) {
             $arr[] = $tag->label;
         }
         $tags = $arr;
     }
     return implode(' ', Q::normalize($tags, ' '));
 }
Example #6
0
 static function createForm($id, $action)
 {
     $form = new Form_Admin_Links($id, $action);
     $form->add(QForm::ELEMENT, 'name', array('_ui' => 'textbox', '_label' => '友情链接名称', '_req' => true, '_tips' => '友情链接的网站名'))->add(QForm::ELEMENT, 'url', array('_ui' => 'textbox', '_label' => '网站地址', '_req' => true, '_tips' => '友情链接网站的网址'))->add(QForm::ELEMENT, 'link_id', array('_ui' => 'hidden'))->add(QForm::ELEMENT, 'img', array('_ui' => 'admin_picpreview', '_label' => '已上传图片', 'attr' => array('dir' => 'links')))->add(QForm::ELEMENT, 'ico', array('_ui' => 'upload', '_label' => '上传图标', '_tips' => ''))->add(QForm::ELEMENT, 'order_num', array('_ui' => 'textbox', '_label' => '排序', 'value' => 0));
     $form->addValidations(Links::meta());
     //上传图片的限制
     $types = Q::normalize(Q::ini('appini/teapics/upload_allowed_types'));
     $size = intval(Q::ini('appini/teapics/upload_allowed_size') * 1024);
     $dim = Q::ini('appini/teapics/img_pic_width') . 'x' . Q::ini('appini/teapics/img_pic_height');
     $form['ico']->_tips = sprintf($form['ico']->_tips, implode('/', $types), $size / 1024, $dim);
     $form->selectUploadElement('ico')->uploadAllowedSize($size)->uploadAllowedTypes($types)->enableSkipUpload();
     //表单验证规则
     return $form;
 }
Example #7
0
 /**
  * 从配置文件中创建表单
  * @param string $action     表单的url	
  * @param string $configName  配置文件的名字
  * @return Form_Tea $form
  */
 protected static function _createFormConfig($action, $configName)
 {
     $form = new Form_Admin_Tea('tea_form', $action);
     $filename = rtrim(dirname(__FILE__), '/\\') . DS . $configName;
     $form->loadFromConfig(Helper_YAML::load($filename));
     $form->addValidations(Tea::meta());
     //图片的路径
     $form['thumb_filename']->dir = Q::ini('appini/teapics/img_dir');
     //上传图片的限制
     $types = Q::normalize(Q::ini('appini/teapics/upload_allowed_types'));
     $size = intval(Q::ini('appini/teapics/upload_allowed_size') * 1024);
     $dim = Q::ini('appini/teapics/img_pic_width') . 'x' . Q::ini('appini/teapics/img_pic_height');
     $form['postfile']->_tips = sprintf($form['postfile']->_tips, implode('/', $types), $size / 1024, $dim);
     //        茶叶类别
     //       $teatype = new TeaType();
     //       $form['type_id']->items=$teatype->list;
     $form->selectUploadElement('postfile')->uploadAllowedSize($size)->uploadAllowedTypes($types)->enableSkipUpload();
     return $form;
 }
Example #8
0
 /**
  * 绑定行为插件
  */
 function bind()
 {
     $props = Q::normalize($this->_settings['assoc_props']);
     foreach ($props as $prop_name) {
         if (empty($this->_meta->props[$prop_name]) || !$this->_meta->props[$prop_name]['assoc']) {
             // LC_MSG: 类 "%s" 的 "%s" 属性不是一个关联.
             throw new QDB_ActiveRecord_Behavior_Exception(__('类 "%s" 的 "%s" 属性不是一个关联.', $this->_meta->class_name, $prop_name));
         }
         $assoc_type = $this->_meta->props[$prop_name]['assoc'];
         $suffix = $this->_meta->props[$prop_name]['assoc_class'];
         $arg = array($prop_name);
         if ($assoc_type == QDB::HAS_MANY) {
             $this->_addDynamicMethod("add{$suffix}", array($this, 'addRelated'), $arg);
         } elseif ($assoc_type == QDB::MANY_TO_MANY) {
             $this->_addDynamicMethod("bind{$suffix}", array($this, 'bindRelated'), $arg);
             $this->_addDynamicMethod("unbind{$suffix}", array($this, 'unbindRelated'), $arg);
             $this->_addDynamicMethod("unbindAll{$suffix}", array($this, 'unbindAllRelated'), $arg);
         }
     }
 }
 protected function _checkUniqueness(QDB_ActiveRecord_Abstract $obj, QDB_Cond $more_cond = null, $ignore_id = false)
 {
     $check_props = Q::normalize($this->_settings['check_props']);
     if (empty($check_props)) {
         return;
     }
     $checks = array();
     $error = array();
     foreach ($check_props as $check) {
         if ($ignore_id && $check == $obj->idname()) {
             continue;
         }
         if (strpos($check, '+') !== false) {
             $props = Q::normalize($check, '+');
             $cond = array();
             foreach ($props as $prop_name) {
                 $cond[$prop_name] = $obj->{$prop_name};
             }
         } else {
             $cond = array($check => $obj->{$check});
             $props = $check;
         }
         if (!is_null($more_cond)) {
             $cond[] = $more_cond;
         }
         $test = $this->_meta->find($cond)->count()->query();
         if ($test['row_count'] < 1) {
             continue;
         }
         if (isset($this->_settings['error_messages'][$check])) {
             $error[$check] = array($check => $this->_settings['error_messages'][$check]);
         } else {
             $error[$check] = array($check => "{$check} duplicated");
         }
     }
     if (!empty($error)) {
         throw new QDB_ActiveRecord_ValidateFailedException($error, $obj);
     }
 }
Example #10
0
 protected function _processMeta($meta, $allows_tags = null)
 {
     if ($allows_tags) {
         $allows_tags = Q::normalize($allows_tags);
     }
     $tags = preg_split('/^\\s*@/m', $meta, -1, PREG_SPLIT_NO_EMPTY);
     $arr = array();
     foreach ($tags as $tag) {
         $segs = preg_split('/\\s+/', trim($tag), 2);
         $tag_name = $segs[0];
         $param = isset($segs[1]) ? trim($segs[1]) : '';
         if ($allows_tags && !in_array($tag_name, $allows_tags)) {
             continue;
         }
         $tag_method = '_processTag' . ucfirst($tag_name);
         if (method_exists($this, $tag_method)) {
             $this->{$tag_method}($param);
         } elseif (property_exists($this, $tag_name)) {
             $this->{$tag_name} = $param;
         } else {
             throw new API_Doc_NotSupportedTagException($this, $tag_name);
         }
     }
 }
Example #11
0
 /**
  * 获得用户的 ACL 数据
  *
  * ACL 数据一般包含用户 ID 和用户名,通常用于配合 QACL 实现基于角色的访问控制。
  *
  * 用法:
  * @code php
  * $data = $member->aclData();
  * dump($data);
  * @endcode
  *
  * 要返回的数据由 acl_data_props 设置来指定。不过不管指定了哪些属性,aclData()
  * 的返回结果中总是为包含名为 id 的键。该键的值是用户对象的 ID。
  *
  * 也可以在获得 ACL 数据时通过 $props 参数指定要返回的属性值:
  * @code php
  * $data = $member->aclData('email, addr');
  * @endcode
  *
  * @param QDB_ActiveRecord_Abstract $member 用户对象
  * @param string $props 要返回的属性值
  *
  * @return array 包含指定属性值的数组
  */
 function aclDataDyn(QDB_ActiveRecord_Abstract $member, $props = null)
 {
     if (!$props) {
         $props = $this->_settings['acl_data_props'];
     }
     $props = Q::normalize($props);
     $data = array();
     foreach ($props as $pn) {
         $data[$pn] = $member[$pn];
     }
     $data['id'] = $member->id();
     return $data;
 }
Example #12
0
 /**
  * 对 ACL 整理,返回整理结果
  *
  * @param array $acl 要整理的 ACL
  *
  * @return array
  */
 function normalize(array $acl)
 {
     $acl = array_change_key_case($acl, CASE_LOWER);
     $ret = array();
     $keys = array('allow', 'deny');
     foreach ($keys as $key) {
         do {
             if (!isset($acl[$key])) {
                 $values = self::ACL_NULL;
                 break;
             }
             $acl[$key] = strtolower($acl[$key]);
             if ($acl[$key] == self::ACL_EVERYONE || $acl[$key] == self::ACL_HAS_ROLE || $acl[$key] == self::ACL_NO_ROLE || $acl[$key] == self::ACL_NULL) {
                 $values = $acl[$key];
                 break;
             }
             $values = Q::normalize($acl[$key]);
             if (empty($values)) {
                 $values = self::ACL_NULL;
             }
         } while (false);
         $ret[$key] = $values;
     }
     return $ret;
 }
Example #13
0
 /**
  * 将缓存的日志信息写入实际存储,并清空缓存
  */
 function flush()
 {
     if (empty($this->_log)) {
         return;
     }
     // 更新日志记录优先级
     $keys = Q::normalize(Q::ini('log_priorities'));
     $arr = array();
     foreach ($keys as $key) {
         if (!isset($this->_priorities[$key])) {
             continue;
         }
         $arr[$key] = true;
     }
     $this->_priorities = $arr;
     // 确定日志写入目录
     $dir = realpath(Q::ini('log_writer_dir'));
     if ($dir === false || empty($dir)) {
         $dir = realpath(Q::ini('runtime_cache_dir'));
         if ($dir === false || empty($dir)) {
             // LC_MSG: 指定的日志文件保存目录不存在 "%s".
             if ($this->_destruct) {
                 return;
             } else {
                 throw new QLog_Exception(__('指定的日志文件保存目录不存在 "%s".', Q::ini('log_writer_dir')));
             }
         }
     }
     $filename = Q::ini('log_writer_filename');
     $this->_filename = rtrim($dir, '/\\') . DS . $filename;
     //if(is_file($this->_filename))
     //unlink($this->_filename);
     $chunk_size = intval(Q::ini('log_cache_chunk_size'));
     if ($chunk_size < 1) {
         $chunk_size = 64;
     }
     $this->_cache_chunk_size = $chunk_size * 1024;
     $this->_writeable = true;
     // 写入日志
     $string = '';
     foreach ($this->_log as $offset => $item) {
         list($time, $msg, $type) = $item;
         unset($this->_log[$offset]);
         // 过滤掉不需要的日志条目
         if (!isset($this->_priorities[$type])) {
             continue;
         }
         $string .= date('c', $time) . " {$type}: {$msg}\n";
     }
     if ($string) {
         $fp = fopen($this->_filename, 'a');
         if ($fp && flock($fp, LOCK_EX)) {
             fwrite($fp, $string);
             flock($fp, LOCK_UN);
             fclose($fp);
         }
     }
     //unset($this->_log);
     $this->_log = array();
     $this->_cached_size = 0;
 }
Example #14
0
 /**
  * 删除多个属性
  *
  * @param string|array $props
  *
  * @return QForm_Element
  */
 function unsetProps($props)
 {
     $props = Q::normalize($props);
     foreach ($props as $prop) {
         unset($this->_props[$prop]);
     }
     if (in_array('value', $props)) {
         $this->setValue(null);
     }
     return $this;
 }
Example #15
0
 /**
  * 第一步初始化
  *
  * @param string $class
  */
 protected function _init1($class)
 {
     // 从指定类获得初步的定义信息
     Q::loadClass($class);
     $this->class_name = $class;
     $ref = (array) call_user_func(array($class, '__define'));
     /**
      * 检查是否是继承
      */
     if (!empty($ref['inherit'])) {
         $this->inherit_base_class = $ref['inherit'];
         /**
          * 继承类的 __define() 方法只需要指定与父类不同的内容
          */
         $base_ref = (array) call_user_func(array($this->inherit_base_class, '__define'));
         $ref = array_merge_recursive($base_ref, $ref);
     }
     // 被继承的类
     $this->inherit_type_field = !empty($ref['inherit_type_field']) ? $ref['inherit_type_field'] : null;
     // 设置表数据入口对象
     $table_config = !empty($ref['table_config']) ? (array) $ref['table_config'] : array();
     if (!empty($ref['table_class'])) {
         $this->table = $this->_tableByClass($ref['table_class'], $table_config);
     } else {
         $this->table = $this->_tableByName($ref['table_name'], $table_config);
     }
     $this->table_meta = $this->table->columns();
     // 根据字段定义确定字段属性
     if (empty($ref['props']) || !is_array($ref['props'])) {
         $ref['props'] = array();
     }
     foreach ($ref['props'] as $prop_name => $config) {
         $this->addProp($prop_name, $config);
     }
     // 将没有指定的字段也设置为对象属性
     foreach ($this->table_meta as $prop_name => $field) {
         if (isset($this->props2fields[$prop_name])) {
             continue;
         }
         $this->addProp($prop_name, $field);
     }
     // 设置其他选项
     if (!empty($ref['create_reject'])) {
         $this->create_reject = array_flip(Q::normalize($ref['create_reject']));
     }
     if (!empty($ref['update_reject'])) {
         $this->update_reject = array_flip(Q::normalize($ref['update_reject']));
     }
     if (!empty($ref['create_autofill']) && is_array($ref['create_autofill'])) {
         $this->create_autofill = $ref['create_autofill'];
     }
     if (!empty($ref['update_autofill']) && is_array($ref['update_autofill'])) {
         $this->update_autofill = $ref['update_autofill'];
     }
     if (!empty($ref['attr_accessible'])) {
         $this->attr_accessible = array_flip(Q::normalize($ref['attr_accessible']));
     }
     if (!empty($ref['attr_protected'])) {
         $this->attr_protected = array_flip(Q::normalize($ref['attr_protected']));
     }
     // 准备验证规则
     if (empty($ref['validations']) || !is_array($ref['validations'])) {
         $ref['validations'] = array();
     }
     $this->validations = $this->_prepareValidationRules($ref['validations']);
     // 设置对象 ID 属性名
     $pk = $this->table->getPK();
     $this->idname = array();
     foreach ($this->table->getPK() as $pk) {
         $pn = $this->fields2props[$pk];
         $this->idname[$pn] = $pn;
     }
     $this->idname_count = count($this->idname);
     // 绑定行为插件
     if (isset($ref['behaviors'])) {
         $config = isset($ref['behaviors_settings']) ? $ref['behaviors_settings'] : array();
         $this->bindBehaviors($ref['behaviors'], $config);
     }
 }
Example #16
0
 function excludes($excludes)
 {
     $this->_excludes = Q::normalize($excludes);
     return $this;
 }
Example #17
0
 /**
  * 获得多个完全限定名
  *
  * @param array|string $names
  * @param string $as
  *
  * @return array
  */
 function qids($names, $as = null)
 {
     $arr = array();
     $names = Q::normalize($names);
     foreach ($names as $alias => $name) {
         if (!is_string($alias)) {
             $alias = null;
         }
         $arr[] = $this->qid($name, $alias, $as);
     }
     return $arr;
 }
Example #18
0
 /**
  * 查询,并返回对象或对象集合
  *
  * @return QDB_ActiveRecord_Association_Coll|QDB_ActiveRecord_Abstract
  */
 protected function _queryObjects()
 {
     /**
      * 执行查询,获得一个查询句柄
      *
      * $this->_query_params[self::USED_LINKS] 是查询涉及到的关联(关联别名 => 关联对象)
      */
     $handle = $this->getQueryHandle();
     /* @var $handle QDB_Result_Abstract */
     $class_name = $this->_meta->class_name;
     $rowset = array();
     $this->_query_params[self::USED_LINKS] = $this->_query_params[self::USED_LINKS];
     $no_lazy_query = Q::normalize($this->_query_params[self::NON_LAZY_QUERY]);
     while ($row = $handle->fetchRow()) {
         $obj = new $class_name($row, QDB::FIELD, true);
         foreach ($no_lazy_query as $assoc) {
             $obj->{$assoc};
         }
         $rowset[] = $obj;
     }
     if (empty($rowset)) {
         // 没有查询到数据时,返回 Null 对象或空集合
         if (!$this->_parts[self::LIMIT_QUERY]) {
             return $this->_meta->newObject();
         } else {
             if ($this->_query_params[self::AS_COLL]) {
                 return new QDB_ActiveRecord_Association_Coll($this->_meta->class_name);
             } else {
                 return array();
             }
         }
     }
     if (!$this->_parts[self::LIMIT_QUERY]) {
         // 创建一个单独的对象
         return reset($rowset);
     } else {
         if ($this->_query_params[self::AS_COLL]) {
             return QDB_ActiveRecord_Association_Coll::createFromArray($rowset, $class_name);
         } else {
             return $rowset;
         }
     }
 }
Example #19
0
 /**
  * 检查唯一性
  *
  * @param QDB_ActiveRecord_Abstract $obj
  * @param QDB_Cond $more_cond
  * @param boolean $ignore_id
  */
 private function _checkUniqueness(QDB_ActiveRecord_Abstract $obj, QDB_Cond $more_cond = null, $ignore_id = false)
 {
     $check_props = Q::normalize($this->_settings['check_props']);
     if (empty($check_props)) {
         return;
     }
     $failed = array();
     foreach ($check_props as $check) {
         // 如果忽略主键字段,而要检查的属性正好是主键字段,则跳过检查
         if ($ignore_id && in_array($check, $this->_meta->idname)) {
             continue;
         }
         if (strpos($check, '+') !== false) {
             $check = Q::normalize($check, '+');
         } else {
             $check = array($check);
         }
         $cond = array();
         $skip_valid = false;
         // FIXED! 标注是否跳过验证
         foreach ($check as $offset => $prop_name) {
             if (substr($prop_name, -1, 1) == '?') {
                 $prop_name = substr($prop_name, 0, -1);
                 $value = $obj[$prop_name];
                 if (strlen($value) == 0) {
                     $skip_valid = true;
                     continue;
                 }
                 $check[$offset] = $prop_name;
             } else {
                 $value = $obj[$prop_name];
             }
             if (is_object($value)) {
                 $value = $value->id();
                 if (is_array($value)) {
                     foreach ($value as $p => $v) {
                         $cond[$p] = $v;
                     }
                 } else {
                     $cond[$obj[$prop_name]->idname()] = $value;
                 }
             } else {
                 $cond[$prop_name] = $value;
             }
         }
         if ($skip_valid) {
             continue;
         }
         if (!is_null($more_cond)) {
             $cond[] = $more_cond;
         }
         if ($this->_meta->find($cond)->getCount() < 1) {
             continue;
         }
         // 验证失败,保存错误消息
         $check = implode('+', $check);
         if (isset($this->_settings['error_messages'][$check])) {
             $failed[$check] = $this->_settings['error_messages'][$check];
         } else {
             $failed[$check] = "{$check} duplicated";
         }
     }
     if (!empty($failed)) {
         throw new QDB_ActiveRecord_ValidateFailedException($failed, $obj);
     }
 }
Example #20
0
 /**
  * 检查指定角色是否有权限访问特定的控制器和动作
  *
  * @param array $roles
  * @param string|array $udi
  *
  * @return boolean
  */
 function authorizedUDI($roles, $udi)
 {
     /**
      * 将 UDI 封装为一个资源
      * 读取控制器的 ACL(访问控制列表)
      * 通过 QACL 组件进行权限检查
      */
     $roles = Q::normalize($roles);
     $udi = QContext::instance()->normalizeUDI($udi);
     $controller_acl = $this->controllerACL($udi);
     // 首先检查动作 ACT
     $acl = Q::singleton('QACL');
     $action_name = strtolower($udi[QContext::UDI_ACTION]);
     if (isset($controller_acl['actions'][$action_name])) {
         // 如果动作的 ACT 检验通过,则忽略控制器的 ACT
         return $acl->rolesBasedCheck($roles, $controller_acl['actions'][$action_name]);
     }
     if (isset($controller_acl['actions'][QACL::ALL_ACTIONS])) {
         // 如果为所有动作指定了默认 ACT,则使用该 ACT 进行检查
         return $acl->rolesBasedCheck($roles, $controller_acl['actions'][QACL::ALL_ACTIONS]);
     }
     // 否则检查是否可以访问指定控制器
     return $acl->rolesBasedCheck($roles, $controller_acl);
 }
Example #21
0
 /**
  * 检查上传的文件是否成功上传,并符合检查条件(文件类型、最大尺寸)
  *
  * 文件类型以扩展名为准,多个扩展名以 , 分割,例如 “jpg, jpeg, png。”。
  *
  * 用法:
  * @code
  * // 检查文件类型和大小
  * if ($file->isValid('jpg, jpeg, png', 2048 * 1024))
  * {
  *     ....
  * }
  * @endcode
  *
  * @param string $allowed_types 允许的扩展名
  * @param int $max_size 允许的最大上传字节数
  *
  * @return boolean 是否检查通过
  */
 function isValid($allowed_types = null, $max_size = null)
 {
     if (!$this->isSuccessed()) {
         return false;
     }
     if ($allowed_types) {
         $allowed_types = Q::normalize($allowed_types);
         foreach ($allowed_types as $offset => $extname) {
             if ($extname[0] == '.') {
                 $extname = substr($extname, 1);
             }
             $allowed_types[$offset] = strtolower($extname);
         }
         $allowed_types = array_flip($allowed_types);
         // when upload filename is chinese, basename() only return extension name, it will be make mistake follow step
         //$filename = strtolower(basename($this->filename()));
         $filename = $this->filename();
         // jerry2801
         $extnames = Q::normalize($filename, '.');
         array_shift($extnames);
         $passed = false;
         for ($i = count($extnames) - 1; $i >= 0; $i--) {
             $checking_ext = implode('.', array_slice($extnames, $i));
             if (isset($allowed_types[$checking_ext])) {
                 $passed = true;
                 break;
             }
         }
         if (!$passed) {
             return false;
         }
     }
     if ($max_size > 0 && $this->filesize() > $max_size) {
         return false;
     }
     return true;
 }
Example #22
0
 /**
  * 在指定目录及其子目录中查找文件
  *
  * 用法:
  * @code php
  * $files = Helper_FileSys::findFiles($dir, array(
  *     // 只查找扩展名为 .jpg, .jpeg, .png 和 .gif 的文件
  *     'extnames' => 'jpg, jpeg, png, gif',
  *     // 排除 .svn 目录和 upload/avatars 目录
  *     'excludes' => '.svn, upload/avatars',
  *     // 只查找 2 层子目录
  *     'level'    => 2,
  * ));
  * @endcode
  *
  * findFiles() 的 $options 参数支持下列选项:
  *
  * -  extnames: 字符串或数组,指定查找文件时有效的文件扩展名。
  *    如果不指定该参数,则查找所有扩展名的文件。
  *
  * -  excludes: 字符串或数组,指定查找文件时要排除的目录或文件。
  *    "upload/avatars" 表示排除 "$dir/upload/avatars" 目录。
  *
  * -  levels: 整数,指定查找的目录深度,默认为 -1。
  *    如果为 0 表示不查找子目录。
  *
  * findFiles() 返回一个数组,包含了排序后的文件完整路径。
  *
  * @param string|array $dir 要查找文件的目录
  * @param array $options 查找选项
  *
  * @return array 包含有效文件名的数组
  */
 static function findFiles($dir, $options = array())
 {
     $extnames = !empty($options['extnames']) ? Q::normalize($options['extnames']) : array();
     foreach ($extnames as $offset => $extname) {
         if ($extname[0] == '.') {
             $extnames[$offset] = substr($extname, 1);
         }
     }
     $excludes = !empty($options['excludes']) ? Q::normalize($options['excludes']) : array();
     $level = isset($options['level']) ? intval($options['level']) : -1;
     $list = self::_findFilesRecursive($dir, '', $extnames, $excludes, $level);
     sort($list);
     return $list;
 }
Example #23
0
 /**
  * 指示群组的数据为无效状态
  *
  * @param mixed $error
  *
  * @return QForm_Group
  */
 function invalidate($error = null)
 {
     if (empty($error)) {
         return $this;
     }
     if ($error instanceof QValidator_ValidateFailedException) {
         $errors = $error->validate_errors;
     } elseif (!is_array($error)) {
         $keys = Q::normalize($error);
         $errors = array();
         foreach ($keys as $key) {
             $errors[$key] = '';
         }
     } else {
         $errors = $error;
     }
     foreach ($errors as $id => $msg) {
         if ($this->existsElement($id)) {
             $this->element($id)->invalidate($msg);
         }
     }
     return $this;
 }
Example #24
0
 /**
  * 清除所有属性或指定的“脏”状态
  *
  * @param string|array $props
  *
  * @return QDB_ActiveRecord_Abstract 连贯接口
  */
 function cleanChanges($props = null)
 {
     if ($props) {
         $props = Q::normalize($props);
         foreach ($props as $prop) {
             unset($this->_changed_props[$prop]);
         }
     } else {
         $this->_changed_props = array();
     }
     return $this;
 }
Example #25
0
 /**
  * 构造 url
  *
  * 用法:
  *
  * @code php
  * url(UDI, [附加参数数组], [路由名])
  * @endcode
  *
  * UDI 是统一目的地标识符(Uniform Destination Identifier)的缩写。
  * UDI 由控制器、动作、名字空间以及模块名组成,采用如下的格式:
  *
  * @code php
  * ns::controller/action@module
  * @endcode
  *
  * UDI 字符串中,每一个部分都是可选的。
  * 如果没有提供控制器和动作名,则使用当前的控制器和默认动作名(index)代替。
  * 同样,如果未提供模块名和名字空间,均使用当前值代替。
  *
  * UDI 字符串写法示例:
  *
  * @code php
  * 'controller'
  * 'controller/action'
  * '/action'
  * 'controller@module'
  * 'controller/action@module'
  * 'ns::controller'
  * 'ns::controller/action'
  * 'ns::controller@module'
  * 'ns::controller/action@module'
  * '@module'
  * 'ns::@module'
  * @endcode
  *
  * 示例:
  * @code php
  * url('admin::posts/edit', array('id' => $post->id()));
  * @endcode
  *
  * $params 参数除了采用数组,还可以是以“/”符号分割的字符串:
  *
  * @code php
  * url('posts/index', 'page/3');
  * url('users/show', 'id/5/profile/yes');
  * @endcode
  *
  * 在使用 PATHINFO 和 URL 重写时,可以使用通过制定路由名来强制要求 QeePHP
  * 采用指定的路由规则来生成 URL。强制指定路由规则可以加快 URL 的生成,
  * 但在路由规则名称发生变化时,需要修改生成 URL 的代码。
  *
  * $opts 参数用于控制如何生成 URL。可用的选项有:
  *
  * -  base_uri: 指定 URL 前部要添加的路径(可以包括协议、域名和端口,以及路径)
  * -  script: 指定 URL 前部要使用的脚本名
  * -  mode: 指定 URL 生成模式,可以是 standard、pathinfo 和 rewrite
  *
  * @param string $udi UDI 字符串
  * @param array|string $params 附加参数数组
  * @param string $route_name 路由名
  * @param array $opts 控制如何生成 URL 的选项
  *
  * @return string 生成的 URL 地址
  */
 function url($udi, $params = null, $route_name = null, array $opts = null)
 {
     static $base_uri;
     if (is_null($base_uri)) {
         if (strlen(Q::ini('base_uri')) > 0) {
             $base_uri = Q::ini('base_uri');
         } else {
             $base_uri = '/' . trim($this->baseDir(), '/');
             if ($base_uri != '/') {
                 $base_uri .= '/';
             }
         }
     }
     $udi = $this->normalizeUDI($udi);
     if (!is_array($params)) {
         $arr = Q::normalize($params, '/');
         $params = array();
         while ($key = array_shift($arr)) {
             $value = array_shift($arr);
             $params[$key] = $value;
         }
     }
     $params = array_filter($params, 'strlen');
     // 处理 $opts
     if (is_array($opts)) {
         $mode = !empty($opts['mode']) ? $opts['mode'] : self::$_url_mode;
         $script = !empty($opts['script']) ? $opts['script'] : $this->scriptName();
         $url = strlen($opts['base_uri']) > 0 ? rtrim($opts['base_uri'], '/') . '/' : $base_uri;
     } else {
         $mode = self::$_url_mode;
         $url = $base_uri;
         $script = $this->scriptName();
     }
     if (!is_null($this->_router) && $mode != self::URL_MODE_STANDARD) {
         // 使用路由生成 URL
         $params = array_merge($params, $udi);
         $path = $this->_router->url($params, $route_name);
         if (self::$_url_mode == self::URL_MODE_PATHINFO && $path != '/') {
             $url .= $this->scriptName();
         } else {
             $url = rtrim($url, '/');
         }
         $url .= $path;
     } else {
         foreach (self::$_udi_defaults as $key => $value) {
             if ($udi[$key] == $value) {
                 unset($udi[$key]);
             }
             unset($params[$key]);
         }
         $params = array_filter(array_merge($udi, $params), 'strlen');
         $url .= $script;
         if (!empty($params)) {
             $url .= '?' . http_build_query($params, '', '&');
         }
     }
     return $url;
 }
Example #26
0
 function testFindHasMany()
 {
     $tableAuthors = Q::singleton('Table_Authors');
     /* @var $tableAuthors Table_Authors */
     $tableAuthors->getConn()->startTrans();
     // $tableAuthors->disableLinks('books');
     $authors = $this->insertAuthors();
     $contents = $this->insertContents($authors);
     $this->insertComments($authors, $contents);
     $author = $tableAuthors->find($authors['liaoyulei'])->query();
     $tableAuthors->getConn()->completeTrans(false);
     $this->assertTrue(!empty($author['contents']), "!empty(\$author['contents'])");
     $this->assertType('array', $author['contents'], "type of \$author['contents'] == array");
     $first = reset($author['contents']);
     $this->assertType('array', $first, "reset(\$author['contents']) == array");
     $this->assertTrue(!empty($first['title']), "!empty(reset(\$author['contents']['title']))");
     $link_contents = $tableAuthors->getLink('contents');
     $on_find_keys = Q::normalize($link_contents->on_find_keys);
     $this->assertEquals(count($on_find_keys), count($first), "count(\$first) == 1");
     if (is_int($link_contents->on_find)) {
         $this->assertEquals($link_contents->on_find, count($author['contents']), "count(\$author['contents']) == " . $link_contents->on_find);
     }
     $first = reset($author['contents']);
     $next = next($author['contents']);
     $this->assertTrue($first['content_id'] < $next['content_id'], "\$first['content_id'] < \$next['content_id']");
 }
Example #27
0
 /**
  * @dataProvider processDataProvider
  */
 function testProcessData($test_failed, $post, $values)
 {
     $forms = array(Form_Data::createDirect(), Form_Data::createFromConfig());
     $test_failed = Q::normalize($test_failed);
     foreach ($forms as $form) {
         $this->assertTrue(isset($form['name']), 'element "name" not exists.');
         $this->assertTrue(isset($form['price']), 'element "price" not exists.');
         /* @var $form Form_Data */
         $failed = null;
         $ret = $form->validate($post, $failed);
         $this->assertEquals($ret, $form->isValid());
         $this->assertEquals($values, $form->values());
         $this->assertEquals($values, $form->value());
         $this->assertEquals($post, $form->unfilteredValues());
         $this->assertEquals($post, $form->unfilteredValue());
         if (empty($test_failed)) {
             $this->assertTrue($ret);
         } else {
             foreach ($failed as $id => $errors) {
                 $this->assertEquals(false, $form[$id]->isValid());
                 $this->assertEquals($errors, $form[$id]->errorMsg());
             }
             $failed = array_keys($failed);
             $this->assertEquals($test_failed, $failed);
         }
     }
 }
 /**
  * 构造控件的属性字符串
  *
  * @param array|string $exclude
  *
  * @return string
  */
 protected function _printAttrs($exclude = 'id, name, value')
 {
     $exclude = Q::normalize($exclude);
     $exclude = array_flip($exclude);
     $out = '';
     foreach ($this->_attrs as $attr => $value) {
         if (isset($exclude[$attr])) {
             continue;
         }
         $out .= $attr . '="' . htmlspecialchars($value) . '" ';
     }
     return $out;
 }
Example #29
0
 /**
  * 将指定的属性设置为“脏”状态
  *
  * @param string|array $props_name
  *
  * @return QDB_ActiveRecord_Abstract
  *   返回 ActiveRecord 本身,实现连贯接口
  */
 function willChanged($props_name)
 {
     $props_name = Q::normalize($props_name);
     foreach ($props_name as $prop_name) {
         if (!isset(self::$_meta[$this->_class_name]->props[$prop_name])) {
             continue;
         }
         $this->_changed_props[$prop_name] = $prop_name;
     }
     return $this;
 }
Example #30
0
 /**
  * 添加到内部的数据表->字段名映射数组
  *
  * @param string $table_name
  * @param array|string|QDB_Expr $cols
  */
 protected function _addCols($table_name, $cols)
 {
     $cols = Q::normalize($cols);
     if (is_null($table_name)) {
         $table_name = '';
     }
     $m = null;
     foreach ($cols as $alias => $col) {
         if (is_string($col)) {
             // 将包含多个字段的字符串打散
             foreach (Q::normalize($col) as $col) {
                 $current_table_name = $table_name;
                 // 检查是不是 "字段名 AS 别名"这样的形式
                 if (preg_match('/^(.+)\\s+' . self::SQL_AS . '\\s+(.+)$/i', $col, $m)) {
                     $col = $m[1];
                     $alias = $m[2];
                 }
                 // 检查字段名是否包含表名称
                 if (preg_match('/(.+)\\.(.+)/', $col, $m)) {
                     $current_table_name = $m[1];
                     $col = $m[2];
                 }
                 if (isset($this->_columns_mapping[$col])) {
                     $col = $this->_columns_mapping[$col];
                 }
                 $this->_parts[self::COLUMNS][] = array($current_table_name, $col, is_string($alias) ? $alias : null);
             }
         } else {
             $this->_parts[self::COLUMNS][] = array($table_name, $col, is_string($alias) ? $alias : null);
         }
     }
 }