26 error_reporting(E_ALL);
27 if ((php_sapi_name() !=
'cli')) trigger_error(
"You can only run this script from the command line\n", E_USER_ERROR);
29 $SYSTEM_ROOT = (isset($_SERVER[
'argv'][1])) ? $_SERVER[
'argv'][1] :
'';
30 if (empty($SYSTEM_ROOT)) {
31 echo
"ERROR: You need to supply the path to the System Root as the first argument\n";
36 if (!is_dir($SYSTEM_ROOT) || !is_readable($SYSTEM_ROOT.
'/core/include/init.inc')) {
37 echo
"ERROR: Path provided doesn't point to a Matrix installation's System Root. Please provide correct path and try again.\n";
42 $command = (isset($_SERVER[
'argv'][2])) ? $_SERVER[
'argv'][2] :
'test';
44 $TREE_ID = (isset($_SERVER[
'argv'][3])) ? $_SERVER[
'argv'][3] :
'1';
46 echo
"You want to $command the file versioning system. Your selected root node is #$TREE_ID\n\n";
48 require_once $SYSTEM_ROOT.
'/core/include/init.inc';
50 $root_user = &$GLOBALS[
'SQ_SYSTEM']->am->getSystemAsset(
'root_user');
52 if (!$GLOBALS[
'SQ_SYSTEM']->setCurrentUser($root_user)) {
53 echo
"ERROR: Failed login in as root user\n";
58 $assetids = $GLOBALS[
'SQ_SYSTEM']->am->getChildren($TREE_ID,
'file', FALSE);
61 if ($TREE_ID !=
'1') {
62 $asset = $GLOBALS[
'SQ_SYSTEM']->am->getAsset($TREE_ID);
63 if ($GLOBALS[
'SQ_SYSTEM']->am->isTypeDecendant($asset->type(),
'file') || $asset instanceof
Image_Variety) {
64 $assetids[$asset->id] = Array(0 => Array(
'type_code' => $asset->type()));
68 $fv = $GLOBALS[
'SQ_SYSTEM']->getFileVersioning();
73 $imageids = $assetids;
74 foreach ($imageids as $assetid => $asset_info) {
75 $asset = $GLOBALS[
'SQ_SYSTEM']->am->getAsset($assetid);
76 if($asset instanceof
Image) {
77 $varieties = $asset->attr(
'varieties');
78 if(empty($varieties))
continue;
79 foreach($varieties[
'data'] as $id => $details) {
80 $assetids[$asset->id.
':'.$id] = $details;
86 foreach ($assetids as $assetid => $asset_info) {
87 $asset = $GLOBALS[
'SQ_SYSTEM']->am->getAsset($assetid);
88 if($asset instanceof Image_Variety) {
89 $file_name = $asset->attr(
'filename');
92 $file_name = $asset->name;
94 $rep_file = $asset->data_path_suffix.
'/'.$file_name;
95 $real_file = $asset->data_path.
'/'.$file_name;
98 $db_info = $fv->_getFileInfoFromPath($rep_file);
101 if (empty($db_info)) {
102 $db_info = Array(
'version' => 0);
106 $fs_info = _getFileInfoFromRealFile($fv, $real_file);
109 if (($fs_info == FUDGE_FV_NOT_CHECKED_OUT) || ($fs_info == FUDGE_FV_ERROR)) {
110 $fs_info = Array(
'version' => 0);
115 if ($db_info[
'version'] != $fs_info[
'version']) {
118 $file_id = isset($db_info[
'fileid'])? $db_info[
'fileid'] : $fs_info[
'fileid'];
119 echo
"The versions of the file asset #{$asset->id} (fileid = $file_id, rep_path = $rep_file) are different. Database version: {$db_info['version']} - File system version {$fs_info['version']}\n";
122 if ($command ==
'recover') {
125 if ($db_info[
'version'] > $fs_info[
'version']) {
127 $new_version = $db_info[
'version'];
128 $is_fixed = _updateVersionFile($fv, $asset->data_path_suffix, $real_file, $db_info, $new_version);
131 $is_fixed = $fv->_createFFVFile($real_file, $db_info[
'fileid'], $new_version);
133 echo
"ERROR: CAN NOT CREATE FFV CONFIGURATION FILE!\n";
136 echo
"ERROR: CAN NOT COPY CURRENT FILE TO VERSION FILE!\n";
141 if ($db_info[
'version'] == 0) {
143 _insertFileVersFileInfo($fv, $fs_info[
'fileid'], $rep_file);
146 $new_version = $fs_info[
'version'];
147 $is_fixed = _updateVersionFile($fv, $asset->data_path_suffix, $real_file, $fs_info, $new_version);
149 if ($new_version != $fs_info[
'version']) {
151 $is_fixed = $fv->_createFFVFile($real_file, $fs_info[
'fileid'], $new_version);
153 echo
"ERROR: CAN NOT CREATE FFV CONFIGURATION FILE!\n";
157 $is_fixed = _updateFileVersionHistory($fv, $fs_info[
'fileid'], $real_file, $new_version);
159 echo
"ERROR: CAN NOT UPDATE VERSION HISTORY TABLE IN DB!\n";
163 echo
"ERROR: CAN NOT COPY CURRENT FILE TO VERSION FILE!\n";
170 $asset->permissionsUpdated();
178 if ($error_count > 0) {
179 echo
"\nThere are $error_count errors detected in the file versioning system. $error_fixed are fixed!\n";
181 echo
"\nThere are no errors detected.\n";
197 function _getFileInfoFromRealFile($file_versioning, $real_file)
199 $ffv_dir = dirname($real_file).
'/.FFV';
201 if (!is_dir($ffv_dir))
return FUDGE_FV_NOT_CHECKED_OUT;
203 $ffv_file = $ffv_dir.
'/'.basename($real_file);
204 if (!is_file($ffv_file)) {
205 return FUDGE_FV_NOT_CHECKED_OUT;
208 $ffv = parse_ini_file($ffv_file);
209 if (!is_array($ffv)) {
210 trigger_localised_error(
'FVER0025', E_USER_WARNING);
211 return FUDGE_FV_ERROR;
214 if (realpath($file_versioning->_dir) != realpath($ffv[
'dir'])) {
215 trigger_localised_error(
'FVER0008', E_USER_WARNING);
216 return FUDGE_FV_ERROR;
230 function _getNextVersion($fileid){
231 $sql =
'SELECT COALESCE(MAX(version), 0) + 1
232 FROM sq_file_vers_history
233 WHERE fileid = :fileid';
239 }
catch (Exception $e) {
258 function _updateVersionFile($file_versioning, $rep_path, $real_file, $file_info, &$new_version) {
259 $fileid = $file_info[
'fileid'];
260 $version = $file_info[
'version'];
261 $new_version = $version;
262 if (file_exists($real_file)) {
263 $real_file_size = filesize($real_file);
264 $real_file_md5 = md5_file($real_file);
265 $real_file_sha1 = sha1_file($real_file);
267 require_once SQ_FUDGE_PATH.
'/general/file_system.inc';
268 $rep_dir = $file_versioning->_dir.
'/'.$rep_path;
269 if (!is_dir($rep_dir) && !create_directory($rep_dir)) {
270 echo
"ERROR: CAN NOT CREATE FOLDER: $rep_dir\n";
274 $rep_file = $rep_dir.
'/'.basename($real_file).
',ffv'.$version;
276 if (!file_exists($rep_file)) {
278 if (!copy($real_file, $rep_file))
return FALSE;
281 if (($real_file_size != filesize($rep_file)) || ($real_file_md5 != md5_file($rep_file)) || ($real_file_sha1 != sha1_file($rep_file))) {
282 $next_version = _getNextVersion($fileid);
283 if ($next_version == 0) {
287 if ($next_version > $version) {
288 $nv = $file_versioning->_updateFile($fileid, $rep_path, $real_file);
290 if ($nv == 0)
return FALSE;
296 $rep_file = $rep_dir.
'/'.basename($real_file).
',ffv'.$version;
297 if (!copy($real_file, $rep_file))
return FALSE;
298 if (!_updateFileVersionHistory($file_versioning, $fileid, $real_file, $version))
return FALSE;
299 $new_version = $version;
306 if (($new_version == $version) && isset($file_info[
'file_size'])) {
307 if (($real_file_size != $file_info[
'file_size']) || ($real_file_md5 != $file_info[
'md5']) || ($real_file_sha1 != $file_info[
'sha1'])) {
308 return $file_versioning->_updateFileVersion($real_file, $fileid, $version);
330 function _updateFileVersionHistory($file_versioning, $fileid, $real_file, $version, $extra_info=
'')
332 $GLOBALS[
'SQ_SYSTEM']->changeDatabaseConnection(
'db2');
333 $GLOBALS[
'SQ_SYSTEM']->doTransaction(
'BEGIN');
337 $db_version_info = $file_versioning->_getFileInfoAtVersion($fileid, $version);
338 if (!empty($db_version_info)) {
339 echo
"ERROR: THIS FILE (FILEID = $fileid, VERSION = $version) IS NO LONGER USED SINCE {$db_version_info['to_date']}\n";
344 $date = ts_iso8601($now);
349 $sql =
'UPDATE sq_file_vers_history
350 SET to_date = :to_date
351 WHERE fileid = :fileid
352 AND to_date IS NULL';
357 $sql = str_replace(
':to_date', db_extras_todate(
MatrixDAL::getDbType(),
':to_date', FALSE), $sql);
363 }
catch (Exception $e) {
364 throw new Exception(
'Unable to update version history for file ID '.$fileid.
' due to database error: '.$e->getMessage());
367 if (file_exists($real_file)) {
368 $file_size = filesize($real_file);
369 $md5 = md5_file($real_file);
370 $sha1 = sha1_file($real_file);
379 $sql =
'INSERT INTO sq_file_vers_history
380 (fileid, version, from_date, to_date, file_size, md5, sha1, removal, extra_info)
382 (:fileid, :version, :from_date, :to_date, :file_size, :md5, :sha1, :removal, :extra_info)';
386 $sql = str_replace(
':from_date', db_extras_todate(
MatrixDAL::getDbType(),
':from_date', FALSE), $sql);
399 }
catch (Exception $e) {
400 throw new Exception(
'Unable to insert version history for file ID '.$fileid.
' due to database error: '.$e->getMessage());
403 $GLOBALS[
'SQ_SYSTEM']->doTransaction(
'COMMIT');
404 $GLOBALS[
'SQ_SYSTEM']->restoreDatabaseConnection();
405 }
catch (Exception $e) {
406 echo
"ERROR: ".$e->getMessage().
"\n";
407 $GLOBALS[
'SQ_SYSTEM']->doTransaction(
'ROLLBACK');
408 $GLOBALS[
'SQ_SYSTEM']->restoreDatabaseConnection();
425 function _insertFileVersFileInfo($file_versioning, $fileid, $rep_file) {
426 $sql =
'SELECT COUNT(*)
427 FROM sq_file_vers_file
428 WHERE fileid = :fileid';
434 }
catch (Exception $e) {
435 echo
"ERROR: ".$e->getMessage().
"\n";
440 if ($fileid_count != 0) {
444 $GLOBALS[
'SQ_SYSTEM']->changeDatabaseConnection(
'db2');
445 $GLOBALS[
'SQ_SYSTEM']->doTransaction(
'BEGIN');
447 $sql =
'INSERT INTO sq_file_vers_file (fileid, path, filename)
448 VALUES (:fileid, :path, :filename)';
456 $GLOBALS[
'SQ_SYSTEM']->doTransaction(
'COMMIT');
457 $GLOBALS[
'SQ_SYSTEM']->restoreDatabaseConnection();
458 }
catch (Exception $e) {
459 echo
"ERROR: ".$e->getMessage().
"\n";
460 $GLOBALS[
'SQ_SYSTEM']->doTransaction(
'ROLLBACK');
461 $GLOBALS[
'SQ_SYSTEM']->restoreDatabaseConnection();
471 function print_usage() {
472 echo
"\n\n------------------------------------------------------------------------------------------------\n\n";
473 echo
"This script is used to test and recover file (and its decendants) assets.\n\n";
474 echo
"Usage: php ".basename(__FILE__).
" SYSTEM_ROOT [test|recover] [TREE_ID]\n\n";
475 echo
"\tSYSTEM_ROOT: The root directory of Matrix system.\n";
476 echo
"\tRunning direction: test (default) - show which assets have their file version integrity broken | recover - fix the broken integrity showed by test option\n";
477 echo
"\tTREE_ID: The asset id of the root of the asset tree. If not specified, all file assets in the system will be used.\n";
478 echo
"\nNOTES: YOU SHOULD BACKUP YOUR SYSTEM BEFORE USING THE recover (in lowercase) OPTION OF THIS SCRIPT\n\n";