Commit 66b7bc5eb6ad94278d50bfdf3d4660eb9c52352a

Authored by teemitop
1 parent e2d3ff7d

短信

Too many changes to show.

To preserve performance only 18 of 18+ files are displayed.

  1 +{include file="common/head"/}
  2 +<div class="admin-main layui-anim layui-anim-upbit">
  3 + <fieldset class="layui-elem-field layui-field-title">
  4 + <legend>{:$title}</legend>
  5 + </fieldset>
  6 + <div class="demoTable">
  7 + 商家:
  8 + <div class="layui-input-inline">
  9 + <input class="layui-input" name="key" id="key" placeholder="{:lang('pleaseEnter')}店铺名称" autocomplete="off">
  10 + </div>
  11 + 日期范围:
  12 + <div class="layui-input-inline" >
  13 + <input type="text" style = "width:300px"; class="layui-input" id="time" placeholder="默认为当天的充值情况">
  14 + </div>
  15 + 商家来源:
  16 + <div class="layui-input-inline layui-form">
  17 + <div class="layui-input-8">
  18 + <select name="class" id="channel" lay-filter="myselect">
  19 + <option value="-1">全部</option>
  20 + <option value="1" selected>合作</option>
  21 + <option value="2">推广</option>
  22 + <option value="3">测试</option>
  23 + </select>
  24 + </div>
  25 + </div>
  26 +
  27 + <button class="layui-btn" id="search" data-type="reload">查询统计</button>
  28 + </div>
  29 + <table class="layui-table" id="list" lay-filter="list"></table>
  30 +</div>
  31 +<script type="text/html" id="toolbarDemo">
  32 +</script>
  33 +{include file="common/foot"/}
  34 +<script>
  35 + layui.use(['table','form','laydate'], function() {
  36 + var table = layui.table,laydate = layui.laydate,$ = layui.jquery;
  37 + console.log(layui);
  38 + var tableIn = table.render({
  39 + elem: '#list',
  40 + url: '{:url("getsellersmslist")}',
  41 + method: 'post',
  42 + title: '短信充值流水',
  43 + page:true,
  44 + toolbar: '#toolbarDemo',
  45 + cols: [[
  46 + {field: 'id', title: '{:lang("id")}',width:70, fixed: true},
  47 + {field: 'sellername', align: 'center',title: '店铺名字'},
  48 + {field: 'package_name', title: '套餐'},
  49 + {field: 'total', title: '充值总数'},
  50 + {field: 'price', title: '金额'},
  51 + {field: 'channel', align: 'center', title: '充值渠道'},
  52 + {field: 'desc', align: 'center', title: '充值备注'},
  53 + {field: 'paystatus', align: 'center',title: '充值状态'},
  54 + {field: 'bdate', align: 'center',title: '购买时间', sort: true},
  55 + {field: 'cdate', align: 'center',title: '记录时间', sort: true},
  56 + ]],
  57 + done: function(res, curr, count){
  58 +
  59 + }
  60 + ,id: 'testReload'
  61 + ,page: true
  62 + ,limit:10
  63 + });
  64 +
  65 + //日期时间范围
  66 + laydate.render({
  67 + elem: '#time'
  68 + ,type: 'datetime'
  69 + ,range: true
  70 + });
  71 +
  72 + //搜索
  73 + $('#search').on('click', function() {
  74 + //关键字
  75 + var key = $('#key').val();
  76 +
  77 + var time = $('#time').val();
  78 + console.log(time);
  79 + //商家来源
  80 + var channel = $('#channel').val();
  81 + console.log(channel);
  82 +
  83 + //传参
  84 + tableIn.reload({ page: {page: 1},where: {key: key,time: time,channel: channel}});
  85 + });
  86 +
  87 + var $ = layui.$, active = {
  88 + reload: function(){
  89 + var key = $('#key');
  90 + //执行重载
  91 + table.reload('testReload', {
  92 + page: {
  93 + curr: 1 //重新从第 1 页开始
  94 + }
  95 + ,where: {
  96 + key: {
  97 + id: key.val()
  98 + }
  99 + }
  100 + });
  101 + }
  102 + };
  103 + })
  104 +</script>
  1 +/*
  2 +* @version: 2.0
  3 +* @Author: tomato
  4 +* @Date: 2018-5-5 11:29:57
  5 +* @Last Modified by: tomato
  6 +* @Last Modified time: 2018-5-26 18:08:43
  7 +*/
  8 +//多选下拉框
  9 +layui.define(['jquery', 'layer'], function(exports){
  10 + var MOD_NAME = 'selectM';
  11 + var $ = layui.jquery,layer=layui.layer;
  12 + var obj = function(config){
  13 + this.disabledIndex =[];
  14 + //当前选中的值名数据
  15 + this.selected = [];
  16 + //当前选中的值
  17 + this.values =[];
  18 + //当前选中的名称
  19 + this.names =[];
  20 +
  21 + //初始化设置参数
  22 + this.config = {
  23 + //选择器id或class
  24 + elem: '',
  25 + //候选项数据[{id:"1",name:"名称1",status:0},{id:"2",name:"名称2",status:1}]
  26 + data: [],
  27 +
  28 + //默认选中值
  29 + selected: [],
  30 +
  31 + //空值项提示,支持将{max}替换为max
  32 + tips: '请选择 最多 {max} 个',
  33 +
  34 + //最多选中个数,默认5
  35 + max : 5,
  36 +
  37 + //选择框宽度
  38 + width:null,
  39 +
  40 + //值验证,与lay-verify一致
  41 + verify: '',
  42 +
  43 + //input的name 不设置与选择器相同(去#.)
  44 + name: '',
  45 +
  46 + //值的分隔符
  47 + delimiter: ',',
  48 +
  49 + //候选项数据的键名 status=0为禁用状态
  50 + field: {idName:'id',titleName:'name',statusName:'status'}
  51 + }
  52 +
  53 + this.config = $.extend(this.config,config);
  54 + //创建选项元素
  55 + this.createOption = function(){
  56 + var o=this,c=o.config,f=c.field,d = c.data;
  57 + var s = c.selected;
  58 + $E = $(c.elem);
  59 + var tips = c.tips.replace('{max}',c.max);
  60 + var inputName = c.name=='' ? c.elem.replace('#','').replace('.','') : c.name;
  61 + var verify = c.verify=='' ? '' : 'lay-verify="'+c.verify+'" ';
  62 + var html = '';
  63 + html += '<div class="layui-unselect layui-form-select">';
  64 + html += '<div class="layui-select-title">';
  65 + html += '<input '+verify+'name="'+inputName+'" type="text" readonly="" class="layui-input layui-unselect">';
  66 + html += '</div>';
  67 + html += '<div class="layui-input multiple">';
  68 + html += '</div>';
  69 + html += '<dl class="layui-anim layui-anim-upbit">';
  70 + html += '<dd lay-value="" class="layui-select-tips">'+tips+'</dd>';
  71 + for(var i=0;i<d.length;i++){
  72 + var disabled1='',disabled2='';
  73 + if(d[i][f.statusName]==0){
  74 + o.disabledIndex[d[i][f.idName]] = d[i][f.titleName];
  75 + disabled1 = d[i][f.statusName]==0 ? 'layui-disabled' : '';
  76 + disabled2 = d[i][f.statusName]==0 ? ' layui-checkbox-disbaled layui-disabled' : '';
  77 + }
  78 + html +='<dd lay-value="'+d[i][f.idName]+'" class="'+disabled1+'">';
  79 + html += '<div class="layui-unselect layui-form-checkbox'+disabled2+'" lay-skin="primary">';
  80 + html += '<span>'+d[i][f.titleName]+'</span><i class="layui-icon">&#xe605;</i>';
  81 + html += '</div>';
  82 + html +='</dd>';
  83 + }
  84 + html += '</dl>';
  85 + html += '</div>';
  86 + $E.html(html);
  87 + }
  88 +
  89 + //设置选中值
  90 + this.set = function(selected){
  91 + var o=this,c=o.config;
  92 + var s = typeof selected=='undefined' ? c.selected : selected;
  93 + $E = $(c.elem);
  94 + $E.find('.layui-form-checkbox').removeClass('layui-form-checked');
  95 + $E.find('dd').removeClass('layui-this');
  96 + //为默认选中值添加类名
  97 + var max = s.length>c.max ? c.max : s.length;
  98 + for(var i=0;i<max;i++){
  99 + if(s[i] && !o.disabledIndex.hasOwnProperty(s[i])){
  100 + $E.find('dd[lay-value='+s[i]+']').addClass('layui-this');
  101 + }
  102 + }
  103 + $E.find('dd.layui-this').each(function(){
  104 + $(this).find('div').addClass('layui-form-checked');
  105 + });
  106 + o.setSelected(selected);
  107 + }
  108 +
  109 + //设置选中值 每次点击操作后执行
  110 + this.setSelected = function(first){
  111 + var o=this,c=o.config,f=c.field;
  112 + $E = $(c.elem);
  113 + var values=[],names=[],selected = [],spans = [];
  114 + var items = $E.find('dd.layui-this');
  115 + if(items.length==0){
  116 + var tips = c.tips.replace('{max}',c.max);
  117 + spans.push('<span class="tips">'+tips+'</span>');
  118 + }
  119 + else{
  120 + items.each(function(){
  121 + $this = $(this);
  122 + var item ={};
  123 + var v = $this.attr('lay-value');
  124 + var n = $this.find('span').text();
  125 + item[f.idName] = v;
  126 + item[f.titleName] = n;
  127 + values.push(v);
  128 + names.push(n);
  129 + spans.push('<a href="javascript:;"><span lay-value="'+v+'">'+n+'</span><i class="layui-icon">&#x1006;</i></a>');
  130 + selected.push(item);
  131 + });
  132 + }
  133 + spans.push('<i class="layui-edge" style="pointer-events: none;"></i>');
  134 + $E.find('.multiple').html(spans.join(''));
  135 + $E.find('.layui-select-title').find('input').each(function(){
  136 + if(typeof first=='undefined'){
  137 + this.defaultValue = values.join(c.delimiter);
  138 + }
  139 + this.value = values.join(c.delimiter);
  140 + });
  141 +
  142 + var h = $E.find('.multiple').height()+14;
  143 + $E.find('.layui-form-select dl').css('top',h+'px');
  144 + o.values=values,o.names=names,o.selected = selected;
  145 + }
  146 + //ajax方式获取候选数据
  147 + this.getData = function(url){
  148 + var d;
  149 + $.ajax({
  150 + url:url,
  151 + dataType:'json',
  152 + async:false,
  153 + success:function(json){
  154 + d=json;
  155 + },
  156 + error: function(){
  157 + console.error(MOD_NAME+' hint:候选数据ajax请求错误 ');
  158 + d = false;
  159 + }
  160 + });
  161 + return d;
  162 + }
  163 + };
  164 + //渲染一个实例
  165 + obj.prototype.render = function(){
  166 + var o=this,c=o.config,f=c.field;
  167 + $E = $(c.elem);
  168 + if($E.length==0){
  169 + console.error(MOD_NAME+' hint:找不到容器 ' +c.elem);
  170 + return false;
  171 + }
  172 + if(Object.prototype.toString.call(c.data)!='[object Array]'){
  173 + var data = o.getData(c.data);
  174 + if(data===false){
  175 + console.error(MOD_NAME+' hint:缺少分类数据');
  176 + return false;
  177 + }
  178 + o.config.data = data;
  179 + }
  180 +
  181 + //给容器添加一个类名
  182 + $E.addClass('lay-ext-mulitsel');
  183 + if(/^\d+$/.test(c.width)){
  184 + $E.css('width',c.width+'px');
  185 + }
  186 + //添加专属的style
  187 + if($('#lay-ext-mulitsel-style').length==0){
  188 + var style = '.lay-ext-mulitsel .layui-form-select dl dd div{margin-top:0px!important;}.lay-ext-mulitsel .layui-form-select dl dd.layui-this{background-color:#fff}.lay-ext-mulitsel .layui-input.multiple{line-height:auto;height:auto;padding:4px 10px 4px 10px;overflow:hidden;min-height:38px;margin-top:-38px;left:0;z-index:99;position:relative;background:#fff;}.lay-ext-mulitsel .layui-input.multiple a{padding:2px 5px;background:#5FB878;border-radius:2px;color:#fff;display:block;line-height:20px;height:20px;margin:2px 5px 2px 0;float:left;}.lay-ext-mulitsel .layui-input.multiple a i{margin-left:4px;font-size:14px;} .lay-ext-mulitsel .layui-input.multiple a i:hover{background-color:#009E94;border-radius:2px;}.lay-ext-mulitsel .danger{border-color:#FF5722!important}.lay-ext-mulitsel .tips{pointer-events: none;position: absolute;left: 10px;top: 10px;color:#757575;}';
  189 + $('<style id="lay-ext-mulitsel-style"></style>').text(style).appendTo($('head'));
  190 + };
  191 +
  192 + //创建选项
  193 + o.createOption();
  194 + //设置选中值
  195 + o.set();
  196 +
  197 + //展开/收起选项
  198 + $E.on('click','.layui-select-title,.multiple,.multiple.layui-edge',function(e){
  199 + //隐藏其他实例显示的弹层
  200 + $('.lay-ext-mulitsel').not(c.elem).removeClass('layui-form-selected');
  201 + if($(c.elem).is('.layui-form-selected')){
  202 + $(c.elem).removeClass('layui-form-selected');
  203 +
  204 + $(document).off('click',mEvent);
  205 + }
  206 + else{
  207 + $(c.elem).addClass('layui-form-selected');
  208 +
  209 + $(document).on('click',mEvent=function(e){
  210 + if(e.target.id!==c.elem && e.target.className!=='layui-input multiple'){
  211 + $(c.elem).removeClass('layui-form-selected');
  212 + $(document).off('click',mEvent);
  213 + }
  214 + });
  215 + }
  216 + });
  217 +
  218 + //点击选项
  219 + $E.on('click','dd',function(e){
  220 + var _dd = $(this);
  221 + if(_dd.hasClass('layui-disabled')){
  222 + return false;
  223 + }
  224 + //点 请选择
  225 + if(_dd.is('.layui-select-tips')){
  226 + _dd.siblings().removeClass('layui-this');
  227 + $(c.elem).find('.layui-form-checkbox').removeClass('layui-form-checked');
  228 + }
  229 + //取消选中
  230 + else if(_dd.is('.layui-this')){
  231 + _dd.removeClass('layui-this');
  232 + _dd.find('.layui-form-checkbox').removeClass('layui-form-checked');
  233 + e.stopPropagation();
  234 + }
  235 + //选中
  236 + else{
  237 + if(o.selected.length >= c.max){
  238 + $(c.elem+' .multiple').addClass('danger');
  239 + layer.tips('最多只能选择 '+c.max+' 个', c.elem+' .multiple', {
  240 + tips: 3,
  241 + time: 1000,
  242 + end:function(){
  243 + $(c.elem+' .multiple').removeClass('danger');
  244 + }
  245 + });
  246 + return false;
  247 + }
  248 + else{
  249 + _dd.addClass('layui-this');
  250 + _dd.find('.layui-form-checkbox').addClass('layui-form-checked');
  251 + e.stopPropagation();
  252 + }
  253 + }
  254 +
  255 + o.setSelected();
  256 + });
  257 +
  258 + //删除选项
  259 + $E.on('click','a i',function(e){
  260 + var _this = $(this).prev('span');
  261 + var v = _this.attr('lay-value');
  262 + if(v){
  263 + var _dd = $(c.elem).find('dd[lay-value='+v+']');
  264 + _dd.removeClass('layui-this');
  265 + _dd.find('.layui-form-checkbox').removeClass('layui-form-checked');
  266 + }
  267 + o.setSelected();
  268 + _this.parent().remove();
  269 + e.stopPropagation();
  270 +
  271 + });
  272 +
  273 + //验证失败样式
  274 + $E.find('input').focus(function(){
  275 + $(c.elem+' .multiple').addClass('danger');
  276 + setTimeout(function(){
  277 + $(c.elem+' .multiple').removeClass('danger');
  278 + },3000);
  279 + });
  280 + }
  281 +
  282 + //输出模块
  283 + exports(MOD_NAME, function (config) {
  284 + var _this = new obj(config);
  285 + _this.render();
  286 + return _this;
  287 + });
  288 +});
  1 +/*
  2 +* @version: 1.2
  3 +* @Author: tomato
  4 +* @Date: 2018-4-24 22:56:00
  5 +* @Last Modified by: tomato
  6 +* @Last Modified time: 2018-5-26 18:08:43
  7 +*/
  8 +//无限级下拉框
  9 +layui.define(['jquery', 'form'], function(exports){
  10 + var MOD_NAME = 'selectN';
  11 + var $ = layui.jquery;
  12 + var form = layui.form;
  13 + var obj = function(config){
  14 + //当前选中数据值名数据
  15 + this.selected =[];
  16 + //当前选中的值
  17 + this.values = [];
  18 + //当前选中的名
  19 + this.names = [];
  20 + //当前选中最后一个值
  21 + this.lastValue = '';
  22 + //当前选中最后一个值
  23 + this.lastName = '';
  24 + //是否已选
  25 + this.isSelected = false;
  26 + //初始化配置
  27 + this.config = {
  28 + //选择器id或class
  29 + elem: '',
  30 + //无限级分类数据
  31 + data: [],
  32 + //默认选中值
  33 + selected: [],
  34 + //空值项提示,可设置为数组['请选择省','请选择市','请选择县']
  35 + tips: '请选择',
  36 + //是否允许搜索,可设置为数组[true,true,true]
  37 + search:false,
  38 + //选择项宽度,可设置为数组['80','90','100']
  39 + width:null,
  40 + //为真只取最后一个值
  41 + last: false,
  42 + //值验证,与lay-verify一致
  43 + verify: '',
  44 + //事件过滤器,lay-filter名
  45 + filter: '',
  46 + //input的name 不设置与选择器相同(去#.)
  47 + name: '',
  48 + //数据分隔符
  49 + delimiter: ',',
  50 + //数据的键名 status=0为禁用状态
  51 + field:{idName:'id',titleName:'name',statusName:'status',childName:'children'},
  52 + //多表单区分 form.render(type, filter); 为class="layui-form" 所在元素的 lay-filter="" 的值
  53 + formFilter: null
  54 + }
  55 +
  56 + //实例化配置
  57 + this.config = $.extend(this.config,config);
  58 +
  59 + //“请选择”文字
  60 + this.setTips = function(){
  61 + var o = this,c = o.config;
  62 + if(Object.prototype.toString.call(c.tips)!='[object Array]'){
  63 + return c.tips;
  64 + }
  65 + else{
  66 + var i=$(c.elem).find('select').length;
  67 + return c.tips.hasOwnProperty(i) ? c.tips[i] : '请选择';
  68 + }
  69 + }
  70 +
  71 + //设置是否允许搜索
  72 + this.setSearch = function(){
  73 + var o = this,c = o.config;
  74 + if(Object.prototype.toString.call(c.search)!='[object Array]'){
  75 + return c.search===true ? 'lay-search ' : ' ';
  76 + }
  77 + else{
  78 + var i=$(c.elem).find('select').length;
  79 + if(c.search.hasOwnProperty(i)){
  80 + return c.search[i]===true ? 'lay-search ' : ' ';
  81 + }
  82 + }
  83 + return ' ';
  84 + }
  85 +
  86 + //设置是否允许搜索
  87 + this.setWidth = function(){
  88 + var o = this,c = o.config;
  89 + if(Object.prototype.toString.call(c.width)!='[object Array]'){
  90 + return /^\d+$/.test(c.width) ? 'style="width:'+c.width+'px;" ' : ' ';
  91 + }
  92 + else{
  93 + var i=$(c.elem).find('select').length;
  94 + if(c.width.hasOwnProperty(i)){
  95 + return /^\d+$/.test(c.width[i]) ? 'style="width:'+c.width[i]+'px;" ' : ' ';
  96 + }
  97 + }
  98 + }
  99 +
  100 + //创建一个Select
  101 + this.createSelect = function(optionData){
  102 + var o = this,c = o.config,f=c.field;
  103 + var html = '';
  104 + html+= '<div class="layui-input-inline" '+o.setWidth()+'>';
  105 + html+= ' <select '+o.setSearch()+'lay-filter="'+c.filter+'">';
  106 + html+= ' <option value="">'+o.setTips()+'</option>';
  107 + for(var i=0;i<optionData.length;i++){
  108 + var disabled = optionData[i][f.statusName]==0 ? 'disabled="" ' : '';
  109 + html+= ' <option '+disabled+'value="'+optionData[i][f.idName]+'">'+optionData[i][f.titleName]+'</option>';
  110 + }
  111 + html+= ' </select>';
  112 + html+= '</div>';
  113 + return html;
  114 + };
  115 +
  116 + //获取当前option的数据
  117 + this.getOptionData=function(catData,optionIndex){
  118 + var f = this.config.field;
  119 + var item = catData;
  120 + for(var i=0;i<optionIndex.length;i++){
  121 + if('undefined' == typeof item[optionIndex[i]]){
  122 + item = null;
  123 + break;
  124 + }
  125 + else if('undefined' == typeof item[optionIndex[i]][f.childName]){
  126 + item = null;
  127 + break;
  128 + }
  129 + else{
  130 + item = item[optionIndex[i]][f.childName];
  131 + }
  132 + }
  133 + return item;
  134 + };
  135 +
  136 + //初始化
  137 + this.set = function(selected){
  138 + var o = this,c = o.config;
  139 + $E = $(c.elem);
  140 + //创建顶级select
  141 + var verify = c.verify=='' ? '' : 'lay-verify="'+c.verify+'" ';
  142 + var html = '<div style="height:0px;width:0px;overflow:hidden"><input '+verify+'name="'+c.name+'"></div>';
  143 + html += o.createSelect(c.data);
  144 + $E.html(html);
  145 + selected = typeof selected=='undefined' ? c.selected : selected;
  146 + var index=[];
  147 + for(var i=0;i<selected.length;i++){
  148 + //设置最后一个select的选中值
  149 + $E.find('select:last').val(selected[i]);
  150 + //获取该选中值的索引
  151 + var lastIndex = $E.find('select:last').get(0).selectedIndex-1;
  152 + index.push(lastIndex);
  153 + //取出下级的选项值
  154 + var childItem = o.getOptionData(c.data,index);
  155 + //下级选项值存在则创建select
  156 + if(childItem){
  157 + var html = o.createSelect(childItem);
  158 + $E.append(html);
  159 + }
  160 + }
  161 + form.render('select',c.formFilter);
  162 + o.getSelected();
  163 + };
  164 +
  165 + //下拉事件
  166 + this.change = function(elem){
  167 + var o = this,c = o.config;
  168 + var $thisItem = elem.parent();
  169 + //移除后面的select
  170 + $thisItem.nextAll('div.layui-input-inline').remove();
  171 + var index=[];
  172 + //获取所有select,取出选中项的值和索引
  173 + $thisItem.parent().find('select').each(function(){
  174 + index.push($(this).get(0).selectedIndex-1);
  175 + });
  176 +
  177 + var childItem = o.getOptionData(c.data,index);
  178 + if(childItem){
  179 + var html = o.createSelect(childItem);
  180 + $thisItem.after(html);
  181 + form.render('select',c.formFilter);
  182 + }
  183 + o.getSelected();
  184 + };
  185 +
  186 + //获取所有值-数组 每次选择后执行
  187 + this.getSelected=function(){
  188 + var o = this,c = o.config;
  189 + var values =[];
  190 + var names =[];
  191 + var selected =[];
  192 + $E = $(c.elem);
  193 + $E.find('select').each(function(){
  194 + var item = {};
  195 + var v = $(this).val()
  196 + var n = $(this).find('option:selected').text();
  197 + item.value = v;
  198 + item.name = n;
  199 + values.push(v);
  200 + names.push(n);
  201 + selected.push(item);
  202 + });
  203 + o.selected =selected;
  204 + o.values = values;
  205 + o.names = names;
  206 + o.lastValue = $E.find('select:last').val();
  207 + o.lastName = $E.find('option:selected:last').text();
  208 +
  209 + o.isSelected = o.lastValue=='' ? false : true;
  210 + var inputVal = c.last===true ? o.lastValue : o.values.join(c.delimiter);
  211 + $E.find('input[name='+c.name+']').val(inputVal);
  212 + };
  213 + //ajax方式获取候选数据
  214 + this.getData = function(url){
  215 + var d;
  216 + $.ajax({
  217 + url:url,
  218 + dataType:'json',
  219 + async:false,
  220 + success:function(json){
  221 + d=json;
  222 + },
  223 + error: function(){
  224 + console.error(MOD_NAME+' hint:候选数据ajax请求错误 ');
  225 + d = false;
  226 + }
  227 + });
  228 + return d;
  229 + }
  230 +
  231 +
  232 + };
  233 +
  234 + //渲染一个实例
  235 + obj.prototype.render = function(){
  236 + var o=this,c=o.config;
  237 + $E = $(c.elem);
  238 + if($E.length==0){
  239 + console.error(MOD_NAME+' hint:找不到容器 '+c.elem);
  240 + return false;
  241 + }
  242 + if(Object.prototype.toString.call(c.data)!='[object Array]'){
  243 + var data = o.getData(c.data);
  244 + if(data===false){
  245 + console.error(MOD_NAME+' hint:缺少分类数据');
  246 + return false;
  247 + }
  248 + o.config.data = data;
  249 + }
  250 +
  251 + c.filter = c.filter=='' ? c.elem.replace('#','').replace('.','') : c.filter;
  252 + c.name = c.name=='' ? c.elem.replace('#','').replace('.','') : c.name;
  253 + o.config = c;
  254 +
  255 + //初始化
  256 + o.set();
  257 +
  258 + //监听下拉事件
  259 + form.on('select('+c.filter+')',function(data){
  260 + o.change($(data.elem));
  261 + });
  262 + //验证失败样式
  263 + $E.find('input[name='+c.name+']').focus(function(){
  264 + var t = $(c.elem).offset().top;
  265 + $('html,body').scrollTop(t-200);
  266 + $(c.elem).find('select:last').addClass('layui-form-danger');
  267 + setTimeout(function(){
  268 + $(c.elem).find('select:last').removeClass('layui-form-danger');
  269 + },3000);
  270 + });
  271 + }
  272 +
  273 + //输出模块
  274 + exports(MOD_NAME, function (config) {
  275 + var _this = new obj(config);
  276 + _this.render();
  277 + return _this;
  278 + });
  279 +});
  1 +<?php
  2 +
  3 +/** PHPExcel root directory */
  4 +if (!defined('PHPEXCEL_ROOT')) {
  5 + define('PHPEXCEL_ROOT', dirname(__FILE__) . '/');
  6 + require(PHPEXCEL_ROOT . 'PHPExcel/Autoloader.php');
  7 +}
  8 +
  9 +/**
  10 + * PHPExcel
  11 + *
  12 + * Copyright (c) 2006 - 2015 PHPExcel
  13 + *
  14 + * This library is free software; you can redistribute it and/or
  15 + * modify it under the terms of the GNU Lesser General Public
  16 + * License as published by the Free Software Foundation; either
  17 + * version 2.1 of the License, or (at your option) any later version.
  18 + *
  19 + * This library is distributed in the hope that it will be useful,
  20 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  21 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  22 + * Lesser General Public License for more details.
  23 + *
  24 + * You should have received a copy of the GNU Lesser General Public
  25 + * License along with this library; if not, write to the Free Software
  26 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  27 + *
  28 + * @category PHPExcel
  29 + * @package PHPExcel
  30 + * @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel)
  31 + * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
  32 + * @version ##VERSION##, ##DATE##
  33 + */
  34 +class PHPExcel
  35 +{
  36 + /**
  37 + * Unique ID
  38 + *
  39 + * @var string
  40 + */
  41 + private $uniqueID;
  42 +
  43 + /**
  44 + * Document properties
  45 + *
  46 + * @var PHPExcel_DocumentProperties
  47 + */
  48 + private $properties;
  49 +
  50 + /**
  51 + * Document security
  52 + *
  53 + * @var PHPExcel_DocumentSecurity
  54 + */
  55 + private $security;
  56 +
  57 + /**
  58 + * Collection of Worksheet objects
  59 + *
  60 + * @var PHPExcel_Worksheet[]
  61 + */
  62 + private $workSheetCollection = array();
  63 +
  64 + /**
  65 + * Calculation Engine
  66 + *
  67 + * @var PHPExcel_Calculation
  68 + */
  69 + private $calculationEngine;
  70 +
  71 + /**
  72 + * Active sheet index
  73 + *
  74 + * @var integer
  75 + */
  76 + private $activeSheetIndex = 0;
  77 +
  78 + /**
  79 + * Named ranges
  80 + *
  81 + * @var PHPExcel_NamedRange[]
  82 + */
  83 + private $namedRanges = array();
  84 +
  85 + /**
  86 + * CellXf supervisor
  87 + *
  88 + * @var PHPExcel_Style
  89 + */
  90 + private $cellXfSupervisor;
  91 +
  92 + /**
  93 + * CellXf collection
  94 + *
  95 + * @var PHPExcel_Style[]
  96 + */
  97 + private $cellXfCollection = array();
  98 +
  99 + /**
  100 + * CellStyleXf collection
  101 + *
  102 + * @var PHPExcel_Style[]
  103 + */
  104 + private $cellStyleXfCollection = array();
  105 +
  106 + /**
  107 + * hasMacros : this workbook have macros ?
  108 + *
  109 + * @var bool
  110 + */
  111 + private $hasMacros = false;
  112 +
  113 + /**
  114 + * macrosCode : all macros code (the vbaProject.bin file, this include form, code, etc.), null if no macro
  115 + *
  116 + * @var binary
  117 + */
  118 + private $macrosCode;
  119 + /**
  120 + * macrosCertificate : if macros are signed, contains vbaProjectSignature.bin file, null if not signed
  121 + *
  122 + * @var binary
  123 + */
  124 + private $macrosCertificate;
  125 +
  126 + /**
  127 + * ribbonXMLData : null if workbook is'nt Excel 2007 or not contain a customized UI
  128 + *
  129 + * @var null|string
  130 + */
  131 + private $ribbonXMLData;
  132 +
  133 + /**
  134 + * ribbonBinObjects : null if workbook is'nt Excel 2007 or not contain embedded objects (picture(s)) for Ribbon Elements
  135 + * ignored if $ribbonXMLData is null
  136 + *
  137 + * @var null|array
  138 + */
  139 + private $ribbonBinObjects;
  140 +
  141 + /**
  142 + * The workbook has macros ?
  143 + *
  144 + * @return boolean true if workbook has macros, false if not
  145 + */
  146 + public function hasMacros()
  147 + {
  148 + return $this->hasMacros;
  149 + }
  150 +
  151 + /**
  152 + * Define if a workbook has macros
  153 + *
  154 + * @param boolean $hasMacros true|false
  155 + */
  156 + public function setHasMacros($hasMacros = false)
  157 + {
  158 + $this->hasMacros = (bool) $hasMacros;
  159 + }
  160 +
  161 + /**
  162 + * Set the macros code
  163 + *
  164 + * @param string $MacrosCode string|null
  165 + */
  166 + public function setMacrosCode($MacrosCode = null)
  167 + {
  168 + $this->macrosCode=$MacrosCode;
  169 + $this->setHasMacros(!is_null($MacrosCode));
  170 + }
  171 +
  172 + /**
  173 + * Return the macros code
  174 + *
  175 + * @return string|null
  176 + */
  177 + public function getMacrosCode()
  178 + {
  179 + return $this->macrosCode;
  180 + }
  181 +
  182 + /**
  183 + * Set the macros certificate
  184 + *
  185 + * @param string|null $Certificate
  186 + */
  187 + public function setMacrosCertificate($Certificate = null)
  188 + {
  189 + $this->macrosCertificate=$Certificate;
  190 + }
  191 +
  192 + /**
  193 + * Is the project signed ?
  194 + *
  195 + * @return boolean true|false
  196 + */
  197 + public function hasMacrosCertificate()
  198 + {
  199 + return !is_null($this->macrosCertificate);
  200 + }
  201 +
  202 + /**
  203 + * Return the macros certificate
  204 + *
  205 + * @return string|null
  206 + */
  207 + public function getMacrosCertificate()
  208 + {
  209 + return $this->macrosCertificate;
  210 + }
  211 +
  212 + /**
  213 + * Remove all macros, certificate from spreadsheet
  214 + *
  215 + */
  216 + public function discardMacros()
  217 + {
  218 + $this->hasMacros=false;
  219 + $this->macrosCode=null;
  220 + $this->macrosCertificate=null;
  221 + }
  222 +
  223 + /**
  224 + * set ribbon XML data
  225 + *
  226 + */
  227 + public function setRibbonXMLData($Target = null, $XMLData = null)
  228 + {
  229 + if (!is_null($Target) && !is_null($XMLData)) {
  230 + $this->ribbonXMLData = array('target' => $Target, 'data' => $XMLData);
  231 + } else {
  232 + $this->ribbonXMLData = null;
  233 + }
  234 + }
  235 +
  236 + /**
  237 + * retrieve ribbon XML Data
  238 + *
  239 + * return string|null|array
  240 + */
  241 + public function getRibbonXMLData($What = 'all') //we need some constants here...
  242 + {
  243 + $ReturnData = null;
  244 + $What = strtolower($What);
  245 + switch ($What){
  246 + case 'all':
  247 + $ReturnData = $this->ribbonXMLData;
  248 + break;
  249 + case 'target':
  250 + case 'data':
  251 + if (is_array($this->ribbonXMLData) && array_key_exists($What, $this->ribbonXMLData)) {
  252 + $ReturnData = $this->ribbonXMLData[$What];
  253 + }
  254 + break;
  255 + }
  256 +
  257 + return $ReturnData;
  258 + }
  259 +
  260 + /**
  261 + * store binaries ribbon objects (pictures)
  262 + *
  263 + */
  264 + public function setRibbonBinObjects($BinObjectsNames = null, $BinObjectsData = null)
  265 + {
  266 + if (!is_null($BinObjectsNames) && !is_null($BinObjectsData)) {
  267 + $this->ribbonBinObjects = array('names' => $BinObjectsNames, 'data' => $BinObjectsData);
  268 + } else {
  269 + $this->ribbonBinObjects = null;
  270 + }
  271 + }
  272 + /**
  273 + * return the extension of a filename. Internal use for a array_map callback (php<5.3 don't like lambda function)
  274 + *
  275 + */
  276 + private function getExtensionOnly($ThePath)
  277 + {
  278 + return pathinfo($ThePath, PATHINFO_EXTENSION);
  279 + }
  280 +
  281 + /**
  282 + * retrieve Binaries Ribbon Objects
  283 + *
  284 + */
  285 + public function getRibbonBinObjects($What = 'all')
  286 + {
  287 + $ReturnData = null;
  288 + $What = strtolower($What);
  289 + switch($What) {
  290 + case 'all':
  291 + return $this->ribbonBinObjects;
  292 + break;
  293 + case 'names':
  294 + case 'data':
  295 + if (is_array($this->ribbonBinObjects) && array_key_exists($What, $this->ribbonBinObjects)) {
  296 + $ReturnData=$this->ribbonBinObjects[$What];
  297 + }
  298 + break;
  299 + case 'types':
  300 + if (is_array($this->ribbonBinObjects) &&
  301 + array_key_exists('data', $this->ribbonBinObjects) && is_array($this->ribbonBinObjects['data'])) {
  302 + $tmpTypes=array_keys($this->ribbonBinObjects['data']);
  303 + $ReturnData = array_unique(array_map(array($this, 'getExtensionOnly'), $tmpTypes));
  304 + } else {
  305 + $ReturnData=array(); // the caller want an array... not null if empty
  306 + }
  307 + break;
  308 + }
  309 + return $ReturnData;
  310 + }
  311 +
  312 + /**
  313 + * This workbook have a custom UI ?
  314 + *
  315 + * @return boolean true|false
  316 + */
  317 + public function hasRibbon()
  318 + {
  319 + return !is_null($this->ribbonXMLData);
  320 + }
  321 +
  322 + /**
  323 + * This workbook have additionnal object for the ribbon ?
  324 + *
  325 + * @return boolean true|false
  326 + */
  327 + public function hasRibbonBinObjects()
  328 + {
  329 + return !is_null($this->ribbonBinObjects);
  330 + }
  331 +
  332 + /**
  333 + * Check if a sheet with a specified code name already exists
  334 + *
  335 + * @param string $pSheetCodeName Name of the worksheet to check
  336 + * @return boolean
  337 + */
  338 + public function sheetCodeNameExists($pSheetCodeName)
  339 + {
  340 + return ($this->getSheetByCodeName($pSheetCodeName) !== null);
  341 + }
  342 +
  343 + /**
  344 + * Get sheet by code name. Warning : sheet don't have always a code name !
  345 + *
  346 + * @param string $pName Sheet name
  347 + * @return PHPExcel_Worksheet
  348 + */
  349 + public function getSheetByCodeName($pName = '')
  350 + {
  351 + $worksheetCount = count($this->workSheetCollection);
  352 + for ($i = 0; $i < $worksheetCount; ++$i) {
  353 + if ($this->workSheetCollection[$i]->getCodeName() == $pName) {
  354 + return $this->workSheetCollection[$i];
  355 + }
  356 + }
  357 +
  358 + return null;
  359 + }
  360 +
  361 + /**
  362 + * Create a new PHPExcel with one Worksheet
  363 + */
  364 + public function __construct()
  365 + {
  366 + $this->uniqueID = uniqid();
  367 + $this->calculationEngine = new PHPExcel_Calculation($this);
  368 +
  369 + // Initialise worksheet collection and add one worksheet
  370 + $this->workSheetCollection = array();
  371 + $this->workSheetCollection[] = new PHPExcel_Worksheet($this);
  372 + $this->activeSheetIndex = 0;
  373 +
  374 + // Create document properties
  375 + $this->properties = new PHPExcel_DocumentProperties();
  376 +
  377 + // Create document security
  378 + $this->security = new PHPExcel_DocumentSecurity();
  379 +
  380 + // Set named ranges
  381 + $this->namedRanges = array();
  382 +
  383 + // Create the cellXf supervisor
  384 + $this->cellXfSupervisor = new PHPExcel_Style(true);
  385 + $this->cellXfSupervisor->bindParent($this);
  386 +
  387 + // Create the default style
  388 + $this->addCellXf(new PHPExcel_Style);
  389 + $this->addCellStyleXf(new PHPExcel_Style);
  390 + }
  391 +
  392 + /**
  393 + * Code to execute when this worksheet is unset()
  394 + *
  395 + */
  396 + public function __destruct()
  397 + {
  398 + $this->calculationEngine = null;
  399 + $this->disconnectWorksheets();
  400 + }
  401 +
  402 + /**
  403 + * Disconnect all worksheets from this PHPExcel workbook object,
  404 + * typically so that the PHPExcel object can be unset
  405 + *
  406 + */
  407 + public function disconnectWorksheets()
  408 + {
  409 + $worksheet = null;
  410 + foreach ($this->workSheetCollection as $k => &$worksheet) {
  411 + $worksheet->disconnectCells();
  412 + $this->workSheetCollection[$k] = null;
  413 + }
  414 + unset($worksheet);
  415 + $this->workSheetCollection = array();
  416 + }
  417 +
  418 + /**
  419 + * Return the calculation engine for this worksheet
  420 + *
  421 + * @return PHPExcel_Calculation
  422 + */
  423 + public function getCalculationEngine()
  424 + {
  425 + return $this->calculationEngine;
  426 + } // function getCellCacheController()
  427 +
  428 + /**
  429 + * Get properties
  430 + *
  431 + * @return PHPExcel_DocumentProperties
  432 + */
  433 + public function getProperties()
  434 + {
  435 + return $this->properties;
  436 + }
  437 +
  438 + /**
  439 + * Set properties
  440 + *
  441 + * @param PHPExcel_DocumentProperties $pValue
  442 + */
  443 + public function setProperties(PHPExcel_DocumentProperties $pValue)
  444 + {
  445 + $this->properties = $pValue;
  446 + }
  447 +
  448 + /**
  449 + * Get security
  450 + *
  451 + * @return PHPExcel_DocumentSecurity
  452 + */
  453 + public function getSecurity()
  454 + {
  455 + return $this->security;
  456 + }
  457 +
  458 + /**
  459 + * Set security
  460 + *
  461 + * @param PHPExcel_DocumentSecurity $pValue
  462 + */
  463 + public function setSecurity(PHPExcel_DocumentSecurity $pValue)
  464 + {
  465 + $this->security = $pValue;
  466 + }
  467 +
  468 + /**
  469 + * Get active sheet
  470 + *
  471 + * @return PHPExcel_Worksheet
  472 + *
  473 + * @throws PHPExcel_Exception
  474 + */
  475 + public function getActiveSheet()
  476 + {
  477 + return $this->getSheet($this->activeSheetIndex);
  478 + }
  479 +
  480 + /**
  481 + * Create sheet and add it to this workbook
  482 + *
  483 + * @param int|null $iSheetIndex Index where sheet should go (0,1,..., or null for last)
  484 + * @return PHPExcel_Worksheet
  485 + * @throws PHPExcel_Exception
  486 + */
  487 + public function createSheet($iSheetIndex = null)
  488 + {
  489 + $newSheet = new PHPExcel_Worksheet($this);
  490 + $this->addSheet($newSheet, $iSheetIndex);
  491 + return $newSheet;
  492 + }
  493 +
  494 + /**
  495 + * Check if a sheet with a specified name already exists
  496 + *
  497 + * @param string $pSheetName Name of the worksheet to check
  498 + * @return boolean
  499 + */
  500 + public function sheetNameExists($pSheetName)
  501 + {
  502 + return ($this->getSheetByName($pSheetName) !== null);
  503 + }
  504 +
  505 + /**
  506 + * Add sheet
  507 + *
  508 + * @param PHPExcel_Worksheet $pSheet
  509 + * @param int|null $iSheetIndex Index where sheet should go (0,1,..., or null for last)
  510 + * @return PHPExcel_Worksheet
  511 + * @throws PHPExcel_Exception
  512 + */
  513 + public function addSheet(PHPExcel_Worksheet $pSheet, $iSheetIndex = null)
  514 + {
  515 + if ($this->sheetNameExists($pSheet->getTitle())) {
  516 + throw new PHPExcel_Exception(
  517 + "Workbook already contains a worksheet named '{$pSheet->getTitle()}'. Rename this worksheet first."
  518 + );
  519 + }
  520 +
  521 + if ($iSheetIndex === null) {
  522 + if ($this->activeSheetIndex < 0) {
  523 + $this->activeSheetIndex = 0;
  524 + }
  525 + $this->workSheetCollection[] = $pSheet;
  526 + } else {
  527 + // Insert the sheet at the requested index
  528 + array_splice(
  529 + $this->workSheetCollection,
  530 + $iSheetIndex,
  531 + 0,
  532 + array($pSheet)
  533 + );
  534 +
  535 + // Adjust active sheet index if necessary
  536 + if ($this->activeSheetIndex >= $iSheetIndex) {
  537 + ++$this->activeSheetIndex;
  538 + }
  539 + }
  540 +
  541 + if ($pSheet->getParent() === null) {
  542 + $pSheet->rebindParent($this);
  543 + }
  544 +
  545 + return $pSheet;
  546 + }
  547 +
  548 + /**
  549 + * Remove sheet by index
  550 + *
  551 + * @param int $pIndex Active sheet index
  552 + * @throws PHPExcel_Exception
  553 + */
  554 + public function removeSheetByIndex($pIndex = 0)
  555 + {
  556 +
  557 + $numSheets = count($this->workSheetCollection);
  558 + if ($pIndex > $numSheets - 1) {
  559 + throw new PHPExcel_Exception(
  560 + "You tried to remove a sheet by the out of bounds index: {$pIndex}. The actual number of sheets is {$numSheets}."
  561 + );
  562 + } else {
  563 + array_splice($this->workSheetCollection, $pIndex, 1);
  564 + }
  565 + // Adjust active sheet index if necessary
  566 + if (($this->activeSheetIndex >= $pIndex) &&
  567 + ($pIndex > count($this->workSheetCollection) - 1)) {
  568 + --$this->activeSheetIndex;
  569 + }
  570 +
  571 + }
  572 +
  573 + /**
  574 + * Get sheet by index
  575 + *
  576 + * @param int $pIndex Sheet index
  577 + * @return PHPExcel_Worksheet
  578 + * @throws PHPExcel_Exception
  579 + */
  580 + public function getSheet($pIndex = 0)
  581 + {
  582 + if (!isset($this->workSheetCollection[$pIndex])) {
  583 + $numSheets = $this->getSheetCount();
  584 + throw new PHPExcel_Exception(
  585 + "Your requested sheet index: {$pIndex} is out of bounds. The actual number of sheets is {$numSheets}."
  586 + );
  587 + }
  588 +
  589 + return $this->workSheetCollection[$pIndex];
  590 + }
  591 +
  592 + /**
  593 + * Get all sheets
  594 + *
  595 + * @return PHPExcel_Worksheet[]
  596 + */
  597 + public function getAllSheets()
  598 + {
  599 + return $this->workSheetCollection;
  600 + }
  601 +
  602 + /**
  603 + * Get sheet by name
  604 + *
  605 + * @param string $pName Sheet name
  606 + * @return PHPExcel_Worksheet
  607 + */
  608 + public function getSheetByName($pName = '')
  609 + {
  610 + $worksheetCount = count($this->workSheetCollection);
  611 + for ($i = 0; $i < $worksheetCount; ++$i) {
  612 + if ($this->workSheetCollection[$i]->getTitle() === $pName) {
  613 + return $this->workSheetCollection[$i];
  614 + }
  615 + }
  616 +
  617 + return null;
  618 + }
  619 +
  620 + /**
  621 + * Get index for sheet
  622 + *
  623 + * @param PHPExcel_Worksheet $pSheet
  624 + * @return int Sheet index
  625 + * @throws PHPExcel_Exception
  626 + */
  627 + public function getIndex(PHPExcel_Worksheet $pSheet)
  628 + {
  629 + foreach ($this->workSheetCollection as $key => $value) {
  630 + if ($value->getHashCode() == $pSheet->getHashCode()) {
  631 + return $key;
  632 + }
  633 + }
  634 +
  635 + throw new PHPExcel_Exception("Sheet does not exist.");
  636 + }
  637 +
  638 + /**
  639 + * Set index for sheet by sheet name.
  640 + *
  641 + * @param string $sheetName Sheet name to modify index for
  642 + * @param int $newIndex New index for the sheet
  643 + * @return int New sheet index
  644 + * @throws PHPExcel_Exception
  645 + */
  646 + public function setIndexByName($sheetName, $newIndex)
  647 + {
  648 + $oldIndex = $this->getIndex($this->getSheetByName($sheetName));
  649 + $pSheet = array_splice(
  650 + $this->workSheetCollection,
  651 + $oldIndex,
  652 + 1
  653 + );
  654 + array_splice(
  655 + $this->workSheetCollection,
  656 + $newIndex,
  657 + 0,
  658 + $pSheet
  659 + );
  660 + return $newIndex;
  661 + }
  662 +
  663 + /**
  664 + * Get sheet count
  665 + *
  666 + * @return int
  667 + */
  668 + public function getSheetCount()
  669 + {
  670 + return count($this->workSheetCollection);
  671 + }
  672 +
  673 + /**
  674 + * Get active sheet index
  675 + *
  676 + * @return int Active sheet index
  677 + */
  678 + public function getActiveSheetIndex()
  679 + {
  680 + return $this->activeSheetIndex;
  681 + }
  682 +
  683 + /**
  684 + * Set active sheet index
  685 + *
  686 + * @param int $pIndex Active sheet index
  687 + * @throws PHPExcel_Exception
  688 + * @return PHPExcel_Worksheet
  689 + */
  690 + public function setActiveSheetIndex($pIndex = 0)
  691 + {
  692 + $numSheets = count($this->workSheetCollection);
  693 +
  694 + if ($pIndex > $numSheets - 1) {
  695 + throw new PHPExcel_Exception(
  696 + "You tried to set a sheet active by the out of bounds index: {$pIndex}. The actual number of sheets is {$numSheets}."
  697 + );
  698 + } else {
  699 + $this->activeSheetIndex = $pIndex;
  700 + }
  701 + return $this->getActiveSheet();
  702 + }
  703 +
  704 + /**
  705 + * Set active sheet index by name
  706 + *
  707 + * @param string $pValue Sheet title
  708 + * @return PHPExcel_Worksheet
  709 + * @throws PHPExcel_Exception
  710 + */
  711 + public function setActiveSheetIndexByName($pValue = '')
  712 + {
  713 + if (($worksheet = $this->getSheetByName($pValue)) instanceof PHPExcel_Worksheet) {
  714 + $this->setActiveSheetIndex($this->getIndex($worksheet));
  715 + return $worksheet;
  716 + }
  717 +
  718 + throw new PHPExcel_Exception('Workbook does not contain sheet:' . $pValue);
  719 + }
  720 +
  721 + /**
  722 + * Get sheet names
  723 + *
  724 + * @return string[]
  725 + */
  726 + public function getSheetNames()
  727 + {
  728 + $returnValue = array();
  729 + $worksheetCount = $this->getSheetCount();
  730 + for ($i = 0; $i < $worksheetCount; ++$i) {
  731 + $returnValue[] = $this->getSheet($i)->getTitle();
  732 + }
  733 +
  734 + return $returnValue;
  735 + }
  736 +
  737 + /**
  738 + * Add external sheet
  739 + *
  740 + * @param PHPExcel_Worksheet $pSheet External sheet to add
  741 + * @param int|null $iSheetIndex Index where sheet should go (0,1,..., or null for last)
  742 + * @throws PHPExcel_Exception
  743 + * @return PHPExcel_Worksheet
  744 + */
  745 + public function addExternalSheet(PHPExcel_Worksheet $pSheet, $iSheetIndex = null)
  746 + {
  747 + if ($this->sheetNameExists($pSheet->getTitle())) {
  748 + throw new PHPExcel_Exception("Workbook already contains a worksheet named '{$pSheet->getTitle()}'. Rename the external sheet first.");
  749 + }
  750 +
  751 + // count how many cellXfs there are in this workbook currently, we will need this below
  752 + $countCellXfs = count($this->cellXfCollection);
  753 +
  754 + // copy all the shared cellXfs from the external workbook and append them to the current
  755 + foreach ($pSheet->getParent()->getCellXfCollection() as $cellXf) {
  756 + $this->addCellXf(clone $cellXf);
  757 + }
  758 +
  759 + // move sheet to this workbook
  760 + $pSheet->rebindParent($this);
  761 +
  762 + // update the cellXfs
  763 + foreach ($pSheet->getCellCollection(false) as $cellID) {
  764 + $cell = $pSheet->getCell($cellID);
  765 + $cell->setXfIndex($cell->getXfIndex() + $countCellXfs);
  766 + }
  767 +
  768 + return $this->addSheet($pSheet, $iSheetIndex);
  769 + }
  770 +
  771 + /**
  772 + * Get named ranges
  773 + *
  774 + * @return PHPExcel_NamedRange[]
  775 + */
  776 + public function getNamedRanges()
  777 + {
  778 + return $this->namedRanges;
  779 + }
  780 +
  781 + /**
  782 + * Add named range
  783 + *
  784 + * @param PHPExcel_NamedRange $namedRange
  785 + * @return boolean
  786 + */
  787 + public function addNamedRange(PHPExcel_NamedRange $namedRange)
  788 + {
  789 + if ($namedRange->getScope() == null) {
  790 + // global scope
  791 + $this->namedRanges[$namedRange->getName()] = $namedRange;
  792 + } else {
  793 + // local scope
  794 + $this->namedRanges[$namedRange->getScope()->getTitle().'!'.$namedRange->getName()] = $namedRange;
  795 + }
  796 + return true;
  797 + }
  798 +
  799 + /**
  800 + * Get named range
  801 + *
  802 + * @param string $namedRange
  803 + * @param PHPExcel_Worksheet|null $pSheet Scope. Use null for global scope
  804 + * @return PHPExcel_NamedRange|null
  805 + */
  806 + public function getNamedRange($namedRange, PHPExcel_Worksheet $pSheet = null)
  807 + {
  808 + $returnValue = null;
  809 +
  810 + if ($namedRange != '' && ($namedRange !== null)) {
  811 + // first look for global defined name
  812 + if (isset($this->namedRanges[$namedRange])) {
  813 + $returnValue = $this->namedRanges[$namedRange];
  814 + }
  815 +
  816 + // then look for local defined name (has priority over global defined name if both names exist)
  817 + if (($pSheet !== null) && isset($this->namedRanges[$pSheet->getTitle() . '!' . $namedRange])) {
  818 + $returnValue = $this->namedRanges[$pSheet->getTitle() . '!' . $namedRange];
  819 + }
  820 + }
  821 +
  822 + return $returnValue;
  823 + }
  824 +
  825 + /**
  826 + * Remove named range
  827 + *
  828 + * @param string $namedRange
  829 + * @param PHPExcel_Worksheet|null $pSheet Scope: use null for global scope.
  830 + * @return PHPExcel
  831 + */
  832 + public function removeNamedRange($namedRange, PHPExcel_Worksheet $pSheet = null)
  833 + {
  834 + if ($pSheet === null) {
  835 + if (isset($this->namedRanges[$namedRange])) {
  836 + unset($this->namedRanges[$namedRange]);
  837 + }
  838 + } else {
  839 + if (isset($this->namedRanges[$pSheet->getTitle() . '!' . $namedRange])) {
  840 + unset($this->namedRanges[$pSheet->getTitle() . '!' . $namedRange]);
  841 + }
  842 + }
  843 + return $this;
  844 + }
  845 +
  846 + /**
  847 + * Get worksheet iterator
  848 + *
  849 + * @return PHPExcel_WorksheetIterator
  850 + */
  851 + public function getWorksheetIterator()
  852 + {
  853 + return new PHPExcel_WorksheetIterator($this);
  854 + }
  855 +
  856 + /**
  857 + * Copy workbook (!= clone!)
  858 + *
  859 + * @return PHPExcel
  860 + */
  861 + public function copy()
  862 + {
  863 + $copied = clone $this;
  864 +
  865 + $worksheetCount = count($this->workSheetCollection);
  866 + for ($i = 0; $i < $worksheetCount; ++$i) {
  867 + $this->workSheetCollection[$i] = $this->workSheetCollection[$i]->copy();
  868 + $this->workSheetCollection[$i]->rebindParent($this);
  869 + }
  870 +
  871 + return $copied;
  872 + }
  873 +
  874 + /**
  875 + * Implement PHP __clone to create a deep clone, not just a shallow copy.
  876 + */
  877 + public function __clone()
  878 + {
  879 + foreach ($this as $key => $val) {
  880 + if (is_object($val) || (is_array($val))) {
  881 + $this->{$key} = unserialize(serialize($val));
  882 + }
  883 + }
  884 + }
  885 +
  886 + /**
  887 + * Get the workbook collection of cellXfs
  888 + *
  889 + * @return PHPExcel_Style[]
  890 + */
  891 + public function getCellXfCollection()
  892 + {
  893 + return $this->cellXfCollection;
  894 + }
  895 +
  896 + /**
  897 + * Get cellXf by index
  898 + *
  899 + * @param int $pIndex
  900 + * @return PHPExcel_Style
  901 + */
  902 + public function getCellXfByIndex($pIndex = 0)
  903 + {
  904 + return $this->cellXfCollection[$pIndex];
  905 + }
  906 +
  907 + /**
  908 + * Get cellXf by hash code
  909 + *
  910 + * @param string $pValue
  911 + * @return PHPExcel_Style|boolean False if no match found
  912 + */
  913 + public function getCellXfByHashCode($pValue = '')
  914 + {
  915 + foreach ($this->cellXfCollection as $cellXf) {
  916 + if ($cellXf->getHashCode() == $pValue) {
  917 + return $cellXf;
  918 + }
  919 + }
  920 + return false;
  921 + }
  922 +
  923 + /**
  924 + * Check if style exists in style collection
  925 + *
  926 + * @param PHPExcel_Style $pCellStyle
  927 + * @return boolean
  928 + */
  929 + public function cellXfExists($pCellStyle = null)
  930 + {
  931 + return in_array($pCellStyle, $this->cellXfCollection, true);
  932 + }
  933 +
  934 + /**
  935 + * Get default style
  936 + *
  937 + * @return PHPExcel_Style
  938 + * @throws PHPExcel_Exception
  939 + */
  940 + public function getDefaultStyle()
  941 + {
  942 + if (isset($this->cellXfCollection[0])) {
  943 + return $this->cellXfCollection[0];
  944 + }
  945 + throw new PHPExcel_Exception('No default style found for this workbook');
  946 + }
  947 +
  948 + /**
  949 + * Add a cellXf to the workbook
  950 + *
  951 + * @param PHPExcel_Style $style
  952 + */
  953 + public function addCellXf(PHPExcel_Style $style)
  954 + {
  955 + $this->cellXfCollection[] = $style;
  956 + $style->setIndex(count($this->cellXfCollection) - 1);
  957 + }
  958 +
  959 + /**
  960 + * Remove cellXf by index. It is ensured that all cells get their xf index updated.
  961 + *
  962 + * @param integer $pIndex Index to cellXf
  963 + * @throws PHPExcel_Exception
  964 + */
  965 + public function removeCellXfByIndex($pIndex = 0)
  966 + {
  967 + if ($pIndex > count($this->cellXfCollection) - 1) {
  968 + throw new PHPExcel_Exception("CellXf index is out of bounds.");
  969 + } else {
  970 + // first remove the cellXf
  971 + array_splice($this->cellXfCollection, $pIndex, 1);
  972 +
  973 + // then update cellXf indexes for cells
  974 + foreach ($this->workSheetCollection as $worksheet) {
  975 + foreach ($worksheet->getCellCollection(false) as $cellID) {
  976 + $cell = $worksheet->getCell($cellID);
  977 + $xfIndex = $cell->getXfIndex();
  978 + if ($xfIndex > $pIndex) {
  979 + // decrease xf index by 1
  980 + $cell->setXfIndex($xfIndex - 1);
  981 + } elseif ($xfIndex == $pIndex) {
  982 + // set to default xf index 0
  983 + $cell->setXfIndex(0);
  984 + }
  985 + }
  986 + }
  987 + }
  988 + }
  989 +
  990 + /**
  991 + * Get the cellXf supervisor
  992 + *
  993 + * @return PHPExcel_Style
  994 + */
  995 + public function getCellXfSupervisor()
  996 + {
  997 + return $this->cellXfSupervisor;
  998 + }
  999 +
  1000 + /**
  1001 + * Get the workbook collection of cellStyleXfs
  1002 + *
  1003 + * @return PHPExcel_Style[]
  1004 + */
  1005 + public function getCellStyleXfCollection()
  1006 + {
  1007 + return $this->cellStyleXfCollection;
  1008 + }
  1009 +
  1010 + /**
  1011 + * Get cellStyleXf by index
  1012 + *
  1013 + * @param integer $pIndex Index to cellXf
  1014 + * @return PHPExcel_Style
  1015 + */
  1016 + public function getCellStyleXfByIndex($pIndex = 0)
  1017 + {
  1018 + return $this->cellStyleXfCollection[$pIndex];
  1019 + }
  1020 +
  1021 + /**
  1022 + * Get cellStyleXf by hash code
  1023 + *
  1024 + * @param string $pValue
  1025 + * @return PHPExcel_Style|boolean False if no match found
  1026 + */
  1027 + public function getCellStyleXfByHashCode($pValue = '')
  1028 + {
  1029 + foreach ($this->cellStyleXfCollection as $cellStyleXf) {
  1030 + if ($cellStyleXf->getHashCode() == $pValue) {
  1031 + return $cellStyleXf;
  1032 + }
  1033 + }
  1034 + return false;
  1035 + }
  1036 +
  1037 + /**
  1038 + * Add a cellStyleXf to the workbook
  1039 + *
  1040 + * @param PHPExcel_Style $pStyle
  1041 + */
  1042 + public function addCellStyleXf(PHPExcel_Style $pStyle)
  1043 + {
  1044 + $this->cellStyleXfCollection[] = $pStyle;
  1045 + $pStyle->setIndex(count($this->cellStyleXfCollection) - 1);
  1046 + }
  1047 +
  1048 + /**
  1049 + * Remove cellStyleXf by index
  1050 + *
  1051 + * @param integer $pIndex Index to cellXf
  1052 + * @throws PHPExcel_Exception
  1053 + */
  1054 + public function removeCellStyleXfByIndex($pIndex = 0)
  1055 + {
  1056 + if ($pIndex > count($this->cellStyleXfCollection) - 1) {
  1057 + throw new PHPExcel_Exception("CellStyleXf index is out of bounds.");
  1058 + } else {
  1059 + array_splice($this->cellStyleXfCollection, $pIndex, 1);
  1060 + }
  1061 + }
  1062 +
  1063 + /**
  1064 + * Eliminate all unneeded cellXf and afterwards update the xfIndex for all cells
  1065 + * and columns in the workbook
  1066 + */
  1067 + public function garbageCollect()
  1068 + {
  1069 + // how many references are there to each cellXf ?
  1070 + $countReferencesCellXf = array();
  1071 + foreach ($this->cellXfCollection as $index => $cellXf) {
  1072 + $countReferencesCellXf[$index] = 0;
  1073 + }
  1074 +
  1075 + foreach ($this->getWorksheetIterator() as $sheet) {
  1076 + // from cells
  1077 + foreach ($sheet->getCellCollection(false) as $cellID) {
  1078 + $cell = $sheet->getCell($cellID);
  1079 + ++$countReferencesCellXf[$cell->getXfIndex()];
  1080 + }
  1081 +
  1082 + // from row dimensions
  1083 + foreach ($sheet->getRowDimensions() as $rowDimension) {
  1084 + if ($rowDimension->getXfIndex() !== null) {
  1085 + ++$countReferencesCellXf[$rowDimension->getXfIndex()];
  1086 + }
  1087 + }
  1088 +
  1089 + // from column dimensions
  1090 + foreach ($sheet->getColumnDimensions() as $columnDimension) {
  1091 + ++$countReferencesCellXf[$columnDimension->getXfIndex()];
  1092 + }
  1093 + }
  1094 +
  1095 + // remove cellXfs without references and create mapping so we can update xfIndex
  1096 + // for all cells and columns
  1097 + $countNeededCellXfs = 0;
  1098 + $map = array();
  1099 + foreach ($this->cellXfCollection as $index => $cellXf) {
  1100 + if ($countReferencesCellXf[$index] > 0 || $index == 0) { // we must never remove the first cellXf
  1101 + ++$countNeededCellXfs;
  1102 + } else {
  1103 + unset($this->cellXfCollection[$index]);
  1104 + }
  1105 + $map[$index] = $countNeededCellXfs - 1;
  1106 + }
  1107 + $this->cellXfCollection = array_values($this->cellXfCollection);
  1108 +
  1109 + // update the index for all cellXfs
  1110 + foreach ($this->cellXfCollection as $i => $cellXf) {
  1111 + $cellXf->setIndex($i);
  1112 + }
  1113 +
  1114 + // make sure there is always at least one cellXf (there should be)
  1115 + if (empty($this->cellXfCollection)) {
  1116 + $this->cellXfCollection[] = new PHPExcel_Style();
  1117 + }
  1118 +
  1119 + // update the xfIndex for all cells, row dimensions, column dimensions
  1120 + foreach ($this->getWorksheetIterator() as $sheet) {
  1121 + // for all cells
  1122 + foreach ($sheet->getCellCollection(false) as $cellID) {
  1123 + $cell = $sheet->getCell($cellID);
  1124 + $cell->setXfIndex($map[$cell->getXfIndex()]);
  1125 + }
  1126 +
  1127 + // for all row dimensions
  1128 + foreach ($sheet->getRowDimensions() as $rowDimension) {
  1129 + if ($rowDimension->getXfIndex() !== null) {
  1130 + $rowDimension->setXfIndex($map[$rowDimension->getXfIndex()]);
  1131 + }
  1132 + }
  1133 +
  1134 + // for all column dimensions
  1135 + foreach ($sheet->getColumnDimensions() as $columnDimension) {
  1136 + $columnDimension->setXfIndex($map[$columnDimension->getXfIndex()]);
  1137 + }
  1138 +
  1139 + // also do garbage collection for all the sheets
  1140 + $sheet->garbageCollect();
  1141 + }
  1142 + }
  1143 +
  1144 + /**
  1145 + * Return the unique ID value assigned to this spreadsheet workbook
  1146 + *
  1147 + * @return string
  1148 + */
  1149 + public function getID()
  1150 + {
  1151 + return $this->uniqueID;
  1152 + }
  1153 +}
  1 +<?php
  2 +
  3 +PHPExcel_Autoloader::register();
  4 +// As we always try to run the autoloader before anything else, we can use it to do a few
  5 +// simple checks and initialisations
  6 +//PHPExcel_Shared_ZipStreamWrapper::register();
  7 +// check mbstring.func_overload
  8 +if (ini_get('mbstring.func_overload') & 2) {
  9 + throw new PHPExcel_Exception('Multibyte function overloading in PHP must be disabled for string functions (2).');
  10 +}
  11 +PHPExcel_Shared_String::buildCharacterSets();
  12 +
  13 +/**
  14 + * PHPExcel
  15 + *
  16 + * Copyright (c) 2006 - 2015 PHPExcel
  17 + *
  18 + * This library is free software; you can redistribute it and/or
  19 + * modify it under the terms of the GNU Lesser General Public
  20 + * License as published by the Free Software Foundation; either
  21 + * version 2.1 of the License, or (at your option) any later version.
  22 + *
  23 + * This library is distributed in the hope that it will be useful,
  24 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  25 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  26 + * Lesser General Public License for more details.
  27 + *
  28 + * You should have received a copy of the GNU Lesser General Public
  29 + * License along with this library; if not, write to the Free Software
  30 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  31 + *
  32 + * @category PHPExcel
  33 + * @package PHPExcel
  34 + * @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel)
  35 + * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
  36 + * @version ##VERSION##, ##DATE##
  37 + */
  38 +class PHPExcel_Autoloader
  39 +{
  40 + /**
  41 + * Register the Autoloader with SPL
  42 + *
  43 + */
  44 + public static function register()
  45 + {
  46 + if (function_exists('__autoload')) {
  47 + // Register any existing autoloader function with SPL, so we don't get any clashes
  48 + spl_autoload_register('__autoload');
  49 + }
  50 + // Register ourselves with SPL
  51 + if (version_compare(PHP_VERSION, '5.3.0') >= 0) {
  52 + return spl_autoload_register(array('PHPExcel_Autoloader', 'load'), true, true);
  53 + } else {
  54 + return spl_autoload_register(array('PHPExcel_Autoloader', 'load'));
  55 + }
  56 + }
  57 +
  58 + /**
  59 + * Autoload a class identified by name
  60 + *
  61 + * @param string $pClassName Name of the object to load
  62 + */
  63 + public static function load($pClassName)
  64 + {
  65 + if ((class_exists($pClassName, false)) || (strpos($pClassName, 'PHPExcel') !== 0)) {
  66 + // Either already loaded, or not a PHPExcel class request
  67 + return false;
  68 + }
  69 +
  70 + $pClassFilePath = PHPEXCEL_ROOT .
  71 + str_replace('_', DIRECTORY_SEPARATOR, $pClassName) .
  72 + '.php';
  73 +
  74 + if ((file_exists($pClassFilePath) === false) || (is_readable($pClassFilePath) === false)) {
  75 + // Can't load
  76 + return false;
  77 + }
  78 +
  79 + require($pClassFilePath);
  80 + }
  81 +}
  1 +<?php
  2 +
  3 +/**
  4 + * PHPExcel_CachedObjectStorage_APC
  5 + *
  6 + * Copyright (c) 2006 - 2015 PHPExcel
  7 + *
  8 + * This library is free software; you can redistribute it and/or
  9 + * modify it under the terms of the GNU Lesser General Public
  10 + * License as published by the Free Software Foundation; either
  11 + * version 2.1 of the License, or (at your option) any later version.
  12 + *
  13 + * This library is distributed in the hope that it will be useful,
  14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  16 + * Lesser General Public License for more details.
  17 + *
  18 + * You should have received a copy of the GNU Lesser General Public
  19 + * License along with this library; if not, write to the Free Software
  20 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  21 + *
  22 + * @category PHPExcel
  23 + * @package PHPExcel_CachedObjectStorage
  24 + * @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel)
  25 + * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
  26 + * @version ##VERSION##, ##DATE##
  27 + */
  28 +class PHPExcel_CachedObjectStorage_APC extends PHPExcel_CachedObjectStorage_CacheBase implements PHPExcel_CachedObjectStorage_ICache
  29 +{
  30 + /**
  31 + * Prefix used to uniquely identify cache data for this worksheet
  32 + *
  33 + * @access private
  34 + * @var string
  35 + */
  36 + private $cachePrefix = null;
  37 +
  38 + /**
  39 + * Cache timeout
  40 + *
  41 + * @access private
  42 + * @var integer
  43 + */
  44 + private $cacheTime = 600;
  45 +
  46 + /**
  47 + * Store cell data in cache for the current cell object if it's "dirty",
  48 + * and the 'nullify' the current cell object
  49 + *
  50 + * @access private
  51 + * @return void
  52 + * @throws PHPExcel_Exception
  53 + */
  54 + protected function storeData()
  55 + {
  56 + if ($this->currentCellIsDirty && !empty($this->currentObjectID)) {
  57 + $this->currentObject->detach();
  58 +
  59 + if (!apc_store(
  60 + $this->cachePrefix . $this->currentObjectID . '.cache',
  61 + serialize($this->currentObject),
  62 + $this->cacheTime
  63 + )) {
  64 + $this->__destruct();
  65 + throw new PHPExcel_Exception('Failed to store cell ' . $this->currentObjectID . ' in APC');
  66 + }
  67 + $this->currentCellIsDirty = false;
  68 + }
  69 + $this->currentObjectID = $this->currentObject = null;
  70 + }
  71 +
  72 + /**
  73 + * Add or Update a cell in cache identified by coordinate address
  74 + *
  75 + * @access public
  76 + * @param string $pCoord Coordinate address of the cell to update
  77 + * @param PHPExcel_Cell $cell Cell to update
  78 + * @return PHPExcel_Cell
  79 + * @throws PHPExcel_Exception
  80 + */
  81 + public function addCacheData($pCoord, PHPExcel_Cell $cell)
  82 + {
  83 + if (($pCoord !== $this->currentObjectID) && ($this->currentObjectID !== null)) {
  84 + $this->storeData();
  85 + }
  86 + $this->cellCache[$pCoord] = true;
  87 +
  88 + $this->currentObjectID = $pCoord;
  89 + $this->currentObject = $cell;
  90 + $this->currentCellIsDirty = true;
  91 +
  92 + return $cell;
  93 + }
  94 +
  95 + /**
  96 + * Is a value set in the current PHPExcel_CachedObjectStorage_ICache for an indexed cell?
  97 + *
  98 + * @access public
  99 + * @param string $pCoord Coordinate address of the cell to check
  100 + * @throws PHPExcel_Exception
  101 + * @return boolean
  102 + */
  103 + public function isDataSet($pCoord)
  104 + {
  105 + // Check if the requested entry is the current object, or exists in the cache
  106 + if (parent::isDataSet($pCoord)) {
  107 + if ($this->currentObjectID == $pCoord) {
  108 + return true;
  109 + }
  110 + // Check if the requested entry still exists in apc
  111 + $success = apc_fetch($this->cachePrefix.$pCoord.'.cache');
  112 + if ($success === false) {
  113 + // Entry no longer exists in APC, so clear it from the cache array
  114 + parent::deleteCacheData($pCoord);
  115 + throw new PHPExcel_Exception('Cell entry '.$pCoord.' no longer exists in APC cache');
  116 + }
  117 + return true;
  118 + }
  119 + return false;
  120 + }
  121 +
  122 + /**
  123 + * Get cell at a specific coordinate
  124 + *
  125 + * @access public
  126 + * @param string $pCoord Coordinate of the cell
  127 + * @throws PHPExcel_Exception
  128 + * @return PHPExcel_Cell Cell that was found, or null if not found
  129 + */
  130 + public function getCacheData($pCoord)
  131 + {
  132 + if ($pCoord === $this->currentObjectID) {
  133 + return $this->currentObject;
  134 + }
  135 + $this->storeData();
  136 +
  137 + // Check if the entry that has been requested actually exists
  138 + if (parent::isDataSet($pCoord)) {
  139 + $obj = apc_fetch($this->cachePrefix . $pCoord . '.cache');
  140 + if ($obj === false) {
  141 + // Entry no longer exists in APC, so clear it from the cache array
  142 + parent::deleteCacheData($pCoord);
  143 + throw new PHPExcel_Exception('Cell entry '.$pCoord.' no longer exists in APC cache');
  144 + }
  145 + } else {
  146 + // Return null if requested entry doesn't exist in cache
  147 + return null;
  148 + }
  149 +
  150 + // Set current entry to the requested entry
  151 + $this->currentObjectID = $pCoord;
  152 + $this->currentObject = unserialize($obj);
  153 + // Re-attach this as the cell's parent
  154 + $this->currentObject->attach($this);
  155 +
  156 + // Return requested entry
  157 + return $this->currentObject;
  158 + }
  159 +
  160 + /**
  161 + * Get a list of all cell addresses currently held in cache
  162 + *
  163 + * @return string[]
  164 + */
  165 + public function getCellList()
  166 + {
  167 + if ($this->currentObjectID !== null) {
  168 + $this->storeData();
  169 + }
  170 +
  171 + return parent::getCellList();
  172 + }
  173 +
  174 + /**
  175 + * Delete a cell in cache identified by coordinate address
  176 + *
  177 + * @access public
  178 + * @param string $pCoord Coordinate address of the cell to delete
  179 + * @throws PHPExcel_Exception
  180 + */
  181 + public function deleteCacheData($pCoord)
  182 + {
  183 + // Delete the entry from APC
  184 + apc_delete($this->cachePrefix.$pCoord.'.cache');
  185 +
  186 + // Delete the entry from our cell address array
  187 + parent::deleteCacheData($pCoord);
  188 + }
  189 +
  190 + /**
  191 + * Clone the cell collection
  192 + *
  193 + * @access public
  194 + * @param PHPExcel_Worksheet $parent The new worksheet
  195 + * @throws PHPExcel_Exception
  196 + * @return void
  197 + */
  198 + public function copyCellCollection(PHPExcel_Worksheet $parent)
  199 + {
  200 + parent::copyCellCollection($parent);
  201 + // Get a new id for the new file name
  202 + $baseUnique = $this->getUniqueID();
  203 + $newCachePrefix = substr(md5($baseUnique), 0, 8) . '.';
  204 + $cacheList = $this->getCellList();
  205 + foreach ($cacheList as $cellID) {
  206 + if ($cellID != $this->currentObjectID) {
  207 + $obj = apc_fetch($this->cachePrefix . $cellID . '.cache');
  208 + if ($obj === false) {
  209 + // Entry no longer exists in APC, so clear it from the cache array
  210 + parent::deleteCacheData($cellID);
  211 + throw new PHPExcel_Exception('Cell entry ' . $cellID . ' no longer exists in APC');
  212 + }
  213 + if (!apc_store($newCachePrefix . $cellID . '.cache', $obj, $this->cacheTime)) {
  214 + $this->__destruct();
  215 + throw new PHPExcel_Exception('Failed to store cell ' . $cellID . ' in APC');
  216 + }
  217 + }
  218 + }
  219 + $this->cachePrefix = $newCachePrefix;
  220 + }
  221 +
  222 + /**
  223 + * Clear the cell collection and disconnect from our parent
  224 + *
  225 + * @return void
  226 + */
  227 + public function unsetWorksheetCells()
  228 + {
  229 + if ($this->currentObject !== null) {
  230 + $this->currentObject->detach();
  231 + $this->currentObject = $this->currentObjectID = null;
  232 + }
  233 +
  234 + // Flush the APC cache
  235 + $this->__destruct();
  236 +
  237 + $this->cellCache = array();
  238 +
  239 + // detach ourself from the worksheet, so that it can then delete this object successfully
  240 + $this->parent = null;
  241 + }
  242 +
  243 + /**
  244 + * Initialise this new cell collection
  245 + *
  246 + * @param PHPExcel_Worksheet $parent The worksheet for this cell collection
  247 + * @param array of mixed $arguments Additional initialisation arguments
  248 + */
  249 + public function __construct(PHPExcel_Worksheet $parent, $arguments)
  250 + {
  251 + $cacheTime = (isset($arguments['cacheTime'])) ? $arguments['cacheTime'] : 600;
  252 +
  253 + if ($this->cachePrefix === null) {
  254 + $baseUnique = $this->getUniqueID();
  255 + $this->cachePrefix = substr(md5($baseUnique), 0, 8) . '.';
  256 + $this->cacheTime = $cacheTime;
  257 +
  258 + parent::__construct($parent);
  259 + }
  260 + }
  261 +
  262 + /**
  263 + * Destroy this cell collection
  264 + */
  265 + public function __destruct()
  266 + {
  267 + $cacheList = $this->getCellList();
  268 + foreach ($cacheList as $cellID) {
  269 + apc_delete($this->cachePrefix . $cellID . '.cache');
  270 + }
  271 + }
  272 +
  273 + /**
  274 + * Identify whether the caching method is currently available
  275 + * Some methods are dependent on the availability of certain extensions being enabled in the PHP build
  276 + *
  277 + * @return boolean
  278 + */
  279 + public static function cacheMethodIsAvailable()
  280 + {
  281 + if (!function_exists('apc_store')) {
  282 + return false;
  283 + }
  284 + if (apc_sma_info() === false) {
  285 + return false;
  286 + }
  287 +
  288 + return true;
  289 + }
  290 +}
  1 +<?php
  2 +
  3 +/**
  4 + * PHPExcel_CachedObjectStorage_CacheBase
  5 + *
  6 + * Copyright (c) 2006 - 2015 PHPExcel
  7 + *
  8 + * This library is free software; you can redistribute it and/or
  9 + * modify it under the terms of the GNU Lesser General Public
  10 + * License as published by the Free Software Foundation; either
  11 + * version 2.1 of the License, or (at your option) any later version.
  12 + *
  13 + * This library is distributed in the hope that it will be useful,
  14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  16 + * Lesser General Public License for more details.
  17 + *
  18 + * You should have received a copy of the GNU Lesser General Public
  19 + * License along with this library; if not, write to the Free Software
  20 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  21 + *
  22 + * @category PHPExcel
  23 + * @package PHPExcel_CachedObjectStorage
  24 + * @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel)
  25 + * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
  26 + * @version ##VERSION##, ##DATE##
  27 + */
  28 +abstract class PHPExcel_CachedObjectStorage_CacheBase
  29 +{
  30 + /**
  31 + * Parent worksheet
  32 + *
  33 + * @var PHPExcel_Worksheet
  34 + */
  35 + protected $parent;
  36 +
  37 + /**
  38 + * The currently active Cell
  39 + *
  40 + * @var PHPExcel_Cell
  41 + */
  42 + protected $currentObject = null;
  43 +
  44 + /**
  45 + * Coordinate address of the currently active Cell
  46 + *
  47 + * @var string
  48 + */
  49 + protected $currentObjectID = null;
  50 +
  51 + /**
  52 + * Flag indicating whether the currently active Cell requires saving
  53 + *
  54 + * @var boolean
  55 + */
  56 + protected $currentCellIsDirty = true;
  57 +
  58 + /**
  59 + * An array of cells or cell pointers for the worksheet cells held in this cache,
  60 + * and indexed by their coordinate address within the worksheet
  61 + *
  62 + * @var array of mixed
  63 + */
  64 + protected $cellCache = array();
  65 +
  66 + /**
  67 + * Initialise this new cell collection
  68 + *
  69 + * @param PHPExcel_Worksheet $parent The worksheet for this cell collection
  70 + */
  71 + public function __construct(PHPExcel_Worksheet $parent)
  72 + {
  73 + // Set our parent worksheet.
  74 + // This is maintained within the cache controller to facilitate re-attaching it to PHPExcel_Cell objects when
  75 + // they are woken from a serialized state
  76 + $this->parent = $parent;
  77 + }
  78 +
  79 + /**
  80 + * Return the parent worksheet for this cell collection
  81 + *
  82 + * @return PHPExcel_Worksheet
  83 + */
  84 + public function getParent()
  85 + {
  86 + return $this->parent;
  87 + }
  88 +
  89 + /**
  90 + * Is a value set in the current PHPExcel_CachedObjectStorage_ICache for an indexed cell?
  91 + *
  92 + * @param string $pCoord Coordinate address of the cell to check
  93 + * @return boolean
  94 + */
  95 + public function isDataSet($pCoord)
  96 + {
  97 + if ($pCoord === $this->currentObjectID) {
  98 + return true;
  99 + }
  100 + // Check if the requested entry exists in the cache
  101 + return isset($this->cellCache[$pCoord]);
  102 + }
  103 +
  104 + /**
  105 + * Move a cell object from one address to another
  106 + *
  107 + * @param string $fromAddress Current address of the cell to move
  108 + * @param string $toAddress Destination address of the cell to move
  109 + * @return boolean
  110 + */
  111 + public function moveCell($fromAddress, $toAddress)
  112 + {
  113 + if ($fromAddress === $this->currentObjectID) {
  114 + $this->currentObjectID = $toAddress;
  115 + }
  116 + $this->currentCellIsDirty = true;
  117 + if (isset($this->cellCache[$fromAddress])) {
  118 + $this->cellCache[$toAddress] = &$this->cellCache[$fromAddress];
  119 + unset($this->cellCache[$fromAddress]);
  120 + }
  121 +
  122 + return true;
  123 + }
  124 +
  125 + /**
  126 + * Add or Update a cell in cache
  127 + *
  128 + * @param PHPExcel_Cell $cell Cell to update
  129 + * @return PHPExcel_Cell
  130 + * @throws PHPExcel_Exception
  131 + */
  132 + public function updateCacheData(PHPExcel_Cell $cell)
  133 + {
  134 + return $this->addCacheData($cell->getCoordinate(), $cell);
  135 + }
  136 +
  137 + /**
  138 + * Delete a cell in cache identified by coordinate address
  139 + *
  140 + * @param string $pCoord Coordinate address of the cell to delete
  141 + * @throws PHPExcel_Exception
  142 + */
  143 + public function deleteCacheData($pCoord)
  144 + {
  145 + if ($pCoord === $this->currentObjectID && !is_null($this->currentObject)) {
  146 + $this->currentObject->detach();
  147 + $this->currentObjectID = $this->currentObject = null;
  148 + }
  149 +
  150 + if (is_object($this->cellCache[$pCoord])) {
  151 + $this->cellCache[$pCoord]->detach();
  152 + unset($this->cellCache[$pCoord]);
  153 + }
  154 + $this->currentCellIsDirty = false;
  155 + }
  156 +
  157 + /**
  158 + * Get a list of all cell addresses currently held in cache
  159 + *
  160 + * @return string[]
  161 + */
  162 + public function getCellList()
  163 + {
  164 + return array_keys($this->cellCache);
  165 + }
  166 +
  167 + /**
  168 + * Sort the list of all cell addresses currently held in cache by row and column
  169 + *
  170 + * @return string[]
  171 + */
  172 + public function getSortedCellList()
  173 + {
  174 + $sortKeys = array();
  175 + foreach ($this->getCellList() as $coord) {
  176 + sscanf($coord, '%[A-Z]%d', $column, $row);
  177 + $sortKeys[sprintf('%09d%3s', $row, $column)] = $coord;
  178 + }
  179 + ksort($sortKeys);
  180 +
  181 + return array_values($sortKeys);
  182 + }
  183 +
  184 + /**
  185 + * Get highest worksheet column and highest row that have cell records
  186 + *
  187 + * @return array Highest column name and highest row number
  188 + */
  189 + public function getHighestRowAndColumn()
  190 + {
  191 + // Lookup highest column and highest row
  192 + $col = array('A' => '1A');
  193 + $row = array(1);
  194 + foreach ($this->getCellList() as $coord) {
  195 + sscanf($coord, '%[A-Z]%d', $c, $r);
  196 + $row[$r] = $r;
  197 + $col[$c] = strlen($c).$c;
  198 + }
  199 + if (!empty($row)) {
  200 + // Determine highest column and row
  201 + $highestRow = max($row);
  202 + $highestColumn = substr(max($col), 1);
  203 + }
  204 +
  205 + return array(
  206 + 'row' => $highestRow,
  207 + 'column' => $highestColumn
  208 + );
  209 + }
  210 +
  211 + /**
  212 + * Return the cell address of the currently active cell object
  213 + *
  214 + * @return string
  215 + */
  216 + public function getCurrentAddress()
  217 + {
  218 + return $this->currentObjectID;
  219 + }
  220 +
  221 + /**
  222 + * Return the column address of the currently active cell object
  223 + *
  224 + * @return string
  225 + */
  226 + public function getCurrentColumn()
  227 + {
  228 + sscanf($this->currentObjectID, '%[A-Z]%d', $column, $row);
  229 + return $column;
  230 + }
  231 +
  232 + /**
  233 + * Return the row address of the currently active cell object
  234 + *
  235 + * @return integer
  236 + */
  237 + public function getCurrentRow()
  238 + {
  239 + sscanf($this->currentObjectID, '%[A-Z]%d', $column, $row);
  240 + return (integer) $row;
  241 + }
  242 +
  243 + /**
  244 + * Get highest worksheet column
  245 + *
  246 + * @param string $row Return the highest column for the specified row,
  247 + * or the highest column of any row if no row number is passed
  248 + * @return string Highest column name
  249 + */
  250 + public function getHighestColumn($row = null)
  251 + {
  252 + if ($row == null) {
  253 + $colRow = $this->getHighestRowAndColumn();
  254 + return $colRow['column'];
  255 + }
  256 +
  257 + $columnList = array(1);
  258 + foreach ($this->getCellList() as $coord) {
  259 + sscanf($coord, '%[A-Z]%d', $c, $r);
  260 + if ($r != $row) {
  261 + continue;
  262 + }
  263 + $columnList[] = PHPExcel_Cell::columnIndexFromString($c);
  264 + }
  265 + return PHPExcel_Cell::stringFromColumnIndex(max($columnList) - 1);
  266 + }
  267 +
  268 + /**
  269 + * Get highest worksheet row
  270 + *
  271 + * @param string $column Return the highest row for the specified column,
  272 + * or the highest row of any column if no column letter is passed
  273 + * @return int Highest row number
  274 + */
  275 + public function getHighestRow($column = null)
  276 + {
  277 + if ($column == null) {
  278 + $colRow = $this->getHighestRowAndColumn();
  279 + return $colRow['row'];
  280 + }
  281 +
  282 + $rowList = array(0);
  283 + foreach ($this->getCellList() as $coord) {
  284 + sscanf($coord, '%[A-Z]%d', $c, $r);
  285 + if ($c != $column) {
  286 + continue;
  287 + }
  288 + $rowList[] = $r;
  289 + }
  290 +
  291 + return max($rowList);
  292 + }
  293 +
  294 + /**
  295 + * Generate a unique ID for cache referencing
  296 + *
  297 + * @return string Unique Reference
  298 + */
  299 + protected function getUniqueID()
  300 + {
  301 + if (function_exists('posix_getpid')) {
  302 + $baseUnique = posix_getpid();
  303 + } else {
  304 + $baseUnique = mt_rand();
  305 + }
  306 + return uniqid($baseUnique, true);
  307 + }
  308 +
  309 + /**
  310 + * Clone the cell collection
  311 + *
  312 + * @param PHPExcel_Worksheet $parent The new worksheet
  313 + * @return void
  314 + */
  315 + public function copyCellCollection(PHPExcel_Worksheet $parent)
  316 + {
  317 + $this->currentCellIsDirty;
  318 + $this->storeData();
  319 +
  320 + $this->parent = $parent;
  321 + if (($this->currentObject !== null) && (is_object($this->currentObject))) {
  322 + $this->currentObject->attach($this);
  323 + }
  324 + } // function copyCellCollection()
  325 +
  326 + /**
  327 + * Remove a row, deleting all cells in that row
  328 + *
  329 + * @param string $row Row number to remove
  330 + * @return void
  331 + */
  332 + public function removeRow($row)
  333 + {
  334 + foreach ($this->getCellList() as $coord) {
  335 + sscanf($coord, '%[A-Z]%d', $c, $r);
  336 + if ($r == $row) {
  337 + $this->deleteCacheData($coord);
  338 + }
  339 + }
  340 + }
  341 +
  342 + /**
  343 + * Remove a column, deleting all cells in that column
  344 + *
  345 + * @param string $column Column ID to remove
  346 + * @return void
  347 + */
  348 + public function removeColumn($column)
  349 + {
  350 + foreach ($this->getCellList() as $coord) {
  351 + sscanf($coord, '%[A-Z]%d', $c, $r);
  352 + if ($c == $column) {
  353 + $this->deleteCacheData($coord);
  354 + }
  355 + }
  356 + }
  357 +
  358 + /**
  359 + * Identify whether the caching method is currently available
  360 + * Some methods are dependent on the availability of certain extensions being enabled in the PHP build
  361 + *
  362 + * @return boolean
  363 + */
  364 + public static function cacheMethodIsAvailable()
  365 + {
  366 + return true;
  367 + }
  368 +}
  1 +<?php
  2 +
  3 +/**
  4 + * PHPExcel_CachedObjectStorage_DiscISAM
  5 + *
  6 + * Copyright (c) 2006 - 2015 PHPExcel
  7 + *
  8 + * This library is free software; you can redistribute it and/or
  9 + * modify it under the terms of the GNU Lesser General Public
  10 + * License as published by the Free Software Foundation; either
  11 + * version 2.1 of the License, or (at your option) any later version.
  12 + *
  13 + * This library is distributed in the hope that it will be useful,
  14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  16 + * Lesser General Public License for more details.
  17 + *
  18 + * You should have received a copy of the GNU Lesser General Public
  19 + * License along with this library; if not, write to the Free Software
  20 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  21 + *
  22 + * @category PHPExcel
  23 + * @package PHPExcel_CachedObjectStorage
  24 + * @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel)
  25 + * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
  26 + * @version ##VERSION##, ##DATE##
  27 + */
  28 +class PHPExcel_CachedObjectStorage_DiscISAM extends PHPExcel_CachedObjectStorage_CacheBase implements PHPExcel_CachedObjectStorage_ICache
  29 +{
  30 + /**
  31 + * Name of the file for this cache
  32 + *
  33 + * @var string
  34 + */
  35 + private $fileName = null;
  36 +
  37 + /**
  38 + * File handle for this cache file
  39 + *
  40 + * @var resource
  41 + */
  42 + private $fileHandle = null;
  43 +
  44 + /**
  45 + * Directory/Folder where the cache file is located
  46 + *
  47 + * @var string
  48 + */
  49 + private $cacheDirectory = null;
  50 +
  51 + /**
  52 + * Store cell data in cache for the current cell object if it's "dirty",
  53 + * and the 'nullify' the current cell object
  54 + *
  55 + * @return void
  56 + * @throws PHPExcel_Exception
  57 + */
  58 + protected function storeData()
  59 + {
  60 + if ($this->currentCellIsDirty && !empty($this->currentObjectID)) {
  61 + $this->currentObject->detach();
  62 +
  63 + fseek($this->fileHandle, 0, SEEK_END);
  64 +
  65 + $this->cellCache[$this->currentObjectID] = array(
  66 + 'ptr' => ftell($this->fileHandle),
  67 + 'sz' => fwrite($this->fileHandle, serialize($this->currentObject))
  68 + );
  69 + $this->currentCellIsDirty = false;
  70 + }
  71 + $this->currentObjectID = $this->currentObject = null;
  72 + }
  73 +
  74 + /**
  75 + * Add or Update a cell in cache identified by coordinate address
  76 + *
  77 + * @param string $pCoord Coordinate address of the cell to update
  78 + * @param PHPExcel_Cell $cell Cell to update
  79 + * @return PHPExcel_Cell
  80 + * @throws PHPExcel_Exception
  81 + */
  82 + public function addCacheData($pCoord, PHPExcel_Cell $cell)
  83 + {
  84 + if (($pCoord !== $this->currentObjectID) && ($this->currentObjectID !== null)) {
  85 + $this->storeData();
  86 + }
  87 +
  88 + $this->currentObjectID = $pCoord;
  89 + $this->currentObject = $cell;
  90 + $this->currentCellIsDirty = true;
  91 +
  92 + return $cell;
  93 + }
  94 +
  95 + /**
  96 + * Get cell at a specific coordinate
  97 + *
  98 + * @param string $pCoord Coordinate of the cell
  99 + * @throws PHPExcel_Exception
  100 + * @return PHPExcel_Cell Cell that was found, or null if not found
  101 + */
  102 + public function getCacheData($pCoord)
  103 + {
  104 + if ($pCoord === $this->currentObjectID) {
  105 + return $this->currentObject;
  106 + }
  107 + $this->storeData();
  108 +
  109 + // Check if the entry that has been requested actually exists
  110 + if (!isset($this->cellCache[$pCoord])) {
  111 + // Return null if requested entry doesn't exist in cache
  112 + return null;
  113 + }
  114 +
  115 + // Set current entry to the requested entry
  116 + $this->currentObjectID = $pCoord;
  117 + fseek($this->fileHandle, $this->cellCache[$pCoord]['ptr']);
  118 + $this->currentObject = unserialize(fread($this->fileHandle, $this->cellCache[$pCoord]['sz']));
  119 + // Re-attach this as the cell's parent
  120 + $this->currentObject->attach($this);
  121 +
  122 + // Return requested entry
  123 + return $this->currentObject;
  124 + }
  125 +
  126 + /**
  127 + * Get a list of all cell addresses currently held in cache
  128 + *
  129 + * @return string[]
  130 + */
  131 + public function getCellList()
  132 + {
  133 + if ($this->currentObjectID !== null) {
  134 + $this->storeData();
  135 + }
  136 +
  137 + return parent::getCellList();
  138 + }
  139 +
  140 + /**
  141 + * Clone the cell collection
  142 + *
  143 + * @param PHPExcel_Worksheet $parent The new worksheet
  144 + */
  145 + public function copyCellCollection(PHPExcel_Worksheet $parent)
  146 + {
  147 + parent::copyCellCollection($parent);
  148 + // Get a new id for the new file name
  149 + $baseUnique = $this->getUniqueID();
  150 + $newFileName = $this->cacheDirectory.'/PHPExcel.'.$baseUnique.'.cache';
  151 + // Copy the existing cell cache file
  152 + copy($this->fileName, $newFileName);
  153 + $this->fileName = $newFileName;
  154 + // Open the copied cell cache file
  155 + $this->fileHandle = fopen($this->fileName, 'a+');
  156 + }
  157 +
  158 + /**
  159 + * Clear the cell collection and disconnect from our parent
  160 + *
  161 + */
  162 + public function unsetWorksheetCells()
  163 + {
  164 + if (!is_null($this->currentObject)) {
  165 + $this->currentObject->detach();
  166 + $this->currentObject = $this->currentObjectID = null;
  167 + }
  168 + $this->cellCache = array();
  169 +
  170 + // detach ourself from the worksheet, so that it can then delete this object successfully
  171 + $this->parent = null;
  172 +
  173 + // Close down the temporary cache file
  174 + $this->__destruct();
  175 + }
  176 +
  177 + /**
  178 + * Initialise this new cell collection
  179 + *
  180 + * @param PHPExcel_Worksheet $parent The worksheet for this cell collection
  181 + * @param array of mixed $arguments Additional initialisation arguments
  182 + */
  183 + public function __construct(PHPExcel_Worksheet $parent, $arguments)
  184 + {
  185 + $this->cacheDirectory = ((isset($arguments['dir'])) && ($arguments['dir'] !== null))
  186 + ? $arguments['dir']
  187 + : PHPExcel_Shared_File::sys_get_temp_dir();
  188 +
  189 + parent::__construct($parent);
  190 + if (is_null($this->fileHandle)) {
  191 + $baseUnique = $this->getUniqueID();
  192 + $this->fileName = $this->cacheDirectory.'/PHPExcel.'.$baseUnique.'.cache';
  193 + $this->fileHandle = fopen($this->fileName, 'a+');
  194 + }
  195 + }
  196 +
  197 + /**
  198 + * Destroy this cell collection
  199 + */
  200 + public function __destruct()
  201 + {
  202 + if (!is_null($this->fileHandle)) {
  203 + fclose($this->fileHandle);
  204 + unlink($this->fileName);
  205 + }
  206 + $this->fileHandle = null;
  207 + }
  208 +}
  1 +<?php
  2 +
  3 +/**
  4 + * PHPExcel_CachedObjectStorage_ICache
  5 + *
  6 + * Copyright (c) 2006 - 2015 PHPExcel
  7 + *
  8 + * This library is free software; you can redistribute it and/or
  9 + * modify it under the terms of the GNU Lesser General Public
  10 + * License as published by the Free Software Foundation; either
  11 + * version 2.1 of the License, or (at your option) any later version.
  12 + *
  13 + * This library is distributed in the hope that it will be useful,
  14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  16 + * Lesser General Public License for more details.
  17 + *
  18 + * You should have received a copy of the GNU Lesser General Public
  19 + * License along with this library; if not, write to the Free Software
  20 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  21 + *
  22 + * @category PHPExcel
  23 + * @package PHPExcel_CachedObjectStorage
  24 + * @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel)
  25 + * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
  26 + * @version ##VERSION##, ##DATE##
  27 + */
  28 +interface PHPExcel_CachedObjectStorage_ICache
  29 +{
  30 + /**
  31 + * Add or Update a cell in cache identified by coordinate address
  32 + *
  33 + * @param string $pCoord Coordinate address of the cell to update
  34 + * @param PHPExcel_Cell $cell Cell to update
  35 + * @return PHPExcel_Cell
  36 + * @throws PHPExcel_Exception
  37 + */
  38 + public function addCacheData($pCoord, PHPExcel_Cell $cell);
  39 +
  40 + /**
  41 + * Add or Update a cell in cache
  42 + *
  43 + * @param PHPExcel_Cell $cell Cell to update
  44 + * @return PHPExcel_Cell
  45 + * @throws PHPExcel_Exception
  46 + */
  47 + public function updateCacheData(PHPExcel_Cell $cell);
  48 +
  49 + /**
  50 + * Fetch a cell from cache identified by coordinate address
  51 + *
  52 + * @param string $pCoord Coordinate address of the cell to retrieve
  53 + * @return PHPExcel_Cell Cell that was found, or null if not found
  54 + * @throws PHPExcel_Exception
  55 + */
  56 + public function getCacheData($pCoord);
  57 +
  58 + /**
  59 + * Delete a cell in cache identified by coordinate address
  60 + *
  61 + * @param string $pCoord Coordinate address of the cell to delete
  62 + * @throws PHPExcel_Exception
  63 + */
  64 + public function deleteCacheData($pCoord);
  65 +
  66 + /**
  67 + * Is a value set in the current PHPExcel_CachedObjectStorage_ICache for an indexed cell?
  68 + *
  69 + * @param string $pCoord Coordinate address of the cell to check
  70 + * @return boolean
  71 + */
  72 + public function isDataSet($pCoord);
  73 +
  74 + /**
  75 + * Get a list of all cell addresses currently held in cache
  76 + *
  77 + * @return string[]
  78 + */
  79 + public function getCellList();
  80 +
  81 + /**
  82 + * Get the list of all cell addresses currently held in cache sorted by column and row
  83 + *
  84 + * @return string[]
  85 + */
  86 + public function getSortedCellList();
  87 +
  88 + /**
  89 + * Clone the cell collection
  90 + *
  91 + * @param PHPExcel_Worksheet $parent The new worksheet
  92 + * @return void
  93 + */
  94 + public function copyCellCollection(PHPExcel_Worksheet $parent);
  95 +
  96 + /**
  97 + * Identify whether the caching method is currently available
  98 + * Some methods are dependent on the availability of certain extensions being enabled in the PHP build
  99 + *
  100 + * @return boolean
  101 + */
  102 + public static function cacheMethodIsAvailable();
  103 +}
  1 +<?php
  2 +
  3 +/**
  4 + * PHPExcel_CachedObjectStorage_Igbinary
  5 + *
  6 + * Copyright (c) 2006 - 2015 PHPExcel
  7 + *
  8 + * This library is free software; you can redistribute it and/or
  9 + * modify it under the terms of the GNU Lesser General Public
  10 + * License as published by the Free Software Foundation; either
  11 + * version 2.1 of the License, or (at your option) any later version.
  12 + *
  13 + * This library is distributed in the hope that it will be useful,
  14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  16 + * Lesser General Public License for more details.
  17 + *
  18 + * You should have received a copy of the GNU Lesser General Public
  19 + * License along with this library; if not, write to the Free Software
  20 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  21 + *
  22 + * @category PHPExcel
  23 + * @package PHPExcel_CachedObjectStorage
  24 + * @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel)
  25 + * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
  26 + * @version ##VERSION##, ##DATE##
  27 + */
  28 +class PHPExcel_CachedObjectStorage_Igbinary extends PHPExcel_CachedObjectStorage_CacheBase implements PHPExcel_CachedObjectStorage_ICache
  29 +{
  30 + /**
  31 + * Store cell data in cache for the current cell object if it's "dirty",
  32 + * and the 'nullify' the current cell object
  33 + *
  34 + * @return void
  35 + * @throws PHPExcel_Exception
  36 + */
  37 + protected function storeData()
  38 + {
  39 + if ($this->currentCellIsDirty && !empty($this->currentObjectID)) {
  40 + $this->currentObject->detach();
  41 +
  42 + $this->cellCache[$this->currentObjectID] = igbinary_serialize($this->currentObject);
  43 + $this->currentCellIsDirty = false;
  44 + }
  45 + $this->currentObjectID = $this->currentObject = null;
  46 + } // function _storeData()
  47 +
  48 +
  49 + /**
  50 + * Add or Update a cell in cache identified by coordinate address
  51 + *
  52 + * @param string $pCoord Coordinate address of the cell to update
  53 + * @param PHPExcel_Cell $cell Cell to update
  54 + * @return PHPExcel_Cell
  55 + * @throws PHPExcel_Exception
  56 + */
  57 + public function addCacheData($pCoord, PHPExcel_Cell $cell)
  58 + {
  59 + if (($pCoord !== $this->currentObjectID) && ($this->currentObjectID !== null)) {
  60 + $this->storeData();
  61 + }
  62 +
  63 + $this->currentObjectID = $pCoord;
  64 + $this->currentObject = $cell;
  65 + $this->currentCellIsDirty = true;
  66 +
  67 + return $cell;
  68 + } // function addCacheData()
  69 +
  70 +
  71 + /**
  72 + * Get cell at a specific coordinate
  73 + *
  74 + * @param string $pCoord Coordinate of the cell
  75 + * @throws PHPExcel_Exception
  76 + * @return PHPExcel_Cell Cell that was found, or null if not found
  77 + */
  78 + public function getCacheData($pCoord)
  79 + {
  80 + if ($pCoord === $this->currentObjectID) {
  81 + return $this->currentObject;
  82 + }
  83 + $this->storeData();
  84 +
  85 + // Check if the entry that has been requested actually exists
  86 + if (!isset($this->cellCache[$pCoord])) {
  87 + // Return null if requested entry doesn't exist in cache
  88 + return null;
  89 + }
  90 +
  91 + // Set current entry to the requested entry
  92 + $this->currentObjectID = $pCoord;
  93 + $this->currentObject = igbinary_unserialize($this->cellCache[$pCoord]);
  94 + // Re-attach this as the cell's parent
  95 + $this->currentObject->attach($this);
  96 +
  97 + // Return requested entry
  98 + return $this->currentObject;
  99 + } // function getCacheData()
  100 +
  101 +
  102 + /**
  103 + * Get a list of all cell addresses currently held in cache
  104 + *
  105 + * @return string[]
  106 + */
  107 + public function getCellList()
  108 + {
  109 + if ($this->currentObjectID !== null) {
  110 + $this->storeData();
  111 + }
  112 +
  113 + return parent::getCellList();
  114 + }
  115 +
  116 +
  117 + /**
  118 + * Clear the cell collection and disconnect from our parent
  119 + *
  120 + * @return void
  121 + */
  122 + public function unsetWorksheetCells()
  123 + {
  124 + if (!is_null($this->currentObject)) {
  125 + $this->currentObject->detach();
  126 + $this->currentObject = $this->currentObjectID = null;
  127 + }
  128 + $this->cellCache = array();
  129 +
  130 + // detach ourself from the worksheet, so that it can then delete this object successfully
  131 + $this->parent = null;
  132 + } // function unsetWorksheetCells()
  133 +
  134 +
  135 + /**
  136 + * Identify whether the caching method is currently available
  137 + * Some methods are dependent on the availability of certain extensions being enabled in the PHP build
  138 + *
  139 + * @return boolean
  140 + */
  141 + public static function cacheMethodIsAvailable()
  142 + {
  143 + if (!function_exists('igbinary_serialize')) {
  144 + return false;
  145 + }
  146 +
  147 + return true;
  148 + }
  149 +}
  1 +<?php
  2 +
  3 +/**
  4 + * PHPExcel_CachedObjectStorage_Memcache
  5 + *
  6 + * Copyright (c) 2006 - 2015 PHPExcel
  7 + *
  8 + * This library is free software; you can redistribute it and/or
  9 + * modify it under the terms of the GNU Lesser General Public
  10 + * License as published by the Free Software Foundation; either
  11 + * version 2.1 of the License, or (at your option) any later version.
  12 + *
  13 + * This library is distributed in the hope that it will be useful,
  14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  16 + * Lesser General Public License for more details.
  17 + *
  18 + * You should have received a copy of the GNU Lesser General Public
  19 + * License along with this library; if not, write to the Free Software
  20 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  21 + *
  22 + * @category PHPExcel
  23 + * @package PHPExcel_CachedObjectStorage
  24 + * @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel)
  25 + * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
  26 + * @version ##VERSION##, ##DATE##
  27 + */
  28 +class PHPExcel_CachedObjectStorage_Memcache extends PHPExcel_CachedObjectStorage_CacheBase implements PHPExcel_CachedObjectStorage_ICache
  29 +{
  30 + /**
  31 + * Prefix used to uniquely identify cache data for this worksheet
  32 + *
  33 + * @var string
  34 + */
  35 + private $cachePrefix = null;
  36 +
  37 + /**
  38 + * Cache timeout
  39 + *
  40 + * @var integer
  41 + */
  42 + private $cacheTime = 600;
  43 +
  44 + /**
  45 + * Memcache interface
  46 + *
  47 + * @var resource
  48 + */
  49 + private $memcache = null;
  50 +
  51 +
  52 + /**
  53 + * Store cell data in cache for the current cell object if it's "dirty",
  54 + * and the 'nullify' the current cell object
  55 + *
  56 + * @return void
  57 + * @throws PHPExcel_Exception
  58 + */
  59 + protected function storeData()
  60 + {
  61 + if ($this->currentCellIsDirty && !empty($this->currentObjectID)) {
  62 + $this->currentObject->detach();
  63 +
  64 + $obj = serialize($this->currentObject);
  65 + if (!$this->memcache->replace($this->cachePrefix . $this->currentObjectID . '.cache', $obj, null, $this->cacheTime)) {
  66 + if (!$this->memcache->add($this->cachePrefix . $this->currentObjectID . '.cache', $obj, null, $this->cacheTime)) {
  67 + $this->__destruct();
  68 + throw new PHPExcel_Exception("Failed to store cell {$this->currentObjectID} in MemCache");
  69 + }
  70 + }
  71 + $this->currentCellIsDirty = false;
  72 + }
  73 + $this->currentObjectID = $this->currentObject = null;
  74 + } // function _storeData()
  75 +
  76 +
  77 + /**
  78 + * Add or Update a cell in cache identified by coordinate address
  79 + *
  80 + * @param string $pCoord Coordinate address of the cell to update
  81 + * @param PHPExcel_Cell $cell Cell to update
  82 + * @return PHPExcel_Cell
  83 + * @throws PHPExcel_Exception
  84 + */
  85 + public function addCacheData($pCoord, PHPExcel_Cell $cell)
  86 + {
  87 + if (($pCoord !== $this->currentObjectID) && ($this->currentObjectID !== null)) {
  88 + $this->storeData();
  89 + }
  90 + $this->cellCache[$pCoord] = true;
  91 +
  92 + $this->currentObjectID = $pCoord;
  93 + $this->currentObject = $cell;
  94 + $this->currentCellIsDirty = true;
  95 +
  96 + return $cell;
  97 + } // function addCacheData()
  98 +
  99 +
  100 + /**
  101 + * Is a value set in the current PHPExcel_CachedObjectStorage_ICache for an indexed cell?
  102 + *
  103 + * @param string $pCoord Coordinate address of the cell to check
  104 + * @return boolean
  105 + * @return boolean
  106 + */
  107 + public function isDataSet($pCoord)
  108 + {
  109 + // Check if the requested entry is the current object, or exists in the cache
  110 + if (parent::isDataSet($pCoord)) {
  111 + if ($this->currentObjectID == $pCoord) {
  112 + return true;
  113 + }
  114 + // Check if the requested entry still exists in Memcache
  115 + $success = $this->memcache->get($this->cachePrefix.$pCoord.'.cache');
  116 + if ($success === false) {
  117 + // Entry no longer exists in Memcache, so clear it from the cache array
  118 + parent::deleteCacheData($pCoord);
  119 + throw new PHPExcel_Exception('Cell entry '.$pCoord.' no longer exists in MemCache');
  120 + }
  121 + return true;
  122 + }
  123 + return false;
  124 + }
  125 +
  126 +
  127 + /**
  128 + * Get cell at a specific coordinate
  129 + *
  130 + * @param string $pCoord Coordinate of the cell
  131 + * @throws PHPExcel_Exception
  132 + * @return PHPExcel_Cell Cell that was found, or null if not found
  133 + */
  134 + public function getCacheData($pCoord)
  135 + {
  136 + if ($pCoord === $this->currentObjectID) {
  137 + return $this->currentObject;
  138 + }
  139 + $this->storeData();
  140 +
  141 + // Check if the entry that has been requested actually exists
  142 + if (parent::isDataSet($pCoord)) {
  143 + $obj = $this->memcache->get($this->cachePrefix . $pCoord . '.cache');
  144 + if ($obj === false) {
  145 + // Entry no longer exists in Memcache, so clear it from the cache array
  146 + parent::deleteCacheData($pCoord);
  147 + throw new PHPExcel_Exception("Cell entry {$pCoord} no longer exists in MemCache");
  148 + }
  149 + } else {
  150 + // Return null if requested entry doesn't exist in cache
  151 + return null;
  152 + }
  153 +
  154 + // Set current entry to the requested entry
  155 + $this->currentObjectID = $pCoord;
  156 + $this->currentObject = unserialize($obj);
  157 + // Re-attach this as the cell's parent
  158 + $this->currentObject->attach($this);
  159 +
  160 + // Return requested entry
  161 + return $this->currentObject;
  162 + }
  163 +
  164 + /**
  165 + * Get a list of all cell addresses currently held in cache
  166 + *
  167 + * @return string[]
  168 + */
  169 + public function getCellList()
  170 + {
  171 + if ($this->currentObjectID !== null) {
  172 + $this->storeData();
  173 + }
  174 +
  175 + return parent::getCellList();
  176 + }
  177 +
  178 + /**
  179 + * Delete a cell in cache identified by coordinate address
  180 + *
  181 + * @param string $pCoord Coordinate address of the cell to delete
  182 + * @throws PHPExcel_Exception
  183 + */
  184 + public function deleteCacheData($pCoord)
  185 + {
  186 + // Delete the entry from Memcache
  187 + $this->memcache->delete($this->cachePrefix . $pCoord . '.cache');
  188 +
  189 + // Delete the entry from our cell address array
  190 + parent::deleteCacheData($pCoord);
  191 + }
  192 +
  193 + /**
  194 + * Clone the cell collection
  195 + *
  196 + * @param PHPExcel_Worksheet $parent The new worksheet
  197 + * @return void
  198 + */
  199 + public function copyCellCollection(PHPExcel_Worksheet $parent)
  200 + {
  201 + parent::copyCellCollection($parent);
  202 + // Get a new id for the new file name
  203 + $baseUnique = $this->getUniqueID();
  204 + $newCachePrefix = substr(md5($baseUnique), 0, 8) . '.';
  205 + $cacheList = $this->getCellList();
  206 + foreach ($cacheList as $cellID) {
  207 + if ($cellID != $this->currentObjectID) {
  208 + $obj = $this->memcache->get($this->cachePrefix.$cellID.'.cache');
  209 + if ($obj === false) {
  210 + // Entry no longer exists in Memcache, so clear it from the cache array
  211 + parent::deleteCacheData($cellID);
  212 + throw new PHPExcel_Exception("Cell entry {$cellID} no longer exists in MemCache");
  213 + }
  214 + if (!$this->memcache->add($newCachePrefix . $cellID . '.cache', $obj, null, $this->cacheTime)) {
  215 + $this->__destruct();
  216 + throw new PHPExcel_Exception("Failed to store cell {$cellID} in MemCache");
  217 + }
  218 + }
  219 + }
  220 + $this->cachePrefix = $newCachePrefix;
  221 + }
  222 +
  223 + /**
  224 + * Clear the cell collection and disconnect from our parent
  225 + *
  226 + * @return void
  227 + */
  228 + public function unsetWorksheetCells()
  229 + {
  230 + if (!is_null($this->currentObject)) {
  231 + $this->currentObject->detach();
  232 + $this->currentObject = $this->currentObjectID = null;
  233 + }
  234 +
  235 + // Flush the Memcache cache
  236 + $this->__destruct();
  237 +
  238 + $this->cellCache = array();
  239 +
  240 + // detach ourself from the worksheet, so that it can then delete this object successfully
  241 + $this->parent = null;
  242 + }
  243 +
  244 + /**
  245 + * Initialise this new cell collection
  246 + *
  247 + * @param PHPExcel_Worksheet $parent The worksheet for this cell collection
  248 + * @param array of mixed $arguments Additional initialisation arguments
  249 + */
  250 + public function __construct(PHPExcel_Worksheet $parent, $arguments)
  251 + {
  252 + $memcacheServer = (isset($arguments['memcacheServer'])) ? $arguments['memcacheServer'] : 'localhost';
  253 + $memcachePort = (isset($arguments['memcachePort'])) ? $arguments['memcachePort'] : 11211;
  254 + $cacheTime = (isset($arguments['cacheTime'])) ? $arguments['cacheTime'] : 600;
  255 +
  256 + if (is_null($this->cachePrefix)) {
  257 + $baseUnique = $this->getUniqueID();
  258 + $this->cachePrefix = substr(md5($baseUnique), 0, 8) . '.';
  259 +
  260 + // Set a new Memcache object and connect to the Memcache server
  261 + $this->memcache = new Memcache();
  262 + if (!$this->memcache->addServer($memcacheServer, $memcachePort, false, 50, 5, 5, true, array($this, 'failureCallback'))) {
  263 + throw new PHPExcel_Exception("Could not connect to MemCache server at {$memcacheServer}:{$memcachePort}");
  264 + }
  265 + $this->cacheTime = $cacheTime;
  266 +
  267 + parent::__construct($parent);
  268 + }
  269 + }
  270 +
  271 + /**
  272 + * Memcache error handler
  273 + *
  274 + * @param string $host Memcache server
  275 + * @param integer $port Memcache port
  276 + * @throws PHPExcel_Exception
  277 + */
  278 + public function failureCallback($host, $port)
  279 + {
  280 + throw new PHPExcel_Exception("memcache {$host}:{$port} failed");
  281 + }
  282 +
  283 + /**
  284 + * Destroy this cell collection
  285 + */
  286 + public function __destruct()
  287 + {
  288 + $cacheList = $this->getCellList();
  289 + foreach ($cacheList as $cellID) {
  290 + $this->memcache->delete($this->cachePrefix.$cellID . '.cache');
  291 + }
  292 + }
  293 +
  294 + /**
  295 + * Identify whether the caching method is currently available
  296 + * Some methods are dependent on the availability of certain extensions being enabled in the PHP build
  297 + *
  298 + * @return boolean
  299 + */
  300 + public static function cacheMethodIsAvailable()
  301 + {
  302 + if (!function_exists('memcache_add')) {
  303 + return false;
  304 + }
  305 +
  306 + return true;
  307 + }
  308 +}
  1 +<?php
  2 +
  3 +/**
  4 + * PHPExcel_CachedObjectStorage_Memory
  5 + *
  6 + * Copyright (c) 2006 - 2015 PHPExcel
  7 + *
  8 + * This library is free software; you can redistribute it and/or
  9 + * modify it under the terms of the GNU Lesser General Public
  10 + * License as published by the Free Software Foundation; either
  11 + * version 2.1 of the License, or (at your option) any later version.
  12 + *
  13 + * This library is distributed in the hope that it will be useful,
  14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  16 + * Lesser General Public License for more details.
  17 + *
  18 + * You should have received a copy of the GNU Lesser General Public
  19 + * License along with this library; if not, write to the Free Software
  20 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  21 + *
  22 + * @category PHPExcel
  23 + * @package PHPExcel_CachedObjectStorage
  24 + * @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel)
  25 + * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
  26 + * @version ##VERSION##, ##DATE##
  27 + */
  28 +class PHPExcel_CachedObjectStorage_Memory extends PHPExcel_CachedObjectStorage_CacheBase implements PHPExcel_CachedObjectStorage_ICache
  29 +{
  30 + /**
  31 + * Dummy method callable from CacheBase, but unused by Memory cache
  32 + *
  33 + * @return void
  34 + */
  35 + protected function storeData()
  36 + {
  37 + }
  38 +
  39 + /**
  40 + * Add or Update a cell in cache identified by coordinate address
  41 + *
  42 + * @param string $pCoord Coordinate address of the cell to update
  43 + * @param PHPExcel_Cell $cell Cell to update
  44 + * @return PHPExcel_Cell
  45 + * @throws PHPExcel_Exception
  46 + */
  47 + public function addCacheData($pCoord, PHPExcel_Cell $cell)
  48 + {
  49 + $this->cellCache[$pCoord] = $cell;
  50 +
  51 + // Set current entry to the new/updated entry
  52 + $this->currentObjectID = $pCoord;
  53 +
  54 + return $cell;
  55 + }
  56 +
  57 +
  58 + /**
  59 + * Get cell at a specific coordinate
  60 + *
  61 + * @param string $pCoord Coordinate of the cell
  62 + * @throws PHPExcel_Exception
  63 + * @return PHPExcel_Cell Cell that was found, or null if not found
  64 + */
  65 + public function getCacheData($pCoord)
  66 + {
  67 + // Check if the entry that has been requested actually exists
  68 + if (!isset($this->cellCache[$pCoord])) {
  69 + $this->currentObjectID = null;
  70 + // Return null if requested entry doesn't exist in cache
  71 + return null;
  72 + }
  73 +
  74 + // Set current entry to the requested entry
  75 + $this->currentObjectID = $pCoord;
  76 +
  77 + // Return requested entry
  78 + return $this->cellCache[$pCoord];
  79 + }
  80 +
  81 +
  82 + /**
  83 + * Clone the cell collection
  84 + *
  85 + * @param PHPExcel_Worksheet $parent The new worksheet
  86 + */
  87 + public function copyCellCollection(PHPExcel_Worksheet $parent)
  88 + {
  89 + parent::copyCellCollection($parent);
  90 +
  91 + $newCollection = array();
  92 + foreach ($this->cellCache as $k => &$cell) {
  93 + $newCollection[$k] = clone $cell;
  94 + $newCollection[$k]->attach($this);
  95 + }
  96 +
  97 + $this->cellCache = $newCollection;
  98 + }
  99 +
  100 + /**
  101 + * Clear the cell collection and disconnect from our parent
  102 + *
  103 + */
  104 + public function unsetWorksheetCells()
  105 + {
  106 + // Because cells are all stored as intact objects in memory, we need to detach each one from the parent
  107 + foreach ($this->cellCache as $k => &$cell) {
  108 + $cell->detach();
  109 + $this->cellCache[$k] = null;
  110 + }
  111 + unset($cell);
  112 +
  113 + $this->cellCache = array();
  114 +
  115 + // detach ourself from the worksheet, so that it can then delete this object successfully
  116 + $this->parent = null;
  117 + }
  118 +}
  1 +<?php
  2 +
  3 +/**
  4 + * PHPExcel_CachedObjectStorage_MemoryGZip
  5 + *
  6 + * Copyright (c) 2006 - 2015 PHPExcel
  7 + *
  8 + * This library is free software; you can redistribute it and/or
  9 + * modify it under the terms of the GNU Lesser General Public
  10 + * License as published by the Free Software Foundation; either
  11 + * version 2.1 of the License, or (at your option) any later version.
  12 + *
  13 + * This library is distributed in the hope that it will be useful,
  14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  16 + * Lesser General Public License for more details.
  17 + *
  18 + * You should have received a copy of the GNU Lesser General Public
  19 + * License along with this library; if not, write to the Free Software
  20 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  21 + *
  22 + * @category PHPExcel
  23 + * @package PHPExcel_CachedObjectStorage
  24 + * @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel)
  25 + * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
  26 + * @version ##VERSION##, ##DATE##
  27 + */
  28 +class PHPExcel_CachedObjectStorage_MemoryGZip extends PHPExcel_CachedObjectStorage_CacheBase implements PHPExcel_CachedObjectStorage_ICache
  29 +{
  30 + /**
  31 + * Store cell data in cache for the current cell object if it's "dirty",
  32 + * and the 'nullify' the current cell object
  33 + *
  34 + * @return void
  35 + * @throws PHPExcel_Exception
  36 + */
  37 + protected function storeData()
  38 + {
  39 + if ($this->currentCellIsDirty && !empty($this->currentObjectID)) {
  40 + $this->currentObject->detach();
  41 +
  42 + $this->cellCache[$this->currentObjectID] = gzdeflate(serialize($this->currentObject));
  43 + $this->currentCellIsDirty = false;
  44 + }
  45 + $this->currentObjectID = $this->currentObject = null;
  46 + }
  47 +
  48 +
  49 + /**
  50 + * Add or Update a cell in cache identified by coordinate address
  51 + *
  52 + * @param string $pCoord Coordinate address of the cell to update
  53 + * @param PHPExcel_Cell $cell Cell to update
  54 + * @return PHPExcel_Cell
  55 + * @throws PHPExcel_Exception
  56 + */
  57 + public function addCacheData($pCoord, PHPExcel_Cell $cell)
  58 + {
  59 + if (($pCoord !== $this->currentObjectID) && ($this->currentObjectID !== null)) {
  60 + $this->storeData();
  61 + }
  62 +
  63 + $this->currentObjectID = $pCoord;
  64 + $this->currentObject = $cell;
  65 + $this->currentCellIsDirty = true;
  66 +
  67 + return $cell;
  68 + }
  69 +
  70 +
  71 + /**
  72 + * Get cell at a specific coordinate
  73 + *
  74 + * @param string $pCoord Coordinate of the cell
  75 + * @throws PHPExcel_Exception
  76 + * @return PHPExcel_Cell Cell that was found, or null if not found
  77 + */
  78 + public function getCacheData($pCoord)
  79 + {
  80 + if ($pCoord === $this->currentObjectID) {
  81 + return $this->currentObject;
  82 + }
  83 + $this->storeData();
  84 +
  85 + // Check if the entry that has been requested actually exists
  86 + if (!isset($this->cellCache[$pCoord])) {
  87 + // Return null if requested entry doesn't exist in cache
  88 + return null;
  89 + }
  90 +
  91 + // Set current entry to the requested entry
  92 + $this->currentObjectID = $pCoord;
  93 + $this->currentObject = unserialize(gzinflate($this->cellCache[$pCoord]));
  94 + // Re-attach this as the cell's parent
  95 + $this->currentObject->attach($this);
  96 +
  97 + // Return requested entry
  98 + return $this->currentObject;
  99 + }
  100 +
  101 +
  102 + /**
  103 + * Get a list of all cell addresses currently held in cache
  104 + *
  105 + * @return string[]
  106 + */
  107 + public function getCellList()
  108 + {
  109 + if ($this->currentObjectID !== null) {
  110 + $this->storeData();
  111 + }
  112 +
  113 + return parent::getCellList();
  114 + }
  115 +
  116 +
  117 + /**
  118 + * Clear the cell collection and disconnect from our parent
  119 + *
  120 + * @return void
  121 + */
  122 + public function unsetWorksheetCells()
  123 + {
  124 + if (!is_null($this->currentObject)) {
  125 + $this->currentObject->detach();
  126 + $this->currentObject = $this->currentObjectID = null;
  127 + }
  128 + $this->cellCache = array();
  129 +
  130 + // detach ourself from the worksheet, so that it can then delete this object successfully
  131 + $this->parent = null;
  132 + }
  133 +}
  1 +<?php
  2 +
  3 +/**
  4 + * PHPExcel_CachedObjectStorage_MemorySerialized
  5 + *
  6 + * Copyright (c) 2006 - 2015 PHPExcel
  7 + *
  8 + * This library is free software; you can redistribute it and/or
  9 + * modify it under the terms of the GNU Lesser General Public
  10 + * License as published by the Free Software Foundation; either
  11 + * version 2.1 of the License, or (at your option) any later version.
  12 + *
  13 + * This library is distributed in the hope that it will be useful,
  14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  16 + * Lesser General Public License for more details.
  17 + *
  18 + * You should have received a copy of the GNU Lesser General Public
  19 + * License along with this library; if not, write to the Free Software
  20 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  21 + *
  22 + * @category PHPExcel
  23 + * @package PHPExcel_CachedObjectStorage
  24 + * @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel)
  25 + * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
  26 + * @version ##VERSION##, ##DATE##
  27 + */
  28 +class PHPExcel_CachedObjectStorage_MemorySerialized extends PHPExcel_CachedObjectStorage_CacheBase implements PHPExcel_CachedObjectStorage_ICache
  29 +{
  30 + /**
  31 + * Store cell data in cache for the current cell object if it's "dirty",
  32 + * and the 'nullify' the current cell object
  33 + *
  34 + * @return void
  35 + * @throws PHPExcel_Exception
  36 + */
  37 + protected function storeData()
  38 + {
  39 + if ($this->currentCellIsDirty && !empty($this->currentObjectID)) {
  40 + $this->currentObject->detach();
  41 +
  42 + $this->cellCache[$this->currentObjectID] = serialize($this->currentObject);
  43 + $this->currentCellIsDirty = false;
  44 + }
  45 + $this->currentObjectID = $this->currentObject = null;
  46 + }
  47 +
  48 + /**
  49 + * Add or Update a cell in cache identified by coordinate address
  50 + *
  51 + * @param string $pCoord Coordinate address of the cell to update
  52 + * @param PHPExcel_Cell $cell Cell to update
  53 + * @return PHPExcel_Cell
  54 + * @throws PHPExcel_Exception
  55 + */
  56 + public function addCacheData($pCoord, PHPExcel_Cell $cell)
  57 + {
  58 + if (($pCoord !== $this->currentObjectID) && ($this->currentObjectID !== null)) {
  59 + $this->storeData();
  60 + }
  61 +
  62 + $this->currentObjectID = $pCoord;
  63 + $this->currentObject = $cell;
  64 + $this->currentCellIsDirty = true;
  65 +
  66 + return $cell;
  67 + }
  68 +
  69 + /**
  70 + * Get cell at a specific coordinate
  71 + *
  72 + * @param string $pCoord Coordinate of the cell
  73 + * @throws PHPExcel_Exception
  74 + * @return PHPExcel_Cell Cell that was found, or null if not found
  75 + */
  76 + public function getCacheData($pCoord)
  77 + {
  78 + if ($pCoord === $this->currentObjectID) {
  79 + return $this->currentObject;
  80 + }
  81 + $this->storeData();
  82 +
  83 + // Check if the entry that has been requested actually exists
  84 + if (!isset($this->cellCache[$pCoord])) {
  85 + // Return null if requested entry doesn't exist in cache
  86 + return null;
  87 + }
  88 +
  89 + // Set current entry to the requested entry
  90 + $this->currentObjectID = $pCoord;
  91 + $this->currentObject = unserialize($this->cellCache[$pCoord]);
  92 + // Re-attach this as the cell's parent
  93 + $this->currentObject->attach($this);
  94 +
  95 + // Return requested entry
  96 + return $this->currentObject;
  97 + }
  98 +
  99 + /**
  100 + * Get a list of all cell addresses currently held in cache
  101 + *
  102 + * @return string[]
  103 + */
  104 + public function getCellList()
  105 + {
  106 + if ($this->currentObjectID !== null) {
  107 + $this->storeData();
  108 + }
  109 +
  110 + return parent::getCellList();
  111 + }
  112 +
  113 + /**
  114 + * Clear the cell collection and disconnect from our parent
  115 + *
  116 + * @return void
  117 + */
  118 + public function unsetWorksheetCells()
  119 + {
  120 + if (!is_null($this->currentObject)) {
  121 + $this->currentObject->detach();
  122 + $this->currentObject = $this->currentObjectID = null;
  123 + }
  124 + $this->cellCache = array();
  125 +
  126 + // detach ourself from the worksheet, so that it can then delete this object successfully
  127 + $this->parent = null;
  128 + }
  129 +}
  1 +<?php
  2 +
  3 +/**
  4 + * PHPExcel_CachedObjectStorage_PHPTemp
  5 + *
  6 + * Copyright (c) 2006 - 2015 PHPExcel
  7 + *
  8 + * This library is free software; you can redistribute it and/or
  9 + * modify it under the terms of the GNU Lesser General Public
  10 + * License as published by the Free Software Foundation; either
  11 + * version 2.1 of the License, or (at your option) any later version.
  12 + *
  13 + * This library is distributed in the hope that it will be useful,
  14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  16 + * Lesser General Public License for more details.
  17 + *
  18 + * You should have received a copy of the GNU Lesser General Public
  19 + * License along with this library; if not, write to the Free Software
  20 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  21 + *
  22 + * @category PHPExcel
  23 + * @package PHPExcel_CachedObjectStorage
  24 + * @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel)
  25 + * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
  26 + * @version ##VERSION##, ##DATE##
  27 + */
  28 +class PHPExcel_CachedObjectStorage_PHPTemp extends PHPExcel_CachedObjectStorage_CacheBase implements PHPExcel_CachedObjectStorage_ICache
  29 +{
  30 + /**
  31 + * Name of the file for this cache
  32 + *
  33 + * @var string
  34 + */
  35 + private $fileHandle = null;
  36 +
  37 + /**
  38 + * Memory limit to use before reverting to file cache
  39 + *
  40 + * @var integer
  41 + */
  42 + private $memoryCacheSize = null;
  43 +
  44 + /**
  45 + * Store cell data in cache for the current cell object if it's "dirty",
  46 + * and the 'nullify' the current cell object
  47 + *
  48 + * @return void
  49 + * @throws PHPExcel_Exception
  50 + */
  51 + protected function storeData()
  52 + {
  53 + if ($this->currentCellIsDirty && !empty($this->currentObjectID)) {
  54 + $this->currentObject->detach();
  55 +
  56 + fseek($this->fileHandle, 0, SEEK_END);
  57 +
  58 + $this->cellCache[$this->currentObjectID] = array(
  59 + 'ptr' => ftell($this->fileHandle),
  60 + 'sz' => fwrite($this->fileHandle, serialize($this->currentObject))
  61 + );
  62 + $this->currentCellIsDirty = false;
  63 + }
  64 + $this->currentObjectID = $this->currentObject = null;
  65 + }
  66 +
  67 +
  68 + /**
  69 + * Add or Update a cell in cache identified by coordinate address
  70 + *
  71 + * @param string $pCoord Coordinate address of the cell to update
  72 + * @param PHPExcel_Cell $cell Cell to update
  73 + * @return PHPExcel_Cell
  74 + * @throws PHPExcel_Exception
  75 + */
  76 + public function addCacheData($pCoord, PHPExcel_Cell $cell)
  77 + {
  78 + if (($pCoord !== $this->currentObjectID) && ($this->currentObjectID !== null)) {
  79 + $this->storeData();
  80 + }
  81 +
  82 + $this->currentObjectID = $pCoord;
  83 + $this->currentObject = $cell;
  84 + $this->currentCellIsDirty = true;
  85 +
  86 + return $cell;
  87 + }
  88 +
  89 +
  90 + /**
  91 + * Get cell at a specific coordinate
  92 + *
  93 + * @param string $pCoord Coordinate of the cell
  94 + * @throws PHPExcel_Exception
  95 + * @return PHPExcel_Cell Cell that was found, or null if not found
  96 + */
  97 + public function getCacheData($pCoord)
  98 + {
  99 + if ($pCoord === $this->currentObjectID) {
  100 + return $this->currentObject;
  101 + }
  102 + $this->storeData();
  103 +
  104 + // Check if the entry that has been requested actually exists
  105 + if (!isset($this->cellCache[$pCoord])) {
  106 + // Return null if requested entry doesn't exist in cache
  107 + return null;
  108 + }
  109 +
  110 + // Set current entry to the requested entry
  111 + $this->currentObjectID = $pCoord;
  112 + fseek($this->fileHandle, $this->cellCache[$pCoord]['ptr']);
  113 + $this->currentObject = unserialize(fread($this->fileHandle, $this->cellCache[$pCoord]['sz']));
  114 + // Re-attach this as the cell's parent
  115 + $this->currentObject->attach($this);
  116 +
  117 + // Return requested entry
  118 + return $this->currentObject;
  119 + }
  120 +
  121 + /**
  122 + * Get a list of all cell addresses currently held in cache
  123 + *
  124 + * @return string[]
  125 + */
  126 + public function getCellList()
  127 + {
  128 + if ($this->currentObjectID !== null) {
  129 + $this->storeData();
  130 + }
  131 +
  132 + return parent::getCellList();
  133 + }
  134 +
  135 + /**
  136 + * Clone the cell collection
  137 + *
  138 + * @param PHPExcel_Worksheet $parent The new worksheet
  139 + * @return void
  140 + */
  141 + public function copyCellCollection(PHPExcel_Worksheet $parent)
  142 + {
  143 + parent::copyCellCollection($parent);
  144 + // Open a new stream for the cell cache data
  145 + $newFileHandle = fopen('php://temp/maxmemory:' . $this->memoryCacheSize, 'a+');
  146 + // Copy the existing cell cache data to the new stream
  147 + fseek($this->fileHandle, 0);
  148 + while (!feof($this->fileHandle)) {
  149 + fwrite($newFileHandle, fread($this->fileHandle, 1024));
  150 + }
  151 + $this->fileHandle = $newFileHandle;
  152 + }
  153 +
  154 + /**
  155 + * Clear the cell collection and disconnect from our parent
  156 + *
  157 + * @return void
  158 + */
  159 + public function unsetWorksheetCells()
  160 + {
  161 + if (!is_null($this->currentObject)) {
  162 + $this->currentObject->detach();
  163 + $this->currentObject = $this->currentObjectID = null;
  164 + }
  165 + $this->cellCache = array();
  166 +
  167 + // detach ourself from the worksheet, so that it can then delete this object successfully
  168 + $this->parent = null;
  169 +
  170 + // Close down the php://temp file
  171 + $this->__destruct();
  172 + }
  173 +
  174 + /**
  175 + * Initialise this new cell collection
  176 + *
  177 + * @param PHPExcel_Worksheet $parent The worksheet for this cell collection
  178 + * @param array of mixed $arguments Additional initialisation arguments
  179 + */
  180 + public function __construct(PHPExcel_Worksheet $parent, $arguments)
  181 + {
  182 + $this->memoryCacheSize = (isset($arguments['memoryCacheSize'])) ? $arguments['memoryCacheSize'] : '1MB';
  183 +
  184 + parent::__construct($parent);
  185 + if (is_null($this->fileHandle)) {
  186 + $this->fileHandle = fopen('php://temp/maxmemory:' . $this->memoryCacheSize, 'a+');
  187 + }
  188 + }
  189 +
  190 + /**
  191 + * Destroy this cell collection
  192 + */
  193 + public function __destruct()
  194 + {
  195 + if (!is_null($this->fileHandle)) {
  196 + fclose($this->fileHandle);
  197 + }
  198 + $this->fileHandle = null;
  199 + }
  200 +}
  1 +<?php
  2 +
  3 +/**
  4 + * PHPExcel_CachedObjectStorage_SQLite
  5 + *
  6 + * Copyright (c) 2006 - 2015 PHPExcel
  7 + *
  8 + * This library is free software; you can redistribute it and/or
  9 + * modify it under the terms of the GNU Lesser General Public
  10 + * License as published by the Free Software Foundation; either
  11 + * version 2.1 of the License, or (at your option) any later version.
  12 + *
  13 + * This library is distributed in the hope that it will be useful,
  14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  16 + * Lesser General Public License for more details.
  17 + *
  18 + * You should have received a copy of the GNU Lesser General Public
  19 + * License along with this library; if not, write to the Free Software
  20 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  21 + *
  22 + * @category PHPExcel
  23 + * @package PHPExcel_CachedObjectStorage
  24 + * @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel)
  25 + * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
  26 + * @version ##VERSION##, ##DATE##
  27 + */
  28 +class PHPExcel_CachedObjectStorage_SQLite extends PHPExcel_CachedObjectStorage_CacheBase implements PHPExcel_CachedObjectStorage_ICache
  29 +{
  30 + /**
  31 + * Database table name
  32 + *
  33 + * @var string
  34 + */
  35 + private $TableName = null;
  36 +
  37 + /**
  38 + * Database handle
  39 + *
  40 + * @var resource
  41 + */
  42 + private $DBHandle = null;
  43 +
  44 + /**
  45 + * Store cell data in cache for the current cell object if it's "dirty",
  46 + * and the 'nullify' the current cell object
  47 + *
  48 + * @return void
  49 + * @throws PHPExcel_Exception
  50 + */
  51 + protected function storeData()
  52 + {
  53 + if ($this->currentCellIsDirty && !empty($this->currentObjectID)) {
  54 + $this->currentObject->detach();
  55 +
  56 + if (!$this->DBHandle->queryExec("INSERT OR REPLACE INTO kvp_".$this->TableName." VALUES('".$this->currentObjectID."','".sqlite_escape_string(serialize($this->currentObject))."')")) {
  57 + throw new PHPExcel_Exception(sqlite_error_string($this->DBHandle->lastError()));
  58 + }
  59 + $this->currentCellIsDirty = false;
  60 + }
  61 + $this->currentObjectID = $this->currentObject = null;
  62 + }
  63 +
  64 + /**
  65 + * Add or Update a cell in cache identified by coordinate address
  66 + *
  67 + * @param string $pCoord Coordinate address of the cell to update
  68 + * @param PHPExcel_Cell $cell Cell to update
  69 + * @return PHPExcel_Cell
  70 + * @throws PHPExcel_Exception
  71 + */
  72 + public function addCacheData($pCoord, PHPExcel_Cell $cell)
  73 + {
  74 + if (($pCoord !== $this->currentObjectID) && ($this->currentObjectID !== null)) {
  75 + $this->storeData();
  76 + }
  77 +
  78 + $this->currentObjectID = $pCoord;
  79 + $this->currentObject = $cell;
  80 + $this->currentCellIsDirty = true;
  81 +
  82 + return $cell;
  83 + }
  84 +
  85 + /**
  86 + * Get cell at a specific coordinate
  87 + *
  88 + * @param string $pCoord Coordinate of the cell
  89 + * @throws PHPExcel_Exception
  90 + * @return PHPExcel_Cell Cell that was found, or null if not found
  91 + */
  92 + public function getCacheData($pCoord)
  93 + {
  94 + if ($pCoord === $this->currentObjectID) {
  95 + return $this->currentObject;
  96 + }
  97 + $this->storeData();
  98 +
  99 + $query = "SELECT value FROM kvp_".$this->TableName." WHERE id='".$pCoord."'";
  100 + $cellResultSet = $this->DBHandle->query($query, SQLITE_ASSOC);
  101 + if ($cellResultSet === false) {
  102 + throw new PHPExcel_Exception(sqlite_error_string($this->DBHandle->lastError()));
  103 + } elseif ($cellResultSet->numRows() == 0) {
  104 + // Return null if requested entry doesn't exist in cache
  105 + return null;
  106 + }
  107 +
  108 + // Set current entry to the requested entry
  109 + $this->currentObjectID = $pCoord;
  110 +
  111 + $cellResult = $cellResultSet->fetchSingle();
  112 + $this->currentObject = unserialize($cellResult);
  113 + // Re-attach this as the cell's parent
  114 + $this->currentObject->attach($this);
  115 +
  116 + // Return requested entry
  117 + return $this->currentObject;
  118 + }
  119 +
  120 + /**
  121 + * Is a value set for an indexed cell?
  122 + *
  123 + * @param string $pCoord Coordinate address of the cell to check
  124 + * @return boolean
  125 + */
  126 + public function isDataSet($pCoord)
  127 + {
  128 + if ($pCoord === $this->currentObjectID) {
  129 + return true;
  130 + }
  131 +
  132 + // Check if the requested entry exists in the cache
  133 + $query = "SELECT id FROM kvp_".$this->TableName." WHERE id='".$pCoord."'";
  134 + $cellResultSet = $this->DBHandle->query($query, SQLITE_ASSOC);
  135 + if ($cellResultSet === false) {
  136 + throw new PHPExcel_Exception(sqlite_error_string($this->DBHandle->lastError()));
  137 + } elseif ($cellResultSet->numRows() == 0) {
  138 + // Return null if requested entry doesn't exist in cache
  139 + return false;
  140 + }
  141 + return true;
  142 + }
  143 +
  144 + /**
  145 + * Delete a cell in cache identified by coordinate address
  146 + *
  147 + * @param string $pCoord Coordinate address of the cell to delete
  148 + * @throws PHPExcel_Exception
  149 + */
  150 + public function deleteCacheData($pCoord)
  151 + {
  152 + if ($pCoord === $this->currentObjectID) {
  153 + $this->currentObject->detach();
  154 + $this->currentObjectID = $this->currentObject = null;
  155 + }
  156 +
  157 + // Check if the requested entry exists in the cache
  158 + $query = "DELETE FROM kvp_".$this->TableName." WHERE id='".$pCoord."'";
  159 + if (!$this->DBHandle->queryExec($query)) {
  160 + throw new PHPExcel_Exception(sqlite_error_string($this->DBHandle->lastError()));
  161 + }
  162 +
  163 + $this->currentCellIsDirty = false;
  164 + }
  165 +
  166 + /**
  167 + * Move a cell object from one address to another
  168 + *
  169 + * @param string $fromAddress Current address of the cell to move
  170 + * @param string $toAddress Destination address of the cell to move
  171 + * @return boolean
  172 + */
  173 + public function moveCell($fromAddress, $toAddress)
  174 + {
  175 + if ($fromAddress === $this->currentObjectID) {
  176 + $this->currentObjectID = $toAddress;
  177 + }
  178 +
  179 + $query = "DELETE FROM kvp_".$this->TableName." WHERE id='".$toAddress."'";
  180 + $result = $this->DBHandle->exec($query);
  181 + if ($result === false) {
  182 + throw new PHPExcel_Exception($this->DBHandle->lastErrorMsg());
  183 + }
  184 +
  185 + $query = "UPDATE kvp_".$this->TableName." SET id='".$toAddress."' WHERE id='".$fromAddress."'";
  186 + $result = $this->DBHandle->exec($query);
  187 + if ($result === false) {
  188 + throw new PHPExcel_Exception($this->DBHandle->lastErrorMsg());
  189 + }
  190 +
  191 + return true;
  192 + }
  193 +
  194 + /**
  195 + * Get a list of all cell addresses currently held in cache
  196 + *
  197 + * @return string[]
  198 + */
  199 + public function getCellList()
  200 + {
  201 + if ($this->currentObjectID !== null) {
  202 + $this->storeData();
  203 + }
  204 +
  205 + $query = "SELECT id FROM kvp_".$this->TableName;
  206 + $cellIdsResult = $this->DBHandle->unbufferedQuery($query, SQLITE_ASSOC);
  207 + if ($cellIdsResult === false) {
  208 + throw new PHPExcel_Exception(sqlite_error_string($this->DBHandle->lastError()));
  209 + }
  210 +
  211 + $cellKeys = array();
  212 + foreach ($cellIdsResult as $row) {
  213 + $cellKeys[] = $row['id'];
  214 + }
  215 +
  216 + return $cellKeys;
  217 + }
  218 +
  219 + /**
  220 + * Clone the cell collection
  221 + *
  222 + * @param PHPExcel_Worksheet $parent The new worksheet
  223 + * @return void
  224 + */
  225 + public function copyCellCollection(PHPExcel_Worksheet $parent)
  226 + {
  227 + $this->currentCellIsDirty;
  228 + $this->storeData();
  229 +
  230 + // Get a new id for the new table name
  231 + $tableName = str_replace('.', '_', $this->getUniqueID());
  232 + if (!$this->DBHandle->queryExec('CREATE TABLE kvp_'.$tableName.' (id VARCHAR(12) PRIMARY KEY, value BLOB)
  233 + AS SELECT * FROM kvp_'.$this->TableName)
  234 + ) {
  235 + throw new PHPExcel_Exception(sqlite_error_string($this->DBHandle->lastError()));
  236 + }
  237 +
  238 + // Copy the existing cell cache file
  239 + $this->TableName = $tableName;
  240 + }
  241 +
  242 + /**
  243 + * Clear the cell collection and disconnect from our parent
  244 + *
  245 + * @return void
  246 + */
  247 + public function unsetWorksheetCells()
  248 + {
  249 + if (!is_null($this->currentObject)) {
  250 + $this->currentObject->detach();
  251 + $this->currentObject = $this->currentObjectID = null;
  252 + }
  253 + // detach ourself from the worksheet, so that it can then delete this object successfully
  254 + $this->parent = null;
  255 +
  256 + // Close down the temporary cache file
  257 + $this->__destruct();
  258 + }
  259 +
  260 + /**
  261 + * Initialise this new cell collection
  262 + *
  263 + * @param PHPExcel_Worksheet $parent The worksheet for this cell collection
  264 + */
  265 + public function __construct(PHPExcel_Worksheet $parent)
  266 + {
  267 + parent::__construct($parent);
  268 + if (is_null($this->DBHandle)) {
  269 + $this->TableName = str_replace('.', '_', $this->getUniqueID());
  270 + $_DBName = ':memory:';
  271 +
  272 + $this->DBHandle = new SQLiteDatabase($_DBName);
  273 + if ($this->DBHandle === false) {
  274 + throw new PHPExcel_Exception(sqlite_error_string($this->DBHandle->lastError()));
  275 + }
  276 + if (!$this->DBHandle->queryExec('CREATE TABLE kvp_'.$this->TableName.' (id VARCHAR(12) PRIMARY KEY, value BLOB)')) {
  277 + throw new PHPExcel_Exception(sqlite_error_string($this->DBHandle->lastError()));
  278 + }
  279 + }
  280 + }
  281 +
  282 + /**
  283 + * Destroy this cell collection
  284 + */
  285 + public function __destruct()
  286 + {
  287 + if (!is_null($this->DBHandle)) {
  288 + $this->DBHandle->queryExec('DROP TABLE kvp_'.$this->TableName);
  289 + }
  290 + $this->DBHandle = null;
  291 + }
  292 +
  293 + /**
  294 + * Identify whether the caching method is currently available
  295 + * Some methods are dependent on the availability of certain extensions being enabled in the PHP build
  296 + *
  297 + * @return boolean
  298 + */
  299 + public static function cacheMethodIsAvailable()
  300 + {
  301 + if (!function_exists('sqlite_open')) {
  302 + return false;
  303 + }
  304 +
  305 + return true;
  306 + }
  307 +}
  1 +<?php
  2 +
  3 +/**
  4 + * PHPExcel_CachedObjectStorage_SQLite3
  5 + *
  6 + * Copyright (c) 2006 - 2015 PHPExcel
  7 + *
  8 + * This library is free software; you can redistribute it and/or
  9 + * modify it under the terms of the GNU Lesser General Public
  10 + * License as published by the Free Software Foundation; either
  11 + * version 2.1 of the License, or (at your option) any later version.
  12 + *
  13 + * This library is distributed in the hope that it will be useful,
  14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  16 + * Lesser General Public License for more details.
  17 + *
  18 + * You should have received a copy of the GNU Lesser General Public
  19 + * License along with this library; if not, write to the Free Software
  20 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  21 + *
  22 + * @category PHPExcel
  23 + * @package PHPExcel_CachedObjectStorage
  24 + * @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel)
  25 + * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
  26 + * @version ##VERSION##, ##DATE##
  27 + */
  28 +class PHPExcel_CachedObjectStorage_SQLite3 extends PHPExcel_CachedObjectStorage_CacheBase implements PHPExcel_CachedObjectStorage_ICache
  29 +{
  30 + /**
  31 + * Database table name
  32 + *
  33 + * @var string
  34 + */
  35 + private $TableName = null;
  36 +
  37 + /**
  38 + * Database handle
  39 + *
  40 + * @var resource
  41 + */
  42 + private $DBHandle = null;
  43 +
  44 + /**
  45 + * Prepared statement for a SQLite3 select query
  46 + *
  47 + * @var SQLite3Stmt
  48 + */
  49 + private $selectQuery;
  50 +
  51 + /**
  52 + * Prepared statement for a SQLite3 insert query
  53 + *
  54 + * @var SQLite3Stmt
  55 + */
  56 + private $insertQuery;
  57 +
  58 + /**
  59 + * Prepared statement for a SQLite3 update query
  60 + *
  61 + * @var SQLite3Stmt
  62 + */
  63 + private $updateQuery;
  64 +
  65 + /**
  66 + * Prepared statement for a SQLite3 delete query
  67 + *
  68 + * @var SQLite3Stmt
  69 + */
  70 + private $deleteQuery;
  71 +
  72 + /**
  73 + * Store cell data in cache for the current cell object if it's "dirty",
  74 + * and the 'nullify' the current cell object
  75 + *
  76 + * @return void
  77 + * @throws PHPExcel_Exception
  78 + */
  79 + protected function storeData()
  80 + {
  81 + if ($this->currentCellIsDirty && !empty($this->currentObjectID)) {
  82 + $this->currentObject->detach();
  83 +
  84 + $this->insertQuery->bindValue('id', $this->currentObjectID, SQLITE3_TEXT);
  85 + $this->insertQuery->bindValue('data', serialize($this->currentObject), SQLITE3_BLOB);
  86 + $result = $this->insertQuery->execute();
  87 + if ($result === false) {
  88 + throw new PHPExcel_Exception($this->DBHandle->lastErrorMsg());
  89 + }
  90 + $this->currentCellIsDirty = false;
  91 + }
  92 + $this->currentObjectID = $this->currentObject = null;
  93 + }
  94 +
  95 + /**
  96 + * Add or Update a cell in cache identified by coordinate address
  97 + *
  98 + * @param string $pCoord Coordinate address of the cell to update
  99 + * @param PHPExcel_Cell $cell Cell to update
  100 + * @return PHPExcel_Cell
  101 + * @throws PHPExcel_Exception
  102 + */
  103 + public function addCacheData($pCoord, PHPExcel_Cell $cell)
  104 + {
  105 + if (($pCoord !== $this->currentObjectID) && ($this->currentObjectID !== null)) {
  106 + $this->storeData();
  107 + }
  108 +
  109 + $this->currentObjectID = $pCoord;
  110 + $this->currentObject = $cell;
  111 + $this->currentCellIsDirty = true;
  112 +
  113 + return $cell;
  114 + }
  115 +
  116 + /**
  117 + * Get cell at a specific coordinate
  118 + *
  119 + * @param string $pCoord Coordinate of the cell
  120 + * @throws PHPExcel_Exception
  121 + * @return PHPExcel_Cell Cell that was found, or null if not found
  122 + */
  123 + public function getCacheData($pCoord)
  124 + {
  125 + if ($pCoord === $this->currentObjectID) {
  126 + return $this->currentObject;
  127 + }
  128 + $this->storeData();
  129 +
  130 + $this->selectQuery->bindValue('id', $pCoord, SQLITE3_TEXT);
  131 + $cellResult = $this->selectQuery->execute();
  132 + if ($cellResult === false) {
  133 + throw new PHPExcel_Exception($this->DBHandle->lastErrorMsg());
  134 + }
  135 + $cellData = $cellResult->fetchArray(SQLITE3_ASSOC);
  136 + if ($cellData === false) {
  137 + // Return null if requested entry doesn't exist in cache
  138 + return null;
  139 + }
  140 +
  141 + // Set current entry to the requested entry
  142 + $this->currentObjectID = $pCoord;
  143 +
  144 + $this->currentObject = unserialize($cellData['value']);
  145 + // Re-attach this as the cell's parent
  146 + $this->currentObject->attach($this);
  147 +
  148 + // Return requested entry
  149 + return $this->currentObject;
  150 + }
  151 +
  152 + /**
  153 + * Is a value set for an indexed cell?
  154 + *
  155 + * @param string $pCoord Coordinate address of the cell to check
  156 + * @return boolean
  157 + */
  158 + public function isDataSet($pCoord)
  159 + {
  160 + if ($pCoord === $this->currentObjectID) {
  161 + return true;
  162 + }
  163 +
  164 + // Check if the requested entry exists in the cache
  165 + $this->selectQuery->bindValue('id', $pCoord, SQLITE3_TEXT);
  166 + $cellResult = $this->selectQuery->execute();
  167 + if ($cellResult === false) {
  168 + throw new PHPExcel_Exception($this->DBHandle->lastErrorMsg());
  169 + }
  170 + $cellData = $cellResult->fetchArray(SQLITE3_ASSOC);
  171 +
  172 + return ($cellData === false) ? false : true;
  173 + }
  174 +
  175 + /**
  176 + * Delete a cell in cache identified by coordinate address
  177 + *
  178 + * @param string $pCoord Coordinate address of the cell to delete
  179 + * @throws PHPExcel_Exception
  180 + */
  181 + public function deleteCacheData($pCoord)
  182 + {
  183 + if ($pCoord === $this->currentObjectID) {
  184 + $this->currentObject->detach();
  185 + $this->currentObjectID = $this->currentObject = null;
  186 + }
  187 +
  188 + // Check if the requested entry exists in the cache
  189 + $this->deleteQuery->bindValue('id', $pCoord, SQLITE3_TEXT);
  190 + $result = $this->deleteQuery->execute();
  191 + if ($result === false) {
  192 + throw new PHPExcel_Exception($this->DBHandle->lastErrorMsg());
  193 + }
  194 +
  195 + $this->currentCellIsDirty = false;
  196 + }
  197 +
  198 + /**
  199 + * Move a cell object from one address to another
  200 + *
  201 + * @param string $fromAddress Current address of the cell to move
  202 + * @param string $toAddress Destination address of the cell to move
  203 + * @return boolean
  204 + */
  205 + public function moveCell($fromAddress, $toAddress)
  206 + {
  207 + if ($fromAddress === $this->currentObjectID) {
  208 + $this->currentObjectID = $toAddress;
  209 + }
  210 +
  211 + $this->deleteQuery->bindValue('id', $toAddress, SQLITE3_TEXT);
  212 + $result = $this->deleteQuery->execute();
  213 + if ($result === false) {
  214 + throw new PHPExcel_Exception($this->DBHandle->lastErrorMsg());
  215 + }
  216 +
  217 + $this->updateQuery->bindValue('toid', $toAddress, SQLITE3_TEXT);
  218 + $this->updateQuery->bindValue('fromid', $fromAddress, SQLITE3_TEXT);
  219 + $result = $this->updateQuery->execute();
  220 + if ($result === false) {
  221 + throw new PHPExcel_Exception($this->DBHandle->lastErrorMsg());
  222 + }
  223 +
  224 + return true;
  225 + }
  226 +
  227 + /**
  228 + * Get a list of all cell addresses currently held in cache
  229 + *
  230 + * @return string[]
  231 + */
  232 + public function getCellList()
  233 + {
  234 + if ($this->currentObjectID !== null) {
  235 + $this->storeData();
  236 + }
  237 +
  238 + $query = "SELECT id FROM kvp_".$this->TableName;
  239 + $cellIdsResult = $this->DBHandle->query($query);
  240 + if ($cellIdsResult === false) {
  241 + throw new PHPExcel_Exception($this->DBHandle->lastErrorMsg());
  242 + }
  243 +
  244 + $cellKeys = array();
  245 + while ($row = $cellIdsResult->fetchArray(SQLITE3_ASSOC)) {
  246 + $cellKeys[] = $row['id'];
  247 + }
  248 +
  249 + return $cellKeys;
  250 + }
  251 +
  252 + /**
  253 + * Clone the cell collection
  254 + *
  255 + * @param PHPExcel_Worksheet $parent The new worksheet
  256 + * @return void
  257 + */
  258 + public function copyCellCollection(PHPExcel_Worksheet $parent)
  259 + {
  260 + $this->currentCellIsDirty;
  261 + $this->storeData();
  262 +
  263 + // Get a new id for the new table name
  264 + $tableName = str_replace('.', '_', $this->getUniqueID());
  265 + if (!$this->DBHandle->exec('CREATE TABLE kvp_'.$tableName.' (id VARCHAR(12) PRIMARY KEY, value BLOB)
  266 + AS SELECT * FROM kvp_'.$this->TableName)
  267 + ) {
  268 + throw new PHPExcel_Exception($this->DBHandle->lastErrorMsg());
  269 + }
  270 +
  271 + // Copy the existing cell cache file
  272 + $this->TableName = $tableName;
  273 + }
  274 +
  275 + /**
  276 + * Clear the cell collection and disconnect from our parent
  277 + *
  278 + * @return void
  279 + */
  280 + public function unsetWorksheetCells()
  281 + {
  282 + if (!is_null($this->currentObject)) {
  283 + $this->currentObject->detach();
  284 + $this->currentObject = $this->currentObjectID = null;
  285 + }
  286 + // detach ourself from the worksheet, so that it can then delete this object successfully
  287 + $this->parent = null;
  288 +
  289 + // Close down the temporary cache file
  290 + $this->__destruct();
  291 + }
  292 +
  293 + /**
  294 + * Initialise this new cell collection
  295 + *
  296 + * @param PHPExcel_Worksheet $parent The worksheet for this cell collection
  297 + */
  298 + public function __construct(PHPExcel_Worksheet $parent)
  299 + {
  300 + parent::__construct($parent);
  301 + if (is_null($this->DBHandle)) {
  302 + $this->TableName = str_replace('.', '_', $this->getUniqueID());
  303 + $_DBName = ':memory:';
  304 +
  305 + $this->DBHandle = new SQLite3($_DBName);
  306 + if ($this->DBHandle === false) {
  307 + throw new PHPExcel_Exception($this->DBHandle->lastErrorMsg());
  308 + }
  309 + if (!$this->DBHandle->exec('CREATE TABLE kvp_'.$this->TableName.' (id VARCHAR(12) PRIMARY KEY, value BLOB)')) {
  310 + throw new PHPExcel_Exception($this->DBHandle->lastErrorMsg());
  311 + }
  312 + }
  313 +
  314 + $this->selectQuery = $this->DBHandle->prepare("SELECT value FROM kvp_".$this->TableName." WHERE id = :id");
  315 + $this->insertQuery = $this->DBHandle->prepare("INSERT OR REPLACE INTO kvp_".$this->TableName." VALUES(:id,:data)");
  316 + $this->updateQuery = $this->DBHandle->prepare("UPDATE kvp_".$this->TableName." SET id=:toId WHERE id=:fromId");
  317 + $this->deleteQuery = $this->DBHandle->prepare("DELETE FROM kvp_".$this->TableName." WHERE id = :id");
  318 + }
  319 +
  320 + /**
  321 + * Destroy this cell collection
  322 + */
  323 + public function __destruct()
  324 + {
  325 + if (!is_null($this->DBHandle)) {
  326 + $this->DBHandle->exec('DROP TABLE kvp_'.$this->TableName);
  327 + $this->DBHandle->close();
  328 + }
  329 + $this->DBHandle = null;
  330 + }
  331 +
  332 + /**
  333 + * Identify whether the caching method is currently available
  334 + * Some methods are dependent on the availability of certain extensions being enabled in the PHP build
  335 + *
  336 + * @return boolean
  337 + */
  338 + public static function cacheMethodIsAvailable()
  339 + {
  340 + if (!class_exists('SQLite3', false)) {
  341 + return false;
  342 + }
  343 +
  344 + return true;
  345 + }
  346 +}
  1 +<?php
  2 +
  3 +/**
  4 + * PHPExcel_CachedObjectStorage_Wincache
  5 + *
  6 + * Copyright (c) 2006 - 2015 PHPExcel
  7 + *
  8 + * This library is free software; you can redistribute it and/or
  9 + * modify it under the terms of the GNU Lesser General Public
  10 + * License as published by the Free Software Foundation; either
  11 + * version 2.1 of the License, or (at your option) any later version.
  12 + *
  13 + * This library is distributed in the hope that it will be useful,
  14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  16 + * Lesser General Public License for more details.
  17 + *
  18 + * You should have received a copy of the GNU Lesser General Public
  19 + * License along with this library; if not, write to the Free Software
  20 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  21 + *
  22 + * @category PHPExcel
  23 + * @package PHPExcel_CachedObjectStorage
  24 + * @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel)
  25 + * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
  26 + * @version ##VERSION##, ##DATE##
  27 + */
  28 +class PHPExcel_CachedObjectStorage_Wincache extends PHPExcel_CachedObjectStorage_CacheBase implements PHPExcel_CachedObjectStorage_ICache
  29 +{
  30 + /**
  31 + * Prefix used to uniquely identify cache data for this worksheet
  32 + *
  33 + * @var string
  34 + */
  35 + private $cachePrefix = null;
  36 +
  37 + /**
  38 + * Cache timeout
  39 + *
  40 + * @var integer
  41 + */
  42 + private $cacheTime = 600;
  43 +
  44 +
  45 + /**
  46 + * Store cell data in cache for the current cell object if it's "dirty",
  47 + * and the 'nullify' the current cell object
  48 + *
  49 + * @return void
  50 + * @throws PHPExcel_Exception
  51 + */
  52 + protected function storeData()
  53 + {
  54 + if ($this->currentCellIsDirty && !empty($this->currentObjectID)) {
  55 + $this->currentObject->detach();
  56 +
  57 + $obj = serialize($this->currentObject);
  58 + if (wincache_ucache_exists($this->cachePrefix.$this->currentObjectID.'.cache')) {
  59 + if (!wincache_ucache_set($this->cachePrefix.$this->currentObjectID.'.cache', $obj, $this->cacheTime)) {
  60 + $this->__destruct();
  61 + throw new PHPExcel_Exception('Failed to store cell '.$this->currentObjectID.' in WinCache');
  62 + }
  63 + } else {
  64 + if (!wincache_ucache_add($this->cachePrefix.$this->currentObjectID.'.cache', $obj, $this->cacheTime)) {
  65 + $this->__destruct();
  66 + throw new PHPExcel_Exception('Failed to store cell '.$this->currentObjectID.' in WinCache');
  67 + }
  68 + }
  69 + $this->currentCellIsDirty = false;
  70 + }
  71 +
  72 + $this->currentObjectID = $this->currentObject = null;
  73 + }
  74 +
  75 + /**
  76 + * Add or Update a cell in cache identified by coordinate address
  77 + *
  78 + * @param string $pCoord Coordinate address of the cell to update
  79 + * @param PHPExcel_Cell $cell Cell to update
  80 + * @return PHPExcel_Cell
  81 + * @throws PHPExcel_Exception
  82 + */
  83 + public function addCacheData($pCoord, PHPExcel_Cell $cell)
  84 + {
  85 + if (($pCoord !== $this->currentObjectID) && ($this->currentObjectID !== null)) {
  86 + $this->storeData();
  87 + }
  88 + $this->cellCache[$pCoord] = true;
  89 +
  90 + $this->currentObjectID = $pCoord;
  91 + $this->currentObject = $cell;
  92 + $this->currentCellIsDirty = true;
  93 +
  94 + return $cell;
  95 + }
  96 +
  97 + /**
  98 + * Is a value set in the current PHPExcel_CachedObjectStorage_ICache for an indexed cell?
  99 + *
  100 + * @param string $pCoord Coordinate address of the cell to check
  101 + * @return boolean
  102 + */
  103 + public function isDataSet($pCoord)
  104 + {
  105 + // Check if the requested entry is the current object, or exists in the cache
  106 + if (parent::isDataSet($pCoord)) {
  107 + if ($this->currentObjectID == $pCoord) {
  108 + return true;
  109 + }
  110 + // Check if the requested entry still exists in cache
  111 + $success = wincache_ucache_exists($this->cachePrefix.$pCoord.'.cache');
  112 + if ($success === false) {
  113 + // Entry no longer exists in Wincache, so clear it from the cache array
  114 + parent::deleteCacheData($pCoord);
  115 + throw new PHPExcel_Exception('Cell entry '.$pCoord.' no longer exists in WinCache');
  116 + }
  117 + return true;
  118 + }
  119 + return false;
  120 + }
  121 +
  122 +
  123 + /**
  124 + * Get cell at a specific coordinate
  125 + *
  126 + * @param string $pCoord Coordinate of the cell
  127 + * @throws PHPExcel_Exception
  128 + * @return PHPExcel_Cell Cell that was found, or null if not found
  129 + */
  130 + public function getCacheData($pCoord)
  131 + {
  132 + if ($pCoord === $this->currentObjectID) {
  133 + return $this->currentObject;
  134 + }
  135 + $this->storeData();
  136 +
  137 + // Check if the entry that has been requested actually exists
  138 + $obj = null;
  139 + if (parent::isDataSet($pCoord)) {
  140 + $success = false;
  141 + $obj = wincache_ucache_get($this->cachePrefix.$pCoord.'.cache', $success);
  142 + if ($success === false) {
  143 + // Entry no longer exists in WinCache, so clear it from the cache array
  144 + parent::deleteCacheData($pCoord);
  145 + throw new PHPExcel_Exception('Cell entry '.$pCoord.' no longer exists in WinCache');
  146 + }
  147 + } else {
  148 + // Return null if requested entry doesn't exist in cache
  149 + return null;
  150 + }
  151 +
  152 + // Set current entry to the requested entry
  153 + $this->currentObjectID = $pCoord;
  154 + $this->currentObject = unserialize($obj);
  155 + // Re-attach this as the cell's parent
  156 + $this->currentObject->attach($this);
  157 +
  158 + // Return requested entry
  159 + return $this->currentObject;
  160 + }
  161 +
  162 +
  163 + /**
  164 + * Get a list of all cell addresses currently held in cache
  165 + *
  166 + * @return string[]
  167 + */
  168 + public function getCellList()
  169 + {
  170 + if ($this->currentObjectID !== null) {
  171 + $this->storeData();
  172 + }
  173 +
  174 + return parent::getCellList();
  175 + }
  176 +
  177 + /**
  178 + * Delete a cell in cache identified by coordinate address
  179 + *
  180 + * @param string $pCoord Coordinate address of the cell to delete
  181 + * @throws PHPExcel_Exception
  182 + */
  183 + public function deleteCacheData($pCoord)
  184 + {
  185 + // Delete the entry from Wincache
  186 + wincache_ucache_delete($this->cachePrefix.$pCoord.'.cache');
  187 +
  188 + // Delete the entry from our cell address array
  189 + parent::deleteCacheData($pCoord);
  190 + }
  191 +
  192 + /**
  193 + * Clone the cell collection
  194 + *
  195 + * @param PHPExcel_Worksheet $parent The new worksheet
  196 + * @return void
  197 + */
  198 + public function copyCellCollection(PHPExcel_Worksheet $parent)
  199 + {
  200 + parent::copyCellCollection($parent);
  201 + // Get a new id for the new file name
  202 + $baseUnique = $this->getUniqueID();
  203 + $newCachePrefix = substr(md5($baseUnique), 0, 8) . '.';
  204 + $cacheList = $this->getCellList();
  205 + foreach ($cacheList as $cellID) {
  206 + if ($cellID != $this->currentObjectID) {
  207 + $success = false;
  208 + $obj = wincache_ucache_get($this->cachePrefix.$cellID.'.cache', $success);
  209 + if ($success === false) {
  210 + // Entry no longer exists in WinCache, so clear it from the cache array
  211 + parent::deleteCacheData($cellID);
  212 + throw new PHPExcel_Exception('Cell entry '.$cellID.' no longer exists in Wincache');
  213 + }
  214 + if (!wincache_ucache_add($newCachePrefix.$cellID.'.cache', $obj, $this->cacheTime)) {
  215 + $this->__destruct();
  216 + throw new PHPExcel_Exception('Failed to store cell '.$cellID.' in Wincache');
  217 + }
  218 + }
  219 + }
  220 + $this->cachePrefix = $newCachePrefix;
  221 + }
  222 +
  223 +
  224 + /**
  225 + * Clear the cell collection and disconnect from our parent
  226 + *
  227 + * @return void
  228 + */
  229 + public function unsetWorksheetCells()
  230 + {
  231 + if (!is_null($this->currentObject)) {
  232 + $this->currentObject->detach();
  233 + $this->currentObject = $this->currentObjectID = null;
  234 + }
  235 +
  236 + // Flush the WinCache cache
  237 + $this->__destruct();
  238 +
  239 + $this->cellCache = array();
  240 +
  241 + // detach ourself from the worksheet, so that it can then delete this object successfully
  242 + $this->parent = null;
  243 + }
  244 +
  245 + /**
  246 + * Initialise this new cell collection
  247 + *
  248 + * @param PHPExcel_Worksheet $parent The worksheet for this cell collection
  249 + * @param array of mixed $arguments Additional initialisation arguments
  250 + */
  251 + public function __construct(PHPExcel_Worksheet $parent, $arguments)
  252 + {
  253 + $cacheTime = (isset($arguments['cacheTime'])) ? $arguments['cacheTime'] : 600;
  254 +
  255 + if (is_null($this->cachePrefix)) {
  256 + $baseUnique = $this->getUniqueID();
  257 + $this->cachePrefix = substr(md5($baseUnique), 0, 8).'.';
  258 + $this->cacheTime = $cacheTime;
  259 +
  260 + parent::__construct($parent);
  261 + }
  262 + }
  263 +
  264 + /**
  265 + * Destroy this cell collection
  266 + */
  267 + public function __destruct()
  268 + {
  269 + $cacheList = $this->getCellList();
  270 + foreach ($cacheList as $cellID) {
  271 + wincache_ucache_delete($this->cachePrefix.$cellID.'.cache');
  272 + }
  273 + }
  274 +
  275 + /**
  276 + * Identify whether the caching method is currently available
  277 + * Some methods are dependent on the availability of certain extensions being enabled in the PHP build
  278 + *
  279 + * @return boolean
  280 + */
  281 + public static function cacheMethodIsAvailable()
  282 + {
  283 + if (!function_exists('wincache_ucache_add')) {
  284 + return false;
  285 + }
  286 +
  287 + return true;
  288 + }
  289 +}