Version Description
- New super gallery cache function
Download this release
Release Info
Developer | robosoft |
Plugin | Gallery – Photo Gallery and Images Gallery |
Version | 2.7.0 |
Comparing to | |
See all releases |
Code changes from version 2.6.22 to 2.7.0
- includes/cache.php +33 -0
- includes/extensions/categoryPage/category.class.php +246 -0
- includes/extensions/categoryPage/category.init.php +23 -0
- includes/extensions/categoryPage/css/index.html +0 -0
- includes/extensions/categoryPage/css/style.css +161 -0
- includes/extensions/categoryPage/index.html +0 -0
- includes/extensions/categoryPage/js/index.html +0 -0
- includes/extensions/categoryPage/js/jquery.nestable.js +484 -0
- includes/extensions/categoryPage/js/script.js +92 -0
- includes/extensions/zip/Core/AbstractException.php +14 -0
- includes/extensions/zip/Core/AbstractZipArchive.php +1046 -0
- includes/extensions/zip/Core/ZipUtils.php +125 -0
- includes/extensions/zip/Core/index.html +0 -0
- includes/extensions/zip/Exception/BufferNotEmpty.php +46 -0
- includes/extensions/zip/Exception/HeaderPositionError.php +52 -0
- includes/extensions/zip/Exception/HeadersSent.php +52 -0
- includes/extensions/zip/Exception/IncompatiblePhpVersion.php +54 -0
- includes/extensions/zip/Exception/InvalidPhpConfiguration.php +58 -0
- includes/extensions/zip/Exception/LengthMismatch.php +51 -0
- includes/extensions/zip/Exception/index.html +0 -0
- includes/extensions/zip/File/Zip.php +187 -0
- includes/extensions/zip/File/index.html +0 -0
- includes/extensions/zip/Listener/ZipArchiveListener.php +29 -0
- includes/extensions/zip/Listener/index.html +0 -0
- includes/extensions/zip/Stream/ZipStream.php +204 -0
- includes/extensions/zip/Stream/index.html +0 -0
- includes/extensions/zip/index.html +0 -0
- includes/frontend/rbs_gallery_class.php +59 -12
- includes/options/cache.php +48 -0
- includes/options/rbs_gallery_options_images.php +7 -0
- includes/options/rbs_gallery_options_tools.php +3 -1
- includes/rbs_gallery_edit.php +2 -0
- includes/rbs_gallery_init.php +5 -1
- includes/rbs_gallery_settings.php +2 -4
- readme.txt +10 -2
- robogallery.php +4 -4
includes/cache.php
ADDED
@@ -0,0 +1,33 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/*
|
3 |
+
* Robo Gallery By Robosoft
|
4 |
+
* Contact: https://robosoft.co/robogallery/
|
5 |
+
* Copyright (c) 2014-2017, Robosoft. All rights reserved.
|
6 |
+
*/
|
7 |
+
|
8 |
+
if ( ! defined( 'ABSPATH' ) ) exit;
|
9 |
+
|
10 |
+
|
11 |
+
function robo_gallery_save_gallery( $post_id, $post, $update ) {
|
12 |
+
|
13 |
+
$post_type = get_post_type($post_id);
|
14 |
+
|
15 |
+
if ( ROBO_GALLERY_TYPE_POST != $post_type ) return;
|
16 |
+
|
17 |
+
delete_transient( 'robo_gallery_cached_id'. $post_id ) ;
|
18 |
+
}
|
19 |
+
add_action( 'save_post', 'robo_gallery_save_gallery', 10, 3 );
|
20 |
+
|
21 |
+
|
22 |
+
function robo_gallery_new_gallery( $post_id, $post, $update ) {
|
23 |
+
|
24 |
+
if( wp_is_post_revision( $post_id ) ) return;
|
25 |
+
|
26 |
+
$post_type = get_post_type($post_id);
|
27 |
+
if ( ROBO_GALLERY_TYPE_POST != $post_type ) return;
|
28 |
+
|
29 |
+
/*add_post_meta($post_id, 'robo_gallery_cache', uniqid() );*/
|
30 |
+
|
31 |
+
}
|
32 |
+
add_action( 'wp_insert_post', 'robo_gallery_new_gallery', 10, 3 );
|
33 |
+
|
includes/extensions/categoryPage/category.class.php
ADDED
@@ -0,0 +1,246 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/*
|
3 |
+
* Robo Gallery
|
4 |
+
* Version: 1.0
|
5 |
+
* By Robosoft
|
6 |
+
*
|
7 |
+
* Contact: https://robosoft.co/robogallery/
|
8 |
+
* Created: 2015
|
9 |
+
* Licensed under the GPLv2 license - http://opensource.org/licenses/gpl-2.0.php
|
10 |
+
*
|
11 |
+
* Copyright (c) 2014-2016, Robosoft. All rights reserved.
|
12 |
+
* Available only in https://robosoft.co/robogallery/
|
13 |
+
*/
|
14 |
+
|
15 |
+
if ( ! defined( 'ABSPATH' ) ) exit;
|
16 |
+
|
17 |
+
class ROBO_GALLERY_CATEGORY_PAGE{
|
18 |
+
|
19 |
+
protected $postType;
|
20 |
+
|
21 |
+
protected $postTypeParams;
|
22 |
+
|
23 |
+
protected $assetsUri;
|
24 |
+
|
25 |
+
protected $currentPostOrder;
|
26 |
+
|
27 |
+
public function __construct($postType){ //, array $postTypeParams
|
28 |
+
|
29 |
+
$this->postType = $postType;
|
30 |
+
$this->postTypeParams = array();
|
31 |
+
//$this->postTypeParams = $postTypeParams;
|
32 |
+
$this->assetsUri = plugin_dir_url(__FILE__);
|
33 |
+
|
34 |
+
|
35 |
+
$this->enqueueScripts();
|
36 |
+
// add_action("wp_ajax_hierarchy_{$this->postType}_meta_box", array($this, 'ajaxMetaBoxAttributes'));
|
37 |
+
|
38 |
+
//add_action("wp_ajax_hierarchy_{$this->postType}_dialog", array($this, 'ajaxDialog'));
|
39 |
+
|
40 |
+
$this->ajaxDialog ();
|
41 |
+
|
42 |
+
add_action("wp_ajax_hierarchy_{$this->postType}_dialog_save", array($this, 'ajaxDialogSave'));
|
43 |
+
|
44 |
+
}
|
45 |
+
|
46 |
+
|
47 |
+
|
48 |
+
|
49 |
+
public function enqueueScripts(){
|
50 |
+
wp_enqueue_style('wp-jquery-ui-dialog');
|
51 |
+
wp_enqueue_style(
|
52 |
+
'hierarchy-post-attributes-style',
|
53 |
+
$this->assetsUri . 'css/style.css',
|
54 |
+
array('wp-jquery-ui-dialog')
|
55 |
+
);
|
56 |
+
|
57 |
+
wp_enqueue_script('jquery-ui-dialog');
|
58 |
+
wp_enqueue_script(
|
59 |
+
'hierarchy-post-attributes-nestable-js',
|
60 |
+
$this->assetsUri . 'js/jquery.nestable.js',
|
61 |
+
array('jquery-ui-dialog'),
|
62 |
+
false,
|
63 |
+
true
|
64 |
+
);
|
65 |
+
wp_enqueue_script(
|
66 |
+
'hierarchy-post-attributes-js',
|
67 |
+
$this->assetsUri . 'js/script.js',
|
68 |
+
array('jquery-ui-dialog', 'hierarchy-post-attributes-nestable-js'),
|
69 |
+
false,
|
70 |
+
true
|
71 |
+
);
|
72 |
+
|
73 |
+
$postTypeObject = get_post_type_object($this->postType);
|
74 |
+
wp_localize_script(
|
75 |
+
'hierarchy-post-attributes-js',
|
76 |
+
'hierarchyPostAttributes',
|
77 |
+
array(
|
78 |
+
'ajaxUrl' => admin_url('admin-ajax.php'),
|
79 |
+
'metaBox' => array(
|
80 |
+
'action' => array(
|
81 |
+
'get' => "hierarchy_{$this->postType}_meta_box"
|
82 |
+
)
|
83 |
+
),
|
84 |
+
'dialog' => array(
|
85 |
+
'title' => __(sprintf('Edit hierarchy of %s', $postTypeObject->labels->name)),
|
86 |
+
'button' => array(
|
87 |
+
'save' => array(
|
88 |
+
'label' => __('Save')
|
89 |
+
),
|
90 |
+
'cancel' => array(
|
91 |
+
'label' => __('Cancel')
|
92 |
+
)
|
93 |
+
),
|
94 |
+
'action' => array(
|
95 |
+
'get' => "hierarchy_{$this->postType}_dialog",
|
96 |
+
'save' => "hierarchy_{$this->postType}_dialog_save",
|
97 |
+
),
|
98 |
+
),
|
99 |
+
'error' => array(
|
100 |
+
'title' => __('Error'),
|
101 |
+
'button' => array(
|
102 |
+
'ok' => array(
|
103 |
+
'label' => __('OK')
|
104 |
+
),
|
105 |
+
)
|
106 |
+
)
|
107 |
+
)
|
108 |
+
);
|
109 |
+
}
|
110 |
+
|
111 |
+
|
112 |
+
|
113 |
+
|
114 |
+
|
115 |
+
|
116 |
+
public function ajaxDialog() {
|
117 |
+
$this->checkPermission();
|
118 |
+
|
119 |
+
$postTree = $this->getPostTree(ROBO_GALLERY_TYPE_POST);
|
120 |
+
?>
|
121 |
+
<p>
|
122 |
+
<button class="save_category button button-primary"> Save</button>
|
123 |
+
</p>
|
124 |
+
<div class="wrapper-nestable-list" >
|
125 |
+
<div class="nestable-list dd">
|
126 |
+
<?php $this->theNestableList($postTree); ?>
|
127 |
+
</div>
|
128 |
+
<div class="nestable-list-spinner">
|
129 |
+
<img src="<?php echo admin_url('/images/spinner-2x.gif') ?>" />
|
130 |
+
</div>
|
131 |
+
</div>
|
132 |
+
<button class="save_category button button-primary"> Save</button>
|
133 |
+
<?php
|
134 |
+
|
135 |
+
//wp_die();
|
136 |
+
}
|
137 |
+
|
138 |
+
public function ajaxDialogSave() {
|
139 |
+
$this->checkPermission();
|
140 |
+
|
141 |
+
if (!isset($_POST['hierarchy_posts'])) {
|
142 |
+
header('HTTP/1.0 403 Forbidden');
|
143 |
+
echo 'Empty posts hierarchy data for saving';
|
144 |
+
die();
|
145 |
+
}
|
146 |
+
if (!is_array($_POST['hierarchy_posts'])) {
|
147 |
+
header('HTTP/1.0 403 Forbidden');
|
148 |
+
echo 'Wrong posts hierarchy data for saving';
|
149 |
+
die();
|
150 |
+
}
|
151 |
+
|
152 |
+
$hierarchyPosts = $_POST['hierarchy_posts'];
|
153 |
+
$this->currentPostOrder = 0;
|
154 |
+
foreach ($hierarchyPosts as $order => $postData) {
|
155 |
+
$this->updatePostHierarchy($postData);
|
156 |
+
}
|
157 |
+
}
|
158 |
+
|
159 |
+
|
160 |
+
protected function getPostTree($postType){
|
161 |
+
$args = array(
|
162 |
+
'post_type' => $postType,
|
163 |
+
'post_status' => 'publish',
|
164 |
+
'posts_per_page' => -1,
|
165 |
+
'orderby' => 'menu_order',
|
166 |
+
'order' => 'ASC'
|
167 |
+
);
|
168 |
+
$postMap = array();
|
169 |
+
$postTree = array();
|
170 |
+
|
171 |
+
foreach (get_posts($args) as $post) {
|
172 |
+
if (isset($postMap[$post->ID])) {
|
173 |
+
$postMap[$post->ID]['post'] = $post;
|
174 |
+
$postData = &$postMap[$post->ID];
|
175 |
+
} else {
|
176 |
+
$postData = array('post' => $post, 'children' => array());
|
177 |
+
$postMap[$post->ID] = &$postData;
|
178 |
+
}
|
179 |
+
if (0 == $post->post_parent) {
|
180 |
+
$postTree["{$post->menu_order}-{$post->ID}"] = &$postData;
|
181 |
+
} else {
|
182 |
+
$postMap[$post->post_parent]['children'][$post->ID] = &$postData;
|
183 |
+
}
|
184 |
+
unset($postData);
|
185 |
+
}
|
186 |
+
|
187 |
+
// Adding children posts with lost parent to tree
|
188 |
+
foreach ($postMap as &$postData) {
|
189 |
+
if (!isset($postData['post']) && is_array($postData['children'])) {
|
190 |
+
foreach ($postData['children'] as &$childPostData) {
|
191 |
+
$childPost = $childPostData['post'];
|
192 |
+
$postTree["{$childPost->menu_order}-{$childPost->ID}"] = &$childPostData;
|
193 |
+
}
|
194 |
+
}
|
195 |
+
}
|
196 |
+
asort($postTree);
|
197 |
+
|
198 |
+
return $postTree;
|
199 |
+
}
|
200 |
+
|
201 |
+
|
202 |
+
protected function theNestableList(array $tree){
|
203 |
+
?>
|
204 |
+
<ol class="dd-list">
|
205 |
+
<?php foreach ($tree as $item) : ?>
|
206 |
+
<li class="dd-item" data-id="<?php echo $item['post']->ID; ?>">
|
207 |
+
<div class="dd-handle">
|
208 |
+
<?php
|
209 |
+
$title = esc_attr($item['post']->post_title);
|
210 |
+
echo "{$title} [{$item['post']->ID}: {$item['post']->post_name}]" ; ?>
|
211 |
+
</div>
|
212 |
+
<?php if (!empty($item['children'])) : ?>
|
213 |
+
<?php $this->theNestableList($item['children']); ?>
|
214 |
+
<?php endif; ?>
|
215 |
+
</li>
|
216 |
+
<?php endforeach; ?>
|
217 |
+
</ol>
|
218 |
+
<?php
|
219 |
+
}
|
220 |
+
|
221 |
+
|
222 |
+
protected function checkPermission(){
|
223 |
+
$postTypeObject = get_post_type_object($this->postType);
|
224 |
+
if (!current_user_can($postTypeObject->cap->edit_posts)) {
|
225 |
+
header('HTTP/1.0 403 Forbidden');
|
226 |
+
echo sprintf("You don't have permission for editing this %s", $postTypeObject->labels->name);
|
227 |
+
die();
|
228 |
+
}
|
229 |
+
}
|
230 |
+
|
231 |
+
|
232 |
+
protected function updatePostHierarchy($postData, $parentId = 0){
|
233 |
+
$this->currentPostOrder++;
|
234 |
+
wp_update_post(array(
|
235 |
+
'ID' => absint($postData['id']),
|
236 |
+
'post_parent' => absint($parentId),
|
237 |
+
'menu_order' => $this->currentPostOrder
|
238 |
+
));
|
239 |
+
|
240 |
+
if (!empty($postData['children'])) {
|
241 |
+
foreach ($postData['children'] as $childPostData) {
|
242 |
+
$this->updatePostHierarchy($childPostData, $postData['id']);
|
243 |
+
}
|
244 |
+
}
|
245 |
+
}
|
246 |
+
}
|
includes/extensions/categoryPage/category.init.php
ADDED
@@ -0,0 +1,23 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/*
|
3 |
+
* Robo Gallery
|
4 |
+
* Version: 1.0
|
5 |
+
* By Robosoft
|
6 |
+
*
|
7 |
+
* Contact: https://robosoft.co/robogallery/
|
8 |
+
* Created: 2015
|
9 |
+
* Licensed under the GPLv2 license - http://opensource.org/licenses/gpl-2.0.php
|
10 |
+
*
|
11 |
+
* Copyright (c) 2014-2016, Robosoft. All rights reserved.
|
12 |
+
* Available only in https://robosoft.co/robogallery/
|
13 |
+
*/
|
14 |
+
|
15 |
+
if ( ! defined( 'ABSPATH' ) ) exit;
|
16 |
+
|
17 |
+
/*if(!function_exists('rbs_gallery_category_init')){
|
18 |
+
function rbs_gallery_category_init(){*/
|
19 |
+
rbs_gallery_include('category.class.php', plugin_dir_path( __FILE__ ) );
|
20 |
+
new ROBO_GALLERY_CATEGORY_PAGE( ROBO_GALLERY_TYPE_POST );
|
21 |
+
/* }
|
22 |
+
add_action( 'init', 'rbs_gallery_category_init' );
|
23 |
+
}*/
|
includes/extensions/categoryPage/css/index.html
ADDED
File without changes
|
includes/extensions/categoryPage/css/style.css
ADDED
@@ -0,0 +1,161 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
.nestable-list.dd,
|
2 |
+
.nestable-list .dd {
|
3 |
+
position: relative;
|
4 |
+
display: block;
|
5 |
+
margin: 0;
|
6 |
+
padding: 0;
|
7 |
+
list-style: none;
|
8 |
+
font-size: 13px;
|
9 |
+
line-height: 20px;
|
10 |
+
}
|
11 |
+
|
12 |
+
.nestable-list .dd-list {
|
13 |
+
display: block;
|
14 |
+
position: relative;
|
15 |
+
margin: 0;
|
16 |
+
padding: 0;
|
17 |
+
list-style: none;
|
18 |
+
}
|
19 |
+
|
20 |
+
.nestable-list .dd-list .dd-list {
|
21 |
+
padding-left: 30px;
|
22 |
+
}
|
23 |
+
|
24 |
+
.nestable-list .dd-collapsed .dd-list {
|
25 |
+
display: none;
|
26 |
+
}
|
27 |
+
|
28 |
+
.nestable-list .dd-item,
|
29 |
+
.nestable-list .dd-empty,
|
30 |
+
.nestable-list .dd-placeholder {
|
31 |
+
display: block;
|
32 |
+
position: relative;
|
33 |
+
margin: 0;
|
34 |
+
padding: 0;
|
35 |
+
min-height: 20px;
|
36 |
+
font-size: 13px;
|
37 |
+
line-height: 20px;
|
38 |
+
}
|
39 |
+
|
40 |
+
.nestable-list .dd-handle {
|
41 |
+
display: block;
|
42 |
+
height: 30px;
|
43 |
+
margin: 5px 0;
|
44 |
+
padding: 5px 10px;
|
45 |
+
color: #333;
|
46 |
+
text-decoration: none;
|
47 |
+
font-weight: bold;
|
48 |
+
border: 1px solid #ccc;
|
49 |
+
background: #fafafa;
|
50 |
+
background: -webkit-linear-gradient(top, #fafafa 0%, #eee 100%);
|
51 |
+
background: -moz-linear-gradient(top, #fafafa 0%, #eee 100%);
|
52 |
+
background: linear-gradient(top, #fafafa 0%, #eee 100%);
|
53 |
+
-webkit-border-radius: 3px;
|
54 |
+
border-radius: 3px;
|
55 |
+
box-sizing: border-box;
|
56 |
+
-moz-box-sizing: border-box;
|
57 |
+
}
|
58 |
+
|
59 |
+
.nestable-list .dd-handle:hover {
|
60 |
+
color: #2ea8e5;
|
61 |
+
background: #fff;
|
62 |
+
}
|
63 |
+
|
64 |
+
.nestable-list .dd-item > button {
|
65 |
+
display: block;
|
66 |
+
position: relative;
|
67 |
+
cursor: pointer;
|
68 |
+
float: left;
|
69 |
+
width: 25px;
|
70 |
+
height: 20px;
|
71 |
+
margin: 5px 0;
|
72 |
+
padding: 0;
|
73 |
+
text-indent: 100%;
|
74 |
+
white-space: nowrap;
|
75 |
+
overflow: hidden;
|
76 |
+
border: 0;
|
77 |
+
background: transparent;
|
78 |
+
font-size: 12px;
|
79 |
+
line-height: 1;
|
80 |
+
text-align: center;
|
81 |
+
font-weight: bold;
|
82 |
+
}
|
83 |
+
|
84 |
+
.nestable-list .dd-item > button:before {
|
85 |
+
content: '+';
|
86 |
+
display: block;
|
87 |
+
position: absolute;
|
88 |
+
width: 100%;
|
89 |
+
text-align: center;
|
90 |
+
text-indent: 0;
|
91 |
+
}
|
92 |
+
|
93 |
+
.nestable-list .dd-item > button[data-action="collapse"]:before {
|
94 |
+
content: '-';
|
95 |
+
}
|
96 |
+
|
97 |
+
.nestable-list .dd-placeholder,
|
98 |
+
.nestable-list .dd-empty {
|
99 |
+
margin: 5px 0;
|
100 |
+
padding: 0;
|
101 |
+
min-height: 30px;
|
102 |
+
background: #f2fbff;
|
103 |
+
border: 1px dashed #b6bcbf;
|
104 |
+
box-sizing: border-box;
|
105 |
+
-moz-box-sizing: border-box;
|
106 |
+
}
|
107 |
+
|
108 |
+
.nestable-list .dd-empty {
|
109 |
+
border: 1px dashed #bbb;
|
110 |
+
min-height: 100px;
|
111 |
+
background-color: #e5e5e5;
|
112 |
+
background-image: -webkit-linear-gradient(45deg, #fff 25%, transparent 25%, transparent 75%, #fff 75%, #fff),
|
113 |
+
-webkit-linear-gradient(45deg, #fff 25%, transparent 25%, transparent 75%, #fff 75%, #fff);
|
114 |
+
background-image: -moz-linear-gradient(45deg, #fff 25%, transparent 25%, transparent 75%, #fff 75%, #fff),
|
115 |
+
-moz-linear-gradient(45deg, #fff 25%, transparent 25%, transparent 75%, #fff 75%, #fff);
|
116 |
+
background-image: linear-gradient(45deg, #fff 25%, transparent 25%, transparent 75%, #fff 75%, #fff),
|
117 |
+
linear-gradient(45deg, #fff 25%, transparent 25%, transparent 75%, #fff 75%, #fff);
|
118 |
+
background-size: 60px 60px;
|
119 |
+
background-position: 0 0, 30px 30px;
|
120 |
+
}
|
121 |
+
|
122 |
+
.nestable-list .dd-dragel {
|
123 |
+
position: absolute;
|
124 |
+
pointer-events: none;
|
125 |
+
z-index: 9999;
|
126 |
+
}
|
127 |
+
|
128 |
+
.nestable-list .dd-dragel > .dd-item .dd-handle {
|
129 |
+
margin-top: 0;
|
130 |
+
}
|
131 |
+
|
132 |
+
.nestable-list .dd-dragel .dd-handle {
|
133 |
+
-webkit-box-shadow: 2px 4px 6px 0 rgba(0, 0, 0, .1);
|
134 |
+
box-shadow: 2px 4px 6px 0 rgba(0, 0, 0, .1);
|
135 |
+
}
|
136 |
+
|
137 |
+
/* EXTRA STYLE */
|
138 |
+
#hierarchy-post-attributes-metabox .actions {
|
139 |
+
text-align: right;
|
140 |
+
}
|
141 |
+
|
142 |
+
.wrapper-nestable-list {
|
143 |
+
position: relative;
|
144 |
+
width: 100%;
|
145 |
+
height: 100%;
|
146 |
+
}
|
147 |
+
.nestable-list-spinner {
|
148 |
+
display: none;
|
149 |
+
position: absolute;
|
150 |
+
top: 0;
|
151 |
+
left: 0;
|
152 |
+
width: 100%;
|
153 |
+
height: 100%;
|
154 |
+
background: rgba(255, 255, 255, 0.5);
|
155 |
+
}
|
156 |
+
.nestable-list-spinner img {
|
157 |
+
position: absolute;
|
158 |
+
top: 50%;
|
159 |
+
left: 50%;
|
160 |
+
margin: -20px 0 0 -20px;
|
161 |
+
}
|
includes/extensions/categoryPage/index.html
ADDED
File without changes
|
includes/extensions/categoryPage/js/index.html
ADDED
File without changes
|
includes/extensions/categoryPage/js/jquery.nestable.js
ADDED
@@ -0,0 +1,484 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
/*!
|
2 |
+
* Nestable jQuery Plugin - Copyright (c) 2012 David Bushell - http://dbushell.com/
|
3 |
+
* Dual-licensed under the BSD or MIT licenses
|
4 |
+
*/
|
5 |
+
;(function($, window, document, undefined)
|
6 |
+
{
|
7 |
+
var hasTouch = 'ontouchstart' in document;
|
8 |
+
|
9 |
+
/**
|
10 |
+
* Detect CSS pointer-events property
|
11 |
+
* events are normally disabled on the dragging element to avoid conflicts
|
12 |
+
* https://github.com/ausi/Feature-detection-technique-for-pointer-events/blob/master/modernizr-pointerevents.js
|
13 |
+
*/
|
14 |
+
var hasPointerEvents = (function()
|
15 |
+
{
|
16 |
+
var el = document.createElement('div'),
|
17 |
+
docEl = document.documentElement;
|
18 |
+
if (!('pointerEvents' in el.style)) {
|
19 |
+
return false;
|
20 |
+
}
|
21 |
+
el.style.pointerEvents = 'auto';
|
22 |
+
el.style.pointerEvents = 'x';
|
23 |
+
docEl.appendChild(el);
|
24 |
+
var supports = window.getComputedStyle && window.getComputedStyle(el, '').pointerEvents === 'auto';
|
25 |
+
docEl.removeChild(el);
|
26 |
+
return !!supports;
|
27 |
+
})();
|
28 |
+
|
29 |
+
var defaults = {
|
30 |
+
listNodeName : 'ol',
|
31 |
+
itemNodeName : 'li',
|
32 |
+
rootClass : 'dd',
|
33 |
+
listClass : 'dd-list',
|
34 |
+
itemClass : 'dd-item',
|
35 |
+
dragClass : 'dd-dragel',
|
36 |
+
handleClass : 'dd-handle',
|
37 |
+
collapsedClass : 'dd-collapsed',
|
38 |
+
placeClass : 'dd-placeholder',
|
39 |
+
noDragClass : 'dd-nodrag',
|
40 |
+
emptyClass : 'dd-empty',
|
41 |
+
expandBtnHTML : '<button data-action="expand" type="button">Expand</button>',
|
42 |
+
collapseBtnHTML : '<button data-action="collapse" type="button">Collapse</button>',
|
43 |
+
group : 0,
|
44 |
+
maxDepth : 5,
|
45 |
+
threshold : 20
|
46 |
+
};
|
47 |
+
|
48 |
+
function Plugin(element, options)
|
49 |
+
{
|
50 |
+
this.w = $(document);
|
51 |
+
this.el = $(element);
|
52 |
+
this.options = $.extend({}, defaults, options);
|
53 |
+
this.init();
|
54 |
+
}
|
55 |
+
|
56 |
+
Plugin.prototype = {
|
57 |
+
|
58 |
+
init: function()
|
59 |
+
{
|
60 |
+
var list = this;
|
61 |
+
|
62 |
+
list.reset();
|
63 |
+
|
64 |
+
list.el.data('nestable-group', this.options.group);
|
65 |
+
|
66 |
+
list.placeEl = $('<div class="' + list.options.placeClass + '"/>');
|
67 |
+
|
68 |
+
$.each(this.el.find(list.options.itemNodeName), function(k, el) {
|
69 |
+
list.setParent($(el));
|
70 |
+
});
|
71 |
+
|
72 |
+
list.el.on('click', 'button', function(e) {
|
73 |
+
if (list.dragEl) {
|
74 |
+
return;
|
75 |
+
}
|
76 |
+
var target = $(e.currentTarget),
|
77 |
+
action = target.data('action'),
|
78 |
+
item = target.parent(list.options.itemNodeName);
|
79 |
+
if (action === 'collapse') {
|
80 |
+
list.collapseItem(item);
|
81 |
+
}
|
82 |
+
if (action === 'expand') {
|
83 |
+
list.expandItem(item);
|
84 |
+
}
|
85 |
+
});
|
86 |
+
|
87 |
+
var onStartEvent = function(e)
|
88 |
+
{
|
89 |
+
var handle = $(e.target);
|
90 |
+
if (!handle.hasClass(list.options.handleClass)) {
|
91 |
+
if (handle.closest('.' + list.options.noDragClass).length) {
|
92 |
+
return;
|
93 |
+
}
|
94 |
+
handle = handle.closest('.' + list.options.handleClass);
|
95 |
+
}
|
96 |
+
|
97 |
+
if (!handle.length || list.dragEl) {
|
98 |
+
return;
|
99 |
+
}
|
100 |
+
|
101 |
+
list.isTouch = /^touch/.test(e.type);
|
102 |
+
if (list.isTouch && e.touches.length !== 1) {
|
103 |
+
return;
|
104 |
+
}
|
105 |
+
|
106 |
+
e.preventDefault();
|
107 |
+
list.dragStart(e.touches ? e.touches[0] : e);
|
108 |
+
};
|
109 |
+
|
110 |
+
var onMoveEvent = function(e)
|
111 |
+
{
|
112 |
+
if (list.dragEl) {
|
113 |
+
e.preventDefault();
|
114 |
+
list.dragMove(e.touches ? e.touches[0] : e);
|
115 |
+
}
|
116 |
+
};
|
117 |
+
|
118 |
+
var onEndEvent = function(e)
|
119 |
+
{
|
120 |
+
if (list.dragEl) {
|
121 |
+
e.preventDefault();
|
122 |
+
list.dragStop(e.touches ? e.touches[0] : e);
|
123 |
+
}
|
124 |
+
};
|
125 |
+
|
126 |
+
if (hasTouch) {
|
127 |
+
list.el[0].addEventListener('touchstart', onStartEvent, false);
|
128 |
+
window.addEventListener('touchmove', onMoveEvent, false);
|
129 |
+
window.addEventListener('touchend', onEndEvent, false);
|
130 |
+
window.addEventListener('touchcancel', onEndEvent, false);
|
131 |
+
}
|
132 |
+
|
133 |
+
list.el.on('mousedown', onStartEvent);
|
134 |
+
list.w.on('mousemove', onMoveEvent);
|
135 |
+
list.w.on('mouseup', onEndEvent);
|
136 |
+
|
137 |
+
},
|
138 |
+
|
139 |
+
serialize: function()
|
140 |
+
{
|
141 |
+
var data,
|
142 |
+
depth = 0,
|
143 |
+
list = this;
|
144 |
+
step = function(level, depth)
|
145 |
+
{
|
146 |
+
var array = [ ],
|
147 |
+
items = level.children(list.options.itemNodeName);
|
148 |
+
items.each(function()
|
149 |
+
{
|
150 |
+
var li = $(this),
|
151 |
+
item = $.extend({}, li.data()),
|
152 |
+
sub = li.children(list.options.listNodeName);
|
153 |
+
if (sub.length) {
|
154 |
+
item.children = step(sub, depth + 1);
|
155 |
+
}
|
156 |
+
array.push(item);
|
157 |
+
});
|
158 |
+
return array;
|
159 |
+
};
|
160 |
+
data = step(list.el.find(list.options.listNodeName).first(), depth);
|
161 |
+
return data;
|
162 |
+
},
|
163 |
+
|
164 |
+
serialise: function()
|
165 |
+
{
|
166 |
+
return this.serialize();
|
167 |
+
},
|
168 |
+
|
169 |
+
reset: function()
|
170 |
+
{
|
171 |
+
this.mouse = {
|
172 |
+
offsetX : 0,
|
173 |
+
offsetY : 0,
|
174 |
+
startX : 0,
|
175 |
+
startY : 0,
|
176 |
+
lastX : 0,
|
177 |
+
lastY : 0,
|
178 |
+
nowX : 0,
|
179 |
+
nowY : 0,
|
180 |
+
distX : 0,
|
181 |
+
distY : 0,
|
182 |
+
dirAx : 0,
|
183 |
+
dirX : 0,
|
184 |
+
dirY : 0,
|
185 |
+
lastDirX : 0,
|
186 |
+
lastDirY : 0,
|
187 |
+
distAxX : 0,
|
188 |
+
distAxY : 0
|
189 |
+
};
|
190 |
+
this.isTouch = false;
|
191 |
+
this.moving = false;
|
192 |
+
this.dragEl = null;
|
193 |
+
this.dragRootEl = null;
|
194 |
+
this.dragDepth = 0;
|
195 |
+
this.hasNewRoot = false;
|
196 |
+
this.pointEl = null;
|
197 |
+
},
|
198 |
+
|
199 |
+
expandItem: function(li)
|
200 |
+
{
|
201 |
+
li.removeClass(this.options.collapsedClass);
|
202 |
+
li.children('[data-action="expand"]').hide();
|
203 |
+
li.children('[data-action="collapse"]').show();
|
204 |
+
li.children(this.options.listNodeName).show();
|
205 |
+
},
|
206 |
+
|
207 |
+
collapseItem: function(li)
|
208 |
+
{
|
209 |
+
var lists = li.children(this.options.listNodeName);
|
210 |
+
if (lists.length) {
|
211 |
+
li.addClass(this.options.collapsedClass);
|
212 |
+
li.children('[data-action="collapse"]').hide();
|
213 |
+
li.children('[data-action="expand"]').show();
|
214 |
+
li.children(this.options.listNodeName).hide();
|
215 |
+
}
|
216 |
+
},
|
217 |
+
|
218 |
+
expandAll: function()
|
219 |
+
{
|
220 |
+
var list = this;
|
221 |
+
list.el.find(list.options.itemNodeName).each(function() {
|
222 |
+
list.expandItem($(this));
|
223 |
+
});
|
224 |
+
},
|
225 |
+
|
226 |
+
collapseAll: function()
|
227 |
+
{
|
228 |
+
var list = this;
|
229 |
+
list.el.find(list.options.itemNodeName).each(function() {
|
230 |
+
list.collapseItem($(this));
|
231 |
+
});
|
232 |
+
},
|
233 |
+
|
234 |
+
setParent: function(li)
|
235 |
+
{
|
236 |
+
if (li.children(this.options.listNodeName).length) {
|
237 |
+
li.prepend($(this.options.expandBtnHTML));
|
238 |
+
li.prepend($(this.options.collapseBtnHTML));
|
239 |
+
}
|
240 |
+
li.children('[data-action="expand"]').hide();
|
241 |
+
},
|
242 |
+
|
243 |
+
unsetParent: function(li)
|
244 |
+
{
|
245 |
+
li.removeClass(this.options.collapsedClass);
|
246 |
+
li.children('[data-action]').remove();
|
247 |
+
li.children(this.options.listNodeName).remove();
|
248 |
+
},
|
249 |
+
|
250 |
+
dragStart: function(e)
|
251 |
+
{
|
252 |
+
var mouse = this.mouse,
|
253 |
+
target = $(e.target),
|
254 |
+
dragItem = target.closest(this.options.itemNodeName);
|
255 |
+
|
256 |
+
this.placeEl.css('height', dragItem.height());
|
257 |
+
|
258 |
+
mouse.offsetX = e.offsetX !== undefined ? e.offsetX : e.pageX - target.offset().left;
|
259 |
+
mouse.offsetY = e.offsetY !== undefined ? e.offsetY : e.pageY - target.offset().top;
|
260 |
+
mouse.startX = mouse.lastX = e.pageX;
|
261 |
+
mouse.startY = mouse.lastY = e.pageY;
|
262 |
+
|
263 |
+
this.dragRootEl = this.el;
|
264 |
+
|
265 |
+
this.dragEl = $(document.createElement(this.options.listNodeName)).addClass(this.options.listClass + ' ' + this.options.dragClass);
|
266 |
+
this.dragEl.css('width', dragItem.width());
|
267 |
+
|
268 |
+
dragItem.after(this.placeEl);
|
269 |
+
dragItem[0].parentNode.removeChild(dragItem[0]);
|
270 |
+
dragItem.appendTo(this.dragEl);
|
271 |
+
|
272 |
+
$(document.body).append(this.dragEl);
|
273 |
+
this.dragEl.css({
|
274 |
+
'left' : e.pageX - mouse.offsetX,
|
275 |
+
'top' : e.pageY - mouse.offsetY
|
276 |
+
});
|
277 |
+
// total depth of dragging item
|
278 |
+
var i, depth,
|
279 |
+
items = this.dragEl.find(this.options.itemNodeName);
|
280 |
+
for (i = 0; i < items.length; i++) {
|
281 |
+
depth = $(items[i]).parents(this.options.listNodeName).length;
|
282 |
+
if (depth > this.dragDepth) {
|
283 |
+
this.dragDepth = depth;
|
284 |
+
}
|
285 |
+
}
|
286 |
+
},
|
287 |
+
|
288 |
+
dragStop: function(e)
|
289 |
+
{
|
290 |
+
var el = this.dragEl.children(this.options.itemNodeName).first();
|
291 |
+
el[0].parentNode.removeChild(el[0]);
|
292 |
+
this.placeEl.replaceWith(el);
|
293 |
+
|
294 |
+
this.dragEl.remove();
|
295 |
+
this.el.trigger('change');
|
296 |
+
if (this.hasNewRoot) {
|
297 |
+
this.dragRootEl.trigger('change');
|
298 |
+
}
|
299 |
+
this.reset();
|
300 |
+
},
|
301 |
+
|
302 |
+
dragMove: function(e)
|
303 |
+
{
|
304 |
+
var list, parent, prev, next, depth,
|
305 |
+
opt = this.options,
|
306 |
+
mouse = this.mouse;
|
307 |
+
|
308 |
+
this.dragEl.css({
|
309 |
+
'left' : e.pageX - mouse.offsetX,
|
310 |
+
'top' : e.pageY - mouse.offsetY
|
311 |
+
});
|
312 |
+
|
313 |
+
// mouse position last events
|
314 |
+
mouse.lastX = mouse.nowX;
|
315 |
+
mouse.lastY = mouse.nowY;
|
316 |
+
// mouse position this events
|
317 |
+
mouse.nowX = e.pageX;
|
318 |
+
mouse.nowY = e.pageY;
|
319 |
+
// distance mouse moved between events
|
320 |
+
mouse.distX = mouse.nowX - mouse.lastX;
|
321 |
+
mouse.distY = mouse.nowY - mouse.lastY;
|
322 |
+
// direction mouse was moving
|
323 |
+
mouse.lastDirX = mouse.dirX;
|
324 |
+
mouse.lastDirY = mouse.dirY;
|
325 |
+
// direction mouse is now moving (on both axis)
|
326 |
+
mouse.dirX = mouse.distX === 0 ? 0 : mouse.distX > 0 ? 1 : -1;
|
327 |
+
mouse.dirY = mouse.distY === 0 ? 0 : mouse.distY > 0 ? 1 : -1;
|
328 |
+
// axis mouse is now moving on
|
329 |
+
var newAx = Math.abs(mouse.distX) > Math.abs(mouse.distY) ? 1 : 0;
|
330 |
+
|
331 |
+
// do nothing on first move
|
332 |
+
if (!mouse.moving) {
|
333 |
+
mouse.dirAx = newAx;
|
334 |
+
mouse.moving = true;
|
335 |
+
return;
|
336 |
+
}
|
337 |
+
|
338 |
+
// calc distance moved on this axis (and direction)
|
339 |
+
if (mouse.dirAx !== newAx) {
|
340 |
+
mouse.distAxX = 0;
|
341 |
+
mouse.distAxY = 0;
|
342 |
+
} else {
|
343 |
+
mouse.distAxX += Math.abs(mouse.distX);
|
344 |
+
if (mouse.dirX !== 0 && mouse.dirX !== mouse.lastDirX) {
|
345 |
+
mouse.distAxX = 0;
|
346 |
+
}
|
347 |
+
mouse.distAxY += Math.abs(mouse.distY);
|
348 |
+
if (mouse.dirY !== 0 && mouse.dirY !== mouse.lastDirY) {
|
349 |
+
mouse.distAxY = 0;
|
350 |
+
}
|
351 |
+
}
|
352 |
+
mouse.dirAx = newAx;
|
353 |
+
|
354 |
+
/**
|
355 |
+
* move horizontal
|
356 |
+
*/
|
357 |
+
if (mouse.dirAx && mouse.distAxX >= opt.threshold) {
|
358 |
+
// reset move distance on x-axis for new phase
|
359 |
+
mouse.distAxX = 0;
|
360 |
+
prev = this.placeEl.prev(opt.itemNodeName);
|
361 |
+
// increase horizontal level if previous sibling exists and is not collapsed
|
362 |
+
if (mouse.distX > 0 && prev.length && !prev.hasClass(opt.collapsedClass)) {
|
363 |
+
// cannot increase level when item above is collapsed
|
364 |
+
list = prev.find(opt.listNodeName).last();
|
365 |
+
// check if depth limit has reached
|
366 |
+
depth = this.placeEl.parents(opt.listNodeName).length;
|
367 |
+
if (depth + this.dragDepth <= opt.maxDepth) {
|
368 |
+
// create new sub-level if one doesn't exist
|
369 |
+
if (!list.length) {
|
370 |
+
list = $('<' + opt.listNodeName + '/>').addClass(opt.listClass);
|
371 |
+
list.append(this.placeEl);
|
372 |
+
prev.append(list);
|
373 |
+
this.setParent(prev);
|
374 |
+
} else {
|
375 |
+
// else append to next level up
|
376 |
+
list = prev.children(opt.listNodeName).last();
|
377 |
+
list.append(this.placeEl);
|
378 |
+
}
|
379 |
+
}
|
380 |
+
}
|
381 |
+
// decrease horizontal level
|
382 |
+
if (mouse.distX < 0) {
|
383 |
+
// we can't decrease a level if an item preceeds the current one
|
384 |
+
next = this.placeEl.next(opt.itemNodeName);
|
385 |
+
if (!next.length) {
|
386 |
+
parent = this.placeEl.parent();
|
387 |
+
this.placeEl.closest(opt.itemNodeName).after(this.placeEl);
|
388 |
+
if (!parent.children().length) {
|
389 |
+
this.unsetParent(parent.parent());
|
390 |
+
}
|
391 |
+
}
|
392 |
+
}
|
393 |
+
}
|
394 |
+
|
395 |
+
var isEmpty = false;
|
396 |
+
|
397 |
+
// find list item under cursor
|
398 |
+
if (!hasPointerEvents) {
|
399 |
+
this.dragEl[0].style.visibility = 'hidden';
|
400 |
+
}
|
401 |
+
this.pointEl = $(document.elementFromPoint(e.pageX - document.body.scrollLeft, e.pageY - (window.pageYOffset || document.documentElement.scrollTop)));
|
402 |
+
if (!hasPointerEvents) {
|
403 |
+
this.dragEl[0].style.visibility = 'visible';
|
404 |
+
}
|
405 |
+
if (this.pointEl.hasClass(opt.handleClass)) {
|
406 |
+
this.pointEl = this.pointEl.parent(opt.itemNodeName);
|
407 |
+
}
|
408 |
+
if (this.pointEl.hasClass(opt.emptyClass)) {
|
409 |
+
isEmpty = true;
|
410 |
+
}
|
411 |
+
else if (!this.pointEl.length || !this.pointEl.hasClass(opt.itemClass)) {
|
412 |
+
return;
|
413 |
+
}
|
414 |
+
|
415 |
+
// find parent list of item under cursor
|
416 |
+
var pointElRoot = this.pointEl.closest('.' + opt.rootClass),
|
417 |
+
isNewRoot = this.dragRootEl.data('nestable-id') !== pointElRoot.data('nestable-id');
|
418 |
+
|
419 |
+
/**
|
420 |
+
* move vertical
|
421 |
+
*/
|
422 |
+
if (!mouse.dirAx || isNewRoot || isEmpty) {
|
423 |
+
// check if groups match if dragging over new root
|
424 |
+
if (isNewRoot && opt.group !== pointElRoot.data('nestable-group')) {
|
425 |
+
return;
|
426 |
+
}
|
427 |
+
// check depth limit
|
428 |
+
depth = this.dragDepth - 1 + this.pointEl.parents(opt.listNodeName).length;
|
429 |
+
if (depth > opt.maxDepth) {
|
430 |
+
return;
|
431 |
+
}
|
432 |
+
var before = e.pageY < (this.pointEl.offset().top + this.pointEl.height() / 2);
|
433 |
+
parent = this.placeEl.parent();
|
434 |
+
// if empty create new list to replace empty placeholder
|
435 |
+
if (isEmpty) {
|
436 |
+
list = $(document.createElement(opt.listNodeName)).addClass(opt.listClass);
|
437 |
+
list.append(this.placeEl);
|
438 |
+
this.pointEl.replaceWith(list);
|
439 |
+
}
|
440 |
+
else if (before) {
|
441 |
+
this.pointEl.before(this.placeEl);
|
442 |
+
}
|
443 |
+
else {
|
444 |
+
this.pointEl.after(this.placeEl);
|
445 |
+
}
|
446 |
+
if (!parent.children().length) {
|
447 |
+
this.unsetParent(parent.parent());
|
448 |
+
}
|
449 |
+
if (!this.dragRootEl.find(opt.itemNodeName).length) {
|
450 |
+
this.dragRootEl.append('<div class="' + opt.emptyClass + '"/>');
|
451 |
+
}
|
452 |
+
// parent root list has changed
|
453 |
+
if (isNewRoot) {
|
454 |
+
this.dragRootEl = pointElRoot;
|
455 |
+
this.hasNewRoot = this.el[0] !== this.dragRootEl[0];
|
456 |
+
}
|
457 |
+
}
|
458 |
+
}
|
459 |
+
|
460 |
+
};
|
461 |
+
|
462 |
+
$.fn.nestable = function(params)
|
463 |
+
{
|
464 |
+
var lists = this,
|
465 |
+
retval = this;
|
466 |
+
|
467 |
+
lists.each(function()
|
468 |
+
{
|
469 |
+
var plugin = $(this).data("nestable");
|
470 |
+
|
471 |
+
if (!plugin) {
|
472 |
+
$(this).data("nestable", new Plugin(this, params));
|
473 |
+
$(this).data("nestable-id", new Date().getTime());
|
474 |
+
} else {
|
475 |
+
if (typeof params === 'string' && typeof plugin[params] === 'function') {
|
476 |
+
retval = plugin[params]();
|
477 |
+
}
|
478 |
+
}
|
479 |
+
});
|
480 |
+
|
481 |
+
return retval || lists;
|
482 |
+
};
|
483 |
+
|
484 |
+
})(window.jQuery || window.Zepto, window, document);
|
includes/extensions/categoryPage/js/script.js
ADDED
@@ -0,0 +1,92 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
;(function ($, undefined){
|
2 |
+
|
3 |
+
|
4 |
+
function DialogEdit() {
|
5 |
+
this.$element = $('.wrapper-nestable-list');
|
6 |
+
this.$nestableList = this.$element.find('.nestable-list');
|
7 |
+
this.$nestableList.nestable({group: 1, maxDepth: 100});
|
8 |
+
|
9 |
+
this.init();
|
10 |
+
}
|
11 |
+
DialogEdit.prototype = {
|
12 |
+
init: function() {
|
13 |
+
var self = this;
|
14 |
+
$('.save_category').click(function(event) {
|
15 |
+
event.preventDefault();
|
16 |
+
self.save() ;
|
17 |
+
});
|
18 |
+
},
|
19 |
+
|
20 |
+
save : function () {
|
21 |
+
var self = this,
|
22 |
+
hierarchyPosts = this.$nestableList.nestable('serialise');
|
23 |
+
|
24 |
+
self.spinner(true);
|
25 |
+
$.ajax({
|
26 |
+
url: hierarchyPostAttributes.ajaxUrl,
|
27 |
+
method: 'post',
|
28 |
+
data: {
|
29 |
+
action: hierarchyPostAttributes.dialog.action.save,
|
30 |
+
hierarchy_posts: hierarchyPosts
|
31 |
+
},
|
32 |
+
success: function (response) {
|
33 |
+
self.spinner(false);
|
34 |
+
self.destroy();
|
35 |
+
},
|
36 |
+
error: function (jqXHR) {
|
37 |
+
self.destroy();
|
38 |
+
new DialogError(jqXHR.responseText);
|
39 |
+
}
|
40 |
+
});
|
41 |
+
},
|
42 |
+
|
43 |
+
spinner: function(isShow) {
|
44 |
+
if (isShow) {
|
45 |
+
var $spinner = this.$element.find('.nestable-list-spinner').clone();
|
46 |
+
$spinner.appendTo(this.$element.closest('.ui-dialog.ui-widget')).show();
|
47 |
+
} else {
|
48 |
+
this.$element.find('.nestable-list-spinner').remove();
|
49 |
+
}
|
50 |
+
},
|
51 |
+
|
52 |
+
destroy: function () {
|
53 |
+
this.$element.dialog('close');
|
54 |
+
this.$element.remove();
|
55 |
+
}
|
56 |
+
};
|
57 |
+
|
58 |
+
function DialogError(message) {
|
59 |
+
this.$element = $('<div id="hierarchy-post-error">' + message + '</div>');
|
60 |
+
this.show()
|
61 |
+
}
|
62 |
+
DialogError.prototype = {
|
63 |
+
show: function () {
|
64 |
+
var self = this;
|
65 |
+
|
66 |
+
self.$element.appendTo('body');
|
67 |
+
self.$element.dialog({
|
68 |
+
'dialogClass' : 'wp-dialog',
|
69 |
+
'title': hierarchyPostAttributes.error.title,
|
70 |
+
'modal' : true,
|
71 |
+
'autoOpen' : true,
|
72 |
+
'closeOnEscape' : false,
|
73 |
+
'buttons' : [
|
74 |
+
{
|
75 |
+
'text' : hierarchyPostAttributes.error.button.ok.label,
|
76 |
+
'class' : 'button',
|
77 |
+
'click' : function() { return self.destroy(); }
|
78 |
+
}
|
79 |
+
],
|
80 |
+
'close': function() { return self.destroy(); }
|
81 |
+
});
|
82 |
+
},
|
83 |
+
destroy: function () {
|
84 |
+
this.$element.dialog('close');
|
85 |
+
this.$element.remove();
|
86 |
+
}
|
87 |
+
};
|
88 |
+
|
89 |
+
$(document).ready(function() {
|
90 |
+
new DialogEdit();
|
91 |
+
});
|
92 |
+
}(jQuery));
|
includes/extensions/zip/Core/AbstractException.php
ADDED
@@ -0,0 +1,14 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
*
|
4 |
+
* @author Greg Kappatos
|
5 |
+
*
|
6 |
+
* This class serves as a proxy for all \PHPZip\Zip\Exception classes.
|
7 |
+
* It is empty for now, but properties can be added in the future without
|
8 |
+
* breaking any code.
|
9 |
+
*
|
10 |
+
*/
|
11 |
+
|
12 |
+
namespace PHPZip\Zip\Core;
|
13 |
+
|
14 |
+
abstract class AbstractException extends \Exception {}
|
includes/extensions/zip/Core/AbstractZipArchive.php
ADDED
@@ -0,0 +1,1046 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
*
|
4 |
+
* @author A. Grandt <php@grandt.com>
|
5 |
+
* @author Greg Kappatos
|
6 |
+
*
|
7 |
+
* This class serves as an abstract superclass for zip archives.
|
8 |
+
*
|
9 |
+
*/
|
10 |
+
|
11 |
+
namespace PHPZip\Zip\Core;
|
12 |
+
|
13 |
+
use com\grandt\BinStringStatic;
|
14 |
+
use PHPZip\Zip\Listener\ZipArchiveListener as ZipArchiveListener;
|
15 |
+
use PHPZip\Zip\Exception\IncompatiblePhpVersion as IncompatiblePhpVersionException;
|
16 |
+
use PHPZip\Zip\Exception\InvalidPhpConfiguration as InvalidPhpConfigurationException;
|
17 |
+
use PHPZip\Zip\Exception\HeadersSent as HeadersSentException;
|
18 |
+
use PHPZip\Zip\Exception\BufferNotEmpty as BufferNotEmptyException;
|
19 |
+
use PHPZip\Zip\Exception\LengthMismatch as LengthMismatchException;
|
20 |
+
use ZipMerge\Zip\Core\AbstractZipWriter;
|
21 |
+
use ZipMerge\Zip\Core\Header\ZipFileEntry;
|
22 |
+
use ZipMerge\Zip\Stream\ZipMerge;
|
23 |
+
|
24 |
+
|
25 |
+
abstract class AbstractZipArchive extends AbstractZipWriter {
|
26 |
+
const APP_NAME = 'PHPZip';
|
27 |
+
const VERSION = "2.0.8";
|
28 |
+
const MIN_PHP_VERSION = 5.3; // for namespaces
|
29 |
+
|
30 |
+
const CONTENT_TYPE = 'application/zip';
|
31 |
+
|
32 |
+
const NULL_BYTE = "\x00";
|
33 |
+
const NULL_WORD = "\x00\x00"; // Two nul bytes, used often enough.
|
34 |
+
const NULL_DWORD = "\x00\x00\x00\x00";
|
35 |
+
|
36 |
+
const ZIP_CENTRAL_FILE_HEADER = "PK\x01\x02"; // Central file header signature
|
37 |
+
const ZIP_LOCAL_FILE_HEADER = "PK\x03\x04"; // Local file header signature
|
38 |
+
const ZIP_LOCAL_DATA_DESCRIPTOR = "PK\x07\x08"; // Local Header, data descriptor
|
39 |
+
const ZIP_END_OF_CENTRAL_DIRECTORY = "PK\x05\x06"; // End of Central directory record
|
40 |
+
|
41 |
+
const HEADER_UNIX_TYPE_1 = 'UX'; // \x55\x58 or 0x5855 It has been replaced by the extended-timestamp extra block 'UT' (0x5455) and the Unix type 2 extra block 'Ux' (0x7855).
|
42 |
+
const HEADER_UNIX_TYPE_2 = 'Ux'; // \x55\x78 or 0x7855
|
43 |
+
const HEADER_UNIX_TYPE_3 = 'ux'; // \x75\x78 or 0x7875
|
44 |
+
const HEADER_EXTENDED_TIMESTAMP = 'UT'; // \x55\x54 or 0x5455
|
45 |
+
const HEADER_UNICODE_PATH = 'up'; // \x75\x70 or 0x7075
|
46 |
+
const HEADER_UNICODE_COMMENT = 'uc'; // \x75\x63 or 0x6375
|
47 |
+
|
48 |
+
const EXT_FILE_ATTR_DIR = 010173200020; // Permission 755 drwxr-xr-x = (((S_IFDIR | 0755) << 16) | S_DOS_D);
|
49 |
+
const EXT_FILE_ATTR_FILE = 020151000040; // Permission 644 -rw-r--r-- = (((S_IFREG | 0644) << 16) | S_DOS_A);
|
50 |
+
|
51 |
+
const ATTR_VERSION_TO_EXTRACT = "\x14\x00"; // Version needed to extract = 20 (File is compressed using Deflate compression)
|
52 |
+
const ATTR_MADE_BY_VERSION = "\x1E\x03"; // Made By Version
|
53 |
+
|
54 |
+
const DEFAULT_GZ_TYPE = "\x08\x00"; // Compression type 8 = deflate
|
55 |
+
const DEFAULT_GP_FLAGS = self::NULL_WORD; // General Purpose bit flags for compression type 8 it is: 0=Normal, 1=Maximum, 2=Fast, 3=super fast compression.
|
56 |
+
|
57 |
+
const DEFAULT_GZ_TYPE_STORED = self::NULL_WORD; // Compression type 0 = stored
|
58 |
+
const DEFAULT_GP_FLAGS_STORED = self::NULL_WORD; // Compression type 0 = stored
|
59 |
+
|
60 |
+
// UID 1000, GID 0
|
61 |
+
const EXTRA_FIELD_NEW_UNIX_GUID = "ux\x0B\x00\x01\x04\xE8\x03\x00\x00\x04\x00\x00\x00\x00"; // \x75\x78 3rd gen Unis GUID
|
62 |
+
const EXTRA_FIELD_NEW_UNIX_GUID_CD = "ux\x00\x00"; // \x75\x78 3rd gen Unis GUID CD record version must have length 0.
|
63 |
+
|
64 |
+
protected $zipComment = null;
|
65 |
+
protected $cdRec = array(); // central directory
|
66 |
+
protected $offset = 0;
|
67 |
+
protected $isFinalized = false;
|
68 |
+
protected $addExtraField = true;
|
69 |
+
|
70 |
+
protected $streamChunkSize = 0;
|
71 |
+
protected $streamFilePath = null;
|
72 |
+
protected $streamTimestamp = null;
|
73 |
+
protected $streamFileComment = null;
|
74 |
+
protected $streamFile = null;
|
75 |
+
protected $streamData = null;
|
76 |
+
protected $streamFileLength = 0;
|
77 |
+
protected $streamExtFileAttr = null;
|
78 |
+
|
79 |
+
/**
|
80 |
+
* A custom temporary folder, or a callable that returns a custom temporary file.
|
81 |
+
* @var string|callable
|
82 |
+
*/
|
83 |
+
public static $temp = null;
|
84 |
+
|
85 |
+
private $_listeners = array();
|
86 |
+
private $_phpConfigurationWatch = array(
|
87 |
+
// 'mbstring.func_overload' => '0' // throw an exception if setting in php.ini is not '0'
|
88 |
+
);
|
89 |
+
|
90 |
+
/**
|
91 |
+
* Constructor.
|
92 |
+
*
|
93 |
+
* @author A. Grandt <php@grandt.com>
|
94 |
+
* @author Greg Kappatos
|
95 |
+
*
|
96 |
+
* @param boolean $streamChunkSize Size of each chunk
|
97 |
+
*
|
98 |
+
* @throws \PHPZip\Zip\Exception\InvalidPhpConfiguration In case of errors
|
99 |
+
*/
|
100 |
+
protected function __construct($streamChunkSize) {
|
101 |
+
$this->streamChunkSize = $streamChunkSize;
|
102 |
+
|
103 |
+
if (count($this->_phpConfigurationWatch) > 0) {
|
104 |
+
foreach ($this->_phpConfigurationWatch as $k => $v) {
|
105 |
+
$s = (string)$v;
|
106 |
+
if (@ini_get($k) !== $s) {
|
107 |
+
$this->_throwException(new InvalidPhpConfigurationException(array(
|
108 |
+
'setting' => $k,
|
109 |
+
'expected' => $s,
|
110 |
+
)));
|
111 |
+
break; // technically not needed.
|
112 |
+
}
|
113 |
+
}
|
114 |
+
}
|
115 |
+
}
|
116 |
+
|
117 |
+
/**
|
118 |
+
* Extra fields on the Zip directory records are Unix time codes needed for compatibility on the default Mac zip archive tool.
|
119 |
+
* These are enabled as default, as they do no harm elsewhere and only add 26 bytes per file added.
|
120 |
+
*
|
121 |
+
* @author A. Grandt <php@grandt.com>
|
122 |
+
*
|
123 |
+
* @param bool $setExtraField true (default) will enable adding of extra fields, anything else will disable it.
|
124 |
+
*/
|
125 |
+
public function setExtraField($setExtraField = true) {
|
126 |
+
$this->addExtraField = ($setExtraField === true);
|
127 |
+
}
|
128 |
+
|
129 |
+
/**
|
130 |
+
* Set Zip archive comment.
|
131 |
+
*
|
132 |
+
* @author A. Grandt <php@grandt.com>
|
133 |
+
*
|
134 |
+
* @param string $newComment New comment. null to clear.
|
135 |
+
*
|
136 |
+
* @return bool $success
|
137 |
+
*/
|
138 |
+
public function setComment($newComment = null) {
|
139 |
+
if ($this->isFinalized) {
|
140 |
+
return false;
|
141 |
+
}
|
142 |
+
|
143 |
+
$this->zipComment = $newComment;
|
144 |
+
|
145 |
+
return true;
|
146 |
+
}
|
147 |
+
|
148 |
+
/**
|
149 |
+
* Add an empty directory entry to the zip archive.
|
150 |
+
* Basically this is only used if an empty directory is added.
|
151 |
+
*
|
152 |
+
* @author A. Grandt <php@grandt.com>
|
153 |
+
* @author Greg Kappatos
|
154 |
+
*
|
155 |
+
* @param string $directoryPath Directory Path and name to be added to the archive.
|
156 |
+
* @param int $timestamp (Optional) Timestamp for the added directory, if omitted or set to 0, the current time will be used.
|
157 |
+
* @param string $fileComment (Optional) Comment to be added to the archive for this directory. To use $fileComment, $timestamp must be given.
|
158 |
+
* @param int $extFileAttr (Optional) The external file reference, use generateExtAttr to generate this.
|
159 |
+
*
|
160 |
+
* @return bool $success
|
161 |
+
*/
|
162 |
+
public function addDirectory($directoryPath, $timestamp = 0, $fileComment = null, $extFileAttr = self::EXT_FILE_ATTR_DIR) {
|
163 |
+
// TODO: get rid of magic numbers.
|
164 |
+
$result = false;
|
165 |
+
|
166 |
+
if (!$this->isFinalized) {
|
167 |
+
$directoryPath = str_replace("\\", '/', $directoryPath);
|
168 |
+
$directoryPath = rtrim($directoryPath, '/');
|
169 |
+
|
170 |
+
if (BinStringStatic::_strlen($directoryPath) > 0) {
|
171 |
+
$this->buildZipEntry($directoryPath.'/',
|
172 |
+
$fileComment,
|
173 |
+
self::DEFAULT_GZ_TYPE_STORED,
|
174 |
+
self::DEFAULT_GP_FLAGS_STORED,
|
175 |
+
$timestamp,
|
176 |
+
"\x00\x00\x00\x00",
|
177 |
+
0, 0, $extFileAttr);
|
178 |
+
$result = true;
|
179 |
+
}
|
180 |
+
}
|
181 |
+
return $result;
|
182 |
+
}
|
183 |
+
|
184 |
+
/**
|
185 |
+
* Add a file to the archive at the specified location and file name.
|
186 |
+
*
|
187 |
+
* @author A. Grandt <php@grandt.com>
|
188 |
+
* @author Greg Kappatos
|
189 |
+
*
|
190 |
+
* @param string $data File data.
|
191 |
+
* @param string $filePath File path and name to be used in the archive.
|
192 |
+
* @param int $timestamp (Optional) Timestamp for the added file, if omitted or set to 0, the current time will be used.
|
193 |
+
* @param string $fileComment (Optional) Comment to be added to the archive for this file. To use $fileComment, $timestamp must be given.
|
194 |
+
* @param bool $compress (Optional) Compress file, if set to false the file will only be stored. Default true.
|
195 |
+
* @param int $extFileAttr (Optional) The external file reference, use generateExtAttr to generate this.
|
196 |
+
*
|
197 |
+
* @return bool $success
|
198 |
+
*/
|
199 |
+
public function addFile($data, $filePath, $timestamp = 0, $fileComment = null, $compress = null, $extFileAttr = self::EXT_FILE_ATTR_FILE) {
|
200 |
+
if ($this->isFinalized) {
|
201 |
+
return false;
|
202 |
+
}
|
203 |
+
|
204 |
+
if (is_resource($data) && get_resource_type($data) === 'stream') {
|
205 |
+
$this->addLargeFile($data, $filePath, $timestamp, $fileComment, $extFileAttr);
|
206 |
+
return false;
|
207 |
+
}
|
208 |
+
|
209 |
+
$gzData = '';
|
210 |
+
$gzType = self::DEFAULT_GZ_TYPE;
|
211 |
+
$gpFlags = self::DEFAULT_GP_FLAGS;
|
212 |
+
$dataLength = BinStringStatic::_strlen($data);
|
213 |
+
$fileCRC32 = pack("V", crc32($data));
|
214 |
+
$gzLength = $dataLength;
|
215 |
+
|
216 |
+
if ($compress) {
|
217 |
+
$gzTmp = gzcompress($data);
|
218 |
+
// gzcompress adds a 2 byte header and 4 byte Adler-32 CRC at the end, which we can't use.
|
219 |
+
$gzData = substr($gzTmp, 2, -4);
|
220 |
+
// The 2 byte header does contain useful data,
|
221 |
+
// though in this case the 2 parameters we'd be interested in will
|
222 |
+
// always be 8 for compression type, and 2 for General purpose flag.
|
223 |
+
$gzLength = BinStringStatic::_strlen($gzData);
|
224 |
+
}
|
225 |
+
|
226 |
+
if ($gzLength >= $dataLength) {
|
227 |
+
$gzLength = $dataLength;
|
228 |
+
$gzData = $data;
|
229 |
+
|
230 |
+
$gzType = self::DEFAULT_GZ_TYPE_STORED;
|
231 |
+
$gpFlags = self::DEFAULT_GP_FLAGS_STORED;
|
232 |
+
}
|
233 |
+
|
234 |
+
$this->onBeginAddFile(array(
|
235 |
+
'gzLength' => $gzLength,
|
236 |
+
));
|
237 |
+
|
238 |
+
$this->buildZipEntry($filePath, $fileComment, $gpFlags, $gzType, $timestamp, $fileCRC32, $gzLength, $dataLength, $extFileAttr);
|
239 |
+
|
240 |
+
$this->onEndAddFile(array(
|
241 |
+
'gzData' => $gzData,
|
242 |
+
));
|
243 |
+
|
244 |
+
$this->_notifyListeners(null, array(
|
245 |
+
'data' => $data,
|
246 |
+
));
|
247 |
+
|
248 |
+
return true;
|
249 |
+
}
|
250 |
+
|
251 |
+
/**
|
252 |
+
* Add the content to a directory.
|
253 |
+
*
|
254 |
+
* @author Adam Schmalhofer <Adam.Schmalhofer@gmx.de>
|
255 |
+
* @author A. Grandt <php@grandt.com>
|
256 |
+
*
|
257 |
+
* @param string $realPath Path on the file system.
|
258 |
+
* @param string $zipPath File path and name to be used in the archive.
|
259 |
+
* @param bool $recursive Add content recursively, default is true.
|
260 |
+
* @param bool $followSymlinks Follow and add symbolic links, if they are accessible, default is true.
|
261 |
+
* @param array &$addedFiles Reference to the added files, this is used to prevent duplicates, default is an empty array.
|
262 |
+
* If you start the function by parsing an array, the array will be populated with the $realPath
|
263 |
+
* and $zipPath kay/value pairs added to the archive by the function.
|
264 |
+
* @param bool $overrideFilePermissions Force the use of the file/dir permissions set in the $extDirAttr
|
265 |
+
* and $extFileAttr parameters.
|
266 |
+
* @param int $extDirAttr Permissions for directories.
|
267 |
+
* @param int $extFileAttr Permissions for files.
|
268 |
+
*/
|
269 |
+
public function addDirectoryContent($realPath, $zipPath, $recursive = true, $followSymlinks = true, &$addedFiles = array(),
|
270 |
+
$overrideFilePermissions = false, $extDirAttr = self::EXT_FILE_ATTR_DIR, $extFileAttr = self::EXT_FILE_ATTR_FILE) {
|
271 |
+
if (file_exists($realPath) && !isset($addedFiles[realpath($realPath)])) {
|
272 |
+
if (is_dir($realPath)) {
|
273 |
+
$this->addDirectory(
|
274 |
+
$zipPath,
|
275 |
+
0,
|
276 |
+
null,
|
277 |
+
$overrideFilePermissions ? $extDirAttr : ZipUtils::getFileExtAttr($realPath)
|
278 |
+
);
|
279 |
+
}
|
280 |
+
|
281 |
+
$addedFiles[realpath($realPath)] = $zipPath;
|
282 |
+
|
283 |
+
$iter = new \DirectoryIterator($realPath);
|
284 |
+
|
285 |
+
foreach ($iter as $file) {
|
286 |
+
/* @var $file \DirectoryIterator */
|
287 |
+
if ($file->isDot()) {
|
288 |
+
continue;
|
289 |
+
}
|
290 |
+
|
291 |
+
$newRealPath = $file->getPathname();
|
292 |
+
$newZipPath = \RelativePath::pathJoin($zipPath, $file->getFilename());
|
293 |
+
|
294 |
+
if (file_exists($newRealPath) && ($followSymlinks || !is_link($newRealPath))) {
|
295 |
+
if ($file->isFile()) {
|
296 |
+
$addedFiles[realpath($newRealPath)] = $newZipPath;
|
297 |
+
$this->addLargeFile(
|
298 |
+
$newRealPath,
|
299 |
+
$newZipPath,
|
300 |
+
0,
|
301 |
+
null,
|
302 |
+
$overrideFilePermissions ? $extFileAttr : ZipUtils::getFileExtAttr($newRealPath)
|
303 |
+
);
|
304 |
+
} else if ($recursive) {
|
305 |
+
$this->addDirectoryContent(
|
306 |
+
$newRealPath,
|
307 |
+
$newZipPath,
|
308 |
+
$recursive,
|
309 |
+
$followSymlinks,
|
310 |
+
$addedFiles,
|
311 |
+
$overrideFilePermissions,
|
312 |
+
$extDirAttr,
|
313 |
+
$extFileAttr
|
314 |
+
);
|
315 |
+
} else {
|
316 |
+
$this->addDirectory(
|
317 |
+
$zipPath,
|
318 |
+
0,
|
319 |
+
null,
|
320 |
+
$overrideFilePermissions ? $extDirAttr : ZipUtils::getFileExtAttr($newRealPath)
|
321 |
+
);
|
322 |
+
}
|
323 |
+
}
|
324 |
+
}
|
325 |
+
}
|
326 |
+
}
|
327 |
+
|
328 |
+
/**
|
329 |
+
* Append the contents of an existing zip file to the current, WITHOUT re-compressing the data within it.
|
330 |
+
*
|
331 |
+
* @param string $file the path to the zip file to be added.
|
332 |
+
* @param string $subPath place the contents in the $subPath sub-folder, default is '', and places the
|
333 |
+
* content in the root of the new zip file.
|
334 |
+
*/
|
335 |
+
public function appendZip($file, $subPath = '') {
|
336 |
+
$zipMerge = new ZipMerge(null);
|
337 |
+
$zipMerge->appendZip($file, $subPath, $this);
|
338 |
+
$files = $zipMerge->finalize();
|
339 |
+
|
340 |
+
/* @var $files array */
|
341 |
+
foreach ($files as $fileEntry) {
|
342 |
+
/* @var $fileEntry ZipFileEntry */
|
343 |
+
$fileEntry->offset = $this->offset;
|
344 |
+
$this->cdRec[] = $fileEntry->getCentralDirectoryHeader();
|
345 |
+
$this->offset += BinStringStatic::_strlen( $fileEntry->getLocalHeader()) + $fileEntry->gzLength;
|
346 |
+
}
|
347 |
+
}
|
348 |
+
|
349 |
+
/**
|
350 |
+
* Add a file to the archive at the specified location and file name.
|
351 |
+
*
|
352 |
+
* @author A. Grandt <php@grandt.com>
|
353 |
+
* @author Greg Kappatos
|
354 |
+
*
|
355 |
+
* @param string $dataFile File name/path.
|
356 |
+
* @param string $filePath File path and name to be used in the archive.
|
357 |
+
* @param int $timestamp (Optional) Timestamp for the added file, if omitted or set to 0, the current time will be used.
|
358 |
+
* @param string $fileComment (Optional) Comment to be added to the archive for this file. To use $fileComment, $timestamp must be given.
|
359 |
+
* @param int $extFileAttr (Optional) The external file reference, use generateExtAttr to generate this.
|
360 |
+
*
|
361 |
+
* @return bool $success
|
362 |
+
*/
|
363 |
+
public function addLargeFile($dataFile, $filePath, $timestamp = 0, $fileComment = null, $extFileAttr = self::EXT_FILE_ATTR_FILE) {
|
364 |
+
$result = false;
|
365 |
+
|
366 |
+
if (!$this->isFinalized) {
|
367 |
+
|
368 |
+
if (is_string($dataFile) && is_file($dataFile)) {
|
369 |
+
$this->processFile($dataFile, $filePath, $timestamp, $fileComment, $extFileAttr);
|
370 |
+
} else if (is_resource($dataFile) && get_resource_type($dataFile) == "stream") {
|
371 |
+
$fh = $dataFile;
|
372 |
+
$this->openStream($filePath, $timestamp, $fileComment, $extFileAttr);
|
373 |
+
|
374 |
+
while (!feof($fh)) {
|
375 |
+
$this->addStreamData(fread($fh, $this->streamChunkSize));
|
376 |
+
}
|
377 |
+
$this->closeStream();
|
378 |
+
}
|
379 |
+
$result = true;
|
380 |
+
}
|
381 |
+
|
382 |
+
$this->_notifyListeners(null, array(
|
383 |
+
'file' => $dataFile,
|
384 |
+
'result' => $result,
|
385 |
+
));
|
386 |
+
|
387 |
+
return $result;
|
388 |
+
}
|
389 |
+
|
390 |
+
/**
|
391 |
+
* Create a stream to be used for large entries.
|
392 |
+
*
|
393 |
+
* @author A. Grandt <php@grandt.com>
|
394 |
+
* @author Greg Kappatos
|
395 |
+
*
|
396 |
+
* @param string $filePath File path and name to be used in the archive.
|
397 |
+
* @param int $timestamp (Optional) Timestamp for the added file, if omitted or set to 0, the current time will be used.
|
398 |
+
* @param string $fileComment (Optional) Comment to be added to the archive for this file. To use $fileComment, $timestamp must be given.
|
399 |
+
* @param int $extFileAttr (Optional) The external file reference, use generateExtAttr to generate this.
|
400 |
+
*
|
401 |
+
* @throws \PHPZip\Zip\Exception\IncompatiblePhpVersion Throws an exception in case of errors
|
402 |
+
*
|
403 |
+
* @return bool $success
|
404 |
+
*/
|
405 |
+
public function openStream($filePath, $timestamp = 0, $fileComment = null, $extFileAttr = self::EXT_FILE_ATTR_FILE) {
|
406 |
+
|
407 |
+
$result = false;
|
408 |
+
|
409 |
+
if (!function_exists('sys_get_temp_dir')) {
|
410 |
+
$this->_throwException(new IncompatiblePhpVersionException(array(
|
411 |
+
'appName' => self::APP_NAME,
|
412 |
+
'appVersion' => self::VERSION,
|
413 |
+
'minVersion' => self::MIN_PHP_VERSION,
|
414 |
+
)));
|
415 |
+
}
|
416 |
+
|
417 |
+
if (!$this->isFinalized) {
|
418 |
+
$this->onOpenStream();
|
419 |
+
|
420 |
+
if (BinStringStatic::_strlen($this->streamFilePath) > 0) {
|
421 |
+
$this->closeStream();
|
422 |
+
}
|
423 |
+
|
424 |
+
$this->streamFile = self::getTemporaryFile();
|
425 |
+
$this->streamData = fopen($this->streamFile, "wb");
|
426 |
+
$this->streamFilePath = $filePath;
|
427 |
+
$this->streamTimestamp = $timestamp;
|
428 |
+
$this->streamFileComment = $fileComment;
|
429 |
+
$this->streamFileLength = 0;
|
430 |
+
$this->streamExtFileAttr = $extFileAttr;
|
431 |
+
|
432 |
+
$result = true;
|
433 |
+
}
|
434 |
+
|
435 |
+
$this->_notifyListeners(null, array(
|
436 |
+
'file' => $this->streamFile,
|
437 |
+
'result' => $result,
|
438 |
+
));
|
439 |
+
|
440 |
+
return $result;
|
441 |
+
}
|
442 |
+
|
443 |
+
/**
|
444 |
+
* Add data to the open stream.
|
445 |
+
*
|
446 |
+
* @author A. Grandt <php@grandt.com>
|
447 |
+
* @author Greg Kappatos
|
448 |
+
*
|
449 |
+
* @param string $data
|
450 |
+
*
|
451 |
+
* @throws LengthMismatchException Throws an exception in case of errors
|
452 |
+
*
|
453 |
+
* @return mixed length in bytes added or false if the archive is finalized or there are no open stream.
|
454 |
+
*/
|
455 |
+
public function addStreamData($data) {
|
456 |
+
if ($this->isFinalized || BinStringStatic::_strlen($this->streamFilePath) == 0) {
|
457 |
+
return false;
|
458 |
+
}
|
459 |
+
|
460 |
+
$dataLength = BinStringStatic::_strlen($data);
|
461 |
+
$length = fwrite($this->streamData, $data, $dataLength);
|
462 |
+
|
463 |
+
if ($length != $dataLength) {
|
464 |
+
$this->_throwException(new LengthMismatchException(array(
|
465 |
+
'expected' => BinStringStatic::_strlen($data),
|
466 |
+
'written' => (!$length ? 'NONE!' : $length),
|
467 |
+
)));
|
468 |
+
}
|
469 |
+
|
470 |
+
$this->streamFileLength += $length;
|
471 |
+
|
472 |
+
return $length;
|
473 |
+
}
|
474 |
+
|
475 |
+
/**
|
476 |
+
* Close the current stream.
|
477 |
+
*
|
478 |
+
* @author A. Grandt <php@grandt.com>
|
479 |
+
*
|
480 |
+
* @return bool $success
|
481 |
+
*/
|
482 |
+
public function closeStream() {
|
483 |
+
if ($this->isFinalized || BinStringStatic::_strlen($this->streamFilePath) == 0) {
|
484 |
+
return false;
|
485 |
+
}
|
486 |
+
|
487 |
+
fflush($this->streamData);
|
488 |
+
fclose($this->streamData);
|
489 |
+
|
490 |
+
$this->processFile(
|
491 |
+
$this->streamFile,
|
492 |
+
$this->streamFilePath,
|
493 |
+
$this->streamTimestamp,
|
494 |
+
$this->streamFileComment,
|
495 |
+
$this->streamExtFileAttr
|
496 |
+
);
|
497 |
+
|
498 |
+
$this->streamData = null;
|
499 |
+
$this->streamFilePath = null;
|
500 |
+
$this->streamTimestamp = null;
|
501 |
+
$this->streamFileComment = null;
|
502 |
+
$this->streamFileLength = 0;
|
503 |
+
$this->streamExtFileAttr = null;
|
504 |
+
|
505 |
+
// Windows is a little slow at times, so a millisecond later, we can unlink this.
|
506 |
+
unlink($this->streamFile);
|
507 |
+
$this->streamFile = null;
|
508 |
+
|
509 |
+
return true;
|
510 |
+
}
|
511 |
+
|
512 |
+
/**
|
513 |
+
* Process the current file.
|
514 |
+
*
|
515 |
+
* @author A. Grandt <php@grandt.com>
|
516 |
+
* @author Greg Kappatos
|
517 |
+
*
|
518 |
+
* @param string $dataFile
|
519 |
+
* @param string $filePath
|
520 |
+
* @param int $timestamp
|
521 |
+
* @param string $fileComment
|
522 |
+
* @param int $extFileAttr
|
523 |
+
*
|
524 |
+
* @return bool $success
|
525 |
+
*/
|
526 |
+
protected function processFile($dataFile, $filePath, $timestamp = 0, $fileComment = null, $extFileAttr = self::EXT_FILE_ATTR_FILE) {
|
527 |
+
|
528 |
+
// TODO: change the magic numbers below to constants.
|
529 |
+
|
530 |
+
if ($this->isFinalized) {
|
531 |
+
return false;
|
532 |
+
}
|
533 |
+
|
534 |
+
$tempZip = self::getTemporaryFile();
|
535 |
+
|
536 |
+
$zip = new \ZipArchive;
|
537 |
+
$rv = $zip->open($tempZip, \ZipArchive::CREATE | \ZipArchive::OVERWRITE);
|
538 |
+
|
539 |
+
if ($rv === true) { // open returns true if successful, however one of the error values is 1, which will also read as true.
|
540 |
+
$zip->addFile($dataFile, 'file');
|
541 |
+
$zip->close();
|
542 |
+
} else {
|
543 |
+
// TODO: An error occurred reading the ZipArchive temp file (Seen on Windows installations)
|
544 |
+
}
|
545 |
+
|
546 |
+
$handle = fopen($tempZip, "rb");
|
547 |
+
$stats = fstat($handle);
|
548 |
+
$eof = $stats['size']-72; // set EOF to the position of the end of the zip data, before the CD record.
|
549 |
+
// Should probably use 34+gzLength instead.
|
550 |
+
|
551 |
+
fseek($handle, 6); // Skip Zip local file header and version
|
552 |
+
|
553 |
+
$gpFlags = fread($handle, 2);
|
554 |
+
$gzType = fread($handle, 2);
|
555 |
+
fread($handle, 4); // Skip DOS Time and Date
|
556 |
+
$fileCRC32 = fread($handle, 4);
|
557 |
+
|
558 |
+
$v = unpack("Vval", fread($handle, 4));
|
559 |
+
$gzLength = $v['val'];
|
560 |
+
|
561 |
+
$v = unpack("Vval", fread($handle, 4));
|
562 |
+
$dataLength = $v['val'];
|
563 |
+
|
564 |
+
$this->buildZipEntry($filePath, $fileComment, $gpFlags, $gzType, $timestamp, $fileCRC32, $gzLength, $dataLength, $extFileAttr);
|
565 |
+
|
566 |
+
$pos = 34;
|
567 |
+
fseek($handle, $pos); // Position pointer at the start of the actual zip data.
|
568 |
+
|
569 |
+
while (!feof($handle) && $pos < $eof) {
|
570 |
+
$len = $this->streamChunkSize;
|
571 |
+
|
572 |
+
if ($pos + $this->streamChunkSize > $eof) {
|
573 |
+
$len = $eof - $pos;
|
574 |
+
}
|
575 |
+
$data = fread($handle, $len);
|
576 |
+
$pos += $len;
|
577 |
+
|
578 |
+
$this->onProcessFile(array(
|
579 |
+
'data' => $data,
|
580 |
+
));
|
581 |
+
}
|
582 |
+
|
583 |
+
fclose($handle);
|
584 |
+
unlink($tempZip);
|
585 |
+
|
586 |
+
$this->_notifyListeners(null, array(
|
587 |
+
'file' => $dataFile,
|
588 |
+
));
|
589 |
+
|
590 |
+
return true;
|
591 |
+
}
|
592 |
+
|
593 |
+
/**
|
594 |
+
* Build the Zip file structures
|
595 |
+
*
|
596 |
+
* @author A. Grandt <php@grandt.com>
|
597 |
+
* @author Greg Kappatos
|
598 |
+
*
|
599 |
+
* @param string $filePath
|
600 |
+
* @param string $fileComment
|
601 |
+
* @param string $gpFlags
|
602 |
+
* @param string $gzType
|
603 |
+
* @param int $timestamp
|
604 |
+
* @param string $fileCRC32
|
605 |
+
* @param int $gzLength
|
606 |
+
* @param int $dataLength
|
607 |
+
* @param int $extFileAttr Use self::EXT_FILE_ATTR_FILE for files, self::EXT_FILE_ATTR_DIR for Directories.
|
608 |
+
*/
|
609 |
+
protected function buildZipEntry($filePath, $fileComment, $gpFlags, $gzType, $timestamp, $fileCRC32, $gzLength, $dataLength, $extFileAttr) {
|
610 |
+
$filePath = str_replace("\\", "/", $filePath);
|
611 |
+
$fileCommentLength = (empty($fileComment) ? 0 : BinStringStatic::_strlen($fileComment));
|
612 |
+
$timestamp = (int)$timestamp;
|
613 |
+
$timestamp = ($timestamp == 0 ? time() : $timestamp);
|
614 |
+
|
615 |
+
$dosTime = ZipUtils::getDosTime($timestamp);
|
616 |
+
$tsPack = pack("V", $timestamp);
|
617 |
+
|
618 |
+
if (!isset($gpFlags) || BinStringStatic::_strlen($gpFlags) != 2) {
|
619 |
+
$gpFlags = self::DEFAULT_GP_FLAGS;
|
620 |
+
}
|
621 |
+
|
622 |
+
$isFileUTF8 = mb_check_encoding($filePath, "UTF-8") && !mb_check_encoding($filePath, "ASCII");
|
623 |
+
$isCommentUTF8 = !empty($fileComment) && mb_check_encoding($fileComment, "UTF-8") && !mb_check_encoding($fileComment, "ASCII");
|
624 |
+
|
625 |
+
$locExField = "";
|
626 |
+
$cenExField = "";
|
627 |
+
|
628 |
+
if ($this->addExtraField) {
|
629 |
+
$locExField .= self::HEADER_EXTENDED_TIMESTAMP . "\x09\x00\x03"
|
630 |
+
. $tsPack . $tsPack
|
631 |
+
. self::EXTRA_FIELD_NEW_UNIX_GUID;
|
632 |
+
$cenExField .= self::HEADER_EXTENDED_TIMESTAMP . "\x05\x00\x03"
|
633 |
+
. $tsPack
|
634 |
+
. self::EXTRA_FIELD_NEW_UNIX_GUID_CD;
|
635 |
+
}
|
636 |
+
|
637 |
+
if ($isFileUTF8 || $isCommentUTF8) {
|
638 |
+
$flag = 0;
|
639 |
+
$gpFlagsV = unpack("vflags", $gpFlags);
|
640 |
+
if (isset($gpFlagsV['flags'])) {
|
641 |
+
$flag = $gpFlagsV['flags'];
|
642 |
+
}
|
643 |
+
$gpFlags = pack("v", $flag | (1 << 11));
|
644 |
+
|
645 |
+
if ($isFileUTF8) {
|
646 |
+
$utfExField = self::HEADER_UNICODE_PATH // utf8 encoded File path extra field
|
647 |
+
. pack ("v", (5 + BinStringStatic::_strlen($filePath)))
|
648 |
+
. "\x01"
|
649 |
+
. pack("V", crc32($filePath))
|
650 |
+
. $filePath;
|
651 |
+
|
652 |
+
$locExField .= $utfExField;
|
653 |
+
$cenExField .= $utfExField;
|
654 |
+
}
|
655 |
+
if ($isCommentUTF8) {
|
656 |
+
$cenExField .= self::HEADER_UNICODE_COMMENT // utf8 encoded file comment extra field
|
657 |
+
. pack ("v", (5 + BinStringStatic::_strlen($fileComment)))
|
658 |
+
. "\x01"
|
659 |
+
. pack("V", crc32($fileComment))
|
660 |
+
. $fileComment;
|
661 |
+
}
|
662 |
+
}
|
663 |
+
|
664 |
+
$header = $gpFlags . $gzType . $dosTime. $fileCRC32
|
665 |
+
. pack("VVv", $gzLength, $dataLength, BinStringStatic::_strlen($filePath)); // File name length
|
666 |
+
|
667 |
+
$zipEntry = self::ZIP_LOCAL_FILE_HEADER
|
668 |
+
. self::ATTR_VERSION_TO_EXTRACT
|
669 |
+
. $header
|
670 |
+
. pack("v", BinStringStatic::_strlen($locExField)) // Extra field length
|
671 |
+
. $filePath // FileName
|
672 |
+
. $locExField; // Extra fields
|
673 |
+
|
674 |
+
$this->onBuildZipEntry(array(
|
675 |
+
'zipEntry' => $zipEntry,
|
676 |
+
));
|
677 |
+
|
678 |
+
$cdEntry = self::ZIP_CENTRAL_FILE_HEADER
|
679 |
+
. self::ATTR_MADE_BY_VERSION
|
680 |
+
. ($dataLength === 0 ? "\x0A\x00" : self::ATTR_VERSION_TO_EXTRACT)
|
681 |
+
. $header
|
682 |
+
. pack("v", BinStringStatic::_strlen($cenExField)) // Extra field length
|
683 |
+
. pack("v", $fileCommentLength) // File comment length
|
684 |
+
. self::NULL_WORD // Disk number start
|
685 |
+
. self::NULL_WORD // internal file attributes
|
686 |
+
. pack("V", $extFileAttr) // External file attributes
|
687 |
+
. pack("V", $this->offset) // Relative offset of local header
|
688 |
+
. $filePath // FileName
|
689 |
+
. $cenExField; // Extra fields
|
690 |
+
|
691 |
+
if (!empty($fileComment)) {
|
692 |
+
$cdEntry .= $fileComment; // Comment
|
693 |
+
}
|
694 |
+
|
695 |
+
$this->cdRec[] = $cdEntry;
|
696 |
+
$this->offset += BinStringStatic::_strlen($zipEntry) + $gzLength;
|
697 |
+
|
698 |
+
$this->_notifyListeners(null, array(
|
699 |
+
'file' => $zipEntry,
|
700 |
+
));
|
701 |
+
}
|
702 |
+
|
703 |
+
/**
|
704 |
+
* Build the base standard response headers, and ensure the content can be streamed.
|
705 |
+
*
|
706 |
+
* @author A. Grandt <php@grandt.com>
|
707 |
+
* @author Greg Kappatos
|
708 |
+
*
|
709 |
+
* @param String $fileName The name of the Zip archive, in ISO-8859-1 (or ASCII) encoding, ie. "archive.zip". Optional, defaults to null, which means that no ISO-8859-1 encoded file name will be specified.
|
710 |
+
* @param String $contentType Content mime type. Optional, defaults to "application/zip".
|
711 |
+
* @param String $utf8FileName The name of the Zip archive, in UTF-8 encoding. Optional, defaults to null, which means that no UTF-8 encoded file name will be specified.
|
712 |
+
* @param bool $inline Use Content-Disposition with "inline" instead of "attached". Optional, defaults to false.
|
713 |
+
*
|
714 |
+
* @throws \PHPZip\Zip\Exception\IncompatiblePhpVersion, BufferNotEmpty, HeadersSent In case of errors
|
715 |
+
*
|
716 |
+
* @return bool Always returns true (for backward compatibility).
|
717 |
+
*/
|
718 |
+
public function buildResponseHeader($fileName = null, $contentType = self::CONTENT_TYPE, $utf8FileName = null, $inline = false) {
|
719 |
+
$ob = null;
|
720 |
+
$headerFile = null;
|
721 |
+
$headerLine = null;
|
722 |
+
$zlibConfig = 'zlib.output_compression';
|
723 |
+
|
724 |
+
$this->onBeginBuildResponseHeader();
|
725 |
+
|
726 |
+
if (!function_exists('sys_get_temp_dir')) {
|
727 |
+
$this->_throwException(new IncompatiblePhpVersionException(array(
|
728 |
+
'appName' => self::APP_NAME,
|
729 |
+
'appVersion' => self::VERSION,
|
730 |
+
'minVersion' => self::MIN_PHP_VERSION,
|
731 |
+
)));
|
732 |
+
}
|
733 |
+
|
734 |
+
$ob = ob_get_contents();
|
735 |
+
if ($ob !== false && BinStringStatic::_strlen($ob)) {
|
736 |
+
$this->_throwException(new BufferNotEmptyException(array(
|
737 |
+
'outputBuffer' => $ob,
|
738 |
+
'fileName' => $fileName,
|
739 |
+
)));
|
740 |
+
}
|
741 |
+
|
742 |
+
if (headers_sent($headerFile, $headerLine)) {
|
743 |
+
$this->_throwException(new HeadersSentException(array(
|
744 |
+
'headerFile' => $headerFile,
|
745 |
+
'headerLine' => $headerLine,
|
746 |
+
'fileName' => $fileName,
|
747 |
+
)));
|
748 |
+
}
|
749 |
+
|
750 |
+
if (@ini_get($zlibConfig)) {
|
751 |
+
@ini_set($zlibConfig, 'Off');
|
752 |
+
}
|
753 |
+
|
754 |
+
$cd = 'Content-Disposition: ' . ($inline ? 'inline' : 'attachment');
|
755 |
+
|
756 |
+
if ($fileName) {
|
757 |
+
$cd .= '; filename="' . $fileName . '"';
|
758 |
+
}
|
759 |
+
|
760 |
+
if ($utf8FileName) {
|
761 |
+
$cd .= "; filename*=UTF-8''" . rawurlencode($utf8FileName);
|
762 |
+
}
|
763 |
+
|
764 |
+
header('Pragma: public');
|
765 |
+
header('Last-Modified: ' . gmdate('D, d M Y H:i:s T'));
|
766 |
+
header('Expires: 0');
|
767 |
+
header('Accept-Ranges: bytes');
|
768 |
+
header('Content-Type: ' . $contentType);
|
769 |
+
header($cd);
|
770 |
+
|
771 |
+
$this->onEndBuildResponseHeader();
|
772 |
+
|
773 |
+
$this->_notifyListeners(null, array(
|
774 |
+
'file' => $fileName,
|
775 |
+
'utf8FileName' => $utf8FileName,
|
776 |
+
'contentType' => $contentType,
|
777 |
+
));
|
778 |
+
|
779 |
+
return true;
|
780 |
+
}
|
781 |
+
|
782 |
+
/**
|
783 |
+
* Close the archive.
|
784 |
+
* A closed archive can no longer have new files added to it.
|
785 |
+
*
|
786 |
+
* @author A. Grandt <php@grandt.com>
|
787 |
+
*
|
788 |
+
* @return bool Success
|
789 |
+
*/
|
790 |
+
public function finalize() {
|
791 |
+
if (!$this->isFinalized) {
|
792 |
+
if (BinStringStatic::_strlen($this->streamFilePath) > 0) {
|
793 |
+
$this->closeStream();
|
794 |
+
}
|
795 |
+
|
796 |
+
$cd = implode("", $this->cdRec);
|
797 |
+
|
798 |
+
$cdRecSize = pack("v", sizeof($this->cdRec));
|
799 |
+
$cdRec = $cd . self::ZIP_END_OF_CENTRAL_DIRECTORY
|
800 |
+
. self::NULL_DWORD // really two words, used for split archives: #ofThisDisk . #ofDiskWithCD. Both 0.
|
801 |
+
. $cdRecSize . $cdRecSize
|
802 |
+
. pack("VV", BinStringStatic::_strlen($cd), $this->offset);
|
803 |
+
|
804 |
+
if (!empty($this->zipComment)) {
|
805 |
+
$cdRec .= pack("v", BinStringStatic::_strlen($this->zipComment))
|
806 |
+
. $this->zipComment;
|
807 |
+
} else {
|
808 |
+
$cdRec .= self::NULL_WORD;
|
809 |
+
}
|
810 |
+
|
811 |
+
$this->zipWrite($cdRec);
|
812 |
+
$this->zipFlushBuffer();
|
813 |
+
|
814 |
+
$this->isFinalized = true;
|
815 |
+
$this->cdRec = null;
|
816 |
+
|
817 |
+
return true;
|
818 |
+
}
|
819 |
+
|
820 |
+
return false;
|
821 |
+
}
|
822 |
+
|
823 |
+
/**
|
824 |
+
* Check PHP version.
|
825 |
+
*
|
826 |
+
* @author A. Grandt <php@grandt.com>
|
827 |
+
*/
|
828 |
+
public function checkVersion() {
|
829 |
+
if (version_compare(PHP_VERSION, self::MIN_PHP_VERSION, '<') || !function_exists('sys_get_temp_dir') ) {
|
830 |
+
die ("ERROR: " . self::APP_NAME . " " . self::VERSION . " requires PHP version " . self::MIN_PHP_VERSION . " or above.");
|
831 |
+
}
|
832 |
+
}
|
833 |
+
|
834 |
+
/*
|
835 |
+
* ************************************************************************
|
836 |
+
* Abstract methods.
|
837 |
+
* ************************************************************************
|
838 |
+
*/
|
839 |
+
|
840 |
+
/**
|
841 |
+
* Called when specialised action is needed
|
842 |
+
* while building a zip entry.
|
843 |
+
*
|
844 |
+
* @author A. Grandt <php@grandt.com>
|
845 |
+
* @author Greg Kappatos
|
846 |
+
*
|
847 |
+
* @param array $params Array that contains zipEntry.
|
848 |
+
*/
|
849 |
+
abstract protected function onBuildZipEntry(array $params);
|
850 |
+
|
851 |
+
/**
|
852 |
+
* Called when specialised action is needed
|
853 |
+
* at the start of adding a file to the archive.
|
854 |
+
*
|
855 |
+
* @author A. Grandt <php@grandt.com>
|
856 |
+
* @author Greg Kappatos
|
857 |
+
*
|
858 |
+
* @param array $params Array that contains gzLength.
|
859 |
+
*/
|
860 |
+
abstract protected function onBeginAddFile(array $params);
|
861 |
+
|
862 |
+
/**
|
863 |
+
* Called when specialised action is needed
|
864 |
+
* at the end of adding a file to the archive.
|
865 |
+
*
|
866 |
+
* @author A. Grandt <php@grandt.com>
|
867 |
+
* @author Greg Kappatos
|
868 |
+
*
|
869 |
+
* @param array $params Array that contains gzData.
|
870 |
+
*/
|
871 |
+
abstract protected function onEndAddFile(array $params);
|
872 |
+
|
873 |
+
/**
|
874 |
+
* Called when specialised action is needed
|
875 |
+
* at the start of sending the zip file|stream
|
876 |
+
* response headers.
|
877 |
+
*
|
878 |
+
* @author A. Grandt <php@grandt.com>
|
879 |
+
* @author Greg Kappatos
|
880 |
+
*/
|
881 |
+
abstract protected function onBeginBuildResponseHeader();
|
882 |
+
|
883 |
+
/**
|
884 |
+
* Called when specialised action is needed
|
885 |
+
* at the end of sending the zip file|stream
|
886 |
+
* response headers.
|
887 |
+
*
|
888 |
+
* @author A. Grandt <php@grandt.com>
|
889 |
+
* @author Greg Kappatos
|
890 |
+
*/
|
891 |
+
abstract protected function onEndBuildResponseHeader();
|
892 |
+
|
893 |
+
/**
|
894 |
+
* Called when specialised action is needed
|
895 |
+
* while opening a file|stream.
|
896 |
+
*
|
897 |
+
* @author A. Grandt <php@grandt.com>
|
898 |
+
* @author Greg Kappatos
|
899 |
+
*/
|
900 |
+
abstract protected function onOpenStream();
|
901 |
+
|
902 |
+
/**
|
903 |
+
* Called when specialised action is needed
|
904 |
+
* while processing a file.
|
905 |
+
*
|
906 |
+
* @author A. Grandt <php@grandt.com>
|
907 |
+
* @author Greg Kappatos
|
908 |
+
*
|
909 |
+
* @param array $params Array that contains data.
|
910 |
+
*/
|
911 |
+
abstract protected function onProcessFile(array $params);
|
912 |
+
|
913 |
+
/**
|
914 |
+
* Verify if the memory buffer is about to be exceeded.
|
915 |
+
*
|
916 |
+
* @author A. Grandt <php@grandt.com>
|
917 |
+
*
|
918 |
+
* @param int $gzLength length of the pending data.
|
919 |
+
*/
|
920 |
+
abstract public function zipVerifyMemBuffer($gzLength);
|
921 |
+
|
922 |
+
/**
|
923 |
+
*
|
924 |
+
* @author A. Grandt <php@grandt.com>
|
925 |
+
*
|
926 |
+
* @param string $data
|
927 |
+
*/
|
928 |
+
//abstract public function zipWrite($data);
|
929 |
+
|
930 |
+
/**
|
931 |
+
* Flush Zip Data stored in memory, to a temp file.
|
932 |
+
*
|
933 |
+
* @author A. Grandt <php@grandt.com>
|
934 |
+
*
|
935 |
+
*/
|
936 |
+
abstract public function zipFlush();
|
937 |
+
|
938 |
+
/**
|
939 |
+
*
|
940 |
+
* @author A. Grandt <php@grandt.com>
|
941 |
+
*
|
942 |
+
*/
|
943 |
+
abstract public function zipFlushBuffer();
|
944 |
+
|
945 |
+
/*
|
946 |
+
* ************************************************************************
|
947 |
+
* Listener methods.
|
948 |
+
* ************************************************************************
|
949 |
+
*/
|
950 |
+
|
951 |
+
/**
|
952 |
+
* Listen to events fired by this class.
|
953 |
+
*
|
954 |
+
* @author Greg Kappatos
|
955 |
+
*
|
956 |
+
* @param ZipArchiveListener $listener Class that implements the ZipArchiveListener interface.
|
957 |
+
*/
|
958 |
+
public function addListener(ZipArchiveListener $listener) {
|
959 |
+
$this->_listeners[] = $listener;
|
960 |
+
}
|
961 |
+
|
962 |
+
/**
|
963 |
+
* Stop listening to events fired by this class.
|
964 |
+
*
|
965 |
+
* @author Greg Kappatos
|
966 |
+
*
|
967 |
+
* @param ZipArchiveListener $listener Class that implements the ZipArchiveListener interface.
|
968 |
+
*/
|
969 |
+
public function removeListener(ZipArchiveListener $listener) {
|
970 |
+
$key = array_search($listener, $this->_listeners);
|
971 |
+
|
972 |
+
if ($key !== false) {
|
973 |
+
unset($this->_listeners[$key]);
|
974 |
+
}
|
975 |
+
}
|
976 |
+
|
977 |
+
/**
|
978 |
+
* Helper method to fire appropriate event.
|
979 |
+
*
|
980 |
+
* @author Greg Kappatos
|
981 |
+
*
|
982 |
+
* @param string|null $method (Optional) The name of the event to fire. If this is null, then the calling method is used.
|
983 |
+
* @param array $data Method parameters passed as an array.
|
984 |
+
*/
|
985 |
+
private function _notifyListeners($method = null, array $data = array()) {
|
986 |
+
if (is_null($method)) {
|
987 |
+
$backtrace = debug_backtrace();
|
988 |
+
if (sizeof($backtrace) > 0) {
|
989 |
+
$trace = $backtrace[1];
|
990 |
+
$method = 'on' . ucwords($trace['function']);
|
991 |
+
}
|
992 |
+
}
|
993 |
+
|
994 |
+
foreach ($this->_listeners as $listener) {
|
995 |
+
if (count($data) > 0) {
|
996 |
+
$listener->$method($data);
|
997 |
+
} else {
|
998 |
+
$listener->$method();
|
999 |
+
}
|
1000 |
+
}
|
1001 |
+
}
|
1002 |
+
|
1003 |
+
/**
|
1004 |
+
* Helper method to fire OnException event for listeners and then throw the appropriate exception.
|
1005 |
+
*
|
1006 |
+
* @author Greg Kappatos
|
1007 |
+
*
|
1008 |
+
* @param AbstractException $exception Whatever exception needs to be thrown.
|
1009 |
+
*
|
1010 |
+
* @throws AbstractException $exception
|
1011 |
+
*/
|
1012 |
+
private function _throwException(AbstractException $exception) {
|
1013 |
+
$this->_notifyListeners('onException', array(
|
1014 |
+
'exception' => $exception,
|
1015 |
+
));
|
1016 |
+
|
1017 |
+
throw $exception;
|
1018 |
+
}
|
1019 |
+
|
1020 |
+
/*
|
1021 |
+
* ************************************************************************
|
1022 |
+
* Static methods/
|
1023 |
+
* ************************************************************************
|
1024 |
+
*/
|
1025 |
+
|
1026 |
+
/**
|
1027 |
+
*
|
1028 |
+
* @author A. Grandt <php@grandt.com>
|
1029 |
+
* @author Greg Kappatos
|
1030 |
+
*
|
1031 |
+
* @return string The full path to a temporary file.
|
1032 |
+
*/
|
1033 |
+
public static function getTemporaryFile() {
|
1034 |
+
if (is_callable(self::$temp)) {
|
1035 |
+
$file = @call_user_func(self::$temp);
|
1036 |
+
|
1037 |
+
if (is_string($file) && BinStringStatic::_strlen($file) && is_writable($file)) {
|
1038 |
+
return $file;
|
1039 |
+
}
|
1040 |
+
}
|
1041 |
+
|
1042 |
+
$dir = (is_string(self::$temp) && BinStringStatic::_strlen(self::$temp)) ? self::$temp : sys_get_temp_dir();
|
1043 |
+
|
1044 |
+
return tempnam($dir, __NAMESPACE__);
|
1045 |
+
}
|
1046 |
+
}
|
includes/extensions/zip/Core/ZipUtils.php
ADDED
@@ -0,0 +1,125 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace PHPZip\Zip\Core;
|
3 |
+
|
4 |
+
use com\grandt\BinStringStatic;
|
5 |
+
|
6 |
+
class ZipUtils {
|
7 |
+
// Unix file types
|
8 |
+
const S_IFIFO = 0010000; // named pipe (fifo)
|
9 |
+
const S_IFCHR = 0020000; // character special
|
10 |
+
const S_IFDIR = 0040000; // directory
|
11 |
+
const S_IFBLK = 0060000; // block special
|
12 |
+
const S_IFREG = 0100000; // regular
|
13 |
+
const S_IFLNK = 0120000; // symbolic link
|
14 |
+
const S_IFSOCK = 0140000; // socket
|
15 |
+
|
16 |
+
// setuid/setgid/sticky bits, the same as for chmod:
|
17 |
+
const S_ISUID = 0004000; // set user id on execution
|
18 |
+
const S_ISGID = 0002000; // set group id on execution
|
19 |
+
const S_ISTXT = 0001000; // sticky bit
|
20 |
+
|
21 |
+
// And of course, the other 12 bits are for the permissions, the same as for chmod:
|
22 |
+
// When adding these up, you can also just write the permissions as a single octal number
|
23 |
+
// ie. 0755. The leading 0 specifies octal notation.
|
24 |
+
const S_IRWXU = 0000700; // RWX mask for owner
|
25 |
+
const S_IRUSR = 0000400; // R for owner
|
26 |
+
const S_IWUSR = 0000200; // W for owner
|
27 |
+
const S_IXUSR = 0000100; // X for owner
|
28 |
+
const S_IRWXG = 0000070; // RWX mask for group
|
29 |
+
const S_IRGRP = 0000040; // R for group
|
30 |
+
const S_IWGRP = 0000020; // W for group
|
31 |
+
const S_IXGRP = 0000010; // X for group
|
32 |
+
const S_IRWXO = 0000007; // RWX mask for other
|
33 |
+
const S_IROTH = 0000004; // R for other
|
34 |
+
const S_IWOTH = 0000002; // W for other
|
35 |
+
const S_IXOTH = 0000001; // X for other
|
36 |
+
const S_ISVTX = 0001000; // save swapped text even after use
|
37 |
+
|
38 |
+
// File type, sticky and permissions are added up, and shifted 16 bits left BEFORE adding the DOS flags.
|
39 |
+
// DOS file type flags, we really only use the S_DOS_D flag.
|
40 |
+
const S_DOS_A = 0000040; // DOS flag for Archive
|
41 |
+
const S_DOS_D = 0000020; // DOS flag for Directory
|
42 |
+
const S_DOS_V = 0000010; // DOS flag for Volume
|
43 |
+
const S_DOS_S = 0000004; // DOS flag for System
|
44 |
+
const S_DOS_H = 0000002; // DOS flag for Hidden
|
45 |
+
const S_DOS_R = 0000001; // DOS flag for Read Only
|
46 |
+
|
47 |
+
/**
|
48 |
+
* Calculate the 2 byte dos time used in the zip entries.
|
49 |
+
*
|
50 |
+
* @author A. Grandt <php@grandt.com>
|
51 |
+
*
|
52 |
+
* @param int $timestamp
|
53 |
+
*
|
54 |
+
* @return string 2-byte encoded DOS Date
|
55 |
+
*/
|
56 |
+
public static function getDosTime($timestamp = 0) {
|
57 |
+
$timestamp = (int)$timestamp;
|
58 |
+
$oldTZ = @date_default_timezone_get();
|
59 |
+
date_default_timezone_set('UTC');
|
60 |
+
|
61 |
+
$date = ($timestamp == 0 ? getdate() : getdate($timestamp));
|
62 |
+
date_default_timezone_set($oldTZ);
|
63 |
+
|
64 |
+
if ($date["year"] >= 1980) { // Dos dates start on 1 Jan 1980
|
65 |
+
return pack("V", (($date["mday"] + ($date["mon"] << 5) + (($date["year"] - 1980) << 9)) << 16) |
|
66 |
+
(($date["seconds"] >> 1) + ($date["minutes"] << 5) + ($date["hours"] << 11)));
|
67 |
+
}
|
68 |
+
return "\x00\x00\x00\x00";
|
69 |
+
}
|
70 |
+
|
71 |
+
/**
|
72 |
+
* Create the file permissions for a file or directory, for use in the extFileAttr parameters.
|
73 |
+
*
|
74 |
+
* @author A. Grandt <php@grandt.com>
|
75 |
+
*
|
76 |
+
* @param int $owner Unix permissions for owner (octal from 00 to 07)
|
77 |
+
* @param int $group Unix permissions for group (octal from 00 to 07)
|
78 |
+
* @param int $other Unix permissions for others (octal from 00 to 07)
|
79 |
+
* @param bool $isFile
|
80 |
+
*
|
81 |
+
* @return string EXTERNAL_REF field.
|
82 |
+
*/
|
83 |
+
public static function generateExtAttr($owner = 07, $group = 05, $other = 05, $isFile = true) {
|
84 |
+
$fp = $isFile ? self::S_IFREG : self::S_IFDIR;
|
85 |
+
$fp |= (($owner & 07) << 6) | (($group & 07) << 3) | ($other & 07);
|
86 |
+
|
87 |
+
return ($fp << 16) | ($isFile ? self::S_DOS_A : self::S_DOS_D);
|
88 |
+
}
|
89 |
+
|
90 |
+
/**
|
91 |
+
* Get the file permissions for a file or directory, for use in the extFileAttr parameters.
|
92 |
+
*
|
93 |
+
* @author A. Grandt <php@grandt.com>
|
94 |
+
*
|
95 |
+
* @param string $filename
|
96 |
+
*
|
97 |
+
* @return string|bool external ref field, or false if the file is not found.
|
98 |
+
*/
|
99 |
+
public static function getFileExtAttr($filename) {
|
100 |
+
if (file_exists($filename)) {
|
101 |
+
$fp = fileperms($filename) << 16;
|
102 |
+
return $fp | (is_dir($filename) ? self::S_DOS_D : self::S_DOS_A);
|
103 |
+
}
|
104 |
+
|
105 |
+
return false;
|
106 |
+
}
|
107 |
+
|
108 |
+
public static function testBit($data, $bit) {
|
109 |
+
$bv = 1 << $bit;
|
110 |
+
return ($data & $bv) == $bv;
|
111 |
+
}
|
112 |
+
|
113 |
+
public static function setBit(&$data, $bit, $value = true) {
|
114 |
+
if ($value) {
|
115 |
+
$data |= (1 << $bit);
|
116 |
+
} else {
|
117 |
+
self::clrBit($data, $bit);
|
118 |
+
}
|
119 |
+
|
120 |
+
}
|
121 |
+
|
122 |
+
public static function clrBit(&$data, $bit) {
|
123 |
+
$data &= ~(1 << $bit);
|
124 |
+
}
|
125 |
+
}
|
includes/extensions/zip/Core/index.html
ADDED
File without changes
|
includes/extensions/zip/Exception/BufferNotEmpty.php
ADDED
@@ -0,0 +1,46 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
*
|
4 |
+
* @author Greg Kappatos
|
5 |
+
*
|
6 |
+
* This class serves as a concrete exception.
|
7 |
+
* It will be thrown if the output buffer contains data while
|
8 |
+
* trying to perform any operations with this library.
|
9 |
+
*
|
10 |
+
*/
|
11 |
+
|
12 |
+
namespace PHPZip\Zip\Exception;
|
13 |
+
|
14 |
+
use PHPZip\Zip\Core\AbstractException;
|
15 |
+
|
16 |
+
class BufferNotEmpty extends AbstractException {
|
17 |
+
|
18 |
+
private $_outputBuffer = null;
|
19 |
+
private $_fileName = null;
|
20 |
+
|
21 |
+
/**
|
22 |
+
* Constructor
|
23 |
+
*
|
24 |
+
* @author A. Grandt <php@grandt.com>
|
25 |
+
* @author Greg Kappatos
|
26 |
+
*
|
27 |
+
* @param array $config Configuration array containing outputBuffer and fileName
|
28 |
+
*/
|
29 |
+
public function __construct(array $config){
|
30 |
+
$this->_outputBuffer = $config['outputBuffer'];
|
31 |
+
$this->_fileName = isset($config['fileName']) ? $config['fileName'] : null;
|
32 |
+
|
33 |
+
$message = is_null($this->_fileName) ? '' : "Unable to send '{$this->_fileName}'. ";
|
34 |
+
$message .= "Output buffer contains the following text (typically warning or errors):\n{$this->_outputBuffer}";
|
35 |
+
|
36 |
+
parent::__construct($message);
|
37 |
+
}
|
38 |
+
|
39 |
+
public function getOutputBuffer(){
|
40 |
+
return $this->_outputBuffer;
|
41 |
+
}
|
42 |
+
|
43 |
+
public function getFileName(){
|
44 |
+
return $this->_fileName;
|
45 |
+
}
|
46 |
+
}
|
includes/extensions/zip/Exception/HeaderPositionError.php
ADDED
@@ -0,0 +1,52 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
*
|
4 |
+
* @author Greg Kappatos
|
5 |
+
*
|
6 |
+
* This class serves as a concrete exception.
|
7 |
+
* It will be thrown if the output length of fwrite() does not match
|
8 |
+
* the input length. So far, this only occurs in Core\AbstractZipArchive::addStreamData()
|
9 |
+
*
|
10 |
+
*/
|
11 |
+
|
12 |
+
namespace PHPZip\Zip\Exception;
|
13 |
+
|
14 |
+
use PHPZip\Zip\Core\AbstractException;
|
15 |
+
|
16 |
+
class HeaderPositionError extends AbstractException {
|
17 |
+
|
18 |
+
private $_expected = null;
|
19 |
+
private $_actual = null;
|
20 |
+
|
21 |
+
/**
|
22 |
+
* Constructor
|
23 |
+
*
|
24 |
+
* @author A. Grandt <php@grandt.com>
|
25 |
+
* @author Greg Kappatos
|
26 |
+
*
|
27 |
+
* @param array $config Configuration array containing expected and written
|
28 |
+
*/
|
29 |
+
public function __construct(array $config){
|
30 |
+
$this->_expected = (string)$config['expected'];
|
31 |
+
$this->_actual = (string)$config['actual'];
|
32 |
+
|
33 |
+
$message = sprintf(
|
34 |
+
'%s %s %s %s %s',
|
35 |
+
(string)($this->_actual - $this->_expected),
|
36 |
+
' extra bytes before header. Expected pos ',
|
37 |
+
$this->_expected,
|
38 |
+
' but found the header at ',
|
39 |
+
$this->_actual
|
40 |
+
);
|
41 |
+
|
42 |
+
parent::__construct($message);
|
43 |
+
}
|
44 |
+
|
45 |
+
public function getExpected(){
|
46 |
+
return $this->_expected;
|
47 |
+
}
|
48 |
+
|
49 |
+
public function getActual(){
|
50 |
+
return $this->_actual;
|
51 |
+
}
|
52 |
+
}
|
includes/extensions/zip/Exception/HeadersSent.php
ADDED
@@ -0,0 +1,52 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
*
|
4 |
+
* @author Greg Kappatos
|
5 |
+
*
|
6 |
+
* This class serves as a concrete exception.
|
7 |
+
* It will be thrown if any headers have been sent, or if any
|
8 |
+
* output has been printed or echoed.
|
9 |
+
*
|
10 |
+
*/
|
11 |
+
|
12 |
+
namespace PHPZip\Zip\Exception;
|
13 |
+
|
14 |
+
use PHPZip\Zip\Core\AbstractException;
|
15 |
+
|
16 |
+
class HeadersSent extends AbstractException {
|
17 |
+
|
18 |
+
private $_headerFile = null;
|
19 |
+
private $_headerLine = null;
|
20 |
+
private $_fileName = null;
|
21 |
+
|
22 |
+
/**
|
23 |
+
* Constructor
|
24 |
+
*
|
25 |
+
* @author A. Grandt <php@grandt.com>
|
26 |
+
* @author Greg Kappatos
|
27 |
+
*
|
28 |
+
* @param array $config Configuration array containing headerFile, headerLine and fileName
|
29 |
+
*/
|
30 |
+
public function __construct(array $config){
|
31 |
+
$this->_headerFile = $config['headerFile'];
|
32 |
+
$this->_headerLine = $config['headerLine'];
|
33 |
+
$this->_fileName = isset($config['fileName']) ? $config['fileName'] : null;
|
34 |
+
|
35 |
+
$message = is_null($this->_fileName) ? '' : "Unable to send '{$this->_fileName}'. ";
|
36 |
+
$message .= "Headers have already been sent from '{$this->_headerFile}' in line {$this->_headerLine}";
|
37 |
+
|
38 |
+
parent::__construct($message);
|
39 |
+
}
|
40 |
+
|
41 |
+
public function getHeaderFile(){
|
42 |
+
return $this->_headerFile;
|
43 |
+
}
|
44 |
+
|
45 |
+
public function getHeaderLine(){
|
46 |
+
return $this->_headerLine;
|
47 |
+
}
|
48 |
+
|
49 |
+
public function getFileName(){
|
50 |
+
return $this->_fileName;
|
51 |
+
}
|
52 |
+
}
|
includes/extensions/zip/Exception/IncompatiblePhpVersion.php
ADDED
@@ -0,0 +1,54 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
*
|
4 |
+
* @author Greg Kappatos
|
5 |
+
*
|
6 |
+
* This class serves as a concrete exception.
|
7 |
+
* It will be thrown if the current PHP version is below the minimum
|
8 |
+
* required version.
|
9 |
+
*
|
10 |
+
*/
|
11 |
+
|
12 |
+
namespace PHPZip\Zip\Exception;
|
13 |
+
|
14 |
+
use PHPZip\Zip\Core\AbstractException;
|
15 |
+
|
16 |
+
class IncompatiblePhpVersion extends AbstractException {
|
17 |
+
|
18 |
+
private $_minVersion = null;
|
19 |
+
private $_currentVersion = null;
|
20 |
+
|
21 |
+
/**
|
22 |
+
* Constructor
|
23 |
+
*
|
24 |
+
* @author A. Grandt <php@grandt.com>
|
25 |
+
* @author Greg Kappatos
|
26 |
+
*
|
27 |
+
* @param array $config Configuration array containing appName, appVersion and minVersion (PHP)
|
28 |
+
*/
|
29 |
+
public function __construct(array $config){
|
30 |
+
$this->_minVersion = (string)$config['minVersion'];
|
31 |
+
$this->_currentVersion = (string)phpversion();
|
32 |
+
|
33 |
+
$message = sprintf(
|
34 |
+
'%s %s %s %s %s (%s %s).',
|
35 |
+
$config['appName'],
|
36 |
+
(string)$config['appVersion'],
|
37 |
+
'requires PHP version',
|
38 |
+
$this->_minVersion,
|
39 |
+
'or above',
|
40 |
+
$this->_currentVersion,
|
41 |
+
'detected'
|
42 |
+
);
|
43 |
+
|
44 |
+
parent::__construct($message);
|
45 |
+
}
|
46 |
+
|
47 |
+
public function getMinVersion(){
|
48 |
+
return $this->_minVersion;
|
49 |
+
}
|
50 |
+
|
51 |
+
public function getCurrentVersion(){
|
52 |
+
return $this->_currentVersion;
|
53 |
+
}
|
54 |
+
}
|
includes/extensions/zip/Exception/InvalidPhpConfiguration.php
ADDED
@@ -0,0 +1,58 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
*
|
4 |
+
* @author Greg Kappatos
|
5 |
+
*
|
6 |
+
* This class serves as a concrete exception.
|
7 |
+
* It will be thrown if an invalid setting is detected in php.ini
|
8 |
+
* that will prevent this library from operating properly.
|
9 |
+
*
|
10 |
+
*/
|
11 |
+
|
12 |
+
namespace PHPZip\Zip\Exception;
|
13 |
+
|
14 |
+
use PHPZip\Zip\Core\AbstractException;
|
15 |
+
|
16 |
+
class InvalidPhpConfiguration extends AbstractException {
|
17 |
+
|
18 |
+
private $_setting = null;
|
19 |
+
private $_expected = null;
|
20 |
+
private $_actual = null;
|
21 |
+
|
22 |
+
/**
|
23 |
+
* Constructor
|
24 |
+
*
|
25 |
+
* @author Greg Kappatos
|
26 |
+
*
|
27 |
+
* @param array $config Configuration array containing php.ini settings: setting and expected (value)
|
28 |
+
*/
|
29 |
+
public function __construct(array $config){
|
30 |
+
$this->_setting = $config['setting'];
|
31 |
+
$this->_expected = $config['expected'];
|
32 |
+
$this->_actual = (string)@ini_get($this->_setting);
|
33 |
+
|
34 |
+
$message = sprintf(
|
35 |
+
'%s %s "%s" %s %s %s',
|
36 |
+
'Invalid PHP Configuration: ',
|
37 |
+
$this->_setting,
|
38 |
+
$this->_actual,
|
39 |
+
'Please change this setting to',
|
40 |
+
$this->_expected,
|
41 |
+
'to continue.'
|
42 |
+
);
|
43 |
+
|
44 |
+
parent::__construct($message);
|
45 |
+
}
|
46 |
+
|
47 |
+
public function getSetting(){
|
48 |
+
return $this->_setting;
|
49 |
+
}
|
50 |
+
|
51 |
+
public function getExpected(){
|
52 |
+
return $this->_expected;
|
53 |
+
}
|
54 |
+
|
55 |
+
public function getActual(){
|
56 |
+
return $this->_actual;
|
57 |
+
}
|
58 |
+
}
|
includes/extensions/zip/Exception/LengthMismatch.php
ADDED
@@ -0,0 +1,51 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
*
|
4 |
+
* @author Greg Kappatos
|
5 |
+
*
|
6 |
+
* This class serves as a concrete exception.
|
7 |
+
* It will be thrown if the output length of fwrite() does not match
|
8 |
+
* the input length. So far, this only occurs in Core\AbstractZipArchive::addStreamData()
|
9 |
+
*
|
10 |
+
*/
|
11 |
+
|
12 |
+
namespace PHPZip\Zip\Exception;
|
13 |
+
|
14 |
+
use PHPZip\Zip\Core\AbstractException;
|
15 |
+
|
16 |
+
class LengthMismatch extends AbstractException {
|
17 |
+
|
18 |
+
private $_expected = null;
|
19 |
+
private $_written = null;
|
20 |
+
|
21 |
+
/**
|
22 |
+
* Constructor
|
23 |
+
*
|
24 |
+
* @author A. Grandt <php@grandt.com>
|
25 |
+
* @author Greg Kappatos
|
26 |
+
*
|
27 |
+
* @param array $config Configuration array containing expected and written
|
28 |
+
*/
|
29 |
+
public function __construct(array $config){
|
30 |
+
$this->_expected = (string)$config['expected'];
|
31 |
+
$this->_written = (string)$config['written'];
|
32 |
+
|
33 |
+
$message = sprintf(
|
34 |
+
'%s %s %s %s',
|
35 |
+
'Length Mismatch Error: Expected',
|
36 |
+
$this->_expected,
|
37 |
+
'bytes, wrote',
|
38 |
+
$this->_written
|
39 |
+
);
|
40 |
+
|
41 |
+
parent::__construct($message);
|
42 |
+
}
|
43 |
+
|
44 |
+
public function getExpected(){
|
45 |
+
return $this->_expected;
|
46 |
+
}
|
47 |
+
|
48 |
+
public function getWritten(){
|
49 |
+
return $this->_written;
|
50 |
+
}
|
51 |
+
}
|
includes/extensions/zip/Exception/index.html
ADDED
File without changes
|
includes/extensions/zip/File/Zip.php
ADDED
@@ -0,0 +1,187 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
*
|
4 |
+
* @author A. Grandt <php@grandt.com>
|
5 |
+
* @author Greg Kappatos
|
6 |
+
*
|
7 |
+
* This class serves as a concrete zip file archive.
|
8 |
+
*
|
9 |
+
*/
|
10 |
+
|
11 |
+
namespace PHPZip\Zip\File;
|
12 |
+
|
13 |
+
use com\grandt\BinStringStatic;
|
14 |
+
use PHPZip\Zip\Core\AbstractZipArchive;
|
15 |
+
|
16 |
+
class Zip extends AbstractZipArchive {
|
17 |
+
|
18 |
+
const MEMORY_THRESHOLD = 1048576; // 1 MB - Auto create temp file if the zip data exceeds this
|
19 |
+
const STREAM_CHUNK_SIZE = 65536; // 64 KB
|
20 |
+
|
21 |
+
private $_zipData = null;
|
22 |
+
private $_zipFile = null;
|
23 |
+
|
24 |
+
public function __construct($useZipFile = false) {
|
25 |
+
parent::__construct(self::STREAM_CHUNK_SIZE);
|
26 |
+
|
27 |
+
if ($useZipFile) {
|
28 |
+
$this->_zipFile = tmpfile();
|
29 |
+
} else {
|
30 |
+
$this->_zipData = '';
|
31 |
+
}
|
32 |
+
}
|
33 |
+
|
34 |
+
public function __destruct() {
|
35 |
+
if (is_resource($this->_zipFile)) {
|
36 |
+
fclose($this->_zipFile);
|
37 |
+
}
|
38 |
+
|
39 |
+
$this->_zipData = null;
|
40 |
+
}
|
41 |
+
|
42 |
+
public function setZipFile($fileName) {
|
43 |
+
if (is_file($fileName)) {
|
44 |
+
unlink($fileName);
|
45 |
+
}
|
46 |
+
|
47 |
+
$fd = fopen($fileName, "x+b");
|
48 |
+
|
49 |
+
if (is_resource($this->_zipFile)) {
|
50 |
+
rewind($this->_zipFile);
|
51 |
+
|
52 |
+
while (!feof($this->_zipFile)) {
|
53 |
+
fwrite($fd, fread($this->_zipFile, $this->streamChunkSize));
|
54 |
+
}
|
55 |
+
|
56 |
+
fclose($this->_zipFile);
|
57 |
+
} else {
|
58 |
+
fwrite($fd, $this->_zipData);
|
59 |
+
$this->_zipData = null;
|
60 |
+
}
|
61 |
+
|
62 |
+
$this->_zipFile = $fd;
|
63 |
+
return true;
|
64 |
+
}
|
65 |
+
|
66 |
+
public function saveZipFile($fileName) {
|
67 |
+
return $this->setZipFile($fileName);
|
68 |
+
}
|
69 |
+
|
70 |
+
public function getZipFile() {
|
71 |
+
if (!$this->isFinalized) {
|
72 |
+
$this->finalize();
|
73 |
+
}
|
74 |
+
|
75 |
+
$this->zipFlush();
|
76 |
+
rewind($this->_zipFile);
|
77 |
+
return $this->_zipFile;
|
78 |
+
}
|
79 |
+
|
80 |
+
public function sendZip($fileName = null, $contentType = self::CONTENT_TYPE, $utf8FileName = null, $inline = false) {
|
81 |
+
if (!$this->isFinalized) {
|
82 |
+
$this->finalize();
|
83 |
+
}
|
84 |
+
|
85 |
+
if ($this->buildResponseHeader($fileName, $contentType, $utf8FileName, $inline)) {
|
86 |
+
return true;
|
87 |
+
}
|
88 |
+
return false;
|
89 |
+
}
|
90 |
+
|
91 |
+
public function getZipData() {
|
92 |
+
$result = null;
|
93 |
+
|
94 |
+
if (!$this->isFinalized) {
|
95 |
+
$this->finalize();
|
96 |
+
}
|
97 |
+
|
98 |
+
if (!is_resource($this->_zipFile)) {
|
99 |
+
$result = $this->_zipData;
|
100 |
+
} else {
|
101 |
+
rewind($this->_zipFile);
|
102 |
+
$stat = fstat($this->_zipFile);
|
103 |
+
$result = fread($this->_zipFile, $stat['size']);
|
104 |
+
}
|
105 |
+
|
106 |
+
return $result;
|
107 |
+
}
|
108 |
+
|
109 |
+
public function getArchiveSize() {
|
110 |
+
if (!is_resource($this->_zipFile)) {
|
111 |
+
return BinStringStatic::_strlen($this->_zipData);
|
112 |
+
}
|
113 |
+
|
114 |
+
$stat = fstat($this->_zipFile);
|
115 |
+
return $stat['size'];
|
116 |
+
}
|
117 |
+
|
118 |
+
public function onBuildZipEntry(array $params) {
|
119 |
+
$this->zipWrite($params['zipEntry']);
|
120 |
+
}
|
121 |
+
|
122 |
+
public function onBeginAddFile(array $params) {
|
123 |
+
if (!is_resource($this->_zipFile) && ($this->offset + $params['gzLength']) > self::MEMORY_THRESHOLD) {
|
124 |
+
$this->zipFlush();
|
125 |
+
}
|
126 |
+
}
|
127 |
+
|
128 |
+
public function onEndAddFile(array $params) {
|
129 |
+
$this->zipWrite($params['gzData']);
|
130 |
+
}
|
131 |
+
|
132 |
+
public function onBeginBuildResponseHeader() {
|
133 |
+
if (!$this->isFinalized) {
|
134 |
+
$this->finalize();
|
135 |
+
}
|
136 |
+
}
|
137 |
+
|
138 |
+
public function onEndBuildResponseHeader() {
|
139 |
+
header('Connection: close');
|
140 |
+
header('Content-Length: ' . $this->getArchiveSize());
|
141 |
+
|
142 |
+
if (!is_resource($this->_zipFile)) {
|
143 |
+
echo $this->_zipData;
|
144 |
+
} else {
|
145 |
+
rewind($this->_zipFile);
|
146 |
+
|
147 |
+
while (!feof($this->_zipFile)) {
|
148 |
+
echo fread($this->_zipFile, $this->streamChunkSize);
|
149 |
+
}
|
150 |
+
}
|
151 |
+
}
|
152 |
+
|
153 |
+
public function onOpenStream() {
|
154 |
+
$this->zipFlush();
|
155 |
+
}
|
156 |
+
|
157 |
+
public function onProcessFile(array $params) {
|
158 |
+
$this->zipWrite($params['data']);
|
159 |
+
}
|
160 |
+
|
161 |
+
public function zipVerifyMemBuffer($gzLength) {
|
162 |
+
if (!is_resource($this->_zipFile) && ($this->offset + $gzLength) > self::MEMORY_THRESHOLD) {
|
163 |
+
$this->zipFlush();
|
164 |
+
}
|
165 |
+
}
|
166 |
+
|
167 |
+
public function zipWrite($data) {
|
168 |
+
if (!is_resource($this->_zipFile)) {
|
169 |
+
$this->_zipData .= $data;
|
170 |
+
} else {
|
171 |
+
fwrite($this->_zipFile, $data);
|
172 |
+
fflush($this->_zipFile);
|
173 |
+
}
|
174 |
+
}
|
175 |
+
|
176 |
+
public function zipFlush() {
|
177 |
+
if (!is_resource($this->_zipFile)) {
|
178 |
+
$this->_zipFile = tmpfile();
|
179 |
+
fwrite($this->_zipFile, $this->_zipData);
|
180 |
+
$this->_zipData = null;
|
181 |
+
}
|
182 |
+
}
|
183 |
+
|
184 |
+
public function zipFlushBuffer() {
|
185 |
+
// Does nothing.
|
186 |
+
}
|
187 |
+
}
|
includes/extensions/zip/File/index.html
ADDED
File without changes
|
includes/extensions/zip/Listener/ZipArchiveListener.php
ADDED
@@ -0,0 +1,29 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
*
|
4 |
+
* @author Greg Kappatos
|
5 |
+
*
|
6 |
+
* This class serves as an observer/listener which can be implemented
|
7 |
+
* by any other class who is interested in the PHPZip events.
|
8 |
+
* Simply implement the methods and call Stream\ZipStream or
|
9 |
+
* File\Zip::addListener($this) from inside your class.
|
10 |
+
*
|
11 |
+
*/
|
12 |
+
|
13 |
+
namespace PHPZip\Zip\Listener;
|
14 |
+
|
15 |
+
interface ZipArchiveListener {
|
16 |
+
|
17 |
+
public function onBuildZipEntry(array $params);
|
18 |
+
|
19 |
+
public function onOpenStream(array $params);
|
20 |
+
|
21 |
+
public function onAddFile(array $params);
|
22 |
+
|
23 |
+
public function onAddLargeFile(array $params);
|
24 |
+
|
25 |
+
public function onSendZip(array $params);
|
26 |
+
|
27 |
+
public function onException(array $params);
|
28 |
+
|
29 |
+
}
|
includes/extensions/zip/Listener/index.html
ADDED
File without changes
|
includes/extensions/zip/Stream/ZipStream.php
ADDED
@@ -0,0 +1,204 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
*
|
4 |
+
* @author A. Grandt <php@grandt.com>
|
5 |
+
* @author Greg Kappatos
|
6 |
+
*
|
7 |
+
* This class serves as a concrete zip stream archive.
|
8 |
+
*
|
9 |
+
*/
|
10 |
+
|
11 |
+
namespace PHPZip\Zip\Stream;
|
12 |
+
|
13 |
+
use PHPZip\Zip\Core\AbstractZipArchive;
|
14 |
+
|
15 |
+
class ZipStream extends AbstractZipArchive {
|
16 |
+
|
17 |
+
const STREAM_CHUNK_SIZE = 16384; // 16 KB
|
18 |
+
private $maxStreamBufferLength = 1048576;
|
19 |
+
|
20 |
+
/**
|
21 |
+
* Constructor.
|
22 |
+
*
|
23 |
+
* @author A. Grandt <php@grandt.com>
|
24 |
+
* @author Greg Kappatos
|
25 |
+
*
|
26 |
+
* @param String $fileName The name of the Zip archive, in ISO-8859-1 (or ASCII) encoding, ie. "archive.zip". Optional, defaults to NULL, which means that no ISO-8859-1 encoded file name will be specified.
|
27 |
+
* @param String $contentType Content mime type. Optional, defaults to "application/zip".
|
28 |
+
* @param String $utf8FileName The name of the Zip archive, in UTF-8 encoding. Optional, defaults to NULL, which means that no UTF-8 encoded file name will be specified.
|
29 |
+
* @param bool $inline Use Content-Disposition with "inline" instead of "attached". Optional, defaults to FALSE.
|
30 |
+
*
|
31 |
+
* @throws \PHPZip\Zip\Exception\BufferNotEmpty, HeadersSent, IncompatiblePhpVersion, InvalidPhpConfiguration In case of errors
|
32 |
+
*/
|
33 |
+
public function __construct($fileName = '', $contentType = self::CONTENT_TYPE, $utf8FileName = null, $inline = false) {
|
34 |
+
parent::__construct(self::STREAM_CHUNK_SIZE);
|
35 |
+
$this->buildResponseHeader($fileName, $contentType, $utf8FileName, $inline);
|
36 |
+
}
|
37 |
+
|
38 |
+
/**
|
39 |
+
* Destructor.
|
40 |
+
* Perform clean up actions.
|
41 |
+
* Please note that frameworks are absolutely prohibited from sending ANYTHING to the output after the Zip is sent.
|
42 |
+
*
|
43 |
+
* @author A. Grandt <php@grandt.com>
|
44 |
+
*/
|
45 |
+
public function __destruct(){
|
46 |
+
$this->isFinalized = true;
|
47 |
+
$this->cdRec = null;
|
48 |
+
}
|
49 |
+
|
50 |
+
/*
|
51 |
+
* ************************************************************************
|
52 |
+
* Superclass callbacks.
|
53 |
+
* ************************************************************************
|
54 |
+
*/
|
55 |
+
|
56 |
+
/**
|
57 |
+
* Called by superclass when specialised action is needed
|
58 |
+
* while building a zip entry.
|
59 |
+
*
|
60 |
+
* @author A. Grandt <php@grandt.com>
|
61 |
+
* @author Greg Kappatos
|
62 |
+
*
|
63 |
+
* @param array $params Array that contains zipEntry.
|
64 |
+
*/
|
65 |
+
public function onBuildZipEntry(array $params){
|
66 |
+
print($params['zipEntry']);
|
67 |
+
}
|
68 |
+
|
69 |
+
/**
|
70 |
+
* Called by superclass when specialised action is needed
|
71 |
+
* at the start of adding a file to the archive.
|
72 |
+
*
|
73 |
+
* @author A. Grandt <php@grandt.com>
|
74 |
+
* @author Greg Kappatos
|
75 |
+
*
|
76 |
+
* @param array $params Array that contains gzLength.
|
77 |
+
*/
|
78 |
+
public function onBeginAddFile(array $params){
|
79 |
+
// Do nothing.
|
80 |
+
}
|
81 |
+
|
82 |
+
/**
|
83 |
+
* Called by superclass when specialised action is needed
|
84 |
+
* at the end of adding a file to the archive.
|
85 |
+
*
|
86 |
+
* @author A. Grandt <php@grandt.com>
|
87 |
+
* @author Greg Kappatos
|
88 |
+
*
|
89 |
+
* @param array $params Array that contains gzData.
|
90 |
+
*/
|
91 |
+
public function onEndAddFile(array $params){
|
92 |
+
print($params['gzData']);
|
93 |
+
}
|
94 |
+
|
95 |
+
/**
|
96 |
+
* Called by superclass when specialised action is needed
|
97 |
+
* at the start of sending the zip stream response header.
|
98 |
+
*
|
99 |
+
* @author A. Grandt <php@grandt.com>
|
100 |
+
* @author Greg Kappatos
|
101 |
+
*/
|
102 |
+
public function onBeginBuildResponseHeader(){
|
103 |
+
// Do nothing.
|
104 |
+
}
|
105 |
+
|
106 |
+
/**
|
107 |
+
* Called by superclass when specialised action is needed
|
108 |
+
* at the end of sending the zip stream response header.
|
109 |
+
*
|
110 |
+
* @author A. Grandt <php@grandt.com>
|
111 |
+
* @author Greg Kappatos
|
112 |
+
*/
|
113 |
+
public function onEndBuildResponseHeader(){
|
114 |
+
//header("Connection: Keep-Alive");
|
115 |
+
$this->zipFlushBuffer();
|
116 |
+
}
|
117 |
+
|
118 |
+
/**
|
119 |
+
* Called by superclass when specialised action is needed
|
120 |
+
* while opening a stream.
|
121 |
+
*
|
122 |
+
* @author A. Grandt <php@grandt.com>
|
123 |
+
* @author Greg Kappatos
|
124 |
+
*/
|
125 |
+
public function onOpenStream(){
|
126 |
+
// Do nothing.
|
127 |
+
}
|
128 |
+
|
129 |
+
/**
|
130 |
+
* Called by superclass when specialised action is needed
|
131 |
+
* while processing a file.
|
132 |
+
*
|
133 |
+
* @author A. Grandt <php@grandt.com>
|
134 |
+
* @author Greg Kappatos
|
135 |
+
*
|
136 |
+
* @param array $params Array that contains data.
|
137 |
+
*/
|
138 |
+
public function onProcessFile(array $params){
|
139 |
+
print($params['data']);
|
140 |
+
$this->zipFlushBuffer();
|
141 |
+
}
|
142 |
+
|
143 |
+
/**
|
144 |
+
* Verify if the memory buffer is about to be exceeded.
|
145 |
+
*
|
146 |
+
* @author A. Grandt <php@grandt.com>
|
147 |
+
*
|
148 |
+
* @param int $gzLength length of the pending data.
|
149 |
+
*/
|
150 |
+
public function zipVerifyMemBuffer($gzLength) {
|
151 |
+
if (ob_get_length() !== FALSE && ob_get_length() > $this->maxStreamBufferLength) {
|
152 |
+
|
153 |
+
ob_flush();
|
154 |
+
|
155 |
+
while (ob_get_length() > $this->maxStreamBufferLength) {
|
156 |
+
usleep(500000);
|
157 |
+
}
|
158 |
+
}
|
159 |
+
}
|
160 |
+
|
161 |
+
/**
|
162 |
+
*
|
163 |
+
* @author A. Grandt <php@grandt.com>
|
164 |
+
*
|
165 |
+
* @param string $data
|
166 |
+
*/
|
167 |
+
public function zipWrite($data) {
|
168 |
+
print($data);
|
169 |
+
}
|
170 |
+
|
171 |
+
/**
|
172 |
+
* Flush Zip Data stored in memory, to a temp file.
|
173 |
+
*
|
174 |
+
* @author A. Grandt <php@grandt.com>
|
175 |
+
*
|
176 |
+
*/
|
177 |
+
public function zipFlush() {
|
178 |
+
// Does nothing.
|
179 |
+
}
|
180 |
+
|
181 |
+
/**
|
182 |
+
*
|
183 |
+
* @author A. Grandt <php@grandt.com>
|
184 |
+
*
|
185 |
+
*/
|
186 |
+
public function zipFlushBuffer() {
|
187 |
+
flush();
|
188 |
+
$this->zipVerifyMemBuffer(0);
|
189 |
+
}
|
190 |
+
|
191 |
+
/**
|
192 |
+
* @return int
|
193 |
+
*/
|
194 |
+
public function getMaxStreamBufferLength() {
|
195 |
+
return $this->maxStreamBufferLength;
|
196 |
+
}
|
197 |
+
|
198 |
+
/**
|
199 |
+
* @param int $maxStreamBufferLength
|
200 |
+
*/
|
201 |
+
public function setMaxStreamBufferLength($maxStreamBufferLength) {
|
202 |
+
$this->maxStreamBufferLength = $maxStreamBufferLength;
|
203 |
+
}
|
204 |
+
}
|
includes/extensions/zip/Stream/index.html
ADDED
File without changes
|
includes/extensions/zip/index.html
ADDED
File without changes
|
includes/frontend/rbs_gallery_class.php
CHANGED
@@ -86,7 +86,10 @@ class roboGallery extends roboGalleryUtils{
|
|
86 |
public $debug = 0;
|
87 |
|
88 |
public $seoContent = '';
|
89 |
-
|
|
|
|
|
|
|
90 |
function updateCountView(){
|
91 |
if(!$this->id) return ;
|
92 |
$count_key = 'gallery_views_count';
|
@@ -100,6 +103,9 @@ class roboGallery extends roboGalleryUtils{
|
|
100 |
}
|
101 |
|
102 |
function __construct($attr){
|
|
|
|
|
|
|
103 |
$this->helper = new roboGalleryHelper();
|
104 |
$this->galleryId = 'rbs_gallery_'.uniqid();
|
105 |
|
@@ -107,8 +113,6 @@ class roboGallery extends roboGalleryUtils{
|
|
107 |
|
108 |
$this->id = $attr['id'];
|
109 |
|
110 |
-
|
111 |
-
|
112 |
$options_id = (int) get_post_meta( $this->id, ROBO_GALLERY_PREFIX.'options', true );
|
113 |
if($options_id){
|
114 |
$this->real_id = $this->id;
|
@@ -187,7 +191,40 @@ class roboGallery extends roboGalleryUtils{
|
|
187 |
public function getGallery( ){
|
188 |
if( !$this->id ) return '';
|
189 |
|
190 |
-
$this->
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
191 |
|
192 |
//$galleryImages = get_post_meta( $this->options_id && $this->real_id ? $this->real_id : $this->id, ROBO_GALLERY_PREFIX.'galleryImages', true );;
|
193 |
//if( !$galleryImages || !is_array( $galleryImages ) || !count($galleryImages) || !(int)$galleryImages[0] ) return '';
|
@@ -439,13 +476,7 @@ class roboGallery extends roboGalleryUtils{
|
|
439 |
|
440 |
if(count($this->selectImages->imgArray)){
|
441 |
|
442 |
-
|
443 |
-
$this->robo_gallery_styles();
|
444 |
-
$this->robo_gallery_scripts();
|
445 |
-
} else {
|
446 |
-
add_action( 'get_footer', array($this, 'robo_gallery_styles') );
|
447 |
-
add_action( 'get_footer', array($this, 'robo_gallery_scripts') );
|
448 |
-
}
|
449 |
|
450 |
for ($i=0; $i<count($this->selectImages->imgArray); $i++) {
|
451 |
|
@@ -572,7 +603,23 @@ class roboGallery extends roboGalleryUtils{
|
|
572 |
}
|
573 |
}
|
574 |
}
|
575 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
576 |
}
|
577 |
|
578 |
|
86 |
public $debug = 0;
|
87 |
|
88 |
public $seoContent = '';
|
89 |
+
|
90 |
+
public $startTime = 0 ;
|
91 |
+
public $endTime = 0 ;
|
92 |
+
|
93 |
function updateCountView(){
|
94 |
if(!$this->id) return ;
|
95 |
$count_key = 'gallery_views_count';
|
103 |
}
|
104 |
|
105 |
function __construct($attr){
|
106 |
+
|
107 |
+
$this->startTime = microtime(true);
|
108 |
+
|
109 |
$this->helper = new roboGalleryHelper();
|
110 |
$this->galleryId = 'rbs_gallery_'.uniqid();
|
111 |
|
113 |
|
114 |
$this->id = $attr['id'];
|
115 |
|
|
|
|
|
116 |
$options_id = (int) get_post_meta( $this->id, ROBO_GALLERY_PREFIX.'options', true );
|
117 |
if($options_id){
|
118 |
$this->real_id = $this->id;
|
191 |
public function getGallery( ){
|
192 |
if( !$this->id ) return '';
|
193 |
|
194 |
+
$cache = get_post_meta( $this->id, ROBO_GALLERY_PREFIX.'cache', true );
|
195 |
+
|
196 |
+
if($cache){
|
197 |
+
$cacheId = $this->real_id ? $this->real_id : $this->id ;
|
198 |
+
$cached_result = get_transient( 'robo_gallery_cached_id'. $cacheId );
|
199 |
+
}
|
200 |
+
|
201 |
+
//$cached_result = '';
|
202 |
+
|
203 |
+
if( get_option( ROBO_GALLERY_PREFIX.'jqueryVersion', 'build' )=='forced' ){
|
204 |
+
$this->robo_gallery_styles();
|
205 |
+
$this->robo_gallery_scripts();
|
206 |
+
} else {
|
207 |
+
add_action( 'get_footer', array($this, 'robo_gallery_styles') );
|
208 |
+
add_action( 'get_footer', array($this, 'robo_gallery_scripts') );
|
209 |
+
}
|
210 |
+
|
211 |
+
$this->updateCountView();
|
212 |
+
|
213 |
+
|
214 |
+
if( $cache && $cached_result ){
|
215 |
+
|
216 |
+
$debugText = '';
|
217 |
+
|
218 |
+
if($this->debug){
|
219 |
+
$this->endTime = microtime(true);
|
220 |
+
$execution_time = ($this->endTime - $this->startTime);
|
221 |
+
$debugText = '<b>Total Execution Time (cache) </b> '.$execution_time;
|
222 |
+
}
|
223 |
+
|
224 |
+
return $debugText.$cached_result;
|
225 |
+
}
|
226 |
+
|
227 |
+
|
228 |
|
229 |
//$galleryImages = get_post_meta( $this->options_id && $this->real_id ? $this->real_id : $this->id, ROBO_GALLERY_PREFIX.'galleryImages', true );;
|
230 |
//if( !$galleryImages || !is_array( $galleryImages ) || !count($galleryImages) || !(int)$galleryImages[0] ) return '';
|
476 |
|
477 |
if(count($this->selectImages->imgArray)){
|
478 |
|
479 |
+
|
|
|
|
|
|
|
|
|
|
|
|
|
480 |
|
481 |
for ($i=0; $i<count($this->selectImages->imgArray); $i++) {
|
482 |
|
603 |
}
|
604 |
}
|
605 |
}
|
606 |
+
|
607 |
+
$debugText = '';
|
608 |
+
|
609 |
+
if( $cache ){
|
610 |
+
set_transient( 'robo_gallery_cached_id'.$cacheId , $this->returnHtml, 12 * HOUR_IN_SECONDS );
|
611 |
+
|
612 |
+
if($this->debug){
|
613 |
+
$this->endTime = microtime(true);
|
614 |
+
$execution_time = ($this->endTime - $this->startTime);
|
615 |
+
$debugText = '<b>Total Execution Time:</b> '.$execution_time;
|
616 |
+
}
|
617 |
+
}
|
618 |
+
|
619 |
+
|
620 |
+
|
621 |
+
|
622 |
+
return $debugText.$this->returnHtml;
|
623 |
}
|
624 |
|
625 |
|
includes/options/cache.php
ADDED
@@ -0,0 +1,48 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/*
|
3 |
+
* Robo Gallery By Robosoft
|
4 |
+
* Version: 2.6.18
|
5 |
+
* Contact: https://robosoft.co/robogallery/
|
6 |
+
* Available only in https://robosoft.co/robogallery/
|
7 |
+
*/
|
8 |
+
if ( ! defined( 'ABSPATH' ) ) exit;
|
9 |
+
|
10 |
+
$cache_box = new_cmb2_box( array(
|
11 |
+
'id' => ROBO_GALLERY_PREFIX . 'cache_metabox',
|
12 |
+
'title' => '<span class="dashicons dashicons-dashboard"></span> '.__( 'Cache', 'robo-gallery' ),
|
13 |
+
'object_types' => array( ROBO_GALLERY_TYPE_POST ),
|
14 |
+
'show_names' => false,
|
15 |
+
'context' => 'normal',
|
16 |
+
'priority' => 'high',
|
17 |
+
));
|
18 |
+
|
19 |
+
$cache_box->add_field( array(
|
20 |
+
'name' => __('Cache','robo-gallery'),
|
21 |
+
'default' => '',
|
22 |
+
'options' => array(
|
23 |
+
'' => 'Disable',
|
24 |
+
'1' => 'Enable',
|
25 |
+
),
|
26 |
+
'id' => ROBO_GALLERY_PREFIX .'cache',
|
27 |
+
'type' => 'rbsradiobutton',
|
28 |
+
'before_row' => '
|
29 |
+
<div class="rbs_block">
|
30 |
+
|
31 |
+
<div class="row">
|
32 |
+
<div class="col-sm-12">
|
33 |
+
'.__('Make your gallery unbelievable faster. With enabled cache option you gallery load faster in ten times.', 'robo-gallery').'
|
34 |
+
</div>
|
35 |
+
</div>
|
36 |
+
|
37 |
+
<br />
|
38 |
+
',
|
39 |
+
'after_row' => '
|
40 |
+
|
41 |
+
<div class="row">
|
42 |
+
<div class="col-sm-12">
|
43 |
+
'.__('If you modify settings gallery generate new cache after save.', 'robo-gallery').'
|
44 |
+
</div>
|
45 |
+
</div>
|
46 |
+
|
47 |
+
</div> ',
|
48 |
+
));
|
includes/options/rbs_gallery_options_images.php
CHANGED
@@ -23,6 +23,13 @@ $images_group = new_cmb2_box( array(
|
|
23 |
'show_names' => false,
|
24 |
));
|
25 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
26 |
$images_group->add_field(array(
|
27 |
'name' => __( 'Manage Images', 'rbs_gallery' ),
|
28 |
'desc' => __( 'Click on Manage Images button to open Images Manager where you can upload, edit or delete images from gallery. Also here you can edit settings of every particular image, define alt, links, description text', 'rbs_gallery' ),
|
23 |
'show_names' => false,
|
24 |
));
|
25 |
|
26 |
+
/*$images_group->add_field(array(
|
27 |
+
'name' => __( 'cache_id', 'rbs_gallery' ),
|
28 |
+
'id' => ROBO_GALLERY_PREFIX . 'cache_id',
|
29 |
+
'type' => 'hidden',
|
30 |
+
'default' => uniqid(),
|
31 |
+
));
|
32 |
+
*/
|
33 |
$images_group->add_field(array(
|
34 |
'name' => __( 'Manage Images', 'rbs_gallery' ),
|
35 |
'desc' => __( 'Click on Manage Images button to open Images Manager where you can upload, edit or delete images from gallery. Also here you can edit settings of every particular image, define alt, links, description text', 'rbs_gallery' ),
|
includes/options/rbs_gallery_options_tools.php
CHANGED
@@ -28,6 +28,8 @@ if(isset($_GET['post'])){
|
|
28 |
'type' => 'title',
|
29 |
'before_row' => '<div class="rbs_block">'
|
30 |
.'<div class="rbs-center-block rbs-margin-block rbs-post-tools">'
|
|
|
|
|
31 |
.'<button id="rbs_create_article" data-galleryid="'.(int)$_GET['post'].'" class="btn btn-info btn-lg ">'
|
32 |
.'<span class="glyphicon glyphicon-plus" aria-hidden="true"></span> '
|
33 |
.__('Create post','rbs_gallery')
|
@@ -37,7 +39,7 @@ if(isset($_GET['post'])){
|
|
37 |
.'<span class="glyphicon glyphicon-list-alt" aria-hidden="true"></span> '
|
38 |
.__('Posts List','rbs_gallery')
|
39 |
.'</button>'
|
40 |
-
.'<p
|
41 |
.'<p>'
|
42 |
.'<span class="glyphicon glyphicon-eye-open"></span> '
|
43 |
.__('Gallery Views','rbs_gallery').': '
|
28 |
'type' => 'title',
|
29 |
'before_row' => '<div class="rbs_block">'
|
30 |
.'<div class="rbs-center-block rbs-margin-block rbs-post-tools">'
|
31 |
+
.'<p class="rbs_desc">'.__('Here you can create and customize new post with gallery inside it','rbs_gallery').'</p> '
|
32 |
+
|
33 |
.'<button id="rbs_create_article" data-galleryid="'.(int)$_GET['post'].'" class="btn btn-info btn-lg ">'
|
34 |
.'<span class="glyphicon glyphicon-plus" aria-hidden="true"></span> '
|
35 |
.__('Create post','rbs_gallery')
|
39 |
.'<span class="glyphicon glyphicon-list-alt" aria-hidden="true"></span> '
|
40 |
.__('Posts List','rbs_gallery')
|
41 |
.'</button>'
|
42 |
+
.'<p></p>'
|
43 |
.'<p>'
|
44 |
.'<span class="glyphicon glyphicon-eye-open"></span> '
|
45 |
.__('Gallery Views','rbs_gallery').': '
|
includes/rbs_gallery_edit.php
CHANGED
@@ -24,7 +24,9 @@ function rbs_gallery_group_metabox() {
|
|
24 |
}
|
25 |
|
26 |
rbs_gallery_include( array(
|
|
|
27 |
'voting.php',
|
|
|
28 |
'rbs_gallery_options_guides.php',
|
29 |
'rbs_gallery_options_images.php',
|
30 |
), ROBO_GALLERY_OPTIONS_PATH);
|
24 |
}
|
25 |
|
26 |
rbs_gallery_include( array(
|
27 |
+
'cache.php',
|
28 |
'voting.php',
|
29 |
+
|
30 |
'rbs_gallery_options_guides.php',
|
31 |
'rbs_gallery_options_images.php',
|
32 |
), ROBO_GALLERY_OPTIONS_PATH);
|
includes/rbs_gallery_init.php
CHANGED
@@ -113,6 +113,8 @@ function create_post_type_robo_gallery() {
|
|
113 |
}
|
114 |
add_action( 'init', 'create_post_type_robo_gallery' );
|
115 |
|
|
|
|
|
116 |
if(!function_exists('rbs_gallery_main_init')){
|
117 |
function rbs_gallery_main_init() {
|
118 |
|
@@ -168,7 +170,9 @@ if(!function_exists('rbs_gallery_main_init')){
|
|
168 |
}
|
169 |
|
170 |
/* only backend */
|
171 |
-
if( is_admin() )
|
|
|
|
|
172 |
|
173 |
/* Frontend*/
|
174 |
rbs_gallery_include(array('rbs_gallery_source.php', 'rbs_gallery_helper.php', 'rbs_gallery_class_utils.php', 'rbs_gallery_class.php', 'rbs_gallery_frontend.php' ), ROBO_GALLERY_FRONTEND_PATH);
|
113 |
}
|
114 |
add_action( 'init', 'create_post_type_robo_gallery' );
|
115 |
|
116 |
+
rbs_gallery_include('cache.php', ROBO_GALLERY_INCLUDES_PATH);
|
117 |
+
|
118 |
if(!function_exists('rbs_gallery_main_init')){
|
119 |
function rbs_gallery_main_init() {
|
120 |
|
170 |
}
|
171 |
|
172 |
/* only backend */
|
173 |
+
if( is_admin() ){
|
174 |
+
rbs_gallery_include(array('rbs_gallery_media.php', 'rbs_gallery_menu.php', 'rbs_gallery_settings.php' ), ROBO_GALLERY_INCLUDES_PATH);
|
175 |
+
}
|
176 |
|
177 |
/* Frontend*/
|
178 |
rbs_gallery_include(array('rbs_gallery_source.php', 'rbs_gallery_helper.php', 'rbs_gallery_class_utils.php', 'rbs_gallery_class.php', 'rbs_gallery_frontend.php' ), ROBO_GALLERY_FRONTEND_PATH);
|
includes/rbs_gallery_settings.php
CHANGED
@@ -83,14 +83,12 @@ class Robo_Gallery_Settings {
|
|
83 |
echo '
|
84 |
<div class="wrap">
|
85 |
<h1>'.__('Robo Gallery', 'robo-gallery').'</h1>';
|
|
|
|
|
86 |
|
87 |
$this->tabs();
|
88 |
|
89 |
echo '<form method="post" action="options.php?tab='.$this->active_tab.'">';
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
settings_errors();
|
94 |
|
95 |
echo '<table class="form-table">';
|
96 |
|
83 |
echo '
|
84 |
<div class="wrap">
|
85 |
<h1>'.__('Robo Gallery', 'robo-gallery').'</h1>';
|
86 |
+
|
87 |
+
settings_errors();
|
88 |
|
89 |
$this->tabs();
|
90 |
|
91 |
echo '<form method="post" action="options.php?tab='.$this->active_tab.'">';
|
|
|
|
|
|
|
|
|
92 |
|
93 |
echo '<table class="form-table">';
|
94 |
|
readme.txt
CHANGED
@@ -1,10 +1,10 @@
|
|
1 |
=== Gallery - Photo Gallery and Images Gallery ===
|
2 |
Contributors: gallerysupport, robosoft
|
3 |
Donate link: https://robosoft.co/robogallery
|
4 |
-
Tags: gallery, photo gallery, images gallery, gallery images, responsive gallery, categories gallery, Polaroid gallery, gallery lightbox, portfolio gallery, video gallery, Gallery Plugin, Robo Gallery
|
5 |
Requires at least: 3.3
|
6 |
Tested up to: 4.8
|
7 |
-
Stable tag: 2.
|
8 |
License: GPLv2 or later
|
9 |
License URI: https://www.gnu.org/licenses/gpl-3.0.html
|
10 |
|
@@ -94,6 +94,8 @@ This interface gallery button have wide range of the front end interface customi
|
|
94 |
* **Advanced Load more function** - in gallery implemented very attractive navigation mode. Auto pre loading images like endless list of the gallery images. This gallery load more function have alot of customization options to make it work the way you need.
|
95 |
* **SEO code optimization** - in gallery implemented few front end code output modes. One simplified mode with all core front end gallery code elements another mode with additional not visible elements. This option have additional modes. This SEO output modes give you default output mode, thumbnail, thumnails+links mode.
|
96 |
* **Gallery Template** - in our gallery we have advanced templating engine for gallery images description. Every hover text of gallery image could be edit and customized with built-in templating options.
|
|
|
|
|
97 |
|
98 |
= Gallery Pro Key Features =
|
99 |
|
@@ -257,6 +259,9 @@ If any problem occurs, please contact us.
|
|
257 |
|
258 |
== Changelog ==
|
259 |
|
|
|
|
|
|
|
260 |
= 2.6.22 =
|
261 |
* Update Robo Gallery ordering page
|
262 |
|
@@ -417,6 +422,9 @@ If any problem occurs, please contact us.
|
|
417 |
|
418 |
== Upgrade Notice ==
|
419 |
|
|
|
|
|
|
|
420 |
= 2.6.22 =
|
421 |
Update Robo Gallery ordering page
|
422 |
|
1 |
=== Gallery - Photo Gallery and Images Gallery ===
|
2 |
Contributors: gallerysupport, robosoft
|
3 |
Donate link: https://robosoft.co/robogallery
|
4 |
+
Tags: gallery, photo gallery, images gallery, gallery images, wordpress gallery plugin, responsive gallery, categories gallery, Polaroid gallery, gallery lightbox, portfolio gallery, video gallery, Gallery Plugin, Robo Gallery
|
5 |
Requires at least: 3.3
|
6 |
Tested up to: 4.8
|
7 |
+
Stable tag: 2.7.0
|
8 |
License: GPLv2 or later
|
9 |
License URI: https://www.gnu.org/licenses/gpl-3.0.html
|
10 |
|
94 |
* **Advanced Load more function** - in gallery implemented very attractive navigation mode. Auto pre loading images like endless list of the gallery images. This gallery load more function have alot of customization options to make it work the way you need.
|
95 |
* **SEO code optimization** - in gallery implemented few front end code output modes. One simplified mode with all core front end gallery code elements another mode with additional not visible elements. This option have additional modes. This SEO output modes give you default output mode, thumbnail, thumnails+links mode.
|
96 |
* **Gallery Template** - in our gallery we have advanced templating engine for gallery images description. Every hover text of gallery image could be edit and customized with built-in templating options.
|
97 |
+
* **Gallery Cache** - incredible new super cache option make your gallery load ten time faster. This function use absolutely new model of the images load. When you enable cache for big size gallery it's gonna be much faster and effective to use our plugin. Your visitors will be really surprised by the speed of the page load.
|
98 |
+
|
99 |
|
100 |
= Gallery Pro Key Features =
|
101 |
|
259 |
|
260 |
== Changelog ==
|
261 |
|
262 |
+
= 2.7.0 =
|
263 |
+
* New super gallery cache function
|
264 |
+
|
265 |
= 2.6.22 =
|
266 |
* Update Robo Gallery ordering page
|
267 |
|
422 |
|
423 |
== Upgrade Notice ==
|
424 |
|
425 |
+
= 2.7.0 =
|
426 |
+
New super gallery cache function
|
427 |
+
|
428 |
= 2.6.22 =
|
429 |
Update Robo Gallery ordering page
|
430 |
|
robogallery.php
CHANGED
@@ -3,7 +3,7 @@
|
|
3 |
Plugin Name: Robo Gallery
|
4 |
Plugin URI: https://robosoft.co/wordpress-gallery-plugin
|
5 |
Description: Gallery modes photo gallery, images gallery, video gallery, Polaroid gallery, gallery lighbox, portfolio gallery, responsive gallery
|
6 |
-
Version: 2.
|
7 |
Author: RoboSoft
|
8 |
Author URI: https://robosoft.co/wordpress-gallery-plugin
|
9 |
License: GPLv3 or later
|
@@ -15,13 +15,13 @@ if(!defined('WPINC'))die;
|
|
15 |
if(!defined("ABSPATH"))exit;
|
16 |
|
17 |
define("ROBO_GALLERY", 1);
|
18 |
-
define("ROBO_GALLERY_VERSION", '2.
|
19 |
|
20 |
if( !defined("ROBO_GALLERY_PATH") ) define("ROBO_GALLERY_PATH", plugin_dir_path( __FILE__ ));
|
21 |
|
22 |
define("ROBO_GALLERY_SPECIAL", 1);
|
23 |
-
define("ROBO_GALLERY_EVENT_DATE", '2017-
|
24 |
-
define("ROBO_GALLERY_EVENT_HOUR",
|
25 |
|
26 |
add_action( 'plugins_loaded', 'rbs_gallery_load_textdomain' );
|
27 |
function rbs_gallery_load_textdomain() {
|
3 |
Plugin Name: Robo Gallery
|
4 |
Plugin URI: https://robosoft.co/wordpress-gallery-plugin
|
5 |
Description: Gallery modes photo gallery, images gallery, video gallery, Polaroid gallery, gallery lighbox, portfolio gallery, responsive gallery
|
6 |
+
Version: 2.7.0
|
7 |
Author: RoboSoft
|
8 |
Author URI: https://robosoft.co/wordpress-gallery-plugin
|
9 |
License: GPLv3 or later
|
15 |
if(!defined("ABSPATH"))exit;
|
16 |
|
17 |
define("ROBO_GALLERY", 1);
|
18 |
+
define("ROBO_GALLERY_VERSION", '2.7.0');
|
19 |
|
20 |
if( !defined("ROBO_GALLERY_PATH") ) define("ROBO_GALLERY_PATH", plugin_dir_path( __FILE__ ));
|
21 |
|
22 |
define("ROBO_GALLERY_SPECIAL", 1);
|
23 |
+
define("ROBO_GALLERY_EVENT_DATE", '2017-10-14');
|
24 |
+
define("ROBO_GALLERY_EVENT_HOUR", 48);
|
25 |
|
26 |
add_action( 'plugins_loaded', 'rbs_gallery_load_textdomain' );
|
27 |
function rbs_gallery_load_textdomain() {
|