583 lines
17 KiB
PHP
583 lines
17 KiB
PHP
<?php
|
|
|
|
require_once 'core/path.php';
|
|
require_once 'core/file.php';
|
|
|
|
interface IFileSystem
|
|
{
|
|
// Îïåðàöèè íàä ôàéëàìè
|
|
public function makeDirectory($name);
|
|
public function deleteDirectory($name);
|
|
|
|
public function deleteFile($name);
|
|
public function renameFile($source, $destination);
|
|
public function copyFile($source, $destination);
|
|
public function moveUploadedFile($source, $destination);
|
|
// deleteDirectoryRecursive
|
|
public function isDir($name);
|
|
|
|
public function readFile($source);
|
|
public function writeFile($source, $content);
|
|
// Ñîäåðæàíèå äèðåêòîðèè
|
|
public function directoryFiles($name);
|
|
public function directoryFilesRecursive($name);
|
|
}
|
|
|
|
interface IFileControl
|
|
{
|
|
public function commitFile($name, $who, $message);
|
|
public function readFileVersion($name, $version = false);
|
|
// Èíôîðìàöèÿ î ôàéëå
|
|
public function getFileLog($name);
|
|
public function getFileInfo($name);
|
|
}
|
|
|
|
// Ðåàëüíàÿ ôàéëîâàÿ ñèñòåìà
|
|
class FileSystem implements IFileSystem
|
|
{
|
|
protected $hidden = array('.', '..');
|
|
protected $visible = null;
|
|
|
|
public function __construct()
|
|
{
|
|
}
|
|
|
|
public function setVisibleFiles(array $visible)
|
|
{
|
|
$this->visible = $visible;
|
|
}
|
|
|
|
public function setHiddenFiles(array $hidden)
|
|
{
|
|
$this->hidden = array_merge($this->hidden, $hidden);
|
|
}
|
|
|
|
/**
|
|
*
|
|
*/
|
|
public function makeDirectory($name)
|
|
{
|
|
if (file_exists($name) === false) {
|
|
mkdir($name);
|
|
}
|
|
}
|
|
|
|
/**
|
|
*
|
|
*/
|
|
public function makeFile($name)
|
|
{
|
|
if (file_exists($name) === false) {
|
|
file_put_contents($name, '');
|
|
}
|
|
}
|
|
|
|
/**
|
|
*
|
|
*/
|
|
public function deleteDirectory($name)
|
|
{
|
|
rmdir($name);
|
|
}
|
|
|
|
/**
|
|
*
|
|
*/
|
|
public function deleteDirectoryRecursive($name)
|
|
{
|
|
if ($handle = opendir($name)) {
|
|
while (false !== ($file = readdir($handle))) {
|
|
if ($file != "." && $file != "..") {
|
|
$sf = $name . DIRECTORY_SEPARATOR . $file;
|
|
if (is_dir($sf) && !is_link($sf)) {
|
|
self::deleteDirectoryRecursive($sf);
|
|
} else {
|
|
unlink($sf);
|
|
}
|
|
}
|
|
}
|
|
closedir($handle);
|
|
@rmdir($name);
|
|
}
|
|
}
|
|
|
|
/**
|
|
*
|
|
*/
|
|
public function deleteFile($name)
|
|
{
|
|
if (file_exists($name)) {
|
|
unlink($name);
|
|
}
|
|
}
|
|
|
|
// Ïðè ïåðåìåùåíèè èëè âñå ôàéëû åñëè åñòü ñîâïàäåíèÿ ïåðåïèñûâàþòñÿ
|
|
/**
|
|
*
|
|
*/
|
|
public function renameFile($source, $destination)
|
|
{
|
|
rename($source, $destination);
|
|
}
|
|
|
|
/**
|
|
*
|
|
*/
|
|
public function copyFile($source, $destination)
|
|
{
|
|
copy($source, $destination);
|
|
}
|
|
|
|
/**
|
|
*
|
|
*/
|
|
public function copyDirectory($source, $destination)
|
|
{
|
|
if (is_dir($source)) {
|
|
if (! file_exists($destination)) mkdir($destination);
|
|
$handle = opendir($source);
|
|
while (false !== ($file = readdir($handle))) {
|
|
$entry = $source . DIRECTORY_SEPARATOR . $file;
|
|
if (is_dir($entry)) {
|
|
self::copyDirectory($entry, $destination . DIRECTORY_SEPARATOR . $file);
|
|
} else {
|
|
copy($entry, $destination . DIRECTORY_SEPARATOR . $file);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
*
|
|
*/
|
|
public function moveUploadedFile($source, $destination)
|
|
{
|
|
move_uploaded_file($source, $destination);
|
|
}
|
|
|
|
/**
|
|
*
|
|
*/
|
|
public function isVisible($file)
|
|
{
|
|
if (in_array(basename($file), $this->hidden) === true) {
|
|
return false;
|
|
}
|
|
return ($this->isDir($file) || $this->visible == null) || in_array(pathinfo($file, PATHINFO_EXTENSION), $this->visible);
|
|
}
|
|
|
|
/**
|
|
*
|
|
*/
|
|
public function directoryFiles($name)
|
|
{
|
|
$result = array();
|
|
$files = scandir($name);
|
|
foreach ($files as $file) {
|
|
$fullname = $name . DIRECTORY_SEPARATOR . $file;
|
|
if ($this->isVisible($fullname)) {
|
|
$result [$file] = new FileRecord(array(), $fullname);
|
|
}
|
|
}
|
|
return $result;
|
|
}
|
|
|
|
/**
|
|
*
|
|
*/
|
|
public function readFile($name)
|
|
{
|
|
return file_get_contents($name);
|
|
}
|
|
|
|
/**
|
|
*
|
|
*/
|
|
public function writeFile($name, $content)
|
|
{
|
|
file_put_contents($name, $content);
|
|
}
|
|
|
|
/**
|
|
*
|
|
*/
|
|
public function directoryFilesRecursive($name)
|
|
{
|
|
}
|
|
|
|
function isDir($name)
|
|
{
|
|
return is_dir($name);
|
|
}
|
|
}
|
|
|
|
// Òî ÷òî õðàíèòñÿ â áàçå äàííûõ
|
|
class EFileSystem implements IFileSystem, IFileControl
|
|
{
|
|
|
|
protected $basepath;
|
|
protected $db;
|
|
|
|
public function __construct($basepath, $db, $fs)
|
|
{
|
|
$this->basepath = $basepath;
|
|
$this->db = $db;
|
|
$this->fs = $fs;
|
|
}
|
|
|
|
/*function createExtendRecord($index)
|
|
{
|
|
static $fileSQL = "INSERT INTO file (id_record) VALUES (?)";
|
|
$query = $this->db->prepareStatement($fileSQL);
|
|
$query->setString(1, $index);
|
|
$query->executeQuery();
|
|
}*/
|
|
|
|
private function createRecord($name, $type, $path)
|
|
{
|
|
static $recordSQL = "INSERT INTO files (filename, idfile, lastrevdate, filepath, filetype) VALUES (?, ?, ?, ?, ?)";
|
|
$last = $this->db->getIdGenerator();
|
|
$index = $last->getId('files_idfile_seq');
|
|
|
|
$query = $this->db->prepareStatement($recordSQL);
|
|
$query->setString(1, $name);
|
|
$query->setInt(2, $index);
|
|
$query->setInt(3, 0);
|
|
$query->setString(4, $path);
|
|
$query->setString(5, $type);
|
|
$query->executeQuery();
|
|
/*if ($type == 0) {
|
|
$this->createExtendRecord($index);
|
|
}*/
|
|
|
|
return $index;
|
|
}
|
|
|
|
function setVisibleFiles(array $visible)
|
|
{
|
|
$this->fs->setVisibleFiles($visible);
|
|
}
|
|
|
|
function setHiddenFiles(array $hidden)
|
|
{
|
|
$this->fs->setHiddenFiles($hidden);
|
|
}
|
|
|
|
public function getFullPath($name)
|
|
{
|
|
return Path::join($this->basepath, $name);
|
|
}
|
|
|
|
private function getRecordId($name, $path)
|
|
{
|
|
static $recordSQL = "SELECT idfile FROM files WHERE filename = ? AND filepath = ?";
|
|
|
|
$query = $this->db->prepareStatement($recordSQL);
|
|
$query->setString(1, $name);
|
|
$query->setString(2, $path);
|
|
$result = $query->executeQuery();
|
|
if ($result->next()) {
|
|
$index = $result->getInt('idfile');
|
|
return $index;
|
|
}
|
|
return false; // Ìîæåò ëó÷øå êèäàòü èñêëþ÷åíèå ??
|
|
}
|
|
|
|
function getIdFromPath($name)
|
|
{
|
|
return $this->getRecordId(basename($name), self::getPathName($name));
|
|
}
|
|
|
|
// Ñîçäàíèå íîâîé äèðåêòîðèè
|
|
public function makeDirectory($name)
|
|
{
|
|
$path = new Path($name);
|
|
$fullpath = $this->basepath;
|
|
$temp_path = '';
|
|
foreach ($path->getParts() as $subpath)
|
|
{
|
|
$index = $this->getRecordId($subpath, $temp_path);
|
|
if ($index === false) {
|
|
$index = $this->createRecord($subpath, 1, $temp_path);
|
|
}
|
|
$temp_path = Path::join($temp_path, $subpath);
|
|
}
|
|
|
|
$this->fs->makeDirectory($this->getFullPath($name));
|
|
}
|
|
|
|
public function isDir($name)
|
|
{
|
|
return $this->fs->isDir($this->getFullPath($name));
|
|
}
|
|
|
|
// Ïåðåèìåíîâàíèå ôàéëà èëè äèðåêòîðèè âñå èçìåíåíèÿ äîëæíû çàïèñûâàòüñÿ â áàçó ÷òîáû ìîæíî áûëî ñäåëàòü îòìåíó !!!
|
|
public function renameFile($source, $destination)
|
|
{
|
|
// Ïðè ïåðåìåùåíèè ôàéëû ìîãóò ñîâïàäàòü
|
|
$stmt = $this->db->prepareStatement('UPDATE files SET filepath = ?, filename = ? WHERE filepath = ? AND filename = ?');
|
|
$stmt->setString(1, self::getPathName($destination));
|
|
$stmt->setString(2, basename($destination));
|
|
$stmt->setString(3, self::getPathName($source));
|
|
$stmt->setString(4, basename($source));
|
|
$stmt->executeQuery();
|
|
|
|
if ($this->isDir($source)) {
|
|
$length = strlen($from) + 1;
|
|
$stmt = $this->db->prepareStatement("UPDATE file
|
|
SET filepath = '?' || substr(filepath, ?) WHERE filepath LIKE (?) OR filepath LIKE (? || '/%')");
|
|
$stmt->setString(1, $destination);
|
|
$stmt->setInt(2, $length);
|
|
$stmt->setString(3, $source);
|
|
$stmt->setString(4, $source);
|
|
}
|
|
|
|
$this->fs->renameFile($this->getFullPath($source), $this->getFullPath($destination));
|
|
}
|
|
|
|
// Êîïèðîâàíèå ôàéëà èëè äèðåêòîðèè
|
|
public function copyFile($source, $destination)
|
|
{
|
|
// Ïðè êîïèðîâàíèè ôàéëû ìîãóò ñîâïàäàòü
|
|
$stmt = $this->db->prepareStatement('INSERT INTO files (filepath, filename, lastrevdate) VALUES (?, ?, ?)');
|
|
$stmt->setString(1, self::getPathName($destination));
|
|
$stmt->setString(2, basename($destination));
|
|
$stmt->setString(3, time());
|
|
$stmt->executeQuery();
|
|
|
|
if ($this->isDir($source)) {
|
|
$stmt = $this->db->prepareStatement("INSERT INTO files (filepath, filename, lastrevdate)
|
|
SELECT '?' || substr(filepath, ?) AS filepath, filename, lastrevdate WHERE WHERE filepath LIKE (?) OR filepath LIKE (? || '/%')");
|
|
|
|
$stmt->setString(1, $destination);
|
|
$stmt->setInt(2, $length);
|
|
$stmt->setString(3, $source);
|
|
$stmt->setString(4, $source);
|
|
}
|
|
|
|
$this->fs->copyFile($this->getFullPath($source), $this->getFullPath($destination));
|
|
}
|
|
|
|
private function getPathName($name)
|
|
{
|
|
$path = dirname($name);
|
|
return ($path == '.') ? '' : $path;
|
|
}
|
|
|
|
public function makeFile($name)
|
|
{
|
|
$base = self::getPathName($name);
|
|
$this->makeDirectory($base);
|
|
|
|
$filename = basename($name);
|
|
$index = $this->getRecordId($filename, $base);
|
|
|
|
if ($index === false) {
|
|
$index = $this->createRecord($filename, 0, $base);
|
|
}
|
|
$this->fs->makeFile($this->getFullPath($name));
|
|
}
|
|
|
|
public function readFile($name)
|
|
{
|
|
return $this->fs->readFile($this->getFullPath($name));
|
|
}
|
|
|
|
public function readFileVersion($name, $revision = false)
|
|
{
|
|
if ($revision === false) {
|
|
return $this->readFile($name);
|
|
} else {
|
|
$id_file = $this->getIdFromPath($name);
|
|
$query = $this->db->prepareStatement("SELECT * FROM history WHERE revision = ? AND idfile = ?");
|
|
$query->setInt(1, $revision);
|
|
$query->setInt(2, $id_file);
|
|
$file = $query->executeQuery();
|
|
if ($file->next()) {
|
|
return gzuncompress($file->getBlob('content'));
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
|
|
public function writeFile($name, $content)
|
|
{
|
|
$this->makeFile($name);
|
|
$this->fs->writeFile($this->getFullPath($name), $content);
|
|
}
|
|
|
|
public function getLastRevision($name)
|
|
{
|
|
$id_file = $this->getIdFromPath($name);
|
|
$stmt = $this->db->prepareStatement("SELECT * FROM history WHERE revision IN (SELECT MAX(revision) AS lastrev FROM history WHERE idfile = ?)");
|
|
$stmt->setInt(1, $id_file);
|
|
$rev = $stmt->executeQuery();
|
|
if ($rev->next()) {
|
|
return $rev;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
*
|
|
*/
|
|
public function commitFile($name, $owner, $message)
|
|
{
|
|
$id_file = $this->getIdFromPath($name);
|
|
$content = $this->readFile($name);
|
|
|
|
$stmt = $this->db->prepareStatement("SELECT MAX(revision) AS lastrev FROM history WHERE idfile = ?");
|
|
$stmt->setInt(1, $id_file);
|
|
$rev = $stmt->executeQuery();
|
|
$revision = ($rev->next()) ? $rev->getInt('lastrev') + 1 : 1;
|
|
|
|
$query = $this->db->prepareStatement("INSERT INTO history (content, owner, revsummary, revdate, revision, idfile) VALUES (?, ?, ?, ?, ?, ?)");
|
|
$query->setBlob(1, gzcompress($content));
|
|
$query->setString(2, $owner);
|
|
$query->setString(3, $message);
|
|
$query->setInt(4, time());
|
|
$query->setInt(5, $revision);
|
|
$query->setInt(6, $id_file);
|
|
$query->executeQuery();
|
|
}
|
|
|
|
/**
|
|
*
|
|
*/
|
|
public function getFileDifference($name, $revision1, $revision2 = false)
|
|
{
|
|
$first = $this->readFileVersion($name, $revision1);
|
|
$second = $this->readFileVersion($name, $revision2);
|
|
}
|
|
|
|
/**
|
|
*
|
|
*/
|
|
public function getFileLog($name)
|
|
{
|
|
$id_file = $this->getIdFromPath($name);
|
|
$query = $this->db->prepareStatement("SELECT revision,revsummary,owner,revdate FROM history WHERE idfile = ? ORDER BY revision");
|
|
$query->setInt(1, $id_file);
|
|
$list = $query->executeQuery();
|
|
return iterator_to_array($list->getIterator());
|
|
}
|
|
|
|
public function directoryFiles($name)
|
|
{
|
|
$result = $this->fs->directoryFiles($this->getFullPath($name));
|
|
|
|
/* Ñïèñîê ôàéëîâ èç áàçû äàííûõ */
|
|
$query = $this->db->prepareStatement("SELECT * FROM files WHERE filepath = ?");
|
|
$query->setString(1, $name);
|
|
$list = $query->executeQuery();
|
|
|
|
foreach ($list as $file) {
|
|
$fullpath = $this->getFullPath($name . DIRECTORY_SEPARATOR . $file['filename']);
|
|
if ($this->fs->isVisible($fullpath)) {
|
|
$file['state'] =
|
|
((isset($result[$file['filename']])) ?
|
|
(($file['lastrevdate'] > $file['change']) ? 'exclamation' : 'unchanged')
|
|
: 'expected');
|
|
$record = new FileRecord($file, $fullpath);
|
|
$result [$file['filename']] = $record;
|
|
}
|
|
}
|
|
return $result;
|
|
}
|
|
|
|
public function getFileInfo($name)
|
|
{
|
|
$index = $this->getIdFromPath($name);
|
|
$fullpath = $this->basepath . DIRECTORY_SEPARATOR . $name;
|
|
if ($index !== false) {
|
|
$query = $this->db->prepareStatement("SELECT * FROM files AS r LEFT JOIN filemeta AS f ON r.idfile = f.id_record WHERE r.idfile = ?");
|
|
$query->setInt(1, $index);
|
|
$list = $query->executeQuery();
|
|
$list->next();
|
|
$file = $list->getRow();
|
|
$file['state'] = (file_exists($fullpath) ? 'unchanged' : 'expected');
|
|
$result = new FileRecord($file, $fullpath);
|
|
} else {
|
|
$result = new FileRecord(array(), $fullpath);
|
|
}
|
|
return $result;
|
|
}
|
|
|
|
public function setFileInfo($name, Collection $list)
|
|
{
|
|
$index = $this->getIdFromPath($name);
|
|
if ($index !== false) {
|
|
$stmt = $this->db->prepareStatement("UPDATE files SET title = ? WHERE idfile = ?");
|
|
$stmt->setString(1, $list->get('title'));
|
|
$stmt->setInt(2, $index);
|
|
$stmt->executeQuery();
|
|
/*if (some($list, array('keywords', 'author', 'description'))) {
|
|
$hasfile = $this->db->executeQuery("SELECT * FROM file WHERE id_record = $index");
|
|
if(!$hasfile->next()) {
|
|
static $fileSQL = "INSERT INTO file (id_record) VALUES (?)";
|
|
$query = $this->db->prepareStatement($fileSQL);
|
|
$query->setString(1, $index);
|
|
$query->executeQuery();
|
|
}
|
|
$query = $this->db->prepareStatement("UPDATE file SET keywords = ?, author = ?, description = ? WHERE id_record = ?");
|
|
$query->setString(1, $list->get('keywords'));
|
|
$query->setString(2, $list->get('author'));
|
|
$query->setString(3, $list->get('description'));
|
|
$query->setInt(4, $index);
|
|
$query->executeQuery();
|
|
}*/
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Óäàëÿåì äèðåêòîðèþ åñëè îíà íå ïóñòàÿ
|
|
*/
|
|
function deleteDirectory($name)
|
|
{
|
|
$index = $this->getIdFromPath($name);
|
|
|
|
$query = $this->db->prepareStatement("SELECT COUNT(*) AS col FROM files WHERE filepath = (?) OR filepath LIKE(? || '/%')");
|
|
$query->setString(1, $name);
|
|
$query->setString(2, $name);
|
|
$result = $query->executeQuery();
|
|
$result->next();
|
|
|
|
if ($index && $result->getInt('col') == 0) {
|
|
$query = $this->db->prepareStatement("DELETE FROM files WHERE idfile = ?");
|
|
$query->setInt(1, $index);
|
|
$query->executeQuery();
|
|
}
|
|
$this->fs->deleteDirectory($this->getFullPath($name));
|
|
}
|
|
|
|
function deleteFile($name)
|
|
{
|
|
$index = $this->getIdFromPath($name);
|
|
if ($index) {
|
|
|
|
$query = $this->db->prepareStatement("DELETE FROM history WHERE idfile = ?;
|
|
DELETE FROM filemeta WHERE id_record = ?;DELETE FROM files WHERE idfile = ?");
|
|
$query->setInt(1, $index);
|
|
$query->setInt(2, $index);
|
|
$query->setInt(3, $index);
|
|
$query->executeQuery();
|
|
}
|
|
$this->fs->deleteFile($this->getFullPath($name));
|
|
}
|
|
|
|
function moveUploadedFile($source, $destination)
|
|
{
|
|
$this->fs->moveUploadedFile($source, $this->getFullPath($destination));
|
|
$this->makeFile($destination);
|
|
}
|
|
|
|
function directoryFilesRecursive($name)
|
|
{
|
|
$files = $this->fs->directoryFilesRecursive($this->getFullPath($name));
|
|
|
|
$query = $this->db->prepareStatement("DELETE FROM files WHERE filepath = (?) OR filepath LIKE (? || '/%')");
|
|
$query->setString(1, $name);
|
|
$query->setString(2, $name);
|
|
$query->executeQuery();
|
|
}
|
|
}
|