使用一个隐藏栏位来存放这些 JSON 数据靠谱吗 ? 因为我发现数据量满大的 ..
以下为其相关的源码:
myztree.js
jQuery(document).ready(function () {
// Start: 初始化 jQuery 外掛 - zTree 的設定
var setting = {
async: {
autoParam: ['path'],
dataType: 'json',
enable: true,
otherParam: {
action: 'ztree'
},
url: ajaxurl
},
callback: {
onCheck: zTreeOnCheck,
onClick: zTreeOnClick
},
check: {
autoCheckTrigger: true,
enable: true
},
view: {
dblClickExpand: false,
showLine: false
}
};
var zTree = jQuery.fn.zTree.init(jQuery('#excluded-files'), setting, null);
// End: 初始化 jQuery 外掛 - zTree 的設定
function zTreeOnCheck(event, treeId, treeNode) {
var basedir = treeNode.path;
var checked = treeNode.checked;
var listval = JSON.parse(jQuery('#excluded-list').val());
var in_list = false;
for (var i = 0; i < listval.length; i++) {
if (listval[i]['basedir'] == basedir) {
listval[i]['checked'] = checked;
in_list = true;
break;
}
}
if (!in_list) {
listval.push({"basedir": basedir, "checked": checked});
}
jQuery('#excluded-list').val(JSON.stringify(listval));
};
function zTreeOnClick(event, treeId, treeNode) {
zTree.expandNode(treeNode);
};
});
ztree.php
<?php
# 初始化 node 變數用於儲存所有檔案與資料夾的樹狀結構
$node = array();
# 檢查是否是第一次初始化輸出結構資訊
if ( empty( $_POST['path'] ) ) {
# 設定欲讀取資料夾為 WordPress 的上傳資料夾
$dir = sprintf( '%s/', array_pop( array_slice( wp_upload_dir(), 3, 1 ) ) );
}
# 使用者已選擇次級的資料夾
else {
# 解碼並設定已選擇的次級資料夾名稱
$dir = sprintf( '%s/', urldecode( $_POST['path'] ) );
}
# 讀取目前資料夾底下所有的資訊
$files = scandir( $dir );
# 採用自然排序法排序所有的名稱
natcasesort( $files );
# Start: 走訪本資料夾底下所有的資訊
foreach( $files as $file ) {
# 過濾無用的上層資料夾等資訊
if( $file != '.' && $file != '..' ) {
# 資料夾
if ( is_dir( $dir . $file ) ) {
# 設定本資料夾的資訊
$folder = array(
'iconSkin' => 'folder',
'isParent' => true,
'name' => $file,
'path' => $dir . $file
);
# 新增本資料夾至節點變數用以回傳給 zTree 處理
array_push( $node, $folder );
# 檔案
} else {
# 設定本檔案的資訊
$file = array(
'iconSkin' => sprintf( 'file_ico_docu %s', preg_replace( '/^.*\./', '', $file ) ),
'name' => $file,
'path' => $dir . $file
);
# 新增本檔案至節點變數用以回傳給 zTree 處理
array_push( $node, $file );
}
} else {
continue;
}
}
# End: 走訪本資料夾底下所有的資訊
# 回傳已編碼的節點資訊
echo json_encode( $node );
?>
ztree.html
<tr>
<th scope="row">
<label for="excluded-files">Exclusion: </label>
</th>
<td>
<!-- Start: 使用 jQuery - ztree 輸出欲排除上傳的檔案清單 -->
<div>
<ul class="ztree" id="excluded-files"></ul>
</div>
<!-- End: 使用 jQuery - ztree 輸出欲排除上傳的檔案清單 -->
</td>
</tr>
未完成的后端处理.php
<?php
function sanitize_values( $input ) {
# 檢查所欲過濾的設定值是否為一個陣列
if ( is_array( $input ) ) {
# 走訪所有的設定名稱與數值
foreach ( $input as $key => $value ) {
# 判斷設定名稱
switch ( $key ) {
# 排除上傳的檔案清單
case 'exclusion':
$list = array(
'folders' => array(),
'files' => array()
);
$exclusions = json_decode( stripslashes( $input[$key] ), true );
if ( count( $exclusions ) > 0 ) {
foreach ( $exclusions as $exclusion ) {
switch ( is_dir ( $exclusion['basedir'] ) ) {
case true:
if ( $exclusion['checked'] )
array_push( $list['folders'], $exclusion['basedir'] );
break;
case false:
if ( $exclusion['checked'] )
array_push( $list['files'], $exclusion['basedir'] );
break;
default:
break;
}
}
}
$input[$key] = $list;
#exit( print_r( $list ) );
break;
}
}
# 回傳已過濾的設定值
return $input;
}
# 回傳錯誤
return false;
}
?>
10 个解决方案
#1
使用一个隐藏栏位来存放这些 JSON 数据靠谱吗 ? 因为我发现数据量满大的 ..
没关系.尽情使用
没关系.尽情使用
#2
我的确使用得很开心,但想请问 PhpNewnew 前辈 .. 该怎么去处理和储存这些数据 ?
谢谢您拨冗回覆我的困扰 :-)
#3
处理?将json 解成数组 想怎么处理就怎么处理呀
存储?如果需要的话可以写到数据库里。如果是临时的话可以直接保存到memcache
如果是要传递的话 直接post
....
存储?如果需要的话可以写到数据库里。如果是临时的话可以直接保存到memcache
如果是要传递的话 直接post
....
#4
恩,谢谢您的回覆 :-)
我的意思是指,这些数据会储存到数据库的表中。
但我不知道该怎么去处理 "级" 的概念 ..
也就是可能父层全选、子层部分选择等勾选状况。
有一点像是权限树的架构 .. 但更复杂,因为目录可能是无穷级的。
我想实现的处理效果是,上图中所有的文件与目录在预设设置下会被上传。
但假如用户有勾选不想被上传的文件与目录等,就将之写进数据库。
待其他的后端脚本在运行上传的程序时,至数据库中读取这些排除清单并做出处理。
当然,若数据库写的进去了 .. 在 zTree 运行成功时也能连带先行查询再将目前用户所勾选的呈现出来。
#5
能说说看这个是什么应用场景吗?说清楚的话可能比较有针对性的探讨。
如果类似于p2p软件的共享 可能这些数据保存在客户端比较合适.例如cookie什么的,
不过cookie也有它的局限性,会给清理,保存内容有限 等等 不过4kb似乎也够了
这些文件目录是非固定的吧?
如果类似于p2p软件的共享 可能这些数据保存在客户端比较合适.例如cookie什么的,
不过cookie也有它的局限性,会给清理,保存内容有限 等等 不过4kb似乎也够了
这些文件目录是非固定的吧?
#6
数据库最简单的方式是
id title parentid
当然还有两中,可以搜索mysql tree 等等的关键字会找到。
前端用ajax吧。
id title parentid
当然还有两中,可以搜索mysql tree 等等的关键字会找到。
前端用ajax吧。
#7
是的,非固定的目录与文件。
有一点像是杀毒软件的架构,它一定会有一个排除扫瞄的清单。
当你没有去更改这些设置时,杀毒默认会扫瞄整个硬盘上的文件,对吧 ?
但假如我从这排除清单中新增了几个文件或目录,那自然在杀毒的扫瞄程序中就会被略过了。
ok, 场景回到目前的状况 ..
前端显示目前目录和文件树的设计目前是可以使用的,后端 PHP 也可以接收到这些来自前端的数据。
但我不知道该怎么去判断某一个文件或目录,他子父层的关系 ?
可能是仅有 2012/02/Chris-150x150.jpg 的文件和 2012/03 的目录被选取;
也可能是仅有 2012 整个目录和 icon/asp.asp 与 jar.jar 被选取等多种状况。
目前正在看一个国外插件的范例,希望可以和大家多多讨论,谢谢你们的热心。
class-file-list.php
<?php
/**
* A class with functions the perform a backup of WordPress
*
* @copyright Copyright (C) 2011 Michael De Wildt. All rights reserved.
* @author Michael De Wildt (http://www.mikeyd.com.au/)
* @license This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
*/
include_once( 'class-wp-backup.php' );
class File_List {
const EXCLUDED = 0;
const INCLUDED = 1;
const PARTIAL = 2;
/**
* A list of directories to mark as partial
* @var null
*/
private $partial_directories = array();
/**
* A list of files that are not allowed to be backed up
* @var null
*/
private $excluded_files = array();
/**
* These files cannot be uploaded to Dropbox
* @var array
*/
private static $ignored_files = array( '.DS_Store', 'Thumbs.db', 'desktop.ini' );
/**
* Construct the file list
* @param $wpdb
*/
public function __construct( $wpdb = null ) {
if ( !$wpdb ) global $wpdb;
$this->database = $wpdb;
$file_list = get_option( 'backup-to-dropbox-file-list' );
if ( $file_list === false ) {
$this->partial_directories = array();
$this->excluded_files = array();
add_option( 'backup-to-dropbox-file-list', array( $this->partial_directories, $this->excluded_files ), null, 'no' );
} else {
list( $this->partial_directories, $this->excluded_files ) = $file_list;
}
}
/**
* Return the state of a file in the list the SQL dump is always included
* @param $path
* @return bool
*/
public function get_file_state( $path ) {
$parent_path = dirname( $path ) . '/';
if ( $path == dirname( ABSPATH ) . '/' ) {
return self::PARTIAL;
} else if ( strstr( $path, DB_NAME . '-backup.sql' ) ) {
return self::INCLUDED;
} else if ( in_array( $path, $this->excluded_files ) ) {
return self::EXCLUDED;
} else if ( in_array( $path, $this->partial_directories ) ) {
$parent_state = $this->get_file_state( $parent_path );
if ( $parent_state == self::INCLUDED && $parent_path != ABSPATH ) {
$this->remove_from_partial( $path );
$this->remove_from_excluded( $path );
return self::INCLUDED;
}
return self::PARTIAL;
}
$state = $this->get_file_state( $parent_path );
if ( $state == self::PARTIAL ) {
$this->remove_from_partial( $path );
$this->remove_from_excluded( $path );
return self::INCLUDED;
}
return $state;
}
/**
* @param $full_path string
* @return string
*/
function get_check_box_class( $full_path ) {
$state = $this->get_file_state( $full_path );
switch ( $state ) {
case self::EXCLUDED:
$class = 'checked';
break;
case self::PARTIAL:
$class = 'partial';
break;
default: //INCLUDED so do not check
$class = '';
break;
}
return $class;
}
/**
* Adds a file to the excluded list if it does not already exist
* @param $file
* @return void
*/
private function add_to_excluded( $file ) {
if ( !in_array( $file, $this->excluded_files ) ) {
$this->excluded_files[] = $file;
}
}
/**
* Adds a file to the partial list if it does not already exist
* @param $file
* @return void
*/
private function add_to_partial( $file ) {
if ( !in_array( $file, $this->partial_directories ) ) {
$this->partial_directories[] = $file;
}
}
/**
* Accepts a JSON encoded list of files and directories and adds their states to the appropriate lists
* @param $json_list
* @return void
*/
public function set_file_list( $json_list ) {
$new_list = json_decode( stripslashes( $json_list ), true );
foreach ( $new_list as $fl ) {
list ( $file, $state ) = $fl;
if ( $state == self::PARTIAL ) {
$this->add_to_partial( $file );
$this->remove_from_excluded( $file );
} else if ( $state == self::EXCLUDED) {
$this->add_to_excluded( $file );
$this->remove_from_partial( $file );
} else {
$this->remove_from_excluded( $file );
$this->remove_from_partial( $file );
}
}
}
/**
* Removes a file from the excluded list if it exists
* @param $file
* @return void
*/
private function remove_from_excluded( $file ) {
if ( in_array( $file, $this->excluded_files ) ) {
$i = array_search( $file, $this->excluded_files );
unset( $this->excluded_files[$i] );
}
}
/**
* Removes a file from the partial list if it exists
* @param $file
* @return void
*/
private function remove_from_partial( $file ) {
if ( in_array( $file, $this->partial_directories ) ) {
$i = array_search( $file, $this->partial_directories );
unset( $this->partial_directories[$i] );
}
}
/**
* Saves the file list
* @return void
*/
public function save() {
update_option( 'backup-to-dropbox-file-list', array( $this->partial_directories, $this->excluded_files ) );
}
/**
* @param $dir
* @return int
*/
private function get_directory_state( $dir ) {
$files = scandir( $dir );
natcasesort( $files );
foreach ( $files as $file ) {
$state = $this->get_file_state( $file );
if ( $state == self::PARTIAL || $state == self::EXCLUDED ) {
return self::PARTIAL;
}
}
return self::INCLUDED;
}
/**
* Some files cannot be uploaded to Dropbox so check them here
* @static
* @param $file
* @return bool
*/
public static function in_ignore_list( $file ) {
return in_array( $file, self::$ignored_files );
}
}
#8
jquert-filetree.js
// jQuery File Tree Plugin
//
// Version 1.01
//
// Cory S.N. LaViska
// A Beautiful Site (http://abeautifulsite.net/)
// 24 March 2008
//
// Visit http://abeautifulsite.net/notebook.php?article=58 for more information
//
// Usage: $('.fileTreeDemo').fileTree( options, callback )
//
// Options: root - root folder to display; default = /
// script - location of the serverside AJAX file to use; default = jqueryFileTree.php
// folderEvent - event to trigger expand/collapse; default = click
// expandSpeed - default = 500 (ms); use -1 for no animation
// collapseSpeed - default = 500 (ms); use -1 for no animation
// expandEasing - easing function to use on expand (optional)
// collapseEasing - easing function to use on collapse (optional)
// multiFolder - whether or not to limit the browser to one subfolder at a time
// loadMessage - Message to display while initial tree loads (can be HTML)
//
// History:
//
// 1.01 - updated to work with foreign characters in directory/file names (12 April 2008)
// 1.00 - released (24 March 2008)
//
// TERMS OF USE
//
// This plugin is dual-licensed under the GNU General Public License and the MIT License and
// is copyright 2008 A Beautiful Site, LLC.
//
if(jQuery) (function($){
$.extend($.fn, {
fileTree: function(o) {
var EXCLUDED = 0;
var INCLUDED = 1;
var PARTIAL = 2;
// Defaults
if( !o ) var o = {};
if( o.root == undefined ) o.root = '/';
if( o.script == undefined ) o.script = 'jqueryFileTree.php';
if( o.folderEvent == undefined ) o.folderEvent = 'click';
if( o.expandSpeed == undefined ) o.expandSpeed= 500;
if( o.collapseSpeed == undefined ) o.collapseSpeed= 500;
if( o.expandEasing == undefined ) o.expandEasing = null;
if( o.collapseEasing == undefined ) o.collapseEasing = null;
if( o.multiFolder == undefined ) o.multiFolder = true;
if( o.loadMessage == undefined ) o.loadMessage = 'Loading...';
$(this).each( function() {
function showTree(c, t) {
$(c).addClass('wait');
$(".jqueryFileTree.start").remove();
$.post(o.script, { action: 'file_tree', dir: t }, function(data) {
$(c).find('.start').html('');
$(c).removeClass('wait').append(data);
if( o.root == t ) $(c).find('UL:hidden').show(); else $(c).find('UL:hidden').slideDown({ duration: o.expandSpeed, easing: o.expandEasing });
//Check that the list of files that we got from the server have not already
//been included or excluded in the UI.
$('.checkbox').each(function () {
var dir = escape(dirname($(this).attr('rel')));
if (dir == t) {
var state = get_include_state($(this).attr('rel'));
if (state !== false) {
set_checkbox_state(this, state);
}
}
});
bindTree(c);
});
}
function bindTree(t) {
$(t).find('LI A.tree').bind(o.folderEvent, function() {
if( $(this).parent().hasClass('directory') ) {
if( $(this).parent().hasClass('collapsed') ) {
// Expand
if( !o.multiFolder ) {
$(this).parent().parent().find('UL').slideUp({ duration: o.collapseSpeed, easing: o.collapseEasing });
$(this).parent().parent().find('LI.directory').removeClass('expanded').addClass('collapsed');
}
$(this).parent().find('UL').remove(); // cleanup
showTree( $(this).parent(), escape($(this).attr('rel').match( /.*\// )) );
$(this).parent().removeClass('collapsed').addClass('expanded');
} else {
// Collapse
$(this).parent().find('UL').slideUp({ duration: o.collapseSpeed, easing: o.collapseEasing });
$(this).parent().removeClass('expanded').addClass('collapsed');
}
} else {
var element = $(this).parent().find('.checkbox');
if (element.length) {
checkbox_click(element);
}
}
return false;
});
//Bind our check box clicks
$(t).find('ul').find('.checkbox').bind('click', function() {
checkbox_click(this);
});
// Prevent A from triggering the # on non-click events
if( o.folderEvent.toLowerCase != 'click' ) $(t).find('LI A').bind('click', function() { return false; });
}
// Loading message
$(this).html('<ul class="jqueryFileTree start"><li class="wait">' + o.loadMessage + '<li></ul>');
// Get the initial file list
showTree( $(this), escape(o.root) );
});
/**
* Updates the tri state check box based on the state hidden element passed
* @param check_box
*/
function set_checkbox_state(check_box, new_state) {
new_state = parseInt(new_state);
$(check_box).removeClass('checked');
$(check_box).removeClass('partial');
switch(new_state) {
case EXCLUDED:
$(check_box).addClass('checked');
break;
case PARTIAL:
$(check_box).addClass('partial');
break;
default:
break; //INCLUDED - Do nothing
}
}
/**
* Toggles the hidden list input with what has changed
* @param element
*/
function set_include_state(element) {
var file = $(element).attr('rel');
var state = get_checkbox_state(element);
var file_tree_list = JSON.parse($('#file_tree_list').val());
var in_list = false;
for (var i = 0; i < file_tree_list.length; i++) {
if (file_tree_list[i][0] == file) {
file_tree_list[i][1] = state;
in_list = true;
break;
}
}
if (!in_list) {
file_tree_list.push([file, state])
}
$('#file_tree_list').val(JSON.stringify(file_tree_list));
}
/**
* Get the file state from the local list
* @param file
* @return int
*/
function get_include_state(file) {
var file_list = JSON.parse($('#file_tree_list').val());
for (var i = 0; i < file_list.length; i++) {
if (file_list[i][0] == file) {
return file_list[i][1];
}
}
return false;
}
/**
* Just like PHP's dirname
* @param path
*/
function dirname(path) {
return path.replace(/\/$/, '').replace(/\/[^\/]*$/, '/');
}
/**
* Toggles the directory check box to ON, OFF or PARTIAL depending on the state of all its children.
* @param clicked
*/
function toggle_directory_check(clicked) {
//Also check its directory if they are all not checked
var checked_count = 0, total = 0;
var clicked_parent_dir = dirname($(clicked).attr('rel'));
$('.checkbox').each(function () {
if (clicked_parent_dir != o.root) {
var parent_dir = dirname($(this).attr('rel'));
if (parent_dir == clicked_parent_dir) {
var state = get_checkbox_state(this);
if (state == PARTIAL || state == EXCLUDED) {
checked_count++;
}
total++;
}
}
});
//Now that we know that the state of all the directories children we can update the parent dir accordingly
$('.checkbox').each(function () {
if ($(this).attr('rel') == clicked_parent_dir) {
if (checked_count == total) {
set_checkbox_state(this, EXCLUDED);
} else if (checked_count == 0) {
set_checkbox_state(this, INCLUDED);
} else {
set_checkbox_state(this, PARTIAL);
}
set_include_state(this);
toggle_directory_check(this);
}
});
}
/**
* Return the current state of a clicked check box
* @param clicked
*/
function get_checkbox_state(clicked) {
var state = INCLUDED;
if ($(clicked).hasClass('partial')) {
state = PARTIAL;
} else if ($(clicked).hasClass('checked')) {
state = EXCLUDED;
}
return state;
}
/**
* Set all the children of a directory to a state
* @param parent
*/
function set_directory_children(parent, state) {
//If this is an expanded directory recursively update all its children
if ($(parent).parent().hasClass('expanded') && $(parent).hasClass('directory')) {
$('.checkbox').each(function () {
if (dirname($(this).attr('rel')) == $(parent).attr('rel')) {
set_checkbox_state(this, state);
set_include_state(this);
set_directory_children(this, state);
}
});
}
}
/**
* The on click function for a file check box. If the user clicks on a directory then all its open children
* need to be updated accordingly.
* @param clicked
*/
function checkbox_click(clicked) {
var state = get_checkbox_state(clicked) == EXCLUDED ? INCLUDED : EXCLUDED;
set_checkbox_state(clicked, state);
set_include_state(clicked);
set_directory_children(clicked, state);
toggle_directory_check(clicked);
}
}
});
})(jQuery);
#9
感觉LZ把简单的问题复杂化了
#10
哈哈,对啊对啊 .. 请你给我当头棒喝一下 :-D
#1
使用一个隐藏栏位来存放这些 JSON 数据靠谱吗 ? 因为我发现数据量满大的 ..
没关系.尽情使用
没关系.尽情使用
#2
我的确使用得很开心,但想请问 PhpNewnew 前辈 .. 该怎么去处理和储存这些数据 ?
谢谢您拨冗回覆我的困扰 :-)
#3
处理?将json 解成数组 想怎么处理就怎么处理呀
存储?如果需要的话可以写到数据库里。如果是临时的话可以直接保存到memcache
如果是要传递的话 直接post
....
存储?如果需要的话可以写到数据库里。如果是临时的话可以直接保存到memcache
如果是要传递的话 直接post
....
#4
恩,谢谢您的回覆 :-)
我的意思是指,这些数据会储存到数据库的表中。
但我不知道该怎么去处理 "级" 的概念 ..
也就是可能父层全选、子层部分选择等勾选状况。
有一点像是权限树的架构 .. 但更复杂,因为目录可能是无穷级的。
我想实现的处理效果是,上图中所有的文件与目录在预设设置下会被上传。
但假如用户有勾选不想被上传的文件与目录等,就将之写进数据库。
待其他的后端脚本在运行上传的程序时,至数据库中读取这些排除清单并做出处理。
当然,若数据库写的进去了 .. 在 zTree 运行成功时也能连带先行查询再将目前用户所勾选的呈现出来。
#5
能说说看这个是什么应用场景吗?说清楚的话可能比较有针对性的探讨。
如果类似于p2p软件的共享 可能这些数据保存在客户端比较合适.例如cookie什么的,
不过cookie也有它的局限性,会给清理,保存内容有限 等等 不过4kb似乎也够了
这些文件目录是非固定的吧?
如果类似于p2p软件的共享 可能这些数据保存在客户端比较合适.例如cookie什么的,
不过cookie也有它的局限性,会给清理,保存内容有限 等等 不过4kb似乎也够了
这些文件目录是非固定的吧?
#6
数据库最简单的方式是
id title parentid
当然还有两中,可以搜索mysql tree 等等的关键字会找到。
前端用ajax吧。
id title parentid
当然还有两中,可以搜索mysql tree 等等的关键字会找到。
前端用ajax吧。
#7
是的,非固定的目录与文件。
有一点像是杀毒软件的架构,它一定会有一个排除扫瞄的清单。
当你没有去更改这些设置时,杀毒默认会扫瞄整个硬盘上的文件,对吧 ?
但假如我从这排除清单中新增了几个文件或目录,那自然在杀毒的扫瞄程序中就会被略过了。
ok, 场景回到目前的状况 ..
前端显示目前目录和文件树的设计目前是可以使用的,后端 PHP 也可以接收到这些来自前端的数据。
但我不知道该怎么去判断某一个文件或目录,他子父层的关系 ?
可能是仅有 2012/02/Chris-150x150.jpg 的文件和 2012/03 的目录被选取;
也可能是仅有 2012 整个目录和 icon/asp.asp 与 jar.jar 被选取等多种状况。
目前正在看一个国外插件的范例,希望可以和大家多多讨论,谢谢你们的热心。
class-file-list.php
<?php
/**
* A class with functions the perform a backup of WordPress
*
* @copyright Copyright (C) 2011 Michael De Wildt. All rights reserved.
* @author Michael De Wildt (http://www.mikeyd.com.au/)
* @license This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
*/
include_once( 'class-wp-backup.php' );
class File_List {
const EXCLUDED = 0;
const INCLUDED = 1;
const PARTIAL = 2;
/**
* A list of directories to mark as partial
* @var null
*/
private $partial_directories = array();
/**
* A list of files that are not allowed to be backed up
* @var null
*/
private $excluded_files = array();
/**
* These files cannot be uploaded to Dropbox
* @var array
*/
private static $ignored_files = array( '.DS_Store', 'Thumbs.db', 'desktop.ini' );
/**
* Construct the file list
* @param $wpdb
*/
public function __construct( $wpdb = null ) {
if ( !$wpdb ) global $wpdb;
$this->database = $wpdb;
$file_list = get_option( 'backup-to-dropbox-file-list' );
if ( $file_list === false ) {
$this->partial_directories = array();
$this->excluded_files = array();
add_option( 'backup-to-dropbox-file-list', array( $this->partial_directories, $this->excluded_files ), null, 'no' );
} else {
list( $this->partial_directories, $this->excluded_files ) = $file_list;
}
}
/**
* Return the state of a file in the list the SQL dump is always included
* @param $path
* @return bool
*/
public function get_file_state( $path ) {
$parent_path = dirname( $path ) . '/';
if ( $path == dirname( ABSPATH ) . '/' ) {
return self::PARTIAL;
} else if ( strstr( $path, DB_NAME . '-backup.sql' ) ) {
return self::INCLUDED;
} else if ( in_array( $path, $this->excluded_files ) ) {
return self::EXCLUDED;
} else if ( in_array( $path, $this->partial_directories ) ) {
$parent_state = $this->get_file_state( $parent_path );
if ( $parent_state == self::INCLUDED && $parent_path != ABSPATH ) {
$this->remove_from_partial( $path );
$this->remove_from_excluded( $path );
return self::INCLUDED;
}
return self::PARTIAL;
}
$state = $this->get_file_state( $parent_path );
if ( $state == self::PARTIAL ) {
$this->remove_from_partial( $path );
$this->remove_from_excluded( $path );
return self::INCLUDED;
}
return $state;
}
/**
* @param $full_path string
* @return string
*/
function get_check_box_class( $full_path ) {
$state = $this->get_file_state( $full_path );
switch ( $state ) {
case self::EXCLUDED:
$class = 'checked';
break;
case self::PARTIAL:
$class = 'partial';
break;
default: //INCLUDED so do not check
$class = '';
break;
}
return $class;
}
/**
* Adds a file to the excluded list if it does not already exist
* @param $file
* @return void
*/
private function add_to_excluded( $file ) {
if ( !in_array( $file, $this->excluded_files ) ) {
$this->excluded_files[] = $file;
}
}
/**
* Adds a file to the partial list if it does not already exist
* @param $file
* @return void
*/
private function add_to_partial( $file ) {
if ( !in_array( $file, $this->partial_directories ) ) {
$this->partial_directories[] = $file;
}
}
/**
* Accepts a JSON encoded list of files and directories and adds their states to the appropriate lists
* @param $json_list
* @return void
*/
public function set_file_list( $json_list ) {
$new_list = json_decode( stripslashes( $json_list ), true );
foreach ( $new_list as $fl ) {
list ( $file, $state ) = $fl;
if ( $state == self::PARTIAL ) {
$this->add_to_partial( $file );
$this->remove_from_excluded( $file );
} else if ( $state == self::EXCLUDED) {
$this->add_to_excluded( $file );
$this->remove_from_partial( $file );
} else {
$this->remove_from_excluded( $file );
$this->remove_from_partial( $file );
}
}
}
/**
* Removes a file from the excluded list if it exists
* @param $file
* @return void
*/
private function remove_from_excluded( $file ) {
if ( in_array( $file, $this->excluded_files ) ) {
$i = array_search( $file, $this->excluded_files );
unset( $this->excluded_files[$i] );
}
}
/**
* Removes a file from the partial list if it exists
* @param $file
* @return void
*/
private function remove_from_partial( $file ) {
if ( in_array( $file, $this->partial_directories ) ) {
$i = array_search( $file, $this->partial_directories );
unset( $this->partial_directories[$i] );
}
}
/**
* Saves the file list
* @return void
*/
public function save() {
update_option( 'backup-to-dropbox-file-list', array( $this->partial_directories, $this->excluded_files ) );
}
/**
* @param $dir
* @return int
*/
private function get_directory_state( $dir ) {
$files = scandir( $dir );
natcasesort( $files );
foreach ( $files as $file ) {
$state = $this->get_file_state( $file );
if ( $state == self::PARTIAL || $state == self::EXCLUDED ) {
return self::PARTIAL;
}
}
return self::INCLUDED;
}
/**
* Some files cannot be uploaded to Dropbox so check them here
* @static
* @param $file
* @return bool
*/
public static function in_ignore_list( $file ) {
return in_array( $file, self::$ignored_files );
}
}
#8
jquert-filetree.js
// jQuery File Tree Plugin
//
// Version 1.01
//
// Cory S.N. LaViska
// A Beautiful Site (http://abeautifulsite.net/)
// 24 March 2008
//
// Visit http://abeautifulsite.net/notebook.php?article=58 for more information
//
// Usage: $('.fileTreeDemo').fileTree( options, callback )
//
// Options: root - root folder to display; default = /
// script - location of the serverside AJAX file to use; default = jqueryFileTree.php
// folderEvent - event to trigger expand/collapse; default = click
// expandSpeed - default = 500 (ms); use -1 for no animation
// collapseSpeed - default = 500 (ms); use -1 for no animation
// expandEasing - easing function to use on expand (optional)
// collapseEasing - easing function to use on collapse (optional)
// multiFolder - whether or not to limit the browser to one subfolder at a time
// loadMessage - Message to display while initial tree loads (can be HTML)
//
// History:
//
// 1.01 - updated to work with foreign characters in directory/file names (12 April 2008)
// 1.00 - released (24 March 2008)
//
// TERMS OF USE
//
// This plugin is dual-licensed under the GNU General Public License and the MIT License and
// is copyright 2008 A Beautiful Site, LLC.
//
if(jQuery) (function($){
$.extend($.fn, {
fileTree: function(o) {
var EXCLUDED = 0;
var INCLUDED = 1;
var PARTIAL = 2;
// Defaults
if( !o ) var o = {};
if( o.root == undefined ) o.root = '/';
if( o.script == undefined ) o.script = 'jqueryFileTree.php';
if( o.folderEvent == undefined ) o.folderEvent = 'click';
if( o.expandSpeed == undefined ) o.expandSpeed= 500;
if( o.collapseSpeed == undefined ) o.collapseSpeed= 500;
if( o.expandEasing == undefined ) o.expandEasing = null;
if( o.collapseEasing == undefined ) o.collapseEasing = null;
if( o.multiFolder == undefined ) o.multiFolder = true;
if( o.loadMessage == undefined ) o.loadMessage = 'Loading...';
$(this).each( function() {
function showTree(c, t) {
$(c).addClass('wait');
$(".jqueryFileTree.start").remove();
$.post(o.script, { action: 'file_tree', dir: t }, function(data) {
$(c).find('.start').html('');
$(c).removeClass('wait').append(data);
if( o.root == t ) $(c).find('UL:hidden').show(); else $(c).find('UL:hidden').slideDown({ duration: o.expandSpeed, easing: o.expandEasing });
//Check that the list of files that we got from the server have not already
//been included or excluded in the UI.
$('.checkbox').each(function () {
var dir = escape(dirname($(this).attr('rel')));
if (dir == t) {
var state = get_include_state($(this).attr('rel'));
if (state !== false) {
set_checkbox_state(this, state);
}
}
});
bindTree(c);
});
}
function bindTree(t) {
$(t).find('LI A.tree').bind(o.folderEvent, function() {
if( $(this).parent().hasClass('directory') ) {
if( $(this).parent().hasClass('collapsed') ) {
// Expand
if( !o.multiFolder ) {
$(this).parent().parent().find('UL').slideUp({ duration: o.collapseSpeed, easing: o.collapseEasing });
$(this).parent().parent().find('LI.directory').removeClass('expanded').addClass('collapsed');
}
$(this).parent().find('UL').remove(); // cleanup
showTree( $(this).parent(), escape($(this).attr('rel').match( /.*\// )) );
$(this).parent().removeClass('collapsed').addClass('expanded');
} else {
// Collapse
$(this).parent().find('UL').slideUp({ duration: o.collapseSpeed, easing: o.collapseEasing });
$(this).parent().removeClass('expanded').addClass('collapsed');
}
} else {
var element = $(this).parent().find('.checkbox');
if (element.length) {
checkbox_click(element);
}
}
return false;
});
//Bind our check box clicks
$(t).find('ul').find('.checkbox').bind('click', function() {
checkbox_click(this);
});
// Prevent A from triggering the # on non-click events
if( o.folderEvent.toLowerCase != 'click' ) $(t).find('LI A').bind('click', function() { return false; });
}
// Loading message
$(this).html('<ul class="jqueryFileTree start"><li class="wait">' + o.loadMessage + '<li></ul>');
// Get the initial file list
showTree( $(this), escape(o.root) );
});
/**
* Updates the tri state check box based on the state hidden element passed
* @param check_box
*/
function set_checkbox_state(check_box, new_state) {
new_state = parseInt(new_state);
$(check_box).removeClass('checked');
$(check_box).removeClass('partial');
switch(new_state) {
case EXCLUDED:
$(check_box).addClass('checked');
break;
case PARTIAL:
$(check_box).addClass('partial');
break;
default:
break; //INCLUDED - Do nothing
}
}
/**
* Toggles the hidden list input with what has changed
* @param element
*/
function set_include_state(element) {
var file = $(element).attr('rel');
var state = get_checkbox_state(element);
var file_tree_list = JSON.parse($('#file_tree_list').val());
var in_list = false;
for (var i = 0; i < file_tree_list.length; i++) {
if (file_tree_list[i][0] == file) {
file_tree_list[i][1] = state;
in_list = true;
break;
}
}
if (!in_list) {
file_tree_list.push([file, state])
}
$('#file_tree_list').val(JSON.stringify(file_tree_list));
}
/**
* Get the file state from the local list
* @param file
* @return int
*/
function get_include_state(file) {
var file_list = JSON.parse($('#file_tree_list').val());
for (var i = 0; i < file_list.length; i++) {
if (file_list[i][0] == file) {
return file_list[i][1];
}
}
return false;
}
/**
* Just like PHP's dirname
* @param path
*/
function dirname(path) {
return path.replace(/\/$/, '').replace(/\/[^\/]*$/, '/');
}
/**
* Toggles the directory check box to ON, OFF or PARTIAL depending on the state of all its children.
* @param clicked
*/
function toggle_directory_check(clicked) {
//Also check its directory if they are all not checked
var checked_count = 0, total = 0;
var clicked_parent_dir = dirname($(clicked).attr('rel'));
$('.checkbox').each(function () {
if (clicked_parent_dir != o.root) {
var parent_dir = dirname($(this).attr('rel'));
if (parent_dir == clicked_parent_dir) {
var state = get_checkbox_state(this);
if (state == PARTIAL || state == EXCLUDED) {
checked_count++;
}
total++;
}
}
});
//Now that we know that the state of all the directories children we can update the parent dir accordingly
$('.checkbox').each(function () {
if ($(this).attr('rel') == clicked_parent_dir) {
if (checked_count == total) {
set_checkbox_state(this, EXCLUDED);
} else if (checked_count == 0) {
set_checkbox_state(this, INCLUDED);
} else {
set_checkbox_state(this, PARTIAL);
}
set_include_state(this);
toggle_directory_check(this);
}
});
}
/**
* Return the current state of a clicked check box
* @param clicked
*/
function get_checkbox_state(clicked) {
var state = INCLUDED;
if ($(clicked).hasClass('partial')) {
state = PARTIAL;
} else if ($(clicked).hasClass('checked')) {
state = EXCLUDED;
}
return state;
}
/**
* Set all the children of a directory to a state
* @param parent
*/
function set_directory_children(parent, state) {
//If this is an expanded directory recursively update all its children
if ($(parent).parent().hasClass('expanded') && $(parent).hasClass('directory')) {
$('.checkbox').each(function () {
if (dirname($(this).attr('rel')) == $(parent).attr('rel')) {
set_checkbox_state(this, state);
set_include_state(this);
set_directory_children(this, state);
}
});
}
}
/**
* The on click function for a file check box. If the user clicks on a directory then all its open children
* need to be updated accordingly.
* @param clicked
*/
function checkbox_click(clicked) {
var state = get_checkbox_state(clicked) == EXCLUDED ? INCLUDED : EXCLUDED;
set_checkbox_state(clicked, state);
set_include_state(clicked);
set_directory_children(clicked, state);
toggle_directory_check(clicked);
}
}
});
})(jQuery);
#9
感觉LZ把简单的问题复杂化了
#10
哈哈,对啊对啊 .. 请你给我当头棒喝一下 :-D