master
yulingwei 5 years ago
commit 26d0d0d6cb

@ -0,0 +1,22 @@
{
// 使 IntelliSense
//
// 访: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "Listen for XDebug",
"type": "php",
"request": "launch",
"port": 9000
},
{
"name": "Launch currently open script",
"type": "php",
"request": "launch",
"program": "${file}",
"cwd": "${fileDirname}",
"port": 9000
}
]
}

@ -0,0 +1,286 @@
<?php
// +----------------------------------------------------------------------
// | OneThink [ WE CAN DO IT JUST THINK IT ]
// +----------------------------------------------------------------------
// | Copyright (c) 2013 http://www.onethink.cn All rights reserved.
// +----------------------------------------------------------------------
// | Author: 麦当苗儿 <zuojiazi@vip.qq.com> <http://www.zjzit.cn>
// +----------------------------------------------------------------------
namespace Admin\Controller;
use User\Api\UserApi as UserApi;
/**
* 后台首页控制器
* @author 麦当苗儿 <zuojiazi@vip.qq.com>
*/
class IndexChartSetController extends AdminController {
public $beginTime;
public $endTime;
public $date;
public $nowdata;
public $UserModel;
public $ChartModel;
public $LoginModel;
public $SpendModel;
public $PromoteModel;
public $addid;
public $adddata;
public $reset=false;
public function _initialize(){
//初始化
$this->UserModel =M("User","tab_");
$this->ChartModel =M("IndexChart","tab_");
$this->LoginModel =M("user_login_record","tab_");
$this->SpendModel =M("spend","tab_");
$this->PromoteModel =M("promote","tab_");
$this->nowdata =time();
if(I("reset")) $this->reset = true;
}
/**
* 每日更新接口
*/
public function setChartCount()
{
$begin = date("Y-m-d",strtotime("-1 day"));
$this->setDateCount($begin);
}
public function setFreeDateCount($begin,$end='')
{
if($end == '') $end = $begin;
//判断日期格式
$patten = "/^\d{4}[\-](0?[1-9]|1[012])[\-](0?[1-9]|[12][0-9]|3[01])$/";
if (!preg_match($patten, $begin)) {
die("开始时间格式错误");
}
if (!preg_match($patten, $end)) {
die("结束时间格式错误");
}
if(strtotime($end) < strtotime($begin)){
die("结束时间不能比开始时间小");
}
if(strtotime($end)+86399 > time()){
die("结束时间不能包含今日");
}
if($begin == $end){
$this->setDateCount($begin);
}else{
$starttime = $begin?strtotime($begin):mktime(0,0,0,date('m'),date('d')-1,date('Y'));
$endtime = $end?strtotime($end)+86399:$starttime+86399;
$datelist = get_date_list($starttime,$endtime,1);
$countdate = count($datelist);
for($i=0;$i<$countdate;$i++){
$this->setDateCount($datelist[$i]);
}
}
}
//
public function setDateCount($date)
{
$this->date = $date;
$tarry = explode('-',$date);
$this->beginTime=mktime(0,0,0,$tarry[1],$tarry[2],$tarry[0]);
$this->endTime=mktime(0,0,0,$tarry[1],$tarry[2]-0+1,$tarry[0])-1;
set_time_limit(0);
$t1 = microtime(true);
//判断是否存在
$res = $this->ChartModel->where("date = '{$this->beginTime}'")->find();
$reset='';
if(!empty($res)){
if($this->reset){
$this->ChartModel->where("date = '{$this->beginTime}'")->delete();
$reset = "reset and creat ";
}else{
echo ("{$this->date} 已统计,请勿重复 ".PHP_EOL);
return;
}
}
$this->newUser();
$this->activeUser();
$this->payUser();
$this->payMoney();
$this->promoteNew();
$this->allCount();
$this->createDb();
$t2 = microtime(true);
echo ("{$this->date} {$reset}success runtime:".round($t2-$t1,3).'s'.PHP_EOL);
# code...
}
//获取每日的增长用户
public function newUser()
{
$map = ['register_time'=>['between',[$this->beginTime,$this->endTime]],"puid"=>0];//0不是小号
$hoursnews = $this->UserModel->field('FROM_UNIXTIME(register_time, "%H") as time,COUNT(1) AS news')
->where($map)
->group("time")
->select();
$hours = ['00','01','02','03','04','05','06','07','08','09','10','11','12','13','14','15','16','17','18','19','20','21','22','23'];
$user_hours = array();
foreach($hours as $v) {
$user_hours[$v] = 0;
}
foreach($hoursnews as $h) {
$user_hours[$h['time']] = (integer)$h['news'];
}
$this->adddata["new_user_hours"] = serialize($user_hours);
unset($user_hours);
//获取当日所有的注册用户
$userList = $this->UserModel->field('count(1) count')
->where($map)
->find();
$this->adddata["new_user_count"] = $userList['count'];
}
/**
* 活跃用户计算
*/
public function activeUser()
{
$map = ['login_time'=>['between',[$this->beginTime,$this->endTime]]];//0不是小号
$hoursnews = $this->LoginModel->field('FROM_UNIXTIME(login_time, "%H") as time,COUNT(DISTINCT user_id) AS active')
->where($map)
->group("time")
->select();
$hours = ['00','01','02','03','04','05','06','07','08','09','10','11','12','13','14','15','16','17','18','19','20','21','22','23'];
$user_hours = array();
foreach($hours as $v) {
$user_hours[$v] = 0;
}
foreach($hoursnews as $h) {
$user_hours[$h['time']] = (integer)$h['active'];
}
$this->adddata["active_user_hours"] = serialize($user_hours);
unset($user_hours);
//获取活跃用户列表
$activeCount = $this->LoginModel->field('user_id')
->where($map)
->group('user_id')
->select();
$this->adddata["active_user_count"] = count($activeCount);
$this->adddata["active_user_list"] = serialize(array_column($activeCount,'user_id'));
unset($activeCount);
}
/**
* 计算充值用户
*/
public function payUser()
{
$map = ['pay_time'=>['between',[$this->beginTime,$this->endTime]],'pay_status'=>1];//1支付成功
$hoursnews = $this->SpendModel->field('FROM_UNIXTIME(pay_time, "%H") as time,COUNT(DISTINCT user_id) AS payuser')
->where($map)
->group("time")
->select();
$hours = ['00','01','02','03','04','05','06','07','08','09','10','11','12','13','14','15','16','17','18','19','20','21','22','23'];
$user_hours = array();
foreach($hours as $v) {
$user_hours[$v] = 0;
}
foreach($hoursnews as $h) {
$user_hours[$h['time']] = (integer)$h['payuser'];
}
$this->adddata["pay_user_hours"] = serialize($user_hours);
unset($user_hours);
$activeCount = $this->SpendModel->field('user_id')
->where($map)
->group('user_id')
->select();
$this->adddata["pay_user_count"] = count($activeCount);
$this->adddata["pay_user_list"] = serialize(array_column($activeCount,'user_id'));
unset($activeCount);
}
/**
* 充值金额计算
*/
public function payMoney()
{
$map = ['pay_time'=>['between',[$this->beginTime,$this->endTime]],"pay_status"=>1];//1支付成功
$hoursnews = $this->SpendModel->field('FROM_UNIXTIME(pay_time, "%H") as time,sum(pay_amount) AS money')
->where($map)
->group("time")
->select();
$hours = ['00','01','02','03','04','05','06','07','08','09','10','11','12','13','14','15','16','17','18','19','20','21','22','23'];
$user_hours = array();
foreach($hours as $v) {
$user_hours[$v] = 0;
}
foreach($hoursnews as $h) {
$user_hours[$h['time']] = (integer)$h['money'];
}
$this->adddata["pay_money_hours"] = serialize($user_hours);
unset($user_hours);
$activeCount = $this->SpendModel->field('sum(pay_amount) AS money')
->where($map)
->find();
$this->adddata["pay_money_count"] = $activeCount['money']?:0;
}
/**
* 新增推广
*/
public function promoteNew()
{
$map = ['create_time'=>['between',[$this->beginTime,$this->endTime]]];
$hoursnews = $this->PromoteModel->field('FROM_UNIXTIME(create_time, "%H") as time,COUNT(1) AS news')
->where($map)
->group("time")
->select();
$hours = ['00','01','02','03','04','05','06','07','08','09','10','11','12','13','14','15','16','17','18','19','20','21','22','23'];
$user_hours = array();
foreach($hours as $v) {
$user_hours[$v] = 0;
}
foreach($hoursnews as $h) {
$user_hours[$h['time']] = (integer)$h['news'];
}
$this->adddata["promote_new_hours"] = serialize($user_hours);//promote_new_hours
unset($user_hours);
$activeCount = $this->PromoteModel->field('COUNT(1) AS news')
->where($map)
->find();
$this->adddata["promote_new_count"] = $activeCount['news'];
}
/**
* 统计其他综合信息
* 1. 7天活跃
* 2. 平台累计用户
* 3. 累计付费用户
*/
public function allCount()
{
$user = D('User');
$spend = D('Spend');
$promote = D('Promote');
$allcount = array();
$allcount['user_count'] = $user->old();
$allcount['active_count'] =$user->active(['tab_user_login_record.login_time'=>['between',[mktime(0,0,0,date('m'),date('d')-7,date('Y')),mktime(0,0,0,date('m'),date('d'),date('Y'))-1]]]);
$allcount['player_count'] =$spend->player();
$allcount['money_sum'] =$spend->totalAmount();
$allcount['promote_sum'] =$promote->total();
$this->adddata["all_count"] = serialize($allcount);
}
public function createDb()
{
$this->adddata['date']=$this->beginTime;
$this->adddata['create_time']=$this->nowdata;
$this->ChartModel->add($this->adddata);
}
}

@ -16,20 +16,13 @@ use Base\Repository\UserRepository;
* @author 麦当苗儿 <zuojiazi@vip.qq.com>
*/
class IndexController extends AdminController {
public function test()
{
$content = 'MDAwMDAwMDAwMJndsKKZZYuXeqCgy324cpebidDdi6mplZy2vKCFdqeagKewp5CKas6JaJ3Nec6fnYWvzM59qK2im5OfZZGrq2d9zqeig3aD0IqNYs6IlnarmnzR0HrP0puGt7B2hqysdoLe0n-FeIKUfnqCl33edZ2DeK_VlJacnJvPvJycebiXlpewpJGLg9eVjWLOk815aoCfqs59qK2skrqwZpKKrJeW0aytkYaCmHqfetV50oaukY2vy5K8tJuHy69nhXWrpH3StKSYZHKUi4573JG7aamAn9TOfs6spYHQuKScedqdfc7VopBlctZ9pJnSipeGrpF82NqVrbmlmpSbopGfqKeOq6yvj2Sxk3-NhtqKqqhlha-ymYrR22OG3L9ohnjaYoKWvKKFZLGTf32Gln-3mJebiczei8_PlZy2v2eHibCUmLjJsoV3oNJ6n6jLiZZpn5GIrpt6z6ibhKWwq5ufzpuOt69vhHZt2X6JqMuJ0oKpkGee2JOYrJuHy6-thYmrqY67r6KDdoPcimiZzpK7hZ2Gnq-Zi5ilpZG6uKGaZayll5a4q4CcsMuLaHfWirppq5l8q5qLva2Yms-sqJKFq2d9za-sgKBqzX-MatyRu5SpgJ_Uzn-svZyRz79phpyknI64p2mRnZyXio2G3H2onKGRn8nQgLy8qYXPv6uGrKeagKewpZx7i86To4LLf816rpGNr5eLva18kqaWrp56uKuOvLCDkXdp2n56dtqT3n6rhZ-mmYC5vWqbqrCqknq4m5ip0qSHh37bfoqGlH7ehWiFr77dgKispYHPrJ6RZJtiltK3ooacg5KLjn-Sfbh5roV5upd6ztqbkpSsqJKIm6aNu5elgJ2oy4l-hpOKuHafj326mH7fy5uQqrtnhpzJYYysu2yRioKViX6Gkoq4l2mCe92WgKmtn4e43mWGnMVmjZXeaoWtgpKAeZzLfKd6pJlos8uV0rmrm5TSqpqbq2d9zquuhHZt2XqfqMuTq3Zpj2ee3ousuauQlJtlmomsnZfNr2-An4ezibB62X24m6uGiaaVfrnGqYWmq2iPnLB3jt2vrIChe8qWjGrclKt2ZJuNss6Az6SlgdConJ2Im2SNvNGihp2c1Xqkf9mKu2Wfj2fR3HrP0puGttGphoa7poG4p66FrYrLl4dunw';
$request=json_decode(think_decrypt($content),true);
var_dump($request);
}
/**
/**
* 后台首页
* @author 麦当苗儿 <zuojiazi@vip.qq.com>
* @author cz
*/
public function index(){
if(session('user_auth.uid')){
public function index()
{
if(session('user_auth.uid')){
$data=M('Member')
->field('uid,nickname,username,us.last_login_time,us.last_login_ip,login')
->join('sys_ucenter_member as us on sys_member.uid = us.id')
@ -49,122 +42,171 @@ class IndexController extends AdminController {
// 日历
$this->calendar();
// 折线图
$this->foldLineDiagram($_REQUEST['start'],$_REQUEST['end'],$_REQUEST['num']);
$userRepository = new UserRepository();
$activeCount = $userRepository->getActiveUserCountRecently(7);
if(strtotime($_REQUEST['start']) == mktime(0,0,0,date('m'),date('d'),date('Y'))){
//今日时时
$this->nowday($_REQUEST['num']);
}else{
$this->foldLineDiagram($_REQUEST['start'],$_REQUEST['end'],$_REQUEST['num']);
}
$tm =strtotime(date("Y-m-d",strtotime("-1 day")));
$allcount = M("IndexChart","tab_")->field("all_count")->where("`date` = '{$tm}'")->find();
$allcount = unserialize($allcount['all_count']);
// 累计数据
$user = D('User');
$spend = D('Spend');
$promote = D('Promote');
$this->assign('user_count', $user->old());
// $this->assign('active_count', $user->active(['tab_user_login_record.login_time'=>['between',[mktime(0,0,0,date('m'),date('d')-7,date('Y')),mktime(0,0,0,date('m'),date('d'),date('Y'))-1]]]));
$this->assign('active_count', $activeCount);
$this->assign('player_count', $spend->player());
$this->assign('money_sum', $spend->totalAmount());
$this->assign('promote_sum', $promote->total());
$this->display();
}
/*
* 日历
* @param integer $start 开始时间(2018-04)
* @param integer $end 结束时间(2018-05)
* @param boolean $flag 是否ajax返回
* @author 鹿文学
*/
public function calendar($start='',$end='',$flag=false) {
$start = $start?$start:date('Y-m',strtotime('-1 month'));
$end = $end?$end:date('Y-m');
$this->assign('user_count',$allcount['user_count']);
$this->assign('active_count', $allcount['active_count']);
$this->assign('player_count', $allcount['player_count']);
$this->assign('money_sum', $allcount['money_sum']);
$this->assign('promote_sum',$allcount['promote_sum']);
//累计统计
$this->display();
}
/*
* 今日折线图
*/
public function nowday($num)
{
$starttime = mktime(0,0,0,date('m'),date('d'),date('Y'));
if ($start == $end) {$start = date('Y-m',strtotime('-1 month',$end));}
if (strtotime($start)>strtotime($end)) {$temp = $end;$end = $start;$start = $temp;}
if (strtotime($end) > strtotime(date('Y-m'))) {$end = date('Y-m');$start = date('Y-m',strtotime('-1 month'));}
$endtime = $starttime+86399;
$iscurrent = $end != date('Y-m')?1:0; // 默认是当前月,不可进入下一个月
$start = date('Y-m-d',$starttime);
$end = date('Y-m-d',$endtime);
$stime = strtotime($start);
$etime = strtotime($end);
$user = D('User');
$spend = D('Spend');
$promote = D('Promote');
$sw = date('w',$stime); // 周几
$ew = date('w',$etime);
$sw = $sw == 0? 6:(integer)$sw-1;
$ew = $ew == 0? 6:(integer)$ew-1;
if ($start == date('Y-m-d',strtotime('-1 day'))) {$num = 2;}
$st = date('t',$stime); // 天数
$et = date('t',$etime);
$hours = ['00','01','02','03','04','05','06','07','08','09','10','11','12','13','14','15','16','17','18','19','20','21','22','23'];
$sf = $ef = $sr = $er = 1; // 行数 ,日期起始值
$data['date'] = [$start];
for($i=0;$i<7;$i++) {
if ($i<$sw)
$first[$sr][$i] = ['value'=>''];
else {
$first[$sr][$i] = ['value'=>set_date_day_format($sf),'full'=>$start.'-'.set_date_day_format($sf)];$sf++;
}
}
for($i=0;$i<7;$i++) {
if ($i<$ew)
$last[$er][$i] = ['value'=>''];
else {
$eday = set_date_day_format($ef);
if (strtotime($end.'-'.$eday)>strtotime(date('Y-m-d'))){
$last[$er][$i] = ['value'=>$eday,'full'=>$end.'-'.$eday,'no'=>1];$ef++;
}else{
$last[$er][$i] = ['value'=>$eday,'full'=>$end.'-'.$eday];$ef++;
}
}
}
$data['hours'] = 1;
$sn = $en = 0; // 列数
for ($i=$sf;$i<=$st;$i++) {
if (count($first[$sr])==7){$sr++;$sn=0;}
$sday = set_date_day_format($i);
$first[$sr][$sn] = ['value'=>$sday,'full'=>$start.'-'.$sday];
$sn++;
}
for ($i=$ef;$i<=$et;$i++) {
if (count($last[$er])==7){$er++;$en=0;}
$eday = set_date_day_format($i);
if (strtotime($end.'-'.$eday)>strtotime(date('Y-m-d'))){$last[$er][$en] = ['value'=>$eday,'full'=>$end.'-'.$eday,'no'=>1];} else{$last[$er][$en] = ['value'=>$eday,'full'=>$end.'-'.$eday];}
$en++;
foreach($hours as $v) {
$data['news'][$v] = 0;
$data['active'][$v] = 0;
$data['player'][$v] = 0;
$data['money'][$v] = 0;
}
$prev = date('Y-m',strtotime('-1 month',$stime)).','.$start;
$next = $end.','.date('Y-m',strtotime('+1 month',$etime));
// 新增用户
$hoursnews = $user->newsAdd(['register_time'=>['between',[$starttime,$endtime]]],'news','time',5);
$calendar = ['first'=>$first,'last'=>$last,'prev'=>$prev,'next'=>$next,'iscurrent'=>$iscurrent,'ftitle'=>date('Y年m月',$stime),'ltitle'=>date('Y年m月',$etime),'today'=>date('Y-m-d')];
// 活跃用户
$hoursactive = $user->totalPlayerByGroup($hours,['tab_user_login_record.login_time'=>['between',[$starttime,$endtime]]],'active','time',5);
if ($flag) {
// 付费用户
$hoursplayer = $spend->totalPlayerByGroup(['pay_time'=>['between',[$starttime,$endtime]]],'player','time',5);
// 充值金额
$hoursmoney = $spend->totalAmountByGroup(['pay_time'=>['between',[$starttime,$endtime]]],'money','time',5);
foreach($hours as $v) {
foreach($hoursnews as $h) {
$time = explode(' ',$h['time']);
if ($time[1] == $v){
$data['news'][$v] = (integer)$h['news'];break;
}
}
echo json_encode($calendar);
foreach($hoursactive as $h) {
if ($h['time'] == $v){
$data['active'][$v] = (integer)$h['active'];break;
}
}
} else {
foreach($hoursplayer as $h) {
$time = explode(' ',$h['time']);
if ($time[1] == $v){
$data['player'][$v] = (integer)$h['player'];break;
}
}
$this->assign('calendar',$calendar);
foreach($hoursmoney as $h) {
$time = explode(' ',$h['time']);
if ($time[1] == $v){
$data['money'][$v] = $h['money'];break;
}
}
}
// 新
$between = ['between',[$starttime-86400,$endtime]];
$cnewslist = $user->newsAdd(['register_time'=>$between],'count','time',1,'time desc');
$cnews['count'] = $cnewslist[0]['count']?$cnewslist[0]['count']:0;
$cnews['rate'] = $cnewslist[0] && $cnewslist[1]? round(($cnewslist[0]['count']/$cnewslist[1]['count']-1)*100,2):($cnewslist[0]&&!$cnewslist[1]?(100):(!$cnewslist[0]&&$cnewslist[1]?(-100):0));
// 活
$cactivelist = $user->totalPlayerByGroup([date('Y-m-d',$starttime-86400),$end],['tab_user_login_record.login_time'=>$between],'count','time',1,'time desc');
$cactive['count'] = $cactivelist[0]['count']?$cactivelist[0]['count']:0;
$cactive['rate'] = $cactivelist[0] && $cactivelist[1]? round(($cactivelist[0]['count']/$cactivelist[1]['count']-1)*100,2):($cactivelist[0]&&!$cactivelist[1]?(100):(!$cactivelist[0]&&$cactivelist[1]?(-100):0));
// 付
$cplayerlist = $spend->totalPlayerByGroup(['pay_time'=>$between],'count','time',1,'time desc');
$cplayer['count'] = $cplayerlist[0]['count']?$cplayerlist[0]['count']:0;
$cplayer['rate'] = $cplayerlist[0] && $cplayerlist[1]? round(($cplayerlist[0]['count']/$cplayerlist[1]['count']-1)*100,2):($cplayerlist[0]&&!$cplayerlist[1]?(100):(!$cplayerlist[0]&&$cplayerlist[1]?(-100):0));
// 充
$cmoneylist = $spend->totalAmountByGroup(['pay_time'=>$between],'count','time',1,'time desc');
$cmoney['count'] = $cmoneylist[0]['count']?$cmoneylist[0]['count']:0;
$cmoney['rate'] = $cmoneylist[0] && $cmoneylist[1]? round(($cmoneylist[0]['count']/$cmoneylist[1]['count']-1)*100,2):($cmoneylist[0]&&!$cmoneylist[1]?(100):(!$cmoneylist[0]&&$cmoneylist[1]?(-100):0));
// 渠
$cpromotelist = $promote->newsAdd(['create_time'=>$between],'count','time',1,'time desc');
$cpromote['count'] = $cpromotelist[0]['count']?$cpromotelist[0]['count']:0;
$cpromote['rate'] = $cpromotelist[0] && $cpromotelist[1]? round(($cpromotelist[0]['count']/$cpromotelist[1]['count']-1)*100,2):($cpromotelist[0]&&!$cpromotelist[1]?(100):(!$cpromotelist[0]&&$cpromotelist[1]?(-100):0));
foreach($data as $k => $v) {
if (is_array($v)) {
if ($k == 'date')
$data[$k] = '"'.implode('","',$v).'"';
else
$data[$k] = implode(',',$v);
}
}
$data['compare']['news'] = $cnews;
$data['compare']['active'] = $cactive;
$data['compare']['player'] = $cplayer;
$data['compare']['money'] = $cmoney;
$data['compare']['promote'] = $cpromote;
/*
* 折线图
* @param integer $start 开始时间
* @param integer $end 结束时间
* @param boolean $flag 是否ajax返回
* @author 鹿文学
*/
public function foldLineDiagram($start='',$end='',$num='',$flag=false) {
if ($flag) {
$starttime = $start?strtotime($start):mktime(0,0,0,date('m'),date('d')-1,date('Y'));
echo json_encode($data);
} else {
$this->assign('foldline',$data);
$this->assign('num',$num);
}
# code...
}
/*
* 折线图
* @param integer $start 开始时间
* @param integer $end 结束时间
* @param boolean $flag 是否ajax返回
* @author 鹿文学
*/
public function foldLineDiagram($start='',$end='',$num='',$flag=false)
{
$starttime = $start?strtotime($start):mktime(0,0,0,date('m'),date('d')-1,date('Y'));
$endtime = $end?strtotime($end)+86399:$starttime+86399;
@ -175,238 +217,144 @@ class IndexController extends AdminController {
$spend = D('Spend');
$promote = D('Promote');
if ($start == $end) {
if ($start == $end) { // 单天
if ($start == date('Y-m-d',strtotime('-1 day'))) {$num = 2;}
$hours = ['00','01','02','03','04','05','06','07','08','09','10','11','12','13','14','15','16','17','18','19','20','21','22','23'];
$data['date'] = [$start];
$data['hours'] = 1;
foreach($hours as $v) {
$data['news'][$v] = 0;
$data['active'][$v] = 0;
$data['player'][$v] = 0;
$data['money'][$v] = 0;
}
// 新增用户
$hoursnews = $user->newsAdd(['register_time'=>['between',[$starttime,$endtime]]],'news','time',5);
// 活跃用户
$hoursactive = $user->totalPlayerByGroup($hours,['tab_user_login_record.login_time'=>['between',[$starttime,$endtime]]],'active','time',5);
// 付费用户
$hoursplayer = $spend->totalPlayerByGroup(['pay_time'=>['between',[$starttime,$endtime]]],'player','time',5);
// 充值金额
$hoursmoney = $spend->totalAmountByGroup(['pay_time'=>['between',[$starttime,$endtime]]],'money','time',5);
foreach($hours as $v) {
foreach($hoursnews as $h) {
$time = explode(' ',$h['time']);
if ($time[1] == $v){
$data['news'][$v] = (integer)$h['news'];break;
}
}
foreach($hoursactive as $h) {
if ($h['time'] == $v){
$data['active'][$v] = (integer)$h['active'];break;
}
}
foreach($hoursplayer as $h) {
$time = explode(' ',$h['time']);
if ($time[1] == $v){
$data['player'][$v] = (integer)$h['player'];break;
}
}
foreach($hoursmoney as $h) {
$time = explode(' ',$h['time']);
if ($time[1] == $v){
$data['money'][$v] = $h['money'];break;
}
}
}
// 新
$between = ['between',[$starttime-86400,$endtime]];
$cnewslist = $user->newsAdd(['register_time'=>$between],'count','time',1,'time desc');
$cnews['count'] = $cnewslist[0]['count']?$cnewslist[0]['count']:0;
$cnews['rate'] = $cnewslist[0] && $cnewslist[1]? round(($cnewslist[0]['count']/$cnewslist[1]['count']-1)*100,2):($cnewslist[0]&&!$cnewslist[1]?(100):(!$cnewslist[0]&&$cnewslist[1]?(-100):0));
// 活
$cactivelist = $user->totalPlayerByGroup([date('Y-m-d',$starttime-86400),$end],['tab_user_login_record.login_time'=>$between],'count','time',1,'time desc');
$cactive['count'] = $cactivelist[0]['count']?$cactivelist[0]['count']:0;
$cactive['rate'] = $cactivelist[0] && $cactivelist[1]? round(($cactivelist[0]['count']/$cactivelist[1]['count']-1)*100,2):($cactivelist[0]&&!$cactivelist[1]?(100):(!$cactivelist[0]&&$cactivelist[1]?(-100):0));
// 付
$cplayerlist = $spend->totalPlayerByGroup(['pay_time'=>$between],'count','time',1,'time desc');
$cplayer['count'] = $cplayerlist[0]['count']?$cplayerlist[0]['count']:0;
$cplayer['rate'] = $cplayerlist[0] && $cplayerlist[1]? round(($cplayerlist[0]['count']/$cplayerlist[1]['count']-1)*100,2):($cplayerlist[0]&&!$cplayerlist[1]?(100):(!$cplayerlist[0]&&$cplayerlist[1]?(-100):0));
// 充
$cmoneylist = $spend->totalAmountByGroup(['pay_time'=>$between],'count','time',1,'time desc');
$cmoney['count'] = $cmoneylist[0]['count']?$cmoneylist[0]['count']:0;
$cmoney['rate'] = $cmoneylist[0] && $cmoneylist[1]? round(($cmoneylist[0]['count']/$cmoneylist[1]['count']-1)*100,2):($cmoneylist[0]&&!$cmoneylist[1]?(100):(!$cmoneylist[0]&&$cmoneylist[1]?(-100):0));
// 渠
$cpromotelist = $promote->newsAdd(['create_time'=>$between],'count','time',1,'time desc');
$cpromote['count'] = $cpromotelist[0]['count']?$cpromotelist[0]['count']:0;
$cpromote['rate'] = $cpromotelist[0] && $cpromotelist[1]? round(($cpromotelist[0]['count']/$cpromotelist[1]['count']-1)*100,2):($cpromotelist[0]&&!$cpromotelist[1]?(100):(!$cpromotelist[0]&&$cpromotelist[1]?(-100):0));
$tm = strtotime($start);
$dbdata = M("IndexChart","tab_")->field("new_user_count,new_user_hours,active_user_count,active_user_hours,pay_user_count,pay_user_hours,pay_money_count,pay_money_hours,promote_new_count")->where("`date` = '{$tm}'")->find();
$data['news'] = unserialize($dbdata["new_user_hours"]);
$data['active'] = unserialize($dbdata["active_user_hours"]);
$data['player']=unserialize($dbdata["pay_user_hours"]);
$data['money']=unserialize($dbdata["pay_money_hours"]);
//获取昨天
$ytm = $starttime-86400;
$ydbdata = M("IndexChart","tab_")->field("new_user_count,active_user_count,pay_user_count,pay_money_count,promote_new_count")->where("`date` = '{$ytm}'")->find();
//计算
$cnews['count'] = $dbdata['new_user_count'];
$cnews['rate'] = $this->setRate($dbdata['new_user_count'],$ydbdata['new_user_count']);
$cactive['count'] = $dbdata['active_user_count'];
$cactive['rate'] = $this->setRate($dbdata['active_user_count'],$ydbdata['active_user_count']);
$cplayer['count'] = $dbdata['pay_user_count'];
$cplayer['rate'] = $this->setRate($dbdata['pay_user_count'],$ydbdata['pay_user_count']);
$cmoney['count'] = $dbdata['pay_money_count'];
$cmoney['rate'] = $this->setRate($dbdata['pay_money_count'],$ydbdata['pay_money_count']);
$cpromote['count'] = $dbdata['promote_new_count'];
$cpromote['rate'] = $this->setRate($dbdata['promote_new_count'],$ydbdata['promote_new_count']);
} else {
$datelist = get_date_list($starttime,$endtime,$num==7?4:1);
$data['date'] = $datelist;
$data['hours'] = 0;
foreach($datelist as $k => $v) {
$data['news'][$v] = 0;
$data['active'][$v] = 0;
$data['player'][$v] = 0;
$data['money'][$v] = 0;
}
// 新增用户
$news = $user->newsAdd(['register_time'=>['between',[$starttime,$endtime]]],'news','time',$num==7?2:1);
// 活跃用户
$active = $user->totalPlayerByGroup($datelist,['tab_user_login_record.login_time'=>['between',[$starttime,$endtime]]],'active','time',$num==7?2:1);
// 付费用户
$player = $spend->totalPlayerByGroup(['pay_time'=>['between',[$starttime,$endtime]]],'player','time',$num==7?2:1);
// 充值金额
$money = $spend->totalAmountByGroup(['pay_time'=>['between',[$starttime,$endtime]]],'money','time',$num==7?2:1);
foreach($datelist as $v) {
foreach($news as $h) {
if ($v == $h['time']) {
$data['news'][$v] = (integer)$h['news'];break;
}
}
foreach($active as $h) {
if ($v == $h['time']) {
$data['active'][$v] = (integer)$h['active'];break;
}
}
foreach($player as $h) {
if ($v == $h['time']) {
$data['player'][$v] = (integer)$h['player'];break;
}
}
foreach($money as $h) {
if ($v == $h['time']) {
$data['money'][$v] = $h['money'];break;
}
}
$map = array(
"date"=>['between',[$starttime,$endtime]]
);
//获取记录
$count1 = array();
$active_user_list = [];
$pay_user_list = [];
$dbdata = M("IndexChart","tab_")->field("new_user_count,active_user_count,active_user_list,pay_user_count,pay_user_list,pay_money_count,promote_new_count")
->where($map)->select();
foreach($dbdata as $k => $v) {
$data['news'][$k] = $v['new_user_count'];
$data['active'][$k] = $v['active_user_count'];
$data['player'][$k] = $v['pay_user_count'];
$data['money'][$k] = $v['pay_money_count'];
$active_user_list += unserialize($v['active_user_list']);
unset($v['active_user_list']);
unset($dbdata[$k]['active_user_list']);
$pay_user_list += unserialize($v['pay_user_list']);
unset($v['pay_user_list']);
unset($dbdata[$k]['pay_user_list']);
$count1['new_user_count'] += $v['new_user_count'];
$count1['pay_money_count'] += $v['pay_money_count'];
$count1['promote_new_count'] += $v['promote_new_count'];
}
// 新
$cnewslist1 = $user->old(['register_time'=>['between',[$starttime,$endtime]]]);
// 活
$cactivelist1 = $user->active(['tab_user_login_record.login_time'=>['between',[$starttime,$endtime]]]);
// 付
$cplayerlist1 = $spend->player(['pay_time'=>['between',[$starttime,$endtime]]]);
// 充
$cmoneylist1 = $spend->totalAmount(['pay_time'=>['between',[$starttime,$endtime]]]);
// 渠
$cpromotelist1 = $promote->total(['create_time'=>['between',[$starttime,$endtime]]]);
unset($dbdata);
$count1['active_user_count'] = count(array_flip(array_flip($active_user_list)));
unset($active_user_list);
$count1['pay_user_count'] = count(array_flip(array_flip($pay_user_list)));
unset($active_user_list);
//获取前num的日志
switch($num) {
case 3:{
$between = ['between',[strtotime('-7 day',$starttime),strtotime('-7 day',$endtime)]];
$cnewslist2 = $user->old(['register_time'=>$between]);
$cactivelist2 = $user->active(['tab_user_login_record.login_time'=>$between]);
$cplayerlist2 = $spend->player(['pay_time'=>$between]);
$cmoneylist2 = $spend->totalAmount(['pay_time'=>$between]);
$cpromotelist2 = $promote->total(['create_time'=>$between]);
};break;
case 4:{
$temp = strtotime('-1 month',$starttime);
$between = ['between',[$temp,mktime(0,0,0,date('m',$temp)+1,1,date('Y',$temp))-1]];
$cnewslist2 = $user->old(['register_time'=>$between]);
$cactivelist2 = $user->active(['tab_user_login_record.login_time'=>$between]);
$cplayerlist2 = $spend->player(['pay_time'=>$between]);
$cmoneylist2 = $spend->totalAmount(['pay_time'=>$between]);
$cpromotelist2 = $promote->total(['create_time'=>$between]);
};break;
case 5:{
$between = ['between',[strtotime('-7 day',$starttime),strtotime('-7 day',$endtime)]];
$cnewslist2 = $user->old(['register_time'=>$between]);
$cactivelist2 = $user->active(['tab_user_login_record.login_time'=>$between]);
$cplayerlist2 = $spend->player(['pay_time'=>$between]);
$cmoneylist2 = $spend->totalAmount(['pay_time'=>$between]);
$cpromotelist2 = $promote->total(['create_time'=>$between]);
};break;
case 6:{
$between = ['between',[strtotime('-30 day',$starttime),strtotime('-30 day',$endtime)]];
$cnewslist2 = $user->old(['register_time'=>$between]);
$cactivelist2 = $user->active(['tab_user_login_record.login_time'=>$between]);
$cplayerlist2 = $spend->player(['pay_time'=>$between]);
$cmoneylist2 = $spend->totalAmount(['pay_time'=>$between]);
$cpromotelist2 = $promote->total(['create_time'=>$between]);
};break;
case 7:{
$between = ['between',[strtotime('-365 day',$starttime),strtotime('-365 day',$endtime)]];
$cnewslist2 = $user->old(['register_time'=>$between]);
$cactivelist2 = $user->active(['tab_user_login_record.login_time'=>$between]);
$cplayerlist2 = $spend->player(['pay_time'=>$between]);
$cmoneylist2 = $spend->totalAmount(['pay_time'=>$between]);
$cpromotelist2 = $promote->total(['create_time'=>$between]);
};break;
default:{
$day_num = count($datelist);
$between = ['between',[strtotime('-'.$day_num.' day',$starttime),strtotime('-'.$day_num.' day',$endtime)]];
$cnewslist2 = $user->old(['register_time'=>$between]);
$cactivelist2 = $user->active(['tab_user_login_record.login_time'=>$between]);
$cplayerlist2 = $spend->player(['pay_time'=>$between]);
$cmoneylist2 = $spend->totalAmount(['pay_time'=>$between]);
$cpromotelist2 = $promote->total(['create_time'=>$between]);
};
}
//获取前几天记录
$map1 = array(
"date"=>$between
);
$ydbdata = M("IndexChart","tab_")->field("new_user_count,active_user_count,active_user_list,pay_user_count,pay_user_list,pay_money_count,promote_new_count")
->where($map1)->select();
$active_user_list = [];
$pay_user_list = [];
$count2 = array();
foreach($ydbdata as $k => $v) {
$active_user_list += unserialize($v['active_user_list']);
unset($v['active_user_list']);
unset($ydbdata[$k]['active_user_list']);
$pay_user_list += unserialize($v['pay_user_list']);
unset($v['pay_user_list']);
unset($ydbdata[$k]['pay_user_list']);
$count2['new_user_count'] += $v['new_user_count'];
$count2['pay_money_count'] += $v['pay_money_count'];
$count2['promote_new_count'] += $v['promote_new_count'];
}
unset($ydbdata);
$count2['active_user_count'] = count(array_flip(array_flip($active_user_list)));
unset($active_user_list);
$count2['pay_user_count'] = count(array_flip(array_flip($pay_user_list)));
unset($active_user_list);
//比较
$cnews['count'] = $count1['new_user_count'];
$cnews['rate'] = $this->setRate($count1['new_user_count'],$count2['new_user_count']);
$cnews['count'] = $cnewslist1?$cnewslist1:0;
$cnews['rate'] = $cnewslist1 && $cnewslist2? round(($cnewslist1/$cnewslist2-1)*100,2):($cnewslist1&&!$cnewslist2?(100):(!$cnewslist1&&$cnewslist2?(-100):0));
$cactive['count'] = $cactivelist1?$cactivelist1:0;
$cactive['rate'] = $cactivelist1 && $cactivelist2? round(($cactivelist1/$cactivelist2-1)*100,2):($cactivelist1&&!$cactivelist2?(100):(!$cactivelist1&&$cactivelist2?(-100):0));
$cactive['count'] =$count1['active_user_count'];
$cactive['rate'] = $this->setRate($count1['active_user_count'],$count2['active_user_count']);
$cplayer['count'] = $cplayerlist1?$cplayerlist1:0;
$cplayer['rate'] = $cplayerlist1 && $cplayerlist2? round(($cplayerlist1/$cplayerlist2-1)*100,2):($cplayerlist1&&!$cplayerlist2?(100):(!$cplayerlist1&&$cplayerlist2?(-100):0));
$cplayer['count'] =$count1['pay_user_count'];
$cplayer['rate'] = $this->setRate($count1['pay_user_count'],$count2['pay_user_count']);
$cmoney['count'] = $cmoneylist1?$cmoneylist1:0;
$cmoney['rate'] = $cmoneylist1 && $cmoneylist2? round(($cmoneylist1/$cmoneylist2-1)*100,2):($cmoneylist1&&!$cmoneylist2?(100):(!$cmoneylist1&&$cmoneylist2?(-100):0));
$cmoney['count'] = $count1['pay_money_count'];
$cmoney['rate'] = $this->setRate($count1['pay_money_count'],$count2['pay_money_count']);
$cpromote['count'] = $cpromotelist1?$cpromotelist1:0;
$cpromote['rate'] = $cpromotelist1 && $cpromotelist2? round(($cpromotelist1/$cpromotelist2-1)*100,2):($cpromotelist1&&!$cpromotelist2?(100):(!$cpromotelist1&&$cpromotelist2?(-100):0));
$cpromote['count'] = $count1['promote_new_count'];
$cpromote['rate'] = $this->setRate($count1['promote_new_count'],$count2['promote_new_count']);
}
foreach($data as $k => $v) {
// dump($k);
if (is_array($v)) {
if ($k == 'date')
$data[$k] = '"'.implode('","',$v).'"';
@ -421,7 +369,6 @@ class IndexController extends AdminController {
$data['compare']['player'] = $cplayer;
$data['compare']['money'] = $cmoney;
$data['compare']['promote'] = $cpromote;
if ($flag) {
echo json_encode($data);
@ -433,9 +380,108 @@ class IndexController extends AdminController {
$this->assign('num',$num);
}
# code...
}
public function setRate($d1,$d2)
{
$rate = 0;
if($d1>0){
if($d2 > 0){
$rate = round(($d1/$d2-1)*100,2);
}else{
$rate = 100;
}
}else if($d1 == 0 && $d2 == 0){
$rate = 0;
}else{
$rate = -100;
}
return $rate;
}
/*
* 日历
* @param integer $start 开始时间(2018-04)
* @param integer $end 结束时间(2018-05)
* @param boolean $flag 是否ajax返回
* @author 鹿文学
*/
public function calendar($start='',$end='',$flag=false) {
$start = $start?$start:date('Y-m',strtotime('-1 month'));
$end = $end?$end:date('Y-m');
if ($start == $end) {$start = date('Y-m',strtotime('-1 month',$end));}
if (strtotime($start)>strtotime($end)) {$temp = $end;$end = $start;$start = $temp;}
if (strtotime($end) > strtotime(date('Y-m'))) {$end = date('Y-m');$start = date('Y-m',strtotime('-1 month'));}
$iscurrent = $end != date('Y-m')?1:0; // 默认是当前月,不可进入下一个月
$stime = strtotime($start);
$etime = strtotime($end);
$sw = date('w',$stime); // 周几
$ew = date('w',$etime);
$sw = $sw == 0? 6:(integer)$sw-1;
$ew = $ew == 0? 6:(integer)$ew-1;
$st = date('t',$stime); // 天数
$et = date('t',$etime);
$sf = $ef = $sr = $er = 1; // 行数 ,日期起始值
for($i=0;$i<7;$i++) {
if ($i<$sw)
$first[$sr][$i] = ['value'=>''];
else {
$first[$sr][$i] = ['value'=>set_date_day_format($sf),'full'=>$start.'-'.set_date_day_format($sf)];$sf++;
}
}
for($i=0;$i<7;$i++) {
if ($i<$ew)
$last[$er][$i] = ['value'=>''];
else {
$eday = set_date_day_format($ef);
if (strtotime($end.'-'.$eday)>strtotime(date('Y-m-d'))){
$last[$er][$i] = ['value'=>$eday,'full'=>$end.'-'.$eday,'no'=>1];$ef++;
}else{
$last[$er][$i] = ['value'=>$eday,'full'=>$end.'-'.$eday];$ef++;
}
}
}
$sn = $en = 0; // 列数
for ($i=$sf;$i<=$st;$i++) {
if (count($first[$sr])==7){$sr++;$sn=0;}
$sday = set_date_day_format($i);
$first[$sr][$sn] = ['value'=>$sday,'full'=>$start.'-'.$sday];
$sn++;
}
for ($i=$ef;$i<=$et;$i++) {
if (count($last[$er])==7){$er++;$en=0;}
$eday = set_date_day_format($i);
if (strtotime($end.'-'.$eday)>strtotime(date('Y-m-d'))){$last[$er][$en] = ['value'=>$eday,'full'=>$end.'-'.$eday,'no'=>1];} else{$last[$er][$en] = ['value'=>$eday,'full'=>$end.'-'.$eday];}
$en++;
}
$prev = date('Y-m',strtotime('-1 month',$stime)).','.$start;
$next = $end.','.date('Y-m',strtotime('+1 month',$etime));
$calendar = ['first'=>$first,'last'=>$last,'prev'=>$prev,'next'=>$next,'iscurrent'=>$iscurrent,'ftitle'=>date('Y年m月',$stime),'ltitle'=>date('Y年m月',$etime),'today'=>date('Y-m-d')];
if ($flag) {
echo json_encode($calendar);
} else {
$this->assign('calendar',$calendar);
}
}
public function indextt(){
$user = M("User","tab_");

@ -380,14 +380,13 @@ class PlatformController extends ThinkController
count(IF(register_time ' . $today . ',1,null)) as today,
count(IF(register_time ' . $week . ',1,null)) as week,
count(IF(register_time ' . $mounth . ',1,null)) as mounth')
->join("tab_promote AS tp2 ON tp2.`chain` LIKE CONCAT('%/', tp1.id, '/%')", 'left')
->join("tab_promote AS tp2 ON tp2.`chain` LIKE CONCAT('%/', tp1.id, '/%') OR tp2.id = tp1.id", 'left')
->join("tab_user as u on tp2.id = u.promote_id", 'left')
->join($play_info_map ? "tab_user_play_info as upi on upi.user_id = u.id " . $play_info_map : false)
->where($map)
->group('tp1.id')
->order('count desc, register_time')
->select();
$count = count($data);
foreach ($data as $key => $value) {
static $i = 0;

@ -237,5 +237,4 @@ class PublicController extends \Think\Controller
cookie('think_language', 'en-us');
$this->ajaxReturn(['status' => 1]);
}
}

@ -1331,26 +1331,28 @@ class StatController extends ThinkController
* @author 鹿文学
*/
public function device_survey() {
$device = D('DeviceRecord');
set_time_limit(0);
// $device = D('DeviceRecord');
// 统计
$total = $device->all_device();
$todaystart = mktime(0,0,0,date('m'),date('d'),date('Y'));
$today = $device->total_device(['create_time'=>array('between',[$todaystart,$todaystart+86399])]);
$yesterday = $device->total_device(['create_time'=>array('between',[$todaystart-86400,$todaystart-1])]);
$day7 = $device->total_device(['create_time'=>array('between',[$todaystart-86400*7,$todaystart-1])],1);
$day30 = $device->total_device(['create_time'=>array('between',[$todaystart-86400*30,$todaystart-1])],1);
$duration = $device->single_duration(['create_time'=>array('between',[$todaystart-86400*7,$todaystart-1])]);
$this->assign('total',$total);
$this->assign('today',$today);
$this->assign('yesterday',$yesterday);
$this->assign('day7',$day7);
$this->assign('day30',$day30);
$this->assign('duration7',second_to_duration($duration/7));
// $total = $device->all_device();
// $todaystart = mktime(0,0,0,date('m'),date('d'),date('Y'));
// $today = $device->total_device(['create_time'=>array('between',[$todaystart,$todaystart+86399])]);
// $yesterday = $device->total_device(['create_time'=>array('between',[$todaystart-86400,$todaystart-1])]);
//
// $day7 = $device->total_device(['create_time'=>array('between',[$todaystart-86400*7,$todaystart-1])],1);
//
//
// $day30 = $device->total_device(['create_time'=>array('between',[$todaystart-86400*30,$todaystart-1])],1);
// $duration = $device->single_duration(['create_time'=>array('between',[$todaystart-86400*7,$todaystart-1])]);
// $this->assign('total',$total);
// $this->assign('today',$today);
// $this->assign('yesterday',$yesterday);
// $this->assign('day7',$day7);
// $this->assign('day30',$day30);
// $this->assign('duration7',second_to_duration($duration/7));
// 日历
R('Index/calendar');
@ -1362,6 +1364,39 @@ class StatController extends ThinkController
}
public function getDevice() {
set_time_limit(0);
$type = I("type",0);
$device = D('DeviceRecord');
$todaystart = mktime(0,0,0,date('m'),date('d'),date('Y'));
$model = M('device_statistics','tab_');
if ($type == 0) {
$return = $model->sum('new_device');
// $return = $device->all_device();
} else if($type == 1) {
$return = $model->where(['time'=>array('between',[$todaystart,$todaystart+86399])])->sum('new_device');
// $return = $device->total_device(['create_time'=>array('between',[$todaystart,$todaystart+86399])]);
} else if($type == 2) {
$return = $model->where(['time'=>array('between',[$todaystart-86400,$todaystart-1])])->sum('new_device');
// $return = $device->total_device(['create_time'=>array('between',[$todaystart-86400,$todaystart-1])]);
} else if($type == 3) {
$return = $model->where(['time'=>array('between',[$todaystart-86400*7,$todaystart-1])])->sum('active_device');
// $return = $device->total_device(['create_time'=>array('between',[$todaystart-86400*7,$todaystart-1])],1);
} else if($type == 4) {
$return = $model->where(['time'=>array('between',[$todaystart-86400*30,$todaystart-1])])->sum('active_device');
// $return = $device->total_device(['create_time'=>array('between',[$todaystart-86400*30,$todaystart-1])],1);
} else if ($type == 5) {
$return = second_to_duration(($model->where(['time'=>$todaystart])->sum('duration7')));
// $return = second_to_duration($device->single_duration(['create_time'=>array('between',[$todaystart-86400*7,$todaystart-1])])/7);
}
$this->ajaxReturn($return?$return:0) ;
}
/*
* 折线图
@ -1399,14 +1434,19 @@ class StatController extends ThinkController
$data['active']['and'][$v] = 0;
}
$deviceDataAnd = M("device_statistics","tab_")->where(['time'=>strtotime($start),'version'=>1])->find();
$deviceDataIos = M("device_statistics","tab_")->where(['time'=>strtotime($start),'version'=>2])->find();
// 新增设备
$hoursnews = $device->news_on_time(['create_time'=>['between',[$starttime,$endtime]]],'news',5,'time,version');
// $hoursnews = $device->news_on_time(['create_time'=>['between',[$starttime,$endtime]]],'news',5,'time,version');
$hoursnews = array_merge(json_decode($deviceDataAnd['today_new_device'],true),json_decode($deviceDataIos['today_new_device'],true));
// 活跃设备
$hoursactive = $device->active_on_time(['create_time'=>['between',[$starttime,$endtime]]],'active',5,'time,version');
// $hoursactive = $device->active_on_time(['create_time'=>['between',[$starttime,$endtime]]],'active',5,'time,version');
$hoursactive = array_merge(json_decode($deviceDataAnd['today_active_device'],true),json_decode($deviceDataIos['today_active_device'],true));
// 启动机型
$hoursmodel = $device->model(['create_time'=>['between',[$starttime,$endtime]]]);
// $hoursmodel = $device->model(['create_time'=>['between',[$starttime,$endtime]]]);
$hoursmodel = array_merge(json_decode($deviceDataAnd['today_model_device'],true),json_decode($deviceDataIos['today_model_device'],true));
foreach($hours as $v) {
foreach($hoursnews as $h) {
@ -1445,15 +1485,68 @@ class StatController extends ThinkController
$data['active']['ios'][$v] = 0;
$data['active']['and'][$v] = 0;
}
$newData = M('device_statistics','tab_')
->field("new_device as news,version,FROM_UNIXTIME(time,'%Y-%m-%d') as time")
->where(['time'=>['between',[$starttime,$endtime]],'new_device'=>['neq','0']])
->group('time,version')
->select();
// 新增设备
$news = $device->news_on_time(['create_time'=>['between',[$starttime,$endtime]]],'news',$num==7?2:1,'time,version');
// $news = $device->news_on_time(['create_time'=>['between',[$starttime,$endtime]]],'news',$num==7?2:1,'time,version');
$news = $newData;
$activeData = M('device_statistics','tab_')
->field("active_device as active,version,FROM_UNIXTIME(time,'%Y-%m-%d') as time")
->where(['time'=>['between',[$starttime,$endtime]],'active_device'=>['neq','0']])
->group('time,version')
->select();
// 活跃设备
$active = $device->active_on_time(['create_time'=>['between',[$starttime,$endtime]]],'active',$num==7?2:1,'time,version');
// $active = $device->active_on_time(['create_time'=>['between',[$starttime,$endtime]]],'active',$num==7?2:1,'time,version');
$active = $activeData;
// 启动机型
$model = $device->model(['create_time'=>['between',[$starttime,$endtime]]]);
$modelData = M('device_statistics','tab_')
->field("model")
->where(['time'=>['between',[$starttime,$endtime]]])
->select();
$modelNew = [];
$unique_code = [];
foreach($modelData as $key => $value) {
$resolveData = json_decode($value['model'],true);
// dump($resolveData);
foreach($resolveData as $k => $v) {
if (!isset($modelNew[$v['model']][$v['version']])) {
$modelNew[$v['model']][$v['version']] = 1;
$unique_code[$v['unique_code']] = 1;
} else if(!$unique_code[$v['unique_code']]){
$modelNew[$v['model']][$v['version']]++;
$unique_code[$v['unique_code']] = 1;
// array_push($unique_code,$v['unique_code']);
}
}
}
$unique_code = [];
$modelNewData = [];
$modelKey = 0;
foreach($modelNew as $key => $value) {
$modelNewData[$modelKey]['model'] = $key;
foreach($value as $k => $v) {
$modelNewData[$modelKey]['version'] = $k;
$modelNewData[$modelKey]['count'] = $v;
}
$modelKey++;
}
$last_names = array_column($modelNewData,'count');
array_multisort($last_names,SORT_DESC,$modelNewData);
// dump($modelNewData);
// die();
// $model = $device->model(['create_time'=>['between',[$starttime,$endtime]]]);
// dump($model);die();
$model = $modelNewData;
foreach($datelist as $v) {
foreach($news as $h) {

@ -0,0 +1,194 @@
<?php
// +----------------------------------------------------------------------
// | OneThink [ WE CAN DO IT JUST THINK IT ]
// +----------------------------------------------------------------------
// | Copyright (c) 2013 http://www.onethink.cn All rights reserved.
// +----------------------------------------------------------------------
// | Author: 麦当苗儿 <zuojiazi@vip.qq.com> <http://www.zjzit.cn>
// +----------------------------------------------------------------------
namespace Admin\Controller;
use User\Api\UserApi as UserApi;
/**
* 后台首页控制器
* @author 麦当苗儿 <zuojiazi@vip.qq.com>
*/
class TimingController extends AdminController {
public function _initialize(){
}
public function caculateDeviceInfo() {
$start = 1569686400;
$end = time();
if (I('time')) {
$start = strtotime(I('time'));
$end = $start+1;
}
if (I('start')) {
$start = strtotime(I('start'));
}
ini_set('memory_limit','1024M');
// $device = D('DeviceRecord');
// echo 1;
for($startTime = $start;$startTime<$end;$startTime=$startTime+86400) {
echo date("Y-m-d",$startTime).' 安卓 ';
//当日新增设备
$newSql = M('device_record','tab_')->field('min(create_time) as create_time,model,unique_code,id')->where(['version'=>1])->group('unique_code')->select(false);
$data['new_device'] = M('device_record','tab_')->table('(' . $newSql . ') as a')->where(['create_time'=>array('between',[$startTime,$startTime+86399])])->order('create_time')->count();
echo $data['new_device'].' ';
//当日活跃设备
$data['active_device'] = $this->active(['create_time'=>array('between',[$startTime,$startTime+86399]),'version'=>1]);
echo $data['active_device'].' ';
$data['time'] = $startTime;
$data['version'] = 1;
$data['today_new_device'] =json_encode($this->news_on_time(['create_time'=>['between',[$startTime,$startTime+86399]]],'news',5,'time,version','time',1));
// echo M('device_record','tab_')->_sql()."\n";
$data['today_active_device'] =json_encode($this->active_on_time(['create_time'=>['between',[$startTime,$startTime+86399]],'version'=>1],'active',5,'time,version'));
// echo M('device_record','tab_')->_sql()."\n";
$data['today_model_device'] = json_encode($this->model(['create_time'=>['between',[$startTime,$startTime+86399]],'version'=>1]));
$data['model'] = json_encode($this->modelDevice(['create_time'=>['between',[$startTime,$startTime+86399]],'version'=>1]));
$duration = $this->duration(['create_time'=>array('between',[$startTime-86400*7,$startTime-1])]);
$newSqls = M('device_record','tab_')->field('min(create_time) as create_time,model,unique_code,id')->group('unique_code')->select(false);
$data['duration7'] = ($duration/M('device_record','tab_')->table('(' . $newSqls . ') as a')->where(['create_time'=>array('between',[$startTime-86400*7,$startTime-1])])->order('create_time')->count())/7;
$getStatistics = M('device_statistics','tab_')->where(['time'=>$startTime,'version'=>1])->find();
echo "\n";
if (!$getStatistics) {
M('device_statistics','tab_')->add($data);
} else {
M('device_statistics','tab_')->where(['time'=>$startTime,'version'=>1])->save($data);
}
echo date("Y-m-d",$startTime).' 苹果 ';
//当日新增设备
$newSql = M('device_record','tab_')->field('min(create_time) as create_time,model,unique_code,id')->where(['version'=>2])->group('unique_code')->select(false);
$data['new_device'] = M('device_record','tab_')->table('(' . $newSql . ') as a')->where(['create_time'=>array('between',[$startTime,$startTime+86399])])->order('create_time')->count();
echo $data['new_device'].' ';
//当日活跃设备
$data['active_device'] = $this->active(['create_time'=>array('between',[$startTime,$startTime+86399]),'version'=>2]);
echo $data['active_device'].' ';
$data['time'] = $startTime;
$data['version'] = 2;
echo 0;
$data['today_new_device'] =json_encode($this->news_on_time(['create_time'=>['between',[$startTime,$startTime+86399]]],'news',5,'time,version','time',2));
// echo M('device_record','tab_')->_sql();die();
echo 1;
$data['today_active_device'] =json_encode($this->active_on_time(['create_time'=>['between',[$startTime,$startTime+86399]],'version'=>2],'active',5,'time,version'));
echo 2;
$data['today_model_device'] = json_encode($this->model(['create_time'=>['between',[$startTime,$startTime+86399]],'version'=>2]));
echo 3;
$data['model'] = json_encode($this->modelDevice(['create_time'=>['between',[$startTime,$startTime+86399]],'version'=>2]));
// $duration = $this->duration(['create_time'=>array('between',[$startTime-86400*7,$startTime-1]),'version'=>2]);
// $data['duration7'] = ($duration/M('device_record','tab_')->table('(' . $newSql . ') as a')->where(['create_time'=>array('between',[$startTime-86400*7,$startTime-1])])->order('create_time')->count())/7;
$data['duration7'] = 0;
echo 4;
$getStatistics = M('device_statistics','tab_')->where(['time'=>$startTime,'version'=>2])->find();
echo "\n";
if (!$getStatistics) {
M('device_statistics','tab_')->add($data);
} else {
M('device_statistics','tab_')->where(['time'=>$startTime,'version'=>2])->save($data);
}
}
}
public function duration($map=array()) {
return M('device_record','tab_')->where($map)->sum('duration');
}
public function active($map=array()) {
$sql = M('device_record','tab_')->field('create_time,model,unique_code')->where($map)->select(false);
$sql = M('device_record','tab_')->table('(' . $sql . ') as a')->group('unique_code')->order('create_time')->select(false);
$sql = "select count(*) as count from ({$sql})t";
$count = M('device_record','tab_')->query($sql);
return $count[0]['count'];
}
public function news_on_time($map=array(),$field='news',$flag=1,$group='time',$order='time',$version = 1) {
switch($flag) {
case 2:{$dateform = '%Y-%m';};break;
case 3:{$dateform = '%Y-%u';};break;
case 4:{$dateform = '%Y';};break;
case 5:{$dateform = '%Y-%m-%d %H';};break;
default:$dateform = '%Y-%m-%d';
}
$sql = M('device_record','tab_')->field('min(create_time) as create_time,version,unique_code,id')->where(['version'=>$version])->group('unique_code')->select(false);
$news = M('device_record','tab_')->table('(' . $sql . ') as a')
->field('FROM_UNIXTIME(a.create_time, "'.$dateform.'") as '.$group.',group_concat(a.id) as id,group_concat(a.unique_code) as unique_code ,COUNT(a.unique_code) AS '.$field)
->where($map)->group($group)->order($order)->select();
// echo M('device_record','tab_')->_sql();die();
return $news;
}
public function active_on_time($map=array(),$field='active',$flag=1,$group='time',$order='time') {
switch($flag) {
case 2:{$dateform = '%Y-%m';};break;
case 3:{$dateform = '%Y-%u';};break;
case 4:{$dateform = '%Y';};break;
case 5:{$dateform = '%Y-%m-%d %H';};break;
default:$dateform = '%Y-%m-%d';
}
$sql = M('device_record','tab_')->field('create_time,version,unique_code,id')->where($map)->select(false);
$mid = M('device_record','tab_')->table('(' . $sql . ') as m')->group('unique_code')->select(false);
$active = M('device_record','tab_')->table('(' . $mid . ') as a')
->field('FROM_UNIXTIME(a.create_time, "'.$dateform.'") as '.$group.',group_concat(a.id) as id,group_concat(a.unique_code) as unique_code ,COUNT(a.unique_code) AS '.$field)
->group($group)->order($order)->select();
// echo $this->_sql();die();
return $active;
}
public function model($map=array()) {
$sql = M('device_record','tab_')->field('create_time,model,version,unique_code')->where($map)->select(false);
$mid = M('device_record','tab_')->table('(' .$sql. ') as m')->group('unique_code')->select(false);
return M('device_record','tab_')->table('(' .$mid. ') as a')->field('a.model,version,count(a.unique_code) as count')->group('model,version')->order('count desc')->select();
}
public function modelDevice($map=array()) {
$sql = M('device_record','tab_')->field('model,version,unique_code')->where($map)->select(false);
$mid = M('device_record','tab_')->table('(' .$sql. ') as m')->group('unique_code')->select();
return $mid;
}
}

@ -46,10 +46,13 @@ class DeviceRecordModel extends Model{
* @author 鹿文学
*/
public function all_device() {
$list = $this->field('min(create_time) as create_time,unique_code')->group('unique_code')->select();
return count($list);
// $list = $this->field('unique_code')->group('unique_code')->count();
$sql = "SELECT count(1) as count from (select unique_code from tab_device_record group by unique_code)t;";
$list = $this->query($sql);
return $list[0]['count'];
}
@ -60,7 +63,7 @@ class DeviceRecordModel extends Model{
public function total_device($map=array(),$flag=0) {
if($flag) {
$list = $this->active($map);
$list = $this->active($map);
} else {
$list = $this->news($map);
}
@ -76,7 +79,7 @@ class DeviceRecordModel extends Model{
public function news($map=array()) {
$sql = $this->field('min(create_time) as create_time,model,unique_code,id')->group('unique_code')->select(false);
return $this->table('(' . $sql . ') as a')->where($map)->order('create_time')->select();
}
@ -89,7 +92,7 @@ class DeviceRecordModel extends Model{
* @author 鹿文学
*/
public function news_on_time($map=array(),$field='news',$flag=1,$group='time',$order='time') {
switch($flag) {
case 2:{$dateform = '%Y-%m';};break;
case 3:{$dateform = '%Y-%u';};break;
@ -97,13 +100,13 @@ class DeviceRecordModel extends Model{
case 5:{$dateform = '%Y-%m-%d %H';};break;
default:$dateform = '%Y-%m-%d';
}
$sql = $this->field('min(create_time) as create_time,version,unique_code,id')->group('unique_code')->select(false);
$news = $this->table('(' . $sql . ') as a')
->field('FROM_UNIXTIME(a.create_time, "'.$dateform.'") as '.$group.',group_concat(a.id) as id,group_concat(a.unique_code) as unique_code ,COUNT(a.unique_code) AS '.$field)
->where($map)->group($group)->order($order)->select();
return $news;
}
@ -145,7 +148,7 @@ class DeviceRecordModel extends Model{
$active = $this->table('(' . $mid . ') as a')
->field('FROM_UNIXTIME(a.create_time, "'.$dateform.'") as '.$group.',group_concat(a.id) as id,group_concat(a.unique_code) as unique_code ,COUNT(a.unique_code) AS '.$field)
->group($group)->order($order)->select();
// echo $this->_sql();die();
return $active;
}
@ -160,6 +163,7 @@ class DeviceRecordModel extends Model{
$mid = $this->table('(' .$sql. ') as m')->group('unique_code')->select(false);
// echo $this->_sql();die();
return $this->table('(' .$mid. ') as a')->field('a.model,version,count(a.unique_code) as count')->group('model,version')->order('count desc')->select();

@ -45,7 +45,7 @@
<li class="<eq name='num' value='4'>datapick_active</eq>"><a href="{:U('index',array('start'=>date('Y-m-d',mktime(0,0,0,date('m')-1,1,date('Y'))),'end'=>date('Y-m-d',mktime(0,0,0,date('m'),1,date('Y'))-1),'num'=>4))}">过去整月</a></li>
<li class="<eq name='num' value='5'>datapick_active</eq>"><a href="{:U('index',array('start'=>date('Y-m-d',strtotime('-7 day')),'end'=>date('Y-m-d',strtotime('-1 day')),'num'=>5))}">过去7天</a></li>
<li class="<eq name='num' value='6'>datapick_active</eq>"><a href="{:U('index',array('start'=>date('Y-m-d',strtotime('-30 day')),'end'=>date('Y-m-d',strtotime('-1 day')),'num'=>6))}">过去30天</a></li>
<li class="<eq name='num' value='7'>datapick_active</eq>"><a href="{:U('index',array('start'=>date('Y-m-d',strtotime('-365 day')),'end'=>date('Y-m-d',strtotime('-1 day')),'num'=>7))}">过去一年</a></li>
<!-- <li class="<eq name='num' value='7'>datapick_active</eq>"><a href="{:U('index',array('start'=>date('Y-m-d',strtotime('-365 day')),'end'=>date('Y-m-d',strtotime('-1 day')),'num'=>7))}">过去一年</a></li> -->
</ul>
<div class="range_inputs">
<button class="applyBtn pt-btn btn-success js_determine" type="button">确定</button>
@ -386,8 +386,32 @@
});
}
}
//执行日期的选择
function chartdata(start,end,parent) {
var starttime = new Date(start).getTime();
if(end){
var endtime = new Date(end).getTime();
}else{
var endtime = new Date(start).getTime();
}
if(starttime > endtime){
var temp = start;
start = end;
end = temp;
}
if(end && (start != end)){
var endtime = (new Date(end).getTime()) + 86399000;
var now = new Date().getTime();
if(endtime > now){
layer.msg('历史时间选择不能包含今日');
return false;
}
};
var index = layer.load(1, {
shade: [0.3,'#000'] //0.1透明度的白色背景
});
var href = '{:U("index")}';
end = end?end:start;

@ -81,33 +81,33 @@
<div class="main_content_main m-channel-data main_content_platform" style="border-bottom:1px solid #ddd;margin-bottom:15px;padding:17px 0;">
<div class="main_content_main_item">
<div class="col-md-2">
<strong class="s-c-orange">{$today|default=0}</strong> <span class="s-c-title">今日新增设备</span>
<div class="col-md-2" onclick="gettotal(1,'#today');">
<strong class="s-c-orange" id = "today">加载中...</strong> <span class="s-c-title">今日新增设备</span>
</div>
</div>
<div class="main_content_main_item">
<div class="col-md-2">
<strong class="s-c-orange">{$yesterday|default=0}</strong> <span class="s-c-title">昨日新增设备</span>
<div class="col-md-2" onclick="gettotal(2,'#yesterday')">
<strong class="s-c-orange" id = "yesterday">加载中...</strong> <span class="s-c-title">昨日新增设备</span>
</div>
</div>
<div class="main_content_main_item">
<div class="col-md-2">
<strong class="s-c-orange">{$total|default=0}</strong> <span class="s-c-title">累计设备</span>
<div class="col-md-2" onclick="gettotal(0,'#total')">
<strong class="s-c-orange" id = "total">加载中...</strong> <span class="s-c-title">累计设备</span>
</div>
</div>
<div class="main_content_main_item">
<div class="col-md-2">
<strong class="s-c-orange">{$day7|default=0}</strong> <span class="s-c-title">近7日活跃设备</span>
<div class="col-md-2" onclick="gettotal(3,'#day7')">
<strong class="s-c-orange" id = "day7">加载中...</strong> <span class="s-c-title">近7日活跃设备</span>
</div>
</div>
<div class="main_content_main_item">
<div class="col-md-2">
<strong class="s-c-orange">{$day30|default=0}</strong> <span class="s-c-title">近30日活跃设备</span>
<div class="col-md-2" onclick="gettotal(4,'#day30')">
<strong class="s-c-orange"id = "day30">加载中...</strong> <span class="s-c-title">近30日活跃设备</span>
</div>
</div>
<div class="main_content_main_item">
<div class="col-md-2">
<strong class="s-c-orange">{$duration7|default='00:00:00'}</strong> <span class="s-c-title">近7日单设备日均使用时长</span>
<div class="col-md-2" onclick="gettotal(5,'#duration7')">
<strong class="s-c-orange" id = "duration7">加载中...</strong> <span class="s-c-title">近7日单设备日均使用时长</span>
</div>
</div>
@ -131,7 +131,7 @@
<li class="<eq name='num' value='4'>datapick_active</eq>"><a href="{:U('device_survey',array('tb'=>I('tb'),'type'=>I('type'),'category'=>I('category'),'start'=>date('Y-m-d',mktime(0,0,0,date('m')-1,1,date('Y'))),'end'=>date('Y-m-d',mktime(0,0,0,date('m'),1,date('Y'))-1),'num'=>4))}">过去整月</a></li>
<li class="<eq name='num' value='5'>datapick_active</eq>"><a href="{:U('device_survey',array('tb'=>I('tb'),'type'=>I('type'),'category'=>I('category'),'start'=>date('Y-m-d',strtotime('-7 day')),'end'=>date('Y-m-d',strtotime('-1 day')),'num'=>5))}">过去7天</a></li>
<li class="<eq name='num' value='6'>datapick_active</eq>"><a href="{:U('device_survey',array('tb'=>I('tb'),'type'=>I('type'),'category'=>I('category'),'start'=>date('Y-m-d',strtotime('-30 day')),'end'=>date('Y-m-d',strtotime('-1 day')),'num'=>6))}">过去30天</a></li>
<li class="<eq name='num' value='7'>datapick_active</eq>"><a href="{:U('device_survey',array('tb'=>I('tb'),'type'=>I('type'),'category'=>I('category'),'start'=>date('Y-m-d',strtotime('-365 day')),'end'=>date('Y-m-d',strtotime('-1 day')),'num'=>7))}">过去一年</a></li>
<!-- <li class="<eq name='num' value='7'>datapick_active</eq>"><a href="{:U('device_survey',array('tb'=>I('tb'),'type'=>I('type'),'category'=>I('category'),'start'=>date('Y-m-d',strtotime('-365 day')),'end'=>date('Y-m-d',strtotime('-1 day')),'num'=>7))}">过去一年</a></li>-->
</ul>
<div class="range_inputs">
<button class="applyBtn pt-btn btn-success js_determine" type="button">确定</button>
@ -457,7 +457,37 @@
<script src="__JS__/zwmjs/highcharts.js"></script>
<script>
var datelist;
function gettotal(types,ids) {
$(ids).text("加载中...");
$(ids).css('color','#FBA10D');
$.ajax({
type:'post',
dataType:'json',
url:'{:U("stat/getDevice")}',
data:{type:types},
success:function(data) {
$(ids).text(data)
},error:function() {
$(ids).text("加载失败");
$(ids).css('color','red');
layer.msg('服务器错误,请稍候再试');that.removeClass('disabled');
}
});
}
$(function() {
gettotal(0,'#total');
gettotal(1,'#today');
gettotal(2,'#yesterday');
gettotal(3,'#day7');
gettotal(4,'#day30');
gettotal(5,'#duration7');
$('.data-box').each(function() {
var that = $(this);
if (that.width()>that.find('.data-wrap').width()) {

@ -62,7 +62,9 @@ class Request {
public function isIOS13()
{
if (preg_match('/OS [1][3-9]_[1-9][_\d]* like Mac OS X/i')) {
$userAgent = $this->getUserAgent();
// if (preg_match('/OS [1][3-9]_[1-9][_\d]* like Mac OS X/i', $userAgent)) {
if (preg_match('/OS.*[1][3-9]_[1-9][_\d]*.*like.*Mac.*OS.*X/i', $userAgent)) {
return true;
}
return false;

@ -3,7 +3,7 @@
namespace Callback\Controller;
use Org\UcenterSDK\Ucservice;
use Think\Log;
/**
* 新版支付回调控制器
@ -31,7 +31,6 @@ class Notify2Controller extends BaseController
exit('Access Denied');
}
}
$pay_way = $apitype;
if ($apitype == "swiftpass") {
$apitype = "weixin";
@ -39,8 +38,7 @@ class Notify2Controller extends BaseController
Vendor('Alipay.AopSdk');
$aop = new \AopClient();
$aop->alipayrsaPublicKey = file_get_contents("./Application/Sdk/SecretKey/alipay/alipay2_public_key.txt");
$result = $aop->rsaCheckV1($notify,'','RSA2');
$result = $aop->rsaCheckV1($notify,"",'RSA2');
if ($result) {
//获取回调订单信息
if (I('get.methodtype') == "notify") {
@ -64,9 +62,15 @@ class Notify2Controller extends BaseController
case 'TB':
$result = $this->set_balance($order_info);
break;
case 'SI':
$result = $this->set_order($order_info);
break;
case 'SI':
$result = $this->set_order($order_info);
break;
case 'SS': // 超级签
$this->supersign_pay_notify(array(
'trade_id' => $order_info['trade_no'],
'order_id' => $order_info['out_trade_no']
));
break;
default:
exit('accident order data');
break;

@ -51,8 +51,6 @@ class NotifyController extends BaseController
}
}
$pay_way = $apitype;
if ($apitype == "swiftpass") {

@ -16,6 +16,7 @@ use Think\Controller;
*/
class AddonsController extends Controller{
public function _initialize(){
/* 读取数据库中的配置 */
$config = S('DB_CONFIG_DATA');

@ -15,7 +15,7 @@ class DownController extends Controller {
}
public function down_file($game_id=0,$promote_id=0){
// 旧版兼容
A('Download')->index();
A('Package')->download();
die();
$applyModel = M('Apply','tab_');

@ -72,6 +72,12 @@ class DownloadController extends BaseController {
}
public function listsIndex($p = 0) {
$nowTime = date('Y-m-d');
$initBegTime = empty(I('begtime')) ? '' : I('begtime');
$initEndTime = $nowTime;
$initEndTime = empty(I('endtime')) ? '' : I('endtime');
$this->assign('begtime',$initBegTime);
$this->assign('endtime',$initEndTime);
$map1['chain'] = ['like','%'.'/'.PID.'/'.'%'];
$res = M('promote','tab_')->where($map1)->field('id,account,nickname')->select();
$childPromoteIds = '';
@ -114,9 +120,10 @@ class DownloadController extends BaseController {
$endtime = strtotime($_REQUEST['endtime']);
}
$map['addtime'] = array('BETWEEN',array(strtotime($_REQUEST['begtime']),$endtime));
}
$page = intval($p);
$page = $page ? $page : 1; //默认显示第一页数据
$page = intval(I('get.p', 1));
$page = $page ? $page : 1; //默认显示第一页数据arraypage
$row=10;
$rs = M('downloadlog','tab_')->where($map)->order('tab_downloadlog.addtime desc')
->page($page, $row)->select();
@ -142,11 +149,19 @@ class DownloadController extends BaseController {
//分页
$parameter['p'] = I('get.p', 1);
$parameter['row'] = I('get.row');
$parameter['dataname'] = $_REQUEST['dataname'];
$parameter['logid'] = $_REQUEST['logid'];
$parameter['begtime'] = I('begtime');
$parameter['endtime'] = I('endtime');
$parameter['level_promote_2'] = $levelPromote[0];
$parameter['level_promote_3'] = $levelPromote[1];
$parameter['level_promote_4'] = $levelPromote[2];
$page = set_pagination($count, $row, $parameter);
if ($page) {
$this->assign('_page', $page);
}
$this->assign('data',$rs);
$this->assign('promoteNameArr',$promoteNameArr);
return $this->display();
}
@ -1710,7 +1725,6 @@ class DownloadController extends BaseController {
$this->orderlistExcelInfo($id,$map);
break;
default:
var_dump('ss');die();
break;
}

@ -24,7 +24,7 @@ class FinanceController extends BaseController
//权限过滤
private function purview()
{
$this->loginPromote = $this->getLoginPromote();
$this->getLoginPromote();
if ($this->loginPromote['level'] != 1) {
$this->error('权限异常');
}
@ -80,7 +80,7 @@ class FinanceController extends BaseController
//是否是会长
$this->purview();
//验证安全密码
$metaTitle = '结算明细';
$metaTitle = '结算中心';
$modelList = ['财务管理', $metaTitle];
$this->verifyPasswordView($modelList);

@ -137,7 +137,6 @@ class HomeController extends Controller
$code = I('code', '');
$gameId = I('gid', 0);
$promoteId = I('pid', 0);
if ($code == '' && ($gameId == 0 || $promoteId == 0)) {
$this->error('访问错误');
}
@ -214,7 +213,7 @@ class HomeController extends Controller
$this->assign('isAndroid', $isAndroid);
$this->assign('apply', $apply);
$this->assign('game', $game);
$this->display();
$this->display('landingPage');
}

@ -151,7 +151,7 @@ class PromoteController extends BaseController
count(IF(register_time ' . $today . ',1,null)) as today,
count(IF(register_time ' . $week . ',1,null)) as week,
count(IF(register_time ' . $mounth . ',1,null)) as mounth')
->join("tab_promote AS tp2 ON tp2.`chain` LIKE CONCAT('%/', tp1.id, '/%')", 'left')
->join("tab_promote AS tp2 ON tp2.`chain` LIKE CONCAT('%/', tp1.id, '/%') OR tp1.id=tp2.id", 'left')
->join("tab_user as u on tp2.id = u.promote_id", 'left')
->join(false)
->where($map)
@ -319,7 +319,7 @@ class PromoteController extends BaseController
$promote_map = "tp1.`id` = {$promote_id}";
$data = $spend->field('sum(a.scount) AS count,sum(a.today) AS today,sum(a. WEEK) AS WEEK,sum(a.mounth) AS mounth')
->join("INNER JOIN (SELECT tp2.*, tp1.id AS pid, tp1.account as promote_account FROM tab_promote tp1 LEFT JOIN tab_promote tp2 ON tp2.`chain` LIKE CONCAT('%/', tp1.id, '/%') where $promote_map ) AS t ON promote_id = t.id")
->join("INNER JOIN (SELECT tp2.*, tp1.id AS pid, tp1.account as promote_account FROM tab_promote tp1 LEFT JOIN tab_promote tp2 ON tp2.`chain` LIKE CONCAT('%/', tp1.id, '/%') OR tp1.id = tp2.id where $promote_map ) AS t ON promote_id = t.id")
->where($condition)->table('(' . $spendData . ') as a')->group()->order('count desc,a.ordertime')->find();
$spendData1 = $spend->field('sum(a.scount) AS count,sum(a.today) AS today,sum(a. WEEK) AS WEEK,sum(a.mounth) AS mounth')
@ -867,7 +867,6 @@ class PromoteController extends BaseController
$realName = I('real_name', '');
$status = I('status', 'all');
$promoteType = I('promote_type', 0);
$loginer = $this->getLoginPromote();
$map = [];
@ -950,6 +949,8 @@ class PromoteController extends BaseController
$this->assign('count', $count);
$this->assign('pagination', $pagination);
$this->assign('records', $records);
$this->assign('promoteType',$promoteType);
$this->assign('promoteTypeTitle',$promoteTypeTitle);
$this->display();
}
@ -1077,6 +1078,16 @@ class PromoteController extends BaseController
public function edit_chlid($id = 0)
{
$promoteType = $_REQUEST['promote_type'];
if($promoteType == 0) {
$promoteTypeTitle = "部门长管理";
}
if($promoteType == 1) {
$promoteTypeTitle = "组长管理";
}
if($promoteType == 2) {
$promoteTypeTitle = "推广员管理";
}
if (IS_POST) {
$type = $_REQUEST['type'];
$map['id'] = $id;
@ -1185,7 +1196,7 @@ class PromoteController extends BaseController
} else {
$promote = A('Promote', 'Event');
$this->meta_title = '子帐号';
$promote->baseinfo('edit_chlid', $id);
$promote->baseinfo('edit_chlid', $id,$promoteTypeTitle);
}
}

@ -17,11 +17,12 @@ class PromoteEvent extends BaseEvent {
/**
获取基本信息
*/
public function baseinfo($tem_edit,$id=0) {
public function baseinfo($tem_edit,$id=0,$promotetitle=0) {
$model = M('Promote','tab_');
$data = $model->find($id);
$data['bank_area'] = explode(',', $data['bank_area']);
$this->assign("data",$data);
$this->assign('promotetitle',$promotetitle);
$this->display($tem_edit);
}

@ -1,10 +1,35 @@
<extend name="Public/promote_base"/>
<block name="css">
<link href="__CSS__/20180207/data.css" rel="stylesheet">
<link href="__CSS__/20180207/manager.css" rel="stylesheet">
<link href="__CSS__/20180207/finance.css" rel="stylesheet">
<link href="__STATIC__/icons_alibaba/iconfont.css" rel="stylesheet">
<link href="__STATIC__/icons_alibaba/iconfont.css?v=1.2" rel="stylesheet">
</block>
<block name="body">
<style>
@media screen and (max-width: 1500px) {
.normal_form {
padding-top: 45px;
}
.trunk-search .normal_txt {
width: 100px
}
.select2-container--default .select2-selection--single {
width: 125px;
}
.trunk-search .select-time .txt {
width: 100px;
}
.form-group .submit {
width: 55px;
}
}
.selected-color {
color: #2bd8ed;
}
@ -20,18 +45,22 @@
float: right;
right: 10px;
}
.current {
display: inline-block;
margin-right: 10px;
padding-left: 10px;
padding-right: 10px;
height: 34px;
border: 1px solid #E5E5E5;
color: red;
border-radius: 4px;
line-height: 34px;
text-align: center;
.th-hide {
display: none;
}
.form-group {
float: left;
margin-bottom: 10px;
}
.form-group label {
line-height: 34px;
height: 34px;
}
.form-group .txt {
width: 180px;
height: 34px;
}
.chakan {
display: inline-block;
@ -47,40 +76,33 @@
}
</style>
</block>
<block name="body">
<div class="page-search normal_list query-register-search">
<div class="trunk-title">
<div class="location">
<div class="location-container">当前位置:<span>下载管理></span><span>控制台</span></div>
</div>
<img src="__IMG__/20180207/icon_zhuce.png">
<span class="title_main">下载日志</span>
<span class="details">记录数据管理中导出数据事件</span>
</div>
<div class="page-search normal_list query-recharge-search jssearch">
<div class="trunk-title">
<div class="location">
<div class="location-container">当前位置:<span>下载管理></span><span>控制台</span></div>
</div>
<img src="__IMG__/20180207/icon_zhuce.png">
<span class="title_main">下载日志</span>
<span class="details">记录数据管理中导出数据事件</span>
</div>
<div class="trunk-content article">
<div class="trunk-search clearfix">
<form action="{:U('download/listsIndex')}" method="post" enctype="multipart/form-data">
<div class="tab normal_tab">
</div>
<!-- <form action="{:U('Finance/settlementDtl')}" method="get" enctype="multipart/form-data" class="normal_form"> -->
<div class="form-group fl">
<div class="form-group normal_space">
<input type="text" name="dataname" class="txt normal_txt" id="uid" placeholder="请输入数据名称"
value="{:I('dataname')}">
</div>
<div class="form-group fl" style='margin-left:10px'>
<div class="form-group normal_space" style='margin-left:10px'>
<input type="text" name="logid" class="txt normal_txt" id="lid" placeholder="输入日志编号"
value="{:I('logid')}">
</div>
<!-- <div class="form-group fl" style="margin-left:10px">
<select id="pid" name="pid" class="reselect select_gallery" style="min-width:200px;width: 175px;">
<option value="0">请选择推广员</option>
<volist name="promoteNameArr" id="vo">
<option value="{$vo.promote_id}" title="{$vo.name}">{$vo.name}</option>
</volist>
</select>
</div>-->
<input type="hidden" id="top-promote-id" value="{$loginer.id}">
<input type="hidden" id="top-promote-id" value="{$loginer.id}">
<if condition="$loginer.level elt 1">
<div class="form-group fl" style="margin-left:10px">
<select name="level_promote_2" class="level-promote reselect select_gallery" style="width: 220px;" data-level="2" data-val="{:I('level_promote_2', 0)}">
@ -103,80 +125,82 @@
</div>
</if>
<div class="form-group normal_space fl">
<label class="form-title select-title" style="position: relative;">申请时间:</label>
<div class="select-time">
<input type="text" id="sdate" class="txt" name="begtime" placeholder="开始时间" value="{:I('begtime')}" autocomplete="off">
</div>
<label class="form-title select-title zhi_color">&nbsp;&nbsp;</label>
<div class="select-time">
<input type="text" id="edate" class="txt" name="endtime" placeholder="结束时间" value="{:I('endtime')}" autocomplete="off">
</div>
</div>
<div class="form-group normal_space fl">
<input type="submit" class="submit" id='submit' value="查询">
<div class="form-group normal_space">
<label class="form-title select-title" style="position: relative;">下载时间:</label>
<div class="select-time">
<input type="text" readonly id="sdate" class="txt" name="begtime" placeholder="开始时间" value="{:I('begtime')}">
</div>
<label class="form-title select-title zhi_color">&nbsp;&nbsp;</label>
<div class="select-time">
<input type="text" readonly id="edate" class="txt" name="endtime" placeholder="结束时间" value="{:I('endtime')}">
</div>
</div>
</form>
<div class="form-group normal_space">
<input type="submit" class="submit" id='submit' url="{:U('download/listsindex','model='.$model['name'],false)}"
value="查询">
</div>
<!-- </form> -->
</div>
</div>
<div class="page-list query-register-list">
<div class="trunk-content article">
<div class="trunk-list list_normal" style="">
<table class="table normal_table">
<tr class="odd">
<th>ID</th>
<th>报表类型</th>
<th>操作人</th>
<th>申请时间</th>
<th>下载时间</th>
<th>状态</th>
</tr>
<empty name="data">
<tr class="num2">
<td colspan="8" style="text-align: center;height: 45vh;">
<img src="__IMG__/20180207/icon_wushujv2.png"/>
<p style="line-height: 40px;color: #A5A5A5;">暂无数据</p>
</td>
</tr>
<else/>
<volist name="data" id="vo">
<tr class="num2">
<td>{$vo.logid}</td>
<td>{$vo.dataname}</td>
<td>{$vo.actor}</td>
<td>{$vo.addtime|date='Y-m-d H:i:s',###}</td>
<td>
<if condition="$vo['begintime'] neq 0">
{$vo.begintime|date='Y-m-d H:i:s',###}
<else />
暂无下载时间
</if>
<div class="page-list apply-app_apply-list query-recharge-list">
<div class="trunk-content article" style="margin-left: 0;margin-right: 0;">
<div class="tabcon trunk-list">
<table class="table normal_table">
<tr class="odd">
<th>ID</th>
<th>报表类型</th>
<th>操作人</th>
<th>申请时间</th>
<th>下载时间</th>
<th>状态</th>
</tr>
<empty name="data">
<tr class="num2">
<td colspan="8" style="text-align: center;height: 45vh;">
<img src="__IMG__/20180207/icon_wushujv2.png"/>
<p style="line-height: 40px;color: #A5A5A5;">暂无数据</p>
</td>
<td>
<if condition="$vo['status'] eq 0">
<a href="{:U('download/export',array('conditions'=>$vo['conditions'],'id'=>$vo['id'],'dataname'=>$vo['dataname']))}" onclick="reload()" style="cursor: pointer"
class="chakan"><span>可下载</span></a>
<else /> <a href="javascript:;" class="current"><span style="color:#9D9D9D">已下载</span></a>
</if>
</td>
</tr>
</volist>
</empty>
</table>
</div>
<div class="pagenation clearfix">
{$_page}
</tr>
<else/>
<volist name="data" id="vo">
<tr class="num2">
<td>{$vo.logid}</td>
<td>{$vo.dataname}</td>
<td>{$vo.actor}</td>
<td>{$vo.addtime|date='Y-m-d H:i:s',###}</td>
<td>
<if condition="$vo['begintime'] neq 0">
{$vo.begintime|date='Y-m-d H:i:s',###}
<else />
暂无下载时间
</if>
</td>
<td>
<if condition="$vo['status'] eq 0">
<form action="{:U('download/export',array('conditions'=>$vo['conditions'],'id'=>$vo['id'],'dataname'=>$vo['dataname']))}" method="post" id="downloadForm">
<a style="cursor: pointer" onclick="reload()" target="_blank" class="chakan"><span>可下载</span></a>
</form>
<else /> <a href="javascript:;" class="current"><span style="color:#9D9D9D">已下载</span></a>
</if>
</td>
</tr>
</volist>
</empty>
</table>
</div>
<div class="pagenation clearfix">
{$_page}
</div>
</div>
</div>
</div>
</div>
</block>
<block name="script">
<link href="__STATIC__/datetimepicker/css/datetimepicker.css" rel="stylesheet" type="text/css">
@ -185,15 +209,21 @@
<script type="text/javascript" src="__STATIC__/datetimepicker/js/locales/bootstrap-datetimepicker.zh-CN.js"
charset="UTF-8"></script>
<script type="text/javascript" src="__JS__/20170831/select2.min.js"></script>
<script type="text/javascript" src="__JS__/common.js"></script>
<script src="__STATIC__/layer/layer.js"></script>
<script type="text/javascript" src="__JS__/common.js"></script>
<script type="text/javascript">
var promoteUrl = "{:U('Query/getSubPromotes')}"
initPromoteSelect(promoteUrl)
$().ready(function () {
setValue('team_leader_id', {$Think.request.team_leader_id |default = '""'});
setValue('promote_id', {$Think.request.promote_id |default = 0});
setValue('row', '{:I("get.row",10)}');
$("#pagehtml a").on("click", function (event) {
event.preventDefault();//使a自带的方法失效即无法调整到href中的URL(http://www.baidu.com)
var geturl = $(this).attr('href');
$('#data_form').attr('action', geturl);
$('#data_form').submit();
});
var date = "{$setdate}";
$('#sdate').datetimepicker({
format: 'yyyy-mm-dd',
@ -218,49 +248,41 @@
endDate: date
});
$('#own').on('click',function () {
var ownId = $('#own_id').val();
var checkBox = $(this).children('i');
$('#submit').click(function () {
var sdate = Date.parse($('#sdate').val()) / 1000;
var edate = Date.parse($('#edate').val()) / 1000;
if (ownId > 0) {
checkBox.removeClass('iconfangxingxuanzhongfill');
checkBox.removeClass('selected-color');
checkBox.addClass('iconfangxingweixuanzhong');
if (sdate > edate) {
layer.msg('开始时间必须小于等于结束时间', {icon: 5});
return false;
}
if ((edate - sdate) > 2592000) {
layer.msg('时间间隔不能超过31天请重新选择日期', {icon: 5});
return false;
}
$('#own_id').val(0);
var url = $(this).attr('url');
console.log(url);
var query = $('.jssearch').find('input').serialize();
query += "&" + $('.jssearch').find('select').serialize();
query = query.replace(/(&|^)(\w*?\d*?\-*?_*?)*?=?((?=&)|(?=$))/g, '');
query = query.replace(/^&/g, '');
if (url.indexOf('?') > 0) {
url += '&' + query;
} else {
checkBox.removeClass('iconfangxingweixuanzhong');
checkBox.addClass('iconfangxingxuanzhongfill');
checkBox.addClass('selected-color');
$('#own_id').val({$pID});
url += '?' + query;
}
});
console.log(url)
window.location.href = url;
$("#pagehtml a").on("click", function (event) {
event.preventDefault();//使a自带的方法失效即无法调整到href中的URL(http://www.baidu.com)
var geturl = $(this).attr('href');
$('#data_form').attr('action', geturl);
$('#data_form').submit();
});
$(".select_gallery").select2();
$('.submit').click(function () {
var sdate = $('#sdate').val();
var edate = $('#edate').val();
if (Date.parse(sdate) > Date.parse(edate)) {
layer.msg('开始时间必须小于等于结束时间');
return false;
}
});
});
</script>
<script>
setValue('pid', {$Think.request.pid |default = '""'});
</script>
<script>
function reload() {
function reload() {
document.getElementById('downloadForm').submit()
setTimeout(function(){ window.location.reload(); }, 7000);
}
</script>

@ -51,7 +51,7 @@
}
if ($('input[name=isIOS13]').val() == 1) {
if (parseInt("{:I('get.status')}") > 0) {
location.href = "{:U('iosDown',array('gid'=>$gameId,'pid'=>I('get.pid'),'status'=>1))}"
location.href = "{:U('iosDown',array('gid'=>$apply['game_id'],'pid'=>$apply['promote_id'],'status'=>1))}"
return
} else {
layer.confirm('请先到官网注册', {title: '提示'}, function () {

@ -83,7 +83,7 @@
</td>
<td>{$record.create_time|date='Y-m-d H:i:s',###}</td>
<td>
<a href="{:U('Promote/edit_chlid','id='.$record['id'])}" class="editbtn">修改</a>
<a href="{:U('Promote/edit_chlid',['id'=>$record['id'],'promote_type'=>$promoteType])}" class="editbtn">修改</a>
<if condition="$record['status'] eq 1">
<a href="javascript:;" class="froze-btn editbtn">冻结</a>
<elseif condition="$record['status'] eq 2"/>

@ -8,7 +8,7 @@
<div class="page-list normal_list promote-edit_chlid-form">
<div class="trunk-title">
<div class="location">
<div class="location-container">当前位置:<span>管理中心></span><span>二级渠道></span><span>修改子渠道</span></div>
<div class="location-container">当前位置:<span>管理中心></span><span>{$promotetitle}></span><span>修改子渠道</span></div>
</div>
<img src="__IMG__/20180207/icon_normal_ziqudao.png"><span class="title_main">修改子渠道</span>
</div>

@ -79,10 +79,10 @@
<div class="page-search normal_list query-recharge-search jssearch">
<div class="trunk-title">
<div class="location">
<div class="location-container">当前位置:<span>数据管理></span><span>数据汇总</span></div>
<div class="location-container">当前位置:<span>数据管理></span><span>{$meta_title}</span></div>
</div>
<img src="__IMG__/20180207/icon_chongzhi.png">
<span class="title_main">数据汇总</span>
<span class="title_main">{$meta_title}</span>
<span class="details">说明:默认展示旗下各子渠道的全部数据</span>
</div>
<div class="trunk-content article">

@ -139,7 +139,7 @@
</div>
</div>
</notempty>
<div class="hd_title mt35">
<!-- <div class="hd_title mt35">
<span class="title">
<span class="line"></span>
发表评论
@ -154,7 +154,7 @@
var width = window.innerWidth || document.documentElement.clientWidth;
if (width < 960) {
window.document.write('<script id="changyan_mobile_js" charset="utf-8" type="text/javascript" src="http://changyan.sohu.com/upload/mobile/wap-js/changyan_mobile.js?client_id=' + appid + '&conf=' + conf + '"><\/script>'); } else { var loadJs=function(d,a){var c=document.getElementsByTagName("head")[0]||document.head||document.documentElement;var b=document.createElement("script");b.setAttribute("type","text/javascript");b.setAttribute("charset","UTF-8");b.setAttribute("src",d);if(typeof a==="function"){if(window.attachEvent){b.onreadystatechange=function(){var e=b.readyState;if(e==="loaded"||e==="complete"){b.onreadystatechange=null;a()}}}else{b.onload=a}}c.appendChild(b)};loadJs("http://changyan.sohu.com/upload/changyan.js",function(){window.changyan.api.config({appid:appid,conf:conf})}); } })(); </script>
</div>
</div>-->
</div>
<div class="fr hotgame">
<div class="hot_title">

@ -44,7 +44,7 @@
</div>
</div>
<!-- 侧导航 -->
<div class="side_tabbar" style="z-index: 1">
<a class="side_tabbar" style="z-index: 1" href="http://wpa.qq.com/msgrd?v=3&amp;uin={:C('PC_SET_SERVER_QQ')}&amp;site=qq&amp;menu=yes" target="_blank">
<img src="__IMG__/index_about/qrcode.png" alt="">
</div>
</a>
</block>

@ -48,6 +48,22 @@ class SsgController extends BaseController {
}
public function home(){
if (I('user_token')) {
$userToker = I('user_token');
$where['user_token'] = $userToker;
$isToken = M('user','tab_')->field('id as user_id,account,nickname')->where($where)->find();
if ($isToken) {
session("user_auth",$isToken);
$this->redirect("Ssg/index");
} else {
$this->redirect("Ssg/login");
}
}
//获取客服qq
$appqq = M("config", "sys_")->field('value')->where("name='APP_QQ'")->find()['value'];
$promoteId = I("promote_id", 0);

@ -272,7 +272,7 @@ class UserController extends BaseController
$post = I('post.');
$account = $post['nickname'];
$password = $post['password'];
$sex = $post['sex'];
$sex = isset($post['sex']) ? $post['sex'] : 0;
if (empty($account)) {
echo json_encode(array('status' => 0, 'msg' => '请填写昵称'));
exit;
@ -307,13 +307,35 @@ class UserController extends BaseController
*/
public function register()
{
$safeinfo = session('safeinfo');
if ($safeinfo['status'] == 1) {
// $safeinfo = session('safeinfo');
// if ($safeinfo['status'] == 1) {
if (IS_POST) {
$post = I('post.');
$account = $post['phone'];
$password = $post['password'];
$sex = isset($post['sex']) ? $post['sex'] : 0;
if (empty($account)) {
echo json_encode(array('status' => 0, 'msg' => '请输入手机号'));
exit;
}
if (empty($password)) {
echo json_encode(array('status' => 0, 'msg' => '请输入密码'));
exit;
}
$promoteId = I('post.promote_id');
$promoteId = intval($promoteId);
if ($promoteId > 0) {
$gameId = intval(I('post.game_id'));
$safeinfo = array('nickname' => $account, 'password' => $password, 'sex' => $sex, 'status' => 1, 'promote_id' => $promoteId, 'game_id' => $gameId);
} else {
$safeinfo = array('nickname' => $account, 'password' => $password, 'sex' => $sex, 'status' => 1);
}
$phone = $post['phone'];
$safecode = $post['code'];
$nickname = $safeinfo['nickname'];
$nickname = 'U_' . substr($safeinfo['nickname'],-4);
$password = $safeinfo['password'];
$sex = $safeinfo['sex'];
@ -423,9 +445,9 @@ class UserController extends BaseController
$this->assign('url', $url);
$this->display();
}
} else {
$this->redirect(U('step'));
}
// } else {
// $this->redirect(U('step'));
// }
}
/**
@ -438,7 +460,8 @@ class UserController extends BaseController
if (IS_POST) {
$post = I('post.');
$account = $post['account'];
$nickname = $post['nickname'];
// $nickname = $post['nickname'];
$nickname = 'U_' . substr($account,-4);;
$password = $post['password'];
$sex = $post['sex'];

@ -9,7 +9,8 @@
<title>订单详情</title>
<link href="__CSS__/ssg/common.css" rel="stylesheet" type="text/css">
<script src="/Public/Mobile/js/ssg/flexible.min.js" type="text/javascript"></script>
<link href="__CSS__/common-cz.css" rel="stylesheet" >
</head>
<body class="install-box">
<div class="title" >
@ -58,11 +59,13 @@
<script src="__JS__/jquery-1.11.1.min.js" type="text/javascript"></script>
<script src="__JS__/ssg/clipboard.min.js" type="text/javascript"></script>
</body>
<div class="popmsg pop-dialog"></div>
<script src="__JS__/pop.lwx.min.js"></script>
<script>
var pmsg = $('.popmsg').pop();
var clipboard = new ClipboardJS(".code-btn1455");
clipboard.on('success', function (e) {
alert("复制成功");
pmsg.msg("复制成功");
});
clipboard.on('error', function (e) {
var ua = navigator.userAgent;

@ -97,7 +97,7 @@
</div>
<div class="formitem">
<img src="__IMG__/ssg/login/password.png">
<input id="phonepassword" type="password" placeholder="请输入6-12位字母组合密码" value="">
<input id="phonepassword" type="password" placeholder="请输入6-12位密码" value="">
</div>
<div class="formitem" style="border: 0px;">
<div class="formitem" style="margin-right: .2rem;margin-top: 0px;width: 3.5rem;">
@ -135,11 +135,11 @@
</div>
<div class="formitem" style="margin-top: 0px;">
<img src="__IMG__/ssg/login/user.png">
<input id="regaccount" type="text" placeholder="请输入账号(6-12位字母数字组合)" value="">
<input id="regaccount" type="text" placeholder="请输入账号(6-15位字母数字组合)" value="">
</div>
<div class="formitem">
<img src="__IMG__/ssg/login/password.png">
<input id="regpassword" type="password" placeholder="请输入6-12位字母组合密码" value="">
<input id="regpassword" type="password" placeholder="请输入6-12位密码" value="">
</div>
<div class="formitem">
<img src="__IMG__/ssg/login/password.png">
@ -267,15 +267,15 @@ var PhoneObj = {
},
checkPassword(password){
console.log(password);
if(password.length < 6 || password.length > 15){
alert('密码长度6-15个字符');
return false;
}
var pwdRegex = new RegExp('(?=.*[0-9])(?=.*[a-zA-Z])');
if (!pwdRegex.test(password)) {
alert("您的密码复杂度太低(密码中必须包含字母、数字)!");
if(password.length < 6 || password.length > 12){
alert('密码长度6-12个字符');
return false;
}
// var pwdRegex = new RegExp('(?=.*[0-9])(?=.*[a-zA-Z])');
// if (!pwdRegex.test(password)) {
// alert("您的密码复杂度太低(密码中必须包含字母、数字)!");
// return false;
// }
var chinaRex = new RegExp("[\\u4E00-\\u9FFF]+","g");;
if (chinaRex.test(password)) {
alert("密码不允许含有中文字符!");
@ -435,12 +435,12 @@ var PhoneObj = {
var regpassword2 = $("#regpassword2").val();
var promoteId = $("#promote_id").val();
var pwdRegex = new RegExp('(?=.*[0-9])(?=.*[a-zA-Z])');
if(account.length < 6 || account.length > 12){
alert('账号长度必须是6-12位');
if(account.length < 6 || account.length > 15){
alert('账号长度必须是6-15位');
return false;
}
if (!pwdRegex.test(account)) {
alert("账号必须是6-12位字母数字组合!");
alert("账号必须是6-15位字母数字组合!");
return false;
}
if(!PhoneObj.checkPassword(regpassword)){

@ -31,7 +31,7 @@
<if condition="I('get.pid') gt 0">
<div class="promptly">还没有账号?<a style="margin-left: 10px;" href="<?='mobile.php?s=/User/step1/pid/'.I('get.pid').'/gid/'.I('get.gid').'.html'?>"> 账号注册 </a>|<a href="<?='mobile.php?s=/User/step/pid/'.I('get.pid').'/gid/'.I('get.gid').'.html'?>"> 手机注册 </a></div>
<else/>
<div class="promptly">还没有账号?<a style="margin-left: 10px;" href="{:U('User/step1')}"> 账号注册 </a>|<a href="{:U('User/step')}"> 手机注册 </a></div>
<div class="promptly">还没有账号?<a style="margin-left: 10px;" href="{:U('User/step1')}"> 账号注册 </a>|<a href="{:U('User/register')}"> 手机注册 </a></div>
</if>
</div>
</div>

@ -28,11 +28,16 @@
<div class="subpage-heard">手机注册
<a href="javascript:window.history.go(-1);" class="arrows"></a>
</div>
<div class="login-box">
<div class="login-input">
<img src="__IMG__/user/shouji.png" alt="">
<input type="text" id="mobile" placeholder="请输入手机号">
</div>
<div class="login-input">
<img src="__IMG__/user/suo.png" alt="">
<input id="password" type="password" placeholder="请输入密码">
</div>
<div class="login-code">
<input id="code" type="text" placeholder="输入验证码">
<div class="jsgetcode">获取验证码</div>
@ -85,12 +90,19 @@
$('.submit').click(function(event) {
var mobile = $.trim($('#mobile').val());
var code = $.trim($('#code').val());
var password = $.trim($('#password').val());
var promoteId = parseInt("{:I('get.pid')}") ? parseInt("{:I('get.pid')}") : 0;
var gameId = parseInt("{:I('get.gid')}") ? parseInt("{:I('get.gid')}") : 0;
if(password.length == 0){
pmsg.msg('密码不能为空');event.preventDefault();
return false;
}
if (mobile) {
if (code) {
$.ajax({
type:'POST',
url:'{:U("register")}',
data:{'phone':mobile,'code':code},
data:{'phone':mobile,'code':code,'password':password,'promote_id':promoteId,'game_id':gameId},
dataType:"Json",
success:function(data){
if(data.status == 1){

@ -28,10 +28,10 @@
<img src="__IMG__/new/suo.png" alt="">
<input type="password" placeholder="请输入密码" name="password" id="password" value="">
</div>
<div class="login-input">
<!--<div class="login-input">
<img src="__IMG__/new/nicheng.png" alt="">
<input type="text" placeholder="请输入昵称" name="nickname" id="nickname" value="">
</div>
</div>-->
<!-- <div class="login-gender">
<div class="title">
<img src="__IMG__/new/xingbie.png" alt="">
@ -81,10 +81,10 @@
pmsg.msg('账号不能为空');event.preventDefault();
return false;
}
if(nickname.length == 0 ){
/*if(nickname.length == 0 ){
pmsg.msg('昵称不能为空');event.preventDefault();
return false;
}
}*/
if(password.length == 0){
pmsg.msg('密码不能为空');event.preventDefault();
return false;

@ -14,6 +14,7 @@ class GameGiftController extends BaseController{
$gift = M("Giftbag","tab_");
$map['game_id'] = $request['game_id'];
$map['status']=1;
$map['giftbag_name'] = ['NEQ','超级签专属礼包'];
$row = $request['row']?:10;
$page = $request['p']?:1;
switch ($request['sdk_version']) {

@ -1 +1 @@
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAv6He7hu2CXe5N0OsyeIBbzT1U4UiJTqiIewNf+6wrNsEm+VYtkybmQ9jdMtOrce/Up/4DmnTMOVMRwQhpdjtaTFGHEYeAHILQOw/DH80zxOukegE7m8xxzETQIkO/3eOFxa+XThP8yWSM8W9oVjOstA+YPzwrq+DA5iVvHl55cU6AhExa+NjVf42x9gzYZZN7v2Y31fm9cw3ejUuEewC58CmrGeua4Lj44kiwwNBvk8Sbwym1u7fCGEOoGWCRXkOh4w3PgMA5UKjVlVgF6jhjkswxmHnH0pMctpcjar8uw0ljxr+d5th+fqydtpzs8HP6Q2KiqHgUZW4EwP74gSH9wIDAQAB
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAj1gR40ZrH2ZoHTmKAhiEcPEsc0vM7Wbeui8SBrjntEVjHCLF4mE9u9V7uYyrs0b/RGlh5Lxqe3AuterzAWOHGTckg2GOXXRagYYekpTl77fTLmm99vI+uTA7mjvs0PLm39/MjuK5hIr39eQgctXM+m4oxSht5hIGahyC9nk5uId0b1oae+tAtT7mBl/9N9rcsDuoNlX447IjDsi/WxKMsI6C2rI+b6p2BBG46550s/9mwrCpWHHeu7jOx9gS8501axUd4cjqOLRlxPuEO4Il6ZCnsI2U91/G4tKgjgXkNdTGXqP+vqvm7MzpYL3SMmqyboEJdKa3vDbQAcfThSPrQwIDAQAB

@ -1 +1 @@
MIIEogIBAAKCAQEA1Z9aMc9T0wVgQTiJ4iiwfpeJD7VGi4Xe6sxGAwqQlNkM799maxc97+JJ5m0KAxUSAZL5gb7Ydba3oxETpwF5G6G2PGCFM/5YWqYWjzYgApEeMcXkKE002mT4UoXSZsUHZEONC2Q1hRzgks4woT1KLc/3TRV5Z7Tz9XHDQQmWvBeV1oU7JkmASbqam8cocIgGQ/RsiiF18jqdLbw3D0LPxyWBrEcj8TEdoDc/kBATXYE4oezjVQZ1QKmd5z7NkdEXWQiNshsuCiNsLUlg9k/0awOOD+kXiDJqo4FQ0QnyFsEQk5z4WaDwwamB2EuijOD8DTynX0/MAIZWNvHemQ6mCQIDAQABAoIBAEJBCBJGwTLDihTwWiNgh0zb5tCOYnDHdlnQPS6YSjtADjkfSn6QWM9bmZvz2ZUXJdyDHwtUi4IGx3G1zCiR1mPxhbm4HdgAXJrQxFJqcQcaxwic3aR6PZg2lKXTh2wEU8SPBuGvlMHSMPyXIpH/llAbHhI0RNEbWEaZn/s95Bg1j03w+bMi71yO3TuMwSNHWoJ2i6PpGjsKzaJLxFwwDaxPgA8TuiMXGnQI0Adu1O4zTxU8XAWK4ndZSfp2wIzsNj7rCEKYMlduOlGZigOv0wykallWyX3LtjcV6EkxN2IyrdvI1vhKFkpZk1Q4KxORA6IlH7QjfEv33dr+7MDAyQECgYEA8N7Rds9s0kvn/7DzI+7Yj3YWVxrPyADm5INfxDt1TgjIgftngFos2Suc7VgKFgf0Qkj/HO6RG9Mei68fNjzoiEHGwYSs02gPVf6hYKDoNZ7aI7F45jEETNh9gYF9Wny9YnohknNknLF8b9tWVHuvCoWPSShD11fYiHKMzJcwwTkCgYEA4wpjpNnjrRDc73kSriG1ImWR71FIr2BsrPBE8EVtT2kbhuAOWZ+dpsfWf3S4EvvsduHQqlcoMa0S84qo76zPVGKiAZvhghwQSUS/yPOsIBK5XEqGORdvju8PNA32VIEgXr8+qCiSPf3j5ik/XuWkNnV0qyccrQ1iVqknvL7Em1ECfxpYRJC6HyzhIH7W28ESXp1STR85z4AQmTBlLhRIbIwcadHNrYRcWItoOcG7316JgC2/zidb8IMalDyy6rcD8mr0xshjuoNk3kiJkR0AfGVg+nrs7kw/EDlXdGK1xwAepJggw4tBE8APqYyScN7MqFh+Qy29Oa5T7Vr/LGc0IiECgYEAj3CX5aXXZxb5Tr6iY6teIf4jxhwHnO2Bm30tQNPMLNiOEJdr2Ymzc5Rb2yilxzCsg6tFRulLtp7PE1juRIZccsbh7bxLLAWI8JFjzZTNkXHi9AENbfJ1g8tbQprznw35ooKXFmyTgGDwZBB5Pf490j5A2IUcY+TJ1VCHj4LC+hECgYEA2rbro3rRBmg+OPRqiGbwq1s/LWrP4hAKeIsKAH1nRsTs1p1EWMVCPWgJtDFWusafRp8ABDDsgaoKS1y/C58+vX3GBcc8CKaJpAetumKRJhqebCY2AEa6qd1lpiWduAydMHm9Ty/4gqXdVZvZ5TfCmo4nHLFXY4LYo9TRAKOO4QQ=
MIIEogIBAAKCAQEA1xgiAwoD6s2UuB/eWyc1cA1vPxtTBYV2fkyBGWpSd8FHzDDzDE7aiKZ1jwOYTsLultNjG7lpJUQqnXX8B8N/uQsW2LVntM7Ry0NMRtYrQnfkaCucTUyjlHSpn+JlOwMzCWF78+b4UuHarmJgc6yqtljL/Sj0wmA8hGxyam37zAPGNKbCZg1xgbO5zSON3zt9+RXfvkSjQlRzZz2LcuWklaa617DvZWxGP6a43hukqbXA1zOwnA3nCm049u0cyrlh9BM/kudRoJqOblu+Qgr4+CKq4FkYDae3EGACqU1xmamQGFVf1fCz55dn8a5E9K0G/PzPbCsAsh4dr9iGc7gzsQIDAQABAoIBACOmPkzephOOiy2RKptU/khaEawV7Uam/iKkr2j09EIg6LNxEXdiwlmPrUBMyjuTl1OsKWr46fJhP+blHSZ0QoD604iLWGrhNGhJ+SRsbrMPh+2z/K3bG+mJBGwZa8nCF/1gCNk92L5z7HimmXHSlmCuivCkjxyAMseH6da179u6HppLYBXpuc0TOwlc1iEzrAb2PdRSq57wYxAOXOtOASmZtmJykaZzemVfS7gyRQQvY5Utl4H0+CiourXrZMV22LMVaDhrQl903R1vMDruX8GbQ2JNiObUh0k6oUpuCl89nZq12B/5RmGZ7BU9KOKYW0gfiVrlVPDPxWzRxj8isAECgYEA8LtgUxuRX4XEEshPqCHwXl6LuUzv79hPni3as/YKGZ9SEvaVsS/BKLEhD5qh5679/SpXmXSY7bCvgxH2Hrni4JWfa7nmQbSzraU1Xt4lP0AvX2MSoa6cOKkIsSKIBPgtgVpdCkatqtl6MuObu4lbrWyMyZydTH9nlcTvu7BqfDECgYEA5Lx+JDgC73YLFVol+X0lGisB9ApHLISOhPyj6ilnVu64lg7OgIHQncvClVYwaXE10Etmd8uTeAQSklaD0ilDh2dz/D996K/SB7a2Vhn4/Pu1hbaqjXWvGlaD5cs6xq3VsR7ldbYR0PESFySTE3EKCObeAVKT4fbtQE2J1Vjkz4ECgYEAt23/YrQh3Ehf8/PgBnv93Npr2wEN3pLTb/L+r5utbIKilkKAI2gA5dG6IFqyPYhwjkSCRTK8CHlV8yhvglAf2QMJW5tmIPDg7FJzTVs1xHFS53rlSn9zGBVswxRN0oOMoQDK3jamxAU8gKRAGPD8AzQwPrtwfEakFlHeXgR5zzECgYEAqD2sWl+IaTFd/ZqNC/DsdU7k5OcaarglS9O3jOhfRiXYRyck5IiXNTlGKil2+ld2yXpsJ/jowwHb1x8jXlVTgiipuwPITHnl9h6CBtqbtRg+79bno5zH6otwAHl3BeOepeSfyfDdMd3e/H6+XzJpuxp0eGyQsUe6Qe3GT9JOmgECfwxTUYt2HULi5Njc+cPw1gTUpo80iJKhdfgGNPjOSDRyWgrlTa5329plJdMPQMOWY8/mh/V5IYzFqdPsolCCQbCQ58Z1NpOzZ7/YQUkZXbY1KBYgEMhmWSPbSVyVi4hHkaWg6U/o/XmcIRgliZZIHeyh0T42SyR2y60Bu7GMid0=

@ -0,0 +1,6 @@
-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCnxj/9qwVfgoUh/y2W89L6BkRA
FljhNhgPdyPuBV64bfQNN1PjbCzkIM6qRdKBoLPXmKKMiFYnkd6rAoprih3/PrQE
B/VsW8OoM8fxn67UDYuyBTqA23MML9q1+ilIZwBC2AQ2UBVOrFXfFl75p6/B5Ksi
NG9zpgmLCUYuLkxpLQIDAQAB
-----END PUBLIC KEY-----

@ -0,0 +1 @@
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAv6He7hu2CXe5N0OsyeIBbzT1U4UiJTqiIewNf+6wrNsEm+VYtkybmQ9jdMtOrce/Up/4DmnTMOVMRwQhpdjtaTFGHEYeAHILQOw/DH80zxOukegE7m8xxzETQIkO/3eOFxa+XThP8yWSM8W9oVjOstA+YPzwrq+DA5iVvHl55cU6AhExa+NjVf42x9gzYZZN7v2Y31fm9cw3ejUuEewC58CmrGeua4Lj44kiwwNBvk8Sbwym1u7fCGEOoGWCRXkOh4w3PgMA5UKjVlVgF6jhjkswxmHnH0pMctpcjar8uw0ljxr+d5th+fqydtpzs8HP6Q2KiqHgUZW4EwP74gSH9wIDAQAB

File diff suppressed because it is too large Load Diff

@ -0,0 +1 @@
MIIEogIBAAKCAQEA1Z9aMc9T0wVgQTiJ4iiwfpeJD7VGi4Xe6sxGAwqQlNkM799maxc97+JJ5m0KAxUSAZL5gb7Ydba3oxETpwF5G6G2PGCFM/5YWqYWjzYgApEeMcXkKE002mT4UoXSZsUHZEONC2Q1hRzgks4woT1KLc/3TRV5Z7Tz9XHDQQmWvBeV1oU7JkmASbqam8cocIgGQ/RsiiF18jqdLbw3D0LPxyWBrEcj8TEdoDc/kBATXYE4oezjVQZ1QKmd5z7NkdEXWQiNshsuCiNsLUlg9k/0awOOD+kXiDJqo4FQ0QnyFsEQk5z4WaDwwamB2EuijOD8DTynX0/MAIZWNvHemQ6mCQIDAQABAoIBAEJBCBJGwTLDihTwWiNgh0zb5tCOYnDHdlnQPS6YSjtADjkfSn6QWM9bmZvz2ZUXJdyDHwtUi4IGx3G1zCiR1mPxhbm4HdgAXJrQxFJqcQcaxwic3aR6PZg2lKXTh2wEU8SPBuGvlMHSMPyXIpH/llAbHhI0RNEbWEaZn/s95Bg1j03w+bMi71yO3TuMwSNHWoJ2i6PpGjsKzaJLxFwwDaxPgA8TuiMXGnQI0Adu1O4zTxU8XAWK4ndZSfp2wIzsNj7rCEKYMlduOlGZigOv0wykallWyX3LtjcV6EkxN2IyrdvI1vhKFkpZk1Q4KxORA6IlH7QjfEv33dr+7MDAyQECgYEA8N7Rds9s0kvn/7DzI+7Yj3YWVxrPyADm5INfxDt1TgjIgftngFos2Suc7VgKFgf0Qkj/HO6RG9Mei68fNjzoiEHGwYSs02gPVf6hYKDoNZ7aI7F45jEETNh9gYF9Wny9YnohknNknLF8b9tWVHuvCoWPSShD11fYiHKMzJcwwTkCgYEA4wpjpNnjrRDc73kSriG1ImWR71FIr2BsrPBE8EVtT2kbhuAOWZ+dpsfWf3S4EvvsduHQqlcoMa0S84qo76zPVGKiAZvhghwQSUS/yPOsIBK5XEqGORdvju8PNA32VIEgXr8+qCiSPf3j5ik/XuWkNnV0qyccrQ1iVqknvL7Em1ECfxpYRJC6HyzhIH7W28ESXp1STR85z4AQmTBlLhRIbIwcadHNrYRcWItoOcG7316JgC2/zidb8IMalDyy6rcD8mr0xshjuoNk3kiJkR0AfGVg+nrs7kw/EDlXdGK1xwAepJggw4tBE8APqYyScN7MqFh+Qy29Oa5T7Vr/LGc0IiECgYEAj3CX5aXXZxb5Tr6iY6teIf4jxhwHnO2Bm30tQNPMLNiOEJdr2Ymzc5Rb2yilxzCsg6tFRulLtp7PE1juRIZccsbh7bxLLAWI8JFjzZTNkXHi9AENbfJ1g8tbQprznw35ooKXFmyTgGDwZBB5Pf490j5A2IUcY+TJ1VCHj4LC+hECgYEA2rbro3rRBmg+OPRqiGbwq1s/LWrP4hAKeIsKAH1nRsTs1p1EWMVCPWgJtDFWusafRp8ABDDsgaoKS1y/C58+vX3GBcc8CKaJpAetumKRJhqebCY2AEa6qd1lpiWduAydMHm9Ty/4gqXdVZvZ5TfCmo4nHLFXY4LYo9TRAKOO4QQ=

@ -0,0 +1,15 @@
-----BEGIN RSA PRIVATE KEY-----
MIICXQIBAAKBgQDA73uzDUhJXHzYjSiEayXtUZOBH8I2SM8P92jhMJtaplTLqxbY
MjjW75YovHhfYPNwTLyThn+BTgiS1H1lqrkjfRapsksg4q9KurK4/iGlvpkLDMAF
ekOGPQJ5VzbnoX42L/uoZp/Sme/fYHfTefuHuCV82XeMZYjSYob4/Ih2YQIDAQAB
AoGBAJHuEeAycbSbcgrRag4OhVdlVm5aOSmaFJP9DKUXgMol+Qk71UGdawSXnzoc
o+dwi3EreY8UMij5ft6gPmDBqtnupdS2T53G/3hBV4tkBZyeddpLdkoVkHyTbmEN
lg8vJWLcB/AxG6JWOFAqT1ZkIqpdw+UVZqHUfZ8PWYes4hapAkEA4q2xTEaexz+1
UZ9ECwC6De1G/gBfdShV5nS+zHrKAYEDwFmYxRn3ywKbuuHFY0jin0aGzpEHI8/5
o+Za4uoUMwJBANnkadbbvWmBSoWyvoYyEtNfljttmUEX1MtLoctTWLB16PW1GzRD
8we4wCBrTOanKr/9cooh56n77KStqFgZVxsCQD9vJAKYcK6JoZAp5by+g1KKaCeE
qzH6C6/mU86dPhKVrBsT97CQx8tD+5icvcQ/DUxNTERaSYk4FkBLonuFzgkCQQCC
UomzRs6tcfU+rkAiR4TXBA75EH5fXn+Z8GyfDgS31m41t9LDmficH7ZaLZNbSZTa
LB7723eSRemuPWe4+b8NAkArnhIj3pbnzDGyBqhjCUkEtDqAhpVwz9HKEmyewjz3
jK2ebG3dTUAl8vsarOeTloP93ywyOy5xxoqL12PYDK/Y
-----END RSA PRIVATE KEY-----

@ -0,0 +1,6 @@
-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDA73uzDUhJXHzYjSiEayXtUZOB
H8I2SM8P92jhMJtaplTLqxbYMjjW75YovHhfYPNwTLyThn+BTgiS1H1lqrkjfRap
sksg4q9KurK4/iGlvpkLDMAFekOGPQJ5VzbnoX42L/uoZp/Sme/fYHfTefuHuCV8
2XeMZYjSYob4/Ih2YQIDAQAB
-----END PUBLIC KEY-----

@ -429,7 +429,7 @@ ALTER TABLE `tab_user_play_info` ADD INDEX `search`(`promote_id`, `game_id`, `se
ALTER TABLE `tab_user_login_record` ADD INDEX `search`(`promote_id`, `game_id`, `server_id`, `login_time`);
ALTER TABLE `tab_spend` ADD INDEX `search`(`promote_id`, `game_id`, `server_id`, `pay_way`, `pay_status`, `pay_time`);
<<<<<<< HEAD
-- 添加登录日统计表
CREATE TABLE `tab_login_daily_record` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
@ -441,7 +441,6 @@ CREATE TABLE `tab_login_daily_record` (
KEY `search` (`promote_id`,`game_id`,`create_time`) USING BTREE,
KEY `user_id` (`user_id`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=284597 DEFAULT CHARSET=utf8;
=======
--sdk
ALTER TABLE `tab_pay_info`
MODIFY COLUMN `order_id` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '平台订单ID' AFTER `game_id`,
@ -453,4 +452,57 @@ ADD COLUMN `extend` varchar(255) NOT NULL DEFAULT '' COMMENT 'cp订单ID' AFTER
ALTER TABLE `tab_promote`
CHANGE COLUMN `ver_status` `ver_status` INT(11) NULL DEFAULT '0' COMMENT '资质认证审核状态(1是审核成功2审核失败3未审核,4修改认证)' AFTER `child_game_permission`,
ADD COLUMN `anothpic` CHAR(254) NULL DEFAULT NULL AFTER `account_type`;
>>>>>>> 05bb9b4aa3ba712199e5489f684bc7a8cfeb59c8
--2019-11-19 chenzhi
CREATE TABLE `tab_index_chart` (
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键自增',
`date` int(11) NOT NULL DEFAULT '0' COMMENT '日期时间戳',
`new_user_hours` varchar(500) NOT NULL DEFAULT '' COMMENT '新增用户聚合',
`new_user_count` int(11) NOT NULL DEFAULT '0' COMMENT '单日新增总计',
`active_user_hours` varchar(500) NOT NULL DEFAULT '' COMMENT '活跃用户聚合',
`active_user_count` int(11) NOT NULL DEFAULT '0' COMMENT '单日活跃总计',
`active_user_list` longtext COMMENT '单日活跃用户的id序列',
`pay_user_hours` varchar(500) NOT NULL DEFAULT '' COMMENT '付费用户聚合',
`pay_user_count` int(11) NOT NULL DEFAULT '0' COMMENT '单日付费用户总计',
`pay_user_list` longtext COMMENT '单日付费用户的id序列',
`pay_money_hours` varchar(500) NOT NULL DEFAULT '' COMMENT '付费金额聚合',
`pay_money_count` decimal(10,2) DEFAULT '0.00' COMMENT '单日付费金额总计',
`promote_new_hours` varchar(500) NOT NULL DEFAULT '' COMMENT '小时新增渠道',
`promote_new_count` int(11) NOT NULL DEFAULT '0' COMMENT '新增合作渠道总计',
`all_count` varchar(500) NOT NULL DEFAULT '' COMMENT '累计的统计数据',
`create_time` int(11) NOT NULL DEFAULT '0' COMMENT '统计日期',
PRIMARY KEY (`id`),
KEY `date` (`date`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COMMENT='首页折线图静态数据';
-- 2019-11-20 zyx
DROP TABLE IF EXISTS `tab_device_statistics`;
CREATE TABLE `tab_device_statistics` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`time` int(11) NOT NULL DEFAULT 0 COMMENT '日期时间戳',
`new_device` int(11) NOT NULL DEFAULT 0 COMMENT '当日新增设备',
`active_device` int(11) NOT NULL DEFAULT 0 COMMENT '当日活跃设备',
`today_new_device` longtext CHARACTER SET utf8 COLLATE utf8_unicode_ci NULL COMMENT '当日新增设备按小时划分的json字符串',
`today_active_device` longtext CHARACTER SET utf8 COLLATE utf8_unicode_ci NULL COMMENT '当日活跃设备按小时划分的json字符串',
`today_model_device` longtext CHARACTER SET utf8 COLLATE utf8_unicode_ci NULL COMMENT '当日启动机型(机型,系统,数量)',
`model` longtext CHARACTER SET utf8 COLLATE utf8_unicode_ci NULL COMMENT '当日启动设备',
`version` int(11) NOT NULL DEFAULT 1 COMMENT '机型',
`duration7` int(255) NOT NULL DEFAULT 0 COMMENT '七天的平均使用时间',
PRIMARY KEY (`id`) USING BTREE,
INDEX `time`(`time`) USING BTREE
) ENGINE = MyISAM AUTO_INCREMENT = 163 CHARACTER SET = utf8 COLLATE = utf8_unicode_ci ROW_FORMAT = Dynamic;
SET FOREIGN_KEY_CHECKS = 1;
ALTER TABLE `platform`.`tab_device_record`
ADD INDEX `create_time`(`create_time`) USING BTREE,
ADD INDEX `unique_code`(`unique_code`) USING BTREE,
ADD INDEX `idx_unique_version`(`version`, `unique_code`) USING BTREE,
ADD INDEX `version`(`version`) USING BTREE;
UPDATE `platform_new`.`tab_quick_menu` SET `url` = '/index.php?s=/Home/TestResource/index.html' WHERE `id` = 11
UPDATE `platform_new`.`tab_quick_menu` SET `url` = '/index.php?s=/Home/TestResource/lists.html' WHERE `id` = 12
--
ALTER TABLE `tab_withdraw`
ADD INDEX `widthdraw_number`(`widthdraw_number`);

@ -13,8 +13,8 @@
docEl.style.fontSize = Math.max(Math.min(20 * (clientWidth / 1536), 22.5), 17.5) * 5 + 'px';
}else{
/* 8.55小于320px不再缩小11.2大于420px不再放大 */
docEl.style.fontSize = Math.max(Math.min(20 * (clientWidth / docWidth), 11.2), 8.55) * 5 + 'px';
/* 8.55小于320px不再缩小11.2大于420px不再放大 17.2 大于667不再放大*/
docEl.style.fontSize = Math.max(Math.min(20 * (clientWidth / docWidth), 17.2), 8.55) * 5 + 'px';
}
return refreshRem;
})();

@ -0,0 +1,7 @@
<?php
// autoload.php @generated by Composer
require_once __DIR__ . '/composer/autoload_real.php';
return ComposerAutoloaderInit4b3d592472598a8d8206a9f170e9bb91::getLoader();

@ -0,0 +1,445 @@
<?php
/*
* This file is part of Composer.
*
* (c) Nils Adermann <naderman@naderman.de>
* Jordi Boggiano <j.boggiano@seld.be>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Composer\Autoload;
/**
* ClassLoader implements a PSR-0, PSR-4 and classmap class loader.
*
* $loader = new \Composer\Autoload\ClassLoader();
*
* // register classes with namespaces
* $loader->add('Symfony\Component', __DIR__.'/component');
* $loader->add('Symfony', __DIR__.'/framework');
*
* // activate the autoloader
* $loader->register();
*
* // to enable searching the include path (eg. for PEAR packages)
* $loader->setUseIncludePath(true);
*
* In this example, if you try to use a class in the Symfony\Component
* namespace or one of its children (Symfony\Component\Console for instance),
* the autoloader will first look for the class under the component/
* directory, and it will then fallback to the framework/ directory if not
* found before giving up.
*
* This class is loosely based on the Symfony UniversalClassLoader.
*
* @author Fabien Potencier <fabien@symfony.com>
* @author Jordi Boggiano <j.boggiano@seld.be>
* @see http://www.php-fig.org/psr/psr-0/
* @see http://www.php-fig.org/psr/psr-4/
*/
class ClassLoader
{
// PSR-4
private $prefixLengthsPsr4 = array();
private $prefixDirsPsr4 = array();
private $fallbackDirsPsr4 = array();
// PSR-0
private $prefixesPsr0 = array();
private $fallbackDirsPsr0 = array();
private $useIncludePath = false;
private $classMap = array();
private $classMapAuthoritative = false;
private $missingClasses = array();
private $apcuPrefix;
public function getPrefixes()
{
if (!empty($this->prefixesPsr0)) {
return call_user_func_array('array_merge', $this->prefixesPsr0);
}
return array();
}
public function getPrefixesPsr4()
{
return $this->prefixDirsPsr4;
}
public function getFallbackDirs()
{
return $this->fallbackDirsPsr0;
}
public function getFallbackDirsPsr4()
{
return $this->fallbackDirsPsr4;
}
public function getClassMap()
{
return $this->classMap;
}
/**
* @param array $classMap Class to filename map
*/
public function addClassMap(array $classMap)
{
if ($this->classMap) {
$this->classMap = array_merge($this->classMap, $classMap);
} else {
$this->classMap = $classMap;
}
}
/**
* Registers a set of PSR-0 directories for a given prefix, either
* appending or prepending to the ones previously set for this prefix.
*
* @param string $prefix The prefix
* @param array|string $paths The PSR-0 root directories
* @param bool $prepend Whether to prepend the directories
*/
public function add($prefix, $paths, $prepend = false)
{
if (!$prefix) {
if ($prepend) {
$this->fallbackDirsPsr0 = array_merge(
(array) $paths,
$this->fallbackDirsPsr0
);
} else {
$this->fallbackDirsPsr0 = array_merge(
$this->fallbackDirsPsr0,
(array) $paths
);
}
return;
}
$first = $prefix[0];
if (!isset($this->prefixesPsr0[$first][$prefix])) {
$this->prefixesPsr0[$first][$prefix] = (array) $paths;
return;
}
if ($prepend) {
$this->prefixesPsr0[$first][$prefix] = array_merge(
(array) $paths,
$this->prefixesPsr0[$first][$prefix]
);
} else {
$this->prefixesPsr0[$first][$prefix] = array_merge(
$this->prefixesPsr0[$first][$prefix],
(array) $paths
);
}
}
/**
* Registers a set of PSR-4 directories for a given namespace, either
* appending or prepending to the ones previously set for this namespace.
*
* @param string $prefix The prefix/namespace, with trailing '\\'
* @param array|string $paths The PSR-4 base directories
* @param bool $prepend Whether to prepend the directories
*
* @throws \InvalidArgumentException
*/
public function addPsr4($prefix, $paths, $prepend = false)
{
if (!$prefix) {
// Register directories for the root namespace.
if ($prepend) {
$this->fallbackDirsPsr4 = array_merge(
(array) $paths,
$this->fallbackDirsPsr4
);
} else {
$this->fallbackDirsPsr4 = array_merge(
$this->fallbackDirsPsr4,
(array) $paths
);
}
} elseif (!isset($this->prefixDirsPsr4[$prefix])) {
// Register directories for a new namespace.
$length = strlen($prefix);
if ('\\' !== $prefix[$length - 1]) {
throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
}
$this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
$this->prefixDirsPsr4[$prefix] = (array) $paths;
} elseif ($prepend) {
// Prepend directories for an already registered namespace.
$this->prefixDirsPsr4[$prefix] = array_merge(
(array) $paths,
$this->prefixDirsPsr4[$prefix]
);
} else {
// Append directories for an already registered namespace.
$this->prefixDirsPsr4[$prefix] = array_merge(
$this->prefixDirsPsr4[$prefix],
(array) $paths
);
}
}
/**
* Registers a set of PSR-0 directories for a given prefix,
* replacing any others previously set for this prefix.
*
* @param string $prefix The prefix
* @param array|string $paths The PSR-0 base directories
*/
public function set($prefix, $paths)
{
if (!$prefix) {
$this->fallbackDirsPsr0 = (array) $paths;
} else {
$this->prefixesPsr0[$prefix[0]][$prefix] = (array) $paths;
}
}
/**
* Registers a set of PSR-4 directories for a given namespace,
* replacing any others previously set for this namespace.
*
* @param string $prefix The prefix/namespace, with trailing '\\'
* @param array|string $paths The PSR-4 base directories
*
* @throws \InvalidArgumentException
*/
public function setPsr4($prefix, $paths)
{
if (!$prefix) {
$this->fallbackDirsPsr4 = (array) $paths;
} else {
$length = strlen($prefix);
if ('\\' !== $prefix[$length - 1]) {
throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
}
$this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
$this->prefixDirsPsr4[$prefix] = (array) $paths;
}
}
/**
* Turns on searching the include path for class files.
*
* @param bool $useIncludePath
*/
public function setUseIncludePath($useIncludePath)
{
$this->useIncludePath = $useIncludePath;
}
/**
* Can be used to check if the autoloader uses the include path to check
* for classes.
*
* @return bool
*/
public function getUseIncludePath()
{
return $this->useIncludePath;
}
/**
* Turns off searching the prefix and fallback directories for classes
* that have not been registered with the class map.
*
* @param bool $classMapAuthoritative
*/
public function setClassMapAuthoritative($classMapAuthoritative)
{
$this->classMapAuthoritative = $classMapAuthoritative;
}
/**
* Should class lookup fail if not found in the current class map?
*
* @return bool
*/
public function isClassMapAuthoritative()
{
return $this->classMapAuthoritative;
}
/**
* APCu prefix to use to cache found/not-found classes, if the extension is enabled.
*
* @param string|null $apcuPrefix
*/
public function setApcuPrefix($apcuPrefix)
{
$this->apcuPrefix = function_exists('apcu_fetch') && filter_var(ini_get('apc.enabled'), FILTER_VALIDATE_BOOLEAN) ? $apcuPrefix : null;
}
/**
* The APCu prefix in use, or null if APCu caching is not enabled.
*
* @return string|null
*/
public function getApcuPrefix()
{
return $this->apcuPrefix;
}
/**
* Registers this instance as an autoloader.
*
* @param bool $prepend Whether to prepend the autoloader or not
*/
public function register($prepend = false)
{
spl_autoload_register(array($this, 'loadClass'), true, $prepend);
}
/**
* Unregisters this instance as an autoloader.
*/
public function unregister()
{
spl_autoload_unregister(array($this, 'loadClass'));
}
/**
* Loads the given class or interface.
*
* @param string $class The name of the class
* @return bool|null True if loaded, null otherwise
*/
public function loadClass($class)
{
if ($file = $this->findFile($class)) {
includeFile($file);
return true;
}
}
/**
* Finds the path to the file where the class is defined.
*
* @param string $class The name of the class
*
* @return string|false The path if found, false otherwise
*/
public function findFile($class)
{
// class map lookup
if (isset($this->classMap[$class])) {
return $this->classMap[$class];
}
if ($this->classMapAuthoritative || isset($this->missingClasses[$class])) {
return false;
}
if (null !== $this->apcuPrefix) {
$file = apcu_fetch($this->apcuPrefix.$class, $hit);
if ($hit) {
return $file;
}
}
$file = $this->findFileWithExtension($class, '.php');
// Search for Hack files if we are running on HHVM
if (false === $file && defined('HHVM_VERSION')) {
$file = $this->findFileWithExtension($class, '.hh');
}
if (null !== $this->apcuPrefix) {
apcu_add($this->apcuPrefix.$class, $file);
}
if (false === $file) {
// Remember that this class does not exist.
$this->missingClasses[$class] = true;
}
return $file;
}
private function findFileWithExtension($class, $ext)
{
// PSR-4 lookup
$logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext;
$first = $class[0];
if (isset($this->prefixLengthsPsr4[$first])) {
$subPath = $class;
while (false !== $lastPos = strrpos($subPath, '\\')) {
$subPath = substr($subPath, 0, $lastPos);
$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;
}
}
}
}
}
// PSR-4 fallback dirs
foreach ($this->fallbackDirsPsr4 as $dir) {
if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) {
return $file;
}
}
// PSR-0 lookup
if (false !== $pos = strrpos($class, '\\')) {
// namespaced class name
$logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1)
. strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR);
} else {
// PEAR-like class name
$logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . $ext;
}
if (isset($this->prefixesPsr0[$first])) {
foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) {
if (0 === strpos($class, $prefix)) {
foreach ($dirs as $dir) {
if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
return $file;
}
}
}
}
}
// PSR-0 fallback dirs
foreach ($this->fallbackDirsPsr0 as $dir) {
if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
return $file;
}
}
// PSR-0 include paths.
if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) {
return $file;
}
return false;
}
}
/**
* Scope isolated include.
*
* Prevents access to $this/self from included files.
*/
function includeFile($file)
{
include $file;
}

@ -0,0 +1,21 @@
Copyright (c) Nils Adermann, Jordi Boggiano
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.

@ -0,0 +1,9 @@
<?php
// autoload_classmap.php @generated by Composer
$vendorDir = dirname(dirname(__FILE__));
$baseDir = dirname($vendorDir);
return array(
);

@ -0,0 +1,10 @@
<?php
// autoload_namespaces.php @generated by Composer
$vendorDir = dirname(dirname(__FILE__));
$baseDir = dirname($vendorDir);
return array(
'CFPropertyList' => array($vendorDir . '/rodneyrehm/plist/classes'),
);

@ -0,0 +1,9 @@
<?php
// autoload_psr4.php @generated by Composer
$vendorDir = dirname(dirname(__FILE__));
$baseDir = dirname($vendorDir);
return array(
);

@ -0,0 +1,52 @@
<?php
// autoload_real.php @generated by Composer
class ComposerAutoloaderInit4b3d592472598a8d8206a9f170e9bb91
{
private static $loader;
public static function loadClassLoader($class)
{
if ('Composer\Autoload\ClassLoader' === $class) {
require __DIR__ . '/ClassLoader.php';
}
}
public static function getLoader()
{
if (null !== self::$loader) {
return self::$loader;
}
spl_autoload_register(array('ComposerAutoloaderInit4b3d592472598a8d8206a9f170e9bb91', 'loadClassLoader'), true, true);
self::$loader = $loader = new \Composer\Autoload\ClassLoader();
spl_autoload_unregister(array('ComposerAutoloaderInit4b3d592472598a8d8206a9f170e9bb91', 'loadClassLoader'));
$useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());
if ($useStaticLoader) {
require_once __DIR__ . '/autoload_static.php';
call_user_func(\Composer\Autoload\ComposerStaticInit4b3d592472598a8d8206a9f170e9bb91::getInitializer($loader));
} else {
$map = require __DIR__ . '/autoload_namespaces.php';
foreach ($map as $namespace => $path) {
$loader->set($namespace, $path);
}
$map = require __DIR__ . '/autoload_psr4.php';
foreach ($map as $namespace => $path) {
$loader->setPsr4($namespace, $path);
}
$classMap = require __DIR__ . '/autoload_classmap.php';
if ($classMap) {
$loader->addClassMap($classMap);
}
}
$loader->register(true);
return $loader;
}
}

@ -0,0 +1,26 @@
<?php
// autoload_static.php @generated by Composer
namespace Composer\Autoload;
class ComposerStaticInit4b3d592472598a8d8206a9f170e9bb91
{
public static $prefixesPsr0 = array (
'C' =>
array (
'CFPropertyList' =>
array (
0 => __DIR__ . '/..' . '/rodneyrehm/plist/classes',
),
),
);
public static function getInitializer(ClassLoader $loader)
{
return \Closure::bind(function () use ($loader) {
$loader->prefixesPsr0 = ComposerStaticInit4b3d592472598a8d8206a9f170e9bb91::$prefixesPsr0;
}, null, ClassLoader::class);
}
}

@ -0,0 +1,48 @@
[
{
"name": "rodneyrehm/plist",
"version": "v2.0.1",
"version_normalized": "2.0.1.0",
"source": {
"type": "git",
"url": "https://github.com/rodneyrehm/CFPropertyList.git",
"reference": "2ea0483806c989eb0518a767fa29a111bb29cb67"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/rodneyrehm/CFPropertyList/zipball/2ea0483806c989eb0518a767fa29a111bb29cb67",
"reference": "2ea0483806c989eb0518a767fa29a111bb29cb67",
"shasum": ""
},
"require": {
"php": ">=5.3"
},
"time": "2015-01-28T23:18:19+00:00",
"type": "library",
"installation-source": "dist",
"autoload": {
"psr-0": {
"CFPropertyList": "classes/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Christian Kruse",
"email": "cjk@wwwtech.de"
},
{
"name": "Rodney Rehm",
"email": "mail+github@rodneyrehm.de"
}
],
"description": "Library for reading and writing Apple's CFPropertyList (plist) files in XML as well as binary format.",
"homepage": "https://github.com/rodneyrehm/CFPropertyList",
"keywords": [
"plist"
]
}
]

@ -0,0 +1,7 @@
docs
*tmp
composer.lock
vendor
.foundation
Makefile
.DS_Store

@ -0,0 +1,22 @@
The MIT License
Copyright (c) 2009 Christian Kruse, Rodney Rehm
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.

@ -0,0 +1,39 @@
# CFPropertyList
The PHP implementation of Apple's PropertyList can handle XML PropertyLists as well as binary PropertyLists. It offers functionality to easily convert data between worlds, e.g. recalculating timestamps from unix epoch to apple epoch and vice versa. A feature to automagically create (guess) the plist structure from a normal PHP data structure will help you dump your data to plist in no time.
Note: CFPropertylist was originally hosted on [Google Code](http://code.google.com/p/cfpropertylist/)
## Choose Your Favorite Operating System
CFPropertyList does not rely on any "Apple proprietary" components, like plutil. CFPropertyList runs on any Operating System with PHP and some standard extensions installed.
Although you might want to deliver data to your iPhone application, you might want to run those server side services on your standard Linux (or even Windows) environment, rather than buying an expensive Apple Server. With CFPropertyList you now have the power to provide data from your favorite Operating System.
## Requirements And Limitations
* requires PHP5.3 (as of CFPropertyList 2.0)
* requires either [MBString](http://php.net/mbstring) or [Iconv](http://php.net/iconv)
* requires either [BC](http://php.net/bc) or [GMP](http://php.net/gmp) or [phpseclib](http://phpseclib.sourceforge.net/) (see BigIntegerBug for an explanation) - as of CFPropertyList 1.0.1
## Authors
- Rodney Rehm <rodney.rehm@medialize.de>
- Christian Kruse <cjk@wwwtech.de>
- PSR-0 changes by Jarvis Badgley <https://github.com/ChiperSoft/CFPropertyList>
## License
CFPropertyList is published under the [MIT License](http://www.opensource.org/licenses/mit-license.php).
## Installation
see [Composer / Packagist](http://packagist.org/packages/rodneyrehm/plist).
## Related
* [man(5) plist](http://developer.apple.com/documentation/Darwin/Reference/ManPages/man5/plist.5.html)
* [CFBinaryPList.c](http://www.opensource.apple.com/source/CF/CF-476.15/CFBinaryPList.c)
* [CFPropertyList in Ruby](http://rubyforge.org/projects/cfpropertylist/)
* [CFPropertyList in Python](https://github.com/bencochran/CFPropertyList)
* [plist on Wikipedia](http://en.wikipedia.org/wiki/Plist)

@ -0,0 +1,5 @@
#!/bin/sh
/bin/sh /opt/local/share/phpDoc/phpdoc -ed /Users/rrehm/Projekte/plist/examples -d /Users/rrehm/Projekte/plist/classes -ti "CFPropertyList" -t /Users/rrehm/Projekte/plist/docs/ -ue on
cd /Users/rrehm/Projekte/plist/
tar --exclude=".git|*.sh" -czf ../CFPropertyList.tgz .

File diff suppressed because it is too large Load Diff

@ -0,0 +1,608 @@
<?php
/**
* CFPropertyList
* {@link http://developer.apple.com/documentation/Darwin/Reference/ManPages/man5/plist.5.html Property Lists}
* @author Rodney Rehm <rodney.rehm@medialize.de>
* @author Christian Kruse <cjk@wwwtech.de>
* @package plist
* @version $Id$
* @example example-read-01.php Read an XML PropertyList
* @example example-read-02.php Read a Binary PropertyList
* @example example-read-03.php Read a PropertyList without knowing the type
* @example example-create-01.php Using the CFPropertyList API
* @example example-create-02.php Using {@link CFTypeDetector}
* @example example-create-03.php Using {@link CFTypeDetector} with {@link CFDate} and {@link CFData}
* @example example-modify-01.php Read, modify and save a PropertyList
*/
namespace CFPropertyList;
use \Iterator, \DOMDocument, \DOMException, DOMImplementation, DOMNode;
/**
* Require IOException, PListException, CFType and CFBinaryPropertyList
*/
require_once(__DIR__.'/IOException.php');
require_once(__DIR__.'/PListException.php');
require_once(__DIR__.'/CFType.php');
require_once(__DIR__.'/CFBinaryPropertyList.php');
require_once(__DIR__.'/CFTypeDetector.php');
/**
* Property List
* Interface for handling reading, editing and saving Property Lists as defined by Apple.
* @author Rodney Rehm <rodney.rehm@medialize.de>
* @author Christian Kruse <cjk@wwwtech.de>
* @package plist
* @example example-read-01.php Read an XML PropertyList
* @example example-read-02.php Read a Binary PropertyList
* @example example-read-03.php Read a PropertyList without knowing the type
* @example example-create-01.php Using the CFPropertyList API
* @example example-create-02.php Using {@link CFTypeDetector}
* @example example-create-03.php Using {@link CFTypeDetector} with {@link CFDate} and {@link CFData}
* @example example-create-04.php Using and extended {@link CFTypeDetector}
*/
class CFPropertyList extends CFBinaryPropertyList implements Iterator {
/**
* Format constant for binary format
* @var integer
*/
const FORMAT_BINARY = 1;
/**
* Format constant for xml format
* @var integer
*/
const FORMAT_XML = 2;
/**
* Format constant for automatic format recognizing
* @var integer
*/
const FORMAT_AUTO = 0;
/**
* Path of PropertyList
* @var string
*/
protected $file = null;
/**
* Detected format of PropertyList
* @var integer
*/
protected $detectedFormat = null;
/**
* Path of PropertyList
* @var integer
*/
protected $format = null;
/**
* CFType nodes
* @var array
*/
protected $value = array();
/**
* Position of iterator {@link http://php.net/manual/en/class.iterator.php}
* @var integer
*/
protected $iteratorPosition = 0;
/**
* List of Keys for numerical iterator access {@link http://php.net/manual/en/class.iterator.php}
* @var array
*/
protected $iteratorKeys = null;
/**
* List of NodeNames to ClassNames for resolving plist-files
* @var array
*/
protected static $types = array(
'string' => 'CFString',
'real' => 'CFNumber',
'integer' => 'CFNumber',
'date' => 'CFDate',
'true' => 'CFBoolean',
'false' => 'CFBoolean',
'data' => 'CFData',
'array' => 'CFArray',
'dict' => 'CFDictionary'
);
/**
* Create new CFPropertyList.
* If a path to a PropertyList is specified, it is loaded automatically.
* @param string $file Path of PropertyList
* @param integer $format he format of the property list, see {@link FORMAT_XML}, {@link FORMAT_BINARY} and {@link FORMAT_AUTO}, defaults to {@link FORMAT_AUTO}
* @throws IOException if file could not be read by {@link load()}
* @uses $file for storing the current file, if specified
* @uses load() for loading the plist-file
*/
public function __construct($file=null,$format=self::FORMAT_AUTO) {
$this->file = $file;
$this->format = $format;
$this->detectedFormat = $format;
if($this->file) $this->load();
}
/**
* Load an XML PropertyList.
* @param string $file Path of PropertyList, defaults to {@link $file}
* @return void
* @throws IOException if file could not be read
* @throws DOMException if XML-file could not be read properly
* @uses load() to actually load the file
*/
public function loadXML($file=null) {
$this->load($file,CFPropertyList::FORMAT_XML);
}
/**
* Load an XML PropertyList.
* @param resource $stream A stream containing the xml document.
* @return void
* @throws IOException if stream could not be read
* @throws DOMException if XML-stream could not be read properly
*/
public function loadXMLStream($stream) {
if(($contents = stream_get_contents($stream)) === FALSE) throw IOException::notReadable('<stream>');
$this->parse($contents,CFPropertyList::FORMAT_XML);
}
/**
* Load an binary PropertyList.
* @param string $file Path of PropertyList, defaults to {@link $file}
* @return void
* @throws IOException if file could not be read
* @throws PListException if binary plist-file could not be read properly
* @uses load() to actually load the file
*/
public function loadBinary($file=null) {
$this->load($file,CFPropertyList::FORMAT_BINARY);
}
/**
* Load an binary PropertyList.
* @param stream $stream Stream containing the PropertyList
* @return void
* @throws IOException if file could not be read
* @throws PListException if binary plist-file could not be read properly
* @uses parse() to actually load the file
*/
public function loadBinaryStream($stream) {
if(($contents = stream_get_contents($stream)) === FALSE) throw IOException::notReadable('<stream>');
$this->parse($contents,CFPropertyList::FORMAT_BINARY);
}
/**
* Load a plist file.
* Load and import a plist file.
* @param string $file Path of PropertyList, defaults to {@link $file}
* @param integer $format The format of the property list, see {@link FORMAT_XML}, {@link FORMAT_BINARY} and {@link FORMAT_AUTO}, defaults to {@link $format}
* @return void
* @throws PListException if file format version is not 00
* @throws IOException if file could not be read
* @throws DOMException if plist file could not be parsed properly
* @uses $file if argument $file was not specified
* @uses $value reset to empty array
* @uses import() for importing the values
*/
public function load($file=null,$format=null) {
$file = $file ? $file : $this->file;
$format = $format !== null ? $format : $this->format;
$this->value = array();
if(!is_readable($file)) throw IOException::notReadable($file);
switch($format) {
case CFPropertyList::FORMAT_BINARY:
$this->readBinary($file);
break;
case CFPropertyList::FORMAT_AUTO: // what we now do is ugly, but neccessary to recognize the file format
$fd = fopen($file,"rb");
if(($magic_number = fread($fd,8)) === false) throw IOException::notReadable($file);
fclose($fd);
$filetype = substr($magic_number,0,6);
$version = substr($magic_number,-2);
if($filetype == "bplist") {
if($version != "00") throw new PListException("Wrong file format version! Expected 00, got $version!");
$this->detectedFormat = CFPropertyList::FORMAT_BINARY;
$this->readBinary($file);
break;
}
$this->detectedFormat = CFPropertyList::FORMAT_XML;
// else: xml format, break not neccessary
case CFPropertyList::FORMAT_XML:
$doc = new DOMDocument();
if(!$doc->load($file)) throw new DOMException();
$this->import($doc->documentElement, $this);
break;
}
}
/**
* Parse a plist string.
* Parse and import a plist string.
* @param string $str String containing the PropertyList, defaults to {@link $content}
* @param integer $format The format of the property list, see {@link FORMAT_XML}, {@link FORMAT_BINARY} and {@link FORMAT_AUTO}, defaults to {@link $format}
* @return void
* @throws PListException if file format version is not 00
* @throws IOException if file could not be read
* @throws DOMException if plist file could not be parsed properly
* @uses $content if argument $str was not specified
* @uses $value reset to empty array
* @uses import() for importing the values
*/
public function parse($str=NULL,$format=NULL) {
$format = $format !== null ? $format : $this->format;
$str = $str !== null ? $str : $this->content;
$this->value = array();
switch($format) {
case CFPropertyList::FORMAT_BINARY:
$this->parseBinary($str);
break;
case CFPropertyList::FORMAT_AUTO: // what we now do is ugly, but neccessary to recognize the file format
if(($magic_number = substr($str,0,8)) === false) throw IOException::notReadable("<string>");
$filetype = substr($magic_number,0,6);
$version = substr($magic_number,-2);
if($filetype == "bplist") {
if($version != "00") throw new PListException("Wrong file format version! Expected 00, got $version!");
$this->detectedFormat = CFPropertyList::FORMAT_BINARY;
$this->parseBinary($str);
break;
}
$this->detectedFormat = CFPropertyList::FORMAT_XML;
// else: xml format, break not neccessary
case CFPropertyList::FORMAT_XML:
$doc = new DOMDocument();
if(!$doc->loadXML($str)) throw new DOMException();
$this->import($doc->documentElement, $this);
break;
}
}
/**
* Convert a DOMNode into a CFType.
* @param DOMNode $node Node to import children of
* @param CFDictionary|CFArray|CFPropertyList $parent
* @return void
*/
protected function import(DOMNode $node, $parent) {
// abort if there are no children
if(!$node->childNodes->length) return;
foreach($node->childNodes as $n) {
// skip if we can't handle the element
if(!isset(self::$types[$n->nodeName])) continue;
$class = 'CFPropertyList\\'.self::$types[$n->nodeName];
$key = null;
// find previous <key> if possible
$ps = $n->previousSibling;
while($ps && $ps->nodeName == '#text' && $ps->previousSibling) $ps = $ps->previousSibling;
// read <key> if possible
if($ps && $ps->nodeName == 'key') $key = $ps->firstChild->nodeValue;
switch($n->nodeName) {
case 'date':
$value = new $class(CFDate::dateValue($n->nodeValue));
break;
case 'data':
$value = new $class($n->nodeValue,true);
break;
case 'string':
$value = new $class($n->nodeValue);
break;
case 'real':
case 'integer':
$value = new $class($n->nodeName == 'real' ? floatval($n->nodeValue) : intval($n->nodeValue));
break;
case 'true':
case 'false':
$value = new $class($n->nodeName == 'true');
break;
case 'array':
case 'dict':
$value = new $class();
$this->import($n, $value);
if($value instanceof CFDictionary) {
$hsh = $value->getValue();
if(isset($hsh['CF$UID']) && count($hsh) == 1) {
$value = new CFUid($hsh['CF$UID']->getValue());
}
}
break;
}
// Dictionaries need a key
if($parent instanceof CFDictionary) $parent->add($key, $value);
// others don't
else $parent->add($value);
}
}
/**
* Convert CFPropertyList to XML and save to file.
* @param string $file Path of PropertyList, defaults to {@link $file}
* @return void
* @throws IOException if file could not be read
* @uses $file if $file was not specified
*/
public function saveXML($file) {
$this->save($file,CFPropertyList::FORMAT_XML);
}
/**
* Convert CFPropertyList to binary format (bplist00) and save to file.
* @param string $file Path of PropertyList, defaults to {@link $file}
* @return void
* @throws IOException if file could not be read
* @uses $file if $file was not specified
*/
public function saveBinary($file) {
$this->save($file,CFPropertyList::FORMAT_BINARY);
}
/**
* Convert CFPropertyList to XML or binary and save to file.
* @param string $file Path of PropertyList, defaults to {@link $file}
* @param string $format Format of PropertyList, defaults to {@link $format}
* @return void
* @throws IOException if file could not be read
* @throws PListException if evaluated $format is neither {@link FORMAT_XML} nor {@link FORMAL_BINARY}
* @uses $file if $file was not specified
* @uses $format if $format was not specified
*/
public function save($file=null,$format=null) {
$file = $file ? $file : $this->file;
$format = $format ? $format : $this->format;
if($format == self::FORMAT_AUTO)$format = $this->detectedFormat;
if( !in_array( $format, array( self::FORMAT_BINARY, self::FORMAT_XML ) ) )
throw new PListException( "format {$format} is not supported, use CFPropertyList::FORMAT_BINARY or CFPropertyList::FORMAT_XML" );
if(!file_exists($file)) {
// dirname("file.xml") == "" and is treated as the current working directory
if(!is_writable(dirname($file))) throw IOException::notWritable($file);
}
else if(!is_writable($file)) throw IOException::notWritable($file);
$content = $format == self::FORMAT_BINARY ? $this->toBinary() : $this->toXML();
$fh = fopen($file, 'wb');
fwrite($fh,$content);
fclose($fh);
}
/**
* Convert CFPropertyList to XML
* @param bool $formatted Print plist formatted (i.e. with newlines and whitespace indention) if true; defaults to false
* @return string The XML content
*/
public function toXML($formatted=false) {
$domimpl = new DOMImplementation();
// <!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
$dtd = $domimpl->createDocumentType('plist', '-//Apple//DTD PLIST 1.0//EN', 'http://www.apple.com/DTDs/PropertyList-1.0.dtd');
$doc = $domimpl->createDocument(null, "plist", $dtd);
$doc->encoding = "UTF-8";
// format output
if($formatted) {
$doc->formatOutput = true;
$doc->preserveWhiteSpace = true;
}
// get documentElement and set attribs
$plist = $doc->documentElement;
$plist->setAttribute('version', '1.0');
// add PropertyList's children
$plist->appendChild($this->getValue(true)->toXML($doc));
return $doc->saveXML();
}
/************************************************************************************************
* M A N I P U L A T I O N
************************************************************************************************/
/**
* Add CFType to collection.
* @param CFType $value CFType to add to collection
* @return void
* @uses $value for adding $value
*/
public function add(CFType $value=null) {
// anything but CFType is null, null is an empty string - sad but true
if( !$value )
$value = new CFString();
$this->value[] = $value;
}
/**
* Get CFType from collection.
* @param integer $key Key of CFType to retrieve from collection
* @return CFType CFType found at $key, null else
* @uses $value for retrieving CFType of $key
*/
public function get($key) {
if(isset($this->value[$key])) return $this->value[$key];
return null;
}
/**
* Generic getter (magic)
*
* @param integer $key Key of CFType to retrieve from collection
* @return CFType CFType found at $key, null else
* @author Sean Coates <sean@php.net>
* @link http://php.net/oop5.overloading
*/
public function __get($key) {
return $this->get($key);
}
/**
* Remove CFType from collection.
* @param integer $key Key of CFType to removes from collection
* @return CFType removed CFType, null else
* @uses $value for removing CFType of $key
*/
public function del($key) {
if(isset($this->value[$key])) {
$t = $this->value[$key];
unset($this->value[$key]);
return $t;
}
return null;
}
/**
* Empty the collection
* @return array the removed CFTypes
* @uses $value for removing CFType of $key
*/
public function purge() {
$t = $this->value;
$this->value = array();
return $t;
}
/**
* Get first (and only) child, or complete collection.
* @param string $cftype if set to true returned value will be CFArray instead of an array in case of a collection
* @return CFType|array CFType or list of CFTypes known to the PropertyList
* @uses $value for retrieving CFTypes
*/
public function getValue($cftype=false) {
if(count($this->value) === 1) {
$t = array_values( $this->value );
return $t[0];
}
if($cftype) {
$t = new CFArray();
foreach( $this->value as $value ) {
if( $value instanceof CFType ) $t->add($value);
}
return $t;
}
return $this->value;
}
/**
* Create CFType-structure from guessing the data-types.
* The functionality has been moved to the more flexible {@link CFTypeDetector} facility.
* @param mixed $value Value to convert to CFType
* @param array $options Configuration for casting values [autoDictionary, suppressExceptions, objectToArrayMethod, castNumericStrings]
* @return CFType CFType based on guessed type
* @uses CFTypeDetector for actual type detection
* @deprecated
*/
public static function guess($value, $options=array()) {
static $t = null;
if( $t === null )
$t = new CFTypeDetector( $options );
return $t->toCFType( $value );
}
/************************************************************************************************
* S E R I A L I Z I N G
************************************************************************************************/
/**
* Get PropertyList as array.
* @return mixed primitive value of first (and only) CFType, or array of primitive values of collection
* @uses $value for retrieving CFTypes
*/
public function toArray() {
$a = array();
foreach($this->value as $value) $a[] = $value->toArray();
if(count($a) === 1) return $a[0];
return $a;
}
/************************************************************************************************
* I T E R A T O R I N T E R F A C E
************************************************************************************************/
/**
* Rewind {@link $iteratorPosition} to first position (being 0)
* @link http://php.net/manual/en/iterator.rewind.php
* @return void
* @uses $iteratorPosition set to 0
* @uses $iteratorKeys store keys of {@link $value}
*/
public function rewind() {
$this->iteratorPosition = 0;
$this->iteratorKeys = array_keys($this->value);
}
/**
* Get Iterator's current {@link CFType} identified by {@link $iteratorPosition}
* @link http://php.net/manual/en/iterator.current.php
* @return CFType current Item
* @uses $iteratorPosition identify current key
* @uses $iteratorKeys identify current value
*/
public function current() {
return $this->value[$this->iteratorKeys[$this->iteratorPosition]];
}
/**
* Get Iterator's current key identified by {@link $iteratorPosition}
* @link http://php.net/manual/en/iterator.key.php
* @return string key of the current Item
* @uses $iteratorPosition identify current key
* @uses $iteratorKeys identify current value
*/
public function key() {
return $this->iteratorKeys[$this->iteratorPosition];
}
/**
* Increment {@link $iteratorPosition} to address next {@see CFType}
* @link http://php.net/manual/en/iterator.next.php
* @return void
* @uses $iteratorPosition increment by 1
*/
public function next() {
$this->iteratorPosition++;
}
/**
* Test if {@link $iteratorPosition} addresses a valid element of {@link $value}
* @link http://php.net/manual/en/iterator.valid.php
* @return boolean true if current position is valid, false else
* @uses $iteratorPosition test if within {@link $iteratorKeys}
* @uses $iteratorPosition test if within {@link $value}
*/
public function valid() {
return isset($this->iteratorKeys[$this->iteratorPosition]) && isset($this->value[$this->iteratorKeys[$this->iteratorPosition]]);
}
}
# eof

@ -0,0 +1,757 @@
<?php
/**
* Data-Types for CFPropertyList as defined by Apple.
* {@link http://developer.apple.com/documentation/Darwin/Reference/ManPages/man5/plist.5.html Property Lists}
* @author Rodney Rehm <rodney.rehm@medialize.de>
* @author Christian Kruse <cjk@wwwtech.de>
* @package plist
* @subpackage plist.types
* @version $Id$
*/
namespace CFPropertyList;
use \DOMDocument, \Iterator, \ArrayAccess;
/**
* Base-Class of all CFTypes used by CFPropertyList
* @author Rodney Rehm <rodney.rehm@medialize.de>
* @author Christian Kruse <cjk@wwwtech.de>
* @package plist
* @subpackage plist.types
* @version $Id$
* @example example-create-01.php Using the CFPropertyList API
* @example example-create-02.php Using CFPropertyList::guess()
* @example example-create-03.php Using CFPropertyList::guess() with {@link CFDate} and {@link CFData}
*/
abstract class CFType {
/**
* CFType nodes
* @var array
*/
protected $value = null;
/**
* Create new CFType.
* @param mixed $value Value of CFType
*/
public function __construct($value=null) {
$this->setValue($value);
}
/************************************************************************************************
* M A G I C P R O P E R T I E S
************************************************************************************************/
/**
* Get the CFType's value
* @return mixed CFType's value
*/
public function getValue() {
return $this->value;
}
/**
* Set the CFType's value
* @return void
*/
public function setValue($value) {
$this->value = $value;
}
/************************************************************************************************
* S E R I A L I Z I N G
************************************************************************************************/
/**
* Get XML-Node.
* @param DOMDocument $doc DOMDocument to create DOMNode in
* @param string $nodeName Name of element to create
* @return DOMNode Node created based on CType
* @uses $value as nodeValue
*/
public function toXML(DOMDocument $doc, $nodeName) {
$node = $doc->createElement($nodeName);
$text = $doc->createTextNode($this->value);
$node->appendChild($text);
return $node;
}
/**
* convert value to binary representation
* @param CFBinaryPropertyList The binary property list object
* @return The offset in the object table
*/
public abstract function toBinary(CFBinaryPropertyList &$bplist);
/**
* Get CFType's value.
* @return mixed primitive value
* @uses $value for retrieving primitive of CFType
*/
public function toArray() {
return $this->getValue();
}
}
/**
* String Type of CFPropertyList
* @author Rodney Rehm <rodney.rehm@medialize.de>
* @author Christian Kruse <cjk@wwwtech.de>
* @package plist
* @subpackage plist.types
*/
class CFString extends CFType {
/**
* Get XML-Node.
* @param DOMDocument $doc DOMDocument to create DOMNode in
* @param string $nodeName For compatibility reasons; just ignore it
* @return DOMNode &lt;string&gt;-Element
*/
public function toXML(DOMDocument $doc,$nodeName="") {
return parent::toXML($doc, 'string');
}
/**
* convert value to binary representation
* @param CFBinaryPropertyList The binary property list object
* @return The offset in the object table
*/
public function toBinary(CFBinaryPropertyList &$bplist) {
return $bplist->stringToBinary($this->value);
}
}
class CFUid extends CFType {
public
function toXML(DOMDocument $doc,$nodeName="") {
$obj = new CFDictionary(array('CF$UID' => new CFNumber($this->value)));
return $obj->toXml($doc);
}
public
function toBinary(CFBinaryPropertyList &$bplist) {
return $bplist->uidToBinary($this->value);
}
}
/**
* Number Type of CFPropertyList
* @author Rodney Rehm <rodney.rehm@medialize.de>
* @author Christian Kruse <cjk@wwwtech.de>
* @package plist
* @subpackage plist.types
*/
class CFNumber extends CFType {
/**
* Get XML-Node.
* Returns &lt;real&gt; if $value is a float, &lt;integer&gt; if $value is an integer.
* @param DOMDocument $doc DOMDocument to create DOMNode in
* @param string $nodeName For compatibility reasons; just ignore it
* @return DOMNode &lt;real&gt; or &lt;integer&gt;-Element
*/
public function toXML(DOMDocument $doc,$nodeName="") {
$ret = 'real';
if(intval($this->value) == $this->value && !is_float($this->value) && strpos($this->value,'.') === false) {
$this->value = intval($this->value);
$ret = 'integer';
}
return parent::toXML($doc, $ret);
}
/**
* convert value to binary representation
* @param CFBinaryPropertyList The binary property list object
* @return The offset in the object table
*/
public function toBinary(CFBinaryPropertyList &$bplist) {
return $bplist->numToBinary($this->value);
}
}
/**
* Date Type of CFPropertyList
* Note: CFDate uses Unix timestamp (epoch) to store dates internally
* @author Rodney Rehm <rodney.rehm@medialize.de>
* @author Christian Kruse <cjk@wwwtech.de>
* @package plist
* @subpackage plist.types
*/
class CFDate extends CFType {
const TIMESTAMP_APPLE = 0;
const TIMESTAMP_UNIX = 1;
const DATE_DIFF_APPLE_UNIX = 978307200;
/**
* Create new Date CFType.
* @param integer $value timestamp to set
* @param integer $format format the timestamp is specified in, use {@link TIMESTAMP_APPLE} or {@link TIMESTAMP_UNIX}, defaults to {@link TIMESTAMP_APPLE}
* @uses setValue() to convert the timestamp
*/
function __construct($value,$format=CFDate::TIMESTAMP_UNIX) {
$this->setValue($value,$format);
}
/**
* Set the Date CFType's value.
* @param integer $value timestamp to set
* @param integer $format format the timestamp is specified in, use {@link TIMESTAMP_APPLE} or {@link TIMESTAMP_UNIX}, defaults to {@link TIMESTAMP_UNIX}
* @return void
* @uses TIMESTAMP_APPLE to determine timestamp type
* @uses TIMESTAMP_UNIX to determine timestamp type
* @uses DATE_DIFF_APPLE_UNIX to convert Apple-timestamp to Unix-timestamp
*/
function setValue($value,$format=CFDate::TIMESTAMP_UNIX) {
if($format == CFDate::TIMESTAMP_UNIX) $this->value = $value;
else $this->value = $value + CFDate::DATE_DIFF_APPLE_UNIX;
}
/**
* Get the Date CFType's value.
* @param integer $format format the timestamp is specified in, use {@link TIMESTAMP_APPLE} or {@link TIMESTAMP_UNIX}, defaults to {@link TIMESTAMP_UNIX}
* @return integer Unix timestamp
* @uses TIMESTAMP_APPLE to determine timestamp type
* @uses TIMESTAMP_UNIX to determine timestamp type
* @uses DATE_DIFF_APPLE_UNIX to convert Unix-timestamp to Apple-timestamp
*/
function getValue($format=CFDate::TIMESTAMP_UNIX) {
if($format == CFDate::TIMESTAMP_UNIX) return $this->value;
else return $this->value - CFDate::DATE_DIFF_APPLE_UNIX;
}
/**
* Get XML-Node.
* @param DOMDocument $doc DOMDocument to create DOMNode in
* @param string $nodeName For compatibility reasons; just ignore it
* @return DOMNode &lt;date&gt;-Element
*/
public function toXML(DOMDocument $doc,$nodeName="") {
$text = $doc->createTextNode(gmdate("Y-m-d\TH:i:s\Z",$this->getValue()));
$node = $doc->createElement("date");
$node->appendChild($text);
return $node;
}
/**
* convert value to binary representation
* @param CFBinaryPropertyList The binary property list object
* @return The offset in the object table
*/
public function toBinary(CFBinaryPropertyList &$bplist) {
return $bplist->dateToBinary($this->value);
}
/**
* Create a UNIX timestamp from a PList date string
* @param string $val The date string (e.g. "2009-05-13T20:23:43Z")
* @return integer The UNIX timestamp
* @throws PListException when encountering an unknown date string format
*/
public static function dateValue($val) {
//2009-05-13T20:23:43Z
if(!preg_match('/^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})Z/',$val,$matches)) throw new PListException("Unknown date format: $val");
return gmmktime($matches[4],$matches[5],$matches[6],$matches[2],$matches[3],$matches[1]);
}
}
/**
* Boolean Type of CFPropertyList
* @author Rodney Rehm <rodney.rehm@medialize.de>
* @author Christian Kruse <cjk@wwwtech.de>
* @package plist
* @subpackage plist.types
*/
class CFBoolean extends CFType {
/**
* Get XML-Node.
* Returns &lt;true&gt; if $value is a true, &lt;false&gt; if $value is false.
* @param DOMDocument $doc DOMDocument to create DOMNode in
* @param string $nodeName For compatibility reasons; just ignore it
* @return DOMNode &lt;true&gt; or &lt;false&gt;-Element
*/
public function toXML(DOMDocument $doc,$nodeName="") {
return $doc->createElement($this->value ? 'true' : 'false');
}
/**
* convert value to binary representation
* @param CFBinaryPropertyList The binary property list object
* @return The offset in the object table
*/
public function toBinary(CFBinaryPropertyList &$bplist) {
return $bplist->boolToBinary($this->value);
}
}
/**
* Data Type of CFPropertyList
* Note: Binary data is base64-encoded.
* @author Rodney Rehm <rodney.rehm@medialize.de>
* @author Christian Kruse <cjk@wwwtech.de>
* @package plist
* @subpackage plist.types
*/
class CFData extends CFType {
/**
* Create new Data CFType
* @param string $value data to be contained by new object
* @param boolean $already_coded if true $value will not be base64-encoded, defaults to false
*/
public function __construct($value=null,$already_coded=false) {
if($already_coded) $this->value = $value;
else $this->setValue($value);
}
/**
* Set the CFType's value and base64-encode it.
* <b>Note:</b> looks like base64_encode has troubles with UTF-8 encoded strings
* @return void
*/
public function setValue($value) {
//if(function_exists('mb_check_encoding') && mb_check_encoding($value, 'UTF-8')) $value = utf8_decode($value);
$this->value = base64_encode($value);
}
/**
* Get base64 encoded data
* @return string The base64 encoded data value
*/
public function getCodedValue() {
return $this->value;
}
/**
* Get the base64-decoded CFType's value.
* @return mixed CFType's value
*/
public function getValue() {
return base64_decode($this->value);
}
/**
* Get XML-Node.
* @param DOMDocument $doc DOMDocument to create DOMNode in
* @param string $nodeName For compatibility reasons; just ignore it
* @return DOMNode &lt;data&gt;-Element
*/
public function toXML(DOMDocument $doc,$nodeName="") {
return parent::toXML($doc, 'data');
}
/**
* convert value to binary representation
* @param CFBinaryPropertyList The binary property list object
* @return The offset in the object table
*/
public function toBinary(CFBinaryPropertyList &$bplist) {
return $bplist->dataToBinary($this->getValue());
}
}
/**
* Array Type of CFPropertyList
* @author Rodney Rehm <rodney.rehm@medialize.de>
* @author Christian Kruse <cjk@wwwtech.de>
* @package plist
* @subpackage plist.types
*/
class CFArray extends CFType implements Iterator, ArrayAccess {
/**
* Position of iterator {@link http://php.net/manual/en/class.iterator.php}
* @var integer
*/
protected $iteratorPosition = 0;
/**
* Create new CFType.
* @param array $value Value of CFType
*/
public function __construct($value=array()) {
$this->value = $value;
}
/**
* Set the CFType's value
* <b>Note:</b> this dummy does nothing
* @return void
*/
public function setValue($value) {
}
/**
* Add CFType to collection.
* @param CFType $value CFType to add to collection, defaults to null which results in an empty {@link CFString}
* @return void
* @uses $value for adding $value
*/
public function add(CFType $value=null) {
// anything but CFType is null, null is an empty string - sad but true
if( !$value )
$value = new CFString();
$this->value[] = $value;
}
/**
* Get CFType from collection.
* @param integer $key Key of CFType to retrieve from collection
* @return CFType CFType found at $key, null else
* @uses $value for retrieving CFType of $key
*/
public function get($key) {
if(isset($this->value[$key])) return $this->value[$key];
return null;
}
/**
* Remove CFType from collection.
* @param integer $key Key of CFType to removes from collection
* @return CFType removed CFType, null else
* @uses $value for removing CFType of $key
*/
public function del($key) {
if(isset($this->value[$key])) unset($this->value[$key]);
}
/************************************************************************************************
* S E R I A L I Z I N G
************************************************************************************************/
/**
* Get XML-Node.
* @param DOMDocument $doc DOMDocument to create DOMNode in
* @param string $nodeName For compatibility reasons; just ignore it
* @return DOMNode &lt;array&gt;-Element
*/
public function toXML(DOMDocument $doc,$nodeName="") {
$node = $doc->createElement('array');
foreach($this->value as $value) $node->appendChild($value->toXML($doc));
return $node;
}
/**
* convert value to binary representation
* @param CFBinaryPropertyList The binary property list object
* @return The offset in the object table
*/
public function toBinary(CFBinaryPropertyList &$bplist) {
return $bplist->arrayToBinary($this);
}
/**
* Get CFType's value.
* @return array primitive value
* @uses $value for retrieving primitive of CFType
*/
public function toArray() {
$a = array();
foreach($this->value as $value) $a[] = $value->toArray();
return $a;
}
/************************************************************************************************
* I T E R A T O R I N T E R F A C E
************************************************************************************************/
/**
* Rewind {@link $iteratorPosition} to first position (being 0)
* @link http://php.net/manual/en/iterator.rewind.php
* @return void
* @uses $iteratorPosition set to 0
*/
public function rewind() {
$this->iteratorPosition = 0;
}
/**
* Get Iterator's current {@link CFType} identified by {@link $iteratorPosition}
* @link http://php.net/manual/en/iterator.current.php
* @return CFType current Item
* @uses $iteratorPosition identify current key
*/
public function current() {
return $this->value[$this->iteratorPosition];
}
/**
* Get Iterator's current key identified by {@link $iteratorPosition}
* @link http://php.net/manual/en/iterator.key.php
* @return string key of the current Item
* @uses $iteratorPosition identify current key
*/
public function key() {
return $this->iteratorPosition;
}
/**
* Increment {@link $iteratorPosition} to address next {@see CFType}
* @link http://php.net/manual/en/iterator.next.php
* @return void
* @uses $iteratorPosition increment by 1
*/
public function next() {
$this->iteratorPosition++;
}
/**
* Test if {@link $iteratorPosition} addresses a valid element of {@link $value}
* @link http://php.net/manual/en/iterator.valid.php
* @return boolean true if current position is valid, false else
* @uses $iteratorPosition test if within {@link $iteratorKeys}
* @uses $iteratorPosition test if within {@link $value}
*/
public function valid() {
return isset($this->value[$this->iteratorPosition]);
}
/************************************************************************************************
* ArrayAccess I N T E R F A C E
************************************************************************************************/
/**
* Determine if the array's key exists
* @param string $key the key to check
* @return bool true if the offset exists, false if not
* @link http://php.net/manual/en/arrayaccess.offsetexists.php
* @uses $value to check if $key exists
* @author Sean Coates <sean@php.net>
*/
public function offsetExists($key) {
return isset($this->value[$key]);
}
/**
* Fetch a specific key from the CFArray
* @param string $key the key to check
* @return mixed the value associated with the key; null if the key is not found
* @link http://php.net/manual/en/arrayaccess.offsetget.php
* @uses get() to get the key's value
* @author Sean Coates <sean@php.net>
*/
public function offsetGet($key) {
return $this->get($key);
}
/**
* Set a value in the array
* @param string $key the key to set
* @param string $value the value to set
* @return void
* @link http://php.net/manual/en/arrayaccess.offsetset.php
* @uses setValue() to set the key's new value
* @author Sean Coates <sean@php.net>
*/
public function offsetSet($key, $value) {
return $this->setValue($value);
}
/**
* Unsets a value in the array
* <b>Note:</b> this dummy does nothing
* @param string $key the key to set
* @return void
* @link http://php.net/manual/en/arrayaccess.offsetunset.php
* @author Sean Coates <sean@php.net>
*/
public function offsetUnset($key) {
}
}
/**
* Array Type of CFPropertyList
* @author Rodney Rehm <rodney.rehm@medialize.de>
* @author Christian Kruse <cjk@wwwtech.de>
* @package plist
* @subpackage plist.types
*/
class CFDictionary extends CFType implements Iterator {
/**
* Position of iterator {@link http://php.net/manual/en/class.iterator.php}
* @var integer
*/
protected $iteratorPosition = 0;
/**
* List of Keys for numerical iterator access {@link http://php.net/manual/en/class.iterator.php}
* @var array
*/
protected $iteratorKeys = null;
/**
* Create new CFType.
* @param array $value Value of CFType
*/
public function __construct($value=array()) {
$this->value = $value;
}
/**
* Set the CFType's value
* <b>Note:</b> this dummy does nothing
* @return void
*/
public function setValue($value) {
}
/**
* Add CFType to collection.
* @param string $key Key to add to collection
* @param CFType $value CFType to add to collection, defaults to null which results in an empty {@link CFString}
* @return void
* @uses $value for adding $key $value pair
*/
public function add($key, CFType $value=null) {
// anything but CFType is null, null is an empty string - sad but true
if( !$value )
$value = new CFString();
$this->value[$key] = $value;
}
/**
* Get CFType from collection.
* @param string $key Key of CFType to retrieve from collection
* @return CFType CFType found at $key, null else
* @uses $value for retrieving CFType of $key
*/
public function get($key) {
if(isset($this->value[$key])) return $this->value[$key];
return null;
}
/**
* Generic getter (magic)
* @param integer $key Key of CFType to retrieve from collection
* @return CFType CFType found at $key, null else
* @link http://php.net/oop5.overloading
* @uses get() to retrieve the key's value
* @author Sean Coates <sean@php.net>
*/
public function __get($key) {
return $this->get($key);
}
/**
* Remove CFType from collection.
* @param string $key Key of CFType to removes from collection
* @return CFType removed CFType, null else
* @uses $value for removing CFType of $key
*/
public function del($key) {
if(isset($this->value[$key])) unset($this->value[$key]);
}
/************************************************************************************************
* S E R I A L I Z I N G
************************************************************************************************/
/**
* Get XML-Node.
* @param DOMDocument $doc DOMDocument to create DOMNode in
* @param string $nodeName For compatibility reasons; just ignore it
* @return DOMNode &lt;dict&gt;-Element
*/
public function toXML(DOMDocument $doc,$nodeName="") {
$node = $doc->createElement('dict');
foreach($this->value as $key => $value) {
$node->appendChild($doc->createElement('key', $key));
$node->appendChild($value->toXML($doc));
}
return $node;
}
/**
* convert value to binary representation
* @param CFBinaryPropertyList The binary property list object
* @return The offset in the object table
*/
public function toBinary(CFBinaryPropertyList &$bplist) {
return $bplist->dictToBinary($this);
}
/**
* Get CFType's value.
* @return array primitive value
* @uses $value for retrieving primitive of CFType
*/
public function toArray() {
$a = array();
foreach($this->value as $key => $value) $a[$key] = $value->toArray();
return $a;
}
/************************************************************************************************
* I T E R A T O R I N T E R F A C E
************************************************************************************************/
/**
* Rewind {@link $iteratorPosition} to first position (being 0)
* @link http://php.net/manual/en/iterator.rewind.php
* @return void
* @uses $iteratorPosition set to 0
* @uses $iteratorKeys store keys of {@link $value}
*/
public function rewind() {
$this->iteratorPosition = 0;
$this->iteratorKeys = array_keys($this->value);
}
/**
* Get Iterator's current {@link CFType} identified by {@link $iteratorPosition}
* @link http://php.net/manual/en/iterator.current.php
* @return CFType current Item
* @uses $iteratorPosition identify current key
* @uses $iteratorKeys identify current value
*/
public function current() {
return $this->value[$this->iteratorKeys[$this->iteratorPosition]];
}
/**
* Get Iterator's current key identified by {@link $iteratorPosition}
* @link http://php.net/manual/en/iterator.key.php
* @return string key of the current Item
* @uses $iteratorPosition identify current key
* @uses $iteratorKeys identify current value
*/
public function key() {
return $this->iteratorKeys[$this->iteratorPosition];
}
/**
* Increment {@link $iteratorPosition} to address next {@see CFType}
* @link http://php.net/manual/en/iterator.next.php
* @return void
* @uses $iteratorPosition increment by 1
*/
public function next() {
$this->iteratorPosition++;
}
/**
* Test if {@link $iteratorPosition} addresses a valid element of {@link $value}
* @link http://php.net/manual/en/iterator.valid.php
* @return boolean true if current position is valid, false else
* @uses $iteratorPosition test if within {@link $iteratorKeys}
* @uses $iteratorPosition test if within {@link $value}
*/
public function valid() {
return isset($this->iteratorKeys[$this->iteratorPosition]) && isset($this->value[$this->iteratorKeys[$this->iteratorPosition]]);
}
}
# eof

@ -0,0 +1,185 @@
<?php
/**
* CFTypeDetector
* Interface for converting native PHP data structures to CFPropertyList objects.
* @author Rodney Rehm <rodney.rehm@medialize.de>
* @author Christian Kruse <cjk@wwwtech.de>
* @package plist
* @subpackage plist.types
* @example example-create-02.php Using {@link CFTypeDetector}
* @example example-create-03.php Using {@link CFTypeDetector} with {@link CFDate} and {@link CFData}
* @example example-create-04.php Using and extended {@link CFTypeDetector}
*/
namespace CFPropertyList;
use \DateTime, \Iterator;
class CFTypeDetector {
/**
* flag stating if all arrays should automatically be converted to {@link CFDictionary}
* @var boolean
*/
protected $autoDictionary = false;
/**
* flag stating if exceptions should be suppressed or thrown
* @var boolean
*/
protected $suppressExceptions = false;
/**
* name of a method that will be used for array to object conversations
* @var callable
*/
protected $objectToArrayMethod = null;
/**
* flag stating if "123.23" should be converted to float (true) or preserved as string (false)
* @var boolean
*/
protected $castNumericStrings = true;
/**
* Create new CFTypeDetector
* @param array $options Configuration for casting values [autoDictionary, suppressExceptions, objectToArrayMethod, castNumericStrings]
*/
public function __construct(array $options=array()) {
//$autoDicitionary=false,$suppressExceptions=false,$objectToArrayMethod=null
foreach ($options as $key => $value) {
if (property_exists($this, $key)) {
$this->$key = $value;
}
}
}
/**
* Determine if an array is associative or numerical.
* Numerical Arrays have incrementing index-numbers that don't contain gaps.
* @param array $value Array to check indexes of
* @return boolean true if array is associative, false if array has numeric indexes
*/
protected function isAssociativeArray($value) {
$numericKeys = true;
$i = 0;
foreach($value as $key => $v) {
if($i !== $key) {
$numericKeys = false;
break;
}
$i++;
}
return !$numericKeys;
}
/**
* Get the default value
* @return CFType the default value to return if no suitable type could be determined
*/
protected function defaultValue() {
return new CFString();
}
/**
* Create CFType-structure by guessing the data-types.
* {@link CFArray}, {@link CFDictionary}, {@link CFBoolean}, {@link CFNumber} and {@link CFString} can be created, {@link CFDate} and {@link CFData} cannot.
* <br /><b>Note:</b>Distinguishing between {@link CFArray} and {@link CFDictionary} is done by examining the keys.
* Keys must be strictly incrementing integers to evaluate to a {@link CFArray}.
* Since PHP does not offer a function to test for associative arrays,
* this test causes the input array to be walked twice and thus work rather slow on large collections.
* If you work with large arrays and can live with all arrays evaluating to {@link CFDictionary},
* feel free to set the appropriate flag.
* <br /><b>Note:</b> If $value is an instance of CFType it is simply returned.
* <br /><b>Note:</b> If $value is neither a CFType, array, numeric, boolean nor string, it is omitted.
* @param mixed $value Value to convert to CFType
* @param boolean $autoDictionary if true {@link CFArray}-detection is bypassed and arrays will be returned as {@link CFDictionary}.
* @return CFType CFType based on guessed type
* @uses isAssociativeArray() to check if an array only has numeric indexes
*/
public function toCFType($value) {
switch(true) {
case $value instanceof CFType:
return $value;
break;
case is_object($value):
// DateTime should be CFDate
if(class_exists( 'DateTime' ) && $value instanceof DateTime){
return new CFDate($value->getTimestamp());
}
// convert possible objects to arrays, arrays will be arrays
if($this->objectToArrayMethod && is_callable(array($value, $this->objectToArrayMethod))){
$value = call_user_func( array( $value, $this->objectToArrayMethod ) );
}
if(!is_array($value)){
if($this->suppressExceptions)
return $this->defaultValue();
throw new PListException('Could not determine CFType for object of type '. get_class($value));
}
/* break; omitted */
case $value instanceof Iterator:
case is_array($value):
// test if $value is simple or associative array
if(!$this->autoDictionary) {
if(!$this->isAssociativeArray($value)) {
$t = new CFArray();
foreach($value as $v) $t->add($this->toCFType($v));
return $t;
}
}
$t = new CFDictionary();
foreach($value as $k => $v) $t->add($k, $this->toCFType($v));
return $t;
break;
case is_bool($value):
return new CFBoolean($value);
break;
case is_null($value):
return new CFString();
break;
case is_resource($value):
if ($this->suppressExceptions) {
return $this->defaultValue();
}
throw new PListException('Could not determine CFType for resource of type '. get_resource_type($value));
break;
case is_numeric($value):
if (!$this->castNumericStrings && is_string($value)) {
return new CFString($value);
}
return new CFNumber($value);
break;
case is_string($value):
if(strpos($value, "\x00") !== false) {
return new CFData($value);
}
return new CFString($value);
break;
default:
if ($this->suppressExceptions) {
return $this->defaultValue();
}
throw new PListException('Could not determine CFType for '. gettype($value));
break;
}
}
}

@ -0,0 +1,98 @@
<?php
/**
* CFPropertyList
* {@link http://developer.apple.com/documentation/Darwin/Reference/ManPages/man5/plist.5.html Property Lists}
* @author Rodney Rehm <rodney.rehm@medialize.de>
* @author Christian Kruse <cjk@wwwtech.de>
* @package plist
* @version $Id$
*/
namespace CFPropertyList;
/**
* Basic Input / Output Exception
* @author Rodney Rehm <rodney.rehm@medialize.de>
* @author Christian Kruse <cjk@wwwtech.de>
* @package plist
*/
class IOException extends \Exception {
/**
* Flag telling the File could not be found
*/
const NOT_FOUND = 1;
/**
* Flag telling the File is not readable
*/
const NOT_READABLE = 2;
/**
* Flag telling the File is not writable
*/
const NOT_WRITABLE = 3;
/**
* Flag telling there was a read error
*/
const READ_ERROR = 4;
/**
* Flag telling there was a read error
*/
const WRITE_ERROR = 5;
/**
* Create new IOException
* @param string $path Source of the problem
* @param integer $type Type of the problem
*/
public function __construct($path, $type=null) {
parent::__construct( $path, $type );
}
/**
* Create new FileNotFound-Exception
* @param string $path Source of the problem
* @return IOException new FileNotFound-Exception
*/
public static function notFound($path) {
return new IOException( $path, self::NOT_FOUND );
}
/**
* Create new FileNotReadable-Exception
* @param string $path Source of the problem
* @return IOException new FileNotReadable-Exception
*/
public static function notReadable($path) {
return new IOException( $path, self::NOT_READABLE );
}
/**
* Create new FileNotWritable-Exception
* @param string $path Source of the problem
* @return IOException new FileNotWritable-Exception
*/
public static function notWritable($path) {
return new IOException( $path, self::NOT_WRITABLE );
}
/**
* Create new ReadError-Exception
* @param string $path Source of the problem
* @return IOException new ReadError-Exception
*/
public static function readError($path) {
return new IOException( $path, self::READ_ERROR );
}
/**
* Create new WriteError-Exception
* @param string $path Source of the problem
* @return IOException new WriteError-Exception
*/
public static function writeError($path) {
return new IOException( $path, self::WRITE_ERROR );
}
}

@ -0,0 +1,22 @@
<?php
/**
* CFPropertyList
* {@link http://developer.apple.com/documentation/Darwin/Reference/ManPages/man5/plist.5.html Property Lists}
* @author Rodney Rehm <rodney.rehm@medialize.de>
* @author Christian Kruse <cjk@wwwtech.de>
* @package plist
* @version $Id$
*/
namespace CFPropertyList;
/**
* Exception for errors with the PList format
* @author Rodney Rehm <rodney.rehm@medialize.de>
* @author Christian Kruse <cjk@wwwtech.de>
* @package plist
*/
class PListException extends \Exception {
}

@ -0,0 +1,30 @@
{
"name": "rodneyrehm/plist",
"description": "Library for reading and writing Apple's CFPropertyList (plist) files in XML as well as binary format.",
"keywords": ["plist"],
"type": "library",
"homepage": "https://github.com/rodneyrehm/CFPropertyList",
"license": "MIT",
"require": {
"php": ">=5.3"
},
"authors": [
{
"name": "Christian Kruse",
"email": "cjk@wwwtech.de"
},
{
"name": "Rodney Rehm",
"email": "mail+github@rodneyrehm.de"
}
],
"support": {
"issues": "https://github.com/rodneyrehm/CFPropertyList/issues",
"source": "https://github.com/rodneyrehm/CFPropertyList"
},
"autoload": {
"psr-0": {
"CFPropertyList":"classes\/"
}
}
}

@ -0,0 +1,67 @@
<?php
/**
* Examples for how to use CFPropertyList
* Create the PropertyList sample.xml.plist by using the CFPropertyList API.
* @package plist
* @subpackage plist.examples
*/
namespace CFPropertyList;
// just in case...
error_reporting( E_ALL );
ini_set( 'display_errors', 'on' );
/**
* Require CFPropertyList
*/
require_once(__DIR__.'/../classes/CFPropertyList/CFPropertyList.php');
/*
* create a new CFPropertyList instance without loading any content
*/
$plist = new CFPropertyList();
/*
* Manuall Create the sample.xml.plist
*/
// the Root element of the PList is a Dictionary
$plist->add( $dict = new CFDictionary() );
// <key>Year Of Birth</key><integer>1965</integer>
$dict->add( 'Year Of Birth', new CFNumber( 1965 ) );
// <key>Date Of Graduation</key><date>2004-06-22T19:23:43Z</date>
$dict->add( 'Date Of Graduation', new CFDate( gmmktime( 19, 23, 43, 06, 22, 2004 ) ) );
// <key>Pets Names</key><array/>
$dict->add( 'Pets Names', new CFArray() );
// <key>Picture</key><data>PEKBpYGlmYFCPA==</data>
// to keep it simple we insert an already base64-encoded string
$dict->add( 'Picture', new CFData( 'PEKBpYGlmYFCPA==', true ) );
// <key>City Of Birth</key><string>Springfield</string>
$dict->add( 'City Of Birth', new CFString( 'Springfield' ) );
// <key>Name</key><string>John Doe</string>
$dict->add( 'Name', new CFString( 'John Doe' ) );
// <key>Kids Names</key><array><string>John</string><string>Kyra</string></array>
$dict->add( 'Kids Names', $array = new CFArray() );
$array->add( new CFString( 'John' ) );
$array->add( new CFString( 'Kyra' ) );
/*
* Save PList as XML
*/
$plist->saveXML( __DIR__.'/example-create-01.xml.plist' );
/*
* Save PList as Binary
*/
$plist->saveBinary( __DIR__.'/example-create-01.binary.plist' );
?>

@ -0,0 +1,61 @@
<?php
/**
* Examples for how to use CFPropertyList
* Create the PropertyList sample.xml.plist by using {@link CFTypeDetector}.
* @package plist
* @subpackage plist.examples
*/
namespace CFPropertyList;
use \DateTime, \DateTimeZone;
// just in case...
error_reporting( E_ALL );
ini_set( 'display_errors', 'on' );
/**
* Require CFPropertyList
*/
require_once(__DIR__.'/../classes/CFPropertyList/CFPropertyList.php');
/*
* create a new CFPropertyList instance without loading any content
*/
$plist = new CFPropertyList();
/*
* import the array structure to create the sample.xml.plist
* We make use of CFTypeDetector, which truly is not almighty!
*/
$structure = array(
'Year Of Birth' => 1965,
// Note: dates cannot be guessed, so this will become a CFNumber and be treated as an integer
// See example-04.php for a possible workaround
'Date Of Graduation' => gmmktime( 19, 23, 43, 06, 22, 2004 ),
'Date Of Birth' => new DateTime( '1984-09-07 08:15:23', new DateTimeZone( 'Europe/Berlin' ) ),
'Pets Names' => array(),
// Note: data cannot be guessed, so this will become a CFString
// See example-03.php for a possible workaround
'Picture' => 'PEKBpYGlmYFCPA==',
'City Of Birth' => 'Springfield',
'Name' => 'John Doe',
'Kids Names' => array( 'John', 'Kyra' ),
);
$td = new CFTypeDetector();
$guessedStructure = $td->toCFType( $structure );
$plist->add( $guessedStructure );
/*
* Save PList as XML
*/
$plist->saveXML( __DIR__.'/example-create-02.xml.plist' );
/*
* Save PList as Binary
*/
$plist->saveBinary( __DIR__.'/example-create-02.binary.plist' );
?>

@ -0,0 +1,58 @@
<?php
/**
* Examples for how to use CFPropertyList
* Create the PropertyList sample.xml.plist by using {@link CFTypeDetector}.
* This example shows how to get around the limitation of guess() regarding {@link CFDate} and {@link CFData}.
* @package plist
* @subpackage plist.examples
*/
namespace CFPropertyList;
// just in case...
error_reporting( E_ALL );
ini_set( 'display_errors', 'on' );
/**
* Require CFPropertyList
*/
require_once(__DIR__.'/../classes/CFPropertyList/CFPropertyList.php');
/*
* create a new CFPropertyList instance without loading any content
*/
$plist = new CFPropertyList();
/*
* import the array structure to create the sample.xml.plist
* We make use of CFTypeDetector, which truly is not almighty!
*/
$structure = array(
'Year Of Birth' => 1965,
// Note: dates cannot be guessed, it thus has to be specified explicitly
'Date Of Graduation' => new CFDate( gmmktime( 19, 23, 43, 06, 22, 2004 ) ),
'Pets Names' => array(),
// Note: data cannot be guessed, it thus has to be specified explicitly
'Picture' => new CFData( 'PEKBpYGlmYFCPA==', true ),
'City Of Birth' => 'Springfield',
'Name' => 'John Doe',
'Kids Names' => array( 'John', 'Kyra' ),
);
$td = new CFTypeDetector();
$guessedStructure = $td->toCFType( $structure );
$plist->add( $guessedStructure );
/*
* Save PList as XML
*/
$plist->saveXML( __DIR__.'/example-create-03.xml.plist' );
/*
* Save PList as Binary
*/
$plist->saveBinary( __DIR__.'/example-create-03.binary.plist' );
?>

@ -0,0 +1,92 @@
<?php
/**
* Examples for how to use CFPropertyList
* Create the PropertyList sample.xml.plist by using {@link CFTypeDetector}.
* @package plist
* @subpackage plist.examples
*/
namespace CFPropertyList;
// just in case...
error_reporting( E_ALL );
ini_set( 'display_errors', 'on' );
/**
* Require CFPropertyList
*/
require_once(__DIR__.'/../classes/CFPropertyList/CFPropertyList.php');
class DemoDetector extends CFTypeDetector {
public function toCFType($value) {
if( $value instanceof PListException ) {
return new CFString( $value->getMessage() );
}
return parent::toCFType($value);
}
}
/*
* import the array structure to create the sample.xml.plist
* We make use of CFTypeDetector, which truly is not almighty!
*/
$stack = new \SplStack();
$stack[] = 1;
$stack[] = 2;
$stack[] = 3;
$structure = array(
'NullValueTest' => null,
'IteratorTest' => $stack,
'ObjectTest' => new PListException('Just a test...'),
);
/*
* Try default detection
*/
try {
$plist = new CFPropertyList();
$td = new CFTypeDetector();
$guessedStructure = $td->toCFType( $structure );
$plist->add( $guessedStructure );
$plist->saveXML( __DIR__.'/example-create-04.xml.plist' );
$plist->saveBinary( __DIR__.'/example-create-04.binary.plist' );
}
catch( PListException $e ) {
echo 'Normal detection: ', $e->getMessage(), "\n";
}
/*
* Try detection by omitting exceptions
*/
try {
$plist = new CFPropertyList();
$td = new CFTypeDetector( array('suppressExceptions' => true) );
$guessedStructure = $td->toCFType( $structure );
$plist->add( $guessedStructure );
$plist->saveXML( __DIR__.'/example-create-04.xml.plist' );
$plist->saveBinary( __DIR__.'/example-create-04.binary.plist' );
}
catch( PListException $e ) {
echo 'Silent detection: ', $e->getMessage(), "\n";
}
/*
* Try detection with an extended version of CFTypeDetector
*/
try {
$plist = new CFPropertyList();
$td = new DemoDetector();
$guessedStructure = $td->toCFType( $structure );
$plist->add( $guessedStructure );
$plist->saveXML( __DIR__.'/example-create-04.xml.plist' );
$plist->saveBinary( __DIR__.'/example-create-04.binary.plist' );
}
catch( PListException $e ) {
echo 'User defined detection: ', $e->getMessage(), "\n";
}
?>

@ -0,0 +1,41 @@
<?php
/**
* Examples for how to use CFPropertyList
* Modify a PropertyList
* @package plist
* @subpackage plist.examples
*/
namespace CFPropertyList;
// just in case...
error_reporting( E_ALL );
ini_set( 'display_errors', 'on' );
/**
* Require CFPropertyList
*/
require_once(__DIR__.'/../classes/CFPropertyList/CFPropertyList.php');
// load an existing list
$plist = new CFPropertyList( __DIR__.'/sample.xml.plist' );
foreach( $plist->getValue(true) as $key => $value )
{
if( $key == "City Of Birth" )
{
$value->setValue( 'Mars' );
}
if( $value instanceof \Iterator )
{
// The value is a CFDictionary or CFArray, you may continue down the tree
}
}
// save data
$plist->save( __DIR__.'/modified.plist', CFPropertyList::FORMAT_XML );
?>

@ -0,0 +1,34 @@
<?php
/**
* Examples for how to use CFPropertyList
* Read an XML PropertyList
* @package plist
* @subpackage plist.examples
*/
namespace CFPropertyList;
// just in case...
error_reporting( E_ALL );
ini_set( 'display_errors', 'on' );
/**
* Require CFPropertyList
*/
require_once(__DIR__.'/../classes/CFPropertyList/CFPropertyList.php');
/*
* create a new CFPropertyList instance which loads the sample.plist on construct.
* since we know it's an XML file, we can skip format-determination
*/
$plist = new CFPropertyList( __DIR__.'/sample.xml.plist', CFPropertyList::FORMAT_XML );
/*
* retrieve the array structure of sample.plist and dump to stdout
*/
echo '<pre>';
var_dump( $plist->toArray() );
echo '</pre>';
?>

@ -0,0 +1,36 @@
<?php
/**
* Examples for how to use CFPropertyList
* Read a Binary PropertyList
* @package plist
* @subpackage plist.examples
*/
namespace CFPropertyList;
// just in case...
error_reporting( E_ALL );
ini_set( 'display_errors', 'on' );
/**
* Require CFPropertyList
*/
require_once(__DIR__.'/../classes/CFPropertyList/CFPropertyList.php');
/*
* create a new CFPropertyList instance which loads the sample.plist on construct.
* since we know it's a binary file, we can skip format-determination
*/
$plist = new CFPropertyList( __DIR__.'/sample.binary.plist', CFPropertyList::FORMAT_BINARY );
/*
* retrieve the array structure of sample.plist and dump to stdout
*/
echo '<pre>';
var_dump( $plist->toArray() );
echo '</pre>';
$plist->saveBinary( __DIR__.'/sample.binary.plist' );
?>

@ -0,0 +1,36 @@
<?php
/**
* Examples for how to use CFPropertyList
* Read a PropertyList without knowing the type
* @package plist
* @subpackage plist.examples
*/
namespace CFPropertyList;
// just in case...
error_reporting( E_ALL );
ini_set( 'display_errors', 'on' );
/**
* Require CFPropertyList
*/
require_once(__DIR__.'/../classes/CFPropertyList/CFPropertyList.php');
/*
* create a new CFPropertyList instance which loads the sample.plist on construct.
* since we know the format, use the automatic format-detection
*/
$plist = new CFPropertyList( __DIR__.'/sample.binary.plist' );
/*
* retrieve the array structure of sample.plist and dump to stdout
*/
echo '<pre>';
var_dump( $plist->toArray() );
echo '</pre>';
$plist->saveBinary( __DIR__.'/sample.binary.plist' );
?>

@ -0,0 +1,36 @@
<?php
/**
* Examples for how to use CFPropertyList with strings
* Read a binary from a string PropertyList
* @package plist
* @subpackage plist.examples
*/
namespace CFPropertyList;
// just in case...
error_reporting( E_ALL );
ini_set( 'display_errors', 'on' );
/**
* Require CFPropertyList
*/
require_once(__DIR__.'/../classes/CFPropertyList/CFPropertyList.php');
/*
* create a new CFPropertyList instance which loads the sample.plist on construct.
* since we know it's an binary file, we can skip format-determination
*/
$content = file_get_contents(__DIR__.'/sample.binary.plist');
$plist = new CFPropertyList();
$plist->parseBinary($content);
/*
* retrieve the array structure of sample.plist and dump to stdout
*/
echo '<pre>';
var_dump( $plist->toArray() );
echo '</pre>';
?>

@ -0,0 +1,36 @@
<?php
/**
* Examples for how to use CFPropertyList with strings
* Read a binary from a string PropertyList
* @package plist
* @subpackage plist.examples
*/
namespace CFPropertyList;
// just in case...
error_reporting( E_ALL );
ini_set( 'display_errors', 'on' );
/**
* Require CFPropertyList
*/
require_once(__DIR__.'/../classes/CFPropertyList/CFPropertyList.php');
/*
* create a new CFPropertyList instance which loads the sample.plist on construct.
* We don't know that it is a binary plist, so we simply call ->parse()
*/
$content = file_get_contents(__DIR__.'/sample.binary.plist');
$plist = new CFPropertyList();
$plist->parse($content);
/*
* retrieve the array structure of sample.plist and dump to stdout
*/
echo '<pre>';
var_dump( $plist->toArray() );
echo '</pre>';
?>

@ -0,0 +1,30 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Year Of Birth</key>
<integer>1965</integer>
<key>Date Of Graduation</key>
<date>2004-06-22T19:23:43Z</date>
<key>Pets Names</key>
<array/>
<key>Picture</key>
<data>PEKBpYGlmYFCPA==</data>
<key>City Of Birth</key>
<string>Springfield</string>
<key>Name</key>
<string>John Doe</string>
<key>Kids Names</key>
<array>
<string>John</string>
<string>Kyra</string>
</array>
</dict>
</plist>

@ -0,0 +1,122 @@
<?php
namespace CFPropertyList;
error_reporting(E_ALL|E_STRICT);
ini_set('display_errors','on');
if(!defined('LIBDIR')) {
define('LIBDIR',__DIR__.'/../classes/CFPropertyList');
}
if(!defined('TEST_BINARY_DATA_FILE')) {
define('TEST_BINARY_DATA_FILE',__DIR__.'/binary-data.plist');
define('TEST_UID_BPLIST', __DIR__ . '/uid-list.plist');
}
require_once(LIBDIR.'/CFPropertyList.php');
class BinaryParseTest extends \PHPUnit_Framework_TestCase {
public function testParseBinary() {
$plist = new CFPropertyList(TEST_BINARY_DATA_FILE);
$vals = $plist->toArray();
$this->assertEquals(count($vals),4);
$this->assertEquals($vals['names']['given-name'],'John');
$this->assertEquals($vals['names']['surname'],'Dow');
$this->assertEquals($vals['pets'][0],'Jonny');
$this->assertEquals($vals['pets'][1],'Bello');
$this->assertEquals($vals['age'],28);
$this->assertEquals($vals['birth-date'],412035803);
}
public function testParseBinaryString() {
$content = file_get_contents(TEST_BINARY_DATA_FILE);
$plist = new CFPropertyList();
$plist->parse($content);
$vals = $plist->toArray();
$this->assertEquals(count($vals),4);
$this->assertEquals($vals['names']['given-name'],'John');
$this->assertEquals($vals['names']['surname'],'Dow');
$this->assertEquals($vals['pets'][0],'Jonny');
$this->assertEquals($vals['pets'][1],'Bello');
$this->assertEquals($vals['age'],28);
$this->assertEquals($vals['birth-date'],412035803);
}
public function testParseStream() {
$plist = new CFPropertyList();
if(($fd = fopen(TEST_BINARY_DATA_FILE,"rb")) == NULL) {
throw new IOException("Error opening test data file for reading!");
}
$plist->readBinaryStream($fd);
$vals = $plist->toArray();
$this->assertEquals(count($vals),4);
$this->assertEquals($vals['names']['given-name'],'John');
$this->assertEquals($vals['names']['surname'],'Dow');
$this->assertEquals($vals['pets'][0],'Jonny');
$this->assertEquals($vals['pets'][1],'Bello');
$this->assertEquals($vals['age'],28);
$this->assertEquals($vals['birth-date'],412035803);
}
/**
* @expectedException CFPropertyList\PListException
*/
public function testEmptyString() {
$plist = new CFPropertyList();
$plist->parseBinary('');
}
public function testInvalidString() {
$catched = false;
try {
$plist = new CFPropertyList();
$plist->parseBinary('lalala');
}
catch(PListException $e) {
$catched = true;
}
if($catched == false) {
$this->fail('No exception thrown for invalid string!');
}
$catched = false;
try {
$plist = new CFPropertyList();
$plist->parseBinary('bplist00dfwefwefwef');
}
catch(PListException $e) {
return;
}
$this->fail('No exception thrown for invalid string!');
}
public function testUidPlist() {
$plist = new CFPropertyList(TEST_UID_BPLIST);
$val = $plist->toArray();
$this->assertEquals(array('test' => 1), $val);
$v = $plist->getValue()->getValue();
$this->assertTrue($v['test'] instanceof CFUid);
}
}
# eof

@ -0,0 +1,31 @@
<?php
namespace CFPropertyList;
error_reporting(E_ALL | E_STRICT);
ini_set('display_errors', 'on');
if (!defined('LIBDIR')) {
define('LIBDIR', __DIR__ . '/../classes/CFPropertyList');
}
require_once(LIBDIR . '/CFPropertyList.php');
class EmptyElementsTest extends \PHPUnit_Framework_TestCase {
public function testWriteFile() {
$expected = '<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0"><dict><key>string</key><string/><key>number</key><integer>0</integer><key>double</key><real>0</real></dict></plist>
';
$plist = new CFPropertyList();
$dict = new CFDictionary();
$dict->add('string', new CFString(''));
$dict->add('number', new CFNumber(0));
$dict->add('double', new CFNumber(0.0));
$plist->add($dict);
$this->assertEquals($expected, $plist->toXML());
}
}

@ -0,0 +1,126 @@
<?php
namespace CFPropertyList;
error_reporting(E_ALL|E_STRICT);
ini_set('display_errors','on');
if(!defined('LIBDIR')) {
define('LIBDIR',__DIR__.'/../classes/CFPropertyList');
}
if(!defined('TEST_XML_DATA_FILE')) {
define('TEST_XML_DATA_FILE',__DIR__.'/xml-data.plist');
define('TEST_UID_XML_PLIST', __DIR__ . '/uid-list.xml');
}
require_once(LIBDIR.'/CFPropertyList.php');
class ParseXMLTest extends \PHPUnit_Framework_TestCase {
public function testParse() {
$plist = new CFPropertyList(TEST_XML_DATA_FILE);
$vals = $plist->toArray();
$this->assertEquals(count($vals),4);
$this->assertEquals($vals['names']['given-name'],'John');
$this->assertEquals($vals['names']['surname'],'Dow');
$this->assertEquals($vals['pets'][0],'Jonny');
$this->assertEquals($vals['pets'][1],'Bello');
$this->assertEquals($vals['age'],28);
$this->assertEquals($vals['birth-date'],412035803);
}
public function testParseString() {
$content = file_get_contents(TEST_XML_DATA_FILE);
$plist = new CFPropertyList();
$plist->parse($content);
$vals = $plist->toArray();
$this->assertEquals(count($vals),4);
$this->assertEquals($vals['names']['given-name'],'John');
$this->assertEquals($vals['names']['surname'],'Dow');
$this->assertEquals($vals['pets'][0],'Jonny');
$this->assertEquals($vals['pets'][1],'Bello');
$this->assertEquals($vals['age'],28);
$this->assertEquals($vals['birth-date'],412035803);
}
public function testParseStream() {
$plist = new CFPropertyList();
if(($fd = fopen(TEST_XML_DATA_FILE,"r")) == NULL) {
throw new IOException("Error opening test data file for reading!");
}
$plist->loadXMLStream($fd);
$vals = $plist->toArray();
$this->assertEquals(count($vals),4);
$this->assertEquals($vals['names']['given-name'],'John');
$this->assertEquals($vals['names']['surname'],'Dow');
$this->assertEquals($vals['pets'][0],'Jonny');
$this->assertEquals($vals['pets'][1],'Bello');
$this->assertEquals($vals['age'],28);
$this->assertEquals($vals['birth-date'],412035803);
}
/**
* @expectedException CFPropertyList\IOException
*/
public function testEmptyString() {
$plist = new CFPropertyList();
$plist->parse('');
}
public function testInvalidString() {
$catched = false;
try {
$plist = new CFPropertyList();
$plist->parse('lalala');
}
catch(\DOMException $e) {
$catched = true;
}
catch(\PHPUnit_Framework_Error $e) {
$catched = true;
}
if($catched == false) {
$this->fail('No exception thrown for invalid string!');
}
$catched = false;
try {
$plist = new CFPropertyList();
$plist->parse('<plist>');
}
catch(PListException $e) {
return;
}
catch(\PHPUnit_Framework_Error $e) {
return;
}
$this->fail('No exception thrown for invalid string!');
}
public function testUidPlist() {
$plist = new CFPropertyList(TEST_UID_XML_PLIST);
$val = $plist->toArray();
$this->assertEquals(array('test' => 1), $val);
$v = $plist->getValue()->getValue();
$this->assertTrue($v['test'] instanceof CFUid);
}
}
# eof

@ -0,0 +1,87 @@
<?php
namespace CFPropertyList;
error_reporting(E_ALL|E_STRICT);
ini_set('display_errors','on');
if(!defined('LIBDIR')) {
define('LIBDIR',__DIR__.'/../classes/CFPropertyList');
}
if(!defined('WRITE_BINARY_DATA_FILE')) {
define('WRITE_BINARY_DATA_FILE',__DIR__.'/binary.plist');
define('TEST_UID_BPLIST', __DIR__ . '/uid-list.plist');
}
require_once(LIBDIR.'/CFPropertyList.php');
class WriteBinaryTest extends \PHPUnit_Framework_TestCase {
public function testWriteFile() {
$plist = new CFPropertyList();
$dict = new CFDictionary();
$names = new CFDictionary();
$names->add('given-name',new CFString('John'));
$names->add('surname',new CFString('Dow'));
$dict->add('names',$names);
$pets = new CFArray();
$pets->add(new CFString('Jonny'));
$pets->add(new CFString('Bello'));
$dict->add('pets',$pets);
$dict->add('age',new CFNumber(28));
$dict->add('birth-date',new CFDate(412035803));
$plist->add($dict);
$plist->saveBinary(WRITE_BINARY_DATA_FILE);
$this->assertTrue(is_file(WRITE_BINARY_DATA_FILE));
$this->assertTrue(filesize(WRITE_BINARY_DATA_FILE) > 32);
$plist->load(WRITE_BINARY_DATA_FILE);
unlink(WRITE_BINARY_DATA_FILE);
}
public function testWriteString() {
$plist = new CFPropertyList();
$dict = new CFDictionary();
$names = new CFDictionary();
$names->add('given-name',new CFString('John'));
$names->add('surname',new CFString('Dow'));
$dict->add('names',$names);
$pets = new CFArray();
$pets->add(new CFString('Jonny'));
$pets->add(new CFString('Bello'));
$dict->add('pets',$pets);
$dict->add('age',new CFNumber(28));
$dict->add('birth-date',new CFDate(412035803));
$plist->add($dict);
$content = $plist->toBinary();
$this->assertTrue(strlen($content) > 32);
$plist->parse($content);
}
public function testWriteUid() {
$plist = new CFPropertyList();
$dict = new CFDictionary();
$dict->add('test', new CFUid(1));
$plist->add($dict);
$plist1 = new CFPropertyList(TEST_UID_BPLIST);
$this->assertEquals($plist1->toBinary(), $plist->toBinary());
}
}
# eof

@ -0,0 +1,85 @@
<?php
namespace CFPropertyList;
error_reporting(E_ALL|E_STRICT);
ini_set('display_errors','on');
if(!defined('LIBDIR')) {
define('LIBDIR',__DIR__.'/../classes/CFPropertyList');
}
if(!defined('WRITE_XML_DATA_FILE')) {
define('WRITE_XML_DATA_FILE',__DIR__.'/binary.plist');
define('TEST_UID_XML_PLIST', __DIR__ . '/uid-list.xml');
}
require_once(LIBDIR.'/CFPropertyList.php');
class WriteXMLTest extends \PHPUnit_Framework_TestCase {
public function testWriteFile() {
$plist = new CFPropertyList();
$dict = new CFDictionary();
$names = new CFDictionary();
$names->add('given-name',new CFString('John'));
$names->add('surname',new CFString('Dow'));
$dict->add('names',$names);
$pets = new CFArray();
$pets->add(new CFString('Jonny'));
$pets->add(new CFString('Bello'));
$dict->add('pets',$pets);
$dict->add('age',new CFNumber(28));
$dict->add('birth-date',new CFDate(412035803));
$plist->add($dict);
$plist->saveXML(WRITE_XML_DATA_FILE);
$this->assertTrue(is_file(WRITE_XML_DATA_FILE));
$plist->load(WRITE_XML_DATA_FILE);
unlink(WRITE_XML_DATA_FILE);
}
public function testWriteString() {
$plist = new CFPropertyList();
$dict = new CFDictionary();
$names = new CFDictionary();
$names->add('given-name',new CFString('John'));
$names->add('surname',new CFString('Dow'));
$dict->add('names',$names);
$pets = new CFArray();
$pets->add(new CFString('Jonny'));
$pets->add(new CFString('Bello'));
$dict->add('pets',$pets);
$dict->add('age',new CFNumber(28));
$dict->add('birth-date',new CFDate(412035803));
$plist->add($dict);
$content = $plist->toXML();
$plist->parse($content);
}
public
function testWriteUid() {
$plist = new CFPropertyList();
$dict = new CFDictionary();
$dict->add('test', new CFUid(1));
$plist->add($dict);
$plist1 = new CFPropertyList(TEST_UID_XML_PLIST);
$this->assertEquals($plist1->toXml(), $plist->toXml());
}
}
# eof

Binary file not shown.

Binary file not shown.

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>test</key>
<dict>
<key>CF$UID</key>
<integer>1</integer>
</dict>
</dict>
</plist>

@ -0,0 +1,22 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>age</key>
<string>28</string>
<key>birth-date</key>
<date>1983-01-21T22:23:23Z</date>
<key>names</key>
<dict>
<key>given-name</key>
<string>John</string>
<key>surname</key>
<string>Dow</string>
</dict>
<key>pets</key>
<array>
<string>Jonny</string>
<string>Bello</string>
</array>
</dict>
</plist>
Loading…
Cancel
Save