2013-05-02 10:10:42 +00:00
< ? php
/**
* Implementation of an extension management .
*
* SeedDMS can be extended by extensions . Extension usually implement
* hook .
*
* @ category DMS
* @ package SeedDMS
* @ license GPL 2
* @ version @ version @
* @ author Uwe Steinmann < uwe @ steinmann . cx >
* @ copyright 2011 Uwe Steinmann
* @ version Release : @ package_version @
*/
/**
* Class to represent an extension manager
*
* This class provides some very basic methods to manage extensions .
*
* @ category DMS
* @ package SeedDMS
* @ author Markus Westphal , Malcolm Cowe , Uwe Steinmann < uwe @ steinmann . cx >
* @ copyright 2011 Uwe Steinmann
* @ version Release : @ package_version @
*/
class SeedDMS_Extension_Mgr {
/**
* @ var string $extdir directory where extensions are located
* @ access protected
*/
protected $extdir ;
2018-03-13 13:37:55 +00:00
/**
* @ var array [] $extconf configuration of all extensions
* @ access protected
*/
protected $extconf ;
2013-05-02 10:10:42 +00:00
/**
* @ var string $cachedir directory where cached extension configuration
* is stored
* @ access protected
*/
protected $cachedir ;
2018-03-13 13:37:55 +00:00
/**
* @ var string [] $errmsg list of error message from last operation
* @ access protected
*/
protected $errmsgs ;
/**
* Compare two version
*
* This functions compares two version in the format x . x . x
*
* @ param string $ver1
* @ param string $ver2
* @ return int - 1 if $ver1 < $ver2 , 0 if $ver1 == $ver2 , 1 if $ver1 > $ver2
*/
static public function cmpVersion ( $ver1 , $ver2 ) { /* {{{ */
$tmp1 = explode ( '.' , $ver1 );
$tmp2 = explode ( '.' , $ver2 );
if ( intval ( $tmp1 [ 0 ]) < intval ( $tmp2 [ 0 ])) {
return - 1 ;
} elseif ( intval ( $tmp1 [ 0 ]) > intval ( $tmp2 [ 0 ])) {
return 1 ;
} else {
if ( intval ( $tmp1 [ 1 ]) < intval ( $tmp2 [ 1 ])) {
return - 1 ;
} elseif ( intval ( $tmp1 [ 1 ]) > intval ( $tmp2 [ 1 ])) {
return 1 ;
} else {
if ( intval ( $tmp1 [ 2 ]) < intval ( $tmp2 [ 2 ])) {
return - 1 ;
} elseif ( intval ( $tmp1 [ 2 ]) > intval ( $tmp2 [ 2 ])) {
return 1 ;
} else {
return 0 ;
}
}
}
} /* }}} */
2013-05-02 10:10:42 +00:00
2018-03-13 13:37:55 +00:00
/**
* Constructor of extension manager
*
* Reads the configuration of all extensions and creates the
* configuration file if it does not exist and the extension dir
* is given
*/
public function __construct ( $extdir = '' , $cachedir = '' ) {
2013-05-02 10:10:42 +00:00
$this -> cachedir = $cachedir ;
$this -> extdir = $extdir ;
2018-03-13 13:37:55 +00:00
$this -> extconf = array ();
if ( $extdir ) {
if ( ! file_exists ( $this -> getExtensionsConfFile ())) {
$this -> createExtensionConf ();
}
include ( $this -> getExtensionsConfFile ());
if ( $EXT_CONF ) {
$this -> extconf = $EXT_CONF ;
}
}
2013-05-02 10:10:42 +00:00
}
2018-03-13 13:37:55 +00:00
protected function getExtensionsConfFile () { /* {{{ */
2013-05-02 10:10:42 +00:00
return $this -> cachedir . " /extensions.php " ;
} /* }}} */
2018-03-13 13:37:55 +00:00
/**
* Get the configuration of extensions
*
* @ return array []
*/
public function getExtensionConfiguration () { /* {{{ */
return $this -> extconf ;
} /* }}} */
2014-11-13 12:56:13 +00:00
/**
* Create the cached file containing extension information
*
* This function will always create a file , even if no extensions
* are installed .
*/
2018-03-13 13:37:55 +00:00
public function createExtensionConf () { /* {{{ */
2013-05-02 10:10:42 +00:00
$extensions = self :: getExtensions ();
2018-03-13 13:37:55 +00:00
$fp = @ fopen ( self :: getExtensionsConfFile (), " w " );
2015-04-16 06:03:23 +00:00
if ( $fp ) {
if ( $extensions ) {
foreach ( $extensions as $_ext ) {
if ( file_exists ( $this -> extdir . " / " . $_ext . " /conf.php " )) {
$content = file_get_contents ( $this -> extdir . " / " . $_ext . " /conf.php " );
fwrite ( $fp , $content );
}
2013-05-02 10:10:42 +00:00
}
}
2015-04-16 06:03:23 +00:00
fclose ( $fp );
return true ;
} else {
return false ;
2013-05-02 10:10:42 +00:00
}
} /* }}} */
2018-03-13 13:37:55 +00:00
protected function getExtensions () { /* {{{ */
2013-05-02 10:10:42 +00:00
$extensions = array ();
2015-05-04 05:14:24 +00:00
if ( file_exists ( $this -> extdir )) {
$handle = opendir ( $this -> extdir );
while ( $entry = readdir ( $handle ) ) {
if ( $entry == " .. " || $entry == " . " )
continue ;
else if ( is_dir ( $this -> extdir . " / " . $entry ))
array_push ( $extensions , $entry );
}
closedir ( $handle );
2013-05-02 10:10:42 +00:00
2015-05-04 05:14:24 +00:00
asort ( $extensions );
}
2013-05-02 10:10:42 +00:00
return $extensions ;
} /* }}} */
2018-03-12 17:33:30 +00:00
public function createArchive ( $extname , $version ) { /* {{{ */
if ( ! is_dir ( $this -> extdir . " / " . $extname ))
return false ;
$tmpfile = $this -> cachedir . " / " . $extname . " - " . $version . " .zip " ;
$cmd = " cd " . $this -> extdir . " / " . $extname . " ; zip -r " . $tmpfile . " . " ;
exec ( $cmd );
return $tmpfile ;
} /* }}} */
2018-03-13 13:37:55 +00:00
/**
* Check content of extension directory
*
* @ param string $dir full path to extension directory or extension name
* @ param boolean $noconstraints set to true if constraints to local seeddms
* installation shall not be checked .
*/
public function checkExtension ( $dir , $noconstraints = false ) { /* {{{ */
$this -> errmsgs = array ();
if ( ! file_exists ( $dir )) {
if ( ! file_exists ( $this -> extdir . '/' . $dir ))
return false ;
else
$dir = $this -> extdir . '/' . $dir ;
}
if ( ! file_exists ( $dir . " /conf.php " )) {
$this -> errmsgs [] = " Missing extension configuration " ;
return false ;
}
include ( $dir . " /conf.php " );
if ( ! isset ( $EXT_CONF )) {
$this -> errmsgs [] = " Missing \$ EXT_CONF in configuration " ;
return false ;
}
$extname = key ( $EXT_CONF );
if ( ! $extname || ! preg_match ( '/[a-zA-Z_]*/' , $extname )) {
return false ;
}
$extconf = $EXT_CONF [ $extname ];
if ( ! isset ( $extconf [ 'constraints' ][ 'depends' ][ 'seeddms' ])) {
$this -> errmsgs [] = " Missing dependency on SeedDMS " ;
}
if ( ! isset ( $extconf [ 'constraints' ][ 'depends' ][ 'php' ])) {
$this -> errmsgs [] = " Missing dependency on PHP " ;
}
if ( ! isset ( $extconf [ 'version' ])) {
$this -> errmsgs [] = " Missing version information " ;
}
if ( ! isset ( $extconf [ 'title' ])) {
$this -> errmsgs [] = " Missing title " ;
}
if ( ! isset ( $extconf [ 'author' ])) {
$this -> errmsgs [] = " Missing author " ;
}
if ( ! empty ( $extconf [ 'language' ][ 'file' ]) && ! file_exists ( $dir . " / " . $extconf [ 'language' ][ 'file' ])) {
$this -> errmsgs [] = " Missing language file " ;
}
if ( ! empty ( $extconf [ 'class' ][ 'file' ]) && ! file_exists ( $dir . " / " . $extconf [ 'class' ][ 'file' ])) {
$this -> errmsgs [] = " Missing class file " ;
}
if ( ! $noconstraints && isset ( $extconf [ 'constraints' ][ 'depends' ])) {
foreach ( $extconf [ 'constraints' ][ 'depends' ] as $dkey => $dval ) {
switch ( $dkey ) {
case 'seeddms' :
$version = new SeedDMS_Version ;
$tmp = explode ( '-' , $dval , 2 );
if ( self :: cmpVersion ( $tmp [ 0 ], $version -> version ()) > 0 || ( $tmp [ 1 ] && self :: cmpVersion ( $tmp [ 1 ], $version -> version ()) < 0 ))
$this -> errmsgs [] = sprintf ( " Incorrect SeedDMS version (needs version %s) " , $extconf [ 'constraints' ][ 'depends' ][ 'seeddms' ]);
break ;
case 'php' :
$tmp = explode ( '-' , $dval , 2 );
if ( self :: cmpVersion ( $tmp [ 0 ], phpversion ()) > 0 || ( $tmp [ 1 ] && self :: cmpVersion ( $tmp [ 1 ], phpversion ()) < 0 ))
$this -> errmsgs [] = sprintf ( " Incorrect PHP version (needs version %s) " , $extconf [ 'constraints' ][ 'depends' ][ 'php' ]);
break ;
default :
$tmp = explode ( '-' , $dval , 2 );
if ( isset ( $GLOBALS [ 'EXT_CONF' ][ $dkey ][ 'version' ])) {
if ( self :: cmpVersion ( $tmp [ 0 ], $GLOBALS [ 'EXT_CONF' ][ $dkey ][ 'version' ]) > 0 || ( $tmp [ 1 ] && self :: cmpVersion ( $tmp [ 1 ], $GLOBALS [ 'EXT_CONF' ][ $dkey ][ 'version' ]) < 0 ))
$this -> errmsgs [] = sprintf ( " Incorrect version of extension '%s' (needs version '%s' but provides '%s') " , $dkey , $dval , $GLOBALS [ 'EXT_CONF' ][ $dkey ][ 'version' ]);
} else {
$this -> errmsgs [] = sprintf ( " Missing extension or version for '%s' " , $dkey );
}
break ;
}
}
}
if ( $this -> errmsgs )
return false ;
return true ;
} /* }}} */
2018-03-12 17:33:30 +00:00
static protected function rrmdir ( $dir ) { /* {{{ */
if ( is_dir ( $dir )) {
$objects = scandir ( $dir );
foreach ( $objects as $object ) {
if ( $object != " . " && $object != " .. " ) {
if ( filetype ( $dir . " / " . $object ) == " dir " ) self :: rrmdir ( $dir . " / " . $object ); else unlink ( $dir . " / " . $object );
}
}
reset ( $objects );
rmdir ( $dir );
}
} /* }}} */
2018-03-13 13:37:55 +00:00
/**
* Update an extension
*
* This function will replace an existing extension or add a new extension
* The passed file has to be zipped content of the extension directory not
* including the directory itself .
*
* @ param string $file name of extension archive
* @ return boolean true on success , othewise false
*/
2018-03-12 17:33:30 +00:00
public function updateExtension ( $file ) { /* {{{ */
$newdir = $this -> cachedir . " /ext.new " ;
if ( ! mkdir ( $newdir , 0755 )) {
2018-03-13 13:37:55 +00:00
$this -> errmsgs [] = " Cannot create temp. extension directory " ;
2018-03-12 17:33:30 +00:00
return false ;
}
$cmd = " cd " . $newdir . " ; unzip " . $file ;
exec ( $cmd );
2018-03-13 13:37:55 +00:00
if ( ! self :: checkExtension ( $newdir )) {
2018-03-12 17:33:30 +00:00
self :: rrmdir ( $newdir );
return false ;
}
include ( $newdir . " /conf.php " );
$extname = key ( $EXT_CONF );
2018-03-13 13:37:55 +00:00
/* Create the target directory */
2018-03-12 17:33:30 +00:00
if ( ! is_dir ( $this -> extdir )) {
if ( ! mkdir ( $this -> extdir , 0755 )) {
2018-03-13 13:37:55 +00:00
$this -> errmsgs [] = " Cannot create extension directory " ;
2018-03-12 17:33:30 +00:00
self :: rrmdir ( $newdir );
return false ;
}
} elseif ( is_dir ( $this -> extdir . " / " . $extname )) {
$this -> rrmdir ( $this -> extdir . " / " . $extname );
}
2018-03-13 13:37:55 +00:00
/* Move the temp. created ext directory to the final location */
2018-03-12 17:33:30 +00:00
rename ( $newdir , $this -> extdir . " / " . $extname );
return true ;
} /* }}} */
2018-03-13 13:37:55 +00:00
/**
* Import list of extension from repository
*
*/
public function importExtensionList ( $url ) { /* {{{ */
$file = file_get_contents ( $url . " /repository.json " );
file_put_contents ( $this -> cachedir . " /repository.json " , $file );
return file ( $this -> cachedir . " /repository.json " );
} /* }}} */
/**
* Return last error message
*
* @ return string
*/
public function getErrorMsg () { /* {{{ */
if ( $this -> errmsgs )
return $this -> errmsgs [ 0 ];
else
return '' ;
} /* }}} */
/**
* Return all error messages
*
* @ return string []
*/
public function getErrorMsgs () { /* {{{ */
return $this -> errmsgs ;
} /* }}} */
2013-05-02 10:10:42 +00:00
}