/branches/v1.3-critias/bibliotheque/pear/Auth/Container/RADIUS.php |
---|
New file |
0,0 → 1,154 |
<?php |
// |
// +----------------------------------------------------------------------+ |
// | PHP Version 4 | |
// +----------------------------------------------------------------------+ |
// | Copyright (c) 1997-2003 The PHP Group | |
// +----------------------------------------------------------------------+ |
// | This source file is subject to version 2.02 of the PHP license, | |
// | that is bundled with this package in the file LICENSE, and is | |
// | available at through the world-wide-web at | |
// | http://www.php.net/license/2_02.txt. | |
// | If you did not receive a copy of the PHP license and are unable to | |
// | obtain it through the world-wide-web, please send a note to | |
// | license@php.net so we can mail you a copy immediately. | |
// +----------------------------------------------------------------------+ |
// | Authors: Michael Bretterklieber <michael@bretterklieber.com> | |
// +----------------------------------------------------------------------+ |
// |
// $Id: RADIUS.php,v 1.7 2003/05/13 19:27:35 mbretter Exp $ |
// |
require_once "Auth/Container.php"; |
require_once "Auth/RADIUS.php"; |
/** |
* Storage driver for authenticating users against RADIUS servers. |
* |
* @author Michael Bretterklieber <michael@bretterklieber.com> |
* @access public |
* @version $Revision: 1.7 $ |
*/ |
class Auth_Container_RADIUS extends Auth_Container |
{ |
/** |
* Contains a RADIUS object |
* @var object |
*/ |
var $radius; |
/** |
* Contains the authentication type |
* @var string |
*/ |
var $authtype; |
/** |
* Constructor of the container class. |
* |
* $options can have these keys: |
* 'servers' an array containing an array: servername, port, |
* sharedsecret, timeout, maxtries |
* 'configfile' The filename of the configuration file |
* 'authtype' The type of authentication, one of: PAP, CHAP_MD5, |
* MSCHAPv1, MSCHAPv2, default is PAP |
* |
* @param $options associative array |
* @return object Returns an error object if something went wrong |
*/ |
function Auth_Container_RADIUS($options) |
{ |
$this->authtype = 'PAP'; |
if (isset($options['authtype'])) { |
$this->authtype = $options['authtype']; |
} |
$classname = 'Auth_RADIUS_' . $this->authtype; |
if (!class_exists($classname)) { |
PEAR::raiseError("Unknown Authtype, please use on of: PAP, CHAP_MD5, MSCHAPv1, MSCHAPv2!", |
41, PEAR_ERROR_DIE); |
} |
$this->radius = new $classname; |
if (isset($options['configfile'])) { |
$this->radius->setConfigfile($options['configfile']); |
} |
$servers = $options['servers']; |
if (is_array($servers)) { |
foreach ($servers as $server) { |
$servername = $server[0]; |
$port = isset($server[1]) ? $server[1] : 0; |
$sharedsecret = isset($server[2]) ? $server[2] : 'testing123'; |
$timeout = isset($server[3]) ? $server[3] : 3; |
$maxtries = isset($server[4]) ? $server[4] : 3; |
$this->radius->addServer($servername, $port, $sharedsecret, $timeout, $maxtries); |
} |
} |
if (!$this->radius->start()) { |
PEAR::raiseError($this->radius->getError(), 41, PEAR_ERROR_DIE); |
} |
} |
/** |
* Authenticate |
* |
* @param string Username |
* @param string Password |
* @return bool true on success, false on reject |
*/ |
function fetchData($username, $password, $challenge = null) |
{ |
switch($this->authtype) { |
case 'CHAP_MD5': |
case 'MSCHAPv1': |
if (isset($challenge)) { |
echo $password; |
$this->radius->challenge = $challenge; |
$this->radius->chapid = 1; |
$this->radius->response = pack('H*', $password); |
} else { |
require_once 'Crypt_CHAP/CHAP.php'; |
$classname = 'Crypt_' . $this->authtype; |
$crpt = new $classname; |
$crpt->password = $password; |
$this->radius->challenge = $crpt->challenge; |
$this->radius->chapid = $crpt->chapid; |
$this->radius->response = $crpt->challengeResponse(); |
break; |
} |
case 'MSCHAPv2': |
require_once 'Crypt_CHAP/CHAP.php'; |
$crpt = new Crypt_MSCHAPv2; |
$crpt->username = $username; |
$crpt->password = $password; |
$this->radius->challenge = $crpt->authChallenge; |
$this->radius->peerChallenge = $crpt->peerChallenge; |
$this->radius->chapid = $crpt->chapid; |
$this->radius->response = $crpt->challengeResponse(); |
break; |
default: |
$this->radius->password = $password; |
break; |
} |
$this->radius->username = $username; |
$this->radius->putAuthAttributes(); |
$result = $this->radius->send(); |
if (PEAR::isError($result)) { |
return false; |
} |
$this->radius->getAttributes(); |
// just for debugging |
// $this->radius->dumpAttributes(); |
return $result; |
} |
} |
?> |
/branches/v1.3-critias/bibliotheque/pear/Auth/Container/vpopmail.php |
---|
New file |
0,0 → 1,66 |
<?PHP |
/* vim: set expandtab tabstop=4 shiftwidth=4: */ |
// +----------------------------------------------------------------------+ |
// | PHP Version 4 | |
// +----------------------------------------------------------------------+ |
// | Copyright (c) 1997-2003 The PHP Group | |
// +----------------------------------------------------------------------+ |
// | This source file is subject to version 2.02 of the PHP license, | |
// | that is bundled with this package in the file LICENSE, and is | |
// | available at through the world-wide-web at | |
// | http://www.php.net/license/2_02.txt. | |
// | If you did not receive a copy of the PHP license and are unable to | |
// | obtain it through the world-wide-web, please send a note to | |
// | license@php.net so we can mail you a copy immediately. | |
// +----------------------------------------------------------------------+ |
// | Author: Stanislav Grozev <tacho@orbitel.bg> | |
// +----------------------------------------------------------------------+ |
// |
// $Id: vpopmail.php,v 1.3 2003/09/08 11:24:05 yavo Exp $ |
// |
require_once "Auth/Container.php"; |
/** |
* Storage driver for fetching login data from vpopmail |
* |
* @author Stanislav Grozev <tacho@orbitel.bg> |
* @package Auth |
* @version $Revision: 1.3 $ |
*/ |
class Auth_Container_vpopmail extends Auth_Container { |
// {{{ Constructor |
/** |
* Constructor of the container class |
* |
* @return integer Always returns 1. |
*/ |
function Auth_Container_vpopmail() |
{ |
return 1; |
} |
// }}} |
// {{{ fetchData() |
/** |
* Get user information from vpopmail |
* |
* @param string Username - has to be valid email address |
* @param string Password |
* @return boolean |
*/ |
function fetchData($username, $password) |
{ |
$userdata = array(); |
$userdata = preg_split("/@/", $username, 2); |
$result = @vpopmail_auth_user($userdata[0], $userdata[1], $password); |
return $result; |
} |
// }}} |
} |
?> |
/branches/v1.3-critias/bibliotheque/pear/Auth/Container/File.php |
---|
New file |
0,0 → 1,200 |
<?php |
/* vim: set expandtab tabstop=4 shiftwidth=4: */ |
// +----------------------------------------------------------------------+ |
// | PHP Version 4 | |
// +----------------------------------------------------------------------+ |
// | Copyright (c) 1997-2003 The PHP Group | |
// +----------------------------------------------------------------------+ |
// | This source file is subject to version 2.02 of the PHP license, | |
// | that is bundled with this package in the file LICENSE, and is | |
// | available at through the world-wide-web at | |
// | http://www.php.net/license/2_02.txt. | |
// | If you did not receive a copy of the PHP license and are unable to | |
// | obtain it through the world-wide-web, please send a note to | |
// | license@php.net so we can mail you a copy immediately. | |
// +----------------------------------------------------------------------+ |
// | Authors: Stefan Ekman <stekman@sedata.org> | |
// | Martin Jansen <mj@php.net> | |
// | Mika Tuupola <tuupola@appelsiini.net> | |
// +----------------------------------------------------------------------+ |
// |
// $Id: File.php,v 1.14 2003/10/29 13:42:40 mike Exp $ |
// |
require_once "File/Passwd.php"; |
require_once "Auth/Container.php"; |
require_once "PEAR.php"; |
/** |
* Storage driver for fetching login data from an encrypted password file. |
* |
* This storage container can handle CVS pserver style passwd files. |
* |
* @author Stefan Ekman <stekman@sedata.org> |
* @author Michael Wallner <mike@php.net> |
* @package Auth |
* @version $Revision: 1.14 $ |
*/ |
class Auth_Container_File extends Auth_Container |
{ |
/** |
* Path to passwd file |
* |
* @var string |
*/ |
var $pwfile = ''; |
// {{{ Constructor |
/** |
* Constructor of the container class |
* |
* @param string $filename path to passwd file |
* @return object Auth_Container_File new Auth_Container_File object |
*/ |
function Auth_Container_File($filename) |
{ |
$this->pwfile = $filename; |
} |
// }}} |
// {{{ fetchData() |
/** |
* Authenticate an user |
* |
* @param string username |
* @param string password |
* @return mixed boolean|PEAR_Error |
*/ |
function fetchData($user, $pass) |
{ |
return File_Passwd::staticAuth('Cvs', $this->pwfile, $user, $pass); |
} |
// }}} |
// {{{ listUsers() |
/** |
* List all available users |
* |
* @return array |
*/ |
function listUsers() |
{ |
$pw_obj = &$this->_load(); |
if (PEAR::isError($pw_obj)) { |
return array(); |
} |
$users = $pw_obj->listUser(); |
if (!is_array($users)) { |
return array(); |
} |
foreach ($users as $key => $value) { |
$retVal[] = array("username" => $key, |
"password" => $value['passwd'], |
"cvsuser" => $value['system']); |
} |
return $retVal; |
} |
// }}} |
// {{{ addUser() |
/** |
* Add a new user to the storage container |
* |
* @param string username |
* @param string password |
* @param mixed CVS username |
* |
* @return boolean |
*/ |
function addUser($user, $pass, $additional='') |
{ |
$cvs = (string) (is_array($additional) && isset($additional['cvsuser'])) ? |
$additional['cvsuser'] : $additional; |
$pw_obj = &$this->_load(); |
if (PEAR::isError($pw_obj)) { |
return false; |
} |
$res = $pw_obj->addUser($user, $pass, $cvs); |
if(PEAR::isError($res)){ |
return false; |
} |
$res = $pw_obj->save(); |
if (PEAR::isError($res)) { |
return false; |
} |
return true; |
} |
// }}} |
// {{{ removeUser() |
/** |
* Remove user from the storage container |
* |
* @param string Username |
* @return boolean |
*/ |
function removeUser($user) |
{ |
$pw_obj = &$this->_load(); |
if (PEAR::isError($pw_obj)) { |
return false; |
} |
$res = $pw_obj->delUser($user); |
if(PEAR::isError($res)){ |
return false; |
} |
$res = $pw_obj->save(); |
if (PEAR::isError($res)) { |
return false; |
} |
return true; |
} |
// }}} |
// {{{ _load() |
/** |
* Load and initialize the File_Passwd object |
* |
* @return object File_Passwd_Cvs|PEAR_Error |
*/ |
function &_load() |
{ |
static $pw_obj; |
if (!isset($pw_obj)) { |
$pw_obj = File_Passwd::factory('Cvs'); |
if (PEAR::isError($pw_obj)) { |
return $pw_obj; |
} |
$pw_obj->setFile($this->pwfile); |
$res = $pw_obj->load(); |
if (PEAR::isError($res)) { |
return $res; |
} |
} |
return $pw_obj; |
} |
// }}} |
} |
?> |
/branches/v1.3-critias/bibliotheque/pear/Auth/Container/LDAP.php |
---|
New file |
0,0 → 1,472 |
<?php |
// |
// +----------------------------------------------------------------------+ |
// | PHP Version 4 | |
// +----------------------------------------------------------------------+ |
// | Copyright (c) 1997-2003 The PHP Group | |
// +----------------------------------------------------------------------+ |
// | This source file is subject to version 2.02 of the PHP license, | |
// | that is bundled with this package in the file LICENSE, and is | |
// | available at through the world-wide-web at | |
// | http://www.php.net/license/2_02.txt. | |
// | If you did not receive a copy of the PHP license and are unable to | |
// | obtain it through the world-wide-web, please send a note to | |
// | license@php.net so we can mail you a copy immediately. | |
// +----------------------------------------------------------------------+ |
// | Authors: Jan Wagner <wagner@netsols.de> | |
// +----------------------------------------------------------------------+ |
// |
// $Id: LDAP.php,v 1.14 2003/06/02 16:55:10 mj Exp $ |
// |
require_once "Auth/Container.php"; |
require_once "PEAR.php"; |
/** |
* Storage driver for fetching login data from LDAP |
* |
* This class is heavily based on the DB and File containers. By default it |
* connects to localhost:389 and searches for uid=$username with the scope |
* "sub". If no search base is specified, it will try to determine it via |
* the namingContexts attribute. It takes its parameters in a hash, connects |
* to the ldap server, binds anonymously, searches for the user, and tries |
* to bind as the user with the supplied password. When a group was set, it |
* will look for group membership of the authenticated user. If all goes |
* well the authentication was successful. |
* |
* Parameters: |
* |
* host: localhost (default), ldap.netsols.de or 127.0.0.1 |
* port: 389 (default) or 636 or whereever your server runs |
* url: ldap://localhost:389/ |
* useful for ldaps://, works only with openldap2 ? |
* it will be preferred over host and port |
* binddn: If set, searching for user will be done after binding |
* as this user, if not set the bind will be anonymous. |
* This is reported to make the container work with MS |
* Active Directory, but should work with any server that |
* is configured this way. |
* This has to be a complete dn for now (basedn and |
* userdn will not be appended). |
* bindpw: The password to use for binding with binddn |
* scope: one, sub (default), or base |
* basedn: the base dn of your server |
* userdn: gets prepended to basedn when searching for user |
* userattr: the user attribute to search for (default: uid) |
* useroc: objectclass of user (for the search filter) |
* (default: posixAccount) |
* groupdn: gets prepended to basedn when searching for group |
* groupattr : the group attribute to search for (default: cn) |
* groupoc : objectclass of group (for the search filter) |
* (default: groupOfUniqueNames) |
* memberattr : the attribute of the group object where the user dn |
* may be found (default: uniqueMember) |
* memberisdn: whether the memberattr is the dn of the user (default) |
* or the value of userattr (usually uid) |
* group: the name of group to search for |
* debug: Enable/Disable debugging output (default: false) |
* |
* To use this storage container, you have to use the following syntax: |
* |
* <?php |
* ... |
* |
* $a = new Auth("LDAP", array( |
* 'host' => 'localhost', |
* 'port' => '389', |
* 'basedn' => 'o=netsols,c=de', |
* 'userattr' => 'uid' |
* 'binddn' => 'cn=admin,o=netsols,c=de', |
* 'bindpw' => 'password')); |
* |
* $a2 = new Auth('LDAP', array( |
* 'url' => 'ldaps://ldap.netsols.de', |
* 'basedn' => 'o=netsols,c=de', |
* 'scope' => 'one', |
* 'userdn' => 'ou=People', |
* 'groupdn' => 'ou=Groups', |
* 'groupoc' => 'posixGroup', |
* 'memberattr' => 'memberUid', |
* 'memberisdn' => false, |
* 'group' => 'admin' |
* )); |
* |
* $a3 = new Auth('LDAP', array( |
* 'host' => 'ad.netsols.de', |
* 'basedn' => 'dc=netsols,dc=de', |
* 'userdn' => 'ou=Users', |
* 'binddn' => 'cn=Jan Wagner,ou=Users,dc=netsols,dc=de', |
* 'bindpw' => '*******', |
* 'userattr' => 'samAccountName', |
* 'useroc' => 'user', |
* 'debug' => true |
* )); |
* |
* The parameter values have to correspond |
* to the ones for your LDAP server of course. |
* |
* When talking to a Microsoft ActiveDirectory server you have to |
* use 'samaccountname' as the 'userattr' and follow special rules |
* to translate the ActiveDirectory directory names into 'basedn'. |
* The 'basedn' for the default 'Users' folder on an ActiveDirectory |
* server for the ActiveDirectory Domain (which is not related to |
* its DNS name) "win2000.example.org" would be: |
* "CN=Users, DC=win2000, DC=example, DC=org' |
* where every component of the domain name becomes a DC attribute |
* of its own. If you want to use a custom users folder you have to |
* replace "CN=Users" with a sequence of "OU" attributes that specify |
* the path to your custom folder in reverse order. |
* So the ActiveDirectory folder |
* "win2000.example.org\Custom\Accounts" |
* would become |
* "OU=Accounts, OU=Custom, DC=win2000, DC=example, DC=org' |
* |
* It seems that binding anonymously to an Active Directory |
* is not allowed, so you have to set binddn and bindpw for |
* user searching, |
* |
* Example a3 shows a tested example for connenction to Windows 2000 |
* Active Directory |
* |
* @author Jan Wagner <wagner@netsols.de> |
* @package Auth |
* @version $Revision: 1.14 $ |
*/ |
class Auth_Container_LDAP extends Auth_Container |
{ |
/** |
* Options for the class |
* @var array |
*/ |
var $options = array(); |
/** |
* Connection ID of LDAP Link |
* @var string |
*/ |
var $conn_id = false; |
/** |
* LDAP search function to use |
* @var string |
*/ |
var $ldap_search_func; |
/** |
* Constructor of the container class |
* |
* @param $params, associative hash with host,port,basedn and userattr key |
* @return object Returns an error object if something went wrong |
*/ |
function Auth_Container_LDAP($params) |
{ |
$this->_setDefaults(); |
if (is_array($params)) { |
$this->_parseOptions($params); |
} |
} |
// }}} |
// {{{ _connect() |
/** |
* Connect to the LDAP server using the global options |
* |
* @access private |
* @return object Returns a PEAR error object if an error occurs. |
*/ |
function _connect() |
{ |
// connect |
if (isset($this->options['url']) && $this->options['url'] != '') { |
$this->_debug('Connecting with URL', __LINE__); |
$conn_params = array($this->options['url']); |
} else { |
$this->_debug('Connecting with host:port', __LINE__); |
$conn_params = array($this->options['host'], $this->options['port']); |
} |
if(($this->conn_id = @call_user_func_array('ldap_connect', $conn_params)) === false) { |
return PEAR::raiseError('Auth_Container_LDAP: Could not connect to server.', 41, PEAR_ERROR_DIE); |
} |
$this->_debug('Successfully connected to server', __LINE__); |
// try switchig to LDAPv3 |
$ver = 0; |
if(@ldap_get_option($this->conn_id, LDAP_OPT_PROTOCOL_VERSION, $ver) && $ver >= 2) { |
$this->_debug('Switching to LDAPv3', __LINE__); |
@ldap_set_option($this->conn_id, LDAP_OPT_PROTOCOL_VERSION, 3); |
} |
// bind with credentials or anonymously |
if($this->options['binddn'] && $this->options['bindpw']) { |
$this->_debug('Binding with credentials', __LINE__); |
$bind_params = array($this->conn_id, $this->options['binddn'], $this->options['bindpw']); |
} else { |
$this->_debug('Binding anonymously', __LINE__); |
$bind_params = array($this->conn_id); |
} |
// bind for searching |
if ((@call_user_func_array('ldap_bind', $bind_params)) == false) { |
$this->_debug(); |
$this->_disconnect(); |
return PEAR::raiseError("Auth_Container_LDAP: Could not bind to LDAP server.", 41, PEAR_ERROR_DIE); |
} |
$this->_debug('Binding was successful', __LINE__); |
} |
/** |
* Disconnects (unbinds) from ldap server |
* |
* @access private |
*/ |
function _disconnect() |
{ |
if($this->_isValidLink()) { |
$this->_debug('disconnecting from server'); |
@ldap_unbind($this->conn_id); |
} |
} |
/** |
* Tries to find Basedn via namingContext Attribute |
* |
* @access private |
*/ |
function _getBaseDN() |
{ |
if ($this->options['basedn'] == "" && $this->_isValidLink()) { |
$this->_debug("basedn not set, searching via namingContexts.", __LINE__); |
$result_id = @ldap_read($this->conn_id, "", "(objectclass=*)", array("namingContexts")); |
if (ldap_count_entries($this->conn_id, $result_id) == 1) { |
$this->_debug("got result for namingContexts", __LINE__); |
$entry_id = ldap_first_entry($this->conn_id, $result_id); |
$attrs = ldap_get_attributes($this->conn_id, $entry_id); |
$basedn = $attrs['namingContexts'][0]; |
if ($basedn != "") { |
$this->_debug("result for namingContexts was $basedn", __LINE__); |
$this->options['basedn'] = $basedn; |
} |
} |
ldap_free_result($result_id); |
} |
// if base ist still not set, raise error |
if ($this->options['basedn'] == "") { |
return PEAR::raiseError("Auth_Container_LDAP: LDAP search base not specified!", 41, PEAR_ERROR_DIE); |
} |
return true; |
} |
/** |
* determines whether there is a valid ldap conenction or not |
* |
* @accessd private |
* @return boolean |
*/ |
function _isValidLink() |
{ |
if(is_resource($this->conn_id)) { |
if(get_resource_type($this->conn_id) == 'ldap link') { |
return true; |
} |
} |
return false; |
} |
/** |
* Set some default options |
* |
* @access private |
*/ |
function _setDefaults() |
{ |
$this->options['host'] = 'localhost'; |
$this->options['port'] = '389'; |
$this->options['binddn'] = ''; |
$this->options['bindpw'] = ''; |
$this->options['scope'] = 'sub'; |
$this->options['basedn'] = ''; |
$this->options['userdn'] = ''; |
$this->options['userattr'] = "uid"; |
$this->options['useroc'] = 'posixAccount'; |
$this->options['groupdn'] = ''; |
$this->options['groupattr'] = 'cn'; |
$this->options['groupoc'] = 'groupOfUniqueNames'; |
$this->options['memberattr'] = 'uniqueMember'; |
$this->options['memberisdn'] = true; |
$this->options['debug'] = false; |
} |
/** |
* Parse options passed to the container class |
* |
* @access private |
* @param array |
*/ |
function _parseOptions($array) |
{ |
foreach ($array as $key => $value) { |
$this->options[$key] = $value; |
} |
// get the according search function for selected scope |
switch($this->options['scope']) { |
case 'one': |
$this->ldap_search_func = 'ldap_list'; |
break; |
case 'base': |
$this->ldap_search_func = 'ldap_read'; |
break; |
default: |
$this->ldap_search_func = 'ldap_search'; |
break; |
} |
$this->_debug("LDAP search function will be: {$this->ldap_search_func}", __LINE__); |
} |
/** |
* Fetch data from LDAP server |
* |
* Searches the LDAP server for the given username/password |
* combination. |
* |
* @param string Username |
* @param string Password |
* @return boolean |
*/ |
function fetchData($username, $password) |
{ |
$this->_connect(); |
$this->_getBaseDN(); |
// make search filter |
$filter = sprintf('(&(objectClass=%s)(%s=%s))', $this->options['useroc'], $this->options['userattr'], $username); |
// make search base dn |
$search_basedn = $this->options['userdn']; |
if ($search_basedn != '' && substr($search_basedn, -1) != ',') { |
$search_basedn .= ','; |
} |
$search_basedn .= $this->options['basedn']; |
// make functions params array |
$func_params = array($this->conn_id, $search_basedn, $filter, array($this->options['userattr'])); |
$this->_debug("Searching with $filter in $search_basedn", __LINE__); |
// search |
if (($result_id = @call_user_func_array($this->ldap_search_func, $func_params)) == false) { |
$this->_debug('User not found', __LINE__); |
} elseif (ldap_count_entries($this->conn_id, $result_id) == 1) { // did we get just one entry? |
$this->_debug('User was found', __LINE__); |
// then get the user dn |
$entry_id = ldap_first_entry($this->conn_id, $result_id); |
$user_dn = ldap_get_dn($this->conn_id, $entry_id); |
ldap_free_result($result_id); |
// need to catch an empty password as openldap seems to return TRUE |
// if anonymous binding is allowed |
if ($password != "") { |
$this->_debug("Bind as $user_dn", __LINE__); |
// try binding as this user with the supplied password |
if (@ldap_bind($this->conn_id, $user_dn, $password)) { |
$this->_debug('Bind successful', __LINE__); |
// check group if appropiate |
if(isset($this->options['group'])) { |
// decide whether memberattr value is a dn or the username |
$this->_debug('Checking group membership', __LINE__); |
return $this->checkGroup(($this->options['memberisdn']) ? $user_dn : $username); |
} else { |
$this->_debug('Authenticated', __LINE__); |
$this->_disconnect(); |
return true; // user authenticated |
} // checkGroup |
} // bind |
} // non-empty password |
} // one entry |
// default |
$this->_debug('NOT authenticated!', __LINE__); |
$this->_disconnect(); |
return false; |
} |
/** |
* Validate group membership |
* |
* Searches the LDAP server for group membership of the |
* authenticated user |
* |
* @param string Distinguished Name of the authenticated User |
* @return boolean |
*/ |
function checkGroup($user) |
{ |
// make filter |
$filter = sprintf('(&(%s=%s)(objectClass=%s)(%s=%s))', |
$this->options['groupattr'], |
$this->options['group'], |
$this->options['groupoc'], |
$this->options['memberattr'], |
$user |
); |
// make search base dn |
$search_basedn = $this->options['groupdn']; |
if($search_basedn != '' && substr($search_basedn, -1) != ',') { |
$search_basedn .= ','; |
} |
$search_basedn .= $this->options['basedn']; |
$func_params = array($this->conn_id, $search_basedn, $filter, array($this->options['memberattr'])); |
$this->_debug("Searching with $filter in $search_basedn", __LINE__); |
// search |
if(($result_id = @call_user_func_array($this->ldap_search_func, $func_params)) != false) { |
if(ldap_count_entries($this->conn_id, $result_id) == 1) { |
ldap_free_result($result_id); |
$this->_debug('User is member of group', __LINE__); |
$this->_disconnect(); |
return true; |
} |
} |
// default |
$this->_debug('User is NOT member of group', __LINE__); |
$this->_disconnect(); |
return false; |
} |
/** |
* Outputs debugging messages |
* |
* @access private |
* @param string Debugging Message |
* @param integer Line number |
*/ |
function _debug($msg = '', $line = 0) |
{ |
if($this->options['debug'] === true) { |
if($msg == '' && $this->_isValidLink()) { |
$msg = 'LDAP_Error: ' . @ldap_err2str(@ldap_errno($this->_conn_id)); |
} |
print("$line: $msg <br />"); |
} |
} |
} |
?> |
/branches/v1.3-critias/bibliotheque/pear/Auth/Container/POP3.php |
---|
New file |
0,0 → 1,107 |
<?php |
/* vim: set expandtab tabstop=4 shiftwidth=4: */ |
// +----------------------------------------------------------------------+ |
// | PHP Version 4 | |
// +----------------------------------------------------------------------+ |
// | Copyright (c) 1997-2002 The PHP Group | |
// +----------------------------------------------------------------------+ |
// | This source file is subject to version 2.02 of the PHP license, | |
// | that is bundled with this package in the file LICENSE, and is | |
// | available at through the world-wide-web at | |
// | http://www.php.net/license/2_02.txt. | |
// | If you did not receive a copy of the PHP license and are unable to | |
// | obtain it through the world-wide-web, please send a note to | |
// | license@php.net so we can mail you a copy immediately. | |
// +----------------------------------------------------------------------+ |
// | Authors: Stefan Ekman <stekman@sedata.org> | |
// | Martin Jansen <mj@php.net> | |
// | Mika Tuupola <tuupola@appelsiini.net> | |
// +----------------------------------------------------------------------+ |
// |
// $Id: POP3.php,v 1.3 2003/07/28 21:39:39 yavo Exp $ |
// |
require_once('Auth/Container.php'); |
require_once('PEAR.php'); |
require_once('Net/POP3.php'); |
/** |
* Storage driver for Authentication on a POP3 server. |
* |
* @author Yavor Shahpasov <yavo@netsmart.com.cy> |
* @package Auth |
* @version $Revision: 1.3 $ |
*/ |
class Auth_Container_POP3 extends Auth_Container |
{ |
/** |
* POP3 Server |
* @var string |
*/ |
var $server='localhost'; |
/** |
* POP3 Server port |
* @var string |
*/ |
var $port='110'; |
// {{{ Constructor |
/** |
* Constructor of the container class |
* |
* @param $server string server or server:port combination |
* @return object Returns an error object if something went wrong |
*/ |
function Auth_Container_POP3($server=null) |
{ |
if(isset($server)){ |
if(is_array($server)){ |
if(isset($server['host'])){ |
$this->server = $server['host']; |
} |
if(isset($server['port'])){ |
$this->port = $server['port']; |
} |
} |
else{ |
if(strstr($server, ':')){ |
$serverparts = explode(':', trim($server)); |
$this->server = $serverparts[0]; |
$this->port = $serverparts[1]; |
} |
else |
{ |
$this->server = $server; |
} |
} |
} |
} |
// }}} |
// {{{ fetchData() |
/** |
* Try to login to the POP3 server |
* |
* @param string Username |
* @param string Password |
* @return boolean |
*/ |
function fetchData($username, $password) |
{ |
$pop3 =& new Net_POP3(); |
$res = $pop3->connect($this->server, $this->port); |
if(!$res){ |
return($res); |
} |
$result = $pop3->login($username, $password); |
$pop3->disconnect(); |
return $result; |
} |
// }}} |
} |
?> |
/branches/v1.3-critias/bibliotheque/pear/Auth/Container/MDB.php |
---|
New file |
0,0 → 1,392 |
<?php |
// |
// +----------------------------------------------------------------------+ |
// | PHP Version 4 | |
// +----------------------------------------------------------------------+ |
// | | |
// +----------------------------------------------------------------------+ |
// | This source file is subject to version 2.02 of the PHP license, | |
// | that is bundled with this package in the file LICENSE, and is | |
// | available at through the world-wide-web at | |
// | http://www.php.net/license/2_02.txt. | |
// | If you did not receive a copy of the PHP license and are unable to | |
// | obtain it through the world-wide-web, please send a note to | |
// | license@php.net so we can mail you a copy immediately. | |
// +----------------------------------------------------------------------+ |
// | Author: Lorenzo Alberton <l.alberton@quipo.it> | |
// +----------------------------------------------------------------------+ |
// |
// $Id: MDB.php,v 1.12 2003/10/13 08:08:45 yavo Exp $ |
// |
require_once 'Auth/Container.php'; |
require_once 'MDB.php'; |
/** |
* Storage driver for fetching login data from a database |
* |
* This storage driver can use all databases which are supported |
* by the PEAR MDB abstraction layer to fetch login data. |
* |
* @author Lorenzo Alberton <l.alberton@quipo.it> |
* @package Auth |
* @version $Revision: 1.12 $ |
*/ |
class Auth_Container_MDB extends Auth_Container |
{ |
/** |
* Additional options for the storage container |
* @var array |
*/ |
var $options = array(); |
/** |
* DB object |
* @var object |
*/ |
var $db = null; |
var $dsn = ''; |
/** |
* User that is currently selected from the DB. |
* @var string |
*/ |
var $activeUser = ''; |
// {{{ Constructor |
/** |
* Constructor of the container class |
* |
* Initate connection to the database via PEAR::DB |
* |
* @param string Connection data or DB object |
* @return object Returns an error object if something went wrong |
*/ |
function Auth_Container_MDB($dsn) |
{ |
$this->_setDefaults(); |
if (is_array($dsn)) { |
$this->_parseOptions($dsn); |
if (empty($this->options['dsn'])) { |
PEAR::raiseError('No connection parameters specified!'); |
} |
} else { |
$this->options['dsn'] = $dsn; |
} |
} |
// }}} |
// {{{ _connect() |
/** |
* Connect to database by using the given DSN string |
* |
* @access private |
* @param string DSN string |
* @return mixed Object on error, otherwise bool |
*/ |
function _connect($dsn) |
{ |
if (is_string($dsn) || is_array($dsn)) { |
$this->db =& MDB::Connect($dsn); |
} elseif (get_parent_class($dsn) == "mdb_common") { |
$this->db = $dsn; |
} elseif (is_object($dsn) && MDB::isError($dsn)) { |
return PEAR::raiseError($dsn->getMessage(), $dsn->code); |
} else { |
return PEAR::raiseError('The given dsn was not valid in file ' . __FILE__ . ' at line ' . __LINE__, |
41, |
PEAR_ERROR_RETURN, |
null, |
null |
); |
} |
if (MDB::isError($this->db) || PEAR::isError($this->db)) { |
return PEAR::raiseError($this->db->getMessage(), $this->db->code); |
} else { |
return true; |
} |
} |
// }}} |
// {{{ _prepare() |
/** |
* Prepare database connection |
* |
* This function checks if we have already opened a connection to |
* the database. If that's not the case, a new connection is opened. |
* |
* @access private |
* @return mixed True or a DB error object. |
*/ |
function _prepare() |
{ |
return $this->_connect($this->options['dsn']); |
} |
// }}} |
// {{{ query() |
/** |
* Prepare query to the database |
* |
* This function checks if we have already opened a connection to |
* the database. If that's not the case, a new connection is opened. |
* After that the query is passed to the database. |
* |
* @access public |
* @param string Query string |
* @return mixed a MDB_result object or MDB_OK on success, a MDB |
* or PEAR error on failure |
*/ |
function query($query) |
{ |
$err = $this->_prepare(); |
if ($err !== true) { |
return $err; |
} |
return $this->db->query($query); |
} |
// }}} |
// {{{ _setDefaults() |
/** |
* Set some default options |
* |
* @access private |
* @return void |
*/ |
function _setDefaults() |
{ |
$this->options['table'] = 'auth'; |
$this->options['usernamecol'] = 'username'; |
$this->options['passwordcol'] = 'password'; |
$this->options['dsn'] = ''; |
$this->options['db_fields'] = ''; |
$this->options['cryptType'] = 'md5'; |
} |
// }}} |
// {{{ _parseOptions() |
/** |
* Parse options passed to the container class |
* |
* @access private |
* @param array |
*/ |
function _parseOptions($array) |
{ |
foreach ($array as $key => $value) { |
if (isset($this->options[$key])) { |
$this->options[$key] = $value; |
} |
} |
// Include additional fields if they exist |
if (!empty($this->options['db_fields'])) { |
if (is_array($this->options['db_fields'])) { |
$this->options['db_fields'] = join($this->options['db_fields'], ', '); |
} |
$this->options['db_fields'] = ', ' . $this->options['db_fields']; |
} |
} |
// }}} |
// {{{ fetchData() |
/** |
* Get user information from database |
* |
* This function uses the given username to fetch |
* the corresponding login data from the database |
* table. If an account that matches the passed username |
* and password is found, the function returns true. |
* Otherwise it returns false. |
* |
* @param string Username |
* @param string Password |
* @return mixed Error object or boolean |
*/ |
function fetchData($username, $password) |
{ |
// Prepare for a database query |
$err = $this->_prepare(); |
if ($err !== true) { |
return PEAR::raiseError($err->getMessage(), $err->getCode()); |
} |
// Find if db_fileds contains a *, i so assume all col are selected |
if (strstr($this->options['db_fields'], '*')) { |
$sql_from = '*'; |
} else{ |
$sql_from = $this->options['usernamecol'] . ', '. $this->options['passwordcol'] . $this->options['db_fields']; |
} |
$query = sprintf("SELECT %s FROM %s WHERE %s = %s", |
$sql_from, |
$this->options['table'], |
$this->options['usernamecol'], |
$this->db->getTextValue($username) |
); |
$res = $this->db->getRow($query, null, null, null, MDB_FETCHMODE_ASSOC); |
if (MDB::isError($res) || PEAR::isError($res)) { |
return PEAR::raiseError($res->getMessage(), $res->getCode()); |
} |
if (!is_array($res)) { |
$this->activeUser = ''; |
return false; |
} |
if ($this->verifyPassword(trim($password, "\r\n"), |
trim($res[$this->options['passwordcol']], "\r\n"), |
$this->options['cryptType'])) { |
// Store additional field values in the session |
foreach ($res as $key => $value) { |
if ($key == $this->options['passwordcol'] || |
$key == $this->options['usernamecol']) { |
continue; |
} |
// Use reference to the auth object if exists |
// This is because the auth session variable can change so a static call to setAuthData does not make sence |
if(is_object($this->_auth_obj)){ |
$this->_auth_obj->setAuthData($key, $value); |
} else { |
Auth::setAuthData($key, $value); |
} |
} |
return true; |
} |
$this->activeUser = $res[$this->options['usernamecol']]; |
return false; |
} |
// }}} |
// {{{ listUsers() |
function listUsers() |
{ |
$err = $this->_prepare(); |
if ($err !== true) { |
return PEAR::raiseError($err->getMessage(), $err->getCode()); |
} |
$retVal = array(); |
// Find if db_fileds contains a *, i so assume all col are selected |
if (strstr($this->options['db_fields'], '*')) { |
$sql_from = '*'; |
} else{ |
$sql_from = $this->options['db_fields']; |
} |
$query = sprintf('SELECT %s FROM %s', |
$sql_from, |
$this->options['table'] |
); |
$res = $this->db->getAll($query, null, null, null, MDB_FETCHMODE_ASSOC); |
if (MDB::isError($res)) { |
return PEAR::raiseError($res->getMessage(), $res->getCode()); |
} else { |
foreach ($res as $user) { |
$user['username'] = $user[$this->options['usernamecol']]; |
$retVal[] = $user; |
} |
} |
return $retVal; |
} |
// }}} |
// {{{ addUser() |
/** |
* Add user to the storage container |
* |
* @access public |
* @param string Username |
* @param string Password |
* @param mixed Additional information that are stored in the DB |
* |
* @return mixed True on success, otherwise error object |
*/ |
function addUser($username, $password, $additional = "") |
{ |
if (function_exists($this->options['cryptType'])) { |
$cryptFunction = $this->options['cryptType']; |
} else { |
$cryptFunction = 'md5'; |
} |
$additional_key = ''; |
$additional_value = ''; |
if (is_array($additional)) { |
foreach ($additional as $key => $value) { |
$additional_key .= ', ' . $key; |
$additional_value .= ', ' . $this->db->getTextValue($value); |
} |
} |
$query = sprintf("INSERT INTO %s (%s, %s%s) VALUES (%s, %s%s)", |
$this->options['table'], |
$this->options['usernamecol'], |
$this->options['passwordcol'], |
$additional_key, |
$this->db->getTextValue($username), |
$this->db->getTextValue($cryptFunction($password)), |
$additional_value |
); |
$res = $this->query($query); |
if (MDB::isError($res)) { |
return PEAR::raiseError($res->getMessage(), $res->code); |
} else { |
return true; |
} |
} |
// }}} |
// {{{ removeUser() |
/** |
* Remove user from the storage container |
* |
* @access public |
* @param string Username |
* |
* @return mixed True on success, otherwise error object |
*/ |
function removeUser($username) |
{ |
$query = sprintf("DELETE FROM %s WHERE %s = %s", |
$this->options['table'], |
$this->options['usernamecol'], |
$this->db->getTextValue($username) |
); |
$res = $this->query($query); |
if (MDB::isError($res)) { |
return PEAR::raiseError($res->getMessage(), $res->code); |
} else { |
return true; |
} |
} |
// }}} |
} |
?> |
/branches/v1.3-critias/bibliotheque/pear/Auth/Container/SOAP.php |
---|
New file |
0,0 → 1,170 |
<?php |
// |
// +----------------------------------------------------------------------+ |
// | PHP Version 4 | |
// +----------------------------------------------------------------------+ |
// | Copyright (c) 1997-2002 The PHP Group | |
// +----------------------------------------------------------------------+ |
// | This source file is subject to version 2.02 of the PHP license, | |
// | that is bundled with this package in the file LICENSE, and is | |
// | available at through the world-wide-web at | |
// | http://www.php.net/license/2_02.txt. | |
// | If you did not receive a copy of the PHP license and are unable to | |
// | obtain it through the world-wide-web, please send a note to | |
// | license@php.net so we can mail you a copy immediately. | |
// +----------------------------------------------------------------------+ |
// | Authors: Bruno Pedro <bpedro@co.sapo.pt> | |
// +----------------------------------------------------------------------+ |
// |
// $Id: SOAP.php,v 1.6 2003/09/08 11:24:05 yavo Exp $ |
// |
require_once "Auth/Container.php"; |
require_once "PEAR.php"; |
require_once 'SOAP/Client.php'; |
/** |
* Storage driver for fetching login data from SOAP |
* |
* This class takes one parameter (options), where |
* you specify the following fields: endpoint, namespace, |
* method, encoding, usernamefield and passwordfield. |
* |
* You can use specify features of your SOAP service |
* by providing its parameters in an associative manner by |
* using the '_features' array through the options parameter. |
* |
* The 'matchpassword' option should be set to false if your |
* webservice doesn't return (username,password) pairs, but |
* instead returns error when the login is invalid. |
* |
* Example usage: |
* |
* <?php |
* |
* ... |
* |
* $options = array ( |
* 'endpoint' => 'http://your.soap.service/endpoint', |
* 'namespace' => 'urn:/Your/Namespace', |
* 'method' => 'get', |
* 'encoding' => 'UTF-8', |
* 'usernamefield' => 'login', |
* 'passwordfield' => 'password', |
* 'matchpasswords' => false, |
* '_features' => array ( |
* 'example_feature' => 'example_value', |
* 'another_example' => '' |
* ) |
* ); |
* $auth = new Auth('SOAP', $options, 'loginFunction'); |
* $auth->start(); |
* |
* ... |
* |
* ?> |
* |
* @author Bruno Pedro <bpedro@co.sapo.pt> |
* @package Auth |
* @version $Revision: 1.6 $ |
*/ |
class Auth_Container_SOAP extends Auth_Container |
{ |
/** |
* Required options for the class |
* @var array |
* @access private |
*/ |
var $_requiredOptions = array('endpoint', 'namespace', 'method', 'encoding', 'usernamefield', 'passwordfield'); |
/** |
* Options for the class |
* @var array |
* @access private |
*/ |
var $_options = array(); |
/** |
* Optional SOAP features |
* @var array |
* @access private |
*/ |
var $_features = array(); |
/** |
* The SOAP response |
* @var array |
* @access public |
*/ |
var $soapResponse = array(); |
/** |
* Constructor of the container class |
* |
* @param $options, associative array with endpoint, namespace, method, |
* usernamefield, passwordfield and optional features |
*/ |
function Auth_Container_SOAP($options) |
{ |
$this->_options = $options; |
if (!isset($this->_options['matchpasswords'])) { |
$this->_options['matchpasswords'] = true; |
} |
if (!empty($this->_options['_features'])) { |
$this->_features = $this->_options['_features']; |
unset($this->_options['_features']); |
} |
} |
/** |
* Fetch data from SOAP service |
* |
* Requests the SOAP service for the given username/password |
* combination. |
* |
* @param string Username |
* @param string Password |
* @return mixed Returns the SOAP response or false if something went wrong |
*/ |
function fetchData($username, $password) |
{ |
// check if all required options are set |
if (array_intersect($this->_requiredOptions, array_keys($this->_options)) != $this->_requiredOptions) { |
return false; |
} else { |
// create a SOAP client and set encoding |
$soapClient = new SOAP_Client($this->_options['endpoint']); |
$soapClient->setEncoding($this->_options['encoding']); |
} |
// assign username and password fields |
$usernameField = new SOAP_Value($this->_options['usernamefield'],'string', $username); |
$passwordField = new SOAP_Value($this->_options['passwordfield'],'string', $password); |
$SOAPParams = array($usernameField, $passwordField); |
// assign optional features |
foreach ($this->_features as $fieldName => $fieldValue) { |
$SOAPParams[] = new SOAP_Value($fieldName, 'string', $fieldValue); |
} |
// make SOAP call |
$this->soapResponse = $soapClient->call( |
$this->_options['method'], |
$SOAPParams, |
array('namespace' => $this->_options['namespace']) |
); |
if (!PEAR::isError($this->soapResponse)) { |
if ($this->_options['matchpasswords']) { |
// check if passwords match |
if ($password == $this->soapResponse->{$this->_options['passwordfield']}) { |
return true; |
} else { |
return false; |
} |
} else { |
return true; |
} |
} else { |
return false; |
} |
} |
} |
?> |
/branches/v1.3-critias/bibliotheque/pear/Auth/Container/SMBPasswd.php |
---|
New file |
0,0 → 1,134 |
<?php |
/* vim: set expandtab tabstop=4 shiftwidth=4: */ |
// +----------------------------------------------------------------------+ |
// | PHP Version 4 | |
// +----------------------------------------------------------------------+ |
// | Copyright (c) 1997-2003 The PHP Group | |
// +----------------------------------------------------------------------+ |
// | This source file is subject to version 2.02 of the PHP license, | |
// | that is bundled with this package in the file LICENSE, and is | |
// | available at through the world-wide-web at | |
// | http://www.php.net/license/2_02.txt. | |
// | If you did not receive a copy of the PHP license and are unable to | |
// | obtain it through the world-wide-web, please send a note to | |
// | license@php.net so we can mail you a copy immediately. | |
// +----------------------------------------------------------------------+ |
// | Authors: Michael Bretterklieber <michael@bretterklieber.com> | |
// +----------------------------------------------------------------------+ |
// |
// $Id: SMBPasswd.php,v 1.1 2003/05/13 19:23:54 mbretter Exp $ |
// |
require_once "File/SMBPasswd.php"; |
require_once "Auth/Container.php"; |
require_once "PEAR.php"; |
/** |
* Storage driver for fetching login data from an SAMBA smbpasswd file. |
* |
* This storage container can handle SAMBA smbpasswd files. |
* |
* Example: |
* $a = new Auth("SMBPasswd", '/usr/local/private/smbpasswd'); |
* $a->start(); |
* if ($a->getAuth()) { |
* printf ("AUTH OK<br>\n"); |
* $a->logout(); |
* } |
* |
* @author Michael Bretterklieber <michael@bretterklieber.com> |
* @package Auth |
* @version $Revision: 1.1 $ |
*/ |
class Auth_Container_SMBPasswd extends Auth_Container |
{ |
/** |
* File_SMBPasswd object |
* @var object |
*/ |
var $pwfile; |
// {{{ Constructor |
/** |
* Constructor of the container class |
* |
* @param $filename string filename for a passwd type file |
* @return object Returns an error object if something went wrong |
*/ |
function Auth_Container_SMBPasswd($filename) |
{ |
$this->pwfile = new File_SMBPasswd($filename,0); |
if (!$this->pwfile->load()) { |
PEAR::raiseError("Error while reading file contents.", 41, PEAR_ERROR_DIE); |
return; |
} |
} |
// }}} |
// {{{ fetchData() |
/** |
* Get user information from pwfile |
* |
* @param string Username |
* @param string Password |
* @return boolean |
*/ |
function fetchData($username, $password) |
{ |
return $this->pwfile->verifyAccount($username, $password); |
} |
// }}} |
// {{{ listUsers() |
function listUsers() |
{ |
return $this->pwfile->getAccounts(); |
} |
// }}} |
// {{{ addUser() |
/** |
* Add a new user to the storage container |
* |
* @param string Username |
* @param string Password |
* @param array Additional information |
* |
* @return boolean |
*/ |
function addUser($username, $password, $additional = '') |
{ |
$res = $this->pwfile->addUser($user, $additional['userid'], $pass); |
if ($res === true) { |
return $this->pwfile->save(); |
} |
return $res; |
} |
// }}} |
// {{{ removeUser() |
/** |
* Remove user from the storage container |
* |
* @param string Username |
*/ |
function removeUser($username) |
{ |
$res = $this->pwfile->delUser($username); |
if ($res === true) { |
return $this->pwfile->save(); |
} |
return $res; |
} |
// }}} |
} |
?> |
/branches/v1.3-critias/bibliotheque/pear/Auth/Container/DB.php |
---|
New file |
0,0 → 1,409 |
<?php |
// |
// +----------------------------------------------------------------------+ |
// | PHP Version 4 | |
// +----------------------------------------------------------------------+ |
// | | |
// +----------------------------------------------------------------------+ |
// | This source file is subject to version 2.02 of the PHP license, | |
// | that is bundled with this package in the file LICENSE, and is | |
// | available at through the world-wide-web at | |
// | http://www.php.net/license/2_02.txt. | |
// | If you did not receive a copy of the PHP license and are unable to | |
// | obtain it through the world-wide-web, please send a note to | |
// | license@php.net so we can mail you a copy immediately. | |
// +----------------------------------------------------------------------+ |
// | Authors: Martin Jansen <mj@php.net> | |
// +----------------------------------------------------------------------+ |
// |
// $Id: DB.php,v 1.40 2003/11/15 13:37:26 yavo Exp $ |
// |
require_once 'Auth/Container.php'; |
require_once 'DB.php'; |
/** |
* Storage driver for fetching login data from a database |
* |
* This storage driver can use all databases which are supported |
* by the PEAR DB abstraction layer to fetch login data. |
* |
* @author Martin Jansen <mj@php.net> |
* @package Auth |
* @version $Revision: 1.40 $ |
*/ |
class Auth_Container_DB extends Auth_Container |
{ |
/** |
* Additional options for the storage container |
* @var array |
*/ |
var $options = array(); |
/** |
* DB object |
* @var object |
*/ |
var $db = null; |
var $dsn = ''; |
/** |
* User that is currently selected from the DB. |
* @var string |
*/ |
var $activeUser = ''; |
// {{{ Constructor |
/** |
* Constructor of the container class |
* |
* Initate connection to the database via PEAR::DB |
* |
* @param string Connection data or DB object |
* @return object Returns an error object if something went wrong |
*/ |
function Auth_Container_DB($dsn) |
{ |
$this->_setDefaults(); |
if (is_array($dsn)) { |
$this->_parseOptions($dsn); |
if (empty($this->options['dsn'])) { |
PEAR::raiseError('No connection parameters specified!'); |
} |
} else { |
$this->options['dsn'] = $dsn; |
} |
} |
// }}} |
// {{{ _connect() |
/** |
* Connect to database by using the given DSN string |
* |
* @access private |
* @param string DSN string |
* @return mixed Object on error, otherwise bool |
*/ |
function _connect($dsn) |
{ |
if (is_string($dsn) || is_array($dsn)) { |
$this->db = DB::Connect($dsn); |
} elseif (get_parent_class($dsn) == "db_common") { |
$this->db = $dsn; |
} elseif (DB::isError($dsn)) { |
return PEAR::raiseError($dsn->getMessage(), $dsn->getCode()); |
} else { |
return PEAR::raiseError('The given dsn was not valid in file ' . __FILE__ . ' at line ' . __LINE__, |
41, |
PEAR_ERROR_RETURN, |
null, |
null |
); |
} |
if (DB::isError($this->db) || PEAR::isError($this->db)) { |
return PEAR::raiseError($this->db->getMessage(), $this->db->getCode()); |
} else { |
return true; |
} |
} |
// }}} |
// {{{ _prepare() |
/** |
* Prepare database connection |
* |
* This function checks if we have already opened a connection to |
* the database. If that's not the case, a new connection is opened. |
* |
* @access private |
* @return mixed True or a DB error object. |
*/ |
function _prepare() |
{ |
if (!DB::isConnection($this->db)) { |
$res = $this->_connect($this->options['dsn']); |
if(DB::isError($res) || PEAR::isError($res)){ |
return $res; |
} |
} |
return true; |
} |
// }}} |
// {{{ query() |
/** |
* Prepare query to the database |
* |
* This function checks if we have already opened a connection to |
* the database. If that's not the case, a new connection is opened. |
* After that the query is passed to the database. |
* |
* @access public |
* @param string Query string |
* @return mixed a DB_result object or DB_OK on success, a DB |
* or PEAR error on failure |
*/ |
function query($query) |
{ |
$err = $this->_prepare(); |
if ($err !== true) { |
return $err; |
} |
return $this->db->query($query); |
} |
// }}} |
// {{{ _setDefaults() |
/** |
* Set some default options |
* |
* @access private |
* @return void |
*/ |
function _setDefaults() |
{ |
$this->options['table'] = 'auth'; |
$this->options['usernamecol'] = 'username'; |
$this->options['passwordcol'] = 'password'; |
$this->options['dsn'] = ''; |
$this->options['db_fields'] = ''; |
$this->options['cryptType'] = 'md5'; |
} |
// }}} |
// {{{ _parseOptions() |
/** |
* Parse options passed to the container class |
* |
* @access private |
* @param array |
*/ |
function _parseOptions($array) |
{ |
foreach ($array as $key => $value) { |
if (isset($this->options[$key])) { |
$this->options[$key] = $value; |
} |
} |
/* Include additional fields if they exist */ |
if(!empty($this->options['db_fields'])){ |
if(is_array($this->options['db_fields'])){ |
$this->options['db_fields'] = join($this->options['db_fields'], ', '); |
} |
$this->options['db_fields'] = ', '.$this->options['db_fields']; |
} |
} |
// }}} |
// {{{ fetchData() |
/** |
* Get user information from database |
* |
* This function uses the given username to fetch |
* the corresponding login data from the database |
* table. If an account that matches the passed username |
* and password is found, the function returns true. |
* Otherwise it returns false. |
* |
* @param string Username |
* @param string Password |
* @return mixed Error object or boolean |
*/ |
function fetchData($username, $password) |
{ |
// Prepare for a database query |
$err = $this->_prepare(); |
if ($err !== true) { |
return PEAR::raiseError($err->getMessage(), $err->getCode()); |
} |
// Find if db_fileds contains a *, i so assume all col are selected |
if(strstr($this->options['db_fields'], '*')){ |
$sql_from = "*"; |
} |
else{ |
$sql_from = $this->options['usernamecol'] . ", ".$this->options['passwordcol'].$this->options['db_fields']; |
} |
/** |
Old Style, removed to go around the oci8 |
problem |
See bug 206 |
http://pear.php.net/bugs/bug.php?id=206 |
$query = "SELECT ! FROM ! WHERE ! = ?"; |
$query_params = array( |
$sql_from, |
$this->options['table'], |
$this->options['usernamecol'], |
$username |
); |
*/ |
$query = "SELECT ".$sql_from. |
" FROM ".$this->options['table']. |
" WHERE ".$this->options['usernamecol']." = '".$this->db->quoteString($username)."'"; |
$res = $this->db->getRow($query, null, DB_FETCHMODE_ASSOC); |
if (DB::isError($res)) { |
return PEAR::raiseError($res->getMessage(), $res->getCode()); |
} |
if (!is_array($res)) { |
$this->activeUser = ''; |
return false; |
} |
if ($this->verifyPassword(trim($password, "\r\n"), |
trim($res[$this->options['passwordcol']], "\r\n"), |
$this->options['cryptType'])) { |
// Store additional field values in the session |
foreach ($res as $key => $value) { |
if ($key == $this->options['passwordcol'] || |
$key == $this->options['usernamecol']) { |
continue; |
} |
// Use reference to the auth object if exists |
// This is because the auth session variable can change so a static call to setAuthData does not make sence |
if(is_object($this->_auth_obj)){ |
$this->_auth_obj->setAuthData($key, $value); |
} else { |
Auth::setAuthData($key, $value); |
} |
} |
return true; |
} |
$this->activeUser = $res[$this->options['usernamecol']]; |
return false; |
} |
// }}} |
// {{{ listUsers() |
function listUsers() |
{ |
$err = $this->_prepare(); |
if ($err !== true) { |
return PEAR::raiseError($err->getMessage(), $err->getCode()); |
} |
$retVal = array(); |
// Find if db_fileds contains a *, i so assume all col are selected |
if(strstr($this->options['db_fields'], '*')){ |
$sql_from = "*"; |
} |
else{ |
$sql_from = $this->options['usernamecol'] . ", ".$this->options['passwordcol'].$this->options['db_fields']; |
} |
$query = sprintf("SELECT %s FROM %s", |
$sql_from, |
$this->options['table'] |
); |
$res = $this->db->getAll($query, null, DB_FETCHMODE_ASSOC); |
if (DB::isError($res)) { |
return PEAR::raiseError($res->getMessage(), $res->getCode()); |
} else { |
foreach ($res as $user) { |
$user['username'] = $user[$this->options['usernamecol']]; |
$retVal[] = $user; |
} |
} |
return $retVal; |
} |
// }}} |
// {{{ addUser() |
/** |
* Add user to the storage container |
* |
* @access public |
* @param string Username |
* @param string Password |
* @param mixed Additional information that are stored in the DB |
* |
* @return mixed True on success, otherwise error object |
*/ |
function addUser($username, $password, $additional = "") |
{ |
if (function_exists($this->options['cryptType'])) { |
$cryptFunction = $this->options['cryptType']; |
} else { |
$cryptFunction = 'md5'; |
} |
$additional_key = ''; |
$additional_value = ''; |
if (is_array($additional)) { |
foreach ($additional as $key => $value) { |
$additional_key .= ', ' . $key; |
$additional_value .= ", '" . $value . "'"; |
} |
} |
$query = sprintf("INSERT INTO %s (%s, %s%s) VALUES ('%s', '%s'%s)", |
$this->options['table'], |
$this->options['usernamecol'], |
$this->options['passwordcol'], |
$additional_key, |
$username, |
$cryptFunction($password), |
$additional_value |
); |
$res = $this->query($query); |
if (DB::isError($res)) { |
return PEAR::raiseError($res->getMessage(), $res->getCode()); |
} else { |
return true; |
} |
} |
// }}} |
// {{{ removeUser() |
/** |
* Remove user from the storage container |
* |
* @access public |
* @param string Username |
* |
* @return mixed True on success, otherwise error object |
*/ |
function removeUser($username) |
{ |
$query = sprintf("DELETE FROM %s WHERE %s = '%s'", |
$this->options['table'], |
$this->options['usernamecol'], |
$username |
); |
$res = $this->query($query); |
if (DB::isError($res)) { |
return PEAR::raiseError($res->getMessage(), $res->getCode()); |
} else { |
return true; |
} |
} |
// }}} |
} |
?> |
/branches/v1.3-critias/bibliotheque/pear/Auth/Container/IMAP.php |
---|
New file |
0,0 → 1,170 |
<?php |
// |
// +----------------------------------------------------------------------+ |
// | PHP Version 4 | |
// +----------------------------------------------------------------------+ |
// | Copyright (c) 1997-2003 The PHP Group | |
// +----------------------------------------------------------------------+ |
// | This source file is subject to version 2.02 of the PHP license, | |
// | that is bundled with this package in the file LICENSE, and is | |
// | available at through the world-wide-web at | |
// | http://www.php.net/license/2_02.txt. | |
// | If you did not receive a copy of the PHP license and are unable to | |
// | obtain it through the world-wide-web, please send a note to | |
// | license@php.net so we can mail you a copy immediately. | |
// +----------------------------------------------------------------------+ |
// | Authors: Jeroen Houben <jeroen@terena.nl> | |
// +----------------------------------------------------------------------+ |
// |
// $Id: IMAP.php,v 1.7 2003/10/20 09:38:29 yavo Exp $ |
// |
require_once "Auth/Container.php"; |
require_once "PEAR.php"; |
/** |
* Storage driver for fetching login data from an IMAP server |
* |
* This class is based on LDAP containers, but it very simple. |
* By default it connects to localhost:143 |
* The constructor will first check if the host:port combination is |
* actually reachable. This behaviour can be disabled. |
* It then tries to create an IMAP stream (without opening a mailbox) |
* If you wish to pass extended options to the connections, you may |
* do so by specifying protocol options. |
* |
* To use this storage containers, you have to use the |
* following syntax: |
* |
* <?php |
* ... |
* $params = array( |
* 'host' => 'mail.example.com', |
* 'port' => 143, |
* ); |
* $myAuth = new Auth('IMAP', $params); |
* .... |
* |
* By default we connect without any protocol options set. However, some |
* servers require you to connect with the notls or norsh options set. |
* To do this you need to add the following value to the params array: |
* 'baseDSN' => '/imap/notls/norsh' |
* |
* To connect to an SSL IMAP server: |
* 'baseDSN' => '/imap/ssl' |
* |
* To connect to an SSL IMAP server with a self-signed certificate: |
* 'baseDSN' => '/imap/ssl/novalidate-cert' |
* |
* Further options may be available and can be found on the php site at |
* http://www.php.net/manual/function.imap-open.php |
* |
*/ |
/* |
* |
* @author Jeroen Houben <jeroen@terena.nl>, Cipriano Groenendal <cipri@campai.nl> |
* @package Auth |
* @version $Revision: 1.7 $ |
*/ |
class Auth_Container_IMAP extends Auth_Container |
{ |
/** |
* Options for the class |
* @var array |
*/ |
var $options = array(); |
/** |
* Constructor of the container class |
* |
* @param $params, associative hash with host,port,basedn and userattr key |
* @param $params, associative array with host, port, baseDSN, checkServer key. |
* @return object Returns an error object if something went wrong |
*/ |
function Auth_Container_IMAP($params) |
{ |
if (!extension_loaded('imap')) { |
return PEAR::raiseError("Cannot use IMAP authentication, IMAP extension not loaded!", |
41, PEAR_ERROR_DIE); |
} |
$this->_setDefaults(); |
// set parameters (if any) |
if (is_array($params)) { |
$this->_parseOptions($params); |
} |
if ($this->options['checkServer']) { |
$this->_checkServer($this->options['timeout']); |
} |
return true; |
} |
/** |
* Set some default options |
* |
* @access private |
*/ |
function _setDefaults() |
{ |
$this->options['host'] = 'localhost'; |
$this->options['port'] = 143; |
$this->options['baseDSN'] = ''; |
$this->options['checkServer'] = true; |
$this->options['timeout'] = 20; |
} |
/** |
* Check if the given server and port are reachable |
* |
* @access private |
*/ |
function _checkServer() { |
$fp = @fsockopen ($this->options['host'], $this->options['port'], |
$errno, $errstr, $timeout); |
if (is_resource($fp)) { |
@fclose($fp); |
} else { |
$message = "Error connecting to IMAP server " |
. $this->options['host'] |
. ":" . $this->options['port']; |
return PEAR::raiseError($message, 41, PEAR_ERROR_DIE); |
} |
} |
/** |
* Parse options passed to the container class |
* |
* @access private |
* @param array |
*/ |
function _parseOptions($array) |
{ |
foreach ($array as $key => $value) { |
$this->options[$key] = $value; |
} |
} |
/** |
* Try to open a IMAP stream using $username / $password |
* |
* @param string Username |
* @param string Password |
* @return boolean |
*/ |
function fetchData($username, $password) |
{ |
$dsn = '{'.$this->options['host'].':'.$this->options['port'].$this->options['baseDSN'].'}'; |
$conn = @imap_open ($dsn, $username, $password, OP_HALFOPEN); |
if (is_resource($conn)){ |
$this->activeUser = $username; |
@imap_close($conn); |
return true; |
} else { |
$this->activeUser = ''; |
return false; |
} |
} |
} |
?> |
/branches/v1.3-critias/bibliotheque/pear/Auth/SASL/Plain.php |
---|
New file |
0,0 → 1,63 |
<?php |
// +-----------------------------------------------------------------------+ |
// | Copyright (c) 2002-2003 Richard Heyes | |
// | All rights reserved. | |
// | | |
// | Redistribution and use in source and binary forms, with or without | |
// | modification, are permitted provided that the following conditions | |
// | are met: | |
// | | |
// | o Redistributions of source code must retain the above copyright | |
// | notice, this list of conditions and the following disclaimer. | |
// | o Redistributions in binary form must reproduce the above copyright | |
// | notice, this list of conditions and the following disclaimer in the | |
// | documentation and/or other materials provided with the distribution.| |
// | o The names of the authors may not be used to endorse or promote | |
// | products derived from this software without specific prior written | |
// | permission. | |
// | | |
// | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
// | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
// | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | |
// | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | |
// | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |
// | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | |
// | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |
// | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |
// | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
// | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |
// | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
// | | |
// +-----------------------------------------------------------------------+ |
// | Author: Richard Heyes <richard@php.net> | |
// +-----------------------------------------------------------------------+ |
// |
// $Id: Plain.php,v 1.6 2003/09/11 18:53:56 mbretter Exp $ |
/** |
* Implmentation of PLAIN SASL mechanism |
* |
* @author Richard Heyes <richard@php.net> |
* @access public |
* @version 1.0 |
* @package Auth_SASL |
*/ |
require_once('Auth/SASL/Common.php'); |
class Auth_SASL_Plain extends Auth_SASL_Common |
{ |
/** |
* Returns PLAIN response |
* |
* @param string $authcid Authentication id (username) |
* @param string $pass Password |
* @param string $authzid Autorization id |
* @return string PLAIN Response |
*/ |
function getResponse($authcid, $pass, $authzid = '') |
{ |
return $authzid . chr(0) . $authcid . chr(0) . $pass; |
} |
} |
?> |
/branches/v1.3-critias/bibliotheque/pear/Auth/SASL/DigestMD5.php |
---|
New file |
0,0 → 1,198 |
<?php |
// +-----------------------------------------------------------------------+ |
// | Copyright (c) 2002-2003 Richard Heyes | |
// | All rights reserved. | |
// | | |
// | Redistribution and use in source and binary forms, with or without | |
// | modification, are permitted provided that the following conditions | |
// | are met: | |
// | | |
// | o Redistributions of source code must retain the above copyright | |
// | notice, this list of conditions and the following disclaimer. | |
// | o Redistributions in binary form must reproduce the above copyright | |
// | notice, this list of conditions and the following disclaimer in the | |
// | documentation and/or other materials provided with the distribution.| |
// | o The names of the authors may not be used to endorse or promote | |
// | products derived from this software without specific prior written | |
// | permission. | |
// | | |
// | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
// | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
// | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | |
// | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | |
// | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |
// | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | |
// | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |
// | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |
// | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
// | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |
// | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
// | | |
// +-----------------------------------------------------------------------+ |
// | Author: Richard Heyes <richard@php.net> | |
// +-----------------------------------------------------------------------+ |
// |
// $Id: DigestMD5.php,v 1.8 2006/03/22 05:20:11 amistry Exp $ |
/** |
* Implmentation of DIGEST-MD5 SASL mechanism |
* |
* @author Richard Heyes <richard@php.net> |
* @access public |
* @version 1.0 |
* @package Auth_SASL |
*/ |
require_once('Auth/SASL/Common.php'); |
class Auth_SASL_DigestMD5 extends Auth_SASL_Common |
{ |
/** |
* Provides the (main) client response for DIGEST-MD5 |
* requires a few extra parameters than the other |
* mechanisms, which are unavoidable. |
* |
* @param string $authcid Authentication id (username) |
* @param string $pass Password |
* @param string $challenge The digest challenge sent by the server |
* @param string $hostname The hostname of the machine you're connecting to |
* @param string $service The servicename (eg. imap, pop, acap etc) |
* @param string $authzid Authorization id (username to proxy as) |
* @return string The digest response (NOT base64 encoded) |
* @access public |
*/ |
function getResponse($authcid, $pass, $challenge, $hostname, $service, $authzid = '') |
{ |
$challenge = $this->_parseChallenge($challenge); |
$authzid_string = ''; |
if ($authzid != '') { |
$authzid_string = ',authzid="' . $authzid . '"'; |
} |
if (!empty($challenge)) { |
$cnonce = $this->_getCnonce(); |
$digest_uri = sprintf('%s/%s', $service, $hostname); |
$response_value = $this->_getResponseValue($authcid, $pass, $challenge['realm'], $challenge['nonce'], $cnonce, $digest_uri, $authzid); |
if ($challenge['realm']) { |
return sprintf('username="%s",realm="%s"' . $authzid_string . |
',nonce="%s",cnonce="%s",nc=00000001,qop=auth,digest-uri="%s",response=%s,maxbuf=%d', $authcid, $challenge['realm'], $challenge['nonce'], $cnonce, $digest_uri, $response_value, $challenge['maxbuf']); |
} else { |
return sprintf('username="%s"' . $authzid_string . ',nonce="%s",cnonce="%s",nc=00000001,qop=auth,digest-uri="%s",response=%s,maxbuf=%d', $authcid, $challenge['nonce'], $cnonce, $digest_uri, $response_value, $challenge['maxbuf']); |
} |
} else { |
return PEAR::raiseError('Invalid digest challenge'); |
} |
} |
/** |
* Parses and verifies the digest challenge* |
* |
* @param string $challenge The digest challenge |
* @return array The parsed challenge as an assoc |
* array in the form "directive => value". |
* @access private |
*/ |
function _parseChallenge($challenge) |
{ |
$tokens = array(); |
while (preg_match('/^([a-z-]+)=("[^"]+(?<!\\\)"|[^,]+)/i', $challenge, $matches)) { |
// Ignore these as per rfc2831 |
if ($matches[1] == 'opaque' OR $matches[1] == 'domain') { |
$challenge = substr($challenge, strlen($matches[0]) + 1); |
continue; |
} |
// Allowed multiple "realm" and "auth-param" |
if (!empty($tokens[$matches[1]]) AND ($matches[1] == 'realm' OR $matches[1] == 'auth-param')) { |
if (is_array($tokens[$matches[1]])) { |
$tokens[$matches[1]][] = preg_replace('/^"(.*)"$/', '\\1', $matches[2]); |
} else { |
$tokens[$matches[1]] = array($tokens[$matches[1]], preg_replace('/^"(.*)"$/', '\\1', $matches[2])); |
} |
// Any other multiple instance = failure |
} elseif (!empty($tokens[$matches[1]])) { |
$tokens = array(); |
break; |
} else { |
$tokens[$matches[1]] = preg_replace('/^"(.*)"$/', '\\1', $matches[2]); |
} |
// Remove the just parsed directive from the challenge |
$challenge = substr($challenge, strlen($matches[0]) + 1); |
} |
/** |
* Defaults and required directives |
*/ |
// Realm |
if (empty($tokens['realm'])) { |
$tokens['realm'] = ""; |
} |
// Maxbuf |
if (empty($tokens['maxbuf'])) { |
$tokens['maxbuf'] = 65536; |
} |
// Required: nonce, algorithm |
if (empty($tokens['nonce']) OR empty($tokens['algorithm'])) { |
return array(); |
} |
return $tokens; |
} |
/** |
* Creates the response= part of the digest response |
* |
* @param string $authcid Authentication id (username) |
* @param string $pass Password |
* @param string $realm Realm as provided by the server |
* @param string $nonce Nonce as provided by the server |
* @param string $cnonce Client nonce |
* @param string $digest_uri The digest-uri= value part of the response |
* @param string $authzid Authorization id |
* @return string The response= part of the digest response |
* @access private |
*/ |
function _getResponseValue($authcid, $pass, $realm, $nonce, $cnonce, $digest_uri, $authzid = '') |
{ |
if ($authzid == '') { |
$A1 = sprintf('%s:%s:%s', pack('H32', md5(sprintf('%s:%s:%s', $authcid, $realm, $pass))), $nonce, $cnonce); |
} else { |
$A1 = sprintf('%s:%s:%s:%s', pack('H32', md5(sprintf('%s:%s:%s', $authcid, $realm, $pass))), $nonce, $cnonce, $authzid); |
} |
$A2 = 'AUTHENTICATE:' . $digest_uri; |
return md5(sprintf('%s:%s:00000001:%s:auth:%s', md5($A1), $nonce, $cnonce, md5($A2))); |
} |
/** |
* Creates the client nonce for the response |
* |
* @return string The cnonce value |
* @access private |
*/ |
function _getCnonce() |
{ |
if (file_exists('/dev/urandom') && $fd = @fopen('/dev/urandom', 'r')) { |
return base64_encode(fread($fd, 32)); |
} elseif (file_exists('/dev/random') && $fd = @fopen('/dev/random', 'r')) { |
return base64_encode(fread($fd, 32)); |
} else { |
$str = ''; |
mt_srand((double)microtime()*10000000); |
for ($i=0; $i<32; $i++) { |
$str .= chr(mt_rand(0, 255)); |
} |
return base64_encode($str); |
} |
} |
} |
?> |
/branches/v1.3-critias/bibliotheque/pear/Auth/SASL/Anonymous.php |
---|
New file |
0,0 → 1,71 |
<?php |
// +-----------------------------------------------------------------------+ |
// | Copyright (c) 2002-2003 Richard Heyes | |
// | All rights reserved. | |
// | | |
// | Redistribution and use in source and binary forms, with or without | |
// | modification, are permitted provided that the following conditions | |
// | are met: | |
// | | |
// | o Redistributions of source code must retain the above copyright | |
// | notice, this list of conditions and the following disclaimer. | |
// | o Redistributions in binary form must reproduce the above copyright | |
// | notice, this list of conditions and the following disclaimer in the | |
// | documentation and/or other materials provided with the distribution.| |
// | o The names of the authors may not be used to endorse or promote | |
// | products derived from this software without specific prior written | |
// | permission. | |
// | | |
// | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
// | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
// | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | |
// | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | |
// | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |
// | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | |
// | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |
// | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |
// | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
// | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |
// | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
// | | |
// +-----------------------------------------------------------------------+ |
// | Author: Richard Heyes <richard@php.net> | |
// +-----------------------------------------------------------------------+ |
// |
// $Id: Anonymous.php,v 1.4 2003/02/21 16:07:17 mj Exp $ |
/** |
* Implmentation of ANONYMOUS SASL mechanism |
* |
* @author Richard Heyes <richard@php.net> |
* @access public |
* @version 1.0 |
* @package Auth_SASL |
*/ |
require_once('Auth/SASL/Common.php'); |
class Auth_SASL_Anonymous extends Auth_SASL_Common |
{ |
/** |
* Not much to do here except return the token supplied. |
* No encoding, hashing or encryption takes place for this |
* mechanism, simply one of: |
* o An email address |
* o An opaque string not containing "@" that can be interpreted |
* by the sysadmin |
* o Nothing |
* |
* We could have some logic here for the second option, but this |
* would by no means create something interpretable. |
* |
* @param string $token Optional email address or string to provide |
* as trace information. |
* @return string The unaltered input token |
*/ |
function getResponse($token = '') |
{ |
return $token; |
} |
} |
?> |
/branches/v1.3-critias/bibliotheque/pear/Auth/SASL/Common.php |
---|
New file |
0,0 → 1,74 |
<?php |
// +-----------------------------------------------------------------------+ |
// | Copyright (c) 2002-2003 Richard Heyes | |
// | All rights reserved. | |
// | | |
// | Redistribution and use in source and binary forms, with or without | |
// | modification, are permitted provided that the following conditions | |
// | are met: | |
// | | |
// | o Redistributions of source code must retain the above copyright | |
// | notice, this list of conditions and the following disclaimer. | |
// | o Redistributions in binary form must reproduce the above copyright | |
// | notice, this list of conditions and the following disclaimer in the | |
// | documentation and/or other materials provided with the distribution.| |
// | o The names of the authors may not be used to endorse or promote | |
// | products derived from this software without specific prior written | |
// | permission. | |
// | | |
// | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
// | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
// | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | |
// | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | |
// | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |
// | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | |
// | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |
// | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |
// | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
// | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |
// | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
// | | |
// +-----------------------------------------------------------------------+ |
// | Author: Richard Heyes <richard@php.net> | |
// +-----------------------------------------------------------------------+ |
// |
// $Id: Common.php,v 1.6 2003/02/21 16:07:17 mj Exp $ |
/** |
* Common functionality to SASL mechanisms |
* |
* @author Richard Heyes <richard@php.net> |
* @access public |
* @version 1.0 |
* @package Auth_SASL |
*/ |
class Auth_SASL_Common |
{ |
/** |
* Function which implements HMAC MD5 digest |
* |
* @param string $key The secret key |
* @param string $data The data to protect |
* @return string The HMAC MD5 digest |
*/ |
function _HMAC_MD5($key, $data) |
{ |
if (strlen($key) > 64) { |
$key = pack('H32', md5($key)); |
} |
if (strlen($key) < 64) { |
$key = str_pad($key, 64, chr(0)); |
} |
$k_ipad = substr($key, 0, 64) ^ str_repeat(chr(0x36), 64); |
$k_opad = substr($key, 0, 64) ^ str_repeat(chr(0x5C), 64); |
$inner = pack('H32', md5($k_ipad . $data)); |
$digest = md5($k_opad . $inner); |
return $digest; |
} |
} |
?> |
/branches/v1.3-critias/bibliotheque/pear/Auth/SASL/CramMD5.php |
---|
New file |
0,0 → 1,68 |
<?php |
// +-----------------------------------------------------------------------+ |
// | Copyright (c) 2002-2003 Richard Heyes | |
// | All rights reserved. | |
// | | |
// | Redistribution and use in source and binary forms, with or without | |
// | modification, are permitted provided that the following conditions | |
// | are met: | |
// | | |
// | o Redistributions of source code must retain the above copyright | |
// | notice, this list of conditions and the following disclaimer. | |
// | o Redistributions in binary form must reproduce the above copyright | |
// | notice, this list of conditions and the following disclaimer in the | |
// | documentation and/or other materials provided with the distribution.| |
// | o The names of the authors may not be used to endorse or promote | |
// | products derived from this software without specific prior written | |
// | permission. | |
// | | |
// | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
// | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
// | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | |
// | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | |
// | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |
// | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | |
// | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |
// | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |
// | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
// | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |
// | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
// | | |
// +-----------------------------------------------------------------------+ |
// | Author: Richard Heyes <richard@php.net> | |
// +-----------------------------------------------------------------------+ |
// |
// $Id: CramMD5.php,v 1.4 2003/02/21 16:07:17 mj Exp $ |
/** |
* Implmentation of CRAM-MD5 SASL mechanism |
* |
* @author Richard Heyes <richard@php.net> |
* @access public |
* @version 1.0 |
* @package Auth_SASL |
*/ |
require_once('Auth/SASL/Common.php'); |
class Auth_SASL_CramMD5 extends Auth_SASL_Common |
{ |
/** |
* Implements the CRAM-MD5 SASL mechanism |
* This DOES NOT base64 encode the return value, |
* you will need to do that yourself. |
* |
* @param string $user Username |
* @param string $pass Password |
* @param string $challenge The challenge supplied by the server. |
* this should be already base64_decoded. |
* |
* @return string The string to pass back to the server, of the form |
* "<user> <digest>". This is NOT base64_encoded. |
*/ |
function getResponse($user, $pass, $challenge) |
{ |
return $user . ' ' . $this->_HMAC_MD5($pass, $challenge); |
} |
} |
?> |
/branches/v1.3-critias/bibliotheque/pear/Auth/SASL/Login.php |
---|
New file |
0,0 → 1,65 |
<?php |
// +-----------------------------------------------------------------------+ |
// | Copyright (c) 2002-2003 Richard Heyes | |
// | All rights reserved. | |
// | | |
// | Redistribution and use in source and binary forms, with or without | |
// | modification, are permitted provided that the following conditions | |
// | are met: | |
// | | |
// | o Redistributions of source code must retain the above copyright | |
// | notice, this list of conditions and the following disclaimer. | |
// | o Redistributions in binary form must reproduce the above copyright | |
// | notice, this list of conditions and the following disclaimer in the | |
// | documentation and/or other materials provided with the distribution.| |
// | o The names of the authors may not be used to endorse or promote | |
// | products derived from this software without specific prior written | |
// | permission. | |
// | | |
// | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
// | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
// | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | |
// | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | |
// | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |
// | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | |
// | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |
// | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |
// | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
// | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |
// | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
// | | |
// +-----------------------------------------------------------------------+ |
// | Author: Richard Heyes <richard@php.net> | |
// +-----------------------------------------------------------------------+ |
// |
// $Id: Login.php,v 1.4 2003/02/21 16:07:17 mj Exp $ |
/** |
* This is technically not a SASL mechanism, however |
* it's used by Net_Sieve, Net_Cyrus and potentially |
* other protocols , so here is a good place to abstract |
* it. |
* |
* @author Richard Heyes <richard@php.net> |
* @access public |
* @version 1.0 |
* @package Auth_SASL |
*/ |
require_once('Auth/SASL/Common.php'); |
class Auth_SASL_Login extends Auth_SASL_Common |
{ |
/** |
* Pseudo SASL LOGIN mechanism |
* |
* @param string $user Username |
* @param string $pass Password |
* @return string LOGIN string |
*/ |
function getResponse($user, $pass) |
{ |
return sprintf('LOGIN %s %s', $user, $pass); |
} |
} |
?> |
/branches/v1.3-critias/bibliotheque/pear/Auth/HTTP.php |
---|
New file |
0,0 → 1,795 |
<?php |
// |
// +----------------------------------------------------------------------+ |
// | PHP Version 4 | |
// +----------------------------------------------------------------------+ |
// | Copyright (c) 1997-2004 The PHP Group | |
// +----------------------------------------------------------------------+ |
// | This source file is subject to version 2.02 of the PHP license, | |
// | that is bundled with this package in the file LICENSE, and is | |
// | available at through the world-wide-web at | |
// | http://www.php.net/license/2_02.txt. | |
// | If you did not receive a copy of the PHP license and are unable to | |
// | obtain it through the world-wide-web, please send a note to | |
// | license@php.net so we can mail you a copy immediately. | |
// +----------------------------------------------------------------------+ |
// | Authors: Martin Jansen <mj@php.net> | |
// | Rui Hirokawa <hirokawa@php.net> | |
// | David Costa <gurugeek@php.net> | |
// +----------------------------------------------------------------------+ |
// |
// $Id: Auth_HTTP.php,v 1.27 2005/04/04 12:48:33 hirokawa Exp $ |
// |
require_once "Auth/Auth.php"; |
define('AUTH_HTTP_NONCE_TIME_LEN', 16); |
define('AUTH_HTTP_NONCE_HASH_LEN', 32); |
// {{{ class Auth_HTTP |
/** |
* PEAR::Auth_HTTP |
* |
* The PEAR::Auth_HTTP class provides methods for creating an |
* HTTP authentication system based on RFC-2617 using PHP. |
* |
* Instead of generating an HTML driven form like PEAR::Auth |
* does, this class sends header commands to the clients which |
* cause them to present a login box like they are e.g. used |
* in Apache's .htaccess mechanism. |
* |
* This class requires the PEAR::Auth package. |
* |
* @notes The HTTP Digest Authentication part is based on |
* authentication class written by Tom Pike <tom.pike@xiven.com> |
* |
* @author Martin Jansen <mj@php.net> |
* @author Rui Hirokawa <hirokawa@php.net> |
* @author David Costa <gurugeek@php.net> |
* @package Auth_HTTP |
* @extends Auth |
* @version $Revision: 1.27 $ |
*/ |
class Auth_HTTP extends Auth |
{ |
// {{{ properties |
/** |
* Authorization method: 'basic' or 'digest' |
* |
* @access public |
* @var string |
*/ |
var $authType = 'basic'; |
/** |
* Name of the realm for Basic Authentication |
* |
* @access public |
* @var string |
* @see drawLogin() |
*/ |
var $realm = "protected area"; |
/** |
* Text to send if user hits cancel button |
* |
* @access public |
* @var string |
* @see drawLogin() |
*/ |
var $CancelText = "Error 401 - Access denied"; |
/** |
* option array |
* |
* @access public |
* @var array |
*/ |
var $options = array(); |
/** |
* flag to indicate the nonce was stale. |
* |
* @access public |
* @var bool |
*/ |
var $stale = false; |
/** |
* opaque string for digest authentication |
* |
* @access public |
* @var string |
*/ |
var $opaque = 'dummy'; |
/** |
* digest URI |
* |
* @access public |
* @var string |
*/ |
var $uri = ''; |
/** |
* authorization info returned by the client |
* |
* @access public |
* @var array |
*/ |
var $auth = array(); |
/** |
* next nonce value |
* |
* @access public |
* @var string |
*/ |
var $nextNonce = ''; |
/** |
* nonce value |
* |
* @access public |
* @var string |
*/ |
var $nonce = ''; |
/** |
* Holds a reference to the global server variable |
* @var array |
*/ |
var $server; |
/** |
* Holds a reference to the global post variable |
* @var array |
*/ |
var $post; |
/** |
* Holds a reference to the global cookie variable |
* @var array |
*/ |
var $cookie; |
// }}} |
// {{{ Constructor |
/** |
* Constructor |
* |
* @param string Type of the storage driver |
* @param mixed Additional options for the storage driver |
* (example: if you are using DB as the storage |
* driver, you have to pass the dsn string here) |
* |
* @return void |
*/ |
function Auth_HTTP($storageDriver, $options = '') |
{ |
/* set default values for options */ |
$this->options = array('cryptType' => 'md5', |
'algorithm' => 'MD5', |
'qop' => 'auth-int,auth', |
'opaquekey' => 'moo', |
'noncekey' => 'moo', |
'digestRealm' => 'protected area', |
'forceDigestOnly' => false, |
'nonceLife' => 300, |
'sessionSharing' => true, |
); |
if (!empty($options['authType'])) { |
$this->authType = strtolower($options['authType']); |
} |
if (is_array($options)) { |
foreach($options as $key => $value) { |
if (array_key_exists( $key, $this->options)) { |
$this->options[$key] = $value; |
} |
} |
if (!empty($this->options['opaquekey'])) { |
$this->opaque = md5($this->options['opaquekey']); |
} |
} |
$this->Auth($storageDriver, $options); |
} |
// }}} |
// {{{ assignData() |
/** |
* Assign values from $PHP_AUTH_USER and $PHP_AUTH_PW or 'Authorization' header |
* to internal variables and sets the session id based |
* on them |
* |
* @access public |
* @return void |
*/ |
function assignData() |
{ |
if (method_exists($this, '_importGlobalVariable')) { |
$this->server = &$this->_importGlobalVariable('server'); |
} |
if ($this->authType == 'basic') { |
if (!empty($this->server['PHP_AUTH_USER'])) { |
$this->username = $this->server['PHP_AUTH_USER']; |
} |
if (!empty($this->server['PHP_AUTH_PW'])) { |
$this->password = $this->server['PHP_AUTH_PW']; |
} |
/** |
* Try to get authentication information from IIS |
*/ |
if (empty($this->username) && empty($this->password)) { |
if (!empty($this->server['HTTP_AUTHORIZATION'])) { |
list($this->username, $this->password) = |
explode(':', base64_decode(substr($this->server['HTTP_AUTHORIZATION'], 6))); |
} |
} |
} elseif ($this->authType == 'digest') { |
$this->username = ''; |
$this->password = ''; |
$this->digest_header = null; |
if (!empty($this->server['PHP_AUTH_DIGEST'])) { |
$this->digest_header = substr($this->server['PHP_AUTH_DIGEST'], |
strpos($this->server['PHP_AUTH_DIGEST'],' ')+1); |
} else { |
$headers = getallheaders(); |
if(isset($headers['Authorization']) && !empty($headers['Authorization'])) { |
$this->digest_header = substr($headers['Authorization'], |
strpos($headers['Authorization'],' ')+1); |
} |
} |
if($this->digest_header) { |
$authtemp = explode(',', $this->digest_header); |
$auth = array(); |
foreach($authtemp as $key => $value) { |
$value = trim($value); |
if(strpos($value,'=') !== false) { |
$lhs = substr($value,0,strpos($value,'=')); |
$rhs = substr($value,strpos($value,'=')+1); |
if(substr($rhs,0,1) == '"' && substr($rhs,-1,1) == '"') { |
$rhs = substr($rhs,1,-1); |
} |
$auth[$lhs] = $rhs; |
} |
} |
} |
if (!isset($auth['uri']) || !isset($auth['realm'])) { |
return; |
} |
if ($this->selfURI() == $auth['uri']) { |
$this->uri = $auth['uri']; |
if (substr($headers['Authorization'],0,7) == 'Digest ') { |
$this->authType = 'digest'; |
if (!isset($auth['nonce']) || !isset($auth['username']) || |
!isset($auth['response']) || !isset($auth['qop']) || |
!isset($auth['nc']) || !isset($auth['cnonce'])){ |
return; |
} |
if ($auth['qop'] != 'auth' && $auth['qop'] != 'auth-int') { |
return; |
} |
$this->stale = $this->_judgeStale($auth['nonce']); |
if ($this->nextNonce == false) { |
return; |
} |
$this->username = $auth['username']; |
$this->password = $auth['response']; |
$this->auth['nonce'] = $auth['nonce']; |
$this->auth['qop'] = $auth['qop']; |
$this->auth['nc'] = $auth['nc']; |
$this->auth['cnonce'] = $auth['cnonce']; |
if (isset($auth['opaque'])) { |
$this->auth['opaque'] = $auth['opaque']; |
} |
} elseif (substr($headers['Authorization'],0,6) == 'Basic ') { |
if ($this->options['forceDigestOnly']) { |
return; // Basic authentication is not allowed. |
} |
$this->authType = 'basic'; |
list($username, $password) = |
explode(':',base64_decode(substr($headers['Authorization'],6))); |
$this->username = $username; |
$this->password = $password; |
} |
} |
} else { |
return PEAR::raiseError('authType is invalid.'); |
} |
if ($this->options['sessionSharing'] && |
isset($this->username) && isset($this->password)) { |
session_id(md5('Auth_HTTP' . $this->username . $this->password)); |
} |
/** |
* set sessionName for AUTH, so that the sessionName is different |
* for distinct realms |
*/ |
$this->_sessionName = "_authhttp".md5($this->realm); |
} |
// }}} |
// {{{ login() |
/** |
* Login function |
* |
* @access private |
* @return void |
*/ |
function login() |
{ |
$login_ok = false; |
if (method_exists($this, '_loadStorage')) { |
$this->_loadStorage(); |
} |
$this->storage->_auth_obj->_sessionName =& $this->_sessionName; |
/** |
* When the user has already entered a username, |
* we have to validate it. |
*/ |
if (!empty($this->username) && !empty($this->password)) { |
if ($this->authType == 'basic' && !$this->options['forceDigestOnly']) { |
if (true === $this->storage->fetchData($this->username, $this->password)) { |
$login_ok = true; |
} |
} else { /* digest authentication */ |
if (!$this->getAuth() || $this->getAuthData('a1') == null) { |
/* |
* note: |
* - only PEAR::DB is supported as container. |
* - password should be stored in container as plain-text |
* (if $options['cryptType'] == 'none') or |
* A1 hashed form (md5('username:realm:password')) |
* (if $options['cryptType'] == 'md5') |
*/ |
$dbs = $this->storage; |
if (!DB::isConnection($dbs->db)) { |
$dbs->_connect($dbs->options['dsn']); |
} |
$query = 'SELECT '.$dbs->options['passwordcol']." FROM ".$dbs->options['table']. |
' WHERE '.$dbs->options['usernamecol']." = '". |
$dbs->db->quoteString($this->username)."' "; |
$pwd = $dbs->db->getOne($query); // password stored in container. |
if (DB::isError($pwd)) { |
return PEAR::raiseError($pwd->getMessage(), $pwd->getCode()); |
} |
if ($this->options['cryptType'] == 'none') { |
$a1 = md5($this->username.':'.$this->options['digestRealm'].':'.$pwd); |
} else { |
$a1 = $pwd; |
} |
$this->setAuthData('a1', $a1, true); |
} else { |
$a1 = $this->getAuthData('a1'); |
} |
$login_ok = $this->validateDigest($this->password, $a1); |
if ($this->nextNonce == false) { |
$login_ok = false; |
} |
} |
if (!$login_ok && is_callable($this->loginFailedCallback)) { |
call_user_func($this->loginFailedCallback,$this->username, $this); |
} |
} |
if (!empty($this->username) && $login_ok) { |
$this->setAuth($this->username); |
if (is_callable($this->loginCallback)) { |
call_user_func($this->loginCallback,$this->username, $this); |
} |
} |
/** |
* If the login failed or the user entered no username, |
* output the login screen again. |
*/ |
if (!empty($this->username) && !$login_ok) { |
$this->status = AUTH_WRONG_LOGIN; |
} |
if ((empty($this->username) || !$login_ok) && $this->showLogin) { |
$this->drawLogin($this->storage->activeUser); |
return; |
} |
if (!empty($this->username) && $login_ok && $this->authType == 'digest' |
&& $this->auth['qop'] == 'auth') { |
$this->authenticationInfo(); |
} |
} |
// }}} |
// {{{ drawLogin() |
/** |
* Launch the login box |
* |
* @param string $username Username |
* @return void |
* @access private |
*/ |
function drawLogin($username = "") |
{ |
/** |
* Send the header commands |
*/ |
if ($this->authType == 'basic') { |
header("WWW-Authenticate: Basic realm=\"".$this->realm."\""); |
header('HTTP/1.0 401 Unauthorized'); |
} else if ($this->authType == 'digest') { |
$this->nonce = $this->_getNonce(); |
$wwwauth = 'WWW-Authenticate: Digest '; |
$wwwauth .= 'qop="'.$this->options['qop'].'", '; |
$wwwauth .= 'algorithm='.$this->options['algorithm'].', '; |
$wwwauth .= 'realm="'.$this->options['digestRealm'].'", '; |
$wwwauth .= 'nonce="'.$this->nonce.'", '; |
if ($this->stale) { |
$wwwauth .= 'stale=true, '; |
} |
if (!empty($this->opaque)) { |
$wwwauth .= 'opaque="'.$this->opaque.'"' ; |
} |
$wwwauth .= "\r\n"; |
if (!$this->options['forceDigestOnly']) { |
$wwwauth .= 'WWW-Authenticate: Basic realm="'.$this->realm.'"'; |
} |
header($wwwauth); |
header('HTTP/1.0 401 Unauthorized'); |
} |
/** |
* This code is only executed if the user hits the cancel |
* button or if he enters wrong data 3 times. |
*/ |
if ($this->stale) { |
echo 'Stale nonce value, please re-authenticate.'; |
} else { |
echo $this->CancelText; |
} |
exit; |
} |
// }}} |
// {{{ setRealm() |
/** |
* Set name of the current realm |
* |
* @access public |
* @param string $realm Name of the realm |
* @param string $digestRealm Name of the realm for digest authentication |
* @return void |
*/ |
function setRealm($realm, $digestRealm = '') |
{ |
$this->realm = $realm; |
if (!empty($digestRealm)) { |
$this->options['digestRealm'] = $digestRealm; |
} |
} |
// }}} |
// {{{ setCancelText() |
/** |
* Set the text to send if user hits the cancel button |
* |
* @access public |
* @param string $text Text to send |
* @return void |
*/ |
function setCancelText($text) |
{ |
$this->CancelText = $text; |
} |
// }}} |
// {{{ validateDigest() |
/** |
* judge if the client response is valid. |
* |
* @access private |
* @param string $response client response |
* @param string $a1 password or hashed password stored in container |
* @return bool true if success, false otherwise |
*/ |
function validateDigest($response, $a1) |
{ |
if (method_exists($this, '_importGlobalVariable')) { |
$this->server = &$this->_importGlobalVariable('server'); |
} |
$a2unhashed = $this->server['REQUEST_METHOD'].":".$this->selfURI(); |
if($this->auth['qop'] == 'auth-int') { |
if(isset($GLOBALS["HTTP_RAW_POST_DATA"])) { |
// In PHP < 4.3 get raw POST data from this variable |
$body = $GLOBALS["HTTP_RAW_POST_DATA"]; |
} else if($lines = @file('php://input')) { |
// In PHP >= 4.3 get raw POST data from this file |
$body = implode("\n", $lines); |
} else { |
if (method_exists($this, '_importGlobalVariable')) { |
$this->post = &$this->_importGlobalVariable('post'); |
} |
$body = ''; |
foreach($this->post as $key => $value) { |
if($body != '') $body .= '&'; |
$body .= rawurlencode($key) . '=' . rawurlencode($value); |
} |
} |
$a2unhashed .= ':'.md5($body); |
} |
$a2 = md5($a2unhashed); |
$combined = $a1.':'. |
$this->auth['nonce'].':'. |
$this->auth['nc'].':'. |
$this->auth['cnonce'].':'. |
$this->auth['qop'].':'. |
$a2; |
$expectedResponse = md5($combined); |
if(!isset($this->auth['opaque']) || $this->auth['opaque'] == $this->opaque) { |
if($response == $expectedResponse) { // password is valid |
if(!$this->stale) { |
return true; |
} else { |
$this->drawLogin(); |
} |
} |
} |
return false; |
} |
// }}} |
// {{{ _judgeStale() |
/** |
* judge if nonce from client is stale. |
* |
* @access private |
* @param string $nonce nonce value from client |
* @return bool stale |
*/ |
function _judgeStale($nonce) |
{ |
$stale = false; |
if(!$this->_decodeNonce($nonce, $time, $hash_cli)) { |
$this->nextNonce = false; |
$stale = true; |
return $stale; |
} |
if ($time < time() - $this->options['nonceLife']) { |
$this->nextNonce = $this->_getNonce(); |
$stale = true; |
} else { |
$this->nextNonce = $nonce; |
} |
return $stale; |
} |
// }}} |
// {{{ _nonceDecode() |
/** |
* decode nonce string |
* |
* @access private |
* @param string $nonce nonce value from client |
* @param string $time decoded time |
* @param string $hash decoded hash |
* @return bool false if nonce is invalid |
*/ |
function _decodeNonce($nonce, &$time, &$hash) |
{ |
if (method_exists($this, '_importGlobalVariable')) { |
$this->server = &$this->_importGlobalVariable('server'); |
} |
if (strlen($nonce) != AUTH_HTTP_NONCE_TIME_LEN + AUTH_HTTP_NONCE_HASH_LEN) { |
return false; |
} |
$time = base64_decode(substr($nonce, 0, AUTH_HTTP_NONCE_TIME_LEN)); |
$hash_cli = substr($nonce, AUTH_HTTP_NONCE_TIME_LEN, AUTH_HTTP_NONCE_HASH_LEN); |
$hash = md5($time . $this->server['HTTP_USER_AGENT'] . $this->options['noncekey']); |
if ($hash_cli != $hash) { |
return false; |
} |
return true; |
} |
// }}} |
// {{{ _getNonce() |
/** |
* return nonce to detect timeout |
* |
* @access private |
* @return string nonce value |
*/ |
function _getNonce() |
{ |
if (method_exists($this, '_importGlobalVariable')) { |
$this->server = &$this->_importGlobalVariable('server'); |
} |
$time = time(); |
$hash = md5($time . $this->server['HTTP_USER_AGENT'] . $this->options['noncekey']); |
return base64_encode($time) . $hash; |
} |
// }}} |
// {{{ authenticationInfo() |
/** |
* output HTTP Authentication-Info header |
* |
* @notes md5 hash of contents is required if 'qop' is 'auth-int' |
* |
* @access private |
* @param string MD5 hash of content |
*/ |
function authenticationInfo($contentMD5 = '') { |
if($this->getAuth() && ($this->getAuthData('a1') != null)) { |
$a1 = $this->getAuthData('a1'); |
// Work out authorisation response |
$a2unhashed = ":".$this->selfURI(); |
if($this->auth['qop'] == 'auth-int') { |
$a2unhashed .= ':'.$contentMD5; |
} |
$a2 = md5($a2unhashed); |
$combined = $a1.':'. |
$this->nonce.':'. |
$this->auth['nc'].':'. |
$this->auth['cnonce'].':'. |
$this->auth['qop'].':'. |
$a2; |
// Send authentication info |
$wwwauth = 'Authentication-Info: '; |
if($this->nonce != $this->nextNonce) { |
$wwwauth .= 'nextnonce="'.$this->nextNonce.'", '; |
} |
$wwwauth .= 'qop='.$this->auth['qop'].', '; |
$wwwauth .= 'rspauth="'.md5($combined).'", '; |
$wwwauth .= 'cnonce="'.$this->auth['cnonce'].'", '; |
$wwwauth .= 'nc='.$this->auth['nc'].''; |
header($wwwauth); |
} |
} |
// }}} |
// {{{ setOption() |
/** |
* set authentication option |
* |
* @access public |
* @param mixed $name key of option |
* @param mixed $value value of option |
* @return void |
*/ |
function setOption($name, $value = null) |
{ |
if (is_array($name)) { |
foreach($name as $key => $value) { |
if (array_key_exists( $key, $this->options)) { |
$this->options[$key] = $value; |
} |
} |
} else { |
if (array_key_exists( $name, $this->options)) { |
$this->options[$name] = $value; |
} |
} |
} |
// }}} |
// {{{ getOption() |
/** |
* get authentication option |
* |
* @access public |
* @param string $name key of option |
* @return mixed option value |
*/ |
function getOption($name) |
{ |
if (array_key_exists( $name, $this->options)) { |
return $this->options[$name]; |
} |
if ($name == 'CancelText') { |
return $this->CancelText; |
} |
if ($name == 'Realm') { |
return $this->realm; |
} |
return false; |
} |
// }}} |
// {{{ selfURI() |
/** |
* get self URI |
* |
* @access public |
* @return string self URI |
*/ |
function selfURI() |
{ |
if (method_exists($this, '_importGlobalVariable')) { |
$this->server = &$this->_importGlobalVariable('server'); |
} |
if (preg_match("/MSIE/",$this->server['HTTP_USER_AGENT'])) { |
// query string should be removed for MSIE |
$uri = preg_replace("/^(.*)\?/","\\1",$this->server['REQUEST_URI']); |
} else { |
$uri = $this->server['REQUEST_URI']; |
} |
return $uri; |
} |
// }}} |
} |
// }}} |
/* |
* Local variables: |
* tab-width: 4 |
* c-basic-offset: 4 |
* End: |
*/ |
?> |
/branches/v1.3-critias/bibliotheque/pear/Auth/Auth.php |
---|
New file |
0,0 → 1,5 |
<?php |
include_once('Auth.php'); |
?> |
/branches/v1.3-critias/bibliotheque/pear/Auth/Container.php |
---|
New file |
0,0 → 1,177 |
<?php |
// |
// +----------------------------------------------------------------------+ |
// | PHP Version 4 | |
// +----------------------------------------------------------------------+ |
// | Copyright (c) 1997-2003 The PHP Group | |
// +----------------------------------------------------------------------+ |
// | This source file is subject to version 2.02 of the PHP license, | |
// | that is bundled with this package in the file LICENSE, and is | |
// | available at through the world-wide-web at | |
// | http://www.php.net/license/2_02.txt. | |
// | If you did not receive a copy of the PHP license and are unable to | |
// | obtain it through the world-wide-web, please send a note to | |
// | license@php.net so we can mail you a copy immediately. | |
// +----------------------------------------------------------------------+ |
// | Authors: Martin Jansen <mj@php.net> | |
// +----------------------------------------------------------------------+ |
// |
// $Id: Container.php,v 1.15 2003/10/19 14:03:19 yavo Exp $ |
// |
define("AUTH_METHOD_NOT_SUPPORTED", -4); |
/** |
* Storage class for fetching login data |
* |
* @author Martin Jansen <mj@php.net> |
* @package Auth |
*/ |
class Auth_Container |
{ |
/** |
* User that is currently selected from the storage container. |
* |
* @access public |
*/ |
var $activeUser = ""; |
// {{{ Constructor |
/** |
* Constructor |
* |
* Has to be overwritten by each storage class |
* |
* @access public |
*/ |
function Auth_Container() |
{ |
} |
// }}} |
// {{{ fetchData() |
/** |
* Fetch data from storage container |
* |
* Has to be overwritten by each storage class |
* |
* @access public |
*/ |
function fetchData() |
{ |
} |
// }}} |
// {{{ verifyPassword() |
/** |
* Crypt and verfiy the entered password |
* |
* @param string Entered password |
* @param string Password from the data container (usually this password |
* is already encrypted. |
* @param string Type of algorithm with which the password from |
* the container has been crypted. (md5, crypt etc.) |
* Defaults to "md5". |
* @return bool True, if the passwords match |
*/ |
function verifyPassword($password1, $password2, $cryptType = "md5") |
{ |
switch ($cryptType) { |
case "crypt" : |
return (($password2 == "**" . $password1) || |
(crypt($password1, $password2) == $password2) |
); |
break; |
case "none" : |
return ($password1 == $password2); |
break; |
case "md5" : |
return (md5($password1) == $password2); |
break; |
default : |
if (function_exists($cryptType)) { |
return ($cryptType($password1) == $password2); |
} |
else if (method_exists($this,$cryptType)) { |
return ($this->$cryptType($password1) == $password2); |
} else { |
return false; |
} |
break; |
} |
} |
// }}} |
// {{{ listUsers() |
/** |
* List all users that are available from the storage container |
*/ |
function listUsers() |
{ |
return AUTH_METHOD_NOT_SUPPORTED; |
} |
/** |
* Returns a user assoc array |
* |
* Containers which want should overide this |
* |
* @param string The username |
*/ |
function getUser($username) |
{ |
$users = $this->listUsers(); |
if($users === AUTH_METHOD_NOT_SUPPORTED){ |
return(AUTH_METHOD_NOT_SUPPORTED); |
} |
for($i=0;$c = count($users),$i<$c;$i++){ |
if($users[$i]['username'] == $username){ |
return($users[$i]); |
} |
} |
return(false); |
} |
// }}} |
// {{{ addUser() |
/** |
* Add a new user to the storage container |
* |
* @param string Username |
* @param string Password |
* @param array Additional information |
* |
* @return boolean |
*/ |
function addUser($username, $password, $additional=null) |
{ |
return AUTH_METHOD_NOT_SUPPORTED; |
} |
// }}} |
// {{{ removeUser() |
/** |
* Remove user from the storage container |
* |
* @param string Username |
*/ |
function removeUser($username) |
{ |
return AUTH_METHOD_NOT_SUPPORTED; |
} |
// }}} |
} |
?> |
/branches/v1.3-critias/bibliotheque/pear/Auth/SASL.php |
---|
New file |
0,0 → 1,99 |
<?php |
// +-----------------------------------------------------------------------+ |
// | Copyright (c) 2002-2003 Richard Heyes | |
// | All rights reserved. | |
// | | |
// | Redistribution and use in source and binary forms, with or without | |
// | modification, are permitted provided that the following conditions | |
// | are met: | |
// | | |
// | o Redistributions of source code must retain the above copyright | |
// | notice, this list of conditions and the following disclaimer. | |
// | o Redistributions in binary form must reproduce the above copyright | |
// | notice, this list of conditions and the following disclaimer in the | |
// | documentation and/or other materials provided with the distribution.| |
// | o The names of the authors may not be used to endorse or promote | |
// | products derived from this software without specific prior written | |
// | permission. | |
// | | |
// | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
// | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
// | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | |
// | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | |
// | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |
// | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | |
// | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |
// | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |
// | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
// | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |
// | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
// | | |
// +-----------------------------------------------------------------------+ |
// | Author: Richard Heyes <richard@php.net> | |
// +-----------------------------------------------------------------------+ |
// |
// $Id: SASL.php,v 1.5 2006/03/22 05:20:11 amistry Exp $ |
/** |
* Client implementation of various SASL mechanisms |
* |
* @author Richard Heyes <richard@php.net> |
* @access public |
* @version 1.0 |
* @package Auth_SASL |
*/ |
require_once('PEAR.php'); |
class Auth_SASL |
{ |
/** |
* Factory class. Returns an object of the request |
* type. |
* |
* @param string $type One of: Anonymous |
* Plain |
* CramMD5 |
* DigestMD5 |
* Types are not case sensitive |
*/ |
function &factory($type) |
{ |
switch (strtolower($type)) { |
case 'anonymous': |
$filename = 'Auth/SASL/Anonymous.php'; |
$classname = 'Auth_SASL_Anonymous'; |
break; |
case 'login': |
$filename = 'Auth/SASL/Login.php'; |
$classname = 'Auth_SASL_Login'; |
break; |
case 'plain': |
$filename = 'Auth/SASL/Plain.php'; |
$classname = 'Auth_SASL_Plain'; |
break; |
case 'crammd5': |
$filename = 'Auth/SASL/CramMD5.php'; |
$classname = 'Auth_SASL_CramMD5'; |
break; |
case 'digestmd5': |
$filename = 'Auth/SASL/DigestMD5.php'; |
$classname = 'Auth_SASL_DigestMD5'; |
break; |
default: |
return PEAR::raiseError('Invalid SASL mechanism type'); |
break; |
} |
require_once($filename); |
$obj = new $classname(); |
return $obj; |
} |
} |
?> |
/branches/v1.3-critias/bibliotheque/pear/Auth/PrefManager.php |
---|
New file |
0,0 → 1,426 |
<?php |
require_once("DB.php"); |
/** |
* A simple preference manager, takes userid, preference name pairs and returns the value |
* of that preference. |
* |
* CREATE TABLE `preferences` ( |
* `user_id` varchar( 255 ) NOT NULL default '', |
* `pref_id` varchar( 32 ) NOT NULL default '', |
* `pref_value` longtext NOT NULL , |
* PRIMARY KEY ( `user_id` , `pref_id` ) |
* ) |
* |
* @author Jon Wood <jon@jellybob.co.uk> |
* @package Auth_PrefManager |
* @category Authentication |
*/ |
class Auth_PrefManager |
{ |
/** |
* The database object. |
* @var object |
* @access private |
*/ |
var $_db; |
/** |
* The user name to get preferences from if the user specified doesn't |
* have that preference set. |
* @var string |
* @access private |
*/ |
var $_defaultUser = "__default__"; |
/** |
* Should we search for default values, or just fail when we find out that |
* the specified user didn't have it set. |
* |
* @var bool |
* @access private |
*/ |
var $_returnDefaults = true; |
/** |
* The table containing the preferences. |
* @var string |
* @access private |
*/ |
var $_table = "preferences"; |
/** |
* The column containing user ids. |
* @var string |
* @access private |
*/ |
var $_userColumn = "user_id"; |
/** |
* The column containing preference names. |
* @var string |
* @access private |
*/ |
var $_nameColumn = "pref_id"; |
/** |
* The column containing preference values. |
* @var string |
* @access private |
*/ |
var $_valueColumn = "pref_value"; |
/** |
* The quoted value column. |
* @var string |
* @access private |
*/ |
var $_valueColumnQuoted = "pref_value"; |
/** |
* The session variable that the cache array is stored in. |
* @var string |
* @access private |
*/ |
var $_cacheName = "prefCache"; |
/** |
* The last error given. |
* @var string |
* @access private |
*/ |
var $_lastError; |
/** |
* Defines whether the cache should be used or not. |
* @var bool |
* @access private |
*/ |
var $_useCache = true; |
/** |
* Defines whether values should be serialized before saving. |
* @var bool |
* @access private |
*/ |
var $_serialize = false; |
/** |
* Constructor |
* |
* Options: |
* table: The table to get prefs from. [preferences] |
* userColumn: The field name to search for userid's [user_id] |
* nameColumn: The field name to search for preference names [pref_name] |
* valueColumn: The field name to search for preference values [pref_value] |
* defaultUser: The userid assigned to default values [__default__] |
* cacheName: The name of cache in the session variable ($_SESSION[cacheName]) [prefsCache] |
* useCache: Whether or not values should be cached. |
* serialize: Should preference values be serialzed before saving? |
* |
* @param string $dsn The DSN of the database connection to make, or a DB object. |
* @param array $properties An array of properties to set. |
* @param string $defaultUser The default user to manage for. |
* @return bool Success or failure. |
* @access public |
*/ |
function Auth_PrefManager($dsn, $properties = NULL) |
{ |
// Connect to the database. |
if (isset($dsn)) { |
if (is_string($dsn)) { |
$this->_db = DB::Connect($dsn); |
if (DB::isError($this->_db)) { |
$this->_lastError = "DB Error: ".$this->_db->getMessage(); |
} |
} else if (is_subclass_of($dsn, 'db_common')) { |
$this->_db = &$dsn; |
} else { |
$this->_lastError = "Invalid DSN specified."; |
return false; |
} |
} else { |
$this->_lastError = "No DSN specified."; |
return false; |
} |
if (is_array($properties)) { |
if (isset($properties["table"])) { $this->_table = $this->_db->quoteIdentifier($properties["table"]); } |
if (isset($properties["userColumn"])) { $this->_userColumn = $this->_db->quoteIdentifier($properties["userColumn"]); } |
if (isset($properties["nameColumn"])) { $this->_nameColumn = $this->_db->quoteIdentifier($properties["nameColumn"]); } |
if (isset($properties["valueColumn"])) { $this->_valueColumn = $properties["valueColumn"]; } |
if (isset($properties["valueColumn"])) { $this->_valueColumnQuoted = $this->_db->quoteIdentifier($properties["valueColumn"]); } |
if (isset($properties["defaultUser"])) { $this->_defaultUser = $properties["defaultUser"]; } |
if (isset($properties["cacheName"])) { $this->_cacheName = $properties["cacheName"]; } |
if (isset($properties["useCache"])) { $this->_useCache = $properties["useCache"]; } |
if (isset($properties["serialize"])) { $this->_serialize = $properties["serialize"]; } |
} |
return true; |
} |
function setReturnDefaults($returnDefaults = true) |
{ |
if (is_bool($returnDefaults)) { |
$this->_returnDefaults = $returnDefaults; |
} |
} |
/** |
* Sets whether the cache should be used. |
* |
* @param bool $use Should the cache be used. |
* @access public |
*/ |
function useCache($use = true) |
{ |
$this->_useCache = $use; |
} |
/** |
* Cleans out the cache. |
* |
* @access public |
*/ |
function clearCache() |
{ |
unset($_SESSION[$this->_cacheName]); |
} |
/** |
* Get a preference for the specified user, or, if returning default values |
* is enabled, the default. |
* |
* @param string $user_id The user to get the preference for. |
* @param string $pref_id The preference to get. |
* @param bool $showDefaults Should default values be searched (overrides the global setting). |
* @return mixed The value if it's found, or NULL if it isn't. |
* @access public |
*/ |
function getPref($user_id, $pref_id, $showDefaults = true) |
{ |
if (isset($_SESSION[$this->_cacheName][$user_id][$pref_id]) && $this->_useCache) { |
// Value is cached for the specified user, so give them the cached copy. |
return $_SESSION[$this->_cacheName][$user_id][$pref_id]; |
} else { |
// Not cached, search the database for this user's preference. |
$query = sprintf("SELECT * FROM %s WHERE %s=%s AND %s=%s", $this->_table, |
$this->_userColumn, |
$this->_db->quote($user_id), |
$this->_nameColumn, |
$this->_db->quote($pref_id)); |
$result = $this->_db->query($query); |
if (DB::isError($result)) { |
// Ouch! The query failed! |
$this->_lastError = "DB Error: ".$result->getMessage(); |
return NULL; |
} else if ($result->numRows()) { |
// The query found a value, so we can cache that, and then return it. |
$row = $result->fetchRow(DB_FETCHMODE_ASSOC); |
$_SESSION[$this->_cacheName][$user_id][$pref_id] = $this->_unpack($row[$this->_valueColumn]); |
return $_SESSION[$this->_cacheName][$user_id][$pref_id]; |
} else if ($this->_returnDefaults && $showDefaults) { |
// I was doing this with a call to getPref again, but it threw things into an |
// infinite loop if the default value didn't exist. If you can fix that, it would |
// be great ;) |
if (isset($_SESSION[$this->_cacheName][$this->_defaultUser][$pref_id]) && $this->_useCache) { |
$_SESSION[$this->_cacheName][$user_id][$pref_id] = $_SESSION[$this->_cacheName][$this->_defaultUser][$pref_id]; |
return $_SESSION[$this->_cacheName][$this->_defaultUser][$pref_id]; |
} else { |
$query = sprintf("SELECT * FROM %s WHERE %s=%s AND %s=%s", $this->_table, |
$this->_userColumn, |
$this->_db->quote($this->_defaultUser), |
$this->_nameColumn, |
$this->_db->quote($pref_id)); |
$result = $this->_db->query($query); |
if (DB::isError($result)) { |
$this->_lastError = "DB Error: ".$result->getMessage(); |
return NULL; |
} else { |
if ($result->numRows()) { |
$row = $result->fetchRow(DB_FETCHMODE_ASSOC); |
$_SESSION[$this->_cacheName][$this->_defaultUser][$pref_id] = $this->_unpack($row[$this->_valueColumn]); |
$_SESSION[$this->_cacheName][$user_id][$pref_id] = $_SESSION[$this->_cacheName][$this->_defaultUser][$pref_id]; |
return $_SESSION[$this->_cacheName][$user_id][$pref_id]; |
} else { |
return NULL; |
} |
} |
} |
} else { |
// We've used up all the resources we're allowed to search, so return a NULL. |
return NULL; |
} |
} |
} |
/** |
* A shortcut function for getPref($this->_defaultUser, $pref_id, $value), |
* useful if you have a logged in user, but want to get defaults anyway. |
* |
* @param string $pref_id The name of the preference to get. |
* @return mixed The value if it's found, or NULL if it isn't. |
* @access public |
*/ |
function getDefaultPref($pref_id) |
{ |
return $this->getPref($this->_defaultUser, $pref_id); |
} |
/** |
* Set a preference for the specified user. |
* |
* @param string $user_id The user to set for. |
* @param string $pref_id The preference to set. |
* @param mixed $value The value it should be set to. |
* @return bool Sucess or failure. |
* @access public |
*/ |
function setPref($user_id, $pref_id, $value) |
{ |
// Start off by checking if the preference is already set (if it is we need to do |
// an UPDATE, if not, it's an INSERT. |
if ($this->_exists($user_id, $pref_id, false)) { |
$query = sprintf("UPDATE %s SET %s=%s WHERE %s=%s AND %s=%s", $this->_table, |
$this->_valueColumnQuoted, |
$this->_db->quote($this->_pack($value)), |
$this->_userColumn, |
$this->_db->quote($user_id), |
$this->_nameColumn, |
$this->_db->quote($pref_id)); |
} else { |
$query = sprintf("INSERT INTO %s (%s, %s, %s) VALUES(%s, %s, %s)", $this->_table, |
$this->_userColumn, |
$this->_nameColumn, |
$this->_valueColumnQuoted, |
$this->_db->quote($user_id), |
$this->_db->quote($pref_id), |
$this->_db->quote($this->_pack($value))); |
} |
$result = $this->_db->query($query); |
if (DB::isError($result)) { |
$this->_lastError = "DB Error: ".$result->getMessage(); |
return false; |
} else { |
if ($this->_useCache) { |
$_SESSION[$this->_cacheName][$user_id][$pref_id] = $value; |
} |
return true; |
} |
} |
/** |
* A shortcut function for setPref($this->_defaultUser, $pref_id, $value) |
* |
* @param string $pref_id The name of the preference to set. |
* @param mixed $value The value to set it to. |
* @return bool Sucess or failure. |
* @access public |
*/ |
function setDefaultPref($pref_id, $value) |
{ |
return $this->setPref($this->_defaultUser, $pref_id, $value); |
} |
/** |
* Deletes a preference for the specified user. |
* |
* @param string $user_id The userid of the user to delete from. |
* @param string $pref_id The preference to delete. |
* @return bool Success/Failure |
* @access public |
*/ |
function deletePref($user_id, $pref_id) |
{ |
if ($this->getPref($user_id, $pref_id) == NULL) { |
// The user doesn't have this variable anyway ;) |
return true; |
} else { |
$query = sprintf("DELETE FROM %s WHERE %s=%s AND %s=%s", $this->_table, |
$this->_userColumn, |
$this->_db->quote($user_id), |
$this->_nameColumn, |
$this->_db->quote($pref_id)); |
$result = $this->_db->query($query); |
if (DB::isError($result)) { |
$this->_lastError = "DB Error: ".$result->getMessage(); |
return false; |
} else { |
if ($this->_useCache) { |
unset($_SESSION[$this->_cacheName][$user_id][$pref_id]); |
} |
return true; |
} |
} |
} |
/** |
* Deletes a preference for the default user. |
* |
* @param string $pref_id The preference to delete. |
* @return bool Success/Failure |
* @access public |
*/ |
function deleteDefaultPref($pref_id) |
{ |
return $this->deletePref($this->_defaultUser, $pref_id); |
} |
/** |
* Checks if a preference exists in the database. |
* |
* @param string $user_id The userid of the preference owner. |
* @param string $pref_id The preference to check for. |
* @return bool True if the preference exists. |
* @access private |
*/ |
function _exists($user_id, $pref_id) |
{ |
$query = sprintf("SELECT COUNT(%s) FROM %s WHERE %s=%s AND %s=%s", $this->_nameColumn, |
$this->_table, |
$this->_userColumn, |
$this->_db->quoteSmart($user_id), |
$this->_nameColumn, |
$this->_db->quote($pref_id)); |
$result = $this->_db->getOne($query); |
if (DB::isError($result)) { |
$this->_lastError = "DB Error: ".$result->getMessage(); |
return false; |
} else { |
return (bool)$result; |
} |
} |
/** |
* Does anything needed to prepare a value for saving in the database. |
* |
* @param mixed $value The value to be saved. |
* @return string The value in a format valid for saving to the database. |
* @access private |
*/ |
function _pack($value) |
{ |
if ($this->_serialize) { |
return serialize($value); |
} else { |
return $value; |
} |
} |
/** |
* Does anything needed to create a value of the preference, such as unserializing. |
* |
* @param string $value The value of the preference. |
* @return mixed The unpacked version of the preference. |
* @access private |
*/ |
function _unpack($value) |
{ |
if ($this->_serialize) { |
return unserialize($value); |
} else { |
return $value; |
} |
} |
} |
?> |
/branches/v1.3-critias/bibliotheque/pear/Auth/RADIUS.php |
---|
New file |
0,0 → 1,964 |
<?php |
/* vim: set expandtab tabstop=4 shiftwidth=4: */ |
/* |
Copyright (c) 2003, Michael Bretterklieber <michael@bretterklieber.com> |
All rights reserved. |
Redistribution and use in source and binary forms, with or without |
modification, are permitted provided that the following conditions |
are met: |
1. Redistributions of source code must retain the above copyright |
notice, this list of conditions and the following disclaimer. |
2. Redistributions in binary form must reproduce the above copyright |
notice, this list of conditions and the following disclaimer in the |
documentation and/or other materials provided with the distribution. |
3. The names of the authors may not be used to endorse or promote products |
derived from this software without specific prior written permission. |
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND |
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, |
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, |
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY |
OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING |
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, |
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
This code cannot simply be copied and put under the GNU Public License or |
any other GPL-like (LGPL, GPL2) License. |
$Id: RADIUS.php,v 1.3 2003/05/02 11:04:02 mbretter Exp $ |
*/ |
require_once 'PEAR.php'; |
/** |
* Client implementation of RADIUS. This are wrapper classes for |
* the RADIUS PECL. |
* Provides RADIUS Authentication (RFC2865) and RADIUS Accounting (RFC2866). |
* |
* @package Auth_RADIUS |
* @author Michael Bretterklieber <michael@bretterklieber.com> |
* @access public |
* @version $Revision: 1.3 $ |
*/ |
/** |
* class Auth_RADIUS |
* |
* Abstract base class for RADIUS |
* |
* @package Auth_RADIUS |
*/ |
class Auth_RADIUS extends PEAR { |
/** |
* List of RADIUS servers. |
* @var array |
* @see addServer(), putServer() |
*/ |
var $_servers = array(); |
/** |
* Path to the configuration-file. |
* @var string |
* @see setConfigFile() |
*/ |
var $_configfile = null; |
/** |
* Resource. |
* @var resource |
* @see open(), close() |
*/ |
var $res = null; |
/** |
* Username for authentication and accounting requests. |
* @var string |
*/ |
var $username = null; |
/** |
* Password for plaintext-authentication (PAP). |
* @var string |
*/ |
var $password = null; |
/** |
* List of known attributes. |
* @var array |
* @see dumpAttributes(), getAttributes() |
*/ |
var $attributes = array(); |
/** |
* List of raw attributes. |
* @var array |
* @see dumpAttributes(), getAttributes() |
*/ |
var $rawAttributes = array(); |
/** |
* List of raw vendor specific attributes. |
* @var array |
* @see dumpAttributes(), getAttributes() |
*/ |
var $rawVendorAttributes = array(); |
/** |
* Constructor |
* |
* Loads the RADIUS PECL/extension |
* |
* @return void |
*/ |
function Auth_RADIUS() |
{ |
$this->PEAR(); |
$this->loadExtension('radius'); |
} |
/** |
* Adds a RADIUS server to the list of servers for requests. |
* |
* At most 10 servers may be specified. When multiple servers |
* are given, they are tried in round-robin fashion until a |
* valid response is received |
* |
* @access public |
* @param string $servername Servername or IP-Address |
* @param integer $port Portnumber |
* @param string $sharedSecret Shared secret |
* @param integer $timeout Timeout for each request |
* @param integer $maxtries Max. retries for each request |
* @return void |
*/ |
function addServer($servername = 'localhost', $port = 0, $sharedSecret = 'testing123', $timeout = 3, $maxtries = 3) |
{ |
$this->_servers[] = array($servername, $port, $sharedSecret, $timeout, $maxtries); |
} |
/** |
* Returns an error message, if an error occurred. |
* |
* @access public |
* @return string |
*/ |
function getError() |
{ |
return radius_strerror($this->res); |
} |
/** |
* Sets the configuration-file. |
* |
* @access public |
* @param string $file Path to the configuration file |
* @return void |
*/ |
function setConfigfile($file) |
{ |
$this->_configfile = $file; |
} |
/** |
* Puts an attribute. |
* |
* @access public |
* @param integer $attrib Attribute-number |
* @param mixed $port Attribute-value |
* @param type $type Attribute-type |
* @return bool true on success, false on error |
*/ |
function putAttribute($attrib, $value, $type = null) |
{ |
if ($type == null) { |
$type = gettype($value); |
} |
switch ($type) { |
case 'integer': |
return radius_put_int($this->res, $attrib, $value); |
case 'addr': |
return radius_put_addr($this->res, $attrib, $value); |
case 'string': |
default: |
return radius_put_attr($this->res, $attrib, $value); |
} |
} |
/** |
* Puts a vendor-specific attribute. |
* |
* @access public |
* @param integer $vendor Vendor (MSoft, Cisco, ...) |
* @param integer $attrib Attribute-number |
* @param mixed $port Attribute-value |
* @param type $type Attribute-type |
* @return bool true on success, false on error |
*/ |
function putVendorAttribute($vendor, $attrib, $value, $type = null) |
{ |
if ($type == null) { |
$type = gettype($value); |
} |
switch ($type) { |
case 'integer': |
return radius_put_vendor_int($this->res, $vendor, $attrib, $value); |
case 'addr': |
return radius_put_vendor_addr($this->res, $vendor,$attrib, $value); |
case 'string': |
default: |
return radius_put_vendor_attr($this->res, $vendor, $attrib, $value); |
} |
} |
/** |
* Prints known attributes received from the server. |
* |
* @access public |
*/ |
function dumpAttributes() |
{ |
foreach ($this->attributes as $name => $data) { |
echo "$name:$data<br>\n"; |
} |
} |
/** |
* Overwrite this. |
* |
* @access public |
*/ |
function open() |
{ |
} |
/** |
* Overwrite this. |
* |
* @access public |
*/ |
function createRequest() |
{ |
} |
/** |
* Puts standard attributes. |
* |
* @access public |
*/ |
function putStandardAttributes() |
{ |
if (isset($_SERVER)) { |
$var = &$_SERVER; |
} else { |
$var = &$GLOBALS['HTTP_SERVER_VARS']; |
} |
$this->putAttribute(RADIUS_NAS_IDENTIFIER, isset($var['HTTP_HOST']) ? $var['HTTP_HOST'] : 'localhost'); |
$this->putAttribute(RADIUS_NAS_PORT_TYPE, RADIUS_VIRTUAL); |
$this->putAttribute(RADIUS_SERVICE_TYPE, RADIUS_FRAMED); |
$this->putAttribute(RADIUS_FRAMED_PROTOCOL, RADIUS_PPP); |
$this->putAttribute(RADIUS_CALLING_STATION_ID, isset($var['REMOTE_HOST']) ? $var['REMOTE_HOST'] : '127.0.0.1'); |
} |
/** |
* Puts custom attributes. |
* |
* @access public |
*/ |
function putAuthAttributes() |
{ |
if (isset($this->username)) { |
$this->putAttribute(RADIUS_USER_NAME, $this->username); |
} |
} |
/** |
* Configures the radius library. |
* |
* @access public |
* @param string $servername Servername or IP-Address |
* @param integer $port Portnumber |
* @param string $sharedSecret Shared secret |
* @param integer $timeout Timeout for each request |
* @param integer $maxtries Max. retries for each request |
* @return bool true on success, false on error |
* @see addServer() |
*/ |
function putServer($servername, $port = 0, $sharedsecret = 'testing123', $timeout = 3, $maxtries = 3) |
{ |
if (!radius_add_server($this->res, $servername, $port, $sharedsecret, $timeout, $maxtries)) { |
return false; |
} |
return true; |
} |
/** |
* Configures the radius library via external configurationfile |
* |
* @access public |
* @param string $servername Servername or IP-Address |
* @return bool true on success, false on error |
*/ |
function putConfigfile($file) |
{ |
if (!radius_config($this->res, $file)) { |
return false; |
} |
return true; |
} |
/** |
* Initiates a RADIUS request. |
* |
* @access public |
* @return bool true on success, false on errors |
*/ |
function start() |
{ |
if (!$this->open()) { |
return false; |
} |
foreach ($this->_servers as $s) { |
// Servername, port, sharedsecret, timeout, retries |
if (!$this->putServer($s[0], $s[1], $s[2], $s[3], $s[4])) { |
return false; |
} |
} |
if (!empty($this->_configfile)) { |
if (!$this->putConfigfile($this->_configfile)) { |
return false; |
} |
} |
$this->createRequest(); |
$this->putStandardAttributes(); |
$this->putAuthAttributes(); |
return true; |
} |
/** |
* Sends a prepared RADIUS request and waits for a response |
* |
* @access public |
* @return mixed true on success, false on reject, PEAR_Error on error |
*/ |
function send() |
{ |
$req = radius_send_request($this->res); |
if (!$req) { |
return $this->raiseError('Error sending request: ' . $this->getError()); |
} |
switch($req) { |
case RADIUS_ACCESS_ACCEPT: |
if (is_subclass_of($this, 'auth_radius_acct')) { |
return $this->raiseError('RADIUS_ACCESS_ACCEPT is unexpected for accounting'); |
} |
return true; |
case RADIUS_ACCESS_REJECT: |
return false; |
case RADIUS_ACCOUNTING_RESPONSE: |
if (is_subclass_of($this, 'auth_radius_pap')) { |
return $this->raiseError('RADIUS_ACCOUNTING_RESPONSE is unexpected for authentication'); |
} |
return true; |
default: |
return $this->raiseError("Unexpected return value: $req"); |
} |
} |
/** |
* Reads all received attributes after sending the request. |
* |
* This methos stores know attributes in the property attributes, |
* all attributes (including known attibutes) are stored in rawAttributes |
* or rawVendorAttributes. |
* NOTE: call this functio also even if the request was rejected, because the |
* Server returns usualy an errormessage |
* |
* @access public |
* @return bool true on success, false on error |
*/ |
function getAttributes() |
{ |
while ($attrib = radius_get_attr($this->res)) { |
if (!is_array($attrib)) { |
return false; |
} |
$attr = $attrib['attr']; |
$data = $attrib['data']; |
$this->rawAttributes[$attr] = $data; |
switch ($attr) { |
case RADIUS_FRAMED_IP_ADDRESS: |
$this->attributes['framed_ip'] = radius_cvt_addr($data); |
break; |
case RADIUS_FRAMED_IP_NETMASK: |
$this->attributes['framed_mask'] = radius_cvt_addr($data); |
break; |
case RADIUS_FRAMED_MTU: |
$this->attributes['framed_mtu'] = radius_cvt_int($data); |
break; |
case RADIUS_FRAMED_COMPRESSION: |
$this->attributes['framed_compression'] = radius_cvt_int($data); |
break; |
case RADIUS_SESSION_TIMEOUT: |
$this->attributes['session_timeout'] = radius_cvt_int($data); |
break; |
case RADIUS_IDLE_TIMEOUT: |
$this->attributes['idle_timeout'] = radius_cvt_int($data); |
break; |
case RADIUS_SERVICE_TYPE: |
$this->attributes['service_type'] = radius_cvt_int($data); |
break; |
case RADIUS_CLASS: |
$this->attributes['class'] = radius_cvt_int($data); |
break; |
case RADIUS_FRAMED_PROTOCOL: |
$this->attributes['framed_protocol'] = radius_cvt_int($data); |
break; |
case RADIUS_FRAMED_ROUTING: |
$this->attributes['framed_routing'] = radius_cvt_int($data); |
break; |
case RADIUS_FILTER_ID: |
$this->attributes['filter_id'] = radius_cvt_string($data); |
break; |
case RADIUS_VENDOR_SPECIFIC: |
$attribv = radius_get_vendor_attr($data); |
if (!is_array($attribv)) { |
return false; |
} |
$vendor = $attribv['vendor']; |
$attrv = $attribv['attr']; |
$datav = $attribv['data']; |
$this->rawVendorAttributes[$vendor][$attrv] = $datav; |
if ($vendor == RADIUS_VENDOR_MICROSOFT) { |
switch ($attrv) { |
case RADIUS_MICROSOFT_MS_CHAP2_SUCCESS: |
$this->attributes['ms_chap2_success'] = radius_cvt_string($datav); |
break; |
case RADIUS_MICROSOFT_MS_CHAP_ERROR: |
$this->attributes['ms_chap_error'] = radius_cvt_string(substr($datav,1)); |
break; |
case RADIUS_MICROSOFT_MS_CHAP_DOMAIN: |
$this->attributes['ms_chap_domain'] = radius_cvt_string($datav); |
break; |
case RADIUS_MICROSOFT_MS_MPPE_ENCRYPTION_POLICY: |
$this->attributes['ms_mppe_encryption_policy'] = radius_cvt_int($datav); |
break; |
case RADIUS_MICROSOFT_MS_MPPE_ENCRYPTION_TYPES: |
$this->attributes['ms_mppe_encryption_types'] = radius_cvt_int($datav); |
break; |
case RADIUS_MICROSOFT_MS_CHAP_MPPE_KEYS: |
$demangled = radius_demangle($this->res, $datav); |
$this->attributes['ms_chap_mppe_lm_key'] = substr($demangled, 0, 8); |
$this->attributes['ms_chap_mppe_nt_key'] = substr($demangled, 8, RADIUS_MPPE_KEY_LEN); |
break; |
case RADIUS_MICROSOFT_MS_MPPE_SEND_KEY: |
$this->attributes['ms_chap_mppe_send_key'] = radius_demangle_mppe_key($this->res, $datav); |
break; |
case RADIUS_MICROSOFT_MS_MPPE_RECV_KEY: |
$this->attributes['ms_chap_mppe_recv_key'] = radius_demangle_mppe_key($this->res, $datav); |
break; |
case RADIUS_MICROSOFT_MS_PRIMARY_DNS_SERVER: |
$this->attributes['ms_primary_dns_server'] = radius_cvt_string($datav); |
break; |
} |
} |
break; |
} |
} |
return true; |
} |
/** |
* Frees resources. |
* |
* Calling this method is always a good idea, because all security relevant |
* attributes are filled with Nullbytes to leave nothing in the mem. |
* |
* @access public |
*/ |
function close() |
{ |
if ($this->res != null) { |
radius_close($this->res); |
$this->res = null; |
} |
$this->username = str_repeat("\0", strlen($this->username)); |
$this->password = str_repeat("\0", strlen($this->password)); |
} |
} |
/** |
* class Auth_RADIUS_PAP |
* |
* Class for authenticating using PAP (Plaintext) |
* |
* @package Auth_RADIUS |
*/ |
class Auth_RADIUS_PAP extends Auth_RADIUS |
{ |
/** |
* Constructor |
* |
* @param string $username Username |
* @param string $password Password |
* @return void |
*/ |
function Auth_RADIUS_PAP($username = null, $password = null) |
{ |
$this->Auth_RADIUS(); |
$this->username = $username; |
$this->password = $password; |
} |
/** |
* Creates a RADIUS resource |
* |
* Creates a RADIUS resource for authentication. This should be the first |
* call before you make any other things with the library. |
* |
* @return bool true on success, false on error |
*/ |
function open() |
{ |
$this->res = radius_auth_open(); |
if (!$this->res) { |
return false; |
} |
return true; |
} |
/** |
* Creates an authentication request |
* |
* Creates an authentication request. |
* You MUST call this method before you can put any attribute |
* |
* @return bool true on success, false on error |
*/ |
function createRequest() |
{ |
if (!radius_create_request($this->res, RADIUS_ACCESS_REQUEST)) { |
return false; |
} |
return true; |
} |
/** |
* Put authentication specific attributes |
* |
* @return void |
*/ |
function putAuthAttributes() |
{ |
if (isset($this->username)) { |
$this->putAttribute(RADIUS_USER_NAME, $this->username); |
} |
if (isset($this->password)) { |
$this->putAttribute(RADIUS_USER_PASSWORD, $this->password); |
} |
} |
} |
/** |
* class Auth_RADIUS_CHAP_MD5 |
* |
* Class for authenticating using CHAP-MD5 see RFC1994. |
* Instead og the plaintext password the challenge and |
* the response are needed. |
* |
* @package Auth_RADIUS |
*/ |
class Auth_RADIUS_CHAP_MD5 extends Auth_RADIUS_PAP |
{ |
/** |
* 8 Bytes binary challenge |
* @var string |
*/ |
var $challenge = null; |
/** |
* 16 Bytes MD5 response binary |
* @var string |
*/ |
var $response = null; |
/** |
* Id of the authentication request. Should incremented after every request. |
* @var integer |
*/ |
var $chapid = 1; |
/** |
* Constructor |
* |
* @param string $username Username |
* @param string $challenge 8 Bytes Challenge (binary) |
* @param integer $chapid Requestnumber |
* @return void |
*/ |
function Auth_RADIUS_CHAP_MD5($username = null, $challenge = null, $chapid = 1) |
{ |
$this->Auth_RADIUS_PAP(); |
$this->username = $username; |
$this->challenge = $challenge; |
$this->chapid = $chapid; |
} |
/** |
* Put CHAP-MD5 specific attributes |
* |
* For authenticating using CHAP-MD5 via RADIUS you have to put the challenge |
* and the response. The chapid is inserted in the first byte of the response. |
* |
* @return void |
*/ |
function putAuthAttributes() |
{ |
if (isset($this->username)) { |
$this->putAttribute(RADIUS_USER_NAME, $this->username); |
} |
if (isset($this->response)) { |
$response = pack('C', $this->chapid) . $this->response; |
$this->putAttribute(RADIUS_CHAP_PASSWORD, $response); |
} |
if (isset($this->challenge)) { |
$this->putAttribute(RADIUS_CHAP_CHALLENGE, $this->challenge); |
} |
} |
/** |
* Frees resources. |
* |
* Calling this method is always a good idea, because all security relevant |
* attributes are filled with Nullbytes to leave nothing in the mem. |
* |
* @access public |
*/ |
function close() |
{ |
Auth_RADIUS_PAP::close(); |
$this->challenge = str_repeat("\0", strlen($this->challenge)); |
$this->response = str_repeat("\0", strlen($this->response)); |
} |
} |
/** |
* class Auth_RADIUS_MSCHAPv1 |
* |
* Class for authenticating using MS-CHAPv1 see RFC2433 |
* |
* @package Auth_RADIUS |
*/ |
class Auth_RADIUS_MSCHAPv1 extends Auth_RADIUS_CHAP_MD5 |
{ |
/** |
* LAN-Manager-Response |
* @var string |
*/ |
var $lmResponse = null; |
/** |
* Wether using deprecated LM-Responses or not. |
* 0 = use LM-Response, 1 = use NT-Response |
* @var bool |
*/ |
var $flags = 1; |
/** |
* Put MS-CHAPv1 specific attributes |
* |
* For authenticating using MS-CHAPv1 via RADIUS you have to put the challenge |
* and the response. The response has this structure: |
* struct rad_mschapvalue { |
* u_char ident; |
* u_char flags; |
* u_char lm_response[24]; |
* u_char response[24]; |
* }; |
* |
* @return void |
*/ |
function putAuthAttributes() |
{ |
if (isset($this->username)) { |
$this->putAttribute(RADIUS_USER_NAME, $this->username); |
} |
if (isset($this->response) || isset($this->lmResponse)) { |
$lmResp = isset($this->lmResponse) ? $this->lmResponse : str_repeat ("\0", 24); |
$ntResp = isset($this->response) ? $this->response : str_repeat ("\0", 24); |
$resp = pack('CC', $this->chapid, $this->flags) . $lmResp . $ntResp; |
$this->putVendorAttribute(RADIUS_VENDOR_MICROSOFT, RADIUS_MICROSOFT_MS_CHAP_RESPONSE, $resp); |
} |
if (isset($this->challenge)) { |
$this->putVendorAttribute(RADIUS_VENDOR_MICROSOFT, RADIUS_MICROSOFT_MS_CHAP_CHALLENGE, $this->challenge); |
} |
} |
} |
/** |
* class Auth_RADIUS_MSCHAPv2 |
* |
* Class for authenticating using MS-CHAPv2 see RFC2759 |
* |
* @package Auth_RADIUS |
*/ |
class Auth_RADIUS_MSCHAPv2 extends Auth_RADIUS_MSCHAPv1 |
{ |
/** |
* 16 Bytes binary challenge |
* @var string |
*/ |
var $challenge = null; |
/** |
* 16 Bytes binary Peer Challenge |
* @var string |
*/ |
var $peerChallenge = null; |
/** |
* Put MS-CHAPv2 specific attributes |
* |
* For authenticating using MS-CHAPv1 via RADIUS you have to put the challenge |
* and the response. The response has this structure: |
* struct rad_mschapv2value { |
* u_char ident; |
* u_char flags; |
* u_char pchallenge[16]; |
* u_char reserved[8]; |
* u_char response[24]; |
* }; |
* where pchallenge is the peer challenge. Like for MS-CHAPv1 we set the flags field to 1. |
* @return void |
*/ |
function putAuthAttributes() |
{ |
if (isset($this->username)) { |
$this->putAttribute(RADIUS_USER_NAME, $this->username); |
} |
if (isset($this->response) && isset($this->peerChallenge)) { |
// Response: chapid, flags (1 = use NT Response), Peer challenge, reserved, Response |
$resp = pack('CCa16a8a24',$this->chapid , 1, $this->peerChallenge, str_repeat("\0", 8), $this->response); |
$this->putVendorAttribute(RADIUS_VENDOR_MICROSOFT, RADIUS_MICROSOFT_MS_CHAP2_RESPONSE, $resp); |
} |
if (isset($this->challenge)) { |
$this->putVendorAttribute(RADIUS_VENDOR_MICROSOFT, RADIUS_MICROSOFT_MS_CHAP_CHALLENGE, $this->challenge); |
} |
} |
/** |
* Frees resources. |
* |
* Calling this method is always a good idea, because all security relevant |
* attributes are filled with Nullbytes to leave nothing in the mem. |
* |
* @access public |
*/ |
function close() |
{ |
Auth_RADIUS_MSCHAPv1::close(); |
$this->peerChallenge = str_repeat("\0", strlen($this->peerChallenge)); |
} |
} |
/** |
* class Auth_RADIUS_Acct |
* |
* Class for RADIUS accounting |
* |
* @package Auth_RADIUS |
*/ |
class Auth_RADIUS_Acct extends Auth_RADIUS |
{ |
/** |
* Defines where the Authentication was made, possible values are: |
* RADIUS_AUTH_RADIUS, RADIUS_AUTH_LOCAL, RADIUS_AUTH_REMOTE |
* @var integer |
*/ |
var $authentic = null; |
/** |
* Defines the type of the accounting request, on of: |
* RADIUS_START, RADIUS_STOP, RADIUS_ACCOUNTING_ON, RADIUS_ACCOUNTING_OFF |
* @var integer |
*/ |
var $status_type = null; |
/** |
* The time the user was logged in in seconds |
* @var integer |
*/ |
var $session_time = null; |
/** |
* A uniq identifier for the session of the user, maybe the PHP-Session-Id |
* @var string |
*/ |
var $session_id = null; |
/** |
* Constructor |
* |
* Generates a predefined session_id. We use the Remote-Address, the PID, and the Current user. |
* @return void |
*/ |
function Auth_RADIUS_Acct() |
{ |
$this->Auth_RADIUS(); |
if (isset($_SERVER)) { |
$var = &$_SERVER; |
} else { |
$var = &$GLOBALS['HTTP_SERVER_VARS']; |
} |
$this->session_id = sprintf("%s:%d-%s", isset($var['REMOTE_ADDR']) ? $var['REMOTE_ADDR'] : '127.0.0.1' , getmypid(), get_current_user()); |
} |
/** |
* Creates a RADIUS resource |
* |
* Creates a RADIUS resource for accounting. This should be the first |
* call before you make any other things with the library. |
* |
* @return bool true on success, false on error |
*/ |
function open() |
{ |
$this->res = radius_acct_open(); |
if (!$this->res) { |
return false; |
} |
return true; |
} |
/** |
* Creates an accounting request |
* |
* Creates an accounting request. |
* You MUST call this method before you can put any attribute. |
* |
* @return bool true on success, false on error |
*/ |
function createRequest() |
{ |
if (!radius_create_request($this->res, RADIUS_ACCOUNTING_REQUEST)) { |
return false; |
} |
return true; |
} |
/** |
* Put attributes for accounting. |
* |
* Here we put some accounting values. There many more attributes for accounting, |
* but for web-applications only certain attributes make sense. |
* @return void |
*/ |
function putAuthAttributes() |
{ |
$this->putAttribute(RADIUS_ACCT_SESSION_ID, $this->session_id); |
$this->putAttribute(RADIUS_ACCT_STATUS_TYPE, $this->status_type); |
if (isset($this->session_time) && $this->status_type == RADIUS_STOP) { |
$this->putAttribute(RADIUS_ACCT_SESSION_TIME, $this->session_time); |
} |
if (isset($this->authentic)) { |
$this->putAttribute(RADIUS_ACCT_AUTHENTIC, $this->authentic); |
} |
} |
} |
/** |
* class Auth_RADIUS_Acct_Start |
* |
* Class for RADIUS accounting. Its usualy used, after the user has logged in. |
* |
* @package Auth_RADIUS |
*/ |
class Auth_RADIUS_Acct_Start extends Auth_RADIUS_Acct |
{ |
/** |
* Defines the type of the accounting request. |
* It is set to RADIUS_START by default in this class. |
* @var integer |
*/ |
var $status_type = Auth_RADIUS_Acct_Stop; |
} |
/** |
* class Auth_RADIUS_Acct_Start |
* |
* Class for RADIUS accounting. Its usualy used, after the user has logged out. |
* |
* @package Auth_RADIUS |
*/ |
class Auth_RADIUS_Acct_Stop extends Auth_RADIUS_Acct |
{ |
/** |
* Defines the type of the accounting request. |
* It is set to RADIUS_STOP by default in this class. |
* @var integer |
*/ |
var $status_type = RADIUS_STOP; |
} |
?> |
/branches/v1.3-critias/bibliotheque/pear/OS/Guess.php |
---|
New file |
0,0 → 1,337 |
<?php |
/** |
* The OS_Guess class |
* |
* PHP versions 4 and 5 |
* |
* @category pear |
* @package PEAR |
* @author Stig Bakken <ssb@php.net> |
* @author Gregory Beaver <cellog@php.net> |
* @copyright 1997-2009 The Authors |
* @license http://opensource.org/licenses/bsd-license.php New BSD License |
* @link http://pear.php.net/package/PEAR |
* @since File available since PEAR 0.1 |
*/ |
// {{{ uname examples |
// php_uname() without args returns the same as 'uname -a', or a PHP-custom |
// string for Windows. |
// PHP versions prior to 4.3 return the uname of the host where PHP was built, |
// as of 4.3 it returns the uname of the host running the PHP code. |
// |
// PC RedHat Linux 7.1: |
// Linux host.example.com 2.4.2-2 #1 Sun Apr 8 20:41:30 EDT 2001 i686 unknown |
// |
// PC Debian Potato: |
// Linux host 2.4.17 #2 SMP Tue Feb 12 15:10:04 CET 2002 i686 unknown |
// |
// PC FreeBSD 3.3: |
// FreeBSD host.example.com 3.3-STABLE FreeBSD 3.3-STABLE #0: Mon Feb 21 00:42:31 CET 2000 root@example.com:/usr/src/sys/compile/CONFIG i386 |
// |
// PC FreeBSD 4.3: |
// FreeBSD host.example.com 4.3-RELEASE FreeBSD 4.3-RELEASE #1: Mon Jun 25 11:19:43 EDT 2001 root@example.com:/usr/src/sys/compile/CONFIG i386 |
// |
// PC FreeBSD 4.5: |
// FreeBSD host.example.com 4.5-STABLE FreeBSD 4.5-STABLE #0: Wed Feb 6 23:59:23 CET 2002 root@example.com:/usr/src/sys/compile/CONFIG i386 |
// |
// PC FreeBSD 4.5 w/uname from GNU shellutils: |
// FreeBSD host.example.com 4.5-STABLE FreeBSD 4.5-STABLE #0: Wed Feb i386 unknown |
// |
// HP 9000/712 HP-UX 10: |
// HP-UX iq B.10.10 A 9000/712 2008429113 two-user license |
// |
// HP 9000/712 HP-UX 10 w/uname from GNU shellutils: |
// HP-UX host B.10.10 A 9000/712 unknown |
// |
// IBM RS6000/550 AIX 4.3: |
// AIX host 3 4 000003531C00 |
// |
// AIX 4.3 w/uname from GNU shellutils: |
// AIX host 3 4 000003531C00 unknown |
// |
// SGI Onyx IRIX 6.5 w/uname from GNU shellutils: |
// IRIX64 host 6.5 01091820 IP19 mips |
// |
// SGI Onyx IRIX 6.5: |
// IRIX64 host 6.5 01091820 IP19 |
// |
// SparcStation 20 Solaris 8 w/uname from GNU shellutils: |
// SunOS host.example.com 5.8 Generic_108528-12 sun4m sparc |
// |
// SparcStation 20 Solaris 8: |
// SunOS host.example.com 5.8 Generic_108528-12 sun4m sparc SUNW,SPARCstation-20 |
// |
// Mac OS X (Darwin) |
// Darwin home-eden.local 7.5.0 Darwin Kernel Version 7.5.0: Thu Aug 5 19:26:16 PDT 2004; root:xnu/xnu-517.7.21.obj~3/RELEASE_PPC Power Macintosh |
// |
// Mac OS X early versions |
// |
// }}} |
/* TODO: |
* - define endianness, to allow matchSignature("bigend") etc. |
*/ |
/** |
* Retrieves information about the current operating system |
* |
* This class uses php_uname() to grok information about the current OS |
* |
* @category pear |
* @package PEAR |
* @author Stig Bakken <ssb@php.net> |
* @author Gregory Beaver <cellog@php.net> |
* @copyright 1997-2009 The Authors |
* @license http://opensource.org/licenses/bsd-license.php New BSD License |
* @version Release: 1.10.1 |
* @link http://pear.php.net/package/PEAR |
* @since Class available since Release 0.1 |
*/ |
class OS_Guess |
{ |
var $sysname; |
var $nodename; |
var $cpu; |
var $release; |
var $extra; |
function __construct($uname = null) |
{ |
list($this->sysname, |
$this->release, |
$this->cpu, |
$this->extra, |
$this->nodename) = $this->parseSignature($uname); |
} |
function parseSignature($uname = null) |
{ |
static $sysmap = array( |
'HP-UX' => 'hpux', |
'IRIX64' => 'irix', |
); |
static $cpumap = array( |
'i586' => 'i386', |
'i686' => 'i386', |
'ppc' => 'powerpc', |
); |
if ($uname === null) { |
$uname = php_uname(); |
} |
$parts = preg_split('/\s+/', trim($uname)); |
$n = count($parts); |
$release = $machine = $cpu = ''; |
$sysname = $parts[0]; |
$nodename = $parts[1]; |
$cpu = $parts[$n-1]; |
$extra = ''; |
if ($cpu == 'unknown') { |
$cpu = $parts[$n - 2]; |
} |
switch ($sysname) { |
case 'AIX' : |
$release = "$parts[3].$parts[2]"; |
break; |
case 'Windows' : |
switch ($parts[1]) { |
case '95/98': |
$release = '9x'; |
break; |
default: |
$release = $parts[1]; |
break; |
} |
$cpu = 'i386'; |
break; |
case 'Linux' : |
$extra = $this->_detectGlibcVersion(); |
// use only the first two digits from the kernel version |
$release = preg_replace('/^([0-9]+\.[0-9]+).*/', '\1', $parts[2]); |
break; |
case 'Mac' : |
$sysname = 'darwin'; |
$nodename = $parts[2]; |
$release = $parts[3]; |
if ($cpu == 'Macintosh') { |
if ($parts[$n - 2] == 'Power') { |
$cpu = 'powerpc'; |
} |
} |
break; |
case 'Darwin' : |
if ($cpu == 'Macintosh') { |
if ($parts[$n - 2] == 'Power') { |
$cpu = 'powerpc'; |
} |
} |
$release = preg_replace('/^([0-9]+\.[0-9]+).*/', '\1', $parts[2]); |
break; |
default: |
$release = preg_replace('/-.*/', '', $parts[2]); |
break; |
} |
if (isset($sysmap[$sysname])) { |
$sysname = $sysmap[$sysname]; |
} else { |
$sysname = strtolower($sysname); |
} |
if (isset($cpumap[$cpu])) { |
$cpu = $cpumap[$cpu]; |
} |
return array($sysname, $release, $cpu, $extra, $nodename); |
} |
function _detectGlibcVersion() |
{ |
static $glibc = false; |
if ($glibc !== false) { |
return $glibc; // no need to run this multiple times |
} |
$major = $minor = 0; |
include_once "System.php"; |
// Use glibc's <features.h> header file to |
// get major and minor version number: |
if (@file_exists('/usr/include/features.h') && |
@is_readable('/usr/include/features.h')) { |
if (!@file_exists('/usr/bin/cpp') || !@is_executable('/usr/bin/cpp')) { |
$features_file = fopen('/usr/include/features.h', 'rb'); |
while (!feof($features_file)) { |
$line = fgets($features_file, 8192); |
if (!$line || (strpos($line, '#define') === false)) { |
continue; |
} |
if (strpos($line, '__GLIBC__')) { |
// major version number #define __GLIBC__ version |
$line = preg_split('/\s+/', $line); |
$glibc_major = trim($line[2]); |
if (isset($glibc_minor)) { |
break; |
} |
continue; |
} |
if (strpos($line, '__GLIBC_MINOR__')) { |
// got the minor version number |
// #define __GLIBC_MINOR__ version |
$line = preg_split('/\s+/', $line); |
$glibc_minor = trim($line[2]); |
if (isset($glibc_major)) { |
break; |
} |
continue; |
} |
} |
fclose($features_file); |
if (!isset($glibc_major) || !isset($glibc_minor)) { |
return $glibc = ''; |
} |
return $glibc = 'glibc' . trim($glibc_major) . "." . trim($glibc_minor) ; |
} // no cpp |
$tmpfile = System::mktemp("glibctest"); |
$fp = fopen($tmpfile, "w"); |
fwrite($fp, "#include <features.h>\n__GLIBC__ __GLIBC_MINOR__\n"); |
fclose($fp); |
$cpp = popen("/usr/bin/cpp $tmpfile", "r"); |
while ($line = fgets($cpp, 1024)) { |
if ($line{0} == '#' || trim($line) == '') { |
continue; |
} |
if (list($major, $minor) = explode(' ', trim($line))) { |
break; |
} |
} |
pclose($cpp); |
unlink($tmpfile); |
} // features.h |
if (!($major && $minor) && @is_link('/lib/libc.so.6')) { |
// Let's try reading the libc.so.6 symlink |
if (preg_match('/^libc-(.*)\.so$/', basename(readlink('/lib/libc.so.6')), $matches)) { |
list($major, $minor) = explode('.', $matches[1]); |
} |
} |
if (!($major && $minor)) { |
return $glibc = ''; |
} |
return $glibc = "glibc{$major}.{$minor}"; |
} |
function getSignature() |
{ |
if (empty($this->extra)) { |
return "{$this->sysname}-{$this->release}-{$this->cpu}"; |
} |
return "{$this->sysname}-{$this->release}-{$this->cpu}-{$this->extra}"; |
} |
function getSysname() |
{ |
return $this->sysname; |
} |
function getNodename() |
{ |
return $this->nodename; |
} |
function getCpu() |
{ |
return $this->cpu; |
} |
function getRelease() |
{ |
return $this->release; |
} |
function getExtra() |
{ |
return $this->extra; |
} |
function matchSignature($match) |
{ |
$fragments = is_array($match) ? $match : explode('-', $match); |
$n = count($fragments); |
$matches = 0; |
if ($n > 0) { |
$matches += $this->_matchFragment($fragments[0], $this->sysname); |
} |
if ($n > 1) { |
$matches += $this->_matchFragment($fragments[1], $this->release); |
} |
if ($n > 2) { |
$matches += $this->_matchFragment($fragments[2], $this->cpu); |
} |
if ($n > 3) { |
$matches += $this->_matchFragment($fragments[3], $this->extra); |
} |
return ($matches == $n); |
} |
function _matchFragment($fragment, $value) |
{ |
if (strcspn($fragment, '*?') < strlen($fragment)) { |
$reg = '/^' . str_replace(array('*', '?', '/'), array('.*', '.', '\\/'), $fragment) . '\\z/'; |
return preg_match($reg, $value); |
} |
return ($fragment == '*' || !strcasecmp($fragment, $value)); |
} |
} |
/* |
* Local Variables: |
* indent-tabs-mode: nil |
* c-basic-offset: 4 |
* End: |
*/ |
/branches/v1.3-critias/bibliotheque/pear/DB/storage.php |
---|
New file |
0,0 → 1,506 |
<?php |
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */ |
/** |
* Provides an object interface to a table row |
* |
* PHP version 5 |
* |
* LICENSE: This source file is subject to version 3.0 of the PHP license |
* that is available through the world-wide-web at the following URI: |
* http://www.php.net/license/3_0.txt. If you did not receive a copy of |
* the PHP License and are unable to obtain it through the web, please |
* send a note to license@php.net so we can mail you a copy immediately. |
* |
* @category Database |
* @package DB |
* @author Stig Bakken <stig@php.net> |
* @copyright 1997-2007 The PHP Group |
* @license http://www.php.net/license/3_0.txt PHP License 3.0 |
* @version CVS: $Id$ |
* @link http://pear.php.net/package/DB |
*/ |
/** |
* Obtain the DB class so it can be extended from |
*/ |
require_once 'DB.php'; |
/** |
* Provides an object interface to a table row |
* |
* It lets you add, delete and change rows using objects rather than SQL |
* statements. |
* |
* @category Database |
* @package DB |
* @author Stig Bakken <stig@php.net> |
* @copyright 1997-2007 The PHP Group |
* @license http://www.php.net/license/3_0.txt PHP License 3.0 |
* @version Release: 1.9.2 |
* @link http://pear.php.net/package/DB |
*/ |
class DB_storage extends PEAR |
{ |
// {{{ properties |
/** the name of the table (or view, if the backend database supports |
updates in views) we hold data from */ |
var $_table = null; |
/** which column(s) in the table contains primary keys, can be a |
string for single-column primary keys, or an array of strings |
for multiple-column primary keys */ |
var $_keycolumn = null; |
/** DB connection handle used for all transactions */ |
var $_dbh = null; |
/** an assoc with the names of database fields stored as properties |
in this object */ |
var $_properties = array(); |
/** an assoc with the names of the properties in this object that |
have been changed since they were fetched from the database */ |
var $_changes = array(); |
/** flag that decides if data in this object can be changed. |
objects that don't have their table's key column in their |
property lists will be flagged as read-only. */ |
var $_readonly = false; |
/** function or method that implements a validator for fields that |
are set, this validator function returns true if the field is |
valid, false if not */ |
var $_validator = null; |
// }}} |
// {{{ constructor |
/** |
* Constructor |
* |
* @param $table string the name of the database table |
* |
* @param $keycolumn mixed string with name of key column, or array of |
* strings if the table has a primary key of more than one column |
* |
* @param $dbh object database connection object |
* |
* @param $validator mixed function or method used to validate |
* each new value, called with three parameters: the name of the |
* field/column that is changing, a reference to the new value and |
* a reference to this object |
* |
*/ |
function __construct($table, $keycolumn, &$dbh, $validator = null) |
{ |
$this->PEAR('DB_Error'); |
$this->_table = $table; |
$this->_keycolumn = $keycolumn; |
$this->_dbh = $dbh; |
$this->_readonly = false; |
$this->_validator = $validator; |
} |
// }}} |
// {{{ _makeWhere() |
/** |
* Utility method to build a "WHERE" clause to locate ourselves in |
* the table. |
* |
* XXX future improvement: use rowids? |
* |
* @access private |
*/ |
function _makeWhere($keyval = null) |
{ |
if (is_array($this->_keycolumn)) { |
if ($keyval === null) { |
for ($i = 0; $i < sizeof($this->_keycolumn); $i++) { |
$keyval[] = $this->{$this->_keycolumn[$i]}; |
} |
} |
$whereclause = ''; |
for ($i = 0; $i < sizeof($this->_keycolumn); $i++) { |
if ($i > 0) { |
$whereclause .= ' AND '; |
} |
$whereclause .= $this->_keycolumn[$i]; |
if (is_null($keyval[$i])) { |
// there's not much point in having a NULL key, |
// but we support it anyway |
$whereclause .= ' IS NULL'; |
} else { |
$whereclause .= ' = ' . $this->_dbh->quote($keyval[$i]); |
} |
} |
} else { |
if ($keyval === null) { |
$keyval = @$this->{$this->_keycolumn}; |
} |
$whereclause = $this->_keycolumn; |
if (is_null($keyval)) { |
// there's not much point in having a NULL key, |
// but we support it anyway |
$whereclause .= ' IS NULL'; |
} else { |
$whereclause .= ' = ' . $this->_dbh->quote($keyval); |
} |
} |
return $whereclause; |
} |
// }}} |
// {{{ setup() |
/** |
* Method used to initialize a DB_storage object from the |
* configured table. |
* |
* @param $keyval mixed the key[s] of the row to fetch (string or array) |
* |
* @return int DB_OK on success, a DB error if not |
*/ |
function setup($keyval) |
{ |
$whereclause = $this->_makeWhere($keyval); |
$query = 'SELECT * FROM ' . $this->_table . ' WHERE ' . $whereclause; |
$sth = $this->_dbh->query($query); |
if (DB::isError($sth)) { |
return $sth; |
} |
$row = $sth->fetchRow(DB_FETCHMODE_ASSOC); |
if (DB::isError($row)) { |
return $row; |
} |
if (!$row) { |
return $this->raiseError(null, DB_ERROR_NOT_FOUND, null, null, |
$query, null, true); |
} |
foreach ($row as $key => $value) { |
$this->_properties[$key] = true; |
$this->$key = $value; |
} |
return DB_OK; |
} |
// }}} |
// {{{ insert() |
/** |
* Create a new (empty) row in the configured table for this |
* object. |
*/ |
function insert($newpk) |
{ |
if (is_array($this->_keycolumn)) { |
$primarykey = $this->_keycolumn; |
} else { |
$primarykey = array($this->_keycolumn); |
} |
settype($newpk, "array"); |
for ($i = 0; $i < sizeof($primarykey); $i++) { |
$pkvals[] = $this->_dbh->quote($newpk[$i]); |
} |
$sth = $this->_dbh->query("INSERT INTO $this->_table (" . |
implode(",", $primarykey) . ") VALUES(" . |
implode(",", $pkvals) . ")"); |
if (DB::isError($sth)) { |
return $sth; |
} |
if (sizeof($newpk) == 1) { |
$newpk = $newpk[0]; |
} |
$this->setup($newpk); |
} |
// }}} |
// {{{ toString() |
/** |
* Output a simple description of this DB_storage object. |
* @return string object description |
*/ |
function toString() |
{ |
$info = strtolower(get_class($this)); |
$info .= " (table="; |
$info .= $this->_table; |
$info .= ", keycolumn="; |
if (is_array($this->_keycolumn)) { |
$info .= "(" . implode(",", $this->_keycolumn) . ")"; |
} else { |
$info .= $this->_keycolumn; |
} |
$info .= ", dbh="; |
if (is_object($this->_dbh)) { |
$info .= $this->_dbh->toString(); |
} else { |
$info .= "null"; |
} |
$info .= ")"; |
if (sizeof($this->_properties)) { |
$info .= " [loaded, key="; |
$keyname = $this->_keycolumn; |
if (is_array($keyname)) { |
$info .= "("; |
for ($i = 0; $i < sizeof($keyname); $i++) { |
if ($i > 0) { |
$info .= ","; |
} |
$info .= $this->$keyname[$i]; |
} |
$info .= ")"; |
} else { |
$info .= $this->$keyname; |
} |
$info .= "]"; |
} |
if (sizeof($this->_changes)) { |
$info .= " [modified]"; |
} |
return $info; |
} |
// }}} |
// {{{ dump() |
/** |
* Dump the contents of this object to "standard output". |
*/ |
function dump() |
{ |
foreach ($this->_properties as $prop => $foo) { |
print "$prop = "; |
print htmlentities($this->$prop); |
print "<br />\n"; |
} |
} |
// }}} |
// {{{ &create() |
/** |
* Static method used to create new DB storage objects. |
* @param $data assoc. array where the keys are the names |
* of properties/columns |
* @return object a new instance of DB_storage or a subclass of it |
*/ |
function &create($table, &$data) |
{ |
$classname = strtolower(get_class($this)); |
$obj = new $classname($table); |
foreach ($data as $name => $value) { |
$obj->_properties[$name] = true; |
$obj->$name = &$value; |
} |
return $obj; |
} |
// }}} |
// {{{ loadFromQuery() |
/** |
* Loads data into this object from the given query. If this |
* object already contains table data, changes will be saved and |
* the object re-initialized first. |
* |
* @param $query SQL query |
* |
* @param $params parameter list in case you want to use |
* prepare/execute mode |
* |
* @return int DB_OK on success, DB_WARNING_READ_ONLY if the |
* returned object is read-only (because the object's specified |
* key column was not found among the columns returned by $query), |
* or another DB error code in case of errors. |
*/ |
// XXX commented out for now |
/* |
function loadFromQuery($query, $params = null) |
{ |
if (sizeof($this->_properties)) { |
if (sizeof($this->_changes)) { |
$this->store(); |
$this->_changes = array(); |
} |
$this->_properties = array(); |
} |
$rowdata = $this->_dbh->getRow($query, DB_FETCHMODE_ASSOC, $params); |
if (DB::isError($rowdata)) { |
return $rowdata; |
} |
reset($rowdata); |
$found_keycolumn = false; |
while (list($key, $value) = each($rowdata)) { |
if ($key == $this->_keycolumn) { |
$found_keycolumn = true; |
} |
$this->_properties[$key] = true; |
$this->$key = &$value; |
unset($value); // have to unset, or all properties will |
// refer to the same value |
} |
if (!$found_keycolumn) { |
$this->_readonly = true; |
return DB_WARNING_READ_ONLY; |
} |
return DB_OK; |
} |
*/ |
// }}} |
// {{{ set() |
/** |
* Modify an attriute value. |
*/ |
function set($property, $newvalue) |
{ |
// only change if $property is known and object is not |
// read-only |
if ($this->_readonly) { |
return $this->raiseError(null, DB_WARNING_READ_ONLY, null, |
null, null, null, true); |
} |
if (@isset($this->_properties[$property])) { |
if (empty($this->_validator)) { |
$valid = true; |
} else { |
$valid = @call_user_func($this->_validator, |
$this->_table, |
$property, |
$newvalue, |
$this->$property, |
$this); |
} |
if ($valid) { |
$this->$property = $newvalue; |
if (empty($this->_changes[$property])) { |
$this->_changes[$property] = 0; |
} else { |
$this->_changes[$property]++; |
} |
} else { |
return $this->raiseError(null, DB_ERROR_INVALID, null, |
null, "invalid field: $property", |
null, true); |
} |
return true; |
} |
return $this->raiseError(null, DB_ERROR_NOSUCHFIELD, null, |
null, "unknown field: $property", |
null, true); |
} |
// }}} |
// {{{ &get() |
/** |
* Fetch an attribute value. |
* |
* @param string attribute name |
* |
* @return attribute contents, or null if the attribute name is |
* unknown |
*/ |
function &get($property) |
{ |
// only return if $property is known |
if (isset($this->_properties[$property])) { |
return $this->$property; |
} |
$tmp = null; |
return $tmp; |
} |
// }}} |
// {{{ _DB_storage() |
/** |
* Destructor, calls DB_storage::store() if there are changes |
* that are to be kept. |
*/ |
function _DB_storage() |
{ |
if (sizeof($this->_changes)) { |
$this->store(); |
} |
$this->_properties = array(); |
$this->_changes = array(); |
$this->_table = null; |
} |
// }}} |
// {{{ store() |
/** |
* Stores changes to this object in the database. |
* |
* @return DB_OK or a DB error |
*/ |
function store() |
{ |
$params = array(); |
$vars = array(); |
foreach ($this->_changes as $name => $foo) { |
$params[] = &$this->$name; |
$vars[] = $name . ' = ?'; |
} |
if ($vars) { |
$query = 'UPDATE ' . $this->_table . ' SET ' . |
implode(', ', $vars) . ' WHERE ' . |
$this->_makeWhere(); |
$stmt = $this->_dbh->prepare($query); |
$res = $this->_dbh->execute($stmt, $params); |
if (DB::isError($res)) { |
return $res; |
} |
$this->_changes = array(); |
} |
return DB_OK; |
} |
// }}} |
// {{{ remove() |
/** |
* Remove the row represented by this object from the database. |
* |
* @return mixed DB_OK or a DB error |
*/ |
function remove() |
{ |
if ($this->_readonly) { |
return $this->raiseError(null, DB_WARNING_READ_ONLY, null, |
null, null, null, true); |
} |
$query = 'DELETE FROM ' . $this->_table .' WHERE '. |
$this->_makeWhere(); |
$res = $this->_dbh->query($query); |
if (DB::isError($res)) { |
return $res; |
} |
foreach ($this->_properties as $prop => $foo) { |
unset($this->$prop); |
} |
$this->_properties = array(); |
$this->_changes = array(); |
return DB_OK; |
} |
// }}} |
} |
/* |
* Local variables: |
* tab-width: 4 |
* c-basic-offset: 4 |
* End: |
*/ |
?> |
/branches/v1.3-critias/bibliotheque/pear/DB/mysql.php |
---|
New file |
0,0 → 1,1034 |
<?php |
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */ |
/** |
* The PEAR DB driver for PHP's mysql extension |
* for interacting with MySQL databases |
* |
* PHP version 5 |
* |
* LICENSE: This source file is subject to version 3.0 of the PHP license |
* that is available through the world-wide-web at the following URI: |
* http://www.php.net/license/3_0.txt. If you did not receive a copy of |
* the PHP License and are unable to obtain it through the web, please |
* send a note to license@php.net so we can mail you a copy immediately. |
* |
* @category Database |
* @package DB |
* @author Stig Bakken <ssb@php.net> |
* @author Daniel Convissor <danielc@php.net> |
* @copyright 1997-2007 The PHP Group |
* @license http://www.php.net/license/3_0.txt PHP License 3.0 |
* @version CVS: $Id$ |
* @link http://pear.php.net/package/DB |
*/ |
/** |
* Obtain the DB_common class so it can be extended from |
*/ |
require_once 'DB/common.php'; |
/** |
* The methods PEAR DB uses to interact with PHP's mysql extension |
* for interacting with MySQL databases |
* |
* These methods overload the ones declared in DB_common. |
* |
* @category Database |
* @package DB |
* @author Stig Bakken <ssb@php.net> |
* @author Daniel Convissor <danielc@php.net> |
* @copyright 1997-2007 The PHP Group |
* @license http://www.php.net/license/3_0.txt PHP License 3.0 |
* @version Release: 1.9.2 |
* @link http://pear.php.net/package/DB |
*/ |
class DB_mysql extends DB_common |
{ |
// {{{ properties |
/** |
* The DB driver type (mysql, oci8, odbc, etc.) |
* @var string |
*/ |
var $phptype = 'mysql'; |
/** |
* The database syntax variant to be used (db2, access, etc.), if any |
* @var string |
*/ |
var $dbsyntax = 'mysql'; |
/** |
* The capabilities of this DB implementation |
* |
* The 'new_link' element contains the PHP version that first provided |
* new_link support for this DBMS. Contains false if it's unsupported. |
* |
* Meaning of the 'limit' element: |
* + 'emulate' = emulate with fetch row by number |
* + 'alter' = alter the query |
* + false = skip rows |
* |
* @var array |
*/ |
var $features = array( |
'limit' => 'alter', |
'new_link' => '4.2.0', |
'numrows' => true, |
'pconnect' => true, |
'prepare' => false, |
'ssl' => false, |
'transactions' => true, |
); |
/** |
* A mapping of native error codes to DB error codes |
* @var array |
*/ |
var $errorcode_map = array( |
1004 => DB_ERROR_CANNOT_CREATE, |
1005 => DB_ERROR_CANNOT_CREATE, |
1006 => DB_ERROR_CANNOT_CREATE, |
1007 => DB_ERROR_ALREADY_EXISTS, |
1008 => DB_ERROR_CANNOT_DROP, |
1022 => DB_ERROR_ALREADY_EXISTS, |
1044 => DB_ERROR_ACCESS_VIOLATION, |
1046 => DB_ERROR_NODBSELECTED, |
1048 => DB_ERROR_CONSTRAINT, |
1049 => DB_ERROR_NOSUCHDB, |
1050 => DB_ERROR_ALREADY_EXISTS, |
1051 => DB_ERROR_NOSUCHTABLE, |
1054 => DB_ERROR_NOSUCHFIELD, |
1061 => DB_ERROR_ALREADY_EXISTS, |
1062 => DB_ERROR_ALREADY_EXISTS, |
1064 => DB_ERROR_SYNTAX, |
1091 => DB_ERROR_NOT_FOUND, |
1100 => DB_ERROR_NOT_LOCKED, |
1136 => DB_ERROR_VALUE_COUNT_ON_ROW, |
1142 => DB_ERROR_ACCESS_VIOLATION, |
1146 => DB_ERROR_NOSUCHTABLE, |
1216 => DB_ERROR_CONSTRAINT, |
1217 => DB_ERROR_CONSTRAINT, |
1356 => DB_ERROR_DIVZERO, |
1451 => DB_ERROR_CONSTRAINT, |
1452 => DB_ERROR_CONSTRAINT, |
); |
/** |
* The raw database connection created by PHP |
* @var resource |
*/ |
var $connection; |
/** |
* The DSN information for connecting to a database |
* @var array |
*/ |
var $dsn = array(); |
/** |
* Should data manipulation queries be committed automatically? |
* @var bool |
* @access private |
*/ |
var $autocommit = true; |
/** |
* The quantity of transactions begun |
* |
* {@internal While this is private, it can't actually be designated |
* private in PHP 5 because it is directly accessed in the test suite.}} |
* |
* @var integer |
* @access private |
*/ |
var $transaction_opcount = 0; |
/** |
* The database specified in the DSN |
* |
* It's a fix to allow calls to different databases in the same script. |
* |
* @var string |
* @access private |
*/ |
var $_db = ''; |
// }}} |
// {{{ constructor |
/** |
* This constructor calls <kbd>parent::__construct()</kbd> |
* |
* @return void |
*/ |
function __construct() |
{ |
parent::__construct(); |
} |
// }}} |
// {{{ connect() |
/** |
* Connect to the database server, log in and open the database |
* |
* Don't call this method directly. Use DB::connect() instead. |
* |
* PEAR DB's mysql driver supports the following extra DSN options: |
* + new_link If set to true, causes subsequent calls to connect() |
* to return a new connection link instead of the |
* existing one. WARNING: this is not portable to |
* other DBMS's. Available since PEAR DB 1.7.0. |
* + client_flags Any combination of MYSQL_CLIENT_* constants. |
* Only used if PHP is at version 4.3.0 or greater. |
* Available since PEAR DB 1.7.0. |
* |
* @param array $dsn the data source name |
* @param bool $persistent should the connection be persistent? |
* |
* @return int DB_OK on success. A DB_Error object on failure. |
*/ |
function connect($dsn, $persistent = false) |
{ |
if (!PEAR::loadExtension('mysql')) { |
return $this->raiseError(DB_ERROR_EXTENSION_NOT_FOUND); |
} |
$this->dsn = $dsn; |
if ($dsn['dbsyntax']) { |
$this->dbsyntax = $dsn['dbsyntax']; |
} |
$params = array(); |
if ($dsn['protocol'] && $dsn['protocol'] == 'unix') { |
$params[0] = ':' . $dsn['socket']; |
} else { |
$params[0] = $dsn['hostspec'] ? $dsn['hostspec'] |
: 'localhost'; |
if ($dsn['port']) { |
$params[0] .= ':' . $dsn['port']; |
} |
} |
$params[] = $dsn['username'] ? $dsn['username'] : null; |
$params[] = $dsn['password'] ? $dsn['password'] : null; |
if (!$persistent) { |
if (isset($dsn['new_link']) |
&& ($dsn['new_link'] == 'true' || $dsn['new_link'] === true)) |
{ |
$params[] = true; |
} else { |
$params[] = false; |
} |
} |
if (version_compare(phpversion(), '4.3.0', '>=')) { |
$params[] = isset($dsn['client_flags']) |
? $dsn['client_flags'] : null; |
} |
$connect_function = $persistent ? 'mysql_pconnect' : 'mysql_connect'; |
$ini = ini_get('track_errors'); |
$php_errormsg = ''; |
if ($ini) { |
$this->connection = @call_user_func_array($connect_function, |
$params); |
} else { |
@ini_set('track_errors', 1); |
$this->connection = @call_user_func_array($connect_function, |
$params); |
@ini_set('track_errors', $ini); |
} |
if (!$this->connection) { |
if (($err = @mysql_error()) != '') { |
return $this->raiseError(DB_ERROR_CONNECT_FAILED, |
null, null, null, |
$err); |
} else { |
return $this->raiseError(DB_ERROR_CONNECT_FAILED, |
null, null, null, |
$php_errormsg); |
} |
} |
if ($dsn['database']) { |
if (!@mysql_select_db($dsn['database'], $this->connection)) { |
return $this->mysqlRaiseError(); |
} |
$this->_db = $dsn['database']; |
} |
return DB_OK; |
} |
// }}} |
// {{{ disconnect() |
/** |
* Disconnects from the database server |
* |
* @return bool TRUE on success, FALSE on failure |
*/ |
function disconnect() |
{ |
$ret = @mysql_close($this->connection); |
$this->connection = null; |
return $ret; |
} |
// }}} |
// {{{ simpleQuery() |
/** |
* Sends a query to the database server |
* |
* Generally uses mysql_query(). If you want to use |
* mysql_unbuffered_query() set the "result_buffering" option to 0 using |
* setOptions(). This option was added in Release 1.7.0. |
* |
* @param string the SQL query string |
* |
* @return mixed + a PHP result resrouce for successful SELECT queries |
* + the DB_OK constant for other successful queries |
* + a DB_Error object on failure |
*/ |
function simpleQuery($query) |
{ |
$ismanip = $this->_checkManip($query); |
$this->last_query = $query; |
$query = $this->modifyQuery($query); |
if ($this->_db) { |
if (!@mysql_select_db($this->_db, $this->connection)) { |
return $this->mysqlRaiseError(DB_ERROR_NODBSELECTED); |
} |
} |
if (!$this->autocommit && $ismanip) { |
if ($this->transaction_opcount == 0) { |
$result = @mysql_query('SET AUTOCOMMIT=0', $this->connection); |
$result = @mysql_query('BEGIN', $this->connection); |
if (!$result) { |
return $this->mysqlRaiseError(); |
} |
} |
$this->transaction_opcount++; |
} |
if (!$this->options['result_buffering']) { |
$result = @mysql_unbuffered_query($query, $this->connection); |
} else { |
$result = @mysql_query($query, $this->connection); |
} |
if (!$result) { |
return $this->mysqlRaiseError(); |
} |
if (is_resource($result)) { |
return $result; |
} |
return DB_OK; |
} |
// }}} |
// {{{ nextResult() |
/** |
* Move the internal mysql result pointer to the next available result |
* |
* This method has not been implemented yet. |
* |
* @param a valid sql result resource |
* |
* @return false |
*/ |
function nextResult($result) |
{ |
return false; |
} |
// }}} |
// {{{ fetchInto() |
/** |
* Places a row from the result set into the given array |
* |
* Formating of the array and the data therein are configurable. |
* See DB_result::fetchInto() for more information. |
* |
* This method is not meant to be called directly. Use |
* DB_result::fetchInto() instead. It can't be declared "protected" |
* because DB_result is a separate object. |
* |
* @param resource $result the query result resource |
* @param array $arr the referenced array to put the data in |
* @param int $fetchmode how the resulting array should be indexed |
* @param int $rownum the row number to fetch (0 = first row) |
* |
* @return mixed DB_OK on success, NULL when the end of a result set is |
* reached or on failure |
* |
* @see DB_result::fetchInto() |
*/ |
function fetchInto($result, &$arr, $fetchmode, $rownum = null) |
{ |
if ($rownum !== null) { |
if (!@mysql_data_seek($result, $rownum)) { |
return null; |
} |
} |
if ($fetchmode & DB_FETCHMODE_ASSOC) { |
$arr = @mysql_fetch_array($result, MYSQL_ASSOC); |
if ($this->options['portability'] & DB_PORTABILITY_LOWERCASE && $arr) { |
$arr = array_change_key_case($arr, CASE_LOWER); |
} |
} else { |
$arr = @mysql_fetch_row($result); |
} |
if (!$arr) { |
return null; |
} |
if ($this->options['portability'] & DB_PORTABILITY_RTRIM) { |
/* |
* Even though this DBMS already trims output, we do this because |
* a field might have intentional whitespace at the end that |
* gets removed by DB_PORTABILITY_RTRIM under another driver. |
*/ |
$this->_rtrimArrayValues($arr); |
} |
if ($this->options['portability'] & DB_PORTABILITY_NULL_TO_EMPTY) { |
$this->_convertNullArrayValuesToEmpty($arr); |
} |
return DB_OK; |
} |
// }}} |
// {{{ freeResult() |
/** |
* Deletes the result set and frees the memory occupied by the result set |
* |
* This method is not meant to be called directly. Use |
* DB_result::free() instead. It can't be declared "protected" |
* because DB_result is a separate object. |
* |
* @param resource $result PHP's query result resource |
* |
* @return bool TRUE on success, FALSE if $result is invalid |
* |
* @see DB_result::free() |
*/ |
function freeResult($result) |
{ |
return is_resource($result) ? mysql_free_result($result) : false; |
} |
// }}} |
// {{{ numCols() |
/** |
* Gets the number of columns in a result set |
* |
* This method is not meant to be called directly. Use |
* DB_result::numCols() instead. It can't be declared "protected" |
* because DB_result is a separate object. |
* |
* @param resource $result PHP's query result resource |
* |
* @return int the number of columns. A DB_Error object on failure. |
* |
* @see DB_result::numCols() |
*/ |
function numCols($result) |
{ |
$cols = @mysql_num_fields($result); |
if (!$cols) { |
return $this->mysqlRaiseError(); |
} |
return $cols; |
} |
// }}} |
// {{{ numRows() |
/** |
* Gets the number of rows in a result set |
* |
* This method is not meant to be called directly. Use |
* DB_result::numRows() instead. It can't be declared "protected" |
* because DB_result is a separate object. |
* |
* @param resource $result PHP's query result resource |
* |
* @return int the number of rows. A DB_Error object on failure. |
* |
* @see DB_result::numRows() |
*/ |
function numRows($result) |
{ |
$rows = @mysql_num_rows($result); |
if ($rows === null) { |
return $this->mysqlRaiseError(); |
} |
return $rows; |
} |
// }}} |
// {{{ autoCommit() |
/** |
* Enables or disables automatic commits |
* |
* @param bool $onoff true turns it on, false turns it off |
* |
* @return int DB_OK on success. A DB_Error object if the driver |
* doesn't support auto-committing transactions. |
*/ |
function autoCommit($onoff = false) |
{ |
// XXX if $this->transaction_opcount > 0, we should probably |
// issue a warning here. |
$this->autocommit = $onoff ? true : false; |
return DB_OK; |
} |
// }}} |
// {{{ commit() |
/** |
* Commits the current transaction |
* |
* @return int DB_OK on success. A DB_Error object on failure. |
*/ |
function commit() |
{ |
if ($this->transaction_opcount > 0) { |
if ($this->_db) { |
if (!@mysql_select_db($this->_db, $this->connection)) { |
return $this->mysqlRaiseError(DB_ERROR_NODBSELECTED); |
} |
} |
$result = @mysql_query('COMMIT', $this->connection); |
$result = @mysql_query('SET AUTOCOMMIT=1', $this->connection); |
$this->transaction_opcount = 0; |
if (!$result) { |
return $this->mysqlRaiseError(); |
} |
} |
return DB_OK; |
} |
// }}} |
// {{{ rollback() |
/** |
* Reverts the current transaction |
* |
* @return int DB_OK on success. A DB_Error object on failure. |
*/ |
function rollback() |
{ |
if ($this->transaction_opcount > 0) { |
if ($this->_db) { |
if (!@mysql_select_db($this->_db, $this->connection)) { |
return $this->mysqlRaiseError(DB_ERROR_NODBSELECTED); |
} |
} |
$result = @mysql_query('ROLLBACK', $this->connection); |
$result = @mysql_query('SET AUTOCOMMIT=1', $this->connection); |
$this->transaction_opcount = 0; |
if (!$result) { |
return $this->mysqlRaiseError(); |
} |
} |
return DB_OK; |
} |
// }}} |
// {{{ affectedRows() |
/** |
* Determines the number of rows affected by a data maniuplation query |
* |
* 0 is returned for queries that don't manipulate data. |
* |
* @return int the number of rows. A DB_Error object on failure. |
*/ |
function affectedRows() |
{ |
if ($this->_last_query_manip) { |
return @mysql_affected_rows($this->connection); |
} else { |
return 0; |
} |
} |
// }}} |
// {{{ nextId() |
/** |
* Returns the next free id in a sequence |
* |
* @param string $seq_name name of the sequence |
* @param boolean $ondemand when true, the seqence is automatically |
* created if it does not exist |
* |
* @return int the next id number in the sequence. |
* A DB_Error object on failure. |
* |
* @see DB_common::nextID(), DB_common::getSequenceName(), |
* DB_mysql::createSequence(), DB_mysql::dropSequence() |
*/ |
function nextId($seq_name, $ondemand = true) |
{ |
$seqname = $this->getSequenceName($seq_name); |
do { |
$repeat = 0; |
$this->pushErrorHandling(PEAR_ERROR_RETURN); |
$result = $this->query("UPDATE ${seqname} ". |
'SET id=LAST_INSERT_ID(id+1)'); |
$this->popErrorHandling(); |
if ($result === DB_OK) { |
// COMMON CASE |
$id = @mysql_insert_id($this->connection); |
if ($id != 0) { |
return $id; |
} |
// EMPTY SEQ TABLE |
// Sequence table must be empty for some reason, so fill |
// it and return 1 and obtain a user-level lock |
$result = $this->getOne("SELECT GET_LOCK('${seqname}_lock',10)"); |
if (DB::isError($result)) { |
return $this->raiseError($result); |
} |
if ($result == 0) { |
// Failed to get the lock |
return $this->mysqlRaiseError(DB_ERROR_NOT_LOCKED); |
} |
// add the default value |
$result = $this->query("REPLACE INTO ${seqname} (id) VALUES (0)"); |
if (DB::isError($result)) { |
return $this->raiseError($result); |
} |
// Release the lock |
$result = $this->getOne('SELECT RELEASE_LOCK(' |
. "'${seqname}_lock')"); |
if (DB::isError($result)) { |
return $this->raiseError($result); |
} |
// We know what the result will be, so no need to try again |
return 1; |
} elseif ($ondemand && DB::isError($result) && |
$result->getCode() == DB_ERROR_NOSUCHTABLE) |
{ |
// ONDEMAND TABLE CREATION |
$result = $this->createSequence($seq_name); |
if (DB::isError($result)) { |
return $this->raiseError($result); |
} else { |
$repeat = 1; |
} |
} elseif (DB::isError($result) && |
$result->getCode() == DB_ERROR_ALREADY_EXISTS) |
{ |
// BACKWARDS COMPAT |
// see _BCsequence() comment |
$result = $this->_BCsequence($seqname); |
if (DB::isError($result)) { |
return $this->raiseError($result); |
} |
$repeat = 1; |
} |
} while ($repeat); |
return $this->raiseError($result); |
} |
// }}} |
// {{{ createSequence() |
/** |
* Creates a new sequence |
* |
* @param string $seq_name name of the new sequence |
* |
* @return int DB_OK on success. A DB_Error object on failure. |
* |
* @see DB_common::createSequence(), DB_common::getSequenceName(), |
* DB_mysql::nextID(), DB_mysql::dropSequence() |
*/ |
function createSequence($seq_name) |
{ |
$seqname = $this->getSequenceName($seq_name); |
$res = $this->query('CREATE TABLE ' . $seqname |
. ' (id INTEGER UNSIGNED AUTO_INCREMENT NOT NULL,' |
. ' PRIMARY KEY(id))'); |
if (DB::isError($res)) { |
return $res; |
} |
// insert yields value 1, nextId call will generate ID 2 |
$res = $this->query("INSERT INTO ${seqname} (id) VALUES (0)"); |
if (DB::isError($res)) { |
return $res; |
} |
// so reset to zero |
return $this->query("UPDATE ${seqname} SET id = 0"); |
} |
// }}} |
// {{{ dropSequence() |
/** |
* Deletes a sequence |
* |
* @param string $seq_name name of the sequence to be deleted |
* |
* @return int DB_OK on success. A DB_Error object on failure. |
* |
* @see DB_common::dropSequence(), DB_common::getSequenceName(), |
* DB_mysql::nextID(), DB_mysql::createSequence() |
*/ |
function dropSequence($seq_name) |
{ |
return $this->query('DROP TABLE ' . $this->getSequenceName($seq_name)); |
} |
// }}} |
// {{{ _BCsequence() |
/** |
* Backwards compatibility with old sequence emulation implementation |
* (clean up the dupes) |
* |
* @param string $seqname the sequence name to clean up |
* |
* @return bool true on success. A DB_Error object on failure. |
* |
* @access private |
*/ |
function _BCsequence($seqname) |
{ |
// Obtain a user-level lock... this will release any previous |
// application locks, but unlike LOCK TABLES, it does not abort |
// the current transaction and is much less frequently used. |
$result = $this->getOne("SELECT GET_LOCK('${seqname}_lock',10)"); |
if (DB::isError($result)) { |
return $result; |
} |
if ($result == 0) { |
// Failed to get the lock, can't do the conversion, bail |
// with a DB_ERROR_NOT_LOCKED error |
return $this->mysqlRaiseError(DB_ERROR_NOT_LOCKED); |
} |
$highest_id = $this->getOne("SELECT MAX(id) FROM ${seqname}"); |
if (DB::isError($highest_id)) { |
return $highest_id; |
} |
// This should kill all rows except the highest |
// We should probably do something if $highest_id isn't |
// numeric, but I'm at a loss as how to handle that... |
$result = $this->query('DELETE FROM ' . $seqname |
. " WHERE id <> $highest_id"); |
if (DB::isError($result)) { |
return $result; |
} |
// If another thread has been waiting for this lock, |
// it will go thru the above procedure, but will have no |
// real effect |
$result = $this->getOne("SELECT RELEASE_LOCK('${seqname}_lock')"); |
if (DB::isError($result)) { |
return $result; |
} |
return true; |
} |
// }}} |
// {{{ quoteIdentifier() |
/** |
* Quotes a string so it can be safely used as a table or column name |
* (WARNING: using names that require this is a REALLY BAD IDEA) |
* |
* WARNING: Older versions of MySQL can't handle the backtick |
* character (<kbd>`</kbd>) in table or column names. |
* |
* @param string $str identifier name to be quoted |
* |
* @return string quoted identifier string |
* |
* @see DB_common::quoteIdentifier() |
* @since Method available since Release 1.6.0 |
*/ |
function quoteIdentifier($str) |
{ |
return '`' . str_replace('`', '``', $str) . '`'; |
} |
// }}} |
// {{{ escapeSimple() |
/** |
* Escapes a string according to the current DBMS's standards |
* |
* @param string $str the string to be escaped |
* |
* @return string the escaped string |
* |
* @see DB_common::quoteSmart() |
* @since Method available since Release 1.6.0 |
*/ |
function escapeSimple($str) |
{ |
if (function_exists('mysql_real_escape_string')) { |
return @mysql_real_escape_string($str, $this->connection); |
} else { |
return @mysql_escape_string($str); |
} |
} |
// }}} |
// {{{ modifyQuery() |
/** |
* Changes a query string for various DBMS specific reasons |
* |
* This little hack lets you know how many rows were deleted |
* when running a "DELETE FROM table" query. Only implemented |
* if the DB_PORTABILITY_DELETE_COUNT portability option is on. |
* |
* @param string $query the query string to modify |
* |
* @return string the modified query string |
* |
* @access protected |
* @see DB_common::setOption() |
*/ |
function modifyQuery($query) |
{ |
if ($this->options['portability'] & DB_PORTABILITY_DELETE_COUNT) { |
// "DELETE FROM table" gives 0 affected rows in MySQL. |
// This little hack lets you know how many rows were deleted. |
if (preg_match('/^\s*DELETE\s+FROM\s+(\S+)\s*$/i', $query)) { |
$query = preg_replace('/^\s*DELETE\s+FROM\s+(\S+)\s*$/', |
'DELETE FROM \1 WHERE 1=1', $query); |
} |
} |
return $query; |
} |
// }}} |
// {{{ modifyLimitQuery() |
/** |
* Adds LIMIT clauses to a query string according to current DBMS standards |
* |
* @param string $query the query to modify |
* @param int $from the row to start to fetching (0 = the first row) |
* @param int $count the numbers of rows to fetch |
* @param mixed $params array, string or numeric data to be used in |
* execution of the statement. Quantity of items |
* passed must match quantity of placeholders in |
* query: meaning 1 placeholder for non-array |
* parameters or 1 placeholder per array element. |
* |
* @return string the query string with LIMIT clauses added |
* |
* @access protected |
*/ |
function modifyLimitQuery($query, $from, $count, $params = array()) |
{ |
if (DB::isManip($query) || $this->_next_query_manip) { |
return $query . " LIMIT $count"; |
} else { |
return $query . " LIMIT $from, $count"; |
} |
} |
// }}} |
// {{{ mysqlRaiseError() |
/** |
* Produces a DB_Error object regarding the current problem |
* |
* @param int $errno if the error is being manually raised pass a |
* DB_ERROR* constant here. If this isn't passed |
* the error information gathered from the DBMS. |
* |
* @return object the DB_Error object |
* |
* @see DB_common::raiseError(), |
* DB_mysql::errorNative(), DB_common::errorCode() |
*/ |
function mysqlRaiseError($errno = null) |
{ |
if ($errno === null) { |
if ($this->options['portability'] & DB_PORTABILITY_ERRORS) { |
$this->errorcode_map[1022] = DB_ERROR_CONSTRAINT; |
$this->errorcode_map[1048] = DB_ERROR_CONSTRAINT_NOT_NULL; |
$this->errorcode_map[1062] = DB_ERROR_CONSTRAINT; |
} else { |
// Doing this in case mode changes during runtime. |
$this->errorcode_map[1022] = DB_ERROR_ALREADY_EXISTS; |
$this->errorcode_map[1048] = DB_ERROR_CONSTRAINT; |
$this->errorcode_map[1062] = DB_ERROR_ALREADY_EXISTS; |
} |
$errno = $this->errorCode(mysql_errno($this->connection)); |
} |
return $this->raiseError($errno, null, null, null, |
@mysql_errno($this->connection) . ' ** ' . |
@mysql_error($this->connection)); |
} |
// }}} |
// {{{ errorNative() |
/** |
* Gets the DBMS' native error code produced by the last query |
* |
* @return int the DBMS' error code |
*/ |
function errorNative() |
{ |
return @mysql_errno($this->connection); |
} |
// }}} |
// {{{ tableInfo() |
/** |
* Returns information about a table or a result set |
* |
* @param object|string $result DB_result object from a query or a |
* string containing the name of a table. |
* While this also accepts a query result |
* resource identifier, this behavior is |
* deprecated. |
* @param int $mode a valid tableInfo mode |
* |
* @return array an associative array with the information requested. |
* A DB_Error object on failure. |
* |
* @see DB_common::tableInfo() |
*/ |
function tableInfo($result, $mode = null) |
{ |
if (is_string($result)) { |
// Fix for bug #11580. |
if ($this->_db) { |
if (!@mysql_select_db($this->_db, $this->connection)) { |
return $this->mysqlRaiseError(DB_ERROR_NODBSELECTED); |
} |
} |
/* |
* Probably received a table name. |
* Create a result resource identifier. |
*/ |
$id = @mysql_query("SELECT * FROM $result LIMIT 0", |
$this->connection); |
$got_string = true; |
} elseif (isset($result->result)) { |
/* |
* Probably received a result object. |
* Extract the result resource identifier. |
*/ |
$id = $result->result; |
$got_string = false; |
} else { |
/* |
* Probably received a result resource identifier. |
* Copy it. |
* Deprecated. Here for compatibility only. |
*/ |
$id = $result; |
$got_string = false; |
} |
if (!is_resource($id)) { |
return $this->mysqlRaiseError(DB_ERROR_NEED_MORE_DATA); |
} |
if ($this->options['portability'] & DB_PORTABILITY_LOWERCASE) { |
$case_func = 'strtolower'; |
} else { |
$case_func = 'strval'; |
} |
$count = @mysql_num_fields($id); |
$res = array(); |
if ($mode) { |
$res['num_fields'] = $count; |
} |
for ($i = 0; $i < $count; $i++) { |
$res[$i] = array( |
'table' => $case_func(@mysql_field_table($id, $i)), |
'name' => $case_func(@mysql_field_name($id, $i)), |
'type' => @mysql_field_type($id, $i), |
'len' => @mysql_field_len($id, $i), |
'flags' => @mysql_field_flags($id, $i), |
); |
if ($mode & DB_TABLEINFO_ORDER) { |
$res['order'][$res[$i]['name']] = $i; |
} |
if ($mode & DB_TABLEINFO_ORDERTABLE) { |
$res['ordertable'][$res[$i]['table']][$res[$i]['name']] = $i; |
} |
} |
// free the result only if we were called on a table |
if ($got_string) { |
@mysql_free_result($id); |
} |
return $res; |
} |
// }}} |
// {{{ getSpecialQuery() |
/** |
* Obtains the query string needed for listing a given type of objects |
* |
* @param string $type the kind of objects you want to retrieve |
* |
* @return string the SQL query string or null if the driver doesn't |
* support the object type requested |
* |
* @access protected |
* @see DB_common::getListOf() |
*/ |
function getSpecialQuery($type) |
{ |
switch ($type) { |
case 'tables': |
return 'SHOW TABLES'; |
case 'users': |
return 'SELECT DISTINCT User FROM mysql.user'; |
case 'databases': |
return 'SHOW DATABASES'; |
default: |
return null; |
} |
} |
// }}} |
} |
/* |
* Local variables: |
* tab-width: 4 |
* c-basic-offset: 4 |
* End: |
*/ |
?> |
/branches/v1.3-critias/bibliotheque/pear/DB/ifx.php |
---|
New file |
0,0 → 1,683 |
<?php |
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */ |
/** |
* The PEAR DB driver for PHP's ifx extension |
* for interacting with Informix databases |
* |
* PHP version 5 |
* |
* LICENSE: This source file is subject to version 3.0 of the PHP license |
* that is available through the world-wide-web at the following URI: |
* http://www.php.net/license/3_0.txt. If you did not receive a copy of |
* the PHP License and are unable to obtain it through the web, please |
* send a note to license@php.net so we can mail you a copy immediately. |
* |
* @category Database |
* @package DB |
* @author Tomas V.V.Cox <cox@idecnet.com> |
* @author Daniel Convissor <danielc@php.net> |
* @copyright 1997-2007 The PHP Group |
* @license http://www.php.net/license/3_0.txt PHP License 3.0 |
* @version CVS: $Id$ |
* @link http://pear.php.net/package/DB |
*/ |
/** |
* Obtain the DB_common class so it can be extended from |
*/ |
require_once 'DB/common.php'; |
/** |
* The methods PEAR DB uses to interact with PHP's ifx extension |
* for interacting with Informix databases |
* |
* These methods overload the ones declared in DB_common. |
* |
* More info on Informix errors can be found at: |
* http://www.informix.com/answers/english/ierrors.htm |
* |
* TODO: |
* - set needed env Informix vars on connect |
* - implement native prepare/execute |
* |
* @category Database |
* @package DB |
* @author Tomas V.V.Cox <cox@idecnet.com> |
* @author Daniel Convissor <danielc@php.net> |
* @copyright 1997-2007 The PHP Group |
* @license http://www.php.net/license/3_0.txt PHP License 3.0 |
* @version Release: 1.9.2 |
* @link http://pear.php.net/package/DB |
*/ |
class DB_ifx extends DB_common |
{ |
// {{{ properties |
/** |
* The DB driver type (mysql, oci8, odbc, etc.) |
* @var string |
*/ |
var $phptype = 'ifx'; |
/** |
* The database syntax variant to be used (db2, access, etc.), if any |
* @var string |
*/ |
var $dbsyntax = 'ifx'; |
/** |
* The capabilities of this DB implementation |
* |
* The 'new_link' element contains the PHP version that first provided |
* new_link support for this DBMS. Contains false if it's unsupported. |
* |
* Meaning of the 'limit' element: |
* + 'emulate' = emulate with fetch row by number |
* + 'alter' = alter the query |
* + false = skip rows |
* |
* @var array |
*/ |
var $features = array( |
'limit' => 'emulate', |
'new_link' => false, |
'numrows' => 'emulate', |
'pconnect' => true, |
'prepare' => false, |
'ssl' => false, |
'transactions' => true, |
); |
/** |
* A mapping of native error codes to DB error codes |
* @var array |
*/ |
var $errorcode_map = array( |
'-201' => DB_ERROR_SYNTAX, |
'-206' => DB_ERROR_NOSUCHTABLE, |
'-217' => DB_ERROR_NOSUCHFIELD, |
'-236' => DB_ERROR_VALUE_COUNT_ON_ROW, |
'-239' => DB_ERROR_CONSTRAINT, |
'-253' => DB_ERROR_SYNTAX, |
'-268' => DB_ERROR_CONSTRAINT, |
'-292' => DB_ERROR_CONSTRAINT_NOT_NULL, |
'-310' => DB_ERROR_ALREADY_EXISTS, |
'-316' => DB_ERROR_ALREADY_EXISTS, |
'-319' => DB_ERROR_NOT_FOUND, |
'-329' => DB_ERROR_NODBSELECTED, |
'-346' => DB_ERROR_CONSTRAINT, |
'-386' => DB_ERROR_CONSTRAINT_NOT_NULL, |
'-391' => DB_ERROR_CONSTRAINT_NOT_NULL, |
'-554' => DB_ERROR_SYNTAX, |
'-691' => DB_ERROR_CONSTRAINT, |
'-692' => DB_ERROR_CONSTRAINT, |
'-703' => DB_ERROR_CONSTRAINT_NOT_NULL, |
'-1202' => DB_ERROR_DIVZERO, |
'-1204' => DB_ERROR_INVALID_DATE, |
'-1205' => DB_ERROR_INVALID_DATE, |
'-1206' => DB_ERROR_INVALID_DATE, |
'-1209' => DB_ERROR_INVALID_DATE, |
'-1210' => DB_ERROR_INVALID_DATE, |
'-1212' => DB_ERROR_INVALID_DATE, |
'-1213' => DB_ERROR_INVALID_NUMBER, |
); |
/** |
* The raw database connection created by PHP |
* @var resource |
*/ |
var $connection; |
/** |
* The DSN information for connecting to a database |
* @var array |
*/ |
var $dsn = array(); |
/** |
* Should data manipulation queries be committed automatically? |
* @var bool |
* @access private |
*/ |
var $autocommit = true; |
/** |
* The quantity of transactions begun |
* |
* {@internal While this is private, it can't actually be designated |
* private in PHP 5 because it is directly accessed in the test suite.}} |
* |
* @var integer |
* @access private |
*/ |
var $transaction_opcount = 0; |
/** |
* The number of rows affected by a data manipulation query |
* @var integer |
* @access private |
*/ |
var $affected = 0; |
// }}} |
// {{{ constructor |
/** |
* This constructor calls <kbd>parent::__construct()</kbd> |
* |
* @return void |
*/ |
function __construct() |
{ |
parent::__construct(); |
} |
// }}} |
// {{{ connect() |
/** |
* Connect to the database server, log in and open the database |
* |
* Don't call this method directly. Use DB::connect() instead. |
* |
* @param array $dsn the data source name |
* @param bool $persistent should the connection be persistent? |
* |
* @return int DB_OK on success. A DB_Error object on failure. |
*/ |
function connect($dsn, $persistent = false) |
{ |
if (!PEAR::loadExtension('informix') && |
!PEAR::loadExtension('Informix')) |
{ |
return $this->raiseError(DB_ERROR_EXTENSION_NOT_FOUND); |
} |
$this->dsn = $dsn; |
if ($dsn['dbsyntax']) { |
$this->dbsyntax = $dsn['dbsyntax']; |
} |
$dbhost = $dsn['hostspec'] ? '@' . $dsn['hostspec'] : ''; |
$dbname = $dsn['database'] ? $dsn['database'] . $dbhost : ''; |
$user = $dsn['username'] ? $dsn['username'] : ''; |
$pw = $dsn['password'] ? $dsn['password'] : ''; |
$connect_function = $persistent ? 'ifx_pconnect' : 'ifx_connect'; |
$this->connection = @$connect_function($dbname, $user, $pw); |
if (!is_resource($this->connection)) { |
return $this->ifxRaiseError(DB_ERROR_CONNECT_FAILED); |
} |
return DB_OK; |
} |
// }}} |
// {{{ disconnect() |
/** |
* Disconnects from the database server |
* |
* @return bool TRUE on success, FALSE on failure |
*/ |
function disconnect() |
{ |
$ret = @ifx_close($this->connection); |
$this->connection = null; |
return $ret; |
} |
// }}} |
// {{{ simpleQuery() |
/** |
* Sends a query to the database server |
* |
* @param string the SQL query string |
* |
* @return mixed + a PHP result resrouce for successful SELECT queries |
* + the DB_OK constant for other successful queries |
* + a DB_Error object on failure |
*/ |
function simpleQuery($query) |
{ |
$ismanip = $this->_checkManip($query); |
$this->last_query = $query; |
$this->affected = null; |
if (preg_match('/(SELECT|EXECUTE)/i', $query)) { //TESTME: Use !DB::isManip()? |
// the scroll is needed for fetching absolute row numbers |
// in a select query result |
$result = @ifx_query($query, $this->connection, IFX_SCROLL); |
} else { |
if (!$this->autocommit && $ismanip) { |
if ($this->transaction_opcount == 0) { |
$result = @ifx_query('BEGIN WORK', $this->connection); |
if (!$result) { |
return $this->ifxRaiseError(); |
} |
} |
$this->transaction_opcount++; |
} |
$result = @ifx_query($query, $this->connection); |
} |
if (!$result) { |
return $this->ifxRaiseError(); |
} |
$this->affected = @ifx_affected_rows($result); |
// Determine which queries should return data, and which |
// should return an error code only. |
if (preg_match('/(SELECT|EXECUTE)/i', $query)) { |
return $result; |
} |
// XXX Testme: free results inside a transaction |
// may cause to stop it and commit the work? |
// Result has to be freed even with a insert or update |
@ifx_free_result($result); |
return DB_OK; |
} |
// }}} |
// {{{ nextResult() |
/** |
* Move the internal ifx result pointer to the next available result |
* |
* @param a valid fbsql result resource |
* |
* @access public |
* |
* @return true if a result is available otherwise return false |
*/ |
function nextResult($result) |
{ |
return false; |
} |
// }}} |
// {{{ affectedRows() |
/** |
* Determines the number of rows affected by a data maniuplation query |
* |
* 0 is returned for queries that don't manipulate data. |
* |
* @return int the number of rows. A DB_Error object on failure. |
*/ |
function affectedRows() |
{ |
if ($this->_last_query_manip) { |
return $this->affected; |
} else { |
return 0; |
} |
} |
// }}} |
// {{{ fetchInto() |
/** |
* Places a row from the result set into the given array |
* |
* Formating of the array and the data therein are configurable. |
* See DB_result::fetchInto() for more information. |
* |
* This method is not meant to be called directly. Use |
* DB_result::fetchInto() instead. It can't be declared "protected" |
* because DB_result is a separate object. |
* |
* @param resource $result the query result resource |
* @param array $arr the referenced array to put the data in |
* @param int $fetchmode how the resulting array should be indexed |
* @param int $rownum the row number to fetch (0 = first row) |
* |
* @return mixed DB_OK on success, NULL when the end of a result set is |
* reached or on failure |
* |
* @see DB_result::fetchInto() |
*/ |
function fetchInto($result, &$arr, $fetchmode, $rownum = null) |
{ |
if (($rownum !== null) && ($rownum < 0)) { |
return null; |
} |
if ($rownum === null) { |
/* |
* Even though fetch_row() should return the next row if |
* $rownum is null, it doesn't in all cases. Bug 598. |
*/ |
$rownum = 'NEXT'; |
} else { |
// Index starts at row 1, unlike most DBMS's starting at 0. |
$rownum++; |
} |
if (!$arr = @ifx_fetch_row($result, $rownum)) { |
return null; |
} |
if ($fetchmode !== DB_FETCHMODE_ASSOC) { |
$i=0; |
$order = array(); |
foreach ($arr as $val) { |
$order[$i++] = $val; |
} |
$arr = $order; |
} elseif ($fetchmode == DB_FETCHMODE_ASSOC && |
$this->options['portability'] & DB_PORTABILITY_LOWERCASE) |
{ |
$arr = array_change_key_case($arr, CASE_LOWER); |
} |
if ($this->options['portability'] & DB_PORTABILITY_RTRIM) { |
$this->_rtrimArrayValues($arr); |
} |
if ($this->options['portability'] & DB_PORTABILITY_NULL_TO_EMPTY) { |
$this->_convertNullArrayValuesToEmpty($arr); |
} |
return DB_OK; |
} |
// }}} |
// {{{ numCols() |
/** |
* Gets the number of columns in a result set |
* |
* This method is not meant to be called directly. Use |
* DB_result::numCols() instead. It can't be declared "protected" |
* because DB_result is a separate object. |
* |
* @param resource $result PHP's query result resource |
* |
* @return int the number of columns. A DB_Error object on failure. |
* |
* @see DB_result::numCols() |
*/ |
function numCols($result) |
{ |
if (!$cols = @ifx_num_fields($result)) { |
return $this->ifxRaiseError(); |
} |
return $cols; |
} |
// }}} |
// {{{ freeResult() |
/** |
* Deletes the result set and frees the memory occupied by the result set |
* |
* This method is not meant to be called directly. Use |
* DB_result::free() instead. It can't be declared "protected" |
* because DB_result is a separate object. |
* |
* @param resource $result PHP's query result resource |
* |
* @return bool TRUE on success, FALSE if $result is invalid |
* |
* @see DB_result::free() |
*/ |
function freeResult($result) |
{ |
return is_resource($result) ? ifx_free_result($result) : false; |
} |
// }}} |
// {{{ autoCommit() |
/** |
* Enables or disables automatic commits |
* |
* @param bool $onoff true turns it on, false turns it off |
* |
* @return int DB_OK on success. A DB_Error object if the driver |
* doesn't support auto-committing transactions. |
*/ |
function autoCommit($onoff = true) |
{ |
// XXX if $this->transaction_opcount > 0, we should probably |
// issue a warning here. |
$this->autocommit = $onoff ? true : false; |
return DB_OK; |
} |
// }}} |
// {{{ commit() |
/** |
* Commits the current transaction |
* |
* @return int DB_OK on success. A DB_Error object on failure. |
*/ |
function commit() |
{ |
if ($this->transaction_opcount > 0) { |
$result = @ifx_query('COMMIT WORK', $this->connection); |
$this->transaction_opcount = 0; |
if (!$result) { |
return $this->ifxRaiseError(); |
} |
} |
return DB_OK; |
} |
// }}} |
// {{{ rollback() |
/** |
* Reverts the current transaction |
* |
* @return int DB_OK on success. A DB_Error object on failure. |
*/ |
function rollback() |
{ |
if ($this->transaction_opcount > 0) { |
$result = @ifx_query('ROLLBACK WORK', $this->connection); |
$this->transaction_opcount = 0; |
if (!$result) { |
return $this->ifxRaiseError(); |
} |
} |
return DB_OK; |
} |
// }}} |
// {{{ ifxRaiseError() |
/** |
* Produces a DB_Error object regarding the current problem |
* |
* @param int $errno if the error is being manually raised pass a |
* DB_ERROR* constant here. If this isn't passed |
* the error information gathered from the DBMS. |
* |
* @return object the DB_Error object |
* |
* @see DB_common::raiseError(), |
* DB_ifx::errorNative(), DB_ifx::errorCode() |
*/ |
function ifxRaiseError($errno = null) |
{ |
if ($errno === null) { |
$errno = $this->errorCode(ifx_error()); |
} |
return $this->raiseError($errno, null, null, null, |
$this->errorNative()); |
} |
// }}} |
// {{{ errorNative() |
/** |
* Gets the DBMS' native error code and message produced by the last query |
* |
* @return string the DBMS' error code and message |
*/ |
function errorNative() |
{ |
return @ifx_error() . ' ' . @ifx_errormsg(); |
} |
// }}} |
// {{{ errorCode() |
/** |
* Maps native error codes to DB's portable ones. |
* |
* Requires that the DB implementation's constructor fills |
* in the <var>$errorcode_map</var> property. |
* |
* @param string $nativecode error code returned by the database |
* @return int a portable DB error code, or DB_ERROR if this DB |
* implementation has no mapping for the given error code. |
*/ |
function errorCode($nativecode) |
{ |
if (preg_match('/SQLCODE=(.*)]/', $nativecode, $match)) { |
$code = $match[1]; |
if (isset($this->errorcode_map[$code])) { |
return $this->errorcode_map[$code]; |
} |
} |
return DB_ERROR; |
} |
// }}} |
// {{{ tableInfo() |
/** |
* Returns information about a table or a result set |
* |
* NOTE: only supports 'table' if <var>$result</var> is a table name. |
* |
* If analyzing a query result and the result has duplicate field names, |
* an error will be raised saying |
* <samp>can't distinguish duplicate field names</samp>. |
* |
* @param object|string $result DB_result object from a query or a |
* string containing the name of a table. |
* While this also accepts a query result |
* resource identifier, this behavior is |
* deprecated. |
* @param int $mode a valid tableInfo mode |
* |
* @return array an associative array with the information requested. |
* A DB_Error object on failure. |
* |
* @see DB_common::tableInfo() |
* @since Method available since Release 1.6.0 |
*/ |
function tableInfo($result, $mode = null) |
{ |
if (is_string($result)) { |
/* |
* Probably received a table name. |
* Create a result resource identifier. |
*/ |
$id = @ifx_query("SELECT * FROM $result WHERE 1=0", |
$this->connection); |
$got_string = true; |
} elseif (isset($result->result)) { |
/* |
* Probably received a result object. |
* Extract the result resource identifier. |
*/ |
$id = $result->result; |
$got_string = false; |
} else { |
/* |
* Probably received a result resource identifier. |
* Copy it. |
*/ |
$id = $result; |
$got_string = false; |
} |
if (!is_resource($id)) { |
return $this->ifxRaiseError(DB_ERROR_NEED_MORE_DATA); |
} |
$flds = @ifx_fieldproperties($id); |
$count = @ifx_num_fields($id); |
if (count($flds) != $count) { |
return $this->raiseError("can't distinguish duplicate field names"); |
} |
if ($this->options['portability'] & DB_PORTABILITY_LOWERCASE) { |
$case_func = 'strtolower'; |
} else { |
$case_func = 'strval'; |
} |
$i = 0; |
$res = array(); |
if ($mode) { |
$res['num_fields'] = $count; |
} |
foreach ($flds as $key => $value) { |
$props = explode(';', $value); |
$res[$i] = array( |
'table' => $got_string ? $case_func($result) : '', |
'name' => $case_func($key), |
'type' => $props[0], |
'len' => $props[1], |
'flags' => $props[4] == 'N' ? 'not_null' : '', |
); |
if ($mode & DB_TABLEINFO_ORDER) { |
$res['order'][$res[$i]['name']] = $i; |
} |
if ($mode & DB_TABLEINFO_ORDERTABLE) { |
$res['ordertable'][$res[$i]['table']][$res[$i]['name']] = $i; |
} |
$i++; |
} |
// free the result only if we were called on a table |
if ($got_string) { |
@ifx_free_result($id); |
} |
return $res; |
} |
// }}} |
// {{{ getSpecialQuery() |
/** |
* Obtains the query string needed for listing a given type of objects |
* |
* @param string $type the kind of objects you want to retrieve |
* |
* @return string the SQL query string or null if the driver doesn't |
* support the object type requested |
* |
* @access protected |
* @see DB_common::getListOf() |
*/ |
function getSpecialQuery($type) |
{ |
switch ($type) { |
case 'tables': |
return 'SELECT tabname FROM systables WHERE tabid >= 100'; |
default: |
return null; |
} |
} |
// }}} |
} |
/* |
* Local variables: |
* tab-width: 4 |
* c-basic-offset: 4 |
* End: |
*/ |
?> |
/branches/v1.3-critias/bibliotheque/pear/DB/pgsql.php |
---|
New file |
0,0 → 1,1123 |
<?php |
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */ |
/** |
* The PEAR DB driver for PHP's pgsql extension |
* for interacting with PostgreSQL databases |
* |
* PHP version 5 |
* |
* LICENSE: This source file is subject to version 3.0 of the PHP license |
* that is available through the world-wide-web at the following URI: |
* http://www.php.net/license/3_0.txt. If you did not receive a copy of |
* the PHP License and are unable to obtain it through the web, please |
* send a note to license@php.net so we can mail you a copy immediately. |
* |
* @category Database |
* @package DB |
* @author Rui Hirokawa <hirokawa@php.net> |
* @author Stig Bakken <ssb@php.net> |
* @author Daniel Convissor <danielc@php.net> |
* @copyright 1997-2007 The PHP Group |
* @license http://www.php.net/license/3_0.txt PHP License 3.0 |
* @version CVS: $Id$ |
* @link http://pear.php.net/package/DB |
*/ |
/** |
* Obtain the DB_common class so it can be extended from |
*/ |
require_once 'DB/common.php'; |
/** |
* The methods PEAR DB uses to interact with PHP's pgsql extension |
* for interacting with PostgreSQL databases |
* |
* These methods overload the ones declared in DB_common. |
* |
* @category Database |
* @package DB |
* @author Rui Hirokawa <hirokawa@php.net> |
* @author Stig Bakken <ssb@php.net> |
* @author Daniel Convissor <danielc@php.net> |
* @copyright 1997-2007 The PHP Group |
* @license http://www.php.net/license/3_0.txt PHP License 3.0 |
* @version Release: 1.9.2 |
* @link http://pear.php.net/package/DB |
*/ |
class DB_pgsql extends DB_common |
{ |
// {{{ properties |
/** |
* The DB driver type (mysql, oci8, odbc, etc.) |
* @var string |
*/ |
var $phptype = 'pgsql'; |
/** |
* The database syntax variant to be used (db2, access, etc.), if any |
* @var string |
*/ |
var $dbsyntax = 'pgsql'; |
/** |
* The capabilities of this DB implementation |
* |
* The 'new_link' element contains the PHP version that first provided |
* new_link support for this DBMS. Contains false if it's unsupported. |
* |
* Meaning of the 'limit' element: |
* + 'emulate' = emulate with fetch row by number |
* + 'alter' = alter the query |
* + false = skip rows |
* |
* @var array |
*/ |
var $features = array( |
'limit' => 'alter', |
'new_link' => '4.3.0', |
'numrows' => true, |
'pconnect' => true, |
'prepare' => false, |
'ssl' => true, |
'transactions' => true, |
); |
/** |
* A mapping of native error codes to DB error codes |
* @var array |
*/ |
var $errorcode_map = array( |
); |
/** |
* The raw database connection created by PHP |
* @var resource |
*/ |
var $connection; |
/** |
* The DSN information for connecting to a database |
* @var array |
*/ |
var $dsn = array(); |
/** |
* Should data manipulation queries be committed automatically? |
* @var bool |
* @access private |
*/ |
var $autocommit = true; |
/** |
* The quantity of transactions begun |
* |
* {@internal While this is private, it can't actually be designated |
* private in PHP 5 because it is directly accessed in the test suite.}} |
* |
* @var integer |
* @access private |
*/ |
var $transaction_opcount = 0; |
/** |
* The number of rows affected by a data manipulation query |
* @var integer |
*/ |
var $affected = 0; |
/** |
* The current row being looked at in fetchInto() |
* @var array |
* @access private |
*/ |
var $row = array(); |
/** |
* The number of rows in a given result set |
* @var array |
* @access private |
*/ |
var $_num_rows = array(); |
// }}} |
// {{{ constructor |
/** |
* This constructor calls <kbd>parent::__construct()</kbd> |
* |
* @return void |
*/ |
function __construct() |
{ |
parent::__construct(); |
} |
// }}} |
// {{{ connect() |
/** |
* Connect to the database server, log in and open the database |
* |
* Don't call this method directly. Use DB::connect() instead. |
* |
* PEAR DB's pgsql driver supports the following extra DSN options: |
* + connect_timeout How many seconds to wait for a connection to |
* be established. Available since PEAR DB 1.7.0. |
* + new_link If set to true, causes subsequent calls to |
* connect() to return a new connection link |
* instead of the existing one. WARNING: this is |
* not portable to other DBMS's. Available only |
* if PHP is >= 4.3.0 and PEAR DB is >= 1.7.0. |
* + options Command line options to be sent to the server. |
* Available since PEAR DB 1.6.4. |
* + service Specifies a service name in pg_service.conf that |
* holds additional connection parameters. |
* Available since PEAR DB 1.7.0. |
* + sslmode How should SSL be used when connecting? Values: |
* disable, allow, prefer or require. |
* Available since PEAR DB 1.7.0. |
* + tty This was used to specify where to send server |
* debug output. Available since PEAR DB 1.6.4. |
* |
* Example of connecting to a new link via a socket: |
* <code> |
* require_once 'DB.php'; |
* |
* $dsn = 'pgsql://user:pass@unix(/tmp)/dbname?new_link=true'; |
* $options = array( |
* 'portability' => DB_PORTABILITY_ALL, |
* ); |
* |
* $db = DB::connect($dsn, $options); |
* if (PEAR::isError($db)) { |
* die($db->getMessage()); |
* } |
* </code> |
* |
* @param array $dsn the data source name |
* @param bool $persistent should the connection be persistent? |
* |
* @return int DB_OK on success. A DB_Error object on failure. |
* |
* @link http://www.postgresql.org/docs/current/static/libpq.html#LIBPQ-CONNECT |
*/ |
function connect($dsn, $persistent = false) |
{ |
if (!PEAR::loadExtension('pgsql')) { |
return $this->raiseError(DB_ERROR_EXTENSION_NOT_FOUND); |
} |
$this->dsn = $dsn; |
if ($dsn['dbsyntax']) { |
$this->dbsyntax = $dsn['dbsyntax']; |
} |
$protocol = $dsn['protocol'] ? $dsn['protocol'] : 'tcp'; |
$params = array(''); |
if ($protocol == 'tcp') { |
if ($dsn['hostspec']) { |
$params[0] .= 'host=' . $dsn['hostspec']; |
} |
if ($dsn['port']) { |
$params[0] .= ' port=' . $dsn['port']; |
} |
} elseif ($protocol == 'unix') { |
// Allow for pg socket in non-standard locations. |
if ($dsn['socket']) { |
$params[0] .= 'host=' . $dsn['socket']; |
} |
if ($dsn['port']) { |
$params[0] .= ' port=' . $dsn['port']; |
} |
} |
if ($dsn['database']) { |
$params[0] .= ' dbname=\'' . addslashes($dsn['database']) . '\''; |
} |
if ($dsn['username']) { |
$params[0] .= ' user=\'' . addslashes($dsn['username']) . '\''; |
} |
if ($dsn['password']) { |
$params[0] .= ' password=\'' . addslashes($dsn['password']) . '\''; |
} |
if (!empty($dsn['options'])) { |
$params[0] .= ' options=' . $dsn['options']; |
} |
if (!empty($dsn['tty'])) { |
$params[0] .= ' tty=' . $dsn['tty']; |
} |
if (!empty($dsn['connect_timeout'])) { |
$params[0] .= ' connect_timeout=' . $dsn['connect_timeout']; |
} |
if (!empty($dsn['sslmode'])) { |
$params[0] .= ' sslmode=' . $dsn['sslmode']; |
} |
if (!empty($dsn['service'])) { |
$params[0] .= ' service=' . $dsn['service']; |
} |
if (isset($dsn['new_link']) |
&& ($dsn['new_link'] == 'true' || $dsn['new_link'] === true)) |
{ |
if (version_compare(phpversion(), '4.3.0', '>=')) { |
$params[] = PGSQL_CONNECT_FORCE_NEW; |
} |
} |
$connect_function = $persistent ? 'pg_pconnect' : 'pg_connect'; |
$ini = ini_get('track_errors'); |
$php_errormsg = ''; |
if ($ini) { |
$this->connection = @call_user_func_array($connect_function, |
$params); |
} else { |
@ini_set('track_errors', 1); |
$this->connection = @call_user_func_array($connect_function, |
$params); |
@ini_set('track_errors', $ini); |
} |
if (!$this->connection) { |
return $this->raiseError(DB_ERROR_CONNECT_FAILED, |
null, null, null, |
$php_errormsg); |
} |
return DB_OK; |
} |
// }}} |
// {{{ disconnect() |
/** |
* Disconnects from the database server |
* |
* @return bool TRUE on success, FALSE on failure |
*/ |
function disconnect() |
{ |
$ret = @pg_close($this->connection); |
$this->connection = null; |
return $ret; |
} |
// }}} |
// {{{ simpleQuery() |
/** |
* Sends a query to the database server |
* |
* @param string the SQL query string |
* |
* @return mixed + a PHP result resrouce for successful SELECT queries |
* + the DB_OK constant for other successful queries |
* + a DB_Error object on failure |
*/ |
function simpleQuery($query) |
{ |
$ismanip = $this->_checkManip($query); |
$this->last_query = $query; |
$query = $this->modifyQuery($query); |
if (!$this->autocommit && $ismanip) { |
if ($this->transaction_opcount == 0) { |
$result = @pg_exec($this->connection, 'begin;'); |
if (!$result) { |
return $this->pgsqlRaiseError(); |
} |
} |
$this->transaction_opcount++; |
} |
$result = @pg_exec($this->connection, $query); |
if (!$result) { |
return $this->pgsqlRaiseError(); |
} |
/* |
* Determine whether queries produce affected rows, result or nothing. |
* |
* This logic was introduced in version 1.1 of the file by ssb, |
* though the regex has been modified slightly since then. |
* |
* PostgreSQL commands: |
* ABORT, ALTER, BEGIN, CLOSE, CLUSTER, COMMIT, COPY, |
* CREATE, DECLARE, DELETE, DROP TABLE, EXPLAIN, FETCH, |
* GRANT, INSERT, LISTEN, LOAD, LOCK, MOVE, NOTIFY, RESET, |
* REVOKE, ROLLBACK, SELECT, SELECT INTO, SET, SHOW, |
* UNLISTEN, UPDATE, VACUUM, WITH |
*/ |
if ($ismanip) { |
$this->affected = @pg_affected_rows($result); |
return DB_OK; |
} elseif (preg_match('/^\s*\(*\s*(SELECT|EXPLAIN|FETCH|SHOW|WITH)\s/si', |
$query)) |
{ |
$this->row[(int)$result] = 0; // reset the row counter. |
$numrows = $this->numRows($result); |
if (is_object($numrows)) { |
return $numrows; |
} |
$this->_num_rows[(int)$result] = $numrows; |
$this->affected = 0; |
return $result; |
} else { |
$this->affected = 0; |
return DB_OK; |
} |
} |
// }}} |
// {{{ nextResult() |
/** |
* Move the internal pgsql result pointer to the next available result |
* |
* @param a valid fbsql result resource |
* |
* @access public |
* |
* @return true if a result is available otherwise return false |
*/ |
function nextResult($result) |
{ |
return false; |
} |
// }}} |
// {{{ fetchInto() |
/** |
* Places a row from the result set into the given array |
* |
* Formating of the array and the data therein are configurable. |
* See DB_result::fetchInto() for more information. |
* |
* This method is not meant to be called directly. Use |
* DB_result::fetchInto() instead. It can't be declared "protected" |
* because DB_result is a separate object. |
* |
* @param resource $result the query result resource |
* @param array $arr the referenced array to put the data in |
* @param int $fetchmode how the resulting array should be indexed |
* @param int $rownum the row number to fetch (0 = first row) |
* |
* @return mixed DB_OK on success, NULL when the end of a result set is |
* reached or on failure |
* |
* @see DB_result::fetchInto() |
*/ |
function fetchInto($result, &$arr, $fetchmode, $rownum = null) |
{ |
$result_int = (int)$result; |
$rownum = ($rownum !== null) ? $rownum : $this->row[$result_int]; |
if ($rownum >= $this->_num_rows[$result_int]) { |
return null; |
} |
if ($fetchmode & DB_FETCHMODE_ASSOC) { |
$arr = @pg_fetch_array($result, $rownum, PGSQL_ASSOC); |
if ($this->options['portability'] & DB_PORTABILITY_LOWERCASE && $arr) { |
$arr = array_change_key_case($arr, CASE_LOWER); |
} |
} else { |
$arr = @pg_fetch_row($result, $rownum); |
} |
if (!$arr) { |
return null; |
} |
if ($this->options['portability'] & DB_PORTABILITY_RTRIM) { |
$this->_rtrimArrayValues($arr); |
} |
if ($this->options['portability'] & DB_PORTABILITY_NULL_TO_EMPTY) { |
$this->_convertNullArrayValuesToEmpty($arr); |
} |
$this->row[$result_int] = ++$rownum; |
return DB_OK; |
} |
// }}} |
// {{{ freeResult() |
/** |
* Deletes the result set and frees the memory occupied by the result set |
* |
* This method is not meant to be called directly. Use |
* DB_result::free() instead. It can't be declared "protected" |
* because DB_result is a separate object. |
* |
* @param resource $result PHP's query result resource |
* |
* @return bool TRUE on success, FALSE if $result is invalid |
* |
* @see DB_result::free() |
*/ |
function freeResult($result) |
{ |
if (is_resource($result)) { |
unset($this->row[(int)$result]); |
unset($this->_num_rows[(int)$result]); |
$this->affected = 0; |
return @pg_freeresult($result); |
} |
return false; |
} |
// }}} |
// {{{ quoteBoolean() |
/** |
* Formats a boolean value for use within a query in a locale-independent |
* manner. |
* |
* @param boolean the boolean value to be quoted. |
* @return string the quoted string. |
* @see DB_common::quoteSmart() |
* @since Method available since release 1.7.8. |
*/ |
function quoteBoolean($boolean) { |
return $boolean ? 'TRUE' : 'FALSE'; |
} |
// }}} |
// {{{ escapeSimple() |
/** |
* Escapes a string according to the current DBMS's standards |
* |
* {@internal PostgreSQL treats a backslash as an escape character, |
* so they are escaped as well. |
* |
* @param string $str the string to be escaped |
* |
* @return string the escaped string |
* |
* @see DB_common::quoteSmart() |
* @since Method available since Release 1.6.0 |
*/ |
function escapeSimple($str) |
{ |
if (function_exists('pg_escape_string')) { |
/* This fixes an undocumented BC break in PHP 5.2.0 which changed |
* the prototype of pg_escape_string. I'm not thrilled about having |
* to sniff the PHP version, quite frankly, but it's the only way |
* to deal with the problem. Revision 1.331.2.13.2.10 on |
* php-src/ext/pgsql/pgsql.c (PHP_5_2 branch) is to blame, for the |
* record. */ |
if (version_compare(PHP_VERSION, '5.2.0', '>=')) { |
return pg_escape_string($this->connection, $str); |
} else { |
return pg_escape_string($str); |
} |
} else { |
return str_replace("'", "''", str_replace('\\', '\\\\', $str)); |
} |
} |
// }}} |
// {{{ numCols() |
/** |
* Gets the number of columns in a result set |
* |
* This method is not meant to be called directly. Use |
* DB_result::numCols() instead. It can't be declared "protected" |
* because DB_result is a separate object. |
* |
* @param resource $result PHP's query result resource |
* |
* @return int the number of columns. A DB_Error object on failure. |
* |
* @see DB_result::numCols() |
*/ |
function numCols($result) |
{ |
$cols = @pg_numfields($result); |
if (!$cols) { |
return $this->pgsqlRaiseError(); |
} |
return $cols; |
} |
// }}} |
// {{{ numRows() |
/** |
* Gets the number of rows in a result set |
* |
* This method is not meant to be called directly. Use |
* DB_result::numRows() instead. It can't be declared "protected" |
* because DB_result is a separate object. |
* |
* @param resource $result PHP's query result resource |
* |
* @return int the number of rows. A DB_Error object on failure. |
* |
* @see DB_result::numRows() |
*/ |
function numRows($result) |
{ |
$rows = @pg_numrows($result); |
if ($rows === null) { |
return $this->pgsqlRaiseError(); |
} |
return $rows; |
} |
// }}} |
// {{{ autoCommit() |
/** |
* Enables or disables automatic commits |
* |
* @param bool $onoff true turns it on, false turns it off |
* |
* @return int DB_OK on success. A DB_Error object if the driver |
* doesn't support auto-committing transactions. |
*/ |
function autoCommit($onoff = false) |
{ |
// XXX if $this->transaction_opcount > 0, we should probably |
// issue a warning here. |
$this->autocommit = $onoff ? true : false; |
return DB_OK; |
} |
// }}} |
// {{{ commit() |
/** |
* Commits the current transaction |
* |
* @return int DB_OK on success. A DB_Error object on failure. |
*/ |
function commit() |
{ |
if ($this->transaction_opcount > 0) { |
// (disabled) hack to shut up error messages from libpq.a |
//@fclose(@fopen("php://stderr", "w")); |
$result = @pg_exec($this->connection, 'end;'); |
$this->transaction_opcount = 0; |
if (!$result) { |
return $this->pgsqlRaiseError(); |
} |
} |
return DB_OK; |
} |
// }}} |
// {{{ rollback() |
/** |
* Reverts the current transaction |
* |
* @return int DB_OK on success. A DB_Error object on failure. |
*/ |
function rollback() |
{ |
if ($this->transaction_opcount > 0) { |
$result = @pg_exec($this->connection, 'abort;'); |
$this->transaction_opcount = 0; |
if (!$result) { |
return $this->pgsqlRaiseError(); |
} |
} |
return DB_OK; |
} |
// }}} |
// {{{ affectedRows() |
/** |
* Determines the number of rows affected by a data maniuplation query |
* |
* 0 is returned for queries that don't manipulate data. |
* |
* @return int the number of rows. A DB_Error object on failure. |
*/ |
function affectedRows() |
{ |
return $this->affected; |
} |
// }}} |
// {{{ nextId() |
/** |
* Returns the next free id in a sequence |
* |
* @param string $seq_name name of the sequence |
* @param boolean $ondemand when true, the seqence is automatically |
* created if it does not exist |
* |
* @return int the next id number in the sequence. |
* A DB_Error object on failure. |
* |
* @see DB_common::nextID(), DB_common::getSequenceName(), |
* DB_pgsql::createSequence(), DB_pgsql::dropSequence() |
*/ |
function nextId($seq_name, $ondemand = true) |
{ |
$seqname = $this->getSequenceName($seq_name); |
$repeat = false; |
do { |
$this->pushErrorHandling(PEAR_ERROR_RETURN); |
$result = $this->query("SELECT NEXTVAL('${seqname}')"); |
$this->popErrorHandling(); |
if ($ondemand && DB::isError($result) && |
$result->getCode() == DB_ERROR_NOSUCHTABLE) { |
$repeat = true; |
$this->pushErrorHandling(PEAR_ERROR_RETURN); |
$result = $this->createSequence($seq_name); |
$this->popErrorHandling(); |
if (DB::isError($result)) { |
return $this->raiseError($result); |
} |
} else { |
$repeat = false; |
} |
} while ($repeat); |
if (DB::isError($result)) { |
return $this->raiseError($result); |
} |
$arr = $result->fetchRow(DB_FETCHMODE_ORDERED); |
$result->free(); |
return $arr[0]; |
} |
// }}} |
// {{{ createSequence() |
/** |
* Creates a new sequence |
* |
* @param string $seq_name name of the new sequence |
* |
* @return int DB_OK on success. A DB_Error object on failure. |
* |
* @see DB_common::createSequence(), DB_common::getSequenceName(), |
* DB_pgsql::nextID(), DB_pgsql::dropSequence() |
*/ |
function createSequence($seq_name) |
{ |
$seqname = $this->getSequenceName($seq_name); |
$result = $this->query("CREATE SEQUENCE ${seqname}"); |
return $result; |
} |
// }}} |
// {{{ dropSequence() |
/** |
* Deletes a sequence |
* |
* @param string $seq_name name of the sequence to be deleted |
* |
* @return int DB_OK on success. A DB_Error object on failure. |
* |
* @see DB_common::dropSequence(), DB_common::getSequenceName(), |
* DB_pgsql::nextID(), DB_pgsql::createSequence() |
*/ |
function dropSequence($seq_name) |
{ |
return $this->query('DROP SEQUENCE ' |
. $this->getSequenceName($seq_name)); |
} |
// }}} |
// {{{ modifyLimitQuery() |
/** |
* Adds LIMIT clauses to a query string according to current DBMS standards |
* |
* @param string $query the query to modify |
* @param int $from the row to start to fetching (0 = the first row) |
* @param int $count the numbers of rows to fetch |
* @param mixed $params array, string or numeric data to be used in |
* execution of the statement. Quantity of items |
* passed must match quantity of placeholders in |
* query: meaning 1 placeholder for non-array |
* parameters or 1 placeholder per array element. |
* |
* @return string the query string with LIMIT clauses added |
* |
* @access protected |
*/ |
function modifyLimitQuery($query, $from, $count, $params = array()) |
{ |
return "$query LIMIT $count OFFSET $from"; |
} |
// }}} |
// {{{ pgsqlRaiseError() |
/** |
* Produces a DB_Error object regarding the current problem |
* |
* @param int $errno if the error is being manually raised pass a |
* DB_ERROR* constant here. If this isn't passed |
* the error information gathered from the DBMS. |
* |
* @return object the DB_Error object |
* |
* @see DB_common::raiseError(), |
* DB_pgsql::errorNative(), DB_pgsql::errorCode() |
*/ |
function pgsqlRaiseError($errno = null) |
{ |
$native = $this->errorNative(); |
if (!$native) { |
$native = 'Database connection has been lost.'; |
$errno = DB_ERROR_CONNECT_FAILED; |
} |
if ($errno === null) { |
$errno = $this->errorCode($native); |
} |
return $this->raiseError($errno, null, null, null, $native); |
} |
// }}} |
// {{{ errorNative() |
/** |
* Gets the DBMS' native error message produced by the last query |
* |
* {@internal Error messages are used instead of error codes |
* in order to support older versions of PostgreSQL.}} |
* |
* @return string the DBMS' error message |
*/ |
function errorNative() |
{ |
return @pg_errormessage($this->connection); |
} |
// }}} |
// {{{ errorCode() |
/** |
* Determines PEAR::DB error code from the database's text error message. |
* |
* @param string $errormsg error message returned from the database |
* @return integer an error number from a DB error constant |
*/ |
function errorCode($errormsg) |
{ |
static $error_regexps; |
if (!isset($error_regexps)) { |
$error_regexps = array( |
'/column .* (of relation .*)?does not exist/i' |
=> DB_ERROR_NOSUCHFIELD, |
'/(relation|sequence|table).*does not exist|class .* not found/i' |
=> DB_ERROR_NOSUCHTABLE, |
'/index .* does not exist/' |
=> DB_ERROR_NOT_FOUND, |
'/relation .* already exists/i' |
=> DB_ERROR_ALREADY_EXISTS, |
'/(divide|division) by zero$/i' |
=> DB_ERROR_DIVZERO, |
'/pg_atoi: error in .*: can\'t parse /i' |
=> DB_ERROR_INVALID_NUMBER, |
'/invalid input syntax for( type)? (integer|numeric)/i' |
=> DB_ERROR_INVALID_NUMBER, |
'/value .* is out of range for type \w*int/i' |
=> DB_ERROR_INVALID_NUMBER, |
'/integer out of range/i' |
=> DB_ERROR_INVALID_NUMBER, |
'/value too long for type character/i' |
=> DB_ERROR_INVALID, |
'/attribute .* not found|relation .* does not have attribute/i' |
=> DB_ERROR_NOSUCHFIELD, |
'/column .* specified in USING clause does not exist in (left|right) table/i' |
=> DB_ERROR_NOSUCHFIELD, |
'/parser: parse error at or near/i' |
=> DB_ERROR_SYNTAX, |
'/syntax error at/' |
=> DB_ERROR_SYNTAX, |
'/column reference .* is ambiguous/i' |
=> DB_ERROR_SYNTAX, |
'/permission denied/' |
=> DB_ERROR_ACCESS_VIOLATION, |
'/violates not-null constraint/' |
=> DB_ERROR_CONSTRAINT_NOT_NULL, |
'/violates [\w ]+ constraint/' |
=> DB_ERROR_CONSTRAINT, |
'/referential integrity violation/' |
=> DB_ERROR_CONSTRAINT, |
'/more expressions than target columns/i' |
=> DB_ERROR_VALUE_COUNT_ON_ROW, |
); |
} |
foreach ($error_regexps as $regexp => $code) { |
if (preg_match($regexp, $errormsg)) { |
return $code; |
} |
} |
// Fall back to DB_ERROR if there was no mapping. |
return DB_ERROR; |
} |
// }}} |
// {{{ tableInfo() |
/** |
* Returns information about a table or a result set |
* |
* NOTE: only supports 'table' and 'flags' if <var>$result</var> |
* is a table name. |
* |
* @param object|string $result DB_result object from a query or a |
* string containing the name of a table. |
* While this also accepts a query result |
* resource identifier, this behavior is |
* deprecated. |
* @param int $mode a valid tableInfo mode |
* |
* @return array an associative array with the information requested. |
* A DB_Error object on failure. |
* |
* @see DB_common::tableInfo() |
*/ |
function tableInfo($result, $mode = null) |
{ |
if (is_string($result)) { |
/* |
* Probably received a table name. |
* Create a result resource identifier. |
*/ |
$id = @pg_exec($this->connection, "SELECT * FROM $result LIMIT 0"); |
$got_string = true; |
} elseif (isset($result->result)) { |
/* |
* Probably received a result object. |
* Extract the result resource identifier. |
*/ |
$id = $result->result; |
$got_string = false; |
} else { |
/* |
* Probably received a result resource identifier. |
* Copy it. |
* Deprecated. Here for compatibility only. |
*/ |
$id = $result; |
$got_string = false; |
} |
if (!is_resource($id)) { |
return $this->pgsqlRaiseError(DB_ERROR_NEED_MORE_DATA); |
} |
if ($this->options['portability'] & DB_PORTABILITY_LOWERCASE) { |
$case_func = 'strtolower'; |
} else { |
$case_func = 'strval'; |
} |
$count = @pg_numfields($id); |
$res = array(); |
if ($mode) { |
$res['num_fields'] = $count; |
} |
for ($i = 0; $i < $count; $i++) { |
$res[$i] = array( |
'table' => $got_string ? $case_func($result) : '', |
'name' => $case_func(@pg_fieldname($id, $i)), |
'type' => @pg_fieldtype($id, $i), |
'len' => @pg_fieldsize($id, $i), |
'flags' => $got_string |
? $this->_pgFieldFlags($id, $i, $result) |
: '', |
); |
if ($mode & DB_TABLEINFO_ORDER) { |
$res['order'][$res[$i]['name']] = $i; |
} |
if ($mode & DB_TABLEINFO_ORDERTABLE) { |
$res['ordertable'][$res[$i]['table']][$res[$i]['name']] = $i; |
} |
} |
// free the result only if we were called on a table |
if ($got_string) { |
@pg_freeresult($id); |
} |
return $res; |
} |
// }}} |
// {{{ _pgFieldFlags() |
/** |
* Get a column's flags |
* |
* Supports "not_null", "default_value", "primary_key", "unique_key" |
* and "multiple_key". The default value is passed through |
* rawurlencode() in case there are spaces in it. |
* |
* @param int $resource the PostgreSQL result identifier |
* @param int $num_field the field number |
* |
* @return string the flags |
* |
* @access private |
*/ |
function _pgFieldFlags($resource, $num_field, $table_name) |
{ |
$field_name = @pg_fieldname($resource, $num_field); |
// Check if there's a schema in $table_name and update things |
// accordingly. |
$from = 'pg_attribute f, pg_class tab, pg_type typ'; |
if (strpos($table_name, '.') !== false) { |
$from .= ', pg_namespace nsp'; |
list($schema, $table) = explode('.', $table_name); |
$tableWhere = "tab.relname = '$table' AND tab.relnamespace = nsp.oid AND nsp.nspname = '$schema'"; |
} else { |
$tableWhere = "tab.relname = '$table_name'"; |
} |
$result = @pg_exec($this->connection, "SELECT f.attnotnull, f.atthasdef |
FROM $from |
WHERE tab.relname = typ.typname |
AND typ.typrelid = f.attrelid |
AND f.attname = '$field_name' |
AND $tableWhere"); |
if (@pg_numrows($result) > 0) { |
$row = @pg_fetch_row($result, 0); |
$flags = ($row[0] == 't') ? 'not_null ' : ''; |
if ($row[1] == 't') { |
$result = @pg_exec($this->connection, "SELECT a.adsrc |
FROM $from, pg_attrdef a |
WHERE tab.relname = typ.typname AND typ.typrelid = f.attrelid |
AND f.attrelid = a.adrelid AND f.attname = '$field_name' |
AND $tableWhere AND f.attnum = a.adnum"); |
$row = @pg_fetch_row($result, 0); |
$num = preg_replace("/'(.*)'::\w+/", "\\1", $row[0]); |
$flags .= 'default_' . rawurlencode($num) . ' '; |
} |
} else { |
$flags = ''; |
} |
$result = @pg_exec($this->connection, "SELECT i.indisunique, i.indisprimary, i.indkey |
FROM $from, pg_index i |
WHERE tab.relname = typ.typname |
AND typ.typrelid = f.attrelid |
AND f.attrelid = i.indrelid |
AND f.attname = '$field_name' |
AND $tableWhere"); |
$count = @pg_numrows($result); |
for ($i = 0; $i < $count ; $i++) { |
$row = @pg_fetch_row($result, $i); |
$keys = explode(' ', $row[2]); |
if (in_array($num_field + 1, $keys)) { |
$flags .= ($row[0] == 't' && $row[1] == 'f') ? 'unique_key ' : ''; |
$flags .= ($row[1] == 't') ? 'primary_key ' : ''; |
if (count($keys) > 1) |
$flags .= 'multiple_key '; |
} |
} |
return trim($flags); |
} |
// }}} |
// {{{ getSpecialQuery() |
/** |
* Obtains the query string needed for listing a given type of objects |
* |
* @param string $type the kind of objects you want to retrieve |
* |
* @return string the SQL query string or null if the driver doesn't |
* support the object type requested |
* |
* @access protected |
* @see DB_common::getListOf() |
*/ |
function getSpecialQuery($type) |
{ |
switch ($type) { |
case 'tables': |
return 'SELECT c.relname AS "Name"' |
. ' FROM pg_class c, pg_user u' |
. ' WHERE c.relowner = u.usesysid' |
. " AND c.relkind = 'r'" |
. ' AND NOT EXISTS' |
. ' (SELECT 1 FROM pg_views' |
. ' WHERE viewname = c.relname)' |
. " AND c.relname !~ '^(pg_|sql_)'" |
. ' UNION' |
. ' SELECT c.relname AS "Name"' |
. ' FROM pg_class c' |
. " WHERE c.relkind = 'r'" |
. ' AND NOT EXISTS' |
. ' (SELECT 1 FROM pg_views' |
. ' WHERE viewname = c.relname)' |
. ' AND NOT EXISTS' |
. ' (SELECT 1 FROM pg_user' |
. ' WHERE usesysid = c.relowner)' |
. " AND c.relname !~ '^pg_'"; |
case 'schema.tables': |
return "SELECT schemaname || '.' || tablename" |
. ' AS "Name"' |
. ' FROM pg_catalog.pg_tables' |
. ' WHERE schemaname NOT IN' |
. " ('pg_catalog', 'information_schema', 'pg_toast')"; |
case 'schema.views': |
return "SELECT schemaname || '.' || viewname from pg_views WHERE schemaname" |
. " NOT IN ('information_schema', 'pg_catalog')"; |
case 'views': |
// Table cols: viewname | viewowner | definition |
return 'SELECT viewname from pg_views WHERE schemaname' |
. " NOT IN ('information_schema', 'pg_catalog')"; |
case 'users': |
// cols: usename |usesysid|usecreatedb|usetrace|usesuper|usecatupd|passwd |valuntil |
return 'SELECT usename FROM pg_user'; |
case 'databases': |
return 'SELECT datname FROM pg_database'; |
case 'functions': |
case 'procedures': |
return 'SELECT proname FROM pg_proc WHERE proowner <> 1'; |
default: |
return null; |
} |
} |
// }}} |
// {{{ _checkManip() |
/** |
* Checks if the given query is a manipulation query. This also takes into |
* account the _next_query_manip flag and sets the _last_query_manip flag |
* (and resets _next_query_manip) according to the result. |
* |
* @param string The query to check. |
* |
* @return boolean true if the query is a manipulation query, false |
* otherwise |
* |
* @access protected |
*/ |
function _checkManip($query) |
{ |
return (preg_match('/^\s*(SAVEPOINT|RELEASE)\s+/i', $query) |
|| parent::_checkManip($query)); |
} |
} |
/* |
* Local variables: |
* tab-width: 4 |
* c-basic-offset: 4 |
* End: |
*/ |
?> |
/branches/v1.3-critias/bibliotheque/pear/DB/sybase.php |
---|
New file |
0,0 → 1,942 |
<?php |
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */ |
/** |
* The PEAR DB driver for PHP's sybase extension |
* for interacting with Sybase databases |
* |
* PHP version 5 |
* |
* LICENSE: This source file is subject to version 3.0 of the PHP license |
* that is available through the world-wide-web at the following URI: |
* http://www.php.net/license/3_0.txt. If you did not receive a copy of |
* the PHP License and are unable to obtain it through the web, please |
* send a note to license@php.net so we can mail you a copy immediately. |
* |
* @category Database |
* @package DB |
* @author Sterling Hughes <sterling@php.net> |
* @author Antônio Carlos Venâncio Júnior <floripa@php.net> |
* @author Daniel Convissor <danielc@php.net> |
* @copyright 1997-2007 The PHP Group |
* @license http://www.php.net/license/3_0.txt PHP License 3.0 |
* @version CVS: $Id$ |
* @link http://pear.php.net/package/DB |
*/ |
/** |
* Obtain the DB_common class so it can be extended from |
*/ |
require_once 'DB/common.php'; |
/** |
* The methods PEAR DB uses to interact with PHP's sybase extension |
* for interacting with Sybase databases |
* |
* These methods overload the ones declared in DB_common. |
* |
* WARNING: This driver may fail with multiple connections under the |
* same user/pass/host and different databases. |
* |
* @category Database |
* @package DB |
* @author Sterling Hughes <sterling@php.net> |
* @author Antônio Carlos Venâncio Júnior <floripa@php.net> |
* @author Daniel Convissor <danielc@php.net> |
* @copyright 1997-2007 The PHP Group |
* @license http://www.php.net/license/3_0.txt PHP License 3.0 |
* @version Release: 1.9.2 |
* @link http://pear.php.net/package/DB |
*/ |
class DB_sybase extends DB_common |
{ |
// {{{ properties |
/** |
* The DB driver type (mysql, oci8, odbc, etc.) |
* @var string |
*/ |
var $phptype = 'sybase'; |
/** |
* The database syntax variant to be used (db2, access, etc.), if any |
* @var string |
*/ |
var $dbsyntax = 'sybase'; |
/** |
* The capabilities of this DB implementation |
* |
* The 'new_link' element contains the PHP version that first provided |
* new_link support for this DBMS. Contains false if it's unsupported. |
* |
* Meaning of the 'limit' element: |
* + 'emulate' = emulate with fetch row by number |
* + 'alter' = alter the query |
* + false = skip rows |
* |
* @var array |
*/ |
var $features = array( |
'limit' => 'emulate', |
'new_link' => false, |
'numrows' => true, |
'pconnect' => true, |
'prepare' => false, |
'ssl' => false, |
'transactions' => true, |
); |
/** |
* A mapping of native error codes to DB error codes |
* @var array |
*/ |
var $errorcode_map = array( |
); |
/** |
* The raw database connection created by PHP |
* @var resource |
*/ |
var $connection; |
/** |
* The DSN information for connecting to a database |
* @var array |
*/ |
var $dsn = array(); |
/** |
* Should data manipulation queries be committed automatically? |
* @var bool |
* @access private |
*/ |
var $autocommit = true; |
/** |
* The quantity of transactions begun |
* |
* {@internal While this is private, it can't actually be designated |
* private in PHP 5 because it is directly accessed in the test suite.}} |
* |
* @var integer |
* @access private |
*/ |
var $transaction_opcount = 0; |
/** |
* The database specified in the DSN |
* |
* It's a fix to allow calls to different databases in the same script. |
* |
* @var string |
* @access private |
*/ |
var $_db = ''; |
// }}} |
// {{{ constructor |
/** |
* This constructor calls <kbd>parent::__construct()</kbd> |
* |
* @return void |
*/ |
function __construct() |
{ |
parent::__construct(); |
} |
// }}} |
// {{{ connect() |
/** |
* Connect to the database server, log in and open the database |
* |
* Don't call this method directly. Use DB::connect() instead. |
* |
* PEAR DB's sybase driver supports the following extra DSN options: |
* + appname The application name to use on this connection. |
* Available since PEAR DB 1.7.0. |
* + charset The character set to use on this connection. |
* Available since PEAR DB 1.7.0. |
* |
* @param array $dsn the data source name |
* @param bool $persistent should the connection be persistent? |
* |
* @return int DB_OK on success. A DB_Error object on failure. |
*/ |
function connect($dsn, $persistent = false) |
{ |
if (!PEAR::loadExtension('sybase') && |
!PEAR::loadExtension('sybase_ct')) |
{ |
return $this->raiseError(DB_ERROR_EXTENSION_NOT_FOUND); |
} |
$this->dsn = $dsn; |
if ($dsn['dbsyntax']) { |
$this->dbsyntax = $dsn['dbsyntax']; |
} |
$dsn['hostspec'] = $dsn['hostspec'] ? $dsn['hostspec'] : 'localhost'; |
$dsn['password'] = !empty($dsn['password']) ? $dsn['password'] : false; |
$dsn['charset'] = isset($dsn['charset']) ? $dsn['charset'] : false; |
$dsn['appname'] = isset($dsn['appname']) ? $dsn['appname'] : false; |
$connect_function = $persistent ? 'sybase_pconnect' : 'sybase_connect'; |
if ($dsn['username']) { |
$this->connection = @$connect_function($dsn['hostspec'], |
$dsn['username'], |
$dsn['password'], |
$dsn['charset'], |
$dsn['appname']); |
} else { |
return $this->raiseError(DB_ERROR_CONNECT_FAILED, |
null, null, null, |
'The DSN did not contain a username.'); |
} |
if (!$this->connection) { |
return $this->raiseError(DB_ERROR_CONNECT_FAILED, |
null, null, null, |
@sybase_get_last_message()); |
} |
if ($dsn['database']) { |
if (!@sybase_select_db($dsn['database'], $this->connection)) { |
return $this->raiseError(DB_ERROR_NODBSELECTED, |
null, null, null, |
@sybase_get_last_message()); |
} |
$this->_db = $dsn['database']; |
} |
return DB_OK; |
} |
// }}} |
// {{{ disconnect() |
/** |
* Disconnects from the database server |
* |
* @return bool TRUE on success, FALSE on failure |
*/ |
function disconnect() |
{ |
$ret = @sybase_close($this->connection); |
$this->connection = null; |
return $ret; |
} |
// }}} |
// {{{ simpleQuery() |
/** |
* Sends a query to the database server |
* |
* @param string the SQL query string |
* |
* @return mixed + a PHP result resrouce for successful SELECT queries |
* + the DB_OK constant for other successful queries |
* + a DB_Error object on failure |
*/ |
function simpleQuery($query) |
{ |
$ismanip = $this->_checkManip($query); |
$this->last_query = $query; |
if ($this->_db && !@sybase_select_db($this->_db, $this->connection)) { |
return $this->sybaseRaiseError(DB_ERROR_NODBSELECTED); |
} |
$query = $this->modifyQuery($query); |
if (!$this->autocommit && $ismanip) { |
if ($this->transaction_opcount == 0) { |
$result = @sybase_query('BEGIN TRANSACTION', $this->connection); |
if (!$result) { |
return $this->sybaseRaiseError(); |
} |
} |
$this->transaction_opcount++; |
} |
$result = @sybase_query($query, $this->connection); |
if (!$result) { |
return $this->sybaseRaiseError(); |
} |
if (is_resource($result)) { |
return $result; |
} |
// Determine which queries that should return data, and which |
// should return an error code only. |
return $ismanip ? DB_OK : $result; |
} |
// }}} |
// {{{ nextResult() |
/** |
* Move the internal sybase result pointer to the next available result |
* |
* @param a valid sybase result resource |
* |
* @access public |
* |
* @return true if a result is available otherwise return false |
*/ |
function nextResult($result) |
{ |
return false; |
} |
// }}} |
// {{{ fetchInto() |
/** |
* Places a row from the result set into the given array |
* |
* Formating of the array and the data therein are configurable. |
* See DB_result::fetchInto() for more information. |
* |
* This method is not meant to be called directly. Use |
* DB_result::fetchInto() instead. It can't be declared "protected" |
* because DB_result is a separate object. |
* |
* @param resource $result the query result resource |
* @param array $arr the referenced array to put the data in |
* @param int $fetchmode how the resulting array should be indexed |
* @param int $rownum the row number to fetch (0 = first row) |
* |
* @return mixed DB_OK on success, NULL when the end of a result set is |
* reached or on failure |
* |
* @see DB_result::fetchInto() |
*/ |
function fetchInto($result, &$arr, $fetchmode, $rownum = null) |
{ |
if ($rownum !== null) { |
if (!@sybase_data_seek($result, $rownum)) { |
return null; |
} |
} |
if ($fetchmode & DB_FETCHMODE_ASSOC) { |
if (function_exists('sybase_fetch_assoc')) { |
$arr = @sybase_fetch_assoc($result); |
} else { |
if ($arr = @sybase_fetch_array($result)) { |
foreach ($arr as $key => $value) { |
if (is_int($key)) { |
unset($arr[$key]); |
} |
} |
} |
} |
if ($this->options['portability'] & DB_PORTABILITY_LOWERCASE && $arr) { |
$arr = array_change_key_case($arr, CASE_LOWER); |
} |
} else { |
$arr = @sybase_fetch_row($result); |
} |
if (!$arr) { |
return null; |
} |
if ($this->options['portability'] & DB_PORTABILITY_RTRIM) { |
$this->_rtrimArrayValues($arr); |
} |
if ($this->options['portability'] & DB_PORTABILITY_NULL_TO_EMPTY) { |
$this->_convertNullArrayValuesToEmpty($arr); |
} |
return DB_OK; |
} |
// }}} |
// {{{ freeResult() |
/** |
* Deletes the result set and frees the memory occupied by the result set |
* |
* This method is not meant to be called directly. Use |
* DB_result::free() instead. It can't be declared "protected" |
* because DB_result is a separate object. |
* |
* @param resource $result PHP's query result resource |
* |
* @return bool TRUE on success, FALSE if $result is invalid |
* |
* @see DB_result::free() |
*/ |
function freeResult($result) |
{ |
return is_resource($result) ? sybase_free_result($result) : false; |
} |
// }}} |
// {{{ numCols() |
/** |
* Gets the number of columns in a result set |
* |
* This method is not meant to be called directly. Use |
* DB_result::numCols() instead. It can't be declared "protected" |
* because DB_result is a separate object. |
* |
* @param resource $result PHP's query result resource |
* |
* @return int the number of columns. A DB_Error object on failure. |
* |
* @see DB_result::numCols() |
*/ |
function numCols($result) |
{ |
$cols = @sybase_num_fields($result); |
if (!$cols) { |
return $this->sybaseRaiseError(); |
} |
return $cols; |
} |
// }}} |
// {{{ numRows() |
/** |
* Gets the number of rows in a result set |
* |
* This method is not meant to be called directly. Use |
* DB_result::numRows() instead. It can't be declared "protected" |
* because DB_result is a separate object. |
* |
* @param resource $result PHP's query result resource |
* |
* @return int the number of rows. A DB_Error object on failure. |
* |
* @see DB_result::numRows() |
*/ |
function numRows($result) |
{ |
$rows = @sybase_num_rows($result); |
if ($rows === false) { |
return $this->sybaseRaiseError(); |
} |
return $rows; |
} |
// }}} |
// {{{ affectedRows() |
/** |
* Determines the number of rows affected by a data maniuplation query |
* |
* 0 is returned for queries that don't manipulate data. |
* |
* @return int the number of rows. A DB_Error object on failure. |
*/ |
function affectedRows() |
{ |
if ($this->_last_query_manip) { |
$result = @sybase_affected_rows($this->connection); |
} else { |
$result = 0; |
} |
return $result; |
} |
// }}} |
// {{{ nextId() |
/** |
* Returns the next free id in a sequence |
* |
* @param string $seq_name name of the sequence |
* @param boolean $ondemand when true, the seqence is automatically |
* created if it does not exist |
* |
* @return int the next id number in the sequence. |
* A DB_Error object on failure. |
* |
* @see DB_common::nextID(), DB_common::getSequenceName(), |
* DB_sybase::createSequence(), DB_sybase::dropSequence() |
*/ |
function nextId($seq_name, $ondemand = true) |
{ |
$seqname = $this->getSequenceName($seq_name); |
if ($this->_db && !@sybase_select_db($this->_db, $this->connection)) { |
return $this->sybaseRaiseError(DB_ERROR_NODBSELECTED); |
} |
$repeat = 0; |
do { |
$this->pushErrorHandling(PEAR_ERROR_RETURN); |
$result = $this->query("INSERT INTO $seqname (vapor) VALUES (0)"); |
$this->popErrorHandling(); |
if ($ondemand && DB::isError($result) && |
($result->getCode() == DB_ERROR || $result->getCode() == DB_ERROR_NOSUCHTABLE)) |
{ |
$repeat = 1; |
$result = $this->createSequence($seq_name); |
if (DB::isError($result)) { |
return $this->raiseError($result); |
} |
} elseif (!DB::isError($result)) { |
$result = $this->query("SELECT @@IDENTITY FROM $seqname"); |
$repeat = 0; |
} else { |
$repeat = false; |
} |
} while ($repeat); |
if (DB::isError($result)) { |
return $this->raiseError($result); |
} |
$result = $result->fetchRow(DB_FETCHMODE_ORDERED); |
return $result[0]; |
} |
/** |
* Creates a new sequence |
* |
* @param string $seq_name name of the new sequence |
* |
* @return int DB_OK on success. A DB_Error object on failure. |
* |
* @see DB_common::createSequence(), DB_common::getSequenceName(), |
* DB_sybase::nextID(), DB_sybase::dropSequence() |
*/ |
function createSequence($seq_name) |
{ |
return $this->query('CREATE TABLE ' |
. $this->getSequenceName($seq_name) |
. ' (id numeric(10, 0) IDENTITY NOT NULL,' |
. ' vapor int NULL)'); |
} |
// }}} |
// {{{ dropSequence() |
/** |
* Deletes a sequence |
* |
* @param string $seq_name name of the sequence to be deleted |
* |
* @return int DB_OK on success. A DB_Error object on failure. |
* |
* @see DB_common::dropSequence(), DB_common::getSequenceName(), |
* DB_sybase::nextID(), DB_sybase::createSequence() |
*/ |
function dropSequence($seq_name) |
{ |
return $this->query('DROP TABLE ' . $this->getSequenceName($seq_name)); |
} |
// }}} |
// {{{ quoteFloat() |
/** |
* Formats a float value for use within a query in a locale-independent |
* manner. |
* |
* @param float the float value to be quoted. |
* @return string the quoted string. |
* @see DB_common::quoteSmart() |
* @since Method available since release 1.7.8. |
*/ |
function quoteFloat($float) { |
return $this->escapeSimple(str_replace(',', '.', strval(floatval($float)))); |
} |
// }}} |
// {{{ autoCommit() |
/** |
* Enables or disables automatic commits |
* |
* @param bool $onoff true turns it on, false turns it off |
* |
* @return int DB_OK on success. A DB_Error object if the driver |
* doesn't support auto-committing transactions. |
*/ |
function autoCommit($onoff = false) |
{ |
// XXX if $this->transaction_opcount > 0, we should probably |
// issue a warning here. |
$this->autocommit = $onoff ? true : false; |
return DB_OK; |
} |
// }}} |
// {{{ commit() |
/** |
* Commits the current transaction |
* |
* @return int DB_OK on success. A DB_Error object on failure. |
*/ |
function commit() |
{ |
if ($this->transaction_opcount > 0) { |
if ($this->_db && !@sybase_select_db($this->_db, $this->connection)) { |
return $this->sybaseRaiseError(DB_ERROR_NODBSELECTED); |
} |
$result = @sybase_query('COMMIT', $this->connection); |
$this->transaction_opcount = 0; |
if (!$result) { |
return $this->sybaseRaiseError(); |
} |
} |
return DB_OK; |
} |
// }}} |
// {{{ rollback() |
/** |
* Reverts the current transaction |
* |
* @return int DB_OK on success. A DB_Error object on failure. |
*/ |
function rollback() |
{ |
if ($this->transaction_opcount > 0) { |
if ($this->_db && !@sybase_select_db($this->_db, $this->connection)) { |
return $this->sybaseRaiseError(DB_ERROR_NODBSELECTED); |
} |
$result = @sybase_query('ROLLBACK', $this->connection); |
$this->transaction_opcount = 0; |
if (!$result) { |
return $this->sybaseRaiseError(); |
} |
} |
return DB_OK; |
} |
// }}} |
// {{{ sybaseRaiseError() |
/** |
* Produces a DB_Error object regarding the current problem |
* |
* @param int $errno if the error is being manually raised pass a |
* DB_ERROR* constant here. If this isn't passed |
* the error information gathered from the DBMS. |
* |
* @return object the DB_Error object |
* |
* @see DB_common::raiseError(), |
* DB_sybase::errorNative(), DB_sybase::errorCode() |
*/ |
function sybaseRaiseError($errno = null) |
{ |
$native = $this->errorNative(); |
if ($errno === null) { |
$errno = $this->errorCode($native); |
} |
return $this->raiseError($errno, null, null, null, $native); |
} |
// }}} |
// {{{ errorNative() |
/** |
* Gets the DBMS' native error message produced by the last query |
* |
* @return string the DBMS' error message |
*/ |
function errorNative() |
{ |
return @sybase_get_last_message(); |
} |
// }}} |
// {{{ errorCode() |
/** |
* Determines PEAR::DB error code from the database's text error message. |
* |
* @param string $errormsg error message returned from the database |
* @return integer an error number from a DB error constant |
*/ |
function errorCode($errormsg) |
{ |
static $error_regexps; |
// PHP 5.2+ prepends the function name to $php_errormsg, so we need |
// this hack to work around it, per bug #9599. |
$errormsg = preg_replace('/^sybase[a-z_]+\(\): /', '', $errormsg); |
if (!isset($error_regexps)) { |
$error_regexps = array( |
'/Incorrect syntax near/' |
=> DB_ERROR_SYNTAX, |
'/^Unclosed quote before the character string [\"\'].*[\"\']\./' |
=> DB_ERROR_SYNTAX, |
'/Implicit conversion (from datatype|of NUMERIC value)/i' |
=> DB_ERROR_INVALID_NUMBER, |
'/Cannot drop the table [\"\'].+[\"\'], because it doesn\'t exist in the system catalogs\./' |
=> DB_ERROR_NOSUCHTABLE, |
'/Only the owner of object [\"\'].+[\"\'] or a user with System Administrator \(SA\) role can run this command\./' |
=> DB_ERROR_ACCESS_VIOLATION, |
'/^.+ permission denied on object .+, database .+, owner .+/' |
=> DB_ERROR_ACCESS_VIOLATION, |
'/^.* permission denied, database .+, owner .+/' |
=> DB_ERROR_ACCESS_VIOLATION, |
'/[^.*] not found\./' |
=> DB_ERROR_NOSUCHTABLE, |
'/There is already an object named/' |
=> DB_ERROR_ALREADY_EXISTS, |
'/Invalid column name/' |
=> DB_ERROR_NOSUCHFIELD, |
'/does not allow null values/' |
=> DB_ERROR_CONSTRAINT_NOT_NULL, |
'/Command has been aborted/' |
=> DB_ERROR_CONSTRAINT, |
'/^Cannot drop the index .* because it doesn\'t exist/i' |
=> DB_ERROR_NOT_FOUND, |
'/^There is already an index/i' |
=> DB_ERROR_ALREADY_EXISTS, |
'/^There are fewer columns in the INSERT statement than values specified/i' |
=> DB_ERROR_VALUE_COUNT_ON_ROW, |
'/Divide by zero/i' |
=> DB_ERROR_DIVZERO, |
); |
} |
foreach ($error_regexps as $regexp => $code) { |
if (preg_match($regexp, $errormsg)) { |
return $code; |
} |
} |
return DB_ERROR; |
} |
// }}} |
// {{{ tableInfo() |
/** |
* Returns information about a table or a result set |
* |
* NOTE: only supports 'table' and 'flags' if <var>$result</var> |
* is a table name. |
* |
* @param object|string $result DB_result object from a query or a |
* string containing the name of a table. |
* While this also accepts a query result |
* resource identifier, this behavior is |
* deprecated. |
* @param int $mode a valid tableInfo mode |
* |
* @return array an associative array with the information requested. |
* A DB_Error object on failure. |
* |
* @see DB_common::tableInfo() |
* @since Method available since Release 1.6.0 |
*/ |
function tableInfo($result, $mode = null) |
{ |
if (is_string($result)) { |
/* |
* Probably received a table name. |
* Create a result resource identifier. |
*/ |
if ($this->_db && !@sybase_select_db($this->_db, $this->connection)) { |
return $this->sybaseRaiseError(DB_ERROR_NODBSELECTED); |
} |
$id = @sybase_query("SELECT * FROM $result WHERE 1=0", |
$this->connection); |
$got_string = true; |
} elseif (isset($result->result)) { |
/* |
* Probably received a result object. |
* Extract the result resource identifier. |
*/ |
$id = $result->result; |
$got_string = false; |
} else { |
/* |
* Probably received a result resource identifier. |
* Copy it. |
* Deprecated. Here for compatibility only. |
*/ |
$id = $result; |
$got_string = false; |
} |
if (!is_resource($id)) { |
return $this->sybaseRaiseError(DB_ERROR_NEED_MORE_DATA); |
} |
if ($this->options['portability'] & DB_PORTABILITY_LOWERCASE) { |
$case_func = 'strtolower'; |
} else { |
$case_func = 'strval'; |
} |
$count = @sybase_num_fields($id); |
$res = array(); |
if ($mode) { |
$res['num_fields'] = $count; |
} |
for ($i = 0; $i < $count; $i++) { |
$f = @sybase_fetch_field($id, $i); |
// column_source is often blank |
$res[$i] = array( |
'table' => $got_string |
? $case_func($result) |
: $case_func($f->column_source), |
'name' => $case_func($f->name), |
'type' => $f->type, |
'len' => $f->max_length, |
'flags' => '', |
); |
if ($res[$i]['table']) { |
$res[$i]['flags'] = $this->_sybase_field_flags( |
$res[$i]['table'], $res[$i]['name']); |
} |
if ($mode & DB_TABLEINFO_ORDER) { |
$res['order'][$res[$i]['name']] = $i; |
} |
if ($mode & DB_TABLEINFO_ORDERTABLE) { |
$res['ordertable'][$res[$i]['table']][$res[$i]['name']] = $i; |
} |
} |
// free the result only if we were called on a table |
if ($got_string) { |
@sybase_free_result($id); |
} |
return $res; |
} |
// }}} |
// {{{ _sybase_field_flags() |
/** |
* Get the flags for a field |
* |
* Currently supports: |
* + <samp>unique_key</samp> (unique index, unique check or primary_key) |
* + <samp>multiple_key</samp> (multi-key index) |
* |
* @param string $table the table name |
* @param string $column the field name |
* |
* @return string space delimited string of flags. Empty string if none. |
* |
* @access private |
*/ |
function _sybase_field_flags($table, $column) |
{ |
static $tableName = null; |
static $flags = array(); |
if ($table != $tableName) { |
$flags = array(); |
$tableName = $table; |
/* We're running sp_helpindex directly because it doesn't exist in |
* older versions of ASE -- unfortunately, we can't just use |
* DB::isError() because the user may be using callback error |
* handling. */ |
$res = @sybase_query("sp_helpindex $table", $this->connection); |
if ($res === false || $res === true) { |
// Fake a valid response for BC reasons. |
return ''; |
} |
while (($val = sybase_fetch_assoc($res)) !== false) { |
if (!isset($val['index_keys'])) { |
/* No useful information returned. Break and be done with |
* it, which preserves the pre-1.7.9 behaviour. */ |
break; |
} |
$keys = explode(', ', trim($val['index_keys'])); |
if (sizeof($keys) > 1) { |
foreach ($keys as $key) { |
$this->_add_flag($flags[$key], 'multiple_key'); |
} |
} |
if (strpos($val['index_description'], 'unique')) { |
foreach ($keys as $key) { |
$this->_add_flag($flags[$key], 'unique_key'); |
} |
} |
} |
sybase_free_result($res); |
} |
if (array_key_exists($column, $flags)) { |
return(implode(' ', $flags[$column])); |
} |
return ''; |
} |
// }}} |
// {{{ _add_flag() |
/** |
* Adds a string to the flags array if the flag is not yet in there |
* - if there is no flag present the array is created |
* |
* @param array $array reference of flags array to add a value to |
* @param mixed $value value to add to the flag array |
* |
* @return void |
* |
* @access private |
*/ |
function _add_flag(&$array, $value) |
{ |
if (!is_array($array)) { |
$array = array($value); |
} elseif (!in_array($value, $array)) { |
array_push($array, $value); |
} |
} |
// }}} |
// {{{ getSpecialQuery() |
/** |
* Obtains the query string needed for listing a given type of objects |
* |
* @param string $type the kind of objects you want to retrieve |
* |
* @return string the SQL query string or null if the driver doesn't |
* support the object type requested |
* |
* @access protected |
* @see DB_common::getListOf() |
*/ |
function getSpecialQuery($type) |
{ |
switch ($type) { |
case 'tables': |
return "SELECT name FROM sysobjects WHERE type = 'U'" |
. ' ORDER BY name'; |
case 'views': |
return "SELECT name FROM sysobjects WHERE type = 'V'"; |
default: |
return null; |
} |
} |
// }}} |
} |
/* |
* Local variables: |
* tab-width: 4 |
* c-basic-offset: 4 |
* End: |
*/ |
?> |
/branches/v1.3-critias/bibliotheque/pear/DB/fbsql.php |
---|
New file |
0,0 → 1,769 |
<?php |
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */ |
/** |
* The PEAR DB driver for PHP's fbsql extension |
* for interacting with FrontBase databases |
* |
* PHP version 5 |
* |
* LICENSE: This source file is subject to version 3.0 of the PHP license |
* that is available through the world-wide-web at the following URI: |
* http://www.php.net/license/3_0.txt. If you did not receive a copy of |
* the PHP License and are unable to obtain it through the web, please |
* send a note to license@php.net so we can mail you a copy immediately. |
* |
* @category Database |
* @package DB |
* @author Frank M. Kromann <frank@frontbase.com> |
* @author Daniel Convissor <danielc@php.net> |
* @copyright 1997-2007 The PHP Group |
* @license http://www.php.net/license/3_0.txt PHP License 3.0 |
* @version CVS: $Id$ |
* @link http://pear.php.net/package/DB |
*/ |
/** |
* Obtain the DB_common class so it can be extended from |
*/ |
require_once 'DB/common.php'; |
/** |
* The methods PEAR DB uses to interact with PHP's fbsql extension |
* for interacting with FrontBase databases |
* |
* These methods overload the ones declared in DB_common. |
* |
* @category Database |
* @package DB |
* @author Frank M. Kromann <frank@frontbase.com> |
* @author Daniel Convissor <danielc@php.net> |
* @copyright 1997-2007 The PHP Group |
* @license http://www.php.net/license/3_0.txt PHP License 3.0 |
* @version Release: 1.9.2 |
* @link http://pear.php.net/package/DB |
* @since Class functional since Release 1.7.0 |
*/ |
class DB_fbsql extends DB_common |
{ |
// {{{ properties |
/** |
* The DB driver type (mysql, oci8, odbc, etc.) |
* @var string |
*/ |
var $phptype = 'fbsql'; |
/** |
* The database syntax variant to be used (db2, access, etc.), if any |
* @var string |
*/ |
var $dbsyntax = 'fbsql'; |
/** |
* The capabilities of this DB implementation |
* |
* The 'new_link' element contains the PHP version that first provided |
* new_link support for this DBMS. Contains false if it's unsupported. |
* |
* Meaning of the 'limit' element: |
* + 'emulate' = emulate with fetch row by number |
* + 'alter' = alter the query |
* + false = skip rows |
* |
* @var array |
*/ |
var $features = array( |
'limit' => 'alter', |
'new_link' => false, |
'numrows' => true, |
'pconnect' => true, |
'prepare' => false, |
'ssl' => false, |
'transactions' => true, |
); |
/** |
* A mapping of native error codes to DB error codes |
* @var array |
*/ |
var $errorcode_map = array( |
22 => DB_ERROR_SYNTAX, |
85 => DB_ERROR_ALREADY_EXISTS, |
108 => DB_ERROR_SYNTAX, |
116 => DB_ERROR_NOSUCHTABLE, |
124 => DB_ERROR_VALUE_COUNT_ON_ROW, |
215 => DB_ERROR_NOSUCHFIELD, |
217 => DB_ERROR_INVALID_NUMBER, |
226 => DB_ERROR_NOSUCHFIELD, |
231 => DB_ERROR_INVALID, |
239 => DB_ERROR_TRUNCATED, |
251 => DB_ERROR_SYNTAX, |
266 => DB_ERROR_NOT_FOUND, |
357 => DB_ERROR_CONSTRAINT_NOT_NULL, |
358 => DB_ERROR_CONSTRAINT, |
360 => DB_ERROR_CONSTRAINT, |
361 => DB_ERROR_CONSTRAINT, |
); |
/** |
* The raw database connection created by PHP |
* @var resource |
*/ |
var $connection; |
/** |
* The DSN information for connecting to a database |
* @var array |
*/ |
var $dsn = array(); |
// }}} |
// {{{ constructor |
/** |
* This constructor calls <kbd>parent::__construct()</kbd> |
* |
* @return void |
*/ |
function __construct() |
{ |
parent::__construct(); |
} |
// }}} |
// {{{ connect() |
/** |
* Connect to the database server, log in and open the database |
* |
* Don't call this method directly. Use DB::connect() instead. |
* |
* @param array $dsn the data source name |
* @param bool $persistent should the connection be persistent? |
* |
* @return int DB_OK on success. A DB_Error object on failure. |
*/ |
function connect($dsn, $persistent = false) |
{ |
if (!PEAR::loadExtension('fbsql')) { |
return $this->raiseError(DB_ERROR_EXTENSION_NOT_FOUND); |
} |
$this->dsn = $dsn; |
if ($dsn['dbsyntax']) { |
$this->dbsyntax = $dsn['dbsyntax']; |
} |
$params = array( |
$dsn['hostspec'] ? $dsn['hostspec'] : 'localhost', |
$dsn['username'] ? $dsn['username'] : null, |
$dsn['password'] ? $dsn['password'] : null, |
); |
$connect_function = $persistent ? 'fbsql_pconnect' : 'fbsql_connect'; |
$ini = ini_get('track_errors'); |
$php_errormsg = ''; |
if ($ini) { |
$this->connection = @call_user_func_array($connect_function, |
$params); |
} else { |
@ini_set('track_errors', 1); |
$this->connection = @call_user_func_array($connect_function, |
$params); |
@ini_set('track_errors', $ini); |
} |
if (!$this->connection) { |
return $this->raiseError(DB_ERROR_CONNECT_FAILED, |
null, null, null, |
$php_errormsg); |
} |
if ($dsn['database']) { |
if (!@fbsql_select_db($dsn['database'], $this->connection)) { |
return $this->fbsqlRaiseError(); |
} |
} |
return DB_OK; |
} |
// }}} |
// {{{ disconnect() |
/** |
* Disconnects from the database server |
* |
* @return bool TRUE on success, FALSE on failure |
*/ |
function disconnect() |
{ |
$ret = @fbsql_close($this->connection); |
$this->connection = null; |
return $ret; |
} |
// }}} |
// {{{ simpleQuery() |
/** |
* Sends a query to the database server |
* |
* @param string the SQL query string |
* |
* @return mixed + a PHP result resrouce for successful SELECT queries |
* + the DB_OK constant for other successful queries |
* + a DB_Error object on failure |
*/ |
function simpleQuery($query) |
{ |
$this->last_query = $query; |
$query = $this->modifyQuery($query); |
$result = @fbsql_query("$query;", $this->connection); |
if (!$result) { |
return $this->fbsqlRaiseError(); |
} |
// Determine which queries that should return data, and which |
// should return an error code only. |
if ($this->_checkManip($query)) { |
return DB_OK; |
} |
return $result; |
} |
// }}} |
// {{{ nextResult() |
/** |
* Move the internal fbsql result pointer to the next available result |
* |
* @param a valid fbsql result resource |
* |
* @access public |
* |
* @return true if a result is available otherwise return false |
*/ |
function nextResult($result) |
{ |
return @fbsql_next_result($result); |
} |
// }}} |
// {{{ fetchInto() |
/** |
* Places a row from the result set into the given array |
* |
* Formating of the array and the data therein are configurable. |
* See DB_result::fetchInto() for more information. |
* |
* This method is not meant to be called directly. Use |
* DB_result::fetchInto() instead. It can't be declared "protected" |
* because DB_result is a separate object. |
* |
* @param resource $result the query result resource |
* @param array $arr the referenced array to put the data in |
* @param int $fetchmode how the resulting array should be indexed |
* @param int $rownum the row number to fetch (0 = first row) |
* |
* @return mixed DB_OK on success, NULL when the end of a result set is |
* reached or on failure |
* |
* @see DB_result::fetchInto() |
*/ |
function fetchInto($result, &$arr, $fetchmode, $rownum = null) |
{ |
if ($rownum !== null) { |
if (!@fbsql_data_seek($result, $rownum)) { |
return null; |
} |
} |
if ($fetchmode & DB_FETCHMODE_ASSOC) { |
$arr = @fbsql_fetch_array($result, FBSQL_ASSOC); |
if ($this->options['portability'] & DB_PORTABILITY_LOWERCASE && $arr) { |
$arr = array_change_key_case($arr, CASE_LOWER); |
} |
} else { |
$arr = @fbsql_fetch_row($result); |
} |
if (!$arr) { |
return null; |
} |
if ($this->options['portability'] & DB_PORTABILITY_RTRIM) { |
$this->_rtrimArrayValues($arr); |
} |
if ($this->options['portability'] & DB_PORTABILITY_NULL_TO_EMPTY) { |
$this->_convertNullArrayValuesToEmpty($arr); |
} |
return DB_OK; |
} |
// }}} |
// {{{ freeResult() |
/** |
* Deletes the result set and frees the memory occupied by the result set |
* |
* This method is not meant to be called directly. Use |
* DB_result::free() instead. It can't be declared "protected" |
* because DB_result is a separate object. |
* |
* @param resource $result PHP's query result resource |
* |
* @return bool TRUE on success, FALSE if $result is invalid |
* |
* @see DB_result::free() |
*/ |
function freeResult($result) |
{ |
return is_resource($result) ? fbsql_free_result($result) : false; |
} |
// }}} |
// {{{ autoCommit() |
/** |
* Enables or disables automatic commits |
* |
* @param bool $onoff true turns it on, false turns it off |
* |
* @return int DB_OK on success. A DB_Error object if the driver |
* doesn't support auto-committing transactions. |
*/ |
function autoCommit($onoff=false) |
{ |
if ($onoff) { |
$this->query("SET COMMIT TRUE"); |
} else { |
$this->query("SET COMMIT FALSE"); |
} |
} |
// }}} |
// {{{ commit() |
/** |
* Commits the current transaction |
* |
* @return int DB_OK on success. A DB_Error object on failure. |
*/ |
function commit() |
{ |
@fbsql_commit($this->connection); |
} |
// }}} |
// {{{ rollback() |
/** |
* Reverts the current transaction |
* |
* @return int DB_OK on success. A DB_Error object on failure. |
*/ |
function rollback() |
{ |
@fbsql_rollback($this->connection); |
} |
// }}} |
// {{{ numCols() |
/** |
* Gets the number of columns in a result set |
* |
* This method is not meant to be called directly. Use |
* DB_result::numCols() instead. It can't be declared "protected" |
* because DB_result is a separate object. |
* |
* @param resource $result PHP's query result resource |
* |
* @return int the number of columns. A DB_Error object on failure. |
* |
* @see DB_result::numCols() |
*/ |
function numCols($result) |
{ |
$cols = @fbsql_num_fields($result); |
if (!$cols) { |
return $this->fbsqlRaiseError(); |
} |
return $cols; |
} |
// }}} |
// {{{ numRows() |
/** |
* Gets the number of rows in a result set |
* |
* This method is not meant to be called directly. Use |
* DB_result::numRows() instead. It can't be declared "protected" |
* because DB_result is a separate object. |
* |
* @param resource $result PHP's query result resource |
* |
* @return int the number of rows. A DB_Error object on failure. |
* |
* @see DB_result::numRows() |
*/ |
function numRows($result) |
{ |
$rows = @fbsql_num_rows($result); |
if ($rows === null) { |
return $this->fbsqlRaiseError(); |
} |
return $rows; |
} |
// }}} |
// {{{ affectedRows() |
/** |
* Determines the number of rows affected by a data maniuplation query |
* |
* 0 is returned for queries that don't manipulate data. |
* |
* @return int the number of rows. A DB_Error object on failure. |
*/ |
function affectedRows() |
{ |
if ($this->_last_query_manip) { |
$result = @fbsql_affected_rows($this->connection); |
} else { |
$result = 0; |
} |
return $result; |
} |
// }}} |
// {{{ nextId() |
/** |
* Returns the next free id in a sequence |
* |
* @param string $seq_name name of the sequence |
* @param boolean $ondemand when true, the seqence is automatically |
* created if it does not exist |
* |
* @return int the next id number in the sequence. |
* A DB_Error object on failure. |
* |
* @see DB_common::nextID(), DB_common::getSequenceName(), |
* DB_fbsql::createSequence(), DB_fbsql::dropSequence() |
*/ |
function nextId($seq_name, $ondemand = true) |
{ |
$seqname = $this->getSequenceName($seq_name); |
do { |
$repeat = 0; |
$this->pushErrorHandling(PEAR_ERROR_RETURN); |
$result = $this->query('SELECT UNIQUE FROM ' . $seqname); |
$this->popErrorHandling(); |
if ($ondemand && DB::isError($result) && |
$result->getCode() == DB_ERROR_NOSUCHTABLE) { |
$repeat = 1; |
$result = $this->createSequence($seq_name); |
if (DB::isError($result)) { |
return $result; |
} |
} else { |
$repeat = 0; |
} |
} while ($repeat); |
if (DB::isError($result)) { |
return $this->fbsqlRaiseError(); |
} |
$result->fetchInto($tmp, DB_FETCHMODE_ORDERED); |
return $tmp[0]; |
} |
/** |
* Creates a new sequence |
* |
* @param string $seq_name name of the new sequence |
* |
* @return int DB_OK on success. A DB_Error object on failure. |
* |
* @see DB_common::createSequence(), DB_common::getSequenceName(), |
* DB_fbsql::nextID(), DB_fbsql::dropSequence() |
*/ |
function createSequence($seq_name) |
{ |
$seqname = $this->getSequenceName($seq_name); |
$res = $this->query('CREATE TABLE ' . $seqname |
. ' (id INTEGER NOT NULL,' |
. ' PRIMARY KEY(id))'); |
if ($res) { |
$res = $this->query('SET UNIQUE = 0 FOR ' . $seqname); |
} |
return $res; |
} |
// }}} |
// {{{ dropSequence() |
/** |
* Deletes a sequence |
* |
* @param string $seq_name name of the sequence to be deleted |
* |
* @return int DB_OK on success. A DB_Error object on failure. |
* |
* @see DB_common::dropSequence(), DB_common::getSequenceName(), |
* DB_fbsql::nextID(), DB_fbsql::createSequence() |
*/ |
function dropSequence($seq_name) |
{ |
return $this->query('DROP TABLE ' . $this->getSequenceName($seq_name) |
. ' RESTRICT'); |
} |
// }}} |
// {{{ modifyLimitQuery() |
/** |
* Adds LIMIT clauses to a query string according to current DBMS standards |
* |
* @param string $query the query to modify |
* @param int $from the row to start to fetching (0 = the first row) |
* @param int $count the numbers of rows to fetch |
* @param mixed $params array, string or numeric data to be used in |
* execution of the statement. Quantity of items |
* passed must match quantity of placeholders in |
* query: meaning 1 placeholder for non-array |
* parameters or 1 placeholder per array element. |
* |
* @return string the query string with LIMIT clauses added |
* |
* @access protected |
*/ |
function modifyLimitQuery($query, $from, $count, $params = array()) |
{ |
if (DB::isManip($query) || $this->_next_query_manip) { |
return preg_replace('/^([\s(])*SELECT/i', |
"\\1SELECT TOP($count)", $query); |
} else { |
return preg_replace('/([\s(])*SELECT/i', |
"\\1SELECT TOP($from, $count)", $query); |
} |
} |
// }}} |
// {{{ quoteBoolean() |
/** |
* Formats a boolean value for use within a query in a locale-independent |
* manner. |
* |
* @param boolean the boolean value to be quoted. |
* @return string the quoted string. |
* @see DB_common::quoteSmart() |
* @since Method available since release 1.7.8. |
*/ |
function quoteBoolean($boolean) { |
return $boolean ? 'TRUE' : 'FALSE'; |
} |
// }}} |
// {{{ quoteFloat() |
/** |
* Formats a float value for use within a query in a locale-independent |
* manner. |
* |
* @param float the float value to be quoted. |
* @return string the quoted string. |
* @see DB_common::quoteSmart() |
* @since Method available since release 1.7.8. |
*/ |
function quoteFloat($float) { |
return $this->escapeSimple(str_replace(',', '.', strval(floatval($float)))); |
} |
// }}} |
// {{{ fbsqlRaiseError() |
/** |
* Produces a DB_Error object regarding the current problem |
* |
* @param int $errno if the error is being manually raised pass a |
* DB_ERROR* constant here. If this isn't passed |
* the error information gathered from the DBMS. |
* |
* @return object the DB_Error object |
* |
* @see DB_common::raiseError(), |
* DB_fbsql::errorNative(), DB_common::errorCode() |
*/ |
function fbsqlRaiseError($errno = null) |
{ |
if ($errno === null) { |
$errno = $this->errorCode(fbsql_errno($this->connection)); |
} |
return $this->raiseError($errno, null, null, null, |
@fbsql_error($this->connection)); |
} |
// }}} |
// {{{ errorNative() |
/** |
* Gets the DBMS' native error code produced by the last query |
* |
* @return int the DBMS' error code |
*/ |
function errorNative() |
{ |
return @fbsql_errno($this->connection); |
} |
// }}} |
// {{{ tableInfo() |
/** |
* Returns information about a table or a result set |
* |
* @param object|string $result DB_result object from a query or a |
* string containing the name of a table. |
* While this also accepts a query result |
* resource identifier, this behavior is |
* deprecated. |
* @param int $mode a valid tableInfo mode |
* |
* @return array an associative array with the information requested. |
* A DB_Error object on failure. |
* |
* @see DB_common::tableInfo() |
*/ |
function tableInfo($result, $mode = null) |
{ |
if (is_string($result)) { |
/* |
* Probably received a table name. |
* Create a result resource identifier. |
*/ |
$id = @fbsql_list_fields($this->dsn['database'], |
$result, $this->connection); |
$got_string = true; |
} elseif (isset($result->result)) { |
/* |
* Probably received a result object. |
* Extract the result resource identifier. |
*/ |
$id = $result->result; |
$got_string = false; |
} else { |
/* |
* Probably received a result resource identifier. |
* Copy it. |
* Deprecated. Here for compatibility only. |
*/ |
$id = $result; |
$got_string = false; |
} |
if (!is_resource($id)) { |
return $this->fbsqlRaiseError(DB_ERROR_NEED_MORE_DATA); |
} |
if ($this->options['portability'] & DB_PORTABILITY_LOWERCASE) { |
$case_func = 'strtolower'; |
} else { |
$case_func = 'strval'; |
} |
$count = @fbsql_num_fields($id); |
$res = array(); |
if ($mode) { |
$res['num_fields'] = $count; |
} |
for ($i = 0; $i < $count; $i++) { |
$res[$i] = array( |
'table' => $case_func(@fbsql_field_table($id, $i)), |
'name' => $case_func(@fbsql_field_name($id, $i)), |
'type' => @fbsql_field_type($id, $i), |
'len' => @fbsql_field_len($id, $i), |
'flags' => @fbsql_field_flags($id, $i), |
); |
if ($mode & DB_TABLEINFO_ORDER) { |
$res['order'][$res[$i]['name']] = $i; |
} |
if ($mode & DB_TABLEINFO_ORDERTABLE) { |
$res['ordertable'][$res[$i]['table']][$res[$i]['name']] = $i; |
} |
} |
// free the result only if we were called on a table |
if ($got_string) { |
@fbsql_free_result($id); |
} |
return $res; |
} |
// }}} |
// {{{ getSpecialQuery() |
/** |
* Obtains the query string needed for listing a given type of objects |
* |
* @param string $type the kind of objects you want to retrieve |
* |
* @return string the SQL query string or null if the driver doesn't |
* support the object type requested |
* |
* @access protected |
* @see DB_common::getListOf() |
*/ |
function getSpecialQuery($type) |
{ |
switch ($type) { |
case 'tables': |
return 'SELECT "table_name" FROM information_schema.tables' |
. ' t0, information_schema.schemata t1' |
. ' WHERE t0.schema_pk=t1.schema_pk AND' |
. ' "table_type" = \'BASE TABLE\'' |
. ' AND "schema_name" = current_schema'; |
case 'views': |
return 'SELECT "table_name" FROM information_schema.tables' |
. ' t0, information_schema.schemata t1' |
. ' WHERE t0.schema_pk=t1.schema_pk AND' |
. ' "table_type" = \'VIEW\'' |
. ' AND "schema_name" = current_schema'; |
case 'users': |
return 'SELECT "user_name" from information_schema.users'; |
case 'functions': |
return 'SELECT "routine_name" FROM' |
. ' information_schema.psm_routines' |
. ' t0, information_schema.schemata t1' |
. ' WHERE t0.schema_pk=t1.schema_pk' |
. ' AND "routine_kind"=\'FUNCTION\'' |
. ' AND "schema_name" = current_schema'; |
case 'procedures': |
return 'SELECT "routine_name" FROM' |
. ' information_schema.psm_routines' |
. ' t0, information_schema.schemata t1' |
. ' WHERE t0.schema_pk=t1.schema_pk' |
. ' AND "routine_kind"=\'PROCEDURE\'' |
. ' AND "schema_name" = current_schema'; |
default: |
return null; |
} |
} |
// }}} |
} |
/* |
* Local variables: |
* tab-width: 4 |
* c-basic-offset: 4 |
* End: |
*/ |
?> |
/branches/v1.3-critias/bibliotheque/pear/DB/odbc.php |
---|
New file |
0,0 → 1,871 |
<?php |
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */ |
/** |
* The PEAR DB driver for PHP's odbc extension |
* for interacting with databases via ODBC connections |
* |
* PHP version 5 |
* |
* LICENSE: This source file is subject to version 3.0 of the PHP license |
* that is available through the world-wide-web at the following URI: |
* http://www.php.net/license/3_0.txt. If you did not receive a copy of |
* the PHP License and are unable to obtain it through the web, please |
* send a note to license@php.net so we can mail you a copy immediately. |
* |
* @category Database |
* @package DB |
* @author Stig Bakken <ssb@php.net> |
* @author Daniel Convissor <danielc@php.net> |
* @copyright 1997-2007 The PHP Group |
* @license http://www.php.net/license/3_0.txt PHP License 3.0 |
* @version CVS: $Id$ |
* @link http://pear.php.net/package/DB |
*/ |
/** |
* Obtain the DB_common class so it can be extended from |
*/ |
require_once 'DB/common.php'; |
/** |
* The methods PEAR DB uses to interact with PHP's odbc extension |
* for interacting with databases via ODBC connections |
* |
* These methods overload the ones declared in DB_common. |
* |
* More info on ODBC errors could be found here: |
* http://msdn.microsoft.com/library/default.asp?url=/library/en-us/trblsql/tr_err_odbc_5stz.asp |
* |
* @category Database |
* @package DB |
* @author Stig Bakken <ssb@php.net> |
* @author Daniel Convissor <danielc@php.net> |
* @copyright 1997-2007 The PHP Group |
* @license http://www.php.net/license/3_0.txt PHP License 3.0 |
* @version Release: 1.9.2 |
* @link http://pear.php.net/package/DB |
*/ |
class DB_odbc extends DB_common |
{ |
// {{{ properties |
/** |
* The DB driver type (mysql, oci8, odbc, etc.) |
* @var string |
*/ |
var $phptype = 'odbc'; |
/** |
* The database syntax variant to be used (db2, access, etc.), if any |
* @var string |
*/ |
var $dbsyntax = 'sql92'; |
/** |
* The capabilities of this DB implementation |
* |
* The 'new_link' element contains the PHP version that first provided |
* new_link support for this DBMS. Contains false if it's unsupported. |
* |
* Meaning of the 'limit' element: |
* + 'emulate' = emulate with fetch row by number |
* + 'alter' = alter the query |
* + false = skip rows |
* |
* NOTE: The feature set of the following drivers are different than |
* the default: |
* + solid: 'transactions' = true |
* + navision: 'limit' = false |
* |
* @var array |
*/ |
var $features = array( |
'limit' => 'emulate', |
'new_link' => false, |
'numrows' => true, |
'pconnect' => true, |
'prepare' => false, |
'ssl' => false, |
'transactions' => false, |
); |
/** |
* A mapping of native error codes to DB error codes |
* @var array |
*/ |
var $errorcode_map = array( |
'01004' => DB_ERROR_TRUNCATED, |
'07001' => DB_ERROR_MISMATCH, |
'21S01' => DB_ERROR_VALUE_COUNT_ON_ROW, |
'21S02' => DB_ERROR_MISMATCH, |
'22001' => DB_ERROR_INVALID, |
'22003' => DB_ERROR_INVALID_NUMBER, |
'22005' => DB_ERROR_INVALID_NUMBER, |
'22008' => DB_ERROR_INVALID_DATE, |
'22012' => DB_ERROR_DIVZERO, |
'23000' => DB_ERROR_CONSTRAINT, |
'23502' => DB_ERROR_CONSTRAINT_NOT_NULL, |
'23503' => DB_ERROR_CONSTRAINT, |
'23504' => DB_ERROR_CONSTRAINT, |
'23505' => DB_ERROR_CONSTRAINT, |
'24000' => DB_ERROR_INVALID, |
'34000' => DB_ERROR_INVALID, |
'37000' => DB_ERROR_SYNTAX, |
'42000' => DB_ERROR_SYNTAX, |
'42601' => DB_ERROR_SYNTAX, |
'IM001' => DB_ERROR_UNSUPPORTED, |
'S0000' => DB_ERROR_NOSUCHTABLE, |
'S0001' => DB_ERROR_ALREADY_EXISTS, |
'S0002' => DB_ERROR_NOSUCHTABLE, |
'S0011' => DB_ERROR_ALREADY_EXISTS, |
'S0012' => DB_ERROR_NOT_FOUND, |
'S0021' => DB_ERROR_ALREADY_EXISTS, |
'S0022' => DB_ERROR_NOSUCHFIELD, |
'S1009' => DB_ERROR_INVALID, |
'S1090' => DB_ERROR_INVALID, |
'S1C00' => DB_ERROR_NOT_CAPABLE, |
); |
/** |
* The raw database connection created by PHP |
* @var resource |
*/ |
var $connection; |
/** |
* The DSN information for connecting to a database |
* @var array |
*/ |
var $dsn = array(); |
/** |
* The number of rows affected by a data manipulation query |
* @var integer |
* @access private |
*/ |
var $affected = 0; |
// }}} |
// {{{ constructor |
/** |
* This constructor calls <kbd>parent::__construct()</kbd> |
* |
* @return void |
*/ |
function __construct() |
{ |
parent::__construct(); |
} |
// }}} |
// {{{ connect() |
/** |
* Connect to the database server, log in and open the database |
* |
* Don't call this method directly. Use DB::connect() instead. |
* |
* PEAR DB's odbc driver supports the following extra DSN options: |
* + cursor The type of cursor to be used for this connection. |
* |
* @param array $dsn the data source name |
* @param bool $persistent should the connection be persistent? |
* |
* @return int DB_OK on success. A DB_Error object on failure. |
*/ |
function connect($dsn, $persistent = false) |
{ |
if (!PEAR::loadExtension('odbc')) { |
return $this->raiseError(DB_ERROR_EXTENSION_NOT_FOUND); |
} |
$this->dsn = $dsn; |
if ($dsn['dbsyntax']) { |
$this->dbsyntax = $dsn['dbsyntax']; |
} |
switch ($this->dbsyntax) { |
case 'access': |
case 'db2': |
case 'solid': |
$this->features['transactions'] = true; |
break; |
case 'navision': |
$this->features['limit'] = false; |
} |
/* |
* This is hear for backwards compatibility. Should have been using |
* 'database' all along, but prior to 1.6.0RC3 'hostspec' was used. |
*/ |
if ($dsn['database']) { |
$odbcdsn = $dsn['database']; |
} elseif ($dsn['hostspec']) { |
$odbcdsn = $dsn['hostspec']; |
} else { |
$odbcdsn = 'localhost'; |
} |
$connect_function = $persistent ? 'odbc_pconnect' : 'odbc_connect'; |
if (empty($dsn['cursor'])) { |
$this->connection = @$connect_function($odbcdsn, $dsn['username'], |
$dsn['password']); |
} else { |
$this->connection = @$connect_function($odbcdsn, $dsn['username'], |
$dsn['password'], |
$dsn['cursor']); |
} |
if (!is_resource($this->connection)) { |
return $this->raiseError(DB_ERROR_CONNECT_FAILED, |
null, null, null, |
$this->errorNative()); |
} |
return DB_OK; |
} |
// }}} |
// {{{ disconnect() |
/** |
* Disconnects from the database server |
* |
* @return bool TRUE on success, FALSE on failure |
*/ |
function disconnect() |
{ |
$err = @odbc_close($this->connection); |
$this->connection = null; |
return $err; |
} |
// }}} |
// {{{ simpleQuery() |
/** |
* Sends a query to the database server |
* |
* @param string the SQL query string |
* |
* @return mixed + a PHP result resrouce for successful SELECT queries |
* + the DB_OK constant for other successful queries |
* + a DB_Error object on failure |
*/ |
function simpleQuery($query) |
{ |
$this->last_query = $query; |
$query = $this->modifyQuery($query); |
$result = @odbc_exec($this->connection, $query); |
if (!$result) { |
return $this->odbcRaiseError(); // XXX ERRORMSG |
} |
// Determine which queries that should return data, and which |
// should return an error code only. |
if ($this->_checkManip($query)) { |
$this->affected = $result; // For affectedRows() |
return DB_OK; |
} |
$this->affected = 0; |
return $result; |
} |
// }}} |
// {{{ nextResult() |
/** |
* Move the internal odbc result pointer to the next available result |
* |
* @param a valid fbsql result resource |
* |
* @access public |
* |
* @return true if a result is available otherwise return false |
*/ |
function nextResult($result) |
{ |
return @odbc_next_result($result); |
} |
// }}} |
// {{{ fetchInto() |
/** |
* Places a row from the result set into the given array |
* |
* Formating of the array and the data therein are configurable. |
* See DB_result::fetchInto() for more information. |
* |
* This method is not meant to be called directly. Use |
* DB_result::fetchInto() instead. It can't be declared "protected" |
* because DB_result is a separate object. |
* |
* @param resource $result the query result resource |
* @param array $arr the referenced array to put the data in |
* @param int $fetchmode how the resulting array should be indexed |
* @param int $rownum the row number to fetch (0 = first row) |
* |
* @return mixed DB_OK on success, NULL when the end of a result set is |
* reached or on failure |
* |
* @see DB_result::fetchInto() |
*/ |
function fetchInto($result, &$arr, $fetchmode, $rownum = null) |
{ |
$arr = array(); |
if ($rownum !== null) { |
$rownum++; // ODBC first row is 1 |
if (version_compare(phpversion(), '4.2.0', 'ge')) { |
$cols = @odbc_fetch_into($result, $arr, $rownum); |
} else { |
$cols = @odbc_fetch_into($result, $rownum, $arr); |
} |
} else { |
$cols = @odbc_fetch_into($result, $arr); |
} |
if (!$cols) { |
return null; |
} |
if ($fetchmode !== DB_FETCHMODE_ORDERED) { |
for ($i = 0; $i < count($arr); $i++) { |
$colName = @odbc_field_name($result, $i+1); |
$a[$colName] = $arr[$i]; |
} |
if ($this->options['portability'] & DB_PORTABILITY_LOWERCASE) { |
$a = array_change_key_case($a, CASE_LOWER); |
} |
$arr = $a; |
} |
if ($this->options['portability'] & DB_PORTABILITY_RTRIM) { |
$this->_rtrimArrayValues($arr); |
} |
if ($this->options['portability'] & DB_PORTABILITY_NULL_TO_EMPTY) { |
$this->_convertNullArrayValuesToEmpty($arr); |
} |
return DB_OK; |
} |
// }}} |
// {{{ freeResult() |
/** |
* Deletes the result set and frees the memory occupied by the result set |
* |
* This method is not meant to be called directly. Use |
* DB_result::free() instead. It can't be declared "protected" |
* because DB_result is a separate object. |
* |
* @param resource $result PHP's query result resource |
* |
* @return bool TRUE on success, FALSE if $result is invalid |
* |
* @see DB_result::free() |
*/ |
function freeResult($result) |
{ |
return is_resource($result) ? odbc_free_result($result) : false; |
} |
// }}} |
// {{{ numCols() |
/** |
* Gets the number of columns in a result set |
* |
* This method is not meant to be called directly. Use |
* DB_result::numCols() instead. It can't be declared "protected" |
* because DB_result is a separate object. |
* |
* @param resource $result PHP's query result resource |
* |
* @return int the number of columns. A DB_Error object on failure. |
* |
* @see DB_result::numCols() |
*/ |
function numCols($result) |
{ |
$cols = @odbc_num_fields($result); |
if (!$cols) { |
return $this->odbcRaiseError(); |
} |
return $cols; |
} |
// }}} |
// {{{ affectedRows() |
/** |
* Determines the number of rows affected by a data maniuplation query |
* |
* 0 is returned for queries that don't manipulate data. |
* |
* @return int the number of rows. A DB_Error object on failure. |
*/ |
function affectedRows() |
{ |
if (empty($this->affected)) { // In case of SELECT stms |
return 0; |
} |
$nrows = @odbc_num_rows($this->affected); |
if ($nrows == -1) { |
return $this->odbcRaiseError(); |
} |
return $nrows; |
} |
// }}} |
// {{{ numRows() |
/** |
* Gets the number of rows in a result set |
* |
* Not all ODBC drivers support this functionality. If they don't |
* a DB_Error object for DB_ERROR_UNSUPPORTED is returned. |
* |
* This method is not meant to be called directly. Use |
* DB_result::numRows() instead. It can't be declared "protected" |
* because DB_result is a separate object. |
* |
* @param resource $result PHP's query result resource |
* |
* @return int the number of rows. A DB_Error object on failure. |
* |
* @see DB_result::numRows() |
*/ |
function numRows($result) |
{ |
$nrows = @odbc_num_rows($result); |
if ($nrows == -1) { |
return $this->odbcRaiseError(DB_ERROR_UNSUPPORTED); |
} |
if ($nrows === false) { |
return $this->odbcRaiseError(); |
} |
return $nrows; |
} |
// }}} |
// {{{ quoteIdentifier() |
/** |
* Quotes a string so it can be safely used as a table or column name |
* |
* Use 'mssql' as the dbsyntax in the DB DSN only if you've unchecked |
* "Use ANSI quoted identifiers" when setting up the ODBC data source. |
* |
* @param string $str identifier name to be quoted |
* |
* @return string quoted identifier string |
* |
* @see DB_common::quoteIdentifier() |
* @since Method available since Release 1.6.0 |
*/ |
function quoteIdentifier($str) |
{ |
switch ($this->dsn['dbsyntax']) { |
case 'access': |
return '[' . $str . ']'; |
case 'mssql': |
case 'sybase': |
return '[' . str_replace(']', ']]', $str) . ']'; |
case 'mysql': |
case 'mysqli': |
return '`' . $str . '`'; |
default: |
return '"' . str_replace('"', '""', $str) . '"'; |
} |
} |
// }}} |
// {{{ nextId() |
/** |
* Returns the next free id in a sequence |
* |
* @param string $seq_name name of the sequence |
* @param boolean $ondemand when true, the seqence is automatically |
* created if it does not exist |
* |
* @return int the next id number in the sequence. |
* A DB_Error object on failure. |
* |
* @see DB_common::nextID(), DB_common::getSequenceName(), |
* DB_odbc::createSequence(), DB_odbc::dropSequence() |
*/ |
function nextId($seq_name, $ondemand = true) |
{ |
$seqname = $this->getSequenceName($seq_name); |
$repeat = 0; |
do { |
$this->pushErrorHandling(PEAR_ERROR_RETURN); |
$result = $this->query("update ${seqname} set id = id + 1"); |
$this->popErrorHandling(); |
if ($ondemand && DB::isError($result) && |
$result->getCode() == DB_ERROR_NOSUCHTABLE) { |
$repeat = 1; |
$this->pushErrorHandling(PEAR_ERROR_RETURN); |
$result = $this->createSequence($seq_name); |
$this->popErrorHandling(); |
if (DB::isError($result)) { |
return $this->raiseError($result); |
} |
$result = $this->query("insert into ${seqname} (id) values(0)"); |
} else { |
$repeat = 0; |
} |
} while ($repeat); |
if (DB::isError($result)) { |
return $this->raiseError($result); |
} |
$result = $this->query("select id from ${seqname}"); |
if (DB::isError($result)) { |
return $result; |
} |
$row = $result->fetchRow(DB_FETCHMODE_ORDERED); |
if (DB::isError($row || !$row)) { |
return $row; |
} |
return $row[0]; |
} |
/** |
* Creates a new sequence |
* |
* @param string $seq_name name of the new sequence |
* |
* @return int DB_OK on success. A DB_Error object on failure. |
* |
* @see DB_common::createSequence(), DB_common::getSequenceName(), |
* DB_odbc::nextID(), DB_odbc::dropSequence() |
*/ |
function createSequence($seq_name) |
{ |
return $this->query('CREATE TABLE ' |
. $this->getSequenceName($seq_name) |
. ' (id integer NOT NULL,' |
. ' PRIMARY KEY(id))'); |
} |
// }}} |
// {{{ dropSequence() |
/** |
* Deletes a sequence |
* |
* @param string $seq_name name of the sequence to be deleted |
* |
* @return int DB_OK on success. A DB_Error object on failure. |
* |
* @see DB_common::dropSequence(), DB_common::getSequenceName(), |
* DB_odbc::nextID(), DB_odbc::createSequence() |
*/ |
function dropSequence($seq_name) |
{ |
return $this->query('DROP TABLE ' . $this->getSequenceName($seq_name)); |
} |
// }}} |
// {{{ autoCommit() |
/** |
* Enables or disables automatic commits |
* |
* @param bool $onoff true turns it on, false turns it off |
* |
* @return int DB_OK on success. A DB_Error object if the driver |
* doesn't support auto-committing transactions. |
*/ |
function autoCommit($onoff = false) |
{ |
if (!@odbc_autocommit($this->connection, $onoff)) { |
return $this->odbcRaiseError(); |
} |
return DB_OK; |
} |
// }}} |
// {{{ commit() |
/** |
* Commits the current transaction |
* |
* @return int DB_OK on success. A DB_Error object on failure. |
*/ |
function commit() |
{ |
if (!@odbc_commit($this->connection)) { |
return $this->odbcRaiseError(); |
} |
return DB_OK; |
} |
// }}} |
// {{{ rollback() |
/** |
* Reverts the current transaction |
* |
* @return int DB_OK on success. A DB_Error object on failure. |
*/ |
function rollback() |
{ |
if (!@odbc_rollback($this->connection)) { |
return $this->odbcRaiseError(); |
} |
return DB_OK; |
} |
// }}} |
// {{{ odbcRaiseError() |
/** |
* Produces a DB_Error object regarding the current problem |
* |
* @param int $errno if the error is being manually raised pass a |
* DB_ERROR* constant here. If this isn't passed |
* the error information gathered from the DBMS. |
* |
* @return object the DB_Error object |
* |
* @see DB_common::raiseError(), |
* DB_odbc::errorNative(), DB_common::errorCode() |
*/ |
function odbcRaiseError($errno = null) |
{ |
if ($errno === null) { |
switch ($this->dbsyntax) { |
case 'access': |
if ($this->options['portability'] & DB_PORTABILITY_ERRORS) { |
$this->errorcode_map['07001'] = DB_ERROR_NOSUCHFIELD; |
} else { |
// Doing this in case mode changes during runtime. |
$this->errorcode_map['07001'] = DB_ERROR_MISMATCH; |
} |
$native_code = odbc_error($this->connection); |
// S1000 is for "General Error." Let's be more specific. |
if ($native_code == 'S1000') { |
$errormsg = odbc_errormsg($this->connection); |
static $error_regexps; |
if (!isset($error_regexps)) { |
$error_regexps = array( |
'/includes related records.$/i' => DB_ERROR_CONSTRAINT, |
'/cannot contain a Null value/i' => DB_ERROR_CONSTRAINT_NOT_NULL, |
); |
} |
foreach ($error_regexps as $regexp => $code) { |
if (preg_match($regexp, $errormsg)) { |
return $this->raiseError($code, |
null, null, null, |
$native_code . ' ' . $errormsg); |
} |
} |
$errno = DB_ERROR; |
} else { |
$errno = $this->errorCode($native_code); |
} |
break; |
default: |
$errno = $this->errorCode(odbc_error($this->connection)); |
} |
} |
return $this->raiseError($errno, null, null, null, |
$this->errorNative()); |
} |
// }}} |
// {{{ errorNative() |
/** |
* Gets the DBMS' native error code and message produced by the last query |
* |
* @return string the DBMS' error code and message |
*/ |
function errorNative() |
{ |
if (!is_resource($this->connection)) { |
return @odbc_error() . ' ' . @odbc_errormsg(); |
} |
return @odbc_error($this->connection) . ' ' . @odbc_errormsg($this->connection); |
} |
// }}} |
// {{{ tableInfo() |
/** |
* Returns information about a table or a result set |
* |
* @param object|string $result DB_result object from a query or a |
* string containing the name of a table. |
* While this also accepts a query result |
* resource identifier, this behavior is |
* deprecated. |
* @param int $mode a valid tableInfo mode |
* |
* @return array an associative array with the information requested. |
* A DB_Error object on failure. |
* |
* @see DB_common::tableInfo() |
* @since Method available since Release 1.7.0 |
*/ |
function tableInfo($result, $mode = null) |
{ |
if (is_string($result)) { |
/* |
* Probably received a table name. |
* Create a result resource identifier. |
*/ |
$id = @odbc_exec($this->connection, "SELECT * FROM $result"); |
if (!$id) { |
return $this->odbcRaiseError(); |
} |
$got_string = true; |
} elseif (isset($result->result)) { |
/* |
* Probably received a result object. |
* Extract the result resource identifier. |
*/ |
$id = $result->result; |
$got_string = false; |
} else { |
/* |
* Probably received a result resource identifier. |
* Copy it. |
* Deprecated. Here for compatibility only. |
*/ |
$id = $result; |
$got_string = false; |
} |
if (!is_resource($id)) { |
return $this->odbcRaiseError(DB_ERROR_NEED_MORE_DATA); |
} |
if ($this->options['portability'] & DB_PORTABILITY_LOWERCASE) { |
$case_func = 'strtolower'; |
} else { |
$case_func = 'strval'; |
} |
$count = @odbc_num_fields($id); |
$res = array(); |
if ($mode) { |
$res['num_fields'] = $count; |
} |
for ($i = 0; $i < $count; $i++) { |
$col = $i + 1; |
$res[$i] = array( |
'table' => $got_string ? $case_func($result) : '', |
'name' => $case_func(@odbc_field_name($id, $col)), |
'type' => @odbc_field_type($id, $col), |
'len' => @odbc_field_len($id, $col), |
'flags' => '', |
); |
if ($mode & DB_TABLEINFO_ORDER) { |
$res['order'][$res[$i]['name']] = $i; |
} |
if ($mode & DB_TABLEINFO_ORDERTABLE) { |
$res['ordertable'][$res[$i]['table']][$res[$i]['name']] = $i; |
} |
} |
// free the result only if we were called on a table |
if ($got_string) { |
@odbc_free_result($id); |
} |
return $res; |
} |
// }}} |
// {{{ getSpecialQuery() |
/** |
* Obtains the query string needed for listing a given type of objects |
* |
* Thanks to symbol1@gmail.com and Philippe.Jausions@11abacus.com. |
* |
* @param string $type the kind of objects you want to retrieve |
* |
* @return string the list of objects requested |
* |
* @access protected |
* @see DB_common::getListOf() |
* @since Method available since Release 1.7.0 |
*/ |
function getSpecialQuery($type) |
{ |
switch ($type) { |
case 'databases': |
if (!function_exists('odbc_data_source')) { |
return null; |
} |
$res = @odbc_data_source($this->connection, SQL_FETCH_FIRST); |
if (is_array($res)) { |
$out = array($res['server']); |
while($res = @odbc_data_source($this->connection, |
SQL_FETCH_NEXT)) |
{ |
$out[] = $res['server']; |
} |
return $out; |
} else { |
return $this->odbcRaiseError(); |
} |
break; |
case 'tables': |
case 'schema.tables': |
$keep = 'TABLE'; |
break; |
case 'views': |
$keep = 'VIEW'; |
break; |
default: |
return null; |
} |
/* |
* Removing non-conforming items in the while loop rather than |
* in the odbc_tables() call because some backends choke on this: |
* odbc_tables($this->connection, '', '', '', 'TABLE') |
*/ |
$res = @odbc_tables($this->connection); |
if (!$res) { |
return $this->odbcRaiseError(); |
} |
$out = array(); |
while ($row = odbc_fetch_array($res)) { |
if ($row['TABLE_TYPE'] != $keep) { |
continue; |
} |
if ($type == 'schema.tables') { |
$out[] = $row['TABLE_SCHEM'] . '.' . $row['TABLE_NAME']; |
} else { |
$out[] = $row['TABLE_NAME']; |
} |
} |
return $out; |
} |
// }}} |
} |
/* |
* Local variables: |
* tab-width: 4 |
* c-basic-offset: 4 |
* End: |
*/ |
?> |
/branches/v1.3-critias/bibliotheque/pear/DB/common.php |
---|
New file |
0,0 → 1,2261 |
<?php |
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */ |
/** |
* Contains the DB_common base class |
* |
* PHP version 5 |
* |
* LICENSE: This source file is subject to version 3.0 of the PHP license |
* that is available through the world-wide-web at the following URI: |
* http://www.php.net/license/3_0.txt. If you did not receive a copy of |
* the PHP License and are unable to obtain it through the web, please |
* send a note to license@php.net so we can mail you a copy immediately. |
* |
* @category Database |
* @package DB |
* @author Stig Bakken <ssb@php.net> |
* @author Tomas V.V. Cox <cox@idecnet.com> |
* @author Daniel Convissor <danielc@php.net> |
* @copyright 1997-2007 The PHP Group |
* @license http://www.php.net/license/3_0.txt PHP License 3.0 |
* @version CVS: $Id$ |
* @link http://pear.php.net/package/DB |
*/ |
/** |
* Obtain the PEAR class so it can be extended from |
*/ |
require_once 'PEAR.php'; |
/** |
* DB_common is the base class from which each database driver class extends |
* |
* All common methods are declared here. If a given DBMS driver contains |
* a particular method, that method will overload the one here. |
* |
* @category Database |
* @package DB |
* @author Stig Bakken <ssb@php.net> |
* @author Tomas V.V. Cox <cox@idecnet.com> |
* @author Daniel Convissor <danielc@php.net> |
* @copyright 1997-2007 The PHP Group |
* @license http://www.php.net/license/3_0.txt PHP License 3.0 |
* @version Release: 1.9.2 |
* @link http://pear.php.net/package/DB |
*/ |
class DB_common extends PEAR |
{ |
// {{{ properties |
/** |
* The current default fetch mode |
* @var integer |
*/ |
var $fetchmode = DB_FETCHMODE_ORDERED; |
/** |
* The name of the class into which results should be fetched when |
* DB_FETCHMODE_OBJECT is in effect |
* |
* @var string |
*/ |
var $fetchmode_object_class = 'stdClass'; |
/** |
* Was a connection present when the object was serialized()? |
* @var bool |
* @see DB_common::__sleep(), DB_common::__wake() |
*/ |
var $was_connected = null; |
/** |
* The most recently executed query |
* @var string |
*/ |
var $last_query = ''; |
/** |
* Run-time configuration options |
* |
* The 'optimize' option has been deprecated. Use the 'portability' |
* option instead. |
* |
* @var array |
* @see DB_common::setOption() |
*/ |
var $options = array( |
'result_buffering' => 500, |
'persistent' => false, |
'ssl' => false, |
'debug' => 0, |
'seqname_format' => '%s_seq', |
'autofree' => false, |
'portability' => DB_PORTABILITY_NONE, |
'optimize' => 'performance', // Deprecated. Use 'portability'. |
); |
/** |
* The parameters from the most recently executed query |
* @var array |
* @since Property available since Release 1.7.0 |
*/ |
var $last_parameters = array(); |
/** |
* The elements from each prepared statement |
* @var array |
*/ |
var $prepare_tokens = array(); |
/** |
* The data types of the various elements in each prepared statement |
* @var array |
*/ |
var $prepare_types = array(); |
/** |
* The prepared queries |
* @var array |
*/ |
var $prepared_queries = array(); |
/** |
* Flag indicating that the last query was a manipulation query. |
* @access protected |
* @var boolean |
*/ |
var $_last_query_manip = false; |
/** |
* Flag indicating that the next query <em>must</em> be a manipulation |
* query. |
* @access protected |
* @var boolean |
*/ |
var $_next_query_manip = false; |
// }}} |
// {{{ DB_common |
/** |
* This constructor calls <kbd>$this->PEAR('DB_Error')</kbd> |
* |
* @return void |
*/ |
function __construct() |
{ |
$this->PEAR('DB_Error'); |
} |
// }}} |
// {{{ __sleep() |
/** |
* Automatically indicates which properties should be saved |
* when PHP's serialize() function is called |
* |
* @return array the array of properties names that should be saved |
*/ |
function __sleep() |
{ |
if ($this->connection) { |
// Don't disconnect(), people use serialize() for many reasons |
$this->was_connected = true; |
} else { |
$this->was_connected = false; |
} |
if (isset($this->autocommit)) { |
return array('autocommit', |
'dbsyntax', |
'dsn', |
'features', |
'fetchmode', |
'fetchmode_object_class', |
'options', |
'was_connected', |
); |
} else { |
return array('dbsyntax', |
'dsn', |
'features', |
'fetchmode', |
'fetchmode_object_class', |
'options', |
'was_connected', |
); |
} |
} |
// }}} |
// {{{ __wakeup() |
/** |
* Automatically reconnects to the database when PHP's unserialize() |
* function is called |
* |
* The reconnection attempt is only performed if the object was connected |
* at the time PHP's serialize() function was run. |
* |
* @return void |
*/ |
function __wakeup() |
{ |
if ($this->was_connected) { |
$this->connect($this->dsn, $this->options['persistent']); |
} |
} |
// }}} |
// {{{ __toString() |
/** |
* Automatic string conversion for PHP 5 |
* |
* @return string a string describing the current PEAR DB object |
* |
* @since Method available since Release 1.7.0 |
*/ |
function __toString() |
{ |
$info = strtolower(get_class($this)); |
$info .= ': (phptype=' . $this->phptype . |
', dbsyntax=' . $this->dbsyntax . |
')'; |
if ($this->connection) { |
$info .= ' [connected]'; |
} |
return $info; |
} |
// }}} |
// {{{ toString() |
/** |
* DEPRECATED: String conversion method |
* |
* @return string a string describing the current PEAR DB object |
* |
* @deprecated Method deprecated in Release 1.7.0 |
*/ |
function toString() |
{ |
return $this->__toString(); |
} |
// }}} |
// {{{ quoteString() |
/** |
* DEPRECATED: Quotes a string so it can be safely used within string |
* delimiters in a query |
* |
* @param string $string the string to be quoted |
* |
* @return string the quoted string |
* |
* @see DB_common::quoteSmart(), DB_common::escapeSimple() |
* @deprecated Method deprecated some time before Release 1.2 |
*/ |
function quoteString($string) |
{ |
$string = $this->quoteSmart($string); |
if ($string{0} == "'") { |
return substr($string, 1, -1); |
} |
return $string; |
} |
// }}} |
// {{{ quote() |
/** |
* DEPRECATED: Quotes a string so it can be safely used in a query |
* |
* @param string $string the string to quote |
* |
* @return string the quoted string or the string <samp>NULL</samp> |
* if the value submitted is <kbd>null</kbd>. |
* |
* @see DB_common::quoteSmart(), DB_common::escapeSimple() |
* @deprecated Deprecated in release 1.6.0 |
*/ |
function quote($string = null) |
{ |
return $this->quoteSmart($string); |
} |
// }}} |
// {{{ quoteIdentifier() |
/** |
* Quotes a string so it can be safely used as a table or column name |
* |
* Delimiting style depends on which database driver is being used. |
* |
* NOTE: just because you CAN use delimited identifiers doesn't mean |
* you SHOULD use them. In general, they end up causing way more |
* problems than they solve. |
* |
* Portability is broken by using the following characters inside |
* delimited identifiers: |
* + backtick (<kbd>`</kbd>) -- due to MySQL |
* + double quote (<kbd>"</kbd>) -- due to Oracle |
* + brackets (<kbd>[</kbd> or <kbd>]</kbd>) -- due to Access |
* |
* Delimited identifiers are known to generally work correctly under |
* the following drivers: |
* + mssql |
* + mysql |
* + mysqli |
* + oci8 |
* + odbc(access) |
* + odbc(db2) |
* + pgsql |
* + sqlite |
* + sybase (must execute <kbd>set quoted_identifier on</kbd> sometime |
* prior to use) |
* |
* InterBase doesn't seem to be able to use delimited identifiers |
* via PHP 4. They work fine under PHP 5. |
* |
* @param string $str the identifier name to be quoted |
* |
* @return string the quoted identifier |
* |
* @since Method available since Release 1.6.0 |
*/ |
function quoteIdentifier($str) |
{ |
return '"' . str_replace('"', '""', $str) . '"'; |
} |
// }}} |
// {{{ quoteSmart() |
/** |
* Formats input so it can be safely used in a query |
* |
* The output depends on the PHP data type of input and the database |
* type being used. |
* |
* @param mixed $in the data to be formatted |
* |
* @return mixed the formatted data. The format depends on the input's |
* PHP type: |
* <ul> |
* <li> |
* <kbd>input</kbd> -> <samp>returns</samp> |
* </li> |
* <li> |
* <kbd>null</kbd> -> the string <samp>NULL</samp> |
* </li> |
* <li> |
* <kbd>integer</kbd> or <kbd>double</kbd> -> the unquoted number |
* </li> |
* <li> |
* <kbd>bool</kbd> -> output depends on the driver in use |
* Most drivers return integers: <samp>1</samp> if |
* <kbd>true</kbd> or <samp>0</samp> if |
* <kbd>false</kbd>. |
* Some return strings: <samp>TRUE</samp> if |
* <kbd>true</kbd> or <samp>FALSE</samp> if |
* <kbd>false</kbd>. |
* Finally one returns strings: <samp>T</samp> if |
* <kbd>true</kbd> or <samp>F</samp> if |
* <kbd>false</kbd>. Here is a list of each DBMS, |
* the values returned and the suggested column type: |
* <ul> |
* <li> |
* <kbd>dbase</kbd> -> <samp>T/F</samp> |
* (<kbd>Logical</kbd>) |
* </li> |
* <li> |
* <kbd>fbase</kbd> -> <samp>TRUE/FALSE</samp> |
* (<kbd>BOOLEAN</kbd>) |
* </li> |
* <li> |
* <kbd>ibase</kbd> -> <samp>1/0</samp> |
* (<kbd>SMALLINT</kbd>) [1] |
* </li> |
* <li> |
* <kbd>ifx</kbd> -> <samp>1/0</samp> |
* (<kbd>SMALLINT</kbd>) [1] |
* </li> |
* <li> |
* <kbd>msql</kbd> -> <samp>1/0</samp> |
* (<kbd>INTEGER</kbd>) |
* </li> |
* <li> |
* <kbd>mssql</kbd> -> <samp>1/0</samp> |
* (<kbd>BIT</kbd>) |
* </li> |
* <li> |
* <kbd>mysql</kbd> -> <samp>1/0</samp> |
* (<kbd>TINYINT(1)</kbd>) |
* </li> |
* <li> |
* <kbd>mysqli</kbd> -> <samp>1/0</samp> |
* (<kbd>TINYINT(1)</kbd>) |
* </li> |
* <li> |
* <kbd>oci8</kbd> -> <samp>1/0</samp> |
* (<kbd>NUMBER(1)</kbd>) |
* </li> |
* <li> |
* <kbd>odbc</kbd> -> <samp>1/0</samp> |
* (<kbd>SMALLINT</kbd>) [1] |
* </li> |
* <li> |
* <kbd>pgsql</kbd> -> <samp>TRUE/FALSE</samp> |
* (<kbd>BOOLEAN</kbd>) |
* </li> |
* <li> |
* <kbd>sqlite</kbd> -> <samp>1/0</samp> |
* (<kbd>INTEGER</kbd>) |
* </li> |
* <li> |
* <kbd>sybase</kbd> -> <samp>1/0</samp> |
* (<kbd>TINYINT(1)</kbd>) |
* </li> |
* </ul> |
* [1] Accommodate the lowest common denominator because not all |
* versions of have <kbd>BOOLEAN</kbd>. |
* </li> |
* <li> |
* other (including strings and numeric strings) -> |
* the data with single quotes escaped by preceeding |
* single quotes, backslashes are escaped by preceeding |
* backslashes, then the whole string is encapsulated |
* between single quotes |
* </li> |
* </ul> |
* |
* @see DB_common::escapeSimple() |
* @since Method available since Release 1.6.0 |
*/ |
function quoteSmart($in) |
{ |
if (is_int($in)) { |
return $in; |
} elseif (is_float($in)) { |
return $this->quoteFloat($in); |
} elseif (is_bool($in)) { |
return $this->quoteBoolean($in); |
} elseif (is_null($in)) { |
return 'NULL'; |
} else { |
if ($this->dbsyntax == 'access' |
&& preg_match('/^#.+#$/', $in)) |
{ |
return $this->escapeSimple($in); |
} |
return "'" . $this->escapeSimple($in) . "'"; |
} |
} |
// }}} |
// {{{ quoteBoolean() |
/** |
* Formats a boolean value for use within a query in a locale-independent |
* manner. |
* |
* @param boolean the boolean value to be quoted. |
* @return string the quoted string. |
* @see DB_common::quoteSmart() |
* @since Method available since release 1.7.8. |
*/ |
function quoteBoolean($boolean) { |
return $boolean ? '1' : '0'; |
} |
// }}} |
// {{{ quoteFloat() |
/** |
* Formats a float value for use within a query in a locale-independent |
* manner. |
* |
* @param float the float value to be quoted. |
* @return string the quoted string. |
* @see DB_common::quoteSmart() |
* @since Method available since release 1.7.8. |
*/ |
function quoteFloat($float) { |
return "'".$this->escapeSimple(str_replace(',', '.', strval(floatval($float))))."'"; |
} |
// }}} |
// {{{ escapeSimple() |
/** |
* Escapes a string according to the current DBMS's standards |
* |
* In SQLite, this makes things safe for inserts/updates, but may |
* cause problems when performing text comparisons against columns |
* containing binary data. See the |
* {@link http://php.net/sqlite_escape_string PHP manual} for more info. |
* |
* @param string $str the string to be escaped |
* |
* @return string the escaped string |
* |
* @see DB_common::quoteSmart() |
* @since Method available since Release 1.6.0 |
*/ |
function escapeSimple($str) |
{ |
return str_replace("'", "''", $str); |
} |
// }}} |
// {{{ provides() |
/** |
* Tells whether the present driver supports a given feature |
* |
* @param string $feature the feature you're curious about |
* |
* @return bool whether this driver supports $feature |
*/ |
function provides($feature) |
{ |
return $this->features[$feature]; |
} |
// }}} |
// {{{ setFetchMode() |
/** |
* Sets the fetch mode that should be used by default for query results |
* |
* @param integer $fetchmode DB_FETCHMODE_ORDERED, DB_FETCHMODE_ASSOC |
* or DB_FETCHMODE_OBJECT |
* @param string $object_class the class name of the object to be returned |
* by the fetch methods when the |
* DB_FETCHMODE_OBJECT mode is selected. |
* If no class is specified by default a cast |
* to object from the assoc array row will be |
* done. There is also the posibility to use |
* and extend the 'DB_row' class. |
* |
* @see DB_FETCHMODE_ORDERED, DB_FETCHMODE_ASSOC, DB_FETCHMODE_OBJECT |
*/ |
function setFetchMode($fetchmode, $object_class = 'stdClass') |
{ |
switch ($fetchmode) { |
case DB_FETCHMODE_OBJECT: |
$this->fetchmode_object_class = $object_class; |
case DB_FETCHMODE_ORDERED: |
case DB_FETCHMODE_ASSOC: |
$this->fetchmode = $fetchmode; |
break; |
default: |
return $this->raiseError('invalid fetchmode mode'); |
} |
} |
// }}} |
// {{{ setOption() |
/** |
* Sets run-time configuration options for PEAR DB |
* |
* Options, their data types, default values and description: |
* <ul> |
* <li> |
* <var>autofree</var> <kbd>boolean</kbd> = <samp>false</samp> |
* <br />should results be freed automatically when there are no |
* more rows? |
* </li><li> |
* <var>result_buffering</var> <kbd>integer</kbd> = <samp>500</samp> |
* <br />how many rows of the result set should be buffered? |
* <br />In mysql: mysql_unbuffered_query() is used instead of |
* mysql_query() if this value is 0. (Release 1.7.0) |
* <br />In oci8: this value is passed to ocisetprefetch(). |
* (Release 1.7.0) |
* </li><li> |
* <var>debug</var> <kbd>integer</kbd> = <samp>0</samp> |
* <br />debug level |
* </li><li> |
* <var>persistent</var> <kbd>boolean</kbd> = <samp>false</samp> |
* <br />should the connection be persistent? |
* </li><li> |
* <var>portability</var> <kbd>integer</kbd> = <samp>DB_PORTABILITY_NONE</samp> |
* <br />portability mode constant (see below) |
* </li><li> |
* <var>seqname_format</var> <kbd>string</kbd> = <samp>%s_seq</samp> |
* <br />the sprintf() format string used on sequence names. This |
* format is applied to sequence names passed to |
* createSequence(), nextID() and dropSequence(). |
* </li><li> |
* <var>ssl</var> <kbd>boolean</kbd> = <samp>false</samp> |
* <br />use ssl to connect? |
* </li> |
* </ul> |
* |
* ----------------------------------------- |
* |
* PORTABILITY MODES |
* |
* These modes are bitwised, so they can be combined using <kbd>|</kbd> |
* and removed using <kbd>^</kbd>. See the examples section below on how |
* to do this. |
* |
* <samp>DB_PORTABILITY_NONE</samp> |
* turn off all portability features |
* |
* This mode gets automatically turned on if the deprecated |
* <var>optimize</var> option gets set to <samp>performance</samp>. |
* |
* |
* <samp>DB_PORTABILITY_LOWERCASE</samp> |
* convert names of tables and fields to lower case when using |
* <kbd>get*()</kbd>, <kbd>fetch*()</kbd> and <kbd>tableInfo()</kbd> |
* |
* This mode gets automatically turned on in the following databases |
* if the deprecated option <var>optimize</var> gets set to |
* <samp>portability</samp>: |
* + oci8 |
* |
* |
* <samp>DB_PORTABILITY_RTRIM</samp> |
* right trim the data output by <kbd>get*()</kbd> <kbd>fetch*()</kbd> |
* |
* |
* <samp>DB_PORTABILITY_DELETE_COUNT</samp> |
* force reporting the number of rows deleted |
* |
* Some DBMS's don't count the number of rows deleted when performing |
* simple <kbd>DELETE FROM tablename</kbd> queries. This portability |
* mode tricks such DBMS's into telling the count by adding |
* <samp>WHERE 1=1</samp> to the end of <kbd>DELETE</kbd> queries. |
* |
* This mode gets automatically turned on in the following databases |
* if the deprecated option <var>optimize</var> gets set to |
* <samp>portability</samp>: |
* + fbsql |
* + mysql |
* + mysqli |
* + sqlite |
* |
* |
* <samp>DB_PORTABILITY_NUMROWS</samp> |
* enable hack that makes <kbd>numRows()</kbd> work in Oracle |
* |
* This mode gets automatically turned on in the following databases |
* if the deprecated option <var>optimize</var> gets set to |
* <samp>portability</samp>: |
* + oci8 |
* |
* |
* <samp>DB_PORTABILITY_ERRORS</samp> |
* makes certain error messages in certain drivers compatible |
* with those from other DBMS's |
* |
* + mysql, mysqli: change unique/primary key constraints |
* DB_ERROR_ALREADY_EXISTS -> DB_ERROR_CONSTRAINT |
* |
* + odbc(access): MS's ODBC driver reports 'no such field' as code |
* 07001, which means 'too few parameters.' When this option is on |
* that code gets mapped to DB_ERROR_NOSUCHFIELD. |
* DB_ERROR_MISMATCH -> DB_ERROR_NOSUCHFIELD |
* |
* <samp>DB_PORTABILITY_NULL_TO_EMPTY</samp> |
* convert null values to empty strings in data output by get*() and |
* fetch*(). Needed because Oracle considers empty strings to be null, |
* while most other DBMS's know the difference between empty and null. |
* |
* |
* <samp>DB_PORTABILITY_ALL</samp> |
* turn on all portability features |
* |
* ----------------------------------------- |
* |
* Example 1. Simple setOption() example |
* <code> |
* $db->setOption('autofree', true); |
* </code> |
* |
* Example 2. Portability for lowercasing and trimming |
* <code> |
* $db->setOption('portability', |
* DB_PORTABILITY_LOWERCASE | DB_PORTABILITY_RTRIM); |
* </code> |
* |
* Example 3. All portability options except trimming |
* <code> |
* $db->setOption('portability', |
* DB_PORTABILITY_ALL ^ DB_PORTABILITY_RTRIM); |
* </code> |
* |
* @param string $option option name |
* @param mixed $value value for the option |
* |
* @return int DB_OK on success. A DB_Error object on failure. |
* |
* @see DB_common::$options |
*/ |
function setOption($option, $value) |
{ |
if (isset($this->options[$option])) { |
$this->options[$option] = $value; |
/* |
* Backwards compatibility check for the deprecated 'optimize' |
* option. Done here in case settings change after connecting. |
*/ |
if ($option == 'optimize') { |
if ($value == 'portability') { |
switch ($this->phptype) { |
case 'oci8': |
$this->options['portability'] = |
DB_PORTABILITY_LOWERCASE | |
DB_PORTABILITY_NUMROWS; |
break; |
case 'fbsql': |
case 'mysql': |
case 'mysqli': |
case 'sqlite': |
$this->options['portability'] = |
DB_PORTABILITY_DELETE_COUNT; |
break; |
} |
} else { |
$this->options['portability'] = DB_PORTABILITY_NONE; |
} |
} |
return DB_OK; |
} |
return $this->raiseError("unknown option $option"); |
} |
// }}} |
// {{{ getOption() |
/** |
* Returns the value of an option |
* |
* @param string $option the option name you're curious about |
* |
* @return mixed the option's value |
*/ |
function getOption($option) |
{ |
if (isset($this->options[$option])) { |
return $this->options[$option]; |
} |
return $this->raiseError("unknown option $option"); |
} |
// }}} |
// {{{ prepare() |
/** |
* Prepares a query for multiple execution with execute() |
* |
* Creates a query that can be run multiple times. Each time it is run, |
* the placeholders, if any, will be replaced by the contents of |
* execute()'s $data argument. |
* |
* Three types of placeholders can be used: |
* + <kbd>?</kbd> scalar value (i.e. strings, integers). The system |
* will automatically quote and escape the data. |
* + <kbd>!</kbd> value is inserted 'as is' |
* + <kbd>&</kbd> requires a file name. The file's contents get |
* inserted into the query (i.e. saving binary |
* data in a db) |
* |
* Example 1. |
* <code> |
* $sth = $db->prepare('INSERT INTO tbl (a, b, c) VALUES (?, !, &)'); |
* $data = array( |
* "John's text", |
* "'it''s good'", |
* 'filename.txt' |
* ); |
* $res = $db->execute($sth, $data); |
* </code> |
* |
* Use backslashes to escape placeholder characters if you don't want |
* them to be interpreted as placeholders: |
* <pre> |
* "UPDATE foo SET col=? WHERE col='over \& under'" |
* </pre> |
* |
* With some database backends, this is emulated. |
* |
* {@internal ibase and oci8 have their own prepare() methods.}} |
* |
* @param string $query the query to be prepared |
* |
* @return mixed DB statement resource on success. A DB_Error object |
* on failure. |
* |
* @see DB_common::execute() |
*/ |
function prepare($query) |
{ |
$tokens = preg_split('/((?<!\\\)[&?!])/', $query, -1, |
PREG_SPLIT_DELIM_CAPTURE); |
$token = 0; |
$types = array(); |
$newtokens = array(); |
foreach ($tokens as $val) { |
switch ($val) { |
case '?': |
$types[$token++] = DB_PARAM_SCALAR; |
break; |
case '&': |
$types[$token++] = DB_PARAM_OPAQUE; |
break; |
case '!': |
$types[$token++] = DB_PARAM_MISC; |
break; |
default: |
$newtokens[] = preg_replace('/\\\([&?!])/', "\\1", $val); |
} |
} |
$this->prepare_tokens[] = &$newtokens; |
end($this->prepare_tokens); |
$k = key($this->prepare_tokens); |
$this->prepare_types[$k] = $types; |
$this->prepared_queries[$k] = implode(' ', $newtokens); |
return $k; |
} |
// }}} |
// {{{ autoPrepare() |
/** |
* Automaticaly generates an insert or update query and pass it to prepare() |
* |
* @param string $table the table name |
* @param array $table_fields the array of field names |
* @param int $mode a type of query to make: |
* DB_AUTOQUERY_INSERT or DB_AUTOQUERY_UPDATE |
* @param string $where for update queries: the WHERE clause to |
* append to the SQL statement. Don't |
* include the "WHERE" keyword. |
* |
* @return resource the query handle |
* |
* @uses DB_common::prepare(), DB_common::buildManipSQL() |
*/ |
function autoPrepare($table, $table_fields, $mode = DB_AUTOQUERY_INSERT, |
$where = false) |
{ |
$query = $this->buildManipSQL($table, $table_fields, $mode, $where); |
if (DB::isError($query)) { |
return $query; |
} |
return $this->prepare($query); |
} |
// }}} |
// {{{ autoExecute() |
/** |
* Automaticaly generates an insert or update query and call prepare() |
* and execute() with it |
* |
* @param string $table the table name |
* @param array $fields_values the associative array where $key is a |
* field name and $value its value |
* @param int $mode a type of query to make: |
* DB_AUTOQUERY_INSERT or DB_AUTOQUERY_UPDATE |
* @param string $where for update queries: the WHERE clause to |
* append to the SQL statement. Don't |
* include the "WHERE" keyword. |
* |
* @return mixed a new DB_result object for successful SELECT queries |
* or DB_OK for successul data manipulation queries. |
* A DB_Error object on failure. |
* |
* @uses DB_common::autoPrepare(), DB_common::execute() |
*/ |
function autoExecute($table, $fields_values, $mode = DB_AUTOQUERY_INSERT, |
$where = false) |
{ |
$sth = $this->autoPrepare($table, array_keys($fields_values), $mode, |
$where); |
if (DB::isError($sth)) { |
return $sth; |
} |
$ret = $this->execute($sth, array_values($fields_values)); |
$this->freePrepared($sth); |
return $ret; |
} |
// }}} |
// {{{ buildManipSQL() |
/** |
* Produces an SQL query string for autoPrepare() |
* |
* Example: |
* <pre> |
* buildManipSQL('table_sql', array('field1', 'field2', 'field3'), |
* DB_AUTOQUERY_INSERT); |
* </pre> |
* |
* That returns |
* <samp> |
* INSERT INTO table_sql (field1,field2,field3) VALUES (?,?,?) |
* </samp> |
* |
* NOTES: |
* - This belongs more to a SQL Builder class, but this is a simple |
* facility. |
* - Be carefull! If you don't give a $where param with an UPDATE |
* query, all the records of the table will be updated! |
* |
* @param string $table the table name |
* @param array $table_fields the array of field names |
* @param int $mode a type of query to make: |
* DB_AUTOQUERY_INSERT or DB_AUTOQUERY_UPDATE |
* @param string $where for update queries: the WHERE clause to |
* append to the SQL statement. Don't |
* include the "WHERE" keyword. |
* |
* @return string the sql query for autoPrepare() |
*/ |
function buildManipSQL($table, $table_fields, $mode, $where = false) |
{ |
if (count($table_fields) == 0) { |
return $this->raiseError(DB_ERROR_NEED_MORE_DATA); |
} |
$first = true; |
switch ($mode) { |
case DB_AUTOQUERY_INSERT: |
$values = ''; |
$names = ''; |
foreach ($table_fields as $value) { |
if ($first) { |
$first = false; |
} else { |
$names .= ','; |
$values .= ','; |
} |
$names .= $value; |
$values .= '?'; |
} |
return "INSERT INTO $table ($names) VALUES ($values)"; |
case DB_AUTOQUERY_UPDATE: |
$set = ''; |
foreach ($table_fields as $value) { |
if ($first) { |
$first = false; |
} else { |
$set .= ','; |
} |
$set .= "$value = ?"; |
} |
$sql = "UPDATE $table SET $set"; |
if ($where) { |
$sql .= " WHERE $where"; |
} |
return $sql; |
default: |
return $this->raiseError(DB_ERROR_SYNTAX); |
} |
} |
// }}} |
// {{{ execute() |
/** |
* Executes a DB statement prepared with prepare() |
* |
* Example 1. |
* <code> |
* $sth = $db->prepare('INSERT INTO tbl (a, b, c) VALUES (?, !, &)'); |
* $data = array( |
* "John's text", |
* "'it''s good'", |
* 'filename.txt' |
* ); |
* $res = $db->execute($sth, $data); |
* </code> |
* |
* @param resource $stmt a DB statement resource returned from prepare() |
* @param mixed $data array, string or numeric data to be used in |
* execution of the statement. Quantity of items |
* passed must match quantity of placeholders in |
* query: meaning 1 placeholder for non-array |
* parameters or 1 placeholder per array element. |
* |
* @return mixed a new DB_result object for successful SELECT queries |
* or DB_OK for successul data manipulation queries. |
* A DB_Error object on failure. |
* |
* {@internal ibase and oci8 have their own execute() methods.}} |
* |
* @see DB_common::prepare() |
*/ |
function &execute($stmt, $data = array()) |
{ |
$realquery = $this->executeEmulateQuery($stmt, $data); |
if (DB::isError($realquery)) { |
return $realquery; |
} |
$result = $this->simpleQuery($realquery); |
if ($result === DB_OK || DB::isError($result)) { |
return $result; |
} else { |
$tmp = new DB_result($this, $result); |
return $tmp; |
} |
} |
// }}} |
// {{{ executeEmulateQuery() |
/** |
* Emulates executing prepared statements if the DBMS not support them |
* |
* @param resource $stmt a DB statement resource returned from execute() |
* @param mixed $data array, string or numeric data to be used in |
* execution of the statement. Quantity of items |
* passed must match quantity of placeholders in |
* query: meaning 1 placeholder for non-array |
* parameters or 1 placeholder per array element. |
* |
* @return mixed a string containing the real query run when emulating |
* prepare/execute. A DB_Error object on failure. |
* |
* @access protected |
* @see DB_common::execute() |
*/ |
function executeEmulateQuery($stmt, $data = array()) |
{ |
$stmt = (int)$stmt; |
$data = (array)$data; |
$this->last_parameters = $data; |
if (count($this->prepare_types[$stmt]) != count($data)) { |
$this->last_query = $this->prepared_queries[$stmt]; |
return $this->raiseError(DB_ERROR_MISMATCH); |
} |
$realquery = $this->prepare_tokens[$stmt][0]; |
$i = 0; |
foreach ($data as $value) { |
if ($this->prepare_types[$stmt][$i] == DB_PARAM_SCALAR) { |
$realquery .= $this->quoteSmart($value); |
} elseif ($this->prepare_types[$stmt][$i] == DB_PARAM_OPAQUE) { |
$fp = @fopen($value, 'rb'); |
if (!$fp) { |
return $this->raiseError(DB_ERROR_ACCESS_VIOLATION); |
} |
$realquery .= $this->quoteSmart(fread($fp, filesize($value))); |
fclose($fp); |
} else { |
$realquery .= $value; |
} |
$realquery .= $this->prepare_tokens[$stmt][++$i]; |
} |
return $realquery; |
} |
// }}} |
// {{{ executeMultiple() |
/** |
* Performs several execute() calls on the same statement handle |
* |
* $data must be an array indexed numerically |
* from 0, one execute call is done for every "row" in the array. |
* |
* If an error occurs during execute(), executeMultiple() does not |
* execute the unfinished rows, but rather returns that error. |
* |
* @param resource $stmt query handle from prepare() |
* @param array $data numeric array containing the |
* data to insert into the query |
* |
* @return int DB_OK on success. A DB_Error object on failure. |
* |
* @see DB_common::prepare(), DB_common::execute() |
*/ |
function executeMultiple($stmt, $data) |
{ |
foreach ($data as $value) { |
$res = $this->execute($stmt, $value); |
if (DB::isError($res)) { |
return $res; |
} |
} |
return DB_OK; |
} |
// }}} |
// {{{ freePrepared() |
/** |
* Frees the internal resources associated with a prepared query |
* |
* @param resource $stmt the prepared statement's PHP resource |
* @param bool $free_resource should the PHP resource be freed too? |
* Use false if you need to get data |
* from the result set later. |
* |
* @return bool TRUE on success, FALSE if $result is invalid |
* |
* @see DB_common::prepare() |
*/ |
function freePrepared($stmt, $free_resource = true) |
{ |
$stmt = (int)$stmt; |
if (isset($this->prepare_tokens[$stmt])) { |
unset($this->prepare_tokens[$stmt]); |
unset($this->prepare_types[$stmt]); |
unset($this->prepared_queries[$stmt]); |
return true; |
} |
return false; |
} |
// }}} |
// {{{ modifyQuery() |
/** |
* Changes a query string for various DBMS specific reasons |
* |
* It is defined here to ensure all drivers have this method available. |
* |
* @param string $query the query string to modify |
* |
* @return string the modified query string |
* |
* @access protected |
* @see DB_mysql::modifyQuery(), DB_oci8::modifyQuery(), |
* DB_sqlite::modifyQuery() |
*/ |
function modifyQuery($query) |
{ |
return $query; |
} |
// }}} |
// {{{ modifyLimitQuery() |
/** |
* Adds LIMIT clauses to a query string according to current DBMS standards |
* |
* It is defined here to assure that all implementations |
* have this method defined. |
* |
* @param string $query the query to modify |
* @param int $from the row to start to fetching (0 = the first row) |
* @param int $count the numbers of rows to fetch |
* @param mixed $params array, string or numeric data to be used in |
* execution of the statement. Quantity of items |
* passed must match quantity of placeholders in |
* query: meaning 1 placeholder for non-array |
* parameters or 1 placeholder per array element. |
* |
* @return string the query string with LIMIT clauses added |
* |
* @access protected |
*/ |
function modifyLimitQuery($query, $from, $count, $params = array()) |
{ |
return $query; |
} |
// }}} |
// {{{ query() |
/** |
* Sends a query to the database server |
* |
* The query string can be either a normal statement to be sent directly |
* to the server OR if <var>$params</var> are passed the query can have |
* placeholders and it will be passed through prepare() and execute(). |
* |
* @param string $query the SQL query or the statement to prepare |
* @param mixed $params array, string or numeric data to be used in |
* execution of the statement. Quantity of items |
* passed must match quantity of placeholders in |
* query: meaning 1 placeholder for non-array |
* parameters or 1 placeholder per array element. |
* |
* @return mixed a new DB_result object for successful SELECT queries |
* or DB_OK for successul data manipulation queries. |
* A DB_Error object on failure. |
* |
* @see DB_result, DB_common::prepare(), DB_common::execute() |
*/ |
function &query($query, $params = array()) |
{ |
if (sizeof($params) > 0) { |
$sth = $this->prepare($query); |
if (DB::isError($sth)) { |
return $sth; |
} |
$ret = $this->execute($sth, $params); |
$this->freePrepared($sth, false); |
return $ret; |
} else { |
$this->last_parameters = array(); |
$result = $this->simpleQuery($query); |
if ($result === DB_OK || DB::isError($result)) { |
return $result; |
} else { |
$tmp = new DB_result($this, $result); |
return $tmp; |
} |
} |
} |
// }}} |
// {{{ limitQuery() |
/** |
* Generates and executes a LIMIT query |
* |
* @param string $query the query |
* @param intr $from the row to start to fetching (0 = the first row) |
* @param int $count the numbers of rows to fetch |
* @param mixed $params array, string or numeric data to be used in |
* execution of the statement. Quantity of items |
* passed must match quantity of placeholders in |
* query: meaning 1 placeholder for non-array |
* parameters or 1 placeholder per array element. |
* |
* @return mixed a new DB_result object for successful SELECT queries |
* or DB_OK for successul data manipulation queries. |
* A DB_Error object on failure. |
*/ |
function &limitQuery($query, $from, $count, $params = array()) |
{ |
$query = $this->modifyLimitQuery($query, $from, $count, $params); |
if (DB::isError($query)){ |
return $query; |
} |
$result = $this->query($query, $params); |
if (is_object($result) && is_a($result, 'DB_result')) { |
$result->setOption('limit_from', $from); |
$result->setOption('limit_count', $count); |
} |
return $result; |
} |
// }}} |
// {{{ getOne() |
/** |
* Fetches the first column of the first row from a query result |
* |
* Takes care of doing the query and freeing the results when finished. |
* |
* @param string $query the SQL query |
* @param mixed $params array, string or numeric data to be used in |
* execution of the statement. Quantity of items |
* passed must match quantity of placeholders in |
* query: meaning 1 placeholder for non-array |
* parameters or 1 placeholder per array element. |
* |
* @return mixed the returned value of the query. |
* A DB_Error object on failure. |
*/ |
function &getOne($query, $params = array()) |
{ |
$params = (array)$params; |
// modifyLimitQuery() would be nice here, but it causes BC issues |
if (sizeof($params) > 0) { |
$sth = $this->prepare($query); |
if (DB::isError($sth)) { |
return $sth; |
} |
$res = $this->execute($sth, $params); |
$this->freePrepared($sth); |
} else { |
$res = $this->query($query); |
} |
if (DB::isError($res)) { |
return $res; |
} |
$err = $res->fetchInto($row, DB_FETCHMODE_ORDERED); |
$res->free(); |
if ($err !== DB_OK) { |
return $err; |
} |
return $row[0]; |
} |
// }}} |
// {{{ getRow() |
/** |
* Fetches the first row of data returned from a query result |
* |
* Takes care of doing the query and freeing the results when finished. |
* |
* @param string $query the SQL query |
* @param mixed $params array, string or numeric data to be used in |
* execution of the statement. Quantity of items |
* passed must match quantity of placeholders in |
* query: meaning 1 placeholder for non-array |
* parameters or 1 placeholder per array element. |
* @param int $fetchmode the fetch mode to use |
* |
* @return array the first row of results as an array. |
* A DB_Error object on failure. |
*/ |
function &getRow($query, $params = array(), |
$fetchmode = DB_FETCHMODE_DEFAULT) |
{ |
// compat check, the params and fetchmode parameters used to |
// have the opposite order |
if (!is_array($params)) { |
if (is_array($fetchmode)) { |
if ($params === null) { |
$tmp = DB_FETCHMODE_DEFAULT; |
} else { |
$tmp = $params; |
} |
$params = $fetchmode; |
$fetchmode = $tmp; |
} elseif ($params !== null) { |
$fetchmode = $params; |
$params = array(); |
} |
} |
// modifyLimitQuery() would be nice here, but it causes BC issues |
if (sizeof($params) > 0) { |
$sth = $this->prepare($query); |
if (DB::isError($sth)) { |
return $sth; |
} |
$res = $this->execute($sth, $params); |
$this->freePrepared($sth); |
} else { |
$res = $this->query($query); |
} |
if (DB::isError($res)) { |
return $res; |
} |
$err = $res->fetchInto($row, $fetchmode); |
$res->free(); |
if ($err !== DB_OK) { |
return $err; |
} |
return $row; |
} |
// }}} |
// {{{ getCol() |
/** |
* Fetches a single column from a query result and returns it as an |
* indexed array |
* |
* @param string $query the SQL query |
* @param mixed $col which column to return (integer [column number, |
* starting at 0] or string [column name]) |
* @param mixed $params array, string or numeric data to be used in |
* execution of the statement. Quantity of items |
* passed must match quantity of placeholders in |
* query: meaning 1 placeholder for non-array |
* parameters or 1 placeholder per array element. |
* |
* @return array the results as an array. A DB_Error object on failure. |
* |
* @see DB_common::query() |
*/ |
function &getCol($query, $col = 0, $params = array()) |
{ |
$params = (array)$params; |
if (sizeof($params) > 0) { |
$sth = $this->prepare($query); |
if (DB::isError($sth)) { |
return $sth; |
} |
$res = $this->execute($sth, $params); |
$this->freePrepared($sth); |
} else { |
$res = $this->query($query); |
} |
if (DB::isError($res)) { |
return $res; |
} |
$fetchmode = is_int($col) ? DB_FETCHMODE_ORDERED : DB_FETCHMODE_ASSOC; |
if (!is_array($row = $res->fetchRow($fetchmode))) { |
$ret = array(); |
} else { |
if (!array_key_exists($col, $row)) { |
$ret = $this->raiseError(DB_ERROR_NOSUCHFIELD); |
} else { |
$ret = array($row[$col]); |
while (is_array($row = $res->fetchRow($fetchmode))) { |
$ret[] = $row[$col]; |
} |
} |
} |
$res->free(); |
if (DB::isError($row)) { |
$ret = $row; |
} |
return $ret; |
} |
// }}} |
// {{{ getAssoc() |
/** |
* Fetches an entire query result and returns it as an |
* associative array using the first column as the key |
* |
* If the result set contains more than two columns, the value |
* will be an array of the values from column 2-n. If the result |
* set contains only two columns, the returned value will be a |
* scalar with the value of the second column (unless forced to an |
* array with the $force_array parameter). A DB error code is |
* returned on errors. If the result set contains fewer than two |
* columns, a DB_ERROR_TRUNCATED error is returned. |
* |
* For example, if the table "mytable" contains: |
* |
* <pre> |
* ID TEXT DATE |
* -------------------------------- |
* 1 'one' 944679408 |
* 2 'two' 944679408 |
* 3 'three' 944679408 |
* </pre> |
* |
* Then the call getAssoc('SELECT id,text FROM mytable') returns: |
* <pre> |
* array( |
* '1' => 'one', |
* '2' => 'two', |
* '3' => 'three', |
* ) |
* </pre> |
* |
* ...while the call getAssoc('SELECT id,text,date FROM mytable') returns: |
* <pre> |
* array( |
* '1' => array('one', '944679408'), |
* '2' => array('two', '944679408'), |
* '3' => array('three', '944679408') |
* ) |
* </pre> |
* |
* If the more than one row occurs with the same value in the |
* first column, the last row overwrites all previous ones by |
* default. Use the $group parameter if you don't want to |
* overwrite like this. Example: |
* |
* <pre> |
* getAssoc('SELECT category,id,name FROM mytable', false, null, |
* DB_FETCHMODE_ASSOC, true) returns: |
* |
* array( |
* '1' => array(array('id' => '4', 'name' => 'number four'), |
* array('id' => '6', 'name' => 'number six') |
* ), |
* '9' => array(array('id' => '4', 'name' => 'number four'), |
* array('id' => '6', 'name' => 'number six') |
* ) |
* ) |
* </pre> |
* |
* Keep in mind that database functions in PHP usually return string |
* values for results regardless of the database's internal type. |
* |
* @param string $query the SQL query |
* @param bool $force_array used only when the query returns |
* exactly two columns. If true, the values |
* of the returned array will be one-element |
* arrays instead of scalars. |
* @param mixed $params array, string or numeric data to be used in |
* execution of the statement. Quantity of |
* items passed must match quantity of |
* placeholders in query: meaning 1 |
* placeholder for non-array parameters or |
* 1 placeholder per array element. |
* @param int $fetchmode the fetch mode to use |
* @param bool $group if true, the values of the returned array |
* is wrapped in another array. If the same |
* key value (in the first column) repeats |
* itself, the values will be appended to |
* this array instead of overwriting the |
* existing values. |
* |
* @return array the associative array containing the query results. |
* A DB_Error object on failure. |
*/ |
function &getAssoc($query, $force_array = false, $params = array(), |
$fetchmode = DB_FETCHMODE_DEFAULT, $group = false) |
{ |
$params = (array)$params; |
if (sizeof($params) > 0) { |
$sth = $this->prepare($query); |
if (DB::isError($sth)) { |
return $sth; |
} |
$res = $this->execute($sth, $params); |
$this->freePrepared($sth); |
} else { |
$res = $this->query($query); |
} |
if (DB::isError($res)) { |
return $res; |
} |
if ($fetchmode == DB_FETCHMODE_DEFAULT) { |
$fetchmode = $this->fetchmode; |
} |
$cols = $res->numCols(); |
if ($cols < 2) { |
$tmp = $this->raiseError(DB_ERROR_TRUNCATED); |
return $tmp; |
} |
$results = array(); |
if ($cols > 2 || $force_array) { |
// return array values |
// XXX this part can be optimized |
if ($fetchmode == DB_FETCHMODE_ASSOC) { |
while (is_array($row = $res->fetchRow(DB_FETCHMODE_ASSOC))) { |
reset($row); |
$key = current($row); |
unset($row[key($row)]); |
if ($group) { |
$results[$key][] = $row; |
} else { |
$results[$key] = $row; |
} |
} |
} elseif ($fetchmode == DB_FETCHMODE_OBJECT) { |
while ($row = $res->fetchRow(DB_FETCHMODE_OBJECT)) { |
$arr = get_object_vars($row); |
$key = current($arr); |
if ($group) { |
$results[$key][] = $row; |
} else { |
$results[$key] = $row; |
} |
} |
} else { |
while (is_array($row = $res->fetchRow(DB_FETCHMODE_ORDERED))) { |
// we shift away the first element to get |
// indices running from 0 again |
$key = array_shift($row); |
if ($group) { |
$results[$key][] = $row; |
} else { |
$results[$key] = $row; |
} |
} |
} |
if (DB::isError($row)) { |
$results = $row; |
} |
} else { |
// return scalar values |
while (is_array($row = $res->fetchRow(DB_FETCHMODE_ORDERED))) { |
if ($group) { |
$results[$row[0]][] = $row[1]; |
} else { |
$results[$row[0]] = $row[1]; |
} |
} |
if (DB::isError($row)) { |
$results = $row; |
} |
} |
$res->free(); |
return $results; |
} |
// }}} |
// {{{ getAll() |
/** |
* Fetches all of the rows from a query result |
* |
* @param string $query the SQL query |
* @param mixed $params array, string or numeric data to be used in |
* execution of the statement. Quantity of |
* items passed must match quantity of |
* placeholders in query: meaning 1 |
* placeholder for non-array parameters or |
* 1 placeholder per array element. |
* @param int $fetchmode the fetch mode to use: |
* + DB_FETCHMODE_ORDERED |
* + DB_FETCHMODE_ASSOC |
* + DB_FETCHMODE_ORDERED | DB_FETCHMODE_FLIPPED |
* + DB_FETCHMODE_ASSOC | DB_FETCHMODE_FLIPPED |
* |
* @return array the nested array. A DB_Error object on failure. |
*/ |
function &getAll($query, $params = array(), |
$fetchmode = DB_FETCHMODE_DEFAULT) |
{ |
// compat check, the params and fetchmode parameters used to |
// have the opposite order |
if (!is_array($params)) { |
if (is_array($fetchmode)) { |
if ($params === null) { |
$tmp = DB_FETCHMODE_DEFAULT; |
} else { |
$tmp = $params; |
} |
$params = $fetchmode; |
$fetchmode = $tmp; |
} elseif ($params !== null) { |
$fetchmode = $params; |
$params = array(); |
} |
} |
if (sizeof($params) > 0) { |
$sth = $this->prepare($query); |
if (DB::isError($sth)) { |
return $sth; |
} |
$res = $this->execute($sth, $params); |
$this->freePrepared($sth); |
} else { |
$res = $this->query($query); |
} |
if ($res === DB_OK || DB::isError($res)) { |
return $res; |
} |
$results = array(); |
while (DB_OK === $res->fetchInto($row, $fetchmode)) { |
if ($fetchmode & DB_FETCHMODE_FLIPPED) { |
foreach ($row as $key => $val) { |
$results[$key][] = $val; |
} |
} else { |
$results[] = $row; |
} |
} |
$res->free(); |
if (DB::isError($row)) { |
$tmp = $this->raiseError($row); |
return $tmp; |
} |
return $results; |
} |
// }}} |
// {{{ autoCommit() |
/** |
* Enables or disables automatic commits |
* |
* @param bool $onoff true turns it on, false turns it off |
* |
* @return int DB_OK on success. A DB_Error object if the driver |
* doesn't support auto-committing transactions. |
*/ |
function autoCommit($onoff = false) |
{ |
return $this->raiseError(DB_ERROR_NOT_CAPABLE); |
} |
// }}} |
// {{{ commit() |
/** |
* Commits the current transaction |
* |
* @return int DB_OK on success. A DB_Error object on failure. |
*/ |
function commit() |
{ |
return $this->raiseError(DB_ERROR_NOT_CAPABLE); |
} |
// }}} |
// {{{ rollback() |
/** |
* Reverts the current transaction |
* |
* @return int DB_OK on success. A DB_Error object on failure. |
*/ |
function rollback() |
{ |
return $this->raiseError(DB_ERROR_NOT_CAPABLE); |
} |
// }}} |
// {{{ numRows() |
/** |
* Determines the number of rows in a query result |
* |
* @param resource $result the query result idenifier produced by PHP |
* |
* @return int the number of rows. A DB_Error object on failure. |
*/ |
function numRows($result) |
{ |
return $this->raiseError(DB_ERROR_NOT_CAPABLE); |
} |
// }}} |
// {{{ affectedRows() |
/** |
* Determines the number of rows affected by a data maniuplation query |
* |
* 0 is returned for queries that don't manipulate data. |
* |
* @return int the number of rows. A DB_Error object on failure. |
*/ |
function affectedRows() |
{ |
return $this->raiseError(DB_ERROR_NOT_CAPABLE); |
} |
// }}} |
// {{{ getSequenceName() |
/** |
* Generates the name used inside the database for a sequence |
* |
* The createSequence() docblock contains notes about storing sequence |
* names. |
* |
* @param string $sqn the sequence's public name |
* |
* @return string the sequence's name in the backend |
* |
* @access protected |
* @see DB_common::createSequence(), DB_common::dropSequence(), |
* DB_common::nextID(), DB_common::setOption() |
*/ |
function getSequenceName($sqn) |
{ |
return sprintf($this->getOption('seqname_format'), |
preg_replace('/[^a-z0-9_.]/i', '_', $sqn)); |
} |
// }}} |
// {{{ nextId() |
/** |
* Returns the next free id in a sequence |
* |
* @param string $seq_name name of the sequence |
* @param boolean $ondemand when true, the seqence is automatically |
* created if it does not exist |
* |
* @return int the next id number in the sequence. |
* A DB_Error object on failure. |
* |
* @see DB_common::createSequence(), DB_common::dropSequence(), |
* DB_common::getSequenceName() |
*/ |
function nextId($seq_name, $ondemand = true) |
{ |
return $this->raiseError(DB_ERROR_NOT_CAPABLE); |
} |
// }}} |
// {{{ createSequence() |
/** |
* Creates a new sequence |
* |
* The name of a given sequence is determined by passing the string |
* provided in the <var>$seq_name</var> argument through PHP's sprintf() |
* function using the value from the <var>seqname_format</var> option as |
* the sprintf()'s format argument. |
* |
* <var>seqname_format</var> is set via setOption(). |
* |
* @param string $seq_name name of the new sequence |
* |
* @return int DB_OK on success. A DB_Error object on failure. |
* |
* @see DB_common::dropSequence(), DB_common::getSequenceName(), |
* DB_common::nextID() |
*/ |
function createSequence($seq_name) |
{ |
return $this->raiseError(DB_ERROR_NOT_CAPABLE); |
} |
// }}} |
// {{{ dropSequence() |
/** |
* Deletes a sequence |
* |
* @param string $seq_name name of the sequence to be deleted |
* |
* @return int DB_OK on success. A DB_Error object on failure. |
* |
* @see DB_common::createSequence(), DB_common::getSequenceName(), |
* DB_common::nextID() |
*/ |
function dropSequence($seq_name) |
{ |
return $this->raiseError(DB_ERROR_NOT_CAPABLE); |
} |
// }}} |
// {{{ raiseError() |
/** |
* Communicates an error and invoke error callbacks, etc |
* |
* Basically a wrapper for PEAR::raiseError without the message string. |
* |
* @param mixed integer error code, or a PEAR error object (all |
* other parameters are ignored if this parameter is |
* an object |
* @param int error mode, see PEAR_Error docs |
* @param mixed if error mode is PEAR_ERROR_TRIGGER, this is the |
* error level (E_USER_NOTICE etc). If error mode is |
* PEAR_ERROR_CALLBACK, this is the callback function, |
* either as a function name, or as an array of an |
* object and method name. For other error modes this |
* parameter is ignored. |
* @param string extra debug information. Defaults to the last |
* query and native error code. |
* @param mixed native error code, integer or string depending the |
* backend |
* @param mixed dummy parameter for E_STRICT compatibility with |
* PEAR::raiseError |
* @param mixed dummy parameter for E_STRICT compatibility with |
* PEAR::raiseError |
* |
* @return object the PEAR_Error object |
* |
* @see PEAR_Error |
*/ |
function &raiseError($code = DB_ERROR, $mode = null, $options = null, |
$userinfo = null, $nativecode = null, $dummy1 = null, |
$dummy2 = null) |
{ |
// The error is yet a DB error object |
if (is_object($code)) { |
// because we the static PEAR::raiseError, our global |
// handler should be used if it is set |
if ($mode === null && !empty($this->_default_error_mode)) { |
$mode = $this->_default_error_mode; |
$options = $this->_default_error_options; |
} |
$tmp = PEAR::raiseError($code, null, $mode, $options, |
null, null, true); |
return $tmp; |
} |
if ($userinfo === null) { |
$userinfo = $this->last_query; |
} |
if ($nativecode) { |
$userinfo .= ' [nativecode=' . trim($nativecode) . ']'; |
} else { |
$userinfo .= ' [DB Error: ' . DB::errorMessage($code) . ']'; |
} |
$tmp = PEAR::raiseError(null, $code, $mode, $options, $userinfo, |
'DB_Error', true); |
return $tmp; |
} |
// }}} |
// {{{ errorNative() |
/** |
* Gets the DBMS' native error code produced by the last query |
* |
* @return mixed the DBMS' error code. A DB_Error object on failure. |
*/ |
function errorNative() |
{ |
return $this->raiseError(DB_ERROR_NOT_CAPABLE); |
} |
// }}} |
// {{{ errorCode() |
/** |
* Maps native error codes to DB's portable ones |
* |
* Uses the <var>$errorcode_map</var> property defined in each driver. |
* |
* @param string|int $nativecode the error code returned by the DBMS |
* |
* @return int the portable DB error code. Return DB_ERROR if the |
* current driver doesn't have a mapping for the |
* $nativecode submitted. |
*/ |
function errorCode($nativecode) |
{ |
if (isset($this->errorcode_map[$nativecode])) { |
return $this->errorcode_map[$nativecode]; |
} |
// Fall back to DB_ERROR if there was no mapping. |
return DB_ERROR; |
} |
// }}} |
// {{{ errorMessage() |
/** |
* Maps a DB error code to a textual message |
* |
* @param integer $dbcode the DB error code |
* |
* @return string the error message corresponding to the error code |
* submitted. FALSE if the error code is unknown. |
* |
* @see DB::errorMessage() |
*/ |
function errorMessage($dbcode) |
{ |
return DB::errorMessage($this->errorcode_map[$dbcode]); |
} |
// }}} |
// {{{ tableInfo() |
/** |
* Returns information about a table or a result set |
* |
* The format of the resulting array depends on which <var>$mode</var> |
* you select. The sample output below is based on this query: |
* <pre> |
* SELECT tblFoo.fldID, tblFoo.fldPhone, tblBar.fldId |
* FROM tblFoo |
* JOIN tblBar ON tblFoo.fldId = tblBar.fldId |
* </pre> |
* |
* <ul> |
* <li> |
* |
* <kbd>null</kbd> (default) |
* <pre> |
* [0] => Array ( |
* [table] => tblFoo |
* [name] => fldId |
* [type] => int |
* [len] => 11 |
* [flags] => primary_key not_null |
* ) |
* [1] => Array ( |
* [table] => tblFoo |
* [name] => fldPhone |
* [type] => string |
* [len] => 20 |
* [flags] => |
* ) |
* [2] => Array ( |
* [table] => tblBar |
* [name] => fldId |
* [type] => int |
* [len] => 11 |
* [flags] => primary_key not_null |
* ) |
* </pre> |
* |
* </li><li> |
* |
* <kbd>DB_TABLEINFO_ORDER</kbd> |
* |
* <p>In addition to the information found in the default output, |
* a notation of the number of columns is provided by the |
* <samp>num_fields</samp> element while the <samp>order</samp> |
* element provides an array with the column names as the keys and |
* their location index number (corresponding to the keys in the |
* the default output) as the values.</p> |
* |
* <p>If a result set has identical field names, the last one is |
* used.</p> |
* |
* <pre> |
* [num_fields] => 3 |
* [order] => Array ( |
* [fldId] => 2 |
* [fldTrans] => 1 |
* ) |
* </pre> |
* |
* </li><li> |
* |
* <kbd>DB_TABLEINFO_ORDERTABLE</kbd> |
* |
* <p>Similar to <kbd>DB_TABLEINFO_ORDER</kbd> but adds more |
* dimensions to the array in which the table names are keys and |
* the field names are sub-keys. This is helpful for queries that |
* join tables which have identical field names.</p> |
* |
* <pre> |
* [num_fields] => 3 |
* [ordertable] => Array ( |
* [tblFoo] => Array ( |
* [fldId] => 0 |
* [fldPhone] => 1 |
* ) |
* [tblBar] => Array ( |
* [fldId] => 2 |
* ) |
* ) |
* </pre> |
* |
* </li> |
* </ul> |
* |
* The <samp>flags</samp> element contains a space separated list |
* of extra information about the field. This data is inconsistent |
* between DBMS's due to the way each DBMS works. |
* + <samp>primary_key</samp> |
* + <samp>unique_key</samp> |
* + <samp>multiple_key</samp> |
* + <samp>not_null</samp> |
* |
* Most DBMS's only provide the <samp>table</samp> and <samp>flags</samp> |
* elements if <var>$result</var> is a table name. The following DBMS's |
* provide full information from queries: |
* + fbsql |
* + mysql |
* |
* If the 'portability' option has <samp>DB_PORTABILITY_LOWERCASE</samp> |
* turned on, the names of tables and fields will be lowercased. |
* |
* @param object|string $result DB_result object from a query or a |
* string containing the name of a table. |
* While this also accepts a query result |
* resource identifier, this behavior is |
* deprecated. |
* @param int $mode either unused or one of the tableInfo modes: |
* <kbd>DB_TABLEINFO_ORDERTABLE</kbd>, |
* <kbd>DB_TABLEINFO_ORDER</kbd> or |
* <kbd>DB_TABLEINFO_FULL</kbd> (which does both). |
* These are bitwise, so the first two can be |
* combined using <kbd>|</kbd>. |
* |
* @return array an associative array with the information requested. |
* A DB_Error object on failure. |
* |
* @see DB_common::setOption() |
*/ |
function tableInfo($result, $mode = null) |
{ |
/* |
* If the DB_<driver> class has a tableInfo() method, that one |
* overrides this one. But, if the driver doesn't have one, |
* this method runs and tells users about that fact. |
*/ |
return $this->raiseError(DB_ERROR_NOT_CAPABLE); |
} |
// }}} |
// {{{ getTables() |
/** |
* Lists the tables in the current database |
* |
* @return array the list of tables. A DB_Error object on failure. |
* |
* @deprecated Method deprecated some time before Release 1.2 |
*/ |
function getTables() |
{ |
return $this->getListOf('tables'); |
} |
// }}} |
// {{{ getListOf() |
/** |
* Lists internal database information |
* |
* @param string $type type of information being sought. |
* Common items being sought are: |
* tables, databases, users, views, functions |
* Each DBMS's has its own capabilities. |
* |
* @return array an array listing the items sought. |
* A DB DB_Error object on failure. |
*/ |
function getListOf($type) |
{ |
$sql = $this->getSpecialQuery($type); |
if ($sql === null) { |
$this->last_query = ''; |
return $this->raiseError(DB_ERROR_UNSUPPORTED); |
} elseif (is_int($sql) || DB::isError($sql)) { |
// Previous error |
return $this->raiseError($sql); |
} elseif (is_array($sql)) { |
// Already the result |
return $sql; |
} |
// Launch this query |
return $this->getCol($sql); |
} |
// }}} |
// {{{ getSpecialQuery() |
/** |
* Obtains the query string needed for listing a given type of objects |
* |
* @param string $type the kind of objects you want to retrieve |
* |
* @return string the SQL query string or null if the driver doesn't |
* support the object type requested |
* |
* @access protected |
* @see DB_common::getListOf() |
*/ |
function getSpecialQuery($type) |
{ |
return $this->raiseError(DB_ERROR_UNSUPPORTED); |
} |
// }}} |
// {{{ nextQueryIsManip() |
/** |
* Sets (or unsets) a flag indicating that the next query will be a |
* manipulation query, regardless of the usual DB::isManip() heuristics. |
* |
* @param boolean true to set the flag overriding the isManip() behaviour, |
* false to clear it and fall back onto isManip() |
* |
* @return void |
* |
* @access public |
*/ |
function nextQueryIsManip($manip) |
{ |
$this->_next_query_manip = $manip; |
} |
// }}} |
// {{{ _checkManip() |
/** |
* Checks if the given query is a manipulation query. This also takes into |
* account the _next_query_manip flag and sets the _last_query_manip flag |
* (and resets _next_query_manip) according to the result. |
* |
* @param string The query to check. |
* |
* @return boolean true if the query is a manipulation query, false |
* otherwise |
* |
* @access protected |
*/ |
function _checkManip($query) |
{ |
if ($this->_next_query_manip || DB::isManip($query)) { |
$this->_last_query_manip = true; |
} else { |
$this->_last_query_manip = false; |
} |
$this->_next_query_manip = false; |
return $this->_last_query_manip; |
$manip = $this->_next_query_manip; |
} |
// }}} |
// {{{ _rtrimArrayValues() |
/** |
* Right-trims all strings in an array |
* |
* @param array $array the array to be trimmed (passed by reference) |
* |
* @return void |
* |
* @access protected |
*/ |
function _rtrimArrayValues(&$array) |
{ |
foreach ($array as $key => $value) { |
if (is_string($value)) { |
$array[$key] = rtrim($value); |
} |
} |
} |
// }}} |
// {{{ _convertNullArrayValuesToEmpty() |
/** |
* Converts all null values in an array to empty strings |
* |
* @param array $array the array to be de-nullified (passed by reference) |
* |
* @return void |
* |
* @access protected |
*/ |
function _convertNullArrayValuesToEmpty(&$array) |
{ |
foreach ($array as $key => $value) { |
if (is_null($value)) { |
$array[$key] = ''; |
} |
} |
} |
// }}} |
} |
/* |
* Local variables: |
* tab-width: 4 |
* c-basic-offset: 4 |
* End: |
*/ |
?> |
/branches/v1.3-critias/bibliotheque/pear/DB/msql.php |
---|
New file |
0,0 → 1,831 |
<?php |
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */ |
/** |
* The PEAR DB driver for PHP's msql extension |
* for interacting with Mini SQL databases |
* |
* PHP's mSQL extension did weird things with NULL values prior to PHP |
* 4.3.11 and 5.0.4. Make sure your version of PHP meets or exceeds |
* those versions. |
* |
* PHP version 5 |
* |
* LICENSE: This source file is subject to version 3.0 of the PHP license |
* that is available through the world-wide-web at the following URI: |
* http://www.php.net/license/3_0.txt. If you did not receive a copy of |
* the PHP License and are unable to obtain it through the web, please |
* send a note to license@php.net so we can mail you a copy immediately. |
* |
* @category Database |
* @package DB |
* @author Daniel Convissor <danielc@php.net> |
* @copyright 1997-2007 The PHP Group |
* @license http://www.php.net/license/3_0.txt PHP License 3.0 |
* @version CVS: $Id$ |
* @link http://pear.php.net/package/DB |
*/ |
/** |
* Obtain the DB_common class so it can be extended from |
*/ |
require_once 'DB/common.php'; |
/** |
* The methods PEAR DB uses to interact with PHP's msql extension |
* for interacting with Mini SQL databases |
* |
* These methods overload the ones declared in DB_common. |
* |
* PHP's mSQL extension did weird things with NULL values prior to PHP |
* 4.3.11 and 5.0.4. Make sure your version of PHP meets or exceeds |
* those versions. |
* |
* @category Database |
* @package DB |
* @author Daniel Convissor <danielc@php.net> |
* @copyright 1997-2007 The PHP Group |
* @license http://www.php.net/license/3_0.txt PHP License 3.0 |
* @version Release: 1.9.2 |
* @link http://pear.php.net/package/DB |
* @since Class not functional until Release 1.7.0 |
*/ |
class DB_msql extends DB_common |
{ |
// {{{ properties |
/** |
* The DB driver type (mysql, oci8, odbc, etc.) |
* @var string |
*/ |
var $phptype = 'msql'; |
/** |
* The database syntax variant to be used (db2, access, etc.), if any |
* @var string |
*/ |
var $dbsyntax = 'msql'; |
/** |
* The capabilities of this DB implementation |
* |
* The 'new_link' element contains the PHP version that first provided |
* new_link support for this DBMS. Contains false if it's unsupported. |
* |
* Meaning of the 'limit' element: |
* + 'emulate' = emulate with fetch row by number |
* + 'alter' = alter the query |
* + false = skip rows |
* |
* @var array |
*/ |
var $features = array( |
'limit' => 'emulate', |
'new_link' => false, |
'numrows' => true, |
'pconnect' => true, |
'prepare' => false, |
'ssl' => false, |
'transactions' => false, |
); |
/** |
* A mapping of native error codes to DB error codes |
* @var array |
*/ |
var $errorcode_map = array( |
); |
/** |
* The raw database connection created by PHP |
* @var resource |
*/ |
var $connection; |
/** |
* The DSN information for connecting to a database |
* @var array |
*/ |
var $dsn = array(); |
/** |
* The query result resource created by PHP |
* |
* Used to make affectedRows() work. Only contains the result for |
* data manipulation queries. Contains false for other queries. |
* |
* @var resource |
* @access private |
*/ |
var $_result; |
// }}} |
// {{{ constructor |
/** |
* This constructor calls <kbd>parent::__construct()</kbd> |
* |
* @return void |
*/ |
function __construct() |
{ |
parent::__construct(); |
} |
// }}} |
// {{{ connect() |
/** |
* Connect to the database server, log in and open the database |
* |
* Don't call this method directly. Use DB::connect() instead. |
* |
* Example of how to connect: |
* <code> |
* require_once 'DB.php'; |
* |
* // $dsn = 'msql://hostname/dbname'; // use a TCP connection |
* $dsn = 'msql:///dbname'; // use a socket |
* $options = array( |
* 'portability' => DB_PORTABILITY_ALL, |
* ); |
* |
* $db = DB::connect($dsn, $options); |
* if (PEAR::isError($db)) { |
* die($db->getMessage()); |
* } |
* </code> |
* |
* @param array $dsn the data source name |
* @param bool $persistent should the connection be persistent? |
* |
* @return int DB_OK on success. A DB_Error object on failure. |
*/ |
function connect($dsn, $persistent = false) |
{ |
if (!PEAR::loadExtension('msql')) { |
return $this->raiseError(DB_ERROR_EXTENSION_NOT_FOUND); |
} |
$this->dsn = $dsn; |
if ($dsn['dbsyntax']) { |
$this->dbsyntax = $dsn['dbsyntax']; |
} |
$params = array(); |
if ($dsn['hostspec']) { |
$params[] = $dsn['port'] |
? $dsn['hostspec'] . ',' . $dsn['port'] |
: $dsn['hostspec']; |
} |
$connect_function = $persistent ? 'msql_pconnect' : 'msql_connect'; |
$ini = ini_get('track_errors'); |
$php_errormsg = ''; |
if ($ini) { |
$this->connection = @call_user_func_array($connect_function, |
$params); |
} else { |
@ini_set('track_errors', 1); |
$this->connection = @call_user_func_array($connect_function, |
$params); |
@ini_set('track_errors', $ini); |
} |
if (!$this->connection) { |
if (($err = @msql_error()) != '') { |
return $this->raiseError(DB_ERROR_CONNECT_FAILED, |
null, null, null, |
$err); |
} else { |
return $this->raiseError(DB_ERROR_CONNECT_FAILED, |
null, null, null, |
$php_errormsg); |
} |
} |
if (!@msql_select_db($dsn['database'], $this->connection)) { |
return $this->msqlRaiseError(); |
} |
return DB_OK; |
} |
// }}} |
// {{{ disconnect() |
/** |
* Disconnects from the database server |
* |
* @return bool TRUE on success, FALSE on failure |
*/ |
function disconnect() |
{ |
$ret = @msql_close($this->connection); |
$this->connection = null; |
return $ret; |
} |
// }}} |
// {{{ simpleQuery() |
/** |
* Sends a query to the database server |
* |
* @param string the SQL query string |
* |
* @return mixed + a PHP result resrouce for successful SELECT queries |
* + the DB_OK constant for other successful queries |
* + a DB_Error object on failure |
*/ |
function simpleQuery($query) |
{ |
$this->last_query = $query; |
$query = $this->modifyQuery($query); |
$result = @msql_query($query, $this->connection); |
if (!$result) { |
return $this->msqlRaiseError(); |
} |
// Determine which queries that should return data, and which |
// should return an error code only. |
if ($this->_checkManip($query)) { |
$this->_result = $result; |
return DB_OK; |
} else { |
$this->_result = false; |
return $result; |
} |
} |
// }}} |
// {{{ nextResult() |
/** |
* Move the internal msql result pointer to the next available result |
* |
* @param a valid fbsql result resource |
* |
* @access public |
* |
* @return true if a result is available otherwise return false |
*/ |
function nextResult($result) |
{ |
return false; |
} |
// }}} |
// {{{ fetchInto() |
/** |
* Places a row from the result set into the given array |
* |
* Formating of the array and the data therein are configurable. |
* See DB_result::fetchInto() for more information. |
* |
* This method is not meant to be called directly. Use |
* DB_result::fetchInto() instead. It can't be declared "protected" |
* because DB_result is a separate object. |
* |
* PHP's mSQL extension did weird things with NULL values prior to PHP |
* 4.3.11 and 5.0.4. Make sure your version of PHP meets or exceeds |
* those versions. |
* |
* @param resource $result the query result resource |
* @param array $arr the referenced array to put the data in |
* @param int $fetchmode how the resulting array should be indexed |
* @param int $rownum the row number to fetch (0 = first row) |
* |
* @return mixed DB_OK on success, NULL when the end of a result set is |
* reached or on failure |
* |
* @see DB_result::fetchInto() |
*/ |
function fetchInto($result, &$arr, $fetchmode, $rownum = null) |
{ |
if ($rownum !== null) { |
if (!@msql_data_seek($result, $rownum)) { |
return null; |
} |
} |
if ($fetchmode & DB_FETCHMODE_ASSOC) { |
$arr = @msql_fetch_array($result, MSQL_ASSOC); |
if ($this->options['portability'] & DB_PORTABILITY_LOWERCASE && $arr) { |
$arr = array_change_key_case($arr, CASE_LOWER); |
} |
} else { |
$arr = @msql_fetch_row($result); |
} |
if (!$arr) { |
return null; |
} |
if ($this->options['portability'] & DB_PORTABILITY_RTRIM) { |
$this->_rtrimArrayValues($arr); |
} |
if ($this->options['portability'] & DB_PORTABILITY_NULL_TO_EMPTY) { |
$this->_convertNullArrayValuesToEmpty($arr); |
} |
return DB_OK; |
} |
// }}} |
// {{{ freeResult() |
/** |
* Deletes the result set and frees the memory occupied by the result set |
* |
* This method is not meant to be called directly. Use |
* DB_result::free() instead. It can't be declared "protected" |
* because DB_result is a separate object. |
* |
* @param resource $result PHP's query result resource |
* |
* @return bool TRUE on success, FALSE if $result is invalid |
* |
* @see DB_result::free() |
*/ |
function freeResult($result) |
{ |
return is_resource($result) ? msql_free_result($result) : false; |
} |
// }}} |
// {{{ numCols() |
/** |
* Gets the number of columns in a result set |
* |
* This method is not meant to be called directly. Use |
* DB_result::numCols() instead. It can't be declared "protected" |
* because DB_result is a separate object. |
* |
* @param resource $result PHP's query result resource |
* |
* @return int the number of columns. A DB_Error object on failure. |
* |
* @see DB_result::numCols() |
*/ |
function numCols($result) |
{ |
$cols = @msql_num_fields($result); |
if (!$cols) { |
return $this->msqlRaiseError(); |
} |
return $cols; |
} |
// }}} |
// {{{ numRows() |
/** |
* Gets the number of rows in a result set |
* |
* This method is not meant to be called directly. Use |
* DB_result::numRows() instead. It can't be declared "protected" |
* because DB_result is a separate object. |
* |
* @param resource $result PHP's query result resource |
* |
* @return int the number of rows. A DB_Error object on failure. |
* |
* @see DB_result::numRows() |
*/ |
function numRows($result) |
{ |
$rows = @msql_num_rows($result); |
if ($rows === false) { |
return $this->msqlRaiseError(); |
} |
return $rows; |
} |
// }}} |
// {{{ affected() |
/** |
* Determines the number of rows affected by a data maniuplation query |
* |
* 0 is returned for queries that don't manipulate data. |
* |
* @return int the number of rows. A DB_Error object on failure. |
*/ |
function affectedRows() |
{ |
if (!$this->_result) { |
return 0; |
} |
return msql_affected_rows($this->_result); |
} |
// }}} |
// {{{ nextId() |
/** |
* Returns the next free id in a sequence |
* |
* @param string $seq_name name of the sequence |
* @param boolean $ondemand when true, the seqence is automatically |
* created if it does not exist |
* |
* @return int the next id number in the sequence. |
* A DB_Error object on failure. |
* |
* @see DB_common::nextID(), DB_common::getSequenceName(), |
* DB_msql::createSequence(), DB_msql::dropSequence() |
*/ |
function nextId($seq_name, $ondemand = true) |
{ |
$seqname = $this->getSequenceName($seq_name); |
$repeat = false; |
do { |
$this->pushErrorHandling(PEAR_ERROR_RETURN); |
$result = $this->query("SELECT _seq FROM ${seqname}"); |
$this->popErrorHandling(); |
if ($ondemand && DB::isError($result) && |
$result->getCode() == DB_ERROR_NOSUCHTABLE) { |
$repeat = true; |
$this->pushErrorHandling(PEAR_ERROR_RETURN); |
$result = $this->createSequence($seq_name); |
$this->popErrorHandling(); |
if (DB::isError($result)) { |
return $this->raiseError($result); |
} |
} else { |
$repeat = false; |
} |
} while ($repeat); |
if (DB::isError($result)) { |
return $this->raiseError($result); |
} |
$arr = $result->fetchRow(DB_FETCHMODE_ORDERED); |
$result->free(); |
return $arr[0]; |
} |
// }}} |
// {{{ createSequence() |
/** |
* Creates a new sequence |
* |
* Also creates a new table to associate the sequence with. Uses |
* a separate table to ensure portability with other drivers. |
* |
* @param string $seq_name name of the new sequence |
* |
* @return int DB_OK on success. A DB_Error object on failure. |
* |
* @see DB_common::createSequence(), DB_common::getSequenceName(), |
* DB_msql::nextID(), DB_msql::dropSequence() |
*/ |
function createSequence($seq_name) |
{ |
$seqname = $this->getSequenceName($seq_name); |
$res = $this->query('CREATE TABLE ' . $seqname |
. ' (id INTEGER NOT NULL)'); |
if (DB::isError($res)) { |
return $res; |
} |
$res = $this->query("CREATE SEQUENCE ON ${seqname}"); |
return $res; |
} |
// }}} |
// {{{ dropSequence() |
/** |
* Deletes a sequence |
* |
* @param string $seq_name name of the sequence to be deleted |
* |
* @return int DB_OK on success. A DB_Error object on failure. |
* |
* @see DB_common::dropSequence(), DB_common::getSequenceName(), |
* DB_msql::nextID(), DB_msql::createSequence() |
*/ |
function dropSequence($seq_name) |
{ |
return $this->query('DROP TABLE ' . $this->getSequenceName($seq_name)); |
} |
// }}} |
// {{{ quoteIdentifier() |
/** |
* mSQL does not support delimited identifiers |
* |
* @param string $str the identifier name to be quoted |
* |
* @return object a DB_Error object |
* |
* @see DB_common::quoteIdentifier() |
* @since Method available since Release 1.7.0 |
*/ |
function quoteIdentifier($str) |
{ |
return $this->raiseError(DB_ERROR_UNSUPPORTED); |
} |
// }}} |
// {{{ quoteFloat() |
/** |
* Formats a float value for use within a query in a locale-independent |
* manner. |
* |
* @param float the float value to be quoted. |
* @return string the quoted string. |
* @see DB_common::quoteSmart() |
* @since Method available since release 1.7.8. |
*/ |
function quoteFloat($float) { |
return $this->escapeSimple(str_replace(',', '.', strval(floatval($float)))); |
} |
// }}} |
// {{{ escapeSimple() |
/** |
* Escapes a string according to the current DBMS's standards |
* |
* @param string $str the string to be escaped |
* |
* @return string the escaped string |
* |
* @see DB_common::quoteSmart() |
* @since Method available since Release 1.7.0 |
*/ |
function escapeSimple($str) |
{ |
return addslashes($str); |
} |
// }}} |
// {{{ msqlRaiseError() |
/** |
* Produces a DB_Error object regarding the current problem |
* |
* @param int $errno if the error is being manually raised pass a |
* DB_ERROR* constant here. If this isn't passed |
* the error information gathered from the DBMS. |
* |
* @return object the DB_Error object |
* |
* @see DB_common::raiseError(), |
* DB_msql::errorNative(), DB_msql::errorCode() |
*/ |
function msqlRaiseError($errno = null) |
{ |
$native = $this->errorNative(); |
if ($errno === null) { |
$errno = $this->errorCode($native); |
} |
return $this->raiseError($errno, null, null, null, $native); |
} |
// }}} |
// {{{ errorNative() |
/** |
* Gets the DBMS' native error message produced by the last query |
* |
* @return string the DBMS' error message |
*/ |
function errorNative() |
{ |
return @msql_error(); |
} |
// }}} |
// {{{ errorCode() |
/** |
* Determines PEAR::DB error code from the database's text error message |
* |
* @param string $errormsg the error message returned from the database |
* |
* @return integer the error number from a DB_ERROR* constant |
*/ |
function errorCode($errormsg) |
{ |
static $error_regexps; |
// PHP 5.2+ prepends the function name to $php_errormsg, so we need |
// this hack to work around it, per bug #9599. |
$errormsg = preg_replace('/^msql[a-z_]+\(\): /', '', $errormsg); |
if (!isset($error_regexps)) { |
$error_regexps = array( |
'/^Access to database denied/i' |
=> DB_ERROR_ACCESS_VIOLATION, |
'/^Bad index name/i' |
=> DB_ERROR_ALREADY_EXISTS, |
'/^Bad order field/i' |
=> DB_ERROR_SYNTAX, |
'/^Bad type for comparison/i' |
=> DB_ERROR_SYNTAX, |
'/^Can\'t perform LIKE on/i' |
=> DB_ERROR_SYNTAX, |
'/^Can\'t use TEXT fields in LIKE comparison/i' |
=> DB_ERROR_SYNTAX, |
'/^Couldn\'t create temporary table/i' |
=> DB_ERROR_CANNOT_CREATE, |
'/^Error creating table file/i' |
=> DB_ERROR_CANNOT_CREATE, |
'/^Field .* cannot be null$/i' |
=> DB_ERROR_CONSTRAINT_NOT_NULL, |
'/^Index (field|condition) .* cannot be null$/i' |
=> DB_ERROR_SYNTAX, |
'/^Invalid date format/i' |
=> DB_ERROR_INVALID_DATE, |
'/^Invalid time format/i' |
=> DB_ERROR_INVALID, |
'/^Literal value for .* is wrong type$/i' |
=> DB_ERROR_INVALID_NUMBER, |
'/^No Database Selected/i' |
=> DB_ERROR_NODBSELECTED, |
'/^No value specified for field/i' |
=> DB_ERROR_VALUE_COUNT_ON_ROW, |
'/^Non unique value for unique index/i' |
=> DB_ERROR_CONSTRAINT, |
'/^Out of memory for temporary table/i' |
=> DB_ERROR_CANNOT_CREATE, |
'/^Permission denied/i' |
=> DB_ERROR_ACCESS_VIOLATION, |
'/^Reference to un-selected table/i' |
=> DB_ERROR_SYNTAX, |
'/^syntax error/i' |
=> DB_ERROR_SYNTAX, |
'/^Table .* exists$/i' |
=> DB_ERROR_ALREADY_EXISTS, |
'/^Unknown database/i' |
=> DB_ERROR_NOSUCHDB, |
'/^Unknown field/i' |
=> DB_ERROR_NOSUCHFIELD, |
'/^Unknown (index|system variable)/i' |
=> DB_ERROR_NOT_FOUND, |
'/^Unknown table/i' |
=> DB_ERROR_NOSUCHTABLE, |
'/^Unqualified field/i' |
=> DB_ERROR_SYNTAX, |
); |
} |
foreach ($error_regexps as $regexp => $code) { |
if (preg_match($regexp, $errormsg)) { |
return $code; |
} |
} |
return DB_ERROR; |
} |
// }}} |
// {{{ tableInfo() |
/** |
* Returns information about a table or a result set |
* |
* @param object|string $result DB_result object from a query or a |
* string containing the name of a table. |
* While this also accepts a query result |
* resource identifier, this behavior is |
* deprecated. |
* @param int $mode a valid tableInfo mode |
* |
* @return array an associative array with the information requested. |
* A DB_Error object on failure. |
* |
* @see DB_common::setOption() |
*/ |
function tableInfo($result, $mode = null) |
{ |
if (is_string($result)) { |
/* |
* Probably received a table name. |
* Create a result resource identifier. |
*/ |
$id = @msql_query("SELECT * FROM $result", |
$this->connection); |
$got_string = true; |
} elseif (isset($result->result)) { |
/* |
* Probably received a result object. |
* Extract the result resource identifier. |
*/ |
$id = $result->result; |
$got_string = false; |
} else { |
/* |
* Probably received a result resource identifier. |
* Copy it. |
* Deprecated. Here for compatibility only. |
*/ |
$id = $result; |
$got_string = false; |
} |
if (!is_resource($id)) { |
return $this->raiseError(DB_ERROR_NEED_MORE_DATA); |
} |
if ($this->options['portability'] & DB_PORTABILITY_LOWERCASE) { |
$case_func = 'strtolower'; |
} else { |
$case_func = 'strval'; |
} |
$count = @msql_num_fields($id); |
$res = array(); |
if ($mode) { |
$res['num_fields'] = $count; |
} |
for ($i = 0; $i < $count; $i++) { |
$tmp = @msql_fetch_field($id); |
$flags = ''; |
if ($tmp->not_null) { |
$flags .= 'not_null '; |
} |
if ($tmp->unique) { |
$flags .= 'unique_key '; |
} |
$flags = trim($flags); |
$res[$i] = array( |
'table' => $case_func($tmp->table), |
'name' => $case_func($tmp->name), |
'type' => $tmp->type, |
'len' => msql_field_len($id, $i), |
'flags' => $flags, |
); |
if ($mode & DB_TABLEINFO_ORDER) { |
$res['order'][$res[$i]['name']] = $i; |
} |
if ($mode & DB_TABLEINFO_ORDERTABLE) { |
$res['ordertable'][$res[$i]['table']][$res[$i]['name']] = $i; |
} |
} |
// free the result only if we were called on a table |
if ($got_string) { |
@msql_free_result($id); |
} |
return $res; |
} |
// }}} |
// {{{ getSpecialQuery() |
/** |
* Obtain a list of a given type of objects |
* |
* @param string $type the kind of objects you want to retrieve |
* |
* @return array the array containing the list of objects requested |
* |
* @access protected |
* @see DB_common::getListOf() |
*/ |
function getSpecialQuery($type) |
{ |
switch ($type) { |
case 'databases': |
$id = @msql_list_dbs($this->connection); |
break; |
case 'tables': |
$id = @msql_list_tables($this->dsn['database'], |
$this->connection); |
break; |
default: |
return null; |
} |
if (!$id) { |
return $this->msqlRaiseError(); |
} |
$out = array(); |
while ($row = @msql_fetch_row($id)) { |
$out[] = $row[0]; |
} |
return $out; |
} |
// }}} |
} |
/* |
* Local variables: |
* tab-width: 4 |
* c-basic-offset: 4 |
* End: |
*/ |
?> |
/branches/v1.3-critias/bibliotheque/pear/DB/dbase.php |
---|
New file |
0,0 → 1,510 |
<?php |
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */ |
/** |
* The PEAR DB driver for PHP's dbase extension |
* for interacting with dBase databases |
* |
* PHP version 5 |
* |
* LICENSE: This source file is subject to version 3.0 of the PHP license |
* that is available through the world-wide-web at the following URI: |
* http://www.php.net/license/3_0.txt. If you did not receive a copy of |
* the PHP License and are unable to obtain it through the web, please |
* send a note to license@php.net so we can mail you a copy immediately. |
* |
* @category Database |
* @package DB |
* @author Tomas V.V. Cox <cox@idecnet.com> |
* @author Daniel Convissor <danielc@php.net> |
* @copyright 1997-2007 The PHP Group |
* @license http://www.php.net/license/3_0.txt PHP License 3.0 |
* @version CVS: $Id$ |
* @link http://pear.php.net/package/DB |
*/ |
/** |
* Obtain the DB_common class so it can be extended from |
*/ |
require_once 'DB/common.php'; |
/** |
* The methods PEAR DB uses to interact with PHP's dbase extension |
* for interacting with dBase databases |
* |
* These methods overload the ones declared in DB_common. |
* |
* @category Database |
* @package DB |
* @author Tomas V.V. Cox <cox@idecnet.com> |
* @author Daniel Convissor <danielc@php.net> |
* @copyright 1997-2007 The PHP Group |
* @license http://www.php.net/license/3_0.txt PHP License 3.0 |
* @version Release: 1.9.2 |
* @link http://pear.php.net/package/DB |
*/ |
class DB_dbase extends DB_common |
{ |
// {{{ properties |
/** |
* The DB driver type (mysql, oci8, odbc, etc.) |
* @var string |
*/ |
var $phptype = 'dbase'; |
/** |
* The database syntax variant to be used (db2, access, etc.), if any |
* @var string |
*/ |
var $dbsyntax = 'dbase'; |
/** |
* The capabilities of this DB implementation |
* |
* The 'new_link' element contains the PHP version that first provided |
* new_link support for this DBMS. Contains false if it's unsupported. |
* |
* Meaning of the 'limit' element: |
* + 'emulate' = emulate with fetch row by number |
* + 'alter' = alter the query |
* + false = skip rows |
* |
* @var array |
*/ |
var $features = array( |
'limit' => false, |
'new_link' => false, |
'numrows' => true, |
'pconnect' => false, |
'prepare' => false, |
'ssl' => false, |
'transactions' => false, |
); |
/** |
* A mapping of native error codes to DB error codes |
* @var array |
*/ |
var $errorcode_map = array( |
); |
/** |
* The raw database connection created by PHP |
* @var resource |
*/ |
var $connection; |
/** |
* The DSN information for connecting to a database |
* @var array |
*/ |
var $dsn = array(); |
/** |
* A means of emulating result resources |
* @var array |
*/ |
var $res_row = array(); |
/** |
* The quantity of results so far |
* |
* For emulating result resources. |
* |
* @var integer |
*/ |
var $result = 0; |
/** |
* Maps dbase data type id's to human readable strings |
* |
* The human readable values are based on the output of PHP's |
* dbase_get_header_info() function. |
* |
* @var array |
* @since Property available since Release 1.7.0 |
*/ |
var $types = array( |
'C' => 'character', |
'D' => 'date', |
'L' => 'boolean', |
'M' => 'memo', |
'N' => 'number', |
); |
// }}} |
// {{{ constructor |
/** |
* This constructor calls <kbd>parent::__construct()</kbd> |
* |
* @return void |
*/ |
function __construct() |
{ |
parent::__construct(); |
} |
// }}} |
// {{{ connect() |
/** |
* Connect to the database and create it if it doesn't exist |
* |
* Don't call this method directly. Use DB::connect() instead. |
* |
* PEAR DB's dbase driver supports the following extra DSN options: |
* + mode An integer specifying the read/write mode to use |
* (0 = read only, 1 = write only, 2 = read/write). |
* Available since PEAR DB 1.7.0. |
* + fields An array of arrays that PHP's dbase_create() function needs |
* to create a new database. This information is used if the |
* dBase file specified in the "database" segment of the DSN |
* does not exist. For more info, see the PHP manual's |
* {@link http://php.net/dbase_create dbase_create()} page. |
* Available since PEAR DB 1.7.0. |
* |
* Example of how to connect and establish a new dBase file if necessary: |
* <code> |
* require_once 'DB.php'; |
* |
* $dsn = array( |
* 'phptype' => 'dbase', |
* 'database' => '/path/and/name/of/dbase/file', |
* 'mode' => 2, |
* 'fields' => array( |
* array('a', 'N', 5, 0), |
* array('b', 'C', 40), |
* array('c', 'C', 255), |
* array('d', 'C', 20), |
* ), |
* ); |
* $options = array( |
* 'debug' => 2, |
* 'portability' => DB_PORTABILITY_ALL, |
* ); |
* |
* $db = DB::connect($dsn, $options); |
* if (PEAR::isError($db)) { |
* die($db->getMessage()); |
* } |
* </code> |
* |
* @param array $dsn the data source name |
* @param bool $persistent should the connection be persistent? |
* |
* @return int DB_OK on success. A DB_Error object on failure. |
*/ |
function connect($dsn, $persistent = false) |
{ |
if (!PEAR::loadExtension('dbase')) { |
return $this->raiseError(DB_ERROR_EXTENSION_NOT_FOUND); |
} |
$this->dsn = $dsn; |
if ($dsn['dbsyntax']) { |
$this->dbsyntax = $dsn['dbsyntax']; |
} |
/* |
* Turn track_errors on for entire script since $php_errormsg |
* is the only way to find errors from the dbase extension. |
*/ |
@ini_set('track_errors', 1); |
$php_errormsg = ''; |
if (!file_exists($dsn['database'])) { |
$this->dsn['mode'] = 2; |
if (empty($dsn['fields']) || !is_array($dsn['fields'])) { |
return $this->raiseError(DB_ERROR_CONNECT_FAILED, |
null, null, null, |
'the dbase file does not exist and ' |
. 'it could not be created because ' |
. 'the "fields" element of the DSN ' |
. 'is not properly set'); |
} |
$this->connection = @dbase_create($dsn['database'], |
$dsn['fields']); |
if (!$this->connection) { |
return $this->raiseError(DB_ERROR_CONNECT_FAILED, |
null, null, null, |
'the dbase file does not exist and ' |
. 'the attempt to create it failed: ' |
. $php_errormsg); |
} |
} else { |
if (!isset($this->dsn['mode'])) { |
$this->dsn['mode'] = 0; |
} |
$this->connection = @dbase_open($dsn['database'], |
$this->dsn['mode']); |
if (!$this->connection) { |
return $this->raiseError(DB_ERROR_CONNECT_FAILED, |
null, null, null, |
$php_errormsg); |
} |
} |
return DB_OK; |
} |
// }}} |
// {{{ disconnect() |
/** |
* Disconnects from the database server |
* |
* @return bool TRUE on success, FALSE on failure |
*/ |
function disconnect() |
{ |
$ret = @dbase_close($this->connection); |
$this->connection = null; |
return $ret; |
} |
// }}} |
// {{{ &query() |
function &query($query = null) |
{ |
// emulate result resources |
$this->res_row[(int)$this->result] = 0; |
$tmp = new DB_result($this, $this->result++); |
return $tmp; |
} |
// }}} |
// {{{ fetchInto() |
/** |
* Places a row from the result set into the given array |
* |
* Formating of the array and the data therein are configurable. |
* See DB_result::fetchInto() for more information. |
* |
* This method is not meant to be called directly. Use |
* DB_result::fetchInto() instead. It can't be declared "protected" |
* because DB_result is a separate object. |
* |
* @param resource $result the query result resource |
* @param array $arr the referenced array to put the data in |
* @param int $fetchmode how the resulting array should be indexed |
* @param int $rownum the row number to fetch (0 = first row) |
* |
* @return mixed DB_OK on success, NULL when the end of a result set is |
* reached or on failure |
* |
* @see DB_result::fetchInto() |
*/ |
function fetchInto($result, &$arr, $fetchmode, $rownum = null) |
{ |
if ($rownum === null) { |
$rownum = $this->res_row[(int)$result]++; |
} |
if ($fetchmode & DB_FETCHMODE_ASSOC) { |
$arr = @dbase_get_record_with_names($this->connection, $rownum); |
if ($this->options['portability'] & DB_PORTABILITY_LOWERCASE && $arr) { |
$arr = array_change_key_case($arr, CASE_LOWER); |
} |
} else { |
$arr = @dbase_get_record($this->connection, $rownum); |
} |
if (!$arr) { |
return null; |
} |
if ($this->options['portability'] & DB_PORTABILITY_RTRIM) { |
$this->_rtrimArrayValues($arr); |
} |
if ($this->options['portability'] & DB_PORTABILITY_NULL_TO_EMPTY) { |
$this->_convertNullArrayValuesToEmpty($arr); |
} |
return DB_OK; |
} |
// }}} |
// {{{ freeResult() |
/** |
* Deletes the result set and frees the memory occupied by the result set. |
* |
* This method is a no-op for dbase, as there aren't result resources in |
* the same sense as most other database backends. |
* |
* @param resource $result PHP's query result resource |
* |
* @return bool TRUE on success, FALSE if $result is invalid |
* |
* @see DB_result::free() |
*/ |
function freeResult($result) |
{ |
return true; |
} |
// }}} |
// {{{ numCols() |
/** |
* Gets the number of columns in a result set |
* |
* This method is not meant to be called directly. Use |
* DB_result::numCols() instead. It can't be declared "protected" |
* because DB_result is a separate object. |
* |
* @param resource $result PHP's query result resource |
* |
* @return int the number of columns. A DB_Error object on failure. |
* |
* @see DB_result::numCols() |
*/ |
function numCols($foo) |
{ |
return @dbase_numfields($this->connection); |
} |
// }}} |
// {{{ numRows() |
/** |
* Gets the number of rows in a result set |
* |
* This method is not meant to be called directly. Use |
* DB_result::numRows() instead. It can't be declared "protected" |
* because DB_result is a separate object. |
* |
* @param resource $result PHP's query result resource |
* |
* @return int the number of rows. A DB_Error object on failure. |
* |
* @see DB_result::numRows() |
*/ |
function numRows($foo) |
{ |
return @dbase_numrecords($this->connection); |
} |
// }}} |
// {{{ quoteBoolean() |
/** |
* Formats a boolean value for use within a query in a locale-independent |
* manner. |
* |
* @param boolean the boolean value to be quoted. |
* @return string the quoted string. |
* @see DB_common::quoteSmart() |
* @since Method available since release 1.7.8. |
*/ |
function quoteBoolean($boolean) { |
return $boolean ? 'T' : 'F'; |
} |
// }}} |
// {{{ tableInfo() |
/** |
* Returns information about the current database |
* |
* @param mixed $result THIS IS UNUSED IN DBASE. The current database |
* is examined regardless of what is provided here. |
* @param int $mode a valid tableInfo mode |
* |
* @return array an associative array with the information requested. |
* A DB_Error object on failure. |
* |
* @see DB_common::tableInfo() |
* @since Method available since Release 1.7.0 |
*/ |
function tableInfo($result = null, $mode = null) |
{ |
if (function_exists('dbase_get_header_info')) { |
$id = @dbase_get_header_info($this->connection); |
if (!$id && $php_errormsg) { |
return $this->raiseError(DB_ERROR, |
null, null, null, |
$php_errormsg); |
} |
} else { |
/* |
* This segment for PHP 4 is loosely based on code by |
* Hadi Rusiah <deegos@yahoo.com> in the comments on |
* the dBase reference page in the PHP manual. |
*/ |
$db = @fopen($this->dsn['database'], 'r'); |
if (!$db) { |
return $this->raiseError(DB_ERROR_CONNECT_FAILED, |
null, null, null, |
$php_errormsg); |
} |
$id = array(); |
$i = 0; |
$line = fread($db, 32); |
while (!feof($db)) { |
$line = fread($db, 32); |
if (substr($line, 0, 1) == chr(13)) { |
break; |
} else { |
$pos = strpos(substr($line, 0, 10), chr(0)); |
$pos = ($pos == 0 ? 10 : $pos); |
$id[$i] = array( |
'name' => substr($line, 0, $pos), |
'type' => $this->types[substr($line, 11, 1)], |
'length' => ord(substr($line, 16, 1)), |
'precision' => ord(substr($line, 17, 1)), |
); |
} |
$i++; |
} |
fclose($db); |
} |
if ($this->options['portability'] & DB_PORTABILITY_LOWERCASE) { |
$case_func = 'strtolower'; |
} else { |
$case_func = 'strval'; |
} |
$res = array(); |
$count = count($id); |
if ($mode) { |
$res['num_fields'] = $count; |
} |
for ($i = 0; $i < $count; $i++) { |
$res[$i] = array( |
'table' => $this->dsn['database'], |
'name' => $case_func($id[$i]['name']), |
'type' => $id[$i]['type'], |
'len' => $id[$i]['length'], |
'flags' => '' |
); |
if ($mode & DB_TABLEINFO_ORDER) { |
$res['order'][$res[$i]['name']] = $i; |
} |
if ($mode & DB_TABLEINFO_ORDERTABLE) { |
$res['ordertable'][$res[$i]['table']][$res[$i]['name']] = $i; |
} |
} |
return $res; |
} |
// }}} |
} |
/* |
* Local variables: |
* tab-width: 4 |
* c-basic-offset: 4 |
* End: |
*/ |
?> |
/branches/v1.3-critias/bibliotheque/pear/DB/mysqli.php |
---|
New file |
0,0 → 1,1100 |
<?php |
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */ |
/** |
* The PEAR DB driver for PHP's mysqli extension |
* for interacting with MySQL databases |
* |
* PHP version 5 |
* |
* LICENSE: This source file is subject to version 3.0 of the PHP license |
* that is available through the world-wide-web at the following URI: |
* http://www.php.net/license/3_0.txt. If you did not receive a copy of |
* the PHP License and are unable to obtain it through the web, please |
* send a note to license@php.net so we can mail you a copy immediately. |
* |
* @category Database |
* @package DB |
* @author Daniel Convissor <danielc@php.net> |
* @copyright 1997-2007 The PHP Group |
* @license http://www.php.net/license/3_0.txt PHP License 3.0 |
* @version CVS: $Id$ |
* @link http://pear.php.net/package/DB |
*/ |
/** |
* Obtain the DB_common class so it can be extended from |
*/ |
require_once 'DB/common.php'; |
/** |
* The methods PEAR DB uses to interact with PHP's mysqli extension |
* for interacting with MySQL databases |
* |
* This is for MySQL versions 4.1 and above. Requires PHP 5. |
* |
* Note that persistent connections no longer exist. |
* |
* These methods overload the ones declared in DB_common. |
* |
* @category Database |
* @package DB |
* @author Daniel Convissor <danielc@php.net> |
* @copyright 1997-2007 The PHP Group |
* @license http://www.php.net/license/3_0.txt PHP License 3.0 |
* @version Release: 1.9.2 |
* @link http://pear.php.net/package/DB |
* @since Class functional since Release 1.6.3 |
*/ |
class DB_mysqli extends DB_common |
{ |
// {{{ properties |
/** |
* The DB driver type (mysql, oci8, odbc, etc.) |
* @var string |
*/ |
var $phptype = 'mysqli'; |
/** |
* The database syntax variant to be used (db2, access, etc.), if any |
* @var string |
*/ |
var $dbsyntax = 'mysqli'; |
/** |
* The capabilities of this DB implementation |
* |
* The 'new_link' element contains the PHP version that first provided |
* new_link support for this DBMS. Contains false if it's unsupported. |
* |
* Meaning of the 'limit' element: |
* + 'emulate' = emulate with fetch row by number |
* + 'alter' = alter the query |
* + false = skip rows |
* |
* @var array |
*/ |
var $features = array( |
'limit' => 'alter', |
'new_link' => false, |
'numrows' => true, |
'pconnect' => false, |
'prepare' => false, |
'ssl' => true, |
'transactions' => true, |
); |
/** |
* A mapping of native error codes to DB error codes |
* @var array |
*/ |
var $errorcode_map = array( |
1004 => DB_ERROR_CANNOT_CREATE, |
1005 => DB_ERROR_CANNOT_CREATE, |
1006 => DB_ERROR_CANNOT_CREATE, |
1007 => DB_ERROR_ALREADY_EXISTS, |
1008 => DB_ERROR_CANNOT_DROP, |
1022 => DB_ERROR_ALREADY_EXISTS, |
1044 => DB_ERROR_ACCESS_VIOLATION, |
1046 => DB_ERROR_NODBSELECTED, |
1048 => DB_ERROR_CONSTRAINT, |
1049 => DB_ERROR_NOSUCHDB, |
1050 => DB_ERROR_ALREADY_EXISTS, |
1051 => DB_ERROR_NOSUCHTABLE, |
1054 => DB_ERROR_NOSUCHFIELD, |
1061 => DB_ERROR_ALREADY_EXISTS, |
1062 => DB_ERROR_ALREADY_EXISTS, |
1064 => DB_ERROR_SYNTAX, |
1091 => DB_ERROR_NOT_FOUND, |
1100 => DB_ERROR_NOT_LOCKED, |
1136 => DB_ERROR_VALUE_COUNT_ON_ROW, |
1142 => DB_ERROR_ACCESS_VIOLATION, |
1146 => DB_ERROR_NOSUCHTABLE, |
1216 => DB_ERROR_CONSTRAINT, |
1217 => DB_ERROR_CONSTRAINT, |
1356 => DB_ERROR_DIVZERO, |
1451 => DB_ERROR_CONSTRAINT, |
1452 => DB_ERROR_CONSTRAINT, |
); |
/** |
* The raw database connection created by PHP |
* @var resource |
*/ |
var $connection; |
/** |
* The DSN information for connecting to a database |
* @var array |
*/ |
var $dsn = array(); |
/** |
* Should data manipulation queries be committed automatically? |
* @var bool |
* @access private |
*/ |
var $autocommit = true; |
/** |
* The quantity of transactions begun |
* |
* {@internal While this is private, it can't actually be designated |
* private in PHP 5 because it is directly accessed in the test suite.}} |
* |
* @var integer |
* @access private |
*/ |
var $transaction_opcount = 0; |
/** |
* The database specified in the DSN |
* |
* It's a fix to allow calls to different databases in the same script. |
* |
* @var string |
* @access private |
*/ |
var $_db = ''; |
/** |
* Array for converting MYSQLI_*_FLAG constants to text values |
* @var array |
* @access public |
* @since Property available since Release 1.6.5 |
*/ |
var $mysqli_flags = array( |
MYSQLI_NOT_NULL_FLAG => 'not_null', |
MYSQLI_PRI_KEY_FLAG => 'primary_key', |
MYSQLI_UNIQUE_KEY_FLAG => 'unique_key', |
MYSQLI_MULTIPLE_KEY_FLAG => 'multiple_key', |
MYSQLI_BLOB_FLAG => 'blob', |
MYSQLI_UNSIGNED_FLAG => 'unsigned', |
MYSQLI_ZEROFILL_FLAG => 'zerofill', |
MYSQLI_AUTO_INCREMENT_FLAG => 'auto_increment', |
MYSQLI_TIMESTAMP_FLAG => 'timestamp', |
MYSQLI_SET_FLAG => 'set', |
// MYSQLI_NUM_FLAG => 'numeric', // unnecessary |
// MYSQLI_PART_KEY_FLAG => 'multiple_key', // duplicatvie |
MYSQLI_GROUP_FLAG => 'group_by' |
); |
/** |
* Array for converting MYSQLI_TYPE_* constants to text values |
* @var array |
* @access public |
* @since Property available since Release 1.6.5 |
*/ |
var $mysqli_types = array( |
MYSQLI_TYPE_DECIMAL => 'decimal', |
MYSQLI_TYPE_TINY => 'tinyint', |
MYSQLI_TYPE_SHORT => 'int', |
MYSQLI_TYPE_LONG => 'int', |
MYSQLI_TYPE_FLOAT => 'float', |
MYSQLI_TYPE_DOUBLE => 'double', |
// MYSQLI_TYPE_NULL => 'DEFAULT NULL', // let flags handle it |
MYSQLI_TYPE_TIMESTAMP => 'timestamp', |
MYSQLI_TYPE_LONGLONG => 'bigint', |
MYSQLI_TYPE_INT24 => 'mediumint', |
MYSQLI_TYPE_DATE => 'date', |
MYSQLI_TYPE_TIME => 'time', |
MYSQLI_TYPE_DATETIME => 'datetime', |
MYSQLI_TYPE_YEAR => 'year', |
MYSQLI_TYPE_NEWDATE => 'date', |
MYSQLI_TYPE_ENUM => 'enum', |
MYSQLI_TYPE_SET => 'set', |
MYSQLI_TYPE_TINY_BLOB => 'tinyblob', |
MYSQLI_TYPE_MEDIUM_BLOB => 'mediumblob', |
MYSQLI_TYPE_LONG_BLOB => 'longblob', |
MYSQLI_TYPE_BLOB => 'blob', |
MYSQLI_TYPE_VAR_STRING => 'varchar', |
MYSQLI_TYPE_STRING => 'char', |
MYSQLI_TYPE_GEOMETRY => 'geometry', |
/* These constants are conditionally compiled in ext/mysqli, so we'll |
* define them by number rather than constant. */ |
16 => 'bit', |
246 => 'decimal', |
); |
// }}} |
// {{{ constructor |
/** |
* This constructor calls <kbd>parent::__construct()</kbd> |
* |
* @return void |
*/ |
function __construct() |
{ |
parent::__construct(); |
} |
// }}} |
// {{{ connect() |
/** |
* Connect to the database server, log in and open the database |
* |
* Don't call this method directly. Use DB::connect() instead. |
* |
* PEAR DB's mysqli driver supports the following extra DSN options: |
* + When the 'ssl' $option passed to DB::connect() is true: |
* + key The path to the key file. |
* + cert The path to the certificate file. |
* + ca The path to the certificate authority file. |
* + capath The path to a directory that contains trusted SSL |
* CA certificates in pem format. |
* + cipher The list of allowable ciphers for SSL encryption. |
* |
* Example of how to connect using SSL: |
* <code> |
* require_once 'DB.php'; |
* |
* $dsn = array( |
* 'phptype' => 'mysqli', |
* 'username' => 'someuser', |
* 'password' => 'apasswd', |
* 'hostspec' => 'localhost', |
* 'database' => 'thedb', |
* 'key' => 'client-key.pem', |
* 'cert' => 'client-cert.pem', |
* 'ca' => 'cacert.pem', |
* 'capath' => '/path/to/ca/dir', |
* 'cipher' => 'AES', |
* ); |
* |
* $options = array( |
* 'ssl' => true, |
* ); |
* |
* $db = DB::connect($dsn, $options); |
* if (PEAR::isError($db)) { |
* die($db->getMessage()); |
* } |
* </code> |
* |
* @param array $dsn the data source name |
* @param bool $persistent should the connection be persistent? |
* |
* @return int DB_OK on success. A DB_Error object on failure. |
*/ |
function connect($dsn, $persistent = false) |
{ |
if (!PEAR::loadExtension('mysqli')) { |
return $this->raiseError(DB_ERROR_EXTENSION_NOT_FOUND); |
} |
$this->dsn = $dsn; |
if ($dsn['dbsyntax']) { |
$this->dbsyntax = $dsn['dbsyntax']; |
} |
$ini = ini_get('track_errors'); |
@ini_set('track_errors', 1); |
$php_errormsg = ''; |
if (((int) $this->getOption('ssl')) === 1) { |
$init = mysqli_init(); |
mysqli_ssl_set( |
$init, |
empty($dsn['key']) ? null : $dsn['key'], |
empty($dsn['cert']) ? null : $dsn['cert'], |
empty($dsn['ca']) ? null : $dsn['ca'], |
empty($dsn['capath']) ? null : $dsn['capath'], |
empty($dsn['cipher']) ? null : $dsn['cipher'] |
); |
if ($this->connection = @mysqli_real_connect( |
$init, |
$dsn['hostspec'], |
$dsn['username'], |
$dsn['password'], |
$dsn['database'], |
$dsn['port'], |
$dsn['socket'])) |
{ |
$this->connection = $init; |
} |
} else { |
$this->connection = @mysqli_connect( |
$dsn['hostspec'], |
$dsn['username'], |
$dsn['password'], |
$dsn['database'], |
$dsn['port'], |
$dsn['socket'] |
); |
} |
@ini_set('track_errors', $ini); |
if (!$this->connection) { |
if (($err = @mysqli_connect_error()) != '') { |
return $this->raiseError(DB_ERROR_CONNECT_FAILED, |
null, null, null, |
$err); |
} else { |
return $this->raiseError(DB_ERROR_CONNECT_FAILED, |
null, null, null, |
$php_errormsg); |
} |
} |
if ($dsn['database']) { |
$this->_db = $dsn['database']; |
} |
return DB_OK; |
} |
// }}} |
// {{{ disconnect() |
/** |
* Disconnects from the database server |
* |
* @return bool TRUE on success, FALSE on failure |
*/ |
function disconnect() |
{ |
$ret = @mysqli_close($this->connection); |
$this->connection = null; |
return $ret; |
} |
// }}} |
// {{{ simpleQuery() |
/** |
* Sends a query to the database server |
* |
* @param string the SQL query string |
* |
* @return mixed + a PHP result resrouce for successful SELECT queries |
* + the DB_OK constant for other successful queries |
* + a DB_Error object on failure |
*/ |
function simpleQuery($query) |
{ |
$ismanip = $this->_checkManip($query); |
$this->last_query = $query; |
$query = $this->modifyQuery($query); |
if ($this->_db) { |
if (!@mysqli_select_db($this->connection, $this->_db)) { |
return $this->mysqliRaiseError(DB_ERROR_NODBSELECTED); |
} |
} |
if (!$this->autocommit && $ismanip) { |
if ($this->transaction_opcount == 0) { |
$result = @mysqli_query($this->connection, 'SET AUTOCOMMIT=0'); |
$result = @mysqli_query($this->connection, 'BEGIN'); |
if (!$result) { |
return $this->mysqliRaiseError(); |
} |
} |
$this->transaction_opcount++; |
} |
$result = @mysqli_query($this->connection, $query); |
if (!$result) { |
return $this->mysqliRaiseError(); |
} |
if (is_object($result)) { |
return $result; |
} |
return DB_OK; |
} |
// }}} |
// {{{ nextResult() |
/** |
* Move the internal mysql result pointer to the next available result. |
* |
* This method has not been implemented yet. |
* |
* @param resource $result a valid sql result resource |
* @return false |
* @access public |
*/ |
function nextResult($result) |
{ |
return false; |
} |
// }}} |
// {{{ fetchInto() |
/** |
* Places a row from the result set into the given array |
* |
* Formating of the array and the data therein are configurable. |
* See DB_result::fetchInto() for more information. |
* |
* This method is not meant to be called directly. Use |
* DB_result::fetchInto() instead. It can't be declared "protected" |
* because DB_result is a separate object. |
* |
* @param resource $result the query result resource |
* @param array $arr the referenced array to put the data in |
* @param int $fetchmode how the resulting array should be indexed |
* @param int $rownum the row number to fetch (0 = first row) |
* |
* @return mixed DB_OK on success, NULL when the end of a result set is |
* reached or on failure |
* |
* @see DB_result::fetchInto() |
*/ |
function fetchInto($result, &$arr, $fetchmode, $rownum = null) |
{ |
if ($rownum !== null) { |
if (!@mysqli_data_seek($result, $rownum)) { |
return null; |
} |
} |
if ($fetchmode & DB_FETCHMODE_ASSOC) { |
$arr = @mysqli_fetch_array($result, MYSQLI_ASSOC); |
if ($this->options['portability'] & DB_PORTABILITY_LOWERCASE && $arr) { |
$arr = array_change_key_case($arr, CASE_LOWER); |
} |
} else { |
$arr = @mysqli_fetch_row($result); |
} |
if (!$arr) { |
return null; |
} |
if ($this->options['portability'] & DB_PORTABILITY_RTRIM) { |
/* |
* Even though this DBMS already trims output, we do this because |
* a field might have intentional whitespace at the end that |
* gets removed by DB_PORTABILITY_RTRIM under another driver. |
*/ |
$this->_rtrimArrayValues($arr); |
} |
if ($this->options['portability'] & DB_PORTABILITY_NULL_TO_EMPTY) { |
$this->_convertNullArrayValuesToEmpty($arr); |
} |
return DB_OK; |
} |
// }}} |
// {{{ freeResult() |
/** |
* Deletes the result set and frees the memory occupied by the result set |
* |
* This method is not meant to be called directly. Use |
* DB_result::free() instead. It can't be declared "protected" |
* because DB_result is a separate object. |
* |
* @param resource $result PHP's query result resource |
* |
* @return bool TRUE on success, FALSE if $result is invalid |
* |
* @see DB_result::free() |
*/ |
function freeResult($result) |
{ |
if (! $result instanceof mysqli_result) { |
return false; |
} |
mysqli_free_result($result); |
return true; |
} |
// }}} |
// {{{ numCols() |
/** |
* Gets the number of columns in a result set |
* |
* This method is not meant to be called directly. Use |
* DB_result::numCols() instead. It can't be declared "protected" |
* because DB_result is a separate object. |
* |
* @param resource $result PHP's query result resource |
* |
* @return int the number of columns. A DB_Error object on failure. |
* |
* @see DB_result::numCols() |
*/ |
function numCols($result) |
{ |
$cols = @mysqli_num_fields($result); |
if (!$cols) { |
return $this->mysqliRaiseError(); |
} |
return $cols; |
} |
// }}} |
// {{{ numRows() |
/** |
* Gets the number of rows in a result set |
* |
* This method is not meant to be called directly. Use |
* DB_result::numRows() instead. It can't be declared "protected" |
* because DB_result is a separate object. |
* |
* @param resource $result PHP's query result resource |
* |
* @return int the number of rows. A DB_Error object on failure. |
* |
* @see DB_result::numRows() |
*/ |
function numRows($result) |
{ |
$rows = @mysqli_num_rows($result); |
if ($rows === null) { |
return $this->mysqliRaiseError(); |
} |
return $rows; |
} |
// }}} |
// {{{ autoCommit() |
/** |
* Enables or disables automatic commits |
* |
* @param bool $onoff true turns it on, false turns it off |
* |
* @return int DB_OK on success. A DB_Error object if the driver |
* doesn't support auto-committing transactions. |
*/ |
function autoCommit($onoff = false) |
{ |
// XXX if $this->transaction_opcount > 0, we should probably |
// issue a warning here. |
$this->autocommit = $onoff ? true : false; |
return DB_OK; |
} |
// }}} |
// {{{ commit() |
/** |
* Commits the current transaction |
* |
* @return int DB_OK on success. A DB_Error object on failure. |
*/ |
function commit() |
{ |
if ($this->transaction_opcount > 0) { |
if ($this->_db) { |
if (!@mysqli_select_db($this->connection, $this->_db)) { |
return $this->mysqliRaiseError(DB_ERROR_NODBSELECTED); |
} |
} |
$result = @mysqli_query($this->connection, 'COMMIT'); |
$result = @mysqli_query($this->connection, 'SET AUTOCOMMIT=1'); |
$this->transaction_opcount = 0; |
if (!$result) { |
return $this->mysqliRaiseError(); |
} |
} |
return DB_OK; |
} |
// }}} |
// {{{ rollback() |
/** |
* Reverts the current transaction |
* |
* @return int DB_OK on success. A DB_Error object on failure. |
*/ |
function rollback() |
{ |
if ($this->transaction_opcount > 0) { |
if ($this->_db) { |
if (!@mysqli_select_db($this->connection, $this->_db)) { |
return $this->mysqliRaiseError(DB_ERROR_NODBSELECTED); |
} |
} |
$result = @mysqli_query($this->connection, 'ROLLBACK'); |
$result = @mysqli_query($this->connection, 'SET AUTOCOMMIT=1'); |
$this->transaction_opcount = 0; |
if (!$result) { |
return $this->mysqliRaiseError(); |
} |
} |
return DB_OK; |
} |
// }}} |
// {{{ affectedRows() |
/** |
* Determines the number of rows affected by a data maniuplation query |
* |
* 0 is returned for queries that don't manipulate data. |
* |
* @return int the number of rows. A DB_Error object on failure. |
*/ |
function affectedRows() |
{ |
if ($this->_last_query_manip) { |
return @mysqli_affected_rows($this->connection); |
} else { |
return 0; |
} |
} |
// }}} |
// {{{ nextId() |
/** |
* Returns the next free id in a sequence |
* |
* @param string $seq_name name of the sequence |
* @param boolean $ondemand when true, the seqence is automatically |
* created if it does not exist |
* |
* @return int the next id number in the sequence. |
* A DB_Error object on failure. |
* |
* @see DB_common::nextID(), DB_common::getSequenceName(), |
* DB_mysqli::createSequence(), DB_mysqli::dropSequence() |
*/ |
function nextId($seq_name, $ondemand = true) |
{ |
$seqname = $this->getSequenceName($seq_name); |
do { |
$repeat = 0; |
$this->pushErrorHandling(PEAR_ERROR_RETURN); |
$result = $this->query('UPDATE ' . $seqname |
. ' SET id = LAST_INSERT_ID(id + 1)'); |
$this->popErrorHandling(); |
if ($result === DB_OK) { |
// COMMON CASE |
$id = @mysqli_insert_id($this->connection); |
if ($id != 0) { |
return $id; |
} |
// EMPTY SEQ TABLE |
// Sequence table must be empty for some reason, |
// so fill it and return 1 |
// Obtain a user-level lock |
$result = $this->getOne('SELECT GET_LOCK(' |
. "'${seqname}_lock', 10)"); |
if (DB::isError($result)) { |
return $this->raiseError($result); |
} |
if ($result == 0) { |
return $this->mysqliRaiseError(DB_ERROR_NOT_LOCKED); |
} |
// add the default value |
$result = $this->query('REPLACE INTO ' . $seqname |
. ' (id) VALUES (0)'); |
if (DB::isError($result)) { |
return $this->raiseError($result); |
} |
// Release the lock |
$result = $this->getOne('SELECT RELEASE_LOCK(' |
. "'${seqname}_lock')"); |
if (DB::isError($result)) { |
return $this->raiseError($result); |
} |
// We know what the result will be, so no need to try again |
return 1; |
} elseif ($ondemand && DB::isError($result) && |
$result->getCode() == DB_ERROR_NOSUCHTABLE) |
{ |
// ONDEMAND TABLE CREATION |
$result = $this->createSequence($seq_name); |
// Since createSequence initializes the ID to be 1, |
// we do not need to retrieve the ID again (or we will get 2) |
if (DB::isError($result)) { |
return $this->raiseError($result); |
} else { |
// First ID of a newly created sequence is 1 |
return 1; |
} |
} elseif (DB::isError($result) && |
$result->getCode() == DB_ERROR_ALREADY_EXISTS) |
{ |
// BACKWARDS COMPAT |
// see _BCsequence() comment |
$result = $this->_BCsequence($seqname); |
if (DB::isError($result)) { |
return $this->raiseError($result); |
} |
$repeat = 1; |
} |
} while ($repeat); |
return $this->raiseError($result); |
} |
/** |
* Creates a new sequence |
* |
* @param string $seq_name name of the new sequence |
* |
* @return int DB_OK on success. A DB_Error object on failure. |
* |
* @see DB_common::createSequence(), DB_common::getSequenceName(), |
* DB_mysqli::nextID(), DB_mysqli::dropSequence() |
*/ |
function createSequence($seq_name) |
{ |
$seqname = $this->getSequenceName($seq_name); |
$res = $this->query('CREATE TABLE ' . $seqname |
. ' (id INTEGER UNSIGNED AUTO_INCREMENT NOT NULL,' |
. ' PRIMARY KEY(id))'); |
if (DB::isError($res)) { |
return $res; |
} |
// insert yields value 1, nextId call will generate ID 2 |
return $this->query("INSERT INTO ${seqname} (id) VALUES (0)"); |
} |
// }}} |
// {{{ dropSequence() |
/** |
* Deletes a sequence |
* |
* @param string $seq_name name of the sequence to be deleted |
* |
* @return int DB_OK on success. A DB_Error object on failure. |
* |
* @see DB_common::dropSequence(), DB_common::getSequenceName(), |
* DB_mysql::nextID(), DB_mysql::createSequence() |
*/ |
function dropSequence($seq_name) |
{ |
return $this->query('DROP TABLE ' . $this->getSequenceName($seq_name)); |
} |
// }}} |
// {{{ _BCsequence() |
/** |
* Backwards compatibility with old sequence emulation implementation |
* (clean up the dupes) |
* |
* @param string $seqname the sequence name to clean up |
* |
* @return bool true on success. A DB_Error object on failure. |
* |
* @access private |
*/ |
function _BCsequence($seqname) |
{ |
// Obtain a user-level lock... this will release any previous |
// application locks, but unlike LOCK TABLES, it does not abort |
// the current transaction and is much less frequently used. |
$result = $this->getOne("SELECT GET_LOCK('${seqname}_lock',10)"); |
if (DB::isError($result)) { |
return $result; |
} |
if ($result == 0) { |
// Failed to get the lock, can't do the conversion, bail |
// with a DB_ERROR_NOT_LOCKED error |
return $this->mysqliRaiseError(DB_ERROR_NOT_LOCKED); |
} |
$highest_id = $this->getOne("SELECT MAX(id) FROM ${seqname}"); |
if (DB::isError($highest_id)) { |
return $highest_id; |
} |
// This should kill all rows except the highest |
// We should probably do something if $highest_id isn't |
// numeric, but I'm at a loss as how to handle that... |
$result = $this->query('DELETE FROM ' . $seqname |
. " WHERE id <> $highest_id"); |
if (DB::isError($result)) { |
return $result; |
} |
// If another thread has been waiting for this lock, |
// it will go thru the above procedure, but will have no |
// real effect |
$result = $this->getOne("SELECT RELEASE_LOCK('${seqname}_lock')"); |
if (DB::isError($result)) { |
return $result; |
} |
return true; |
} |
// }}} |
// {{{ quoteIdentifier() |
/** |
* Quotes a string so it can be safely used as a table or column name |
* (WARNING: using names that require this is a REALLY BAD IDEA) |
* |
* WARNING: Older versions of MySQL can't handle the backtick |
* character (<kbd>`</kbd>) in table or column names. |
* |
* @param string $str identifier name to be quoted |
* |
* @return string quoted identifier string |
* |
* @see DB_common::quoteIdentifier() |
* @since Method available since Release 1.6.0 |
*/ |
function quoteIdentifier($str) |
{ |
return '`' . str_replace('`', '``', $str) . '`'; |
} |
// }}} |
// {{{ escapeSimple() |
/** |
* Escapes a string according to the current DBMS's standards |
* |
* @param string $str the string to be escaped |
* |
* @return string the escaped string |
* |
* @see DB_common::quoteSmart() |
* @since Method available since Release 1.6.0 |
*/ |
function escapeSimple($str) |
{ |
return @mysqli_real_escape_string($this->connection, $str); |
} |
// }}} |
// {{{ modifyLimitQuery() |
/** |
* Adds LIMIT clauses to a query string according to current DBMS standards |
* |
* @param string $query the query to modify |
* @param int $from the row to start to fetching (0 = the first row) |
* @param int $count the numbers of rows to fetch |
* @param mixed $params array, string or numeric data to be used in |
* execution of the statement. Quantity of items |
* passed must match quantity of placeholders in |
* query: meaning 1 placeholder for non-array |
* parameters or 1 placeholder per array element. |
* |
* @return string the query string with LIMIT clauses added |
* |
* @access protected |
*/ |
function modifyLimitQuery($query, $from, $count, $params = array()) |
{ |
if (DB::isManip($query) || $this->_next_query_manip) { |
return $query . " LIMIT $count"; |
} else { |
return $query . " LIMIT $from, $count"; |
} |
} |
// }}} |
// {{{ mysqliRaiseError() |
/** |
* Produces a DB_Error object regarding the current problem |
* |
* @param int $errno if the error is being manually raised pass a |
* DB_ERROR* constant here. If this isn't passed |
* the error information gathered from the DBMS. |
* |
* @return object the DB_Error object |
* |
* @see DB_common::raiseError(), |
* DB_mysqli::errorNative(), DB_common::errorCode() |
*/ |
function mysqliRaiseError($errno = null) |
{ |
if ($errno === null) { |
if ($this->options['portability'] & DB_PORTABILITY_ERRORS) { |
$this->errorcode_map[1022] = DB_ERROR_CONSTRAINT; |
$this->errorcode_map[1048] = DB_ERROR_CONSTRAINT_NOT_NULL; |
$this->errorcode_map[1062] = DB_ERROR_CONSTRAINT; |
} else { |
// Doing this in case mode changes during runtime. |
$this->errorcode_map[1022] = DB_ERROR_ALREADY_EXISTS; |
$this->errorcode_map[1048] = DB_ERROR_CONSTRAINT; |
$this->errorcode_map[1062] = DB_ERROR_ALREADY_EXISTS; |
} |
$errno = $this->errorCode(mysqli_errno($this->connection)); |
} |
return $this->raiseError($errno, null, null, null, |
@mysqli_errno($this->connection) . ' ** ' . |
@mysqli_error($this->connection)); |
} |
// }}} |
// {{{ errorNative() |
/** |
* Gets the DBMS' native error code produced by the last query |
* |
* @return int the DBMS' error code |
*/ |
function errorNative() |
{ |
return @mysqli_errno($this->connection); |
} |
// }}} |
// {{{ tableInfo() |
/** |
* Returns information about a table or a result set |
* |
* @param object|string $result DB_result object from a query or a |
* string containing the name of a table. |
* While this also accepts a query result |
* resource identifier, this behavior is |
* deprecated. |
* @param int $mode a valid tableInfo mode |
* |
* @return array an associative array with the information requested. |
* A DB_Error object on failure. |
* |
* @see DB_common::setOption() |
*/ |
function tableInfo($result, $mode = null) |
{ |
if (is_string($result)) { |
// Fix for bug #11580. |
if ($this->_db) { |
if (!@mysqli_select_db($this->connection, $this->_db)) { |
return $this->mysqliRaiseError(DB_ERROR_NODBSELECTED); |
} |
} |
/* |
* Probably received a table name. |
* Create a result resource identifier. |
*/ |
$id = @mysqli_query($this->connection, |
"SELECT * FROM $result LIMIT 0"); |
$got_string = true; |
} elseif (isset($result->result)) { |
/* |
* Probably received a result object. |
* Extract the result resource identifier. |
*/ |
$id = $result->result; |
$got_string = false; |
} else { |
/* |
* Probably received a result resource identifier. |
* Copy it. |
* Deprecated. Here for compatibility only. |
*/ |
$id = $result; |
$got_string = false; |
} |
if (!is_object($id) || !is_a($id, 'mysqli_result')) { |
return $this->mysqliRaiseError(DB_ERROR_NEED_MORE_DATA); |
} |
if ($this->options['portability'] & DB_PORTABILITY_LOWERCASE) { |
$case_func = 'strtolower'; |
} else { |
$case_func = 'strval'; |
} |
$count = @mysqli_num_fields($id); |
$res = array(); |
if ($mode) { |
$res['num_fields'] = $count; |
} |
for ($i = 0; $i < $count; $i++) { |
$tmp = @mysqli_fetch_field($id); |
$flags = ''; |
foreach ($this->mysqli_flags as $const => $means) { |
if ($tmp->flags & $const) { |
$flags .= $means . ' '; |
} |
} |
if ($tmp->def) { |
$flags .= 'default_' . rawurlencode($tmp->def); |
} |
$flags = trim($flags); |
$res[$i] = array( |
'table' => $case_func($tmp->table), |
'name' => $case_func($tmp->name), |
'type' => isset($this->mysqli_types[$tmp->type]) |
? $this->mysqli_types[$tmp->type] |
: 'unknown', |
// http://bugs.php.net/?id=36579 |
// Doc Bug #36579: mysqli_fetch_field length handling |
// https://bugs.php.net/bug.php?id=62426 |
// Bug #62426: mysqli_fetch_field_direct returns incorrect |
// length on UTF8 fields |
'len' => $tmp->length, |
'flags' => $flags, |
); |
if ($mode & DB_TABLEINFO_ORDER) { |
$res['order'][$res[$i]['name']] = $i; |
} |
if ($mode & DB_TABLEINFO_ORDERTABLE) { |
$res['ordertable'][$res[$i]['table']][$res[$i]['name']] = $i; |
} |
} |
// free the result only if we were called on a table |
if ($got_string) { |
@mysqli_free_result($id); |
} |
return $res; |
} |
// }}} |
// {{{ getSpecialQuery() |
/** |
* Obtains the query string needed for listing a given type of objects |
* |
* @param string $type the kind of objects you want to retrieve |
* |
* @return string the SQL query string or null if the driver doesn't |
* support the object type requested |
* |
* @access protected |
* @see DB_common::getListOf() |
*/ |
function getSpecialQuery($type) |
{ |
switch ($type) { |
case 'tables': |
return 'SHOW TABLES'; |
case 'users': |
return 'SELECT DISTINCT User FROM mysql.user'; |
case 'databases': |
return 'SHOW DATABASES'; |
default: |
return null; |
} |
} |
// }}} |
} |
/* |
* Local variables: |
* tab-width: 4 |
* c-basic-offset: 4 |
* End: |
*/ |
?> |
/branches/v1.3-critias/bibliotheque/pear/DB/mssql.php |
---|
New file |
0,0 → 1,984 |
<?php |
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */ |
/** |
* The PEAR DB driver for PHP's mssql extension |
* for interacting with Microsoft SQL Server databases |
* |
* PHP version 5 |
* |
* LICENSE: This source file is subject to version 3.0 of the PHP license |
* that is available through the world-wide-web at the following URI: |
* http://www.php.net/license/3_0.txt. If you did not receive a copy of |
* the PHP License and are unable to obtain it through the web, please |
* send a note to license@php.net so we can mail you a copy immediately. |
* |
* @category Database |
* @package DB |
* @author Sterling Hughes <sterling@php.net> |
* @author Daniel Convissor <danielc@php.net> |
* @copyright 1997-2007 The PHP Group |
* @license http://www.php.net/license/3_0.txt PHP License 3.0 |
* @version CVS: $Id$ |
* @link http://pear.php.net/package/DB |
*/ |
/** |
* Obtain the DB_common class so it can be extended from |
*/ |
require_once 'DB/common.php'; |
/** |
* The methods PEAR DB uses to interact with PHP's mssql extension |
* for interacting with Microsoft SQL Server databases |
* |
* These methods overload the ones declared in DB_common. |
* |
* DB's mssql driver is only for Microsfoft SQL Server databases. |
* |
* If you're connecting to a Sybase database, you MUST specify "sybase" |
* as the "phptype" in the DSN. |
* |
* This class only works correctly if you have compiled PHP using |
* --with-mssql=[dir_to_FreeTDS]. |
* |
* @category Database |
* @package DB |
* @author Sterling Hughes <sterling@php.net> |
* @author Daniel Convissor <danielc@php.net> |
* @copyright 1997-2007 The PHP Group |
* @license http://www.php.net/license/3_0.txt PHP License 3.0 |
* @version Release: 1.9.2 |
* @link http://pear.php.net/package/DB |
*/ |
class DB_mssql extends DB_common |
{ |
// {{{ properties |
/** |
* The DB driver type (mysql, oci8, odbc, etc.) |
* @var string |
*/ |
var $phptype = 'mssql'; |
/** |
* The database syntax variant to be used (db2, access, etc.), if any |
* @var string |
*/ |
var $dbsyntax = 'mssql'; |
/** |
* The capabilities of this DB implementation |
* |
* The 'new_link' element contains the PHP version that first provided |
* new_link support for this DBMS. Contains false if it's unsupported. |
* |
* Meaning of the 'limit' element: |
* + 'emulate' = emulate with fetch row by number |
* + 'alter' = alter the query |
* + false = skip rows |
* |
* @var array |
*/ |
var $features = array( |
'limit' => 'emulate', |
'new_link' => false, |
'numrows' => true, |
'pconnect' => true, |
'prepare' => false, |
'ssl' => false, |
'transactions' => true, |
); |
/** |
* A mapping of native error codes to DB error codes |
* @var array |
*/ |
// XXX Add here error codes ie: 'S100E' => DB_ERROR_SYNTAX |
var $errorcode_map = array( |
102 => DB_ERROR_SYNTAX, |
110 => DB_ERROR_VALUE_COUNT_ON_ROW, |
155 => DB_ERROR_NOSUCHFIELD, |
156 => DB_ERROR_SYNTAX, |
170 => DB_ERROR_SYNTAX, |
207 => DB_ERROR_NOSUCHFIELD, |
208 => DB_ERROR_NOSUCHTABLE, |
245 => DB_ERROR_INVALID_NUMBER, |
319 => DB_ERROR_SYNTAX, |
321 => DB_ERROR_NOSUCHFIELD, |
325 => DB_ERROR_SYNTAX, |
336 => DB_ERROR_SYNTAX, |
515 => DB_ERROR_CONSTRAINT_NOT_NULL, |
547 => DB_ERROR_CONSTRAINT, |
1018 => DB_ERROR_SYNTAX, |
1035 => DB_ERROR_SYNTAX, |
1913 => DB_ERROR_ALREADY_EXISTS, |
2209 => DB_ERROR_SYNTAX, |
2223 => DB_ERROR_SYNTAX, |
2248 => DB_ERROR_SYNTAX, |
2256 => DB_ERROR_SYNTAX, |
2257 => DB_ERROR_SYNTAX, |
2627 => DB_ERROR_CONSTRAINT, |
2714 => DB_ERROR_ALREADY_EXISTS, |
3607 => DB_ERROR_DIVZERO, |
3701 => DB_ERROR_NOSUCHTABLE, |
7630 => DB_ERROR_SYNTAX, |
8134 => DB_ERROR_DIVZERO, |
9303 => DB_ERROR_SYNTAX, |
9317 => DB_ERROR_SYNTAX, |
9318 => DB_ERROR_SYNTAX, |
9331 => DB_ERROR_SYNTAX, |
9332 => DB_ERROR_SYNTAX, |
15253 => DB_ERROR_SYNTAX, |
); |
/** |
* The raw database connection created by PHP |
* @var resource |
*/ |
var $connection; |
/** |
* The DSN information for connecting to a database |
* @var array |
*/ |
var $dsn = array(); |
/** |
* Should data manipulation queries be committed automatically? |
* @var bool |
* @access private |
*/ |
var $autocommit = true; |
/** |
* The quantity of transactions begun |
* |
* {@internal While this is private, it can't actually be designated |
* private in PHP 5 because it is directly accessed in the test suite.}} |
* |
* @var integer |
* @access private |
*/ |
var $transaction_opcount = 0; |
/** |
* The database specified in the DSN |
* |
* It's a fix to allow calls to different databases in the same script. |
* |
* @var string |
* @access private |
*/ |
var $_db = null; |
// }}} |
// {{{ constructor |
/** |
* This constructor calls <kbd>parent::__construct()</kbd> |
* |
* @return void |
*/ |
function __construct() |
{ |
parent::__construct(); |
} |
// }}} |
// {{{ connect() |
/** |
* Connect to the database server, log in and open the database |
* |
* Don't call this method directly. Use DB::connect() instead. |
* |
* @param array $dsn the data source name |
* @param bool $persistent should the connection be persistent? |
* |
* @return int DB_OK on success. A DB_Error object on failure. |
*/ |
function connect($dsn, $persistent = false) |
{ |
if (!PEAR::loadExtension('mssql') && !PEAR::loadExtension('sybase') |
&& !PEAR::loadExtension('sybase_ct')) |
{ |
return $this->raiseError(DB_ERROR_EXTENSION_NOT_FOUND); |
} |
$this->dsn = $dsn; |
if ($dsn['dbsyntax']) { |
$this->dbsyntax = $dsn['dbsyntax']; |
} |
$params = array( |
$dsn['hostspec'] ? $dsn['hostspec'] : 'localhost', |
$dsn['username'] ? $dsn['username'] : null, |
$dsn['password'] ? $dsn['password'] : null, |
); |
if ($dsn['port']) { |
$params[0] .= ((substr(PHP_OS, 0, 3) == 'WIN') ? ',' : ':') |
. $dsn['port']; |
} |
$connect_function = $persistent ? 'mssql_pconnect' : 'mssql_connect'; |
$this->connection = @call_user_func_array($connect_function, $params); |
if (!$this->connection) { |
return $this->raiseError(DB_ERROR_CONNECT_FAILED, |
null, null, null, |
@mssql_get_last_message()); |
} |
if ($dsn['database']) { |
if (!@mssql_select_db($dsn['database'], $this->connection)) { |
return $this->raiseError(DB_ERROR_NODBSELECTED, |
null, null, null, |
@mssql_get_last_message()); |
} |
$this->_db = $dsn['database']; |
} |
return DB_OK; |
} |
// }}} |
// {{{ disconnect() |
/** |
* Disconnects from the database server |
* |
* @return bool TRUE on success, FALSE on failure |
*/ |
function disconnect() |
{ |
$ret = @mssql_close($this->connection); |
$this->connection = null; |
return $ret; |
} |
// }}} |
// {{{ simpleQuery() |
/** |
* Sends a query to the database server |
* |
* @param string the SQL query string |
* |
* @return mixed + a PHP result resrouce for successful SELECT queries |
* + the DB_OK constant for other successful queries |
* + a DB_Error object on failure |
*/ |
function simpleQuery($query) |
{ |
$ismanip = $this->_checkManip($query); |
$this->last_query = $query; |
if (!@mssql_select_db($this->_db, $this->connection)) { |
return $this->mssqlRaiseError(DB_ERROR_NODBSELECTED); |
} |
$query = $this->modifyQuery($query); |
if (!$this->autocommit && $ismanip) { |
if ($this->transaction_opcount == 0) { |
$result = @mssql_query('BEGIN TRAN', $this->connection); |
if (!$result) { |
return $this->mssqlRaiseError(); |
} |
} |
$this->transaction_opcount++; |
} |
$result = @mssql_query($query, $this->connection); |
if (!$result) { |
return $this->mssqlRaiseError(); |
} |
// Determine which queries that should return data, and which |
// should return an error code only. |
return $ismanip ? DB_OK : $result; |
} |
// }}} |
// {{{ nextResult() |
/** |
* Move the internal mssql result pointer to the next available result |
* |
* @param a valid fbsql result resource |
* |
* @access public |
* |
* @return true if a result is available otherwise return false |
*/ |
function nextResult($result) |
{ |
return @mssql_next_result($result); |
} |
// }}} |
// {{{ fetchInto() |
/** |
* Places a row from the result set into the given array |
* |
* Formating of the array and the data therein are configurable. |
* See DB_result::fetchInto() for more information. |
* |
* This method is not meant to be called directly. Use |
* DB_result::fetchInto() instead. It can't be declared "protected" |
* because DB_result is a separate object. |
* |
* @param resource $result the query result resource |
* @param array $arr the referenced array to put the data in |
* @param int $fetchmode how the resulting array should be indexed |
* @param int $rownum the row number to fetch (0 = first row) |
* |
* @return mixed DB_OK on success, NULL when the end of a result set is |
* reached or on failure |
* |
* @see DB_result::fetchInto() |
*/ |
function fetchInto($result, &$arr, $fetchmode, $rownum = null) |
{ |
if ($rownum !== null) { |
if (!@mssql_data_seek($result, $rownum)) { |
return null; |
} |
} |
if ($fetchmode & DB_FETCHMODE_ASSOC) { |
$arr = @mssql_fetch_assoc($result); |
if ($this->options['portability'] & DB_PORTABILITY_LOWERCASE && $arr) { |
$arr = array_change_key_case($arr, CASE_LOWER); |
} |
} else { |
$arr = @mssql_fetch_row($result); |
} |
if (!$arr) { |
return null; |
} |
if ($this->options['portability'] & DB_PORTABILITY_RTRIM) { |
$this->_rtrimArrayValues($arr); |
} |
if ($this->options['portability'] & DB_PORTABILITY_NULL_TO_EMPTY) { |
$this->_convertNullArrayValuesToEmpty($arr); |
} |
return DB_OK; |
} |
// }}} |
// {{{ freeResult() |
/** |
* Deletes the result set and frees the memory occupied by the result set |
* |
* This method is not meant to be called directly. Use |
* DB_result::free() instead. It can't be declared "protected" |
* because DB_result is a separate object. |
* |
* @param resource $result PHP's query result resource |
* |
* @return bool TRUE on success, FALSE if $result is invalid |
* |
* @see DB_result::free() |
*/ |
function freeResult($result) |
{ |
return is_resource($result) ? mssql_free_result($result) : false; |
} |
// }}} |
// {{{ numCols() |
/** |
* Gets the number of columns in a result set |
* |
* This method is not meant to be called directly. Use |
* DB_result::numCols() instead. It can't be declared "protected" |
* because DB_result is a separate object. |
* |
* @param resource $result PHP's query result resource |
* |
* @return int the number of columns. A DB_Error object on failure. |
* |
* @see DB_result::numCols() |
*/ |
function numCols($result) |
{ |
$cols = @mssql_num_fields($result); |
if (!$cols) { |
return $this->mssqlRaiseError(); |
} |
return $cols; |
} |
// }}} |
// {{{ numRows() |
/** |
* Gets the number of rows in a result set |
* |
* This method is not meant to be called directly. Use |
* DB_result::numRows() instead. It can't be declared "protected" |
* because DB_result is a separate object. |
* |
* @param resource $result PHP's query result resource |
* |
* @return int the number of rows. A DB_Error object on failure. |
* |
* @see DB_result::numRows() |
*/ |
function numRows($result) |
{ |
$rows = @mssql_num_rows($result); |
if ($rows === false) { |
return $this->mssqlRaiseError(); |
} |
return $rows; |
} |
// }}} |
// {{{ autoCommit() |
/** |
* Enables or disables automatic commits |
* |
* @param bool $onoff true turns it on, false turns it off |
* |
* @return int DB_OK on success. A DB_Error object if the driver |
* doesn't support auto-committing transactions. |
*/ |
function autoCommit($onoff = false) |
{ |
// XXX if $this->transaction_opcount > 0, we should probably |
// issue a warning here. |
$this->autocommit = $onoff ? true : false; |
return DB_OK; |
} |
// }}} |
// {{{ commit() |
/** |
* Commits the current transaction |
* |
* @return int DB_OK on success. A DB_Error object on failure. |
*/ |
function commit() |
{ |
if ($this->transaction_opcount > 0) { |
if (!@mssql_select_db($this->_db, $this->connection)) { |
return $this->mssqlRaiseError(DB_ERROR_NODBSELECTED); |
} |
$result = @mssql_query('COMMIT TRAN', $this->connection); |
$this->transaction_opcount = 0; |
if (!$result) { |
return $this->mssqlRaiseError(); |
} |
} |
return DB_OK; |
} |
// }}} |
// {{{ rollback() |
/** |
* Reverts the current transaction |
* |
* @return int DB_OK on success. A DB_Error object on failure. |
*/ |
function rollback() |
{ |
if ($this->transaction_opcount > 0) { |
if (!@mssql_select_db($this->_db, $this->connection)) { |
return $this->mssqlRaiseError(DB_ERROR_NODBSELECTED); |
} |
$result = @mssql_query('ROLLBACK TRAN', $this->connection); |
$this->transaction_opcount = 0; |
if (!$result) { |
return $this->mssqlRaiseError(); |
} |
} |
return DB_OK; |
} |
// }}} |
// {{{ affectedRows() |
/** |
* Determines the number of rows affected by a data maniuplation query |
* |
* 0 is returned for queries that don't manipulate data. |
* |
* @return int the number of rows. A DB_Error object on failure. |
*/ |
function affectedRows() |
{ |
if ($this->_last_query_manip) { |
$res = @mssql_query('select @@rowcount', $this->connection); |
if (!$res) { |
return $this->mssqlRaiseError(); |
} |
$ar = @mssql_fetch_row($res); |
if (!$ar) { |
$result = 0; |
} else { |
@mssql_free_result($res); |
$result = $ar[0]; |
} |
} else { |
$result = 0; |
} |
return $result; |
} |
// }}} |
// {{{ nextId() |
/** |
* Returns the next free id in a sequence |
* |
* @param string $seq_name name of the sequence |
* @param boolean $ondemand when true, the seqence is automatically |
* created if it does not exist |
* |
* @return int the next id number in the sequence. |
* A DB_Error object on failure. |
* |
* @see DB_common::nextID(), DB_common::getSequenceName(), |
* DB_mssql::createSequence(), DB_mssql::dropSequence() |
*/ |
function nextId($seq_name, $ondemand = true) |
{ |
$seqname = $this->getSequenceName($seq_name); |
if (!@mssql_select_db($this->_db, $this->connection)) { |
return $this->mssqlRaiseError(DB_ERROR_NODBSELECTED); |
} |
$repeat = 0; |
do { |
$this->pushErrorHandling(PEAR_ERROR_RETURN); |
$result = $this->query("INSERT INTO $seqname (vapor) VALUES (0)"); |
$this->popErrorHandling(); |
if ($ondemand && DB::isError($result) && |
($result->getCode() == DB_ERROR || $result->getCode() == DB_ERROR_NOSUCHTABLE)) |
{ |
$repeat = 1; |
$result = $this->createSequence($seq_name); |
if (DB::isError($result)) { |
return $this->raiseError($result); |
} |
} elseif (!DB::isError($result)) { |
$result = $this->query("SELECT IDENT_CURRENT('$seqname')"); |
if (DB::isError($result)) { |
/* Fallback code for MS SQL Server 7.0, which doesn't have |
* IDENT_CURRENT. This is *not* safe for concurrent |
* requests, and really, if you're using it, you're in a |
* world of hurt. Nevertheless, it's here to ensure BC. See |
* bug #181 for the gory details.*/ |
$result = $this->query("SELECT @@IDENTITY FROM $seqname"); |
} |
$repeat = 0; |
} else { |
$repeat = false; |
} |
} while ($repeat); |
if (DB::isError($result)) { |
return $this->raiseError($result); |
} |
$result = $result->fetchRow(DB_FETCHMODE_ORDERED); |
return $result[0]; |
} |
/** |
* Creates a new sequence |
* |
* @param string $seq_name name of the new sequence |
* |
* @return int DB_OK on success. A DB_Error object on failure. |
* |
* @see DB_common::createSequence(), DB_common::getSequenceName(), |
* DB_mssql::nextID(), DB_mssql::dropSequence() |
*/ |
function createSequence($seq_name) |
{ |
return $this->query('CREATE TABLE ' |
. $this->getSequenceName($seq_name) |
. ' ([id] [int] IDENTITY (1, 1) NOT NULL,' |
. ' [vapor] [int] NULL)'); |
} |
// }}} |
// {{{ dropSequence() |
/** |
* Deletes a sequence |
* |
* @param string $seq_name name of the sequence to be deleted |
* |
* @return int DB_OK on success. A DB_Error object on failure. |
* |
* @see DB_common::dropSequence(), DB_common::getSequenceName(), |
* DB_mssql::nextID(), DB_mssql::createSequence() |
*/ |
function dropSequence($seq_name) |
{ |
return $this->query('DROP TABLE ' . $this->getSequenceName($seq_name)); |
} |
// }}} |
// {{{ escapeSimple() |
/** |
* Escapes a string in a manner suitable for SQL Server. |
* |
* @param string $str the string to be escaped |
* @return string the escaped string |
* |
* @see DB_common::quoteSmart() |
* @since Method available since Release 1.6.0 |
*/ |
function escapeSimple($str) |
{ |
return str_replace( |
array("'", "\\\r\n", "\\\n"), |
array("''", "\\\\\r\n\r\n", "\\\\\n\n"), |
$str |
); |
} |
// }}} |
// {{{ quoteIdentifier() |
/** |
* Quotes a string so it can be safely used as a table or column name |
* |
* @param string $str identifier name to be quoted |
* |
* @return string quoted identifier string |
* |
* @see DB_common::quoteIdentifier() |
* @since Method available since Release 1.6.0 |
*/ |
function quoteIdentifier($str) |
{ |
return '[' . str_replace(']', ']]', $str) . ']'; |
} |
// }}} |
// {{{ mssqlRaiseError() |
/** |
* Produces a DB_Error object regarding the current problem |
* |
* @param int $errno if the error is being manually raised pass a |
* DB_ERROR* constant here. If this isn't passed |
* the error information gathered from the DBMS. |
* |
* @return object the DB_Error object |
* |
* @see DB_common::raiseError(), |
* DB_mssql::errorNative(), DB_mssql::errorCode() |
*/ |
function mssqlRaiseError($code = null) |
{ |
$message = @mssql_get_last_message(); |
if (!$code) { |
$code = $this->errorNative(); |
} |
return $this->raiseError($this->errorCode($code, $message), |
null, null, null, "$code - $message"); |
} |
// }}} |
// {{{ errorNative() |
/** |
* Gets the DBMS' native error code produced by the last query |
* |
* @return int the DBMS' error code |
*/ |
function errorNative() |
{ |
$res = @mssql_query('select @@ERROR as ErrorCode', $this->connection); |
if (!$res) { |
return DB_ERROR; |
} |
$row = @mssql_fetch_row($res); |
return $row[0]; |
} |
// }}} |
// {{{ errorCode() |
/** |
* Determines PEAR::DB error code from mssql's native codes. |
* |
* If <var>$nativecode</var> isn't known yet, it will be looked up. |
* |
* @param mixed $nativecode mssql error code, if known |
* @return integer an error number from a DB error constant |
* @see errorNative() |
*/ |
function errorCode($nativecode = null, $msg = '') |
{ |
if (!$nativecode) { |
$nativecode = $this->errorNative(); |
} |
if (isset($this->errorcode_map[$nativecode])) { |
if ($nativecode == 3701 |
&& preg_match('/Cannot drop the index/i', $msg)) |
{ |
return DB_ERROR_NOT_FOUND; |
} |
return $this->errorcode_map[$nativecode]; |
} else { |
return DB_ERROR; |
} |
} |
// }}} |
// {{{ tableInfo() |
/** |
* Returns information about a table or a result set |
* |
* NOTE: only supports 'table' and 'flags' if <var>$result</var> |
* is a table name. |
* |
* @param object|string $result DB_result object from a query or a |
* string containing the name of a table. |
* While this also accepts a query result |
* resource identifier, this behavior is |
* deprecated. |
* @param int $mode a valid tableInfo mode |
* |
* @return array an associative array with the information requested. |
* A DB_Error object on failure. |
* |
* @see DB_common::tableInfo() |
*/ |
function tableInfo($result, $mode = null) |
{ |
if (is_string($result)) { |
/* |
* Probably received a table name. |
* Create a result resource identifier. |
*/ |
if (!@mssql_select_db($this->_db, $this->connection)) { |
return $this->mssqlRaiseError(DB_ERROR_NODBSELECTED); |
} |
$id = @mssql_query("SELECT * FROM $result WHERE 1=0", |
$this->connection); |
$got_string = true; |
} elseif (isset($result->result)) { |
/* |
* Probably received a result object. |
* Extract the result resource identifier. |
*/ |
$id = $result->result; |
$got_string = false; |
} else { |
/* |
* Probably received a result resource identifier. |
* Copy it. |
* Deprecated. Here for compatibility only. |
*/ |
$id = $result; |
$got_string = false; |
} |
if (!is_resource($id)) { |
return $this->mssqlRaiseError(DB_ERROR_NEED_MORE_DATA); |
} |
if ($this->options['portability'] & DB_PORTABILITY_LOWERCASE) { |
$case_func = 'strtolower'; |
} else { |
$case_func = 'strval'; |
} |
$count = @mssql_num_fields($id); |
$res = array(); |
if ($mode) { |
$res['num_fields'] = $count; |
} |
for ($i = 0; $i < $count; $i++) { |
if ($got_string) { |
$flags = $this->_mssql_field_flags($result, |
@mssql_field_name($id, $i)); |
if (DB::isError($flags)) { |
return $flags; |
} |
} else { |
$flags = ''; |
} |
$res[$i] = array( |
'table' => $got_string ? $case_func($result) : '', |
'name' => $case_func(@mssql_field_name($id, $i)), |
'type' => @mssql_field_type($id, $i), |
'len' => @mssql_field_length($id, $i), |
'flags' => $flags, |
); |
if ($mode & DB_TABLEINFO_ORDER) { |
$res['order'][$res[$i]['name']] = $i; |
} |
if ($mode & DB_TABLEINFO_ORDERTABLE) { |
$res['ordertable'][$res[$i]['table']][$res[$i]['name']] = $i; |
} |
} |
// free the result only if we were called on a table |
if ($got_string) { |
@mssql_free_result($id); |
} |
return $res; |
} |
// }}} |
// {{{ _mssql_field_flags() |
/** |
* Get a column's flags |
* |
* Supports "not_null", "primary_key", |
* "auto_increment" (mssql identity), "timestamp" (mssql timestamp), |
* "unique_key" (mssql unique index, unique check or primary_key) and |
* "multiple_key" (multikey index) |
* |
* mssql timestamp is NOT similar to the mysql timestamp so this is maybe |
* not useful at all - is the behaviour of mysql_field_flags that primary |
* keys are alway unique? is the interpretation of multiple_key correct? |
* |
* @param string $table the table name |
* @param string $column the field name |
* |
* @return string the flags |
* |
* @access private |
* @author Joern Barthel <j_barthel@web.de> |
*/ |
function _mssql_field_flags($table, $column) |
{ |
static $tableName = null; |
static $flags = array(); |
if ($table != $tableName) { |
$flags = array(); |
$tableName = $table; |
// get unique and primary keys |
$res = $this->getAll("EXEC SP_HELPINDEX $table", DB_FETCHMODE_ASSOC); |
if (DB::isError($res)) { |
return $res; |
} |
foreach ($res as $val) { |
$keys = explode(', ', $val['index_keys']); |
if (sizeof($keys) > 1) { |
foreach ($keys as $key) { |
$this->_add_flag($flags[$key], 'multiple_key'); |
} |
} |
if (strpos($val['index_description'], 'primary key')) { |
foreach ($keys as $key) { |
$this->_add_flag($flags[$key], 'primary_key'); |
} |
} elseif (strpos($val['index_description'], 'unique')) { |
foreach ($keys as $key) { |
$this->_add_flag($flags[$key], 'unique_key'); |
} |
} |
} |
// get auto_increment, not_null and timestamp |
$res = $this->getAll("EXEC SP_COLUMNS $table", DB_FETCHMODE_ASSOC); |
if (DB::isError($res)) { |
return $res; |
} |
foreach ($res as $val) { |
$val = array_change_key_case($val, CASE_LOWER); |
if ($val['nullable'] == '0') { |
$this->_add_flag($flags[$val['column_name']], 'not_null'); |
} |
if (strpos($val['type_name'], 'identity')) { |
$this->_add_flag($flags[$val['column_name']], 'auto_increment'); |
} |
if (strpos($val['type_name'], 'timestamp')) { |
$this->_add_flag($flags[$val['column_name']], 'timestamp'); |
} |
} |
} |
if (array_key_exists($column, $flags)) { |
return(implode(' ', $flags[$column])); |
} |
return ''; |
} |
// }}} |
// {{{ _add_flag() |
/** |
* Adds a string to the flags array if the flag is not yet in there |
* - if there is no flag present the array is created |
* |
* @param array &$array the reference to the flag-array |
* @param string $value the flag value |
* |
* @return void |
* |
* @access private |
* @author Joern Barthel <j_barthel@web.de> |
*/ |
function _add_flag(&$array, $value) |
{ |
if (!is_array($array)) { |
$array = array($value); |
} elseif (!in_array($value, $array)) { |
array_push($array, $value); |
} |
} |
// }}} |
// {{{ getSpecialQuery() |
/** |
* Obtains the query string needed for listing a given type of objects |
* |
* @param string $type the kind of objects you want to retrieve |
* |
* @return string the SQL query string or null if the driver doesn't |
* support the object type requested |
* |
* @access protected |
* @see DB_common::getListOf() |
*/ |
function getSpecialQuery($type) |
{ |
switch ($type) { |
case 'tables': |
return "SELECT name FROM sysobjects WHERE type = 'U'" |
. ' ORDER BY name'; |
case 'views': |
return "SELECT name FROM sysobjects WHERE type = 'V'"; |
default: |
return null; |
} |
} |
// }}} |
} |
/* |
* Local variables: |
* tab-width: 4 |
* c-basic-offset: 4 |
* End: |
*/ |
?> |
/branches/v1.3-critias/bibliotheque/pear/DB/sqlite.php |
---|
New file |
0,0 → 1,963 |
<?php |
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */ |
/** |
* The PEAR DB driver for PHP's sqlite extension |
* for interacting with SQLite databases |
* |
* PHP version 5 |
* |
* LICENSE: This source file is subject to version 3.0 of the PHP license |
* that is available through the world-wide-web at the following URI: |
* http://www.php.net/license/3_0.txt. If you did not receive a copy of |
* the PHP License and are unable to obtain it through the web, please |
* send a note to license@php.net so we can mail you a copy immediately. |
* |
* @category Database |
* @package DB |
* @author Urs Gehrig <urs@circle.ch> |
* @author Mika Tuupola <tuupola@appelsiini.net> |
* @author Daniel Convissor <danielc@php.net> |
* @copyright 1997-2007 The PHP Group |
* @license http://www.php.net/license/3_0.txt PHP License 3.0 3.0 |
* @version CVS: $Id$ |
* @link http://pear.php.net/package/DB |
*/ |
/** |
* Obtain the DB_common class so it can be extended from |
*/ |
require_once 'DB/common.php'; |
/** |
* The methods PEAR DB uses to interact with PHP's sqlite extension |
* for interacting with SQLite databases |
* |
* These methods overload the ones declared in DB_common. |
* |
* NOTICE: This driver needs PHP's track_errors ini setting to be on. |
* It is automatically turned on when connecting to the database. |
* Make sure your scripts don't turn it off. |
* |
* @category Database |
* @package DB |
* @author Urs Gehrig <urs@circle.ch> |
* @author Mika Tuupola <tuupola@appelsiini.net> |
* @author Daniel Convissor <danielc@php.net> |
* @copyright 1997-2007 The PHP Group |
* @license http://www.php.net/license/3_0.txt PHP License 3.0 3.0 |
* @version Release: 1.9.2 |
* @link http://pear.php.net/package/DB |
*/ |
class DB_sqlite extends DB_common |
{ |
// {{{ properties |
/** |
* The DB driver type (mysql, oci8, odbc, etc.) |
* @var string |
*/ |
var $phptype = 'sqlite'; |
/** |
* The database syntax variant to be used (db2, access, etc.), if any |
* @var string |
*/ |
var $dbsyntax = 'sqlite'; |
/** |
* The capabilities of this DB implementation |
* |
* The 'new_link' element contains the PHP version that first provided |
* new_link support for this DBMS. Contains false if it's unsupported. |
* |
* Meaning of the 'limit' element: |
* + 'emulate' = emulate with fetch row by number |
* + 'alter' = alter the query |
* + false = skip rows |
* |
* @var array |
*/ |
var $features = array( |
'limit' => 'alter', |
'new_link' => false, |
'numrows' => true, |
'pconnect' => true, |
'prepare' => false, |
'ssl' => false, |
'transactions' => false, |
); |
/** |
* A mapping of native error codes to DB error codes |
* |
* {@internal Error codes according to sqlite_exec. See the online |
* manual at http://sqlite.org/c_interface.html for info. |
* This error handling based on sqlite_exec is not yet implemented.}} |
* |
* @var array |
*/ |
var $errorcode_map = array( |
); |
/** |
* The raw database connection created by PHP |
* @var resource |
*/ |
var $connection; |
/** |
* The DSN information for connecting to a database |
* @var array |
*/ |
var $dsn = array(); |
/** |
* SQLite data types |
* |
* @link http://www.sqlite.org/datatypes.html |
* |
* @var array |
*/ |
var $keywords = array ( |
'BLOB' => '', |
'BOOLEAN' => '', |
'CHARACTER' => '', |
'CLOB' => '', |
'FLOAT' => '', |
'INTEGER' => '', |
'KEY' => '', |
'NATIONAL' => '', |
'NUMERIC' => '', |
'NVARCHAR' => '', |
'PRIMARY' => '', |
'TEXT' => '', |
'TIMESTAMP' => '', |
'UNIQUE' => '', |
'VARCHAR' => '', |
'VARYING' => '', |
); |
/** |
* The most recent error message from $php_errormsg |
* @var string |
* @access private |
*/ |
var $_lasterror = ''; |
// }}} |
// {{{ constructor |
/** |
* This constructor calls <kbd>parent::__construct()</kbd> |
* |
* @return void |
*/ |
function __construct() |
{ |
parent::__construct(); |
} |
// }}} |
// {{{ connect() |
/** |
* Connect to the database server, log in and open the database |
* |
* Don't call this method directly. Use DB::connect() instead. |
* |
* PEAR DB's sqlite driver supports the following extra DSN options: |
* + mode The permissions for the database file, in four digit |
* chmod octal format (eg "0600"). |
* |
* Example of connecting to a database in read-only mode: |
* <code> |
* require_once 'DB.php'; |
* |
* $dsn = 'sqlite:///path/and/name/of/db/file?mode=0400'; |
* $options = array( |
* 'portability' => DB_PORTABILITY_ALL, |
* ); |
* |
* $db = DB::connect($dsn, $options); |
* if (PEAR::isError($db)) { |
* die($db->getMessage()); |
* } |
* </code> |
* |
* @param array $dsn the data source name |
* @param bool $persistent should the connection be persistent? |
* |
* @return int DB_OK on success. A DB_Error object on failure. |
*/ |
function connect($dsn, $persistent = false) |
{ |
if (!PEAR::loadExtension('sqlite')) { |
return $this->raiseError(DB_ERROR_EXTENSION_NOT_FOUND); |
} |
$this->dsn = $dsn; |
if ($dsn['dbsyntax']) { |
$this->dbsyntax = $dsn['dbsyntax']; |
} |
if (!$dsn['database']) { |
return $this->sqliteRaiseError(DB_ERROR_ACCESS_VIOLATION); |
} |
if ($dsn['database'] !== ':memory:') { |
if (!file_exists($dsn['database'])) { |
if (!touch($dsn['database'])) { |
return $this->sqliteRaiseError(DB_ERROR_NOT_FOUND); |
} |
if (!isset($dsn['mode']) || |
!is_numeric($dsn['mode'])) |
{ |
$mode = 0644; |
} else { |
$mode = octdec($dsn['mode']); |
} |
if (!chmod($dsn['database'], $mode)) { |
return $this->sqliteRaiseError(DB_ERROR_NOT_FOUND); |
} |
if (!file_exists($dsn['database'])) { |
return $this->sqliteRaiseError(DB_ERROR_NOT_FOUND); |
} |
} |
if (!is_file($dsn['database'])) { |
return $this->sqliteRaiseError(DB_ERROR_INVALID); |
} |
if (!is_readable($dsn['database'])) { |
return $this->sqliteRaiseError(DB_ERROR_ACCESS_VIOLATION); |
} |
} |
$connect_function = $persistent ? 'sqlite_popen' : 'sqlite_open'; |
// track_errors must remain on for simpleQuery() |
@ini_set('track_errors', 1); |
$php_errormsg = ''; |
if (!$this->connection = @$connect_function($dsn['database'])) { |
return $this->raiseError(DB_ERROR_NODBSELECTED, |
null, null, null, |
$php_errormsg); |
} |
return DB_OK; |
} |
// }}} |
// {{{ disconnect() |
/** |
* Disconnects from the database server |
* |
* @return bool TRUE on success, FALSE on failure |
*/ |
function disconnect() |
{ |
$ret = @sqlite_close($this->connection); |
$this->connection = null; |
return $ret; |
} |
// }}} |
// {{{ simpleQuery() |
/** |
* Sends a query to the database server |
* |
* NOTICE: This method needs PHP's track_errors ini setting to be on. |
* It is automatically turned on when connecting to the database. |
* Make sure your scripts don't turn it off. |
* |
* @param string the SQL query string |
* |
* @return mixed + a PHP result resrouce for successful SELECT queries |
* + the DB_OK constant for other successful queries |
* + a DB_Error object on failure |
*/ |
function simpleQuery($query) |
{ |
$ismanip = $this->_checkManip($query); |
$this->last_query = $query; |
$query = $this->modifyQuery($query); |
$php_errormsg = ''; |
$result = @sqlite_query($query, $this->connection); |
$this->_lasterror = $php_errormsg ? $php_errormsg : ''; |
$this->result = $result; |
if (!$this->result) { |
return $this->sqliteRaiseError(null); |
} |
// sqlite_query() seems to allways return a resource |
// so cant use that. Using $ismanip instead |
if (!$ismanip) { |
$numRows = $this->numRows($result); |
if (is_object($numRows)) { |
// we've got PEAR_Error |
return $numRows; |
} |
return $result; |
} |
return DB_OK; |
} |
// }}} |
// {{{ nextResult() |
/** |
* Move the internal sqlite result pointer to the next available result |
* |
* @param resource $result the valid sqlite result resource |
* |
* @return bool true if a result is available otherwise return false |
*/ |
function nextResult($result) |
{ |
return false; |
} |
// }}} |
// {{{ fetchInto() |
/** |
* Places a row from the result set into the given array |
* |
* Formating of the array and the data therein are configurable. |
* See DB_result::fetchInto() for more information. |
* |
* This method is not meant to be called directly. Use |
* DB_result::fetchInto() instead. It can't be declared "protected" |
* because DB_result is a separate object. |
* |
* @param resource $result the query result resource |
* @param array $arr the referenced array to put the data in |
* @param int $fetchmode how the resulting array should be indexed |
* @param int $rownum the row number to fetch (0 = first row) |
* |
* @return mixed DB_OK on success, NULL when the end of a result set is |
* reached or on failure |
* |
* @see DB_result::fetchInto() |
*/ |
function fetchInto($result, &$arr, $fetchmode, $rownum = null) |
{ |
if ($rownum !== null) { |
if (!@sqlite_seek($this->result, $rownum)) { |
return null; |
} |
} |
if ($fetchmode & DB_FETCHMODE_ASSOC) { |
$arr = @sqlite_fetch_array($result, SQLITE_ASSOC); |
if ($this->options['portability'] & DB_PORTABILITY_LOWERCASE && $arr) { |
$arr = array_change_key_case($arr, CASE_LOWER); |
} |
/* Remove extraneous " characters from the fields in the result. |
* Fixes bug #11716. */ |
if (is_array($arr) && count($arr) > 0) { |
$strippedArr = array(); |
foreach ($arr as $field => $value) { |
$strippedArr[trim($field, '"')] = $value; |
} |
$arr = $strippedArr; |
} |
} else { |
$arr = @sqlite_fetch_array($result, SQLITE_NUM); |
} |
if (!$arr) { |
return null; |
} |
if ($this->options['portability'] & DB_PORTABILITY_RTRIM) { |
/* |
* Even though this DBMS already trims output, we do this because |
* a field might have intentional whitespace at the end that |
* gets removed by DB_PORTABILITY_RTRIM under another driver. |
*/ |
$this->_rtrimArrayValues($arr); |
} |
if ($this->options['portability'] & DB_PORTABILITY_NULL_TO_EMPTY) { |
$this->_convertNullArrayValuesToEmpty($arr); |
} |
return DB_OK; |
} |
// }}} |
// {{{ freeResult() |
/** |
* Deletes the result set and frees the memory occupied by the result set |
* |
* This method is not meant to be called directly. Use |
* DB_result::free() instead. It can't be declared "protected" |
* because DB_result is a separate object. |
* |
* @param resource $result PHP's query result resource |
* |
* @return bool TRUE on success, FALSE if $result is invalid |
* |
* @see DB_result::free() |
*/ |
function freeResult(&$result) |
{ |
// XXX No native free? |
if (!is_resource($result)) { |
return false; |
} |
$result = null; |
return true; |
} |
// }}} |
// {{{ numCols() |
/** |
* Gets the number of columns in a result set |
* |
* This method is not meant to be called directly. Use |
* DB_result::numCols() instead. It can't be declared "protected" |
* because DB_result is a separate object. |
* |
* @param resource $result PHP's query result resource |
* |
* @return int the number of columns. A DB_Error object on failure. |
* |
* @see DB_result::numCols() |
*/ |
function numCols($result) |
{ |
$cols = @sqlite_num_fields($result); |
if (!$cols) { |
return $this->sqliteRaiseError(); |
} |
return $cols; |
} |
// }}} |
// {{{ numRows() |
/** |
* Gets the number of rows in a result set |
* |
* This method is not meant to be called directly. Use |
* DB_result::numRows() instead. It can't be declared "protected" |
* because DB_result is a separate object. |
* |
* @param resource $result PHP's query result resource |
* |
* @return int the number of rows. A DB_Error object on failure. |
* |
* @see DB_result::numRows() |
*/ |
function numRows($result) |
{ |
$rows = @sqlite_num_rows($result); |
if ($rows === null) { |
return $this->sqliteRaiseError(); |
} |
return $rows; |
} |
// }}} |
// {{{ affected() |
/** |
* Determines the number of rows affected by a data maniuplation query |
* |
* 0 is returned for queries that don't manipulate data. |
* |
* @return int the number of rows. A DB_Error object on failure. |
*/ |
function affectedRows() |
{ |
return @sqlite_changes($this->connection); |
} |
// }}} |
// {{{ dropSequence() |
/** |
* Deletes a sequence |
* |
* @param string $seq_name name of the sequence to be deleted |
* |
* @return int DB_OK on success. A DB_Error object on failure. |
* |
* @see DB_common::dropSequence(), DB_common::getSequenceName(), |
* DB_sqlite::nextID(), DB_sqlite::createSequence() |
*/ |
function dropSequence($seq_name) |
{ |
return $this->query('DROP TABLE ' . $this->getSequenceName($seq_name)); |
} |
/** |
* Creates a new sequence |
* |
* @param string $seq_name name of the new sequence |
* |
* @return int DB_OK on success. A DB_Error object on failure. |
* |
* @see DB_common::createSequence(), DB_common::getSequenceName(), |
* DB_sqlite::nextID(), DB_sqlite::dropSequence() |
*/ |
function createSequence($seq_name) |
{ |
$seqname = $this->getSequenceName($seq_name); |
$query = 'CREATE TABLE ' . $seqname . |
' (id INTEGER UNSIGNED PRIMARY KEY) '; |
$result = $this->query($query); |
if (DB::isError($result)) { |
return($result); |
} |
$query = "CREATE TRIGGER ${seqname}_cleanup AFTER INSERT ON $seqname |
BEGIN |
DELETE FROM $seqname WHERE id<LAST_INSERT_ROWID(); |
END "; |
$result = $this->query($query); |
if (DB::isError($result)) { |
return($result); |
} |
} |
// }}} |
// {{{ nextId() |
/** |
* Returns the next free id in a sequence |
* |
* @param string $seq_name name of the sequence |
* @param boolean $ondemand when true, the seqence is automatically |
* created if it does not exist |
* |
* @return int the next id number in the sequence. |
* A DB_Error object on failure. |
* |
* @see DB_common::nextID(), DB_common::getSequenceName(), |
* DB_sqlite::createSequence(), DB_sqlite::dropSequence() |
*/ |
function nextId($seq_name, $ondemand = true) |
{ |
$seqname = $this->getSequenceName($seq_name); |
do { |
$repeat = 0; |
$this->pushErrorHandling(PEAR_ERROR_RETURN); |
$result = $this->query("INSERT INTO $seqname (id) VALUES (NULL)"); |
$this->popErrorHandling(); |
if ($result === DB_OK) { |
$id = @sqlite_last_insert_rowid($this->connection); |
if ($id != 0) { |
return $id; |
} |
} elseif ($ondemand && DB::isError($result) && |
$result->getCode() == DB_ERROR_NOSUCHTABLE) |
{ |
$result = $this->createSequence($seq_name); |
if (DB::isError($result)) { |
return $this->raiseError($result); |
} else { |
$repeat = 1; |
} |
} |
} while ($repeat); |
return $this->raiseError($result); |
} |
// }}} |
// {{{ getDbFileStats() |
/** |
* Get the file stats for the current database |
* |
* Possible arguments are dev, ino, mode, nlink, uid, gid, rdev, size, |
* atime, mtime, ctime, blksize, blocks or a numeric key between |
* 0 and 12. |
* |
* @param string $arg the array key for stats() |
* |
* @return mixed an array on an unspecified key, integer on a passed |
* arg and false at a stats error |
*/ |
function getDbFileStats($arg = '') |
{ |
$stats = stat($this->dsn['database']); |
if ($stats == false) { |
return false; |
} |
if (is_array($stats)) { |
if (is_numeric($arg)) { |
if (((int)$arg <= 12) & ((int)$arg >= 0)) { |
return false; |
} |
return $stats[$arg ]; |
} |
if (array_key_exists(trim($arg), $stats)) { |
return $stats[$arg ]; |
} |
} |
return $stats; |
} |
// }}} |
// {{{ escapeSimple() |
/** |
* Escapes a string according to the current DBMS's standards |
* |
* In SQLite, this makes things safe for inserts/updates, but may |
* cause problems when performing text comparisons against columns |
* containing binary data. See the |
* {@link http://php.net/sqlite_escape_string PHP manual} for more info. |
* |
* @param string $str the string to be escaped |
* |
* @return string the escaped string |
* |
* @since Method available since Release 1.6.1 |
* @see DB_common::escapeSimple() |
*/ |
function escapeSimple($str) |
{ |
return @sqlite_escape_string($str); |
} |
// }}} |
// {{{ modifyLimitQuery() |
/** |
* Adds LIMIT clauses to a query string according to current DBMS standards |
* |
* @param string $query the query to modify |
* @param int $from the row to start to fetching (0 = the first row) |
* @param int $count the numbers of rows to fetch |
* @param mixed $params array, string or numeric data to be used in |
* execution of the statement. Quantity of items |
* passed must match quantity of placeholders in |
* query: meaning 1 placeholder for non-array |
* parameters or 1 placeholder per array element. |
* |
* @return string the query string with LIMIT clauses added |
* |
* @access protected |
*/ |
function modifyLimitQuery($query, $from, $count, $params = array()) |
{ |
return "$query LIMIT $count OFFSET $from"; |
} |
// }}} |
// {{{ modifyQuery() |
/** |
* Changes a query string for various DBMS specific reasons |
* |
* This little hack lets you know how many rows were deleted |
* when running a "DELETE FROM table" query. Only implemented |
* if the DB_PORTABILITY_DELETE_COUNT portability option is on. |
* |
* @param string $query the query string to modify |
* |
* @return string the modified query string |
* |
* @access protected |
* @see DB_common::setOption() |
*/ |
function modifyQuery($query) |
{ |
if ($this->options['portability'] & DB_PORTABILITY_DELETE_COUNT) { |
if (preg_match('/^\s*DELETE\s+FROM\s+(\S+)\s*$/i', $query)) { |
$query = preg_replace('/^\s*DELETE\s+FROM\s+(\S+)\s*$/', |
'DELETE FROM \1 WHERE 1=1', $query); |
} |
} |
return $query; |
} |
// }}} |
// {{{ sqliteRaiseError() |
/** |
* Produces a DB_Error object regarding the current problem |
* |
* @param int $errno if the error is being manually raised pass a |
* DB_ERROR* constant here. If this isn't passed |
* the error information gathered from the DBMS. |
* |
* @return object the DB_Error object |
* |
* @see DB_common::raiseError(), |
* DB_sqlite::errorNative(), DB_sqlite::errorCode() |
*/ |
function sqliteRaiseError($errno = null) |
{ |
$native = $this->errorNative(); |
if ($errno === null) { |
$errno = $this->errorCode($native); |
} |
$errorcode = @sqlite_last_error($this->connection); |
$userinfo = "$errorcode ** $this->last_query"; |
return $this->raiseError($errno, null, null, $userinfo, $native); |
} |
// }}} |
// {{{ errorNative() |
/** |
* Gets the DBMS' native error message produced by the last query |
* |
* {@internal This is used to retrieve more meaningfull error messages |
* because sqlite_last_error() does not provide adequate info.}} |
* |
* @return string the DBMS' error message |
*/ |
function errorNative() |
{ |
return $this->_lasterror; |
} |
// }}} |
// {{{ errorCode() |
/** |
* Determines PEAR::DB error code from the database's text error message |
* |
* @param string $errormsg the error message returned from the database |
* |
* @return integer the DB error number |
*/ |
function errorCode($errormsg) |
{ |
static $error_regexps; |
// PHP 5.2+ prepends the function name to $php_errormsg, so we need |
// this hack to work around it, per bug #9599. |
$errormsg = preg_replace('/^sqlite[a-z_]+\(\): /', '', $errormsg); |
if (!isset($error_regexps)) { |
$error_regexps = array( |
'/^no such table:/' => DB_ERROR_NOSUCHTABLE, |
'/^no such index:/' => DB_ERROR_NOT_FOUND, |
'/^(table|index) .* already exists$/' => DB_ERROR_ALREADY_EXISTS, |
'/PRIMARY KEY must be unique/i' => DB_ERROR_CONSTRAINT, |
'/is not unique/' => DB_ERROR_CONSTRAINT, |
'/columns .* are not unique/i' => DB_ERROR_CONSTRAINT, |
'/uniqueness constraint failed/' => DB_ERROR_CONSTRAINT, |
'/may not be NULL/' => DB_ERROR_CONSTRAINT_NOT_NULL, |
'/^no such column:/' => DB_ERROR_NOSUCHFIELD, |
'/no column named/' => DB_ERROR_NOSUCHFIELD, |
'/column not present in both tables/i' => DB_ERROR_NOSUCHFIELD, |
'/^near ".*": syntax error$/' => DB_ERROR_SYNTAX, |
'/[0-9]+ values for [0-9]+ columns/i' => DB_ERROR_VALUE_COUNT_ON_ROW, |
); |
} |
foreach ($error_regexps as $regexp => $code) { |
if (preg_match($regexp, $errormsg)) { |
return $code; |
} |
} |
// Fall back to DB_ERROR if there was no mapping. |
return DB_ERROR; |
} |
// }}} |
// {{{ tableInfo() |
/** |
* Returns information about a table |
* |
* @param string $result a string containing the name of a table |
* @param int $mode a valid tableInfo mode |
* |
* @return array an associative array with the information requested. |
* A DB_Error object on failure. |
* |
* @see DB_common::tableInfo() |
* @since Method available since Release 1.7.0 |
*/ |
function tableInfo($result, $mode = null) |
{ |
if (is_string($result)) { |
/* |
* Probably received a table name. |
* Create a result resource identifier. |
*/ |
$id = @sqlite_array_query($this->connection, |
"PRAGMA table_info('$result');", |
SQLITE_ASSOC); |
$got_string = true; |
} else { |
$this->last_query = ''; |
return $this->raiseError(DB_ERROR_NOT_CAPABLE, null, null, null, |
'This DBMS can not obtain tableInfo' . |
' from result sets'); |
} |
if ($this->options['portability'] & DB_PORTABILITY_LOWERCASE) { |
$case_func = 'strtolower'; |
} else { |
$case_func = 'strval'; |
} |
$count = count($id); |
$res = array(); |
if ($mode) { |
$res['num_fields'] = $count; |
} |
for ($i = 0; $i < $count; $i++) { |
if (strpos($id[$i]['type'], '(') !== false) { |
$bits = explode('(', $id[$i]['type']); |
$type = $bits[0]; |
$len = rtrim($bits[1],')'); |
} else { |
$type = $id[$i]['type']; |
$len = 0; |
} |
$flags = ''; |
if ($id[$i]['pk']) { |
$flags .= 'primary_key '; |
if (strtoupper($type) == 'INTEGER') { |
$flags .= 'auto_increment '; |
} |
} |
if ($id[$i]['notnull']) { |
$flags .= 'not_null '; |
} |
if ($id[$i]['dflt_value'] !== null) { |
$flags .= 'default_' . rawurlencode($id[$i]['dflt_value']); |
} |
$flags = trim($flags); |
$res[$i] = array( |
'table' => $case_func($result), |
'name' => $case_func($id[$i]['name']), |
'type' => $type, |
'len' => $len, |
'flags' => $flags, |
); |
if ($mode & DB_TABLEINFO_ORDER) { |
$res['order'][$res[$i]['name']] = $i; |
} |
if ($mode & DB_TABLEINFO_ORDERTABLE) { |
$res['ordertable'][$res[$i]['table']][$res[$i]['name']] = $i; |
} |
} |
return $res; |
} |
// }}} |
// {{{ getSpecialQuery() |
/** |
* Obtains the query string needed for listing a given type of objects |
* |
* @param string $type the kind of objects you want to retrieve |
* @param array $args SQLITE DRIVER ONLY: a private array of arguments |
* used by the getSpecialQuery(). Do not use |
* this directly. |
* |
* @return string the SQL query string or null if the driver doesn't |
* support the object type requested |
* |
* @access protected |
* @see DB_common::getListOf() |
*/ |
function getSpecialQuery($type, $args = array()) |
{ |
if (!is_array($args)) { |
return $this->raiseError('no key specified', null, null, null, |
'Argument has to be an array.'); |
} |
switch ($type) { |
case 'master': |
return 'SELECT * FROM sqlite_master;'; |
case 'tables': |
return "SELECT name FROM sqlite_master WHERE type='table' " |
. 'UNION ALL SELECT name FROM sqlite_temp_master ' |
. "WHERE type='table' ORDER BY name;"; |
case 'schema': |
return 'SELECT sql FROM (SELECT * FROM sqlite_master ' |
. 'UNION ALL SELECT * FROM sqlite_temp_master) ' |
. "WHERE type!='meta' " |
. 'ORDER BY tbl_name, type DESC, name;'; |
case 'schemax': |
case 'schema_x': |
/* |
* Use like: |
* $res = $db->query($db->getSpecialQuery('schema_x', |
* array('table' => 'table3'))); |
*/ |
return 'SELECT sql FROM (SELECT * FROM sqlite_master ' |
. 'UNION ALL SELECT * FROM sqlite_temp_master) ' |
. "WHERE tbl_name LIKE '{$args['table']}' " |
. "AND type!='meta' " |
. 'ORDER BY type DESC, name;'; |
case 'alter': |
/* |
* SQLite does not support ALTER TABLE; this is a helper query |
* to handle this. 'table' represents the table name, 'rows' |
* the news rows to create, 'save' the row(s) to keep _with_ |
* the data. |
* |
* Use like: |
* $args = array( |
* 'table' => $table, |
* 'rows' => "id INTEGER PRIMARY KEY, firstname TEXT, surname TEXT, datetime TEXT", |
* 'save' => "NULL, titel, content, datetime" |
* ); |
* $res = $db->query( $db->getSpecialQuery('alter', $args)); |
*/ |
$rows = strtr($args['rows'], $this->keywords); |
$q = array( |
'BEGIN TRANSACTION', |
"CREATE TEMPORARY TABLE {$args['table']}_backup ({$args['rows']})", |
"INSERT INTO {$args['table']}_backup SELECT {$args['save']} FROM {$args['table']}", |
"DROP TABLE {$args['table']}", |
"CREATE TABLE {$args['table']} ({$args['rows']})", |
"INSERT INTO {$args['table']} SELECT {$rows} FROM {$args['table']}_backup", |
"DROP TABLE {$args['table']}_backup", |
'COMMIT', |
); |
/* |
* This is a dirty hack, since the above query will not get |
* executed with a single query call so here the query method |
* will be called directly and return a select instead. |
*/ |
foreach ($q as $query) { |
$this->query($query); |
} |
return "SELECT * FROM {$args['table']};"; |
default: |
return null; |
} |
} |
// }}} |
} |
/* |
* Local variables: |
* tab-width: 4 |
* c-basic-offset: 4 |
* End: |
*/ |
?> |
/branches/v1.3-critias/bibliotheque/pear/DB/oci8.php |
---|
New file |
0,0 → 1,1158 |
<?php |
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */ |
/** |
* The PEAR DB driver for PHP's oci8 extension |
* for interacting with Oracle databases |
* |
* PHP version 5 |
* |
* LICENSE: This source file is subject to version 3.0 of the PHP license |
* that is available through the world-wide-web at the following URI: |
* http://www.php.net/license/3_0.txt. If you did not receive a copy of |
* the PHP License and are unable to obtain it through the web, please |
* send a note to license@php.net so we can mail you a copy immediately. |
* |
* @category Database |
* @package DB |
* @author James L. Pine <jlp@valinux.com> |
* @author Daniel Convissor <danielc@php.net> |
* @copyright 1997-2007 The PHP Group |
* @license http://www.php.net/license/3_0.txt PHP License 3.0 |
* @version CVS: $Id$ |
* @link http://pear.php.net/package/DB |
*/ |
/** |
* Obtain the DB_common class so it can be extended from |
*/ |
require_once 'DB/common.php'; |
/** |
* The methods PEAR DB uses to interact with PHP's oci8 extension |
* for interacting with Oracle databases |
* |
* Definitely works with versions 8 and 9 of Oracle. |
* |
* These methods overload the ones declared in DB_common. |
* |
* Be aware... OCIError() only appears to return anything when given a |
* statement, so functions return the generic DB_ERROR instead of more |
* useful errors that have to do with feedback from the database. |
* |
* @category Database |
* @package DB |
* @author James L. Pine <jlp@valinux.com> |
* @author Daniel Convissor <danielc@php.net> |
* @copyright 1997-2007 The PHP Group |
* @license http://www.php.net/license/3_0.txt PHP License 3.0 |
* @version Release: 1.9.2 |
* @link http://pear.php.net/package/DB |
*/ |
class DB_oci8 extends DB_common |
{ |
// {{{ properties |
/** |
* The DB driver type (mysql, oci8, odbc, etc.) |
* @var string |
*/ |
var $phptype = 'oci8'; |
/** |
* The database syntax variant to be used (db2, access, etc.), if any |
* @var string |
*/ |
var $dbsyntax = 'oci8'; |
/** |
* The capabilities of this DB implementation |
* |
* The 'new_link' element contains the PHP version that first provided |
* new_link support for this DBMS. Contains false if it's unsupported. |
* |
* Meaning of the 'limit' element: |
* + 'emulate' = emulate with fetch row by number |
* + 'alter' = alter the query |
* + false = skip rows |
* |
* @var array |
*/ |
var $features = array( |
'limit' => 'alter', |
'new_link' => '5.0.0', |
'numrows' => 'subquery', |
'pconnect' => true, |
'prepare' => true, |
'ssl' => false, |
'transactions' => true, |
); |
/** |
* A mapping of native error codes to DB error codes |
* @var array |
*/ |
var $errorcode_map = array( |
1 => DB_ERROR_CONSTRAINT, |
900 => DB_ERROR_SYNTAX, |
904 => DB_ERROR_NOSUCHFIELD, |
913 => DB_ERROR_VALUE_COUNT_ON_ROW, |
921 => DB_ERROR_SYNTAX, |
923 => DB_ERROR_SYNTAX, |
942 => DB_ERROR_NOSUCHTABLE, |
955 => DB_ERROR_ALREADY_EXISTS, |
1400 => DB_ERROR_CONSTRAINT_NOT_NULL, |
1401 => DB_ERROR_INVALID, |
1407 => DB_ERROR_CONSTRAINT_NOT_NULL, |
1418 => DB_ERROR_NOT_FOUND, |
1476 => DB_ERROR_DIVZERO, |
1722 => DB_ERROR_INVALID_NUMBER, |
2289 => DB_ERROR_NOSUCHTABLE, |
2291 => DB_ERROR_CONSTRAINT, |
2292 => DB_ERROR_CONSTRAINT, |
2449 => DB_ERROR_CONSTRAINT, |
12899 => DB_ERROR_INVALID, |
); |
/** |
* The raw database connection created by PHP |
* @var resource |
*/ |
var $connection; |
/** |
* The DSN information for connecting to a database |
* @var array |
*/ |
var $dsn = array(); |
/** |
* Should data manipulation queries be committed automatically? |
* @var bool |
* @access private |
*/ |
var $autocommit = true; |
/** |
* Stores the $data passed to execute() in the oci8 driver |
* |
* Gets reset to array() when simpleQuery() is run. |
* |
* Needed in case user wants to call numRows() after prepare/execute |
* was used. |
* |
* @var array |
* @access private |
*/ |
var $_data = array(); |
/** |
* The result or statement handle from the most recently executed query |
* @var resource |
*/ |
var $last_stmt; |
/** |
* Is the given prepared statement a data manipulation query? |
* @var array |
* @access private |
*/ |
var $manip_query = array(); |
/** |
* Store of prepared SQL queries. |
* @var array |
* @access private |
*/ |
var $_prepared_queries = array(); |
// }}} |
// {{{ constructor |
/** |
* This constructor calls <kbd>parent::__construct()</kbd> |
* |
* @return void |
*/ |
function __construct() |
{ |
parent::__construct(); |
} |
// }}} |
// {{{ connect() |
/** |
* Connect to the database server, log in and open the database |
* |
* Don't call this method directly. Use DB::connect() instead. |
* |
* If PHP is at version 5.0.0 or greater: |
* + Generally, oci_connect() or oci_pconnect() are used. |
* + But if the new_link DSN option is set to true, oci_new_connect() |
* is used. |
* |
* When using PHP version 4.x, OCILogon() or OCIPLogon() are used. |
* |
* PEAR DB's oci8 driver supports the following extra DSN options: |
* + charset The character set to be used on the connection. |
* Only used if PHP is at version 5.0.0 or greater |
* and the Oracle server is at 9.2 or greater. |
* Available since PEAR DB 1.7.0. |
* + new_link If set to true, causes subsequent calls to |
* connect() to return a new connection link |
* instead of the existing one. WARNING: this is |
* not portable to other DBMS's. |
* Available since PEAR DB 1.7.0. |
* |
* @param array $dsn the data source name |
* @param bool $persistent should the connection be persistent? |
* |
* @return int DB_OK on success. A DB_Error object on failure. |
*/ |
function connect($dsn, $persistent = false) |
{ |
if (!PEAR::loadExtension('oci8')) { |
return $this->raiseError(DB_ERROR_EXTENSION_NOT_FOUND); |
} |
$this->dsn = $dsn; |
if ($dsn['dbsyntax']) { |
$this->dbsyntax = $dsn['dbsyntax']; |
} |
// Backwards compatibility with DB < 1.7.0 |
if (empty($dsn['database']) && !empty($dsn['hostspec'])) { |
$db = $dsn['hostspec']; |
} else { |
$db = $dsn['database']; |
} |
if (function_exists('oci_connect')) { |
if (isset($dsn['new_link']) |
&& ($dsn['new_link'] == 'true' || $dsn['new_link'] === true)) |
{ |
$connect_function = 'oci_new_connect'; |
} else { |
$connect_function = $persistent ? 'oci_pconnect' |
: 'oci_connect'; |
} |
if (isset($this->dsn['port']) && $this->dsn['port']) { |
$db = '//'.$db.':'.$this->dsn['port']; |
} |
$char = empty($dsn['charset']) ? null : $dsn['charset']; |
$this->connection = @$connect_function($dsn['username'], |
$dsn['password'], |
$db, |
$char); |
$error = OCIError(); |
if (!empty($error) && $error['code'] == 12541) { |
// Couldn't find TNS listener. Try direct connection. |
$this->connection = @$connect_function($dsn['username'], |
$dsn['password'], |
null, |
$char); |
} |
} else { |
$connect_function = $persistent ? 'OCIPLogon' : 'OCILogon'; |
if ($db) { |
$this->connection = @$connect_function($dsn['username'], |
$dsn['password'], |
$db); |
} elseif ($dsn['username'] || $dsn['password']) { |
$this->connection = @$connect_function($dsn['username'], |
$dsn['password']); |
} |
} |
if (!$this->connection) { |
$error = OCIError(); |
$error = (is_array($error)) ? $error['message'] : null; |
return $this->raiseError(DB_ERROR_CONNECT_FAILED, |
null, null, null, |
$error); |
} |
return DB_OK; |
} |
// }}} |
// {{{ disconnect() |
/** |
* Disconnects from the database server |
* |
* @return bool TRUE on success, FALSE on failure |
*/ |
function disconnect() |
{ |
if (function_exists('oci_close')) { |
$ret = @oci_close($this->connection); |
} else { |
$ret = @OCILogOff($this->connection); |
} |
$this->connection = null; |
return $ret; |
} |
// }}} |
// {{{ simpleQuery() |
/** |
* Sends a query to the database server |
* |
* To determine how many rows of a result set get buffered using |
* ocisetprefetch(), see the "result_buffering" option in setOptions(). |
* This option was added in Release 1.7.0. |
* |
* @param string the SQL query string |
* |
* @return mixed + a PHP result resrouce for successful SELECT queries |
* + the DB_OK constant for other successful queries |
* + a DB_Error object on failure |
*/ |
function simpleQuery($query) |
{ |
$this->_data = array(); |
$this->last_parameters = array(); |
$this->last_query = $query; |
$query = $this->modifyQuery($query); |
$result = @OCIParse($this->connection, $query); |
if (!$result) { |
return $this->oci8RaiseError(); |
} |
if ($this->autocommit) { |
$success = @OCIExecute($result,OCI_COMMIT_ON_SUCCESS); |
} else { |
$success = @OCIExecute($result,OCI_DEFAULT); |
} |
if (!$success) { |
return $this->oci8RaiseError($result); |
} |
$this->last_stmt = $result; |
if ($this->_checkManip($query)) { |
return DB_OK; |
} else { |
@ocisetprefetch($result, $this->options['result_buffering']); |
return $result; |
} |
} |
// }}} |
// {{{ nextResult() |
/** |
* Move the internal oracle result pointer to the next available result |
* |
* @param a valid oci8 result resource |
* |
* @access public |
* |
* @return true if a result is available otherwise return false |
*/ |
function nextResult($result) |
{ |
return false; |
} |
// }}} |
// {{{ fetchInto() |
/** |
* Places a row from the result set into the given array |
* |
* Formating of the array and the data therein are configurable. |
* See DB_result::fetchInto() for more information. |
* |
* This method is not meant to be called directly. Use |
* DB_result::fetchInto() instead. It can't be declared "protected" |
* because DB_result is a separate object. |
* |
* @param resource $result the query result resource |
* @param array $arr the referenced array to put the data in |
* @param int $fetchmode how the resulting array should be indexed |
* @param int $rownum the row number to fetch (0 = first row) |
* |
* @return mixed DB_OK on success, NULL when the end of a result set is |
* reached or on failure |
* |
* @see DB_result::fetchInto() |
*/ |
function fetchInto($result, &$arr, $fetchmode, $rownum = null) |
{ |
if ($rownum !== null) { |
return $this->raiseError(DB_ERROR_NOT_CAPABLE); |
} |
if ($fetchmode & DB_FETCHMODE_ASSOC) { |
$moredata = @OCIFetchInto($result,$arr,OCI_ASSOC+OCI_RETURN_NULLS+OCI_RETURN_LOBS); |
if ($this->options['portability'] & DB_PORTABILITY_LOWERCASE && |
$moredata) |
{ |
$arr = array_change_key_case($arr, CASE_LOWER); |
} |
} else { |
$moredata = OCIFetchInto($result,$arr,OCI_RETURN_NULLS+OCI_RETURN_LOBS); |
} |
if (!$moredata) { |
return null; |
} |
if ($this->options['portability'] & DB_PORTABILITY_RTRIM) { |
$this->_rtrimArrayValues($arr); |
} |
if ($this->options['portability'] & DB_PORTABILITY_NULL_TO_EMPTY) { |
$this->_convertNullArrayValuesToEmpty($arr); |
} |
return DB_OK; |
} |
// }}} |
// {{{ freeResult() |
/** |
* Deletes the result set and frees the memory occupied by the result set |
* |
* This method is not meant to be called directly. Use |
* DB_result::free() instead. It can't be declared "protected" |
* because DB_result is a separate object. |
* |
* @param resource $result PHP's query result resource |
* |
* @return bool TRUE on success, FALSE if $result is invalid |
* |
* @see DB_result::free() |
*/ |
function freeResult($result) |
{ |
return is_resource($result) ? OCIFreeStatement($result) : false; |
} |
/** |
* Frees the internal resources associated with a prepared query |
* |
* @param resource $stmt the prepared statement's resource |
* @param bool $free_resource should the PHP resource be freed too? |
* Use false if you need to get data |
* from the result set later. |
* |
* @return bool TRUE on success, FALSE if $result is invalid |
* |
* @see DB_oci8::prepare() |
*/ |
function freePrepared($stmt, $free_resource = true) |
{ |
if (!is_resource($stmt)) { |
return false; |
} |
if ($free_resource) { |
@ocifreestatement($stmt); |
} |
if (isset($this->prepare_types[(int)$stmt])) { |
unset($this->prepare_types[(int)$stmt]); |
unset($this->manip_query[(int)$stmt]); |
unset($this->_prepared_queries[(int)$stmt]); |
} else { |
return false; |
} |
return true; |
} |
// }}} |
// {{{ numRows() |
/** |
* Gets the number of rows in a result set |
* |
* Only works if the DB_PORTABILITY_NUMROWS portability option |
* is turned on. |
* |
* This method is not meant to be called directly. Use |
* DB_result::numRows() instead. It can't be declared "protected" |
* because DB_result is a separate object. |
* |
* @param resource $result PHP's query result resource |
* |
* @return int the number of rows. A DB_Error object on failure. |
* |
* @see DB_result::numRows(), DB_common::setOption() |
*/ |
function numRows($result) |
{ |
// emulate numRows for Oracle. yuck. |
if ($this->options['portability'] & DB_PORTABILITY_NUMROWS && |
$result === $this->last_stmt) |
{ |
$countquery = 'SELECT COUNT(*) FROM ('.$this->last_query.')'; |
$save_query = $this->last_query; |
$save_stmt = $this->last_stmt; |
$count = $this->query($countquery); |
// Restore the last query and statement. |
$this->last_query = $save_query; |
$this->last_stmt = $save_stmt; |
if (DB::isError($count) || |
DB::isError($row = $count->fetchRow(DB_FETCHMODE_ORDERED))) |
{ |
return $this->raiseError(DB_ERROR_NOT_CAPABLE); |
} |
return $row[0]; |
} |
return $this->raiseError(DB_ERROR_NOT_CAPABLE); |
} |
// }}} |
// {{{ numCols() |
/** |
* Gets the number of columns in a result set |
* |
* This method is not meant to be called directly. Use |
* DB_result::numCols() instead. It can't be declared "protected" |
* because DB_result is a separate object. |
* |
* @param resource $result PHP's query result resource |
* |
* @return int the number of columns. A DB_Error object on failure. |
* |
* @see DB_result::numCols() |
*/ |
function numCols($result) |
{ |
$cols = @OCINumCols($result); |
if (!$cols) { |
return $this->oci8RaiseError($result); |
} |
return $cols; |
} |
// }}} |
// {{{ prepare() |
/** |
* Prepares a query for multiple execution with execute(). |
* |
* With oci8, this is emulated. |
* |
* prepare() requires a generic query as string like <code> |
* INSERT INTO numbers VALUES (?, ?, ?) |
* </code>. The <kbd>?</kbd> characters are placeholders. |
* |
* Three types of placeholders can be used: |
* + <kbd>?</kbd> a quoted scalar value, i.e. strings, integers |
* + <kbd>!</kbd> value is inserted 'as is' |
* + <kbd>&</kbd> requires a file name. The file's contents get |
* inserted into the query (i.e. saving binary |
* data in a db) |
* |
* Use backslashes to escape placeholder characters if you don't want |
* them to be interpreted as placeholders. Example: <code> |
* "UPDATE foo SET col=? WHERE col='over \& under'" |
* </code> |
* |
* @param string $query the query to be prepared |
* |
* @return mixed DB statement resource on success. DB_Error on failure. |
* |
* @see DB_oci8::execute() |
*/ |
function prepare($query) |
{ |
$tokens = preg_split('/((?<!\\\)[&?!])/', $query, -1, |
PREG_SPLIT_DELIM_CAPTURE); |
$binds = count($tokens) - 1; |
$token = 0; |
$types = array(); |
$newquery = ''; |
foreach ($tokens as $key => $val) { |
switch ($val) { |
case '?': |
$types[$token++] = DB_PARAM_SCALAR; |
unset($tokens[$key]); |
break; |
case '&': |
$types[$token++] = DB_PARAM_OPAQUE; |
unset($tokens[$key]); |
break; |
case '!': |
$types[$token++] = DB_PARAM_MISC; |
unset($tokens[$key]); |
break; |
default: |
$tokens[$key] = preg_replace('/\\\([&?!])/', "\\1", $val); |
if ($key != $binds) { |
$newquery .= $tokens[$key] . ':bind' . $token; |
} else { |
$newquery .= $tokens[$key]; |
} |
} |
} |
$this->last_query = $query; |
$newquery = $this->modifyQuery($newquery); |
if (!$stmt = @OCIParse($this->connection, $newquery)) { |
return $this->oci8RaiseError(); |
} |
$this->prepare_types[(int)$stmt] = $types; |
$this->manip_query[(int)$stmt] = DB::isManip($query); |
$this->_prepared_queries[(int)$stmt] = $newquery; |
return $stmt; |
} |
// }}} |
// {{{ execute() |
/** |
* Executes a DB statement prepared with prepare(). |
* |
* To determine how many rows of a result set get buffered using |
* ocisetprefetch(), see the "result_buffering" option in setOptions(). |
* This option was added in Release 1.7.0. |
* |
* @param resource $stmt a DB statement resource returned from prepare() |
* @param mixed $data array, string or numeric data to be used in |
* execution of the statement. Quantity of items |
* passed must match quantity of placeholders in |
* query: meaning 1 for non-array items or the |
* quantity of elements in the array. |
* |
* @return mixed returns an oic8 result resource for successful SELECT |
* queries, DB_OK for other successful queries. |
* A DB error object is returned on failure. |
* |
* @see DB_oci8::prepare() |
*/ |
function &execute($stmt, $data = array()) |
{ |
$data = (array)$data; |
$this->last_parameters = $data; |
$this->last_query = $this->_prepared_queries[(int)$stmt]; |
$this->_data = $data; |
$types = $this->prepare_types[(int)$stmt]; |
if (count($types) != count($data)) { |
$tmp = $this->raiseError(DB_ERROR_MISMATCH); |
return $tmp; |
} |
$i = 0; |
foreach ($data as $key => $value) { |
if ($types[$i] == DB_PARAM_MISC) { |
/* |
* Oracle doesn't seem to have the ability to pass a |
* parameter along unchanged, so strip off quotes from start |
* and end, plus turn two single quotes to one single quote, |
* in order to avoid the quotes getting escaped by |
* Oracle and ending up in the database. |
*/ |
$data[$key] = preg_replace("/^'(.*)'$/", "\\1", $data[$key]); |
$data[$key] = str_replace("''", "'", $data[$key]); |
} elseif ($types[$i] == DB_PARAM_OPAQUE) { |
$fp = @fopen($data[$key], 'rb'); |
if (!$fp) { |
$tmp = $this->raiseError(DB_ERROR_ACCESS_VIOLATION); |
return $tmp; |
} |
$data[$key] = fread($fp, filesize($data[$key])); |
fclose($fp); |
} elseif ($types[$i] == DB_PARAM_SCALAR) { |
// Floats have to be converted to a locale-neutral |
// representation. |
if (is_float($data[$key])) { |
$data[$key] = $this->quoteFloat($data[$key]); |
} |
} |
if (!@OCIBindByName($stmt, ':bind' . $i, $data[$key], -1)) { |
$tmp = $this->oci8RaiseError($stmt); |
return $tmp; |
} |
$this->last_query = preg_replace("/:bind$i(?!\d)/", |
$this->quoteSmart($data[$key]), $this->last_query, 1); |
$i++; |
} |
if ($this->autocommit) { |
$success = @OCIExecute($stmt, OCI_COMMIT_ON_SUCCESS); |
} else { |
$success = @OCIExecute($stmt, OCI_DEFAULT); |
} |
if (!$success) { |
$tmp = $this->oci8RaiseError($stmt); |
return $tmp; |
} |
$this->last_stmt = $stmt; |
if ($this->manip_query[(int)$stmt] || $this->_next_query_manip) { |
$this->_last_query_manip = true; |
$this->_next_query_manip = false; |
$tmp = DB_OK; |
} else { |
$this->_last_query_manip = false; |
@ocisetprefetch($stmt, $this->options['result_buffering']); |
$tmp = new DB_result($this, $stmt); |
} |
return $tmp; |
} |
// }}} |
// {{{ autoCommit() |
/** |
* Enables or disables automatic commits |
* |
* @param bool $onoff true turns it on, false turns it off |
* |
* @return int DB_OK on success. A DB_Error object if the driver |
* doesn't support auto-committing transactions. |
*/ |
function autoCommit($onoff = false) |
{ |
$this->autocommit = (bool)$onoff;; |
return DB_OK; |
} |
// }}} |
// {{{ commit() |
/** |
* Commits the current transaction |
* |
* @return int DB_OK on success. A DB_Error object on failure. |
*/ |
function commit() |
{ |
$result = @OCICommit($this->connection); |
if (!$result) { |
return $this->oci8RaiseError(); |
} |
return DB_OK; |
} |
// }}} |
// {{{ rollback() |
/** |
* Reverts the current transaction |
* |
* @return int DB_OK on success. A DB_Error object on failure. |
*/ |
function rollback() |
{ |
$result = @OCIRollback($this->connection); |
if (!$result) { |
return $this->oci8RaiseError(); |
} |
return DB_OK; |
} |
// }}} |
// {{{ affectedRows() |
/** |
* Determines the number of rows affected by a data maniuplation query |
* |
* 0 is returned for queries that don't manipulate data. |
* |
* @return int the number of rows. A DB_Error object on failure. |
*/ |
function affectedRows() |
{ |
if ($this->last_stmt === false) { |
return $this->oci8RaiseError(); |
} |
$result = @OCIRowCount($this->last_stmt); |
if ($result === false) { |
return $this->oci8RaiseError($this->last_stmt); |
} |
return $result; |
} |
// }}} |
// {{{ modifyQuery() |
/** |
* Changes a query string for various DBMS specific reasons |
* |
* "SELECT 2+2" must be "SELECT 2+2 FROM dual" in Oracle. |
* |
* @param string $query the query string to modify |
* |
* @return string the modified query string |
* |
* @access protected |
*/ |
function modifyQuery($query) |
{ |
if (preg_match('/^\s*SELECT/i', $query) && |
!preg_match('/\sFROM\s/i', $query)) { |
$query .= ' FROM dual'; |
} |
return $query; |
} |
// }}} |
// {{{ modifyLimitQuery() |
/** |
* Adds LIMIT clauses to a query string according to current DBMS standards |
* |
* @param string $query the query to modify |
* @param int $from the row to start to fetching (0 = the first row) |
* @param int $count the numbers of rows to fetch |
* @param mixed $params array, string or numeric data to be used in |
* execution of the statement. Quantity of items |
* passed must match quantity of placeholders in |
* query: meaning 1 placeholder for non-array |
* parameters or 1 placeholder per array element. |
* |
* @return string the query string with LIMIT clauses added |
* |
* @access protected |
*/ |
function modifyLimitQuery($query, $from, $count, $params = array()) |
{ |
// Let Oracle return the name of the columns instead of |
// coding a "home" SQL parser |
if (count($params)) { |
$result = $this->prepare("SELECT * FROM ($query) " |
. 'WHERE NULL = NULL'); |
$tmp = $this->execute($result, $params); |
} else { |
$q_fields = "SELECT * FROM ($query) WHERE NULL = NULL"; |
if (!$result = @OCIParse($this->connection, $q_fields)) { |
$this->last_query = $q_fields; |
return $this->oci8RaiseError(); |
} |
if (!@OCIExecute($result, OCI_DEFAULT)) { |
$this->last_query = $q_fields; |
return $this->oci8RaiseError($result); |
} |
} |
$ncols = OCINumCols($result); |
$cols = array(); |
for ( $i = 1; $i <= $ncols; $i++ ) { |
$cols[] = '"' . OCIColumnName($result, $i) . '"'; |
} |
$fields = implode(', ', $cols); |
// XXX Test that (tip by John Lim) |
//if (preg_match('/^\s*SELECT\s+/is', $query, $match)) { |
// // Introduce the FIRST_ROWS Oracle query optimizer |
// $query = substr($query, strlen($match[0]), strlen($query)); |
// $query = "SELECT /* +FIRST_ROWS */ " . $query; |
//} |
// Construct the query |
// more at: http://marc.theaimsgroup.com/?l=php-db&m=99831958101212&w=2 |
// Perhaps this could be optimized with the use of Unions |
$query = "SELECT $fields FROM". |
" (SELECT rownum as linenum, $fields FROM". |
" ($query)". |
' WHERE rownum <= '. ($from + $count) . |
') WHERE linenum >= ' . ++$from; |
return $query; |
} |
// }}} |
// {{{ nextId() |
/** |
* Returns the next free id in a sequence |
* |
* @param string $seq_name name of the sequence |
* @param boolean $ondemand when true, the seqence is automatically |
* created if it does not exist |
* |
* @return int the next id number in the sequence. |
* A DB_Error object on failure. |
* |
* @see DB_common::nextID(), DB_common::getSequenceName(), |
* DB_oci8::createSequence(), DB_oci8::dropSequence() |
*/ |
function nextId($seq_name, $ondemand = true) |
{ |
$seqname = $this->getSequenceName($seq_name); |
$repeat = 0; |
do { |
$this->expectError(DB_ERROR_NOSUCHTABLE); |
$result = $this->query("SELECT ${seqname}.nextval FROM dual"); |
$this->popExpect(); |
if ($ondemand && DB::isError($result) && |
$result->getCode() == DB_ERROR_NOSUCHTABLE) { |
$repeat = 1; |
$result = $this->createSequence($seq_name); |
if (DB::isError($result)) { |
return $this->raiseError($result); |
} |
} else { |
$repeat = 0; |
} |
} while ($repeat); |
if (DB::isError($result)) { |
return $this->raiseError($result); |
} |
$arr = $result->fetchRow(DB_FETCHMODE_ORDERED); |
return $arr[0]; |
} |
/** |
* Creates a new sequence |
* |
* @param string $seq_name name of the new sequence |
* |
* @return int DB_OK on success. A DB_Error object on failure. |
* |
* @see DB_common::createSequence(), DB_common::getSequenceName(), |
* DB_oci8::nextID(), DB_oci8::dropSequence() |
*/ |
function createSequence($seq_name) |
{ |
return $this->query('CREATE SEQUENCE ' |
. $this->getSequenceName($seq_name)); |
} |
// }}} |
// {{{ dropSequence() |
/** |
* Deletes a sequence |
* |
* @param string $seq_name name of the sequence to be deleted |
* |
* @return int DB_OK on success. A DB_Error object on failure. |
* |
* @see DB_common::dropSequence(), DB_common::getSequenceName(), |
* DB_oci8::nextID(), DB_oci8::createSequence() |
*/ |
function dropSequence($seq_name) |
{ |
return $this->query('DROP SEQUENCE ' |
. $this->getSequenceName($seq_name)); |
} |
// }}} |
// {{{ oci8RaiseError() |
/** |
* Produces a DB_Error object regarding the current problem |
* |
* @param int $errno if the error is being manually raised pass a |
* DB_ERROR* constant here. If this isn't passed |
* the error information gathered from the DBMS. |
* |
* @return object the DB_Error object |
* |
* @see DB_common::raiseError(), |
* DB_oci8::errorNative(), DB_oci8::errorCode() |
*/ |
function oci8RaiseError($errno = null) |
{ |
if ($errno === null) { |
$error = @OCIError($this->connection); |
return $this->raiseError($this->errorCode($error['code']), |
null, null, null, $error['message']); |
} elseif (is_resource($errno)) { |
$error = @OCIError($errno); |
return $this->raiseError($this->errorCode($error['code']), |
null, null, null, $error['message']); |
} |
return $this->raiseError($this->errorCode($errno)); |
} |
// }}} |
// {{{ errorNative() |
/** |
* Gets the DBMS' native error code produced by the last query |
* |
* @return int the DBMS' error code. FALSE if the code could not be |
* determined |
*/ |
function errorNative() |
{ |
if (is_resource($this->last_stmt)) { |
$error = @OCIError($this->last_stmt); |
} else { |
$error = @OCIError($this->connection); |
} |
if (is_array($error)) { |
return $error['code']; |
} |
return false; |
} |
// }}} |
// {{{ tableInfo() |
/** |
* Returns information about a table or a result set |
* |
* NOTE: only supports 'table' and 'flags' if <var>$result</var> |
* is a table name. |
* |
* NOTE: flags won't contain index information. |
* |
* @param object|string $result DB_result object from a query or a |
* string containing the name of a table. |
* While this also accepts a query result |
* resource identifier, this behavior is |
* deprecated. |
* @param int $mode a valid tableInfo mode |
* |
* @return array an associative array with the information requested. |
* A DB_Error object on failure. |
* |
* @see DB_common::tableInfo() |
*/ |
function tableInfo($result, $mode = null) |
{ |
if ($this->options['portability'] & DB_PORTABILITY_LOWERCASE) { |
$case_func = 'strtolower'; |
} else { |
$case_func = 'strval'; |
} |
$res = array(); |
if (is_string($result)) { |
/* |
* Probably received a table name. |
* Create a result resource identifier. |
*/ |
$result = strtoupper($result); |
$q_fields = 'SELECT column_name, data_type, data_length, ' |
. 'nullable ' |
. 'FROM user_tab_columns ' |
. "WHERE table_name='$result' ORDER BY column_id"; |
$this->last_query = $q_fields; |
if (!$stmt = @OCIParse($this->connection, $q_fields)) { |
return $this->oci8RaiseError(DB_ERROR_NEED_MORE_DATA); |
} |
if (!@OCIExecute($stmt, OCI_DEFAULT)) { |
return $this->oci8RaiseError($stmt); |
} |
$i = 0; |
while (@OCIFetch($stmt)) { |
$res[$i] = array( |
'table' => $case_func($result), |
'name' => $case_func(@OCIResult($stmt, 1)), |
'type' => @OCIResult($stmt, 2), |
'len' => @OCIResult($stmt, 3), |
'flags' => (@OCIResult($stmt, 4) == 'N') ? 'not_null' : '', |
); |
if ($mode & DB_TABLEINFO_ORDER) { |
$res['order'][$res[$i]['name']] = $i; |
} |
if ($mode & DB_TABLEINFO_ORDERTABLE) { |
$res['ordertable'][$res[$i]['table']][$res[$i]['name']] = $i; |
} |
$i++; |
} |
if ($mode) { |
$res['num_fields'] = $i; |
} |
@OCIFreeStatement($stmt); |
} else { |
if (isset($result->result)) { |
/* |
* Probably received a result object. |
* Extract the result resource identifier. |
*/ |
$result = $result->result; |
} |
$res = array(); |
if ($result === $this->last_stmt) { |
$count = @OCINumCols($result); |
if ($mode) { |
$res['num_fields'] = $count; |
} |
for ($i = 0; $i < $count; $i++) { |
$res[$i] = array( |
'table' => '', |
'name' => $case_func(@OCIColumnName($result, $i+1)), |
'type' => @OCIColumnType($result, $i+1), |
'len' => @OCIColumnSize($result, $i+1), |
'flags' => '', |
); |
if ($mode & DB_TABLEINFO_ORDER) { |
$res['order'][$res[$i]['name']] = $i; |
} |
if ($mode & DB_TABLEINFO_ORDERTABLE) { |
$res['ordertable'][$res[$i]['table']][$res[$i]['name']] = $i; |
} |
} |
} else { |
return $this->raiseError(DB_ERROR_NOT_CAPABLE); |
} |
} |
return $res; |
} |
// }}} |
// {{{ getSpecialQuery() |
/** |
* Obtains the query string needed for listing a given type of objects |
* |
* @param string $type the kind of objects you want to retrieve |
* |
* @return string the SQL query string or null if the driver doesn't |
* support the object type requested |
* |
* @access protected |
* @see DB_common::getListOf() |
*/ |
function getSpecialQuery($type) |
{ |
switch ($type) { |
case 'tables': |
return 'SELECT table_name FROM user_tables'; |
case 'synonyms': |
return 'SELECT synonym_name FROM user_synonyms'; |
case 'views': |
return 'SELECT view_name FROM user_views'; |
default: |
return null; |
} |
} |
// }}} |
// {{{ quoteFloat() |
/** |
* Formats a float value for use within a query in a locale-independent |
* manner. |
* |
* @param float the float value to be quoted. |
* @return string the quoted string. |
* @see DB_common::quoteSmart() |
* @since Method available since release 1.7.8. |
*/ |
function quoteFloat($float) { |
return $this->escapeSimple(str_replace(',', '.', strval(floatval($float)))); |
} |
// }}} |
} |
/* |
* Local variables: |
* tab-width: 4 |
* c-basic-offset: 4 |
* End: |
*/ |
?> |
/branches/v1.3-critias/bibliotheque/pear/DB/ibase.php |
---|
New file |
0,0 → 1,1082 |
<?php |
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */ |
/** |
* The PEAR DB driver for PHP's interbase extension |
* for interacting with Interbase and Firebird databases |
* |
* While this class works with PHP 4, PHP's InterBase extension is |
* unstable in PHP 4. Use PHP 5. |
* |
* PHP version 5 |
* |
* LICENSE: This source file is subject to version 3.0 of the PHP license |
* that is available through the world-wide-web at the following URI: |
* http://www.php.net/license/3_0.txt. If you did not receive a copy of |
* the PHP License and are unable to obtain it through the web, please |
* send a note to license@php.net so we can mail you a copy immediately. |
* |
* @category Database |
* @package DB |
* @author Sterling Hughes <sterling@php.net> |
* @author Daniel Convissor <danielc@php.net> |
* @copyright 1997-2007 The PHP Group |
* @license http://www.php.net/license/3_0.txt PHP License 3.0 |
* @version CVS: $Id$ |
* @link http://pear.php.net/package/DB |
*/ |
/** |
* Obtain the DB_common class so it can be extended from |
*/ |
require_once 'DB/common.php'; |
/** |
* The methods PEAR DB uses to interact with PHP's interbase extension |
* for interacting with Interbase and Firebird databases |
* |
* These methods overload the ones declared in DB_common. |
* |
* While this class works with PHP 4, PHP's InterBase extension is |
* unstable in PHP 4. Use PHP 5. |
* |
* NOTICE: limitQuery() only works for Firebird. |
* |
* @category Database |
* @package DB |
* @author Sterling Hughes <sterling@php.net> |
* @author Daniel Convissor <danielc@php.net> |
* @copyright 1997-2007 The PHP Group |
* @license http://www.php.net/license/3_0.txt PHP License 3.0 |
* @version Release: 1.9.2 |
* @link http://pear.php.net/package/DB |
* @since Class became stable in Release 1.7.0 |
*/ |
class DB_ibase extends DB_common |
{ |
// {{{ properties |
/** |
* The DB driver type (mysql, oci8, odbc, etc.) |
* @var string |
*/ |
var $phptype = 'ibase'; |
/** |
* The database syntax variant to be used (db2, access, etc.), if any |
* @var string |
*/ |
var $dbsyntax = 'ibase'; |
/** |
* The capabilities of this DB implementation |
* |
* The 'new_link' element contains the PHP version that first provided |
* new_link support for this DBMS. Contains false if it's unsupported. |
* |
* Meaning of the 'limit' element: |
* + 'emulate' = emulate with fetch row by number |
* + 'alter' = alter the query |
* + false = skip rows |
* |
* NOTE: only firebird supports limit. |
* |
* @var array |
*/ |
var $features = array( |
'limit' => false, |
'new_link' => false, |
'numrows' => 'emulate', |
'pconnect' => true, |
'prepare' => true, |
'ssl' => false, |
'transactions' => true, |
); |
/** |
* A mapping of native error codes to DB error codes |
* @var array |
*/ |
var $errorcode_map = array( |
-104 => DB_ERROR_SYNTAX, |
-150 => DB_ERROR_ACCESS_VIOLATION, |
-151 => DB_ERROR_ACCESS_VIOLATION, |
-155 => DB_ERROR_NOSUCHTABLE, |
-157 => DB_ERROR_NOSUCHFIELD, |
-158 => DB_ERROR_VALUE_COUNT_ON_ROW, |
-170 => DB_ERROR_MISMATCH, |
-171 => DB_ERROR_MISMATCH, |
-172 => DB_ERROR_INVALID, |
// -204 => // Covers too many errors, need to use regex on msg |
-205 => DB_ERROR_NOSUCHFIELD, |
-206 => DB_ERROR_NOSUCHFIELD, |
-208 => DB_ERROR_INVALID, |
-219 => DB_ERROR_NOSUCHTABLE, |
-297 => DB_ERROR_CONSTRAINT, |
-303 => DB_ERROR_INVALID, |
-413 => DB_ERROR_INVALID_NUMBER, |
-530 => DB_ERROR_CONSTRAINT, |
-551 => DB_ERROR_ACCESS_VIOLATION, |
-552 => DB_ERROR_ACCESS_VIOLATION, |
// -607 => // Covers too many errors, need to use regex on msg |
-625 => DB_ERROR_CONSTRAINT_NOT_NULL, |
-803 => DB_ERROR_CONSTRAINT, |
-804 => DB_ERROR_VALUE_COUNT_ON_ROW, |
// -902 => // Covers too many errors, need to use regex on msg |
-904 => DB_ERROR_CONNECT_FAILED, |
-922 => DB_ERROR_NOSUCHDB, |
-923 => DB_ERROR_CONNECT_FAILED, |
-924 => DB_ERROR_CONNECT_FAILED |
); |
/** |
* The raw database connection created by PHP |
* @var resource |
*/ |
var $connection; |
/** |
* The DSN information for connecting to a database |
* @var array |
*/ |
var $dsn = array(); |
/** |
* The number of rows affected by a data manipulation query |
* @var integer |
* @access private |
*/ |
var $affected = 0; |
/** |
* Should data manipulation queries be committed automatically? |
* @var bool |
* @access private |
*/ |
var $autocommit = true; |
/** |
* The prepared statement handle from the most recently executed statement |
* |
* {@internal Mainly here because the InterBase/Firebird API is only |
* able to retrieve data from result sets if the statemnt handle is |
* still in scope.}} |
* |
* @var resource |
*/ |
var $last_stmt; |
/** |
* Is the given prepared statement a data manipulation query? |
* @var array |
* @access private |
*/ |
var $manip_query = array(); |
// }}} |
// {{{ constructor |
/** |
* This constructor calls <kbd>parent::__construct()</kbd> |
* |
* @return void |
*/ |
function __construct() |
{ |
parent::__construct(); |
} |
// }}} |
// {{{ connect() |
/** |
* Connect to the database server, log in and open the database |
* |
* Don't call this method directly. Use DB::connect() instead. |
* |
* PEAR DB's ibase driver supports the following extra DSN options: |
* + buffers The number of database buffers to allocate for the |
* server-side cache. |
* + charset The default character set for a database. |
* + dialect The default SQL dialect for any statement |
* executed within a connection. Defaults to the |
* highest one supported by client libraries. |
* Functional only with InterBase 6 and up. |
* + role Functional only with InterBase 5 and up. |
* |
* @param array $dsn the data source name |
* @param bool $persistent should the connection be persistent? |
* |
* @return int DB_OK on success. A DB_Error object on failure. |
*/ |
function connect($dsn, $persistent = false) |
{ |
if (!PEAR::loadExtension('interbase')) { |
return $this->raiseError(DB_ERROR_EXTENSION_NOT_FOUND); |
} |
$this->dsn = $dsn; |
if ($dsn['dbsyntax']) { |
$this->dbsyntax = $dsn['dbsyntax']; |
} |
if ($this->dbsyntax == 'firebird') { |
$this->features['limit'] = 'alter'; |
} |
$params = array( |
$dsn['hostspec'] |
? ($dsn['hostspec'] . ':' . $dsn['database']) |
: $dsn['database'], |
$dsn['username'] ? $dsn['username'] : null, |
$dsn['password'] ? $dsn['password'] : null, |
isset($dsn['charset']) ? $dsn['charset'] : null, |
isset($dsn['buffers']) ? $dsn['buffers'] : null, |
isset($dsn['dialect']) ? $dsn['dialect'] : null, |
isset($dsn['role']) ? $dsn['role'] : null, |
); |
$connect_function = $persistent ? 'ibase_pconnect' : 'ibase_connect'; |
$this->connection = @call_user_func_array($connect_function, $params); |
if (!$this->connection) { |
return $this->ibaseRaiseError(DB_ERROR_CONNECT_FAILED); |
} |
return DB_OK; |
} |
// }}} |
// {{{ disconnect() |
/** |
* Disconnects from the database server |
* |
* @return bool TRUE on success, FALSE on failure |
*/ |
function disconnect() |
{ |
$ret = @ibase_close($this->connection); |
$this->connection = null; |
return $ret; |
} |
// }}} |
// {{{ simpleQuery() |
/** |
* Sends a query to the database server |
* |
* @param string the SQL query string |
* |
* @return mixed + a PHP result resrouce for successful SELECT queries |
* + the DB_OK constant for other successful queries |
* + a DB_Error object on failure |
*/ |
function simpleQuery($query) |
{ |
$ismanip = $this->_checkManip($query); |
$this->last_query = $query; |
$query = $this->modifyQuery($query); |
$result = @ibase_query($this->connection, $query); |
if (!$result) { |
return $this->ibaseRaiseError(); |
} |
if ($this->autocommit && $ismanip) { |
@ibase_commit($this->connection); |
} |
if ($ismanip) { |
$this->affected = $result; |
return DB_OK; |
} else { |
$this->affected = 0; |
return $result; |
} |
} |
// }}} |
// {{{ modifyLimitQuery() |
/** |
* Adds LIMIT clauses to a query string according to current DBMS standards |
* |
* Only works with Firebird. |
* |
* @param string $query the query to modify |
* @param int $from the row to start to fetching (0 = the first row) |
* @param int $count the numbers of rows to fetch |
* @param mixed $params array, string or numeric data to be used in |
* execution of the statement. Quantity of items |
* passed must match quantity of placeholders in |
* query: meaning 1 placeholder for non-array |
* parameters or 1 placeholder per array element. |
* |
* @return string the query string with LIMIT clauses added |
* |
* @access protected |
*/ |
function modifyLimitQuery($query, $from, $count, $params = array()) |
{ |
if ($this->dsn['dbsyntax'] == 'firebird') { |
$query = preg_replace('/^([\s(])*SELECT/i', |
"SELECT FIRST $count SKIP $from", $query); |
} |
return $query; |
} |
// }}} |
// {{{ nextResult() |
/** |
* Move the internal ibase result pointer to the next available result |
* |
* @param a valid fbsql result resource |
* |
* @access public |
* |
* @return true if a result is available otherwise return false |
*/ |
function nextResult($result) |
{ |
return false; |
} |
// }}} |
// {{{ fetchInto() |
/** |
* Places a row from the result set into the given array |
* |
* Formating of the array and the data therein are configurable. |
* See DB_result::fetchInto() for more information. |
* |
* This method is not meant to be called directly. Use |
* DB_result::fetchInto() instead. It can't be declared "protected" |
* because DB_result is a separate object. |
* |
* @param resource $result the query result resource |
* @param array $arr the referenced array to put the data in |
* @param int $fetchmode how the resulting array should be indexed |
* @param int $rownum the row number to fetch (0 = first row) |
* |
* @return mixed DB_OK on success, NULL when the end of a result set is |
* reached or on failure |
* |
* @see DB_result::fetchInto() |
*/ |
function fetchInto($result, &$arr, $fetchmode, $rownum = null) |
{ |
if ($rownum !== null) { |
return $this->ibaseRaiseError(DB_ERROR_NOT_CAPABLE); |
} |
if ($fetchmode & DB_FETCHMODE_ASSOC) { |
if (function_exists('ibase_fetch_assoc')) { |
$arr = @ibase_fetch_assoc($result); |
} else { |
$arr = get_object_vars(ibase_fetch_object($result)); |
} |
if ($this->options['portability'] & DB_PORTABILITY_LOWERCASE && $arr) { |
$arr = array_change_key_case($arr, CASE_LOWER); |
} |
} else { |
$arr = @ibase_fetch_row($result); |
} |
if (!$arr) { |
return null; |
} |
if ($this->options['portability'] & DB_PORTABILITY_RTRIM) { |
$this->_rtrimArrayValues($arr); |
} |
if ($this->options['portability'] & DB_PORTABILITY_NULL_TO_EMPTY) { |
$this->_convertNullArrayValuesToEmpty($arr); |
} |
return DB_OK; |
} |
// }}} |
// {{{ freeResult() |
/** |
* Deletes the result set and frees the memory occupied by the result set |
* |
* This method is not meant to be called directly. Use |
* DB_result::free() instead. It can't be declared "protected" |
* because DB_result is a separate object. |
* |
* @param resource $result PHP's query result resource |
* |
* @return bool TRUE on success, FALSE if $result is invalid |
* |
* @see DB_result::free() |
*/ |
function freeResult($result) |
{ |
return is_resource($result) ? ibase_free_result($result) : false; |
} |
// }}} |
// {{{ freeQuery() |
function freeQuery($query) |
{ |
return is_resource($query) ? ibase_free_query($query) : false; |
} |
// }}} |
// {{{ affectedRows() |
/** |
* Determines the number of rows affected by a data maniuplation query |
* |
* 0 is returned for queries that don't manipulate data. |
* |
* @return int the number of rows. A DB_Error object on failure. |
*/ |
function affectedRows() |
{ |
if (is_integer($this->affected)) { |
return $this->affected; |
} |
return $this->ibaseRaiseError(DB_ERROR_NOT_CAPABLE); |
} |
// }}} |
// {{{ numCols() |
/** |
* Gets the number of columns in a result set |
* |
* This method is not meant to be called directly. Use |
* DB_result::numCols() instead. It can't be declared "protected" |
* because DB_result is a separate object. |
* |
* @param resource $result PHP's query result resource |
* |
* @return int the number of columns. A DB_Error object on failure. |
* |
* @see DB_result::numCols() |
*/ |
function numCols($result) |
{ |
$cols = @ibase_num_fields($result); |
if (!$cols) { |
return $this->ibaseRaiseError(); |
} |
return $cols; |
} |
// }}} |
// {{{ prepare() |
/** |
* Prepares a query for multiple execution with execute(). |
* |
* prepare() requires a generic query as string like <code> |
* INSERT INTO numbers VALUES (?, ?, ?) |
* </code>. The <kbd>?</kbd> characters are placeholders. |
* |
* Three types of placeholders can be used: |
* + <kbd>?</kbd> a quoted scalar value, i.e. strings, integers |
* + <kbd>!</kbd> value is inserted 'as is' |
* + <kbd>&</kbd> requires a file name. The file's contents get |
* inserted into the query (i.e. saving binary |
* data in a db) |
* |
* Use backslashes to escape placeholder characters if you don't want |
* them to be interpreted as placeholders. Example: <code> |
* "UPDATE foo SET col=? WHERE col='over \& under'" |
* </code> |
* |
* @param string $query query to be prepared |
* @return mixed DB statement resource on success. DB_Error on failure. |
*/ |
function prepare($query) |
{ |
$tokens = preg_split('/((?<!\\\)[&?!])/', $query, -1, |
PREG_SPLIT_DELIM_CAPTURE); |
$token = 0; |
$types = array(); |
$newquery = ''; |
foreach ($tokens as $key => $val) { |
switch ($val) { |
case '?': |
$types[$token++] = DB_PARAM_SCALAR; |
break; |
case '&': |
$types[$token++] = DB_PARAM_OPAQUE; |
break; |
case '!': |
$types[$token++] = DB_PARAM_MISC; |
break; |
default: |
$tokens[$key] = preg_replace('/\\\([&?!])/', "\\1", $val); |
$newquery .= $tokens[$key] . '?'; |
} |
} |
$newquery = substr($newquery, 0, -1); |
$this->last_query = $query; |
$newquery = $this->modifyQuery($newquery); |
$stmt = @ibase_prepare($this->connection, $newquery); |
if ($stmt === false) { |
$stmt = $this->ibaseRaiseError(); |
} else { |
$this->prepare_types[(int)$stmt] = $types; |
$this->manip_query[(int)$stmt] = DB::isManip($query); |
} |
return $stmt; |
} |
// }}} |
// {{{ execute() |
/** |
* Executes a DB statement prepared with prepare(). |
* |
* @param resource $stmt a DB statement resource returned from prepare() |
* @param mixed $data array, string or numeric data to be used in |
* execution of the statement. Quantity of items |
* passed must match quantity of placeholders in |
* query: meaning 1 for non-array items or the |
* quantity of elements in the array. |
* @return object a new DB_Result or a DB_Error when fail |
* @see DB_ibase::prepare() |
* @access public |
*/ |
function &execute($stmt, $data = array()) |
{ |
$data = (array)$data; |
$this->last_parameters = $data; |
$types = $this->prepare_types[(int)$stmt]; |
if (count($types) != count($data)) { |
$tmp = $this->raiseError(DB_ERROR_MISMATCH); |
return $tmp; |
} |
$i = 0; |
foreach ($data as $key => $value) { |
if ($types[$i] == DB_PARAM_MISC) { |
/* |
* ibase doesn't seem to have the ability to pass a |
* parameter along unchanged, so strip off quotes from start |
* and end, plus turn two single quotes to one single quote, |
* in order to avoid the quotes getting escaped by |
* ibase and ending up in the database. |
*/ |
$data[$key] = preg_replace("/^'(.*)'$/", "\\1", $data[$key]); |
$data[$key] = str_replace("''", "'", $data[$key]); |
} elseif ($types[$i] == DB_PARAM_OPAQUE) { |
$fp = @fopen($data[$key], 'rb'); |
if (!$fp) { |
$tmp = $this->raiseError(DB_ERROR_ACCESS_VIOLATION); |
return $tmp; |
} |
$data[$key] = fread($fp, filesize($data[$key])); |
fclose($fp); |
} |
$i++; |
} |
array_unshift($data, $stmt); |
$res = call_user_func_array('ibase_execute', $data); |
if (!$res) { |
$tmp = $this->ibaseRaiseError(); |
return $tmp; |
} |
/* XXX need this? |
if ($this->autocommit && $this->manip_query[(int)$stmt]) { |
@ibase_commit($this->connection); |
}*/ |
$this->last_stmt = $stmt; |
if ($this->manip_query[(int)$stmt] || $this->_next_query_manip) { |
$this->_last_query_manip = true; |
$this->_next_query_manip = false; |
$tmp = DB_OK; |
} else { |
$this->_last_query_manip = false; |
$tmp = new DB_result($this, $res); |
} |
return $tmp; |
} |
/** |
* Frees the internal resources associated with a prepared query |
* |
* @param resource $stmt the prepared statement's PHP resource |
* @param bool $free_resource should the PHP resource be freed too? |
* Use false if you need to get data |
* from the result set later. |
* |
* @return bool TRUE on success, FALSE if $result is invalid |
* |
* @see DB_ibase::prepare() |
*/ |
function freePrepared($stmt, $free_resource = true) |
{ |
if (!is_resource($stmt)) { |
return false; |
} |
if ($free_resource) { |
@ibase_free_query($stmt); |
} |
unset($this->prepare_tokens[(int)$stmt]); |
unset($this->prepare_types[(int)$stmt]); |
unset($this->manip_query[(int)$stmt]); |
return true; |
} |
// }}} |
// {{{ autoCommit() |
/** |
* Enables or disables automatic commits |
* |
* @param bool $onoff true turns it on, false turns it off |
* |
* @return int DB_OK on success. A DB_Error object if the driver |
* doesn't support auto-committing transactions. |
*/ |
function autoCommit($onoff = false) |
{ |
$this->autocommit = $onoff ? 1 : 0; |
return DB_OK; |
} |
// }}} |
// {{{ commit() |
/** |
* Commits the current transaction |
* |
* @return int DB_OK on success. A DB_Error object on failure. |
*/ |
function commit() |
{ |
return @ibase_commit($this->connection); |
} |
// }}} |
// {{{ rollback() |
/** |
* Reverts the current transaction |
* |
* @return int DB_OK on success. A DB_Error object on failure. |
*/ |
function rollback() |
{ |
return @ibase_rollback($this->connection); |
} |
// }}} |
// {{{ transactionInit() |
function transactionInit($trans_args = 0) |
{ |
return $trans_args |
? @ibase_trans($trans_args, $this->connection) |
: @ibase_trans(); |
} |
// }}} |
// {{{ nextId() |
/** |
* Returns the next free id in a sequence |
* |
* @param string $seq_name name of the sequence |
* @param boolean $ondemand when true, the seqence is automatically |
* created if it does not exist |
* |
* @return int the next id number in the sequence. |
* A DB_Error object on failure. |
* |
* @see DB_common::nextID(), DB_common::getSequenceName(), |
* DB_ibase::createSequence(), DB_ibase::dropSequence() |
*/ |
function nextId($seq_name, $ondemand = true) |
{ |
$sqn = strtoupper($this->getSequenceName($seq_name)); |
$repeat = 0; |
do { |
$this->pushErrorHandling(PEAR_ERROR_RETURN); |
$result = $this->query("SELECT GEN_ID(${sqn}, 1) " |
. 'FROM RDB$GENERATORS ' |
. "WHERE RDB\$GENERATOR_NAME='${sqn}'"); |
$this->popErrorHandling(); |
if ($ondemand && DB::isError($result)) { |
$repeat = 1; |
$result = $this->createSequence($seq_name); |
if (DB::isError($result)) { |
return $result; |
} |
} else { |
$repeat = 0; |
} |
} while ($repeat); |
if (DB::isError($result)) { |
return $this->raiseError($result); |
} |
$arr = $result->fetchRow(DB_FETCHMODE_ORDERED); |
$result->free(); |
return $arr[0]; |
} |
// }}} |
// {{{ createSequence() |
/** |
* Creates a new sequence |
* |
* @param string $seq_name name of the new sequence |
* |
* @return int DB_OK on success. A DB_Error object on failure. |
* |
* @see DB_common::createSequence(), DB_common::getSequenceName(), |
* DB_ibase::nextID(), DB_ibase::dropSequence() |
*/ |
function createSequence($seq_name) |
{ |
$sqn = strtoupper($this->getSequenceName($seq_name)); |
$this->pushErrorHandling(PEAR_ERROR_RETURN); |
$result = $this->query("CREATE GENERATOR ${sqn}"); |
$this->popErrorHandling(); |
return $result; |
} |
// }}} |
// {{{ dropSequence() |
/** |
* Deletes a sequence |
* |
* @param string $seq_name name of the sequence to be deleted |
* |
* @return int DB_OK on success. A DB_Error object on failure. |
* |
* @see DB_common::dropSequence(), DB_common::getSequenceName(), |
* DB_ibase::nextID(), DB_ibase::createSequence() |
*/ |
function dropSequence($seq_name) |
{ |
return $this->query('DELETE FROM RDB$GENERATORS ' |
. "WHERE RDB\$GENERATOR_NAME='" |
. strtoupper($this->getSequenceName($seq_name)) |
. "'"); |
} |
// }}} |
// {{{ _ibaseFieldFlags() |
/** |
* Get the column's flags |
* |
* Supports "primary_key", "unique_key", "not_null", "default", |
* "computed" and "blob". |
* |
* @param string $field_name the name of the field |
* @param string $table_name the name of the table |
* |
* @return string the flags |
* |
* @access private |
*/ |
function _ibaseFieldFlags($field_name, $table_name) |
{ |
$sql = 'SELECT R.RDB$CONSTRAINT_TYPE CTYPE' |
.' FROM RDB$INDEX_SEGMENTS I' |
.' JOIN RDB$RELATION_CONSTRAINTS R ON I.RDB$INDEX_NAME=R.RDB$INDEX_NAME' |
.' WHERE I.RDB$FIELD_NAME=\'' . $field_name . '\'' |
.' AND UPPER(R.RDB$RELATION_NAME)=\'' . strtoupper($table_name) . '\''; |
$result = @ibase_query($this->connection, $sql); |
if (!$result) { |
return $this->ibaseRaiseError(); |
} |
$flags = ''; |
if ($obj = @ibase_fetch_object($result)) { |
@ibase_free_result($result); |
if (isset($obj->CTYPE) && trim($obj->CTYPE) == 'PRIMARY KEY') { |
$flags .= 'primary_key '; |
} |
if (isset($obj->CTYPE) && trim($obj->CTYPE) == 'UNIQUE') { |
$flags .= 'unique_key '; |
} |
} |
$sql = 'SELECT R.RDB$NULL_FLAG AS NFLAG,' |
.' R.RDB$DEFAULT_SOURCE AS DSOURCE,' |
.' F.RDB$FIELD_TYPE AS FTYPE,' |
.' F.RDB$COMPUTED_SOURCE AS CSOURCE' |
.' FROM RDB$RELATION_FIELDS R ' |
.' JOIN RDB$FIELDS F ON R.RDB$FIELD_SOURCE=F.RDB$FIELD_NAME' |
.' WHERE UPPER(R.RDB$RELATION_NAME)=\'' . strtoupper($table_name) . '\'' |
.' AND R.RDB$FIELD_NAME=\'' . $field_name . '\''; |
$result = @ibase_query($this->connection, $sql); |
if (!$result) { |
return $this->ibaseRaiseError(); |
} |
if ($obj = @ibase_fetch_object($result)) { |
@ibase_free_result($result); |
if (isset($obj->NFLAG)) { |
$flags .= 'not_null '; |
} |
if (isset($obj->DSOURCE)) { |
$flags .= 'default '; |
} |
if (isset($obj->CSOURCE)) { |
$flags .= 'computed '; |
} |
if (isset($obj->FTYPE) && $obj->FTYPE == 261) { |
$flags .= 'blob '; |
} |
} |
return trim($flags); |
} |
// }}} |
// {{{ ibaseRaiseError() |
/** |
* Produces a DB_Error object regarding the current problem |
* |
* @param int $errno if the error is being manually raised pass a |
* DB_ERROR* constant here. If this isn't passed |
* the error information gathered from the DBMS. |
* |
* @return object the DB_Error object |
* |
* @see DB_common::raiseError(), |
* DB_ibase::errorNative(), DB_ibase::errorCode() |
*/ |
function &ibaseRaiseError($errno = null) |
{ |
if ($errno === null) { |
$errno = $this->errorCode($this->errorNative()); |
} |
$tmp = $this->raiseError($errno, null, null, null, @ibase_errmsg()); |
return $tmp; |
} |
// }}} |
// {{{ errorNative() |
/** |
* Gets the DBMS' native error code produced by the last query |
* |
* @return int the DBMS' error code. NULL if there is no error code. |
* |
* @since Method available since Release 1.7.0 |
*/ |
function errorNative() |
{ |
if (function_exists('ibase_errcode')) { |
return @ibase_errcode(); |
} |
if (preg_match('/^Dynamic SQL Error SQL error code = ([0-9-]+)/i', |
@ibase_errmsg(), $m)) { |
return (int)$m[1]; |
} |
return null; |
} |
// }}} |
// {{{ errorCode() |
/** |
* Maps native error codes to DB's portable ones |
* |
* @param int $nativecode the error code returned by the DBMS |
* |
* @return int the portable DB error code. Return DB_ERROR if the |
* current driver doesn't have a mapping for the |
* $nativecode submitted. |
* |
* @since Method available since Release 1.7.0 |
*/ |
function errorCode($nativecode = null) |
{ |
if (isset($this->errorcode_map[$nativecode])) { |
return $this->errorcode_map[$nativecode]; |
} |
static $error_regexps; |
if (!isset($error_regexps)) { |
$error_regexps = array( |
'/generator .* is not defined/' |
=> DB_ERROR_SYNTAX, // for compat. w ibase_errcode() |
'/violation of [\w ]+ constraint/i' |
=> DB_ERROR_CONSTRAINT, |
'/table.*(not exist|not found|unknown)/i' |
=> DB_ERROR_NOSUCHTABLE, |
'/table .* already exists/i' |
=> DB_ERROR_ALREADY_EXISTS, |
'/unsuccessful metadata update .* failed attempt to store duplicate value/i' |
=> DB_ERROR_ALREADY_EXISTS, |
'/unsuccessful metadata update .* not found/i' |
=> DB_ERROR_NOT_FOUND, |
'/validation error for column .* value "\*\*\* null/i' |
=> DB_ERROR_CONSTRAINT_NOT_NULL, |
'/conversion error from string/i' |
=> DB_ERROR_INVALID_NUMBER, |
'/no permission for/i' |
=> DB_ERROR_ACCESS_VIOLATION, |
'/arithmetic exception, numeric overflow, or string truncation/i' |
=> DB_ERROR_INVALID, |
'/feature is not supported/i' |
=> DB_ERROR_NOT_CAPABLE, |
); |
} |
$errormsg = @ibase_errmsg(); |
foreach ($error_regexps as $regexp => $code) { |
if (preg_match($regexp, $errormsg)) { |
return $code; |
} |
} |
return DB_ERROR; |
} |
// }}} |
// {{{ tableInfo() |
/** |
* Returns information about a table or a result set |
* |
* NOTE: only supports 'table' and 'flags' if <var>$result</var> |
* is a table name. |
* |
* @param object|string $result DB_result object from a query or a |
* string containing the name of a table. |
* While this also accepts a query result |
* resource identifier, this behavior is |
* deprecated. |
* @param int $mode a valid tableInfo mode |
* |
* @return array an associative array with the information requested. |
* A DB_Error object on failure. |
* |
* @see DB_common::tableInfo() |
*/ |
function tableInfo($result, $mode = null) |
{ |
if (is_string($result)) { |
/* |
* Probably received a table name. |
* Create a result resource identifier. |
*/ |
$id = @ibase_query($this->connection, |
"SELECT * FROM $result WHERE 1=0"); |
$got_string = true; |
} elseif (isset($result->result)) { |
/* |
* Probably received a result object. |
* Extract the result resource identifier. |
*/ |
$id = $result->result; |
$got_string = false; |
} else { |
/* |
* Probably received a result resource identifier. |
* Copy it. |
* Deprecated. Here for compatibility only. |
*/ |
$id = $result; |
$got_string = false; |
} |
if (!is_resource($id)) { |
return $this->ibaseRaiseError(DB_ERROR_NEED_MORE_DATA); |
} |
if ($this->options['portability'] & DB_PORTABILITY_LOWERCASE) { |
$case_func = 'strtolower'; |
} else { |
$case_func = 'strval'; |
} |
$count = @ibase_num_fields($id); |
$res = array(); |
if ($mode) { |
$res['num_fields'] = $count; |
} |
for ($i = 0; $i < $count; $i++) { |
$info = @ibase_field_info($id, $i); |
$res[$i] = array( |
'table' => $got_string ? $case_func($result) : '', |
'name' => $case_func($info['name']), |
'type' => $info['type'], |
'len' => $info['length'], |
'flags' => ($got_string) |
? $this->_ibaseFieldFlags($info['name'], $result) |
: '', |
); |
if ($mode & DB_TABLEINFO_ORDER) { |
$res['order'][$res[$i]['name']] = $i; |
} |
if ($mode & DB_TABLEINFO_ORDERTABLE) { |
$res['ordertable'][$res[$i]['table']][$res[$i]['name']] = $i; |
} |
} |
// free the result only if we were called on a table |
if ($got_string) { |
@ibase_free_result($id); |
} |
return $res; |
} |
// }}} |
// {{{ getSpecialQuery() |
/** |
* Obtains the query string needed for listing a given type of objects |
* |
* @param string $type the kind of objects you want to retrieve |
* |
* @return string the SQL query string or null if the driver doesn't |
* support the object type requested |
* |
* @access protected |
* @see DB_common::getListOf() |
*/ |
function getSpecialQuery($type) |
{ |
switch ($type) { |
case 'tables': |
return 'SELECT DISTINCT R.RDB$RELATION_NAME FROM ' |
. 'RDB$RELATION_FIELDS R WHERE R.RDB$SYSTEM_FLAG=0'; |
case 'views': |
return 'SELECT DISTINCT RDB$VIEW_NAME from RDB$VIEW_RELATIONS'; |
case 'users': |
return 'SELECT DISTINCT RDB$USER FROM RDB$USER_PRIVILEGES'; |
default: |
return null; |
} |
} |
// }}} |
} |
/* |
* Local variables: |
* tab-width: 4 |
* c-basic-offset: 4 |
* End: |
*/ |
?> |
/branches/v1.3-critias/bibliotheque/pear/Auth.php |
---|
New file |
0,0 → 1,869 |
<?php |
/* vim: set expandtab tabstop=4 shiftwidth=4: */ |
// +----------------------------------------------------------------------+ |
// | PHP Version 4 | |
// +----------------------------------------------------------------------+ |
// | Copyright (c) 1997-2003 The PHP Group | |
// +----------------------------------------------------------------------+ |
// | This source file is subject to version 2.02 of the PHP license, | |
// | that is bundled with this package in the file LICENSE, and is | |
// | available at through the world-wide-web at | |
// | http://www.php.net/license/2_02.txt. | |
// | If you did not receive a copy of the PHP license and are unable to | |
// | obtain it through the world-wide-web, please send a note to | |
// | license@php.net so we can mail you a copy immediately. | |
// +----------------------------------------------------------------------+ |
// | Authors: Martin Jansen <mj@php.net> | |
// +----------------------------------------------------------------------+ |
// |
// $Id: Auth.php,v 1.67 2003/10/20 06:36:34 yavo Exp $ |
// |
require_once 'PEAR.php'; |
define('AUTH_IDLED', -1); |
define('AUTH_EXPIRED', -2); |
define('AUTH_WRONG_LOGIN', -3); |
/** |
* PEAR::Auth |
* |
* The PEAR::Auth class provides methods for creating an |
* authentication system using PHP. |
* |
* @author Martin Jansen <mj@php.net> |
* @package Auth |
* @version $Revision: 1.67 $ |
*/ |
class Auth { |
/** |
* Auth lifetime in seconds |
* |
* If this variable is set to 0, auth never expires |
* |
* @var integer |
* @see setExpire(), checkAuth() |
*/ |
var $expire = 0; |
/** |
* Has the auth session expired? |
* |
* @var bool |
* @see checkAuth(), drawLogin() |
*/ |
var $expired = false; |
/** |
* Maximum time of idleness in seconds |
* |
* The difference to $expire is, that the idletime gets |
* refreshed each time, checkAuth() is called. If this |
* variable is set to 0, idle time is never checked. |
* |
* @var integer |
* @see setIdle(), checkAuth() |
*/ |
var $idle = 0; |
/** |
* Is the maximum idletime over? |
* |
* @var boolean |
* @see checkAuth(), drawLogin(); |
*/ |
var $idled = false; |
/** |
* Storage object |
* |
* @var object |
* @see Auth(), validateLogin() |
*/ |
var $storage = ''; |
/** |
* Function defined by the user, that creates the login screen |
* |
* @var string |
*/ |
var $loginFunction = ''; |
/** |
* Should the login form be displayed? |
* |
* @var bool |
* @see setShowlogin() |
*/ |
var $showLogin = true; |
/** |
* Current authentication status |
* |
* @var string |
*/ |
var $status = ''; |
/** |
* Username |
* |
* @var string |
*/ |
var $username = ''; |
/** |
* Password |
* |
* @var string |
*/ |
var $password = ''; |
/** |
* Login callback function name |
* |
* @var string |
* @see setLoginCallback() |
*/ |
var $loginCallback = ''; |
/** |
* Failed Login callback function name |
* |
* @var string |
* @see setLoginFailedCallback() |
*/ |
var $loginFailedCallback = ''; |
/** |
* Logout callback function name |
* |
* @var string |
* @see setLogoutCallback() |
*/ |
var $logoutCallback = ''; |
/** |
* Auth session-array name |
* |
* @var string |
*/ |
var $_sessionName = '_authsession'; |
/** |
* Package Version |
* |
* @var string |
*/ |
var $version = "1.2.3"; |
// {{{ Constructor |
/** |
* Constructor |
* |
* Set up the storage driver. |
* |
* @param string Type of the storage driver |
* @param mixed Additional options for the storage driver |
* (example: if you are using DB as the storage |
* driver, you have to pass the dsn string here) |
* |
* @param string Name of the function that creates the login form |
* @param boolean Should the login form be displayed if neccessary? |
* @return void |
*/ |
function Auth($storageDriver, $options = '', $loginFunction = '', $showLogin = true) |
{ |
if (!empty($options['sessionName'])) { |
$this->_sessionName = $options['sessionName']; |
unset($options['sessionName']); |
} |
if ($loginFunction != '' && is_callable($loginFunction)) { |
$this->loginFunction = $loginFunction; |
} |
if (is_bool($showLogin)) { |
$this->showLogin = $showLogin; |
} |
if (is_object($storageDriver)) { |
$this->storage =& $storageDriver; |
} else { |
$this->storage = $this->_factory($storageDriver, $options); |
} |
// Pass a reference to auth to the container, ugly but works |
// this is used by the DB container to use method setAuthData not staticaly. |
$this->storage->_auth_obj =& $this; |
} |
// }}} |
// {{{ _factory() |
/** |
* Return a storage driver based on $driver and $options |
* |
* @access private |
* @static |
* @param string $driver Type of storage class to return |
* @param string $options Optional parameters for the storage class |
* @return object Object Storage object |
*/ |
function _factory($driver, $options = '') |
{ |
$storage_path = 'Auth/Container/' . $driver . '.php'; |
$storage_class = 'Auth_Container_' . $driver; |
require_once $storage_path; |
return new $storage_class($options); |
} |
// }}} |
// {{{ assignData() |
/** |
* Assign data from login form to internal values |
* |
* This function takes the values for username and password |
* from $HTTP_POST_VARS and assigns them to internal variables. |
* If you wish to use another source apart from $HTTP_POST_VARS, |
* you have to derive this function. |
* |
* @access private |
* @global $HTTP_POST_VARS |
* @see Auth |
* @return void |
*/ |
function assignData() |
{ |
$post = &$this->_importGlobalVariable('post'); |
if (isset($post['username']) && $post['username'] != '') { |
$this->username = (get_magic_quotes_gpc() == 1 ? stripslashes($post['username']) : $post['username']); |
} |
if (isset($post['password']) && $post['password'] != '') { |
$this->password = (get_magic_quotes_gpc() == 1 ? stripslashes($post['password']) : $post['password'] ); |
} |
} |
// }}} |
// {{{ start() |
/** |
* Start new auth session |
* |
* @access public |
* @return void |
*/ |
function start() |
{ |
$this->assignData(); |
@session_start(); |
if (!$this->checkAuth()) { |
$this->login(); |
} |
} |
// }}} |
// {{{ login() |
/** |
* Login function |
* |
* @access private |
* @return void |
*/ |
function login() |
{ |
$login_ok = false; |
/** |
* When the user has already entered a username, |
* we have to validate it. |
*/ |
if (!empty($this->username)) { |
if (true === $this->storage->fetchData($this->username, $this->password)) { |
$login_ok = true; |
} else { |
if (is_callable($this->loginFailedCallback)) { |
call_user_func($this->loginFailedCallback,$this->username, $this); |
} |
} |
} |
if (!empty($this->username) && $login_ok) { |
$this->setAuth($this->username); |
if (is_callable($this->loginCallback)) { |
call_user_func($this->loginCallback,$this->username, $this); |
} |
} |
/** |
* If the login failed or the user entered no username, |
* output the login screen again. |
*/ |
if (!empty($this->username) && !$login_ok) { |
$this->status = AUTH_WRONG_LOGIN; |
} |
if ((empty($this->username) || !$login_ok) && $this->showLogin) { |
$this->drawLogin($this->storage->activeUser); |
return; |
} |
} |
// }}} |
// {{{ setExpire() |
/** |
* Set the maximum expire time |
* |
* @access public |
* @param integer time in seconds |
* @param bool add time to current expire time or not |
* @return void |
*/ |
function setExpire($time, $add = false) |
{ |
if ($add) { |
$this->expire += $time; |
} else { |
$this->expire = $time; |
} |
} |
// }}} |
// {{{ setIdle() |
/** |
* Set the maximum idle time |
* |
* @access public |
* @param integer time in seconds |
* @param bool add time to current maximum idle time or not |
* @return void |
*/ |
function setIdle($time, $add = false) |
{ |
if ($add) { |
$this->idle += $time; |
} else { |
$this->idle = $time; |
} |
} |
// }}} |
// {{{ setSessionname() |
/** |
* Set name of the session to a customized value. |
* |
* If you are using multiple instances of PEAR::Auth |
* on the same domain, you can change the name of |
* session per application via this function. |
* |
* @access public |
* @param string New name for the session |
* @return void |
*/ |
function setSessionname($name = 'PHPSESSID') |
{ |
@session_name($name); |
} |
// }}} |
// {{{ setShowLogin() |
/** |
* Should the login form be displayed if neccessary? |
* |
* @access public |
* @param bool show login form or not |
* @return void |
*/ |
function setShowLogin($showLogin = true) |
{ |
$this->showLogin = $showLogin; |
} |
/** |
* Register a callback function to be called on user login. |
* The function will receive two parameters, the username and a reference to the auth object. |
* |
* @access public |
* @param string callback function name |
* @return void |
* @see setLogoutCallback() |
*/ |
function setLoginCallback($loginCallback) |
{ |
$this->loginCallback = $loginCallback; |
} |
/** |
* Register a callback function to be called on failed user login. |
* The function will receive a single parameter, the username and a reference to the auth object. |
* |
* @access public |
* @param string callback function name |
* @return void |
*/ |
function setFailedLoginCallback($loginFailedCallback) |
{ |
$this->loginFailedCallback = $loginFailedCallback; |
} |
/** |
* Register a callback function to be called on user logout. |
* The function will receive three parameters, the username and a reference to the auth object. |
* |
* @access public |
* @param string callback function name |
* @return void |
* @see setLoginCallback() |
*/ |
function setLogoutCallback($logoutCallback) |
{ |
$this->logoutCallback = $logoutCallback; |
} |
// }}} |
// {{{ setAuthData() |
/** |
* Register additional information that is to be stored |
* in the session. |
* |
* @access public |
* @param string Name of the data field |
* @param mixed Value of the data field |
* @param boolean Should existing data be overwritten? (default |
* is true) |
* @return void |
*/ |
function setAuthData($name, $value, $overwrite = true) |
{ |
$session = &Auth::_importGlobalVariable('session'); |
if (!empty($session[$this->_sessionName]['data'][$name]) && $overwrite == false) { |
return; |
} |
$session[$this->_sessionName]['data'][$name] = $value; |
} |
// }}} |
// {{{ getAuthData() |
/** |
* Get additional information that is stored in the session. |
* |
* If no value for the first parameter is passed, the method will |
* return all data that is currently stored. |
* |
* @access public |
* @param string Name of the data field |
* @return mixed Value of the data field. |
*/ |
function getAuthData($name = null) |
{ |
$session = &Auth::_importGlobalVariable('session'); |
if(!isset($session[$this->_sessionName]['data'])){ |
return(null); |
} |
if (is_null($name)) { |
if(isset($session[$this->_sessionName]['data'])) { |
return $session[$this->_sessionName]['data']; |
} else { |
return null; |
} |
} |
if (isset($session[$this->_sessionName]['data'][$name])) { |
return $session[$this->_sessionName]['data'][$name]; |
} else { |
return null; |
} |
} |
// }}} |
// {{{ setAuth() |
/** |
* Register variable in a session telling that the user |
* has logged in successfully |
* |
* @access public |
* @param string Username |
* @return void |
*/ |
function setAuth($username) |
{ |
$session = &Auth::_importGlobalVariable('session'); |
if (!isset($session[$this->_sessionName]) && !isset($_SESSION)) { |
session_register($this->_sessionName); |
} |
if (!isset($session[$this->_sessionName]) || !is_array($session[$this->_sessionName])) { |
$session[$this->_sessionName] = array(); |
} |
if(!isset($session[$this->_sessionName]['data'])){ |
$session[$this->_sessionName]['data'] = array(); |
} |
$session[$this->_sessionName]['registered'] = true; |
$session[$this->_sessionName]['username'] = $username; |
$session[$this->_sessionName]['timestamp'] = time(); |
$session[$this->_sessionName]['idle'] = time(); |
} |
// }}} |
// {{{ checkAuth() |
/** |
* Checks if there is a session with valid auth information. |
* |
* @access private |
* @return boolean Whether or not the user is authenticated. |
*/ |
function checkAuth() |
{ |
$session = &$this->_importGlobalVariable('session'); |
if (isset($session[$this->_sessionName])) { |
// Check if authentication session is expired |
if ($this->expire > 0 && |
isset($session[$this->_sessionName]['timestamp']) && |
($session[$this->_sessionName]['timestamp'] + $this->expire) < time()) { |
$this->logout(); |
$this->expired = true; |
$this->status = AUTH_EXPIRED; |
return false; |
} |
// Check if maximum idle time is reached |
if ($this->idle > 0 && |
isset($session[$this->_sessionName]['idle']) && |
($session[$this->_sessionName]['idle'] + $this->idle) < time()) { |
$this->logout(); |
$this->idled = true; |
$this->status = AUTH_IDLED; |
return false; |
} |
if (isset($session[$this->_sessionName]['registered']) && |
isset($session[$this->_sessionName]['username']) && |
$session[$this->_sessionName]['registered'] == true && |
$session[$this->_sessionName]['username'] != '') { |
Auth::updateIdle(); |
return true; |
} |
} |
return false; |
} |
// }}} |
// {{{ getAuth() |
/** |
* Has the user been authenticated? |
* |
* @access public |
* @return bool True if the user is logged in, otherwise false. |
*/ |
function getAuth() |
{ |
$session = &$this->_importGlobalVariable('session'); |
if (!empty($session) && |
(isset($session[$this->_sessionName]['registered']) && |
$session[$this->_sessionName]['registered'] === true)) |
{ |
return true; |
} else { |
return false; |
} |
} |
// }}} |
// {{{ drawLogin() |
/** |
* Draw the login form |
* |
* Normally you will not use this output in your application, |
* because you can pass a different function name to the |
* constructor. For more information on this, please |
* consult the documentation. |
* |
* @access private |
* @param string Username if already entered |
* @return void |
*/ |
function drawLogin($username = '') |
{ |
if (is_callable($this->loginFunction)) { |
call_user_func($this->loginFunction, $username, $this->status, $this); |
} else { |
$server = &$this->_importGlobalVariable('server'); |
echo '<center>'."\n"; |
if (!empty($this->status) && $this->status == AUTH_EXPIRED) { |
echo '<i>Your session expired. Please login again!</i>'."\n"; |
} else if (!empty($this->status) && $this->status == AUTH_IDLED) { |
echo '<i>You have been idle for too long. Please login again!</i>'."\n"; |
} else if (!empty ($this->status) && $this->status == AUTH_WRONG_LOGIN) { |
echo '<i>Wrong login data!</i>'."\n"; |
} |
PEAR::raiseError('You are using the built-in login screen of PEAR::Auth.<br />See the <a href="http://pear.php.net/manual/">manual</a> for details on how to create your own login function.', null); |
echo '<form method="post" action="' . $server['PHP_SELF'] . '">'."\n"; |
echo '<table border="0" cellpadding="2" cellspacing="0" summary="login form">'."\n"; |
echo '<tr>'."\n"; |
echo ' <td colspan="2" bgcolor="#eeeeee"><b>Login:</b></td>'."\n"; |
echo '</tr>'."\n"; |
echo '<tr>'."\n"; |
echo ' <td>Username:</td>'."\n"; |
echo ' <td><input type="text" name="username" value="' . $username . '" /></td>'."\n"; |
echo '</tr>'."\n"; |
echo '<tr>'."\n"; |
echo ' <td>Password:</td>'."\n"; |
echo ' <td><input type="password" name="password" /></td>'."\n"; |
echo '</tr>'."\n"; |
echo '<tr>'."\n"; |
echo ' <td colspan="2" bgcolor="#eeeeee"><input type="submit" /></td>'."\n"; |
echo '</tr>'."\n"; |
echo '</table>'."\n"; |
echo '</form>'."\n"; |
echo '</center>'."\n\n"; |
} |
} |
// }}} |
// {{{ logout() |
/** |
* Logout function |
* |
* This function clears any auth tokens in the currently |
* active session and executes the logout callback function, |
* if any |
* |
* @access public |
* @return void |
*/ |
function logout() |
{ |
$session = &$this->_importGlobalVariable('session'); |
if (is_callable($this->logoutCallback)) { |
call_user_func($this->logoutCallback, $session[$this->_sessionName]['username'], $this); |
} |
$this->username = ''; |
$this->password = ''; |
$session[$this->_sessionName] = array(); |
if (isset($_SESSION)) { |
unset($session[$this->_sessionName]); |
} else { |
session_unregister($this->_sessionName); |
} |
} |
// }}} |
// {{{ updateIdle() |
/** |
* Update the idletime |
* |
* @access private |
* @return void |
*/ |
function updateIdle() |
{ |
$session = &$this->_importGlobalVariable('session'); |
$session[$this->_sessionName]['idle'] = time(); |
} |
// }}} |
// {{{ getUsername() |
/** |
* Get the username |
* |
* @access public |
* @return string |
*/ |
function getUsername() |
{ |
$session = &$this->_importGlobalVariable('session'); |
if (!isset($session[$this->_sessionName]['username'])) { |
return ''; |
} |
return $session[$this->_sessionName]['username']; |
} |
// }}} |
// {{{ getStatus() |
/** |
* Get the current status |
* |
* @access public |
* @return string |
*/ |
function getStatus() |
{ |
return $this->status; |
} |
// }}} |
// {{{ sessionValidThru() |
/** |
* Returns the time up to the session is valid |
* |
* @access public |
* @return integer |
*/ |
function sessionValidThru() |
{ |
$session = &$this->_importGlobalVariable('session'); |
if (!isset($session[$this->_sessionName]['idle'])) { |
return 0; |
} |
return ($session[$this->_sessionName]['idle'] + $this->idle); |
} |
// }}} |
// {{{ listUsers() |
/** |
* List all users that are currently available in the storage |
* container |
* |
* @access public |
* @return array |
*/ |
function listUsers() |
{ |
return $this->storage->listUsers(); |
} |
// }}} |
// {{{ addUser() |
/** |
* Add user to the storage container |
* |
* @access public |
* @param string Username |
* @param string Password |
* @param mixed Additional parameters |
* @return mixed True on success, PEAR error object on error |
* and AUTH_METHOD_NOT_SUPPORTED otherwise. |
*/ |
function addUser($username, $password, $additional = '') |
{ |
return $this->storage->addUser($username, $password, $additional); |
} |
// }}} |
// {{{ removeUser() |
/** |
* Remove user from the storage container |
* |
* @access public |
* @param string Username |
* @return mixed True on success, PEAR error object on error |
* and AUTH_METHOD_NOT_SUPPORTED otherwise. |
*/ |
function removeUser($username) |
{ |
return $this->storage->removeUser($username); |
} |
// }}} |
// {{{ _importGlobalVariable() |
/** |
* Import variables from special namespaces. |
* |
* @access private |
* @param string Type of variable (server, session, post) |
* @return array |
*/ |
function &_importGlobalVariable($variable) |
{ |
$var = null; |
switch (strtolower($variable)) { |
case 'server' : |
if (isset($_SERVER)) { |
$var = &$_SERVER; |
} else { |
$var = &$GLOBALS['HTTP_SERVER_VARS']; |
} |
break; |
case 'session' : |
if (isset($_SESSION)) { |
$var = &$_SESSION; |
} else { |
$var = &$GLOBALS['HTTP_SESSION_VARS']; |
} |
break; |
case 'post' : |
if (isset($_POST)) { |
$var = &$_POST; |
} else { |
$var = &$GLOBALS['HTTP_POST_VARS']; |
} |
break; |
case 'cookie' : |
if (isset($_COOKIE)) { |
$var = &$_COOKIE; |
} else { |
$var = &$GLOBALS['HTTP_COOKIE_VARS']; |
} |
break; |
case 'get' : |
if (isset($_GET)) { |
$var = &$_GET; |
} else { |
$var = &$GLOBALS['HTTP_GET_VARS']; |
} |
break; |
default: |
break; |
} |
return $var; |
} |
// }}} |
} |
?> |
/branches/v1.3-critias/bibliotheque/pear/PEAR/RunTest.php |
---|
New file |
0,0 → 1,972 |
<?php |
/** |
* PEAR_RunTest |
* |
* PHP versions 4 and 5 |
* |
* @category pear |
* @package PEAR |
* @author Tomas V.V.Cox <cox@idecnet.com> |
* @author Greg Beaver <cellog@php.net> |
* @copyright 1997-2009 The Authors |
* @license http://opensource.org/licenses/bsd-license.php New BSD License |
* @link http://pear.php.net/package/PEAR |
* @since File available since Release 1.3.3 |
*/ |
/** |
* for error handling |
*/ |
require_once 'PEAR.php'; |
require_once 'PEAR/Config.php'; |
define('DETAILED', 1); |
putenv("PHP_PEAR_RUNTESTS=1"); |
/** |
* Simplified version of PHP's test suite |
* |
* Try it with: |
* |
* $ php -r 'include "../PEAR/RunTest.php"; $t=new PEAR_RunTest; $o=$t->run("./pear_system.phpt");print_r($o);' |
* |
* |
* @category pear |
* @package PEAR |
* @author Tomas V.V.Cox <cox@idecnet.com> |
* @author Greg Beaver <cellog@php.net> |
* @copyright 1997-2009 The Authors |
* @license http://opensource.org/licenses/bsd-license.php New BSD License |
* @version Release: 1.10.1 |
* @link http://pear.php.net/package/PEAR |
* @since Class available since Release 1.3.3 |
*/ |
class PEAR_RunTest |
{ |
var $_headers = array(); |
var $_logger; |
var $_options; |
var $_php; |
var $tests_count; |
var $xdebug_loaded; |
/** |
* Saved value of php executable, used to reset $_php when we |
* have a test that uses cgi |
* |
* @var unknown_type |
*/ |
var $_savephp; |
var $ini_overwrites = array( |
'output_handler=', |
'open_basedir=', |
'disable_functions=', |
'output_buffering=Off', |
'display_errors=1', |
'log_errors=0', |
'html_errors=0', |
'track_errors=1', |
'report_memleaks=0', |
'report_zend_debug=0', |
'docref_root=', |
'docref_ext=.html', |
'error_prepend_string=', |
'error_append_string=', |
'auto_prepend_file=', |
'auto_append_file=', |
'xdebug.default_enable=0', |
'allow_url_fopen=1', |
); |
/** |
* An object that supports the PEAR_Common->log() signature, or null |
* @param PEAR_Common|null |
*/ |
function __construct($logger = null, $options = array()) |
{ |
if (!defined('E_DEPRECATED')) { |
define('E_DEPRECATED', 0); |
} |
if (!defined('E_STRICT')) { |
define('E_STRICT', 0); |
} |
$this->ini_overwrites[] = 'error_reporting=' . (E_ALL & ~(E_DEPRECATED | E_STRICT)); |
if (is_null($logger)) { |
require_once 'PEAR/Common.php'; |
$logger = new PEAR_Common; |
} |
$this->_logger = $logger; |
$this->_options = $options; |
$conf = &PEAR_Config::singleton(); |
$this->_php = $conf->get('php_bin'); |
} |
/** |
* Taken from php-src/run-tests.php |
* |
* @param string $commandline command name |
* @param array $env |
* @param string $stdin standard input to pass to the command |
* @return unknown |
*/ |
function system_with_timeout($commandline, $env = null, $stdin = null) |
{ |
$data = ''; |
$proc = proc_open($commandline, array( |
0 => array('pipe', 'r'), |
1 => array('pipe', 'w'), |
2 => array('pipe', 'w') |
), $pipes, null, $env, array('suppress_errors' => true)); |
if (!$proc) { |
return false; |
} |
if (is_string($stdin)) { |
fwrite($pipes[0], $stdin); |
} |
fclose($pipes[0]); |
while (true) { |
/* hide errors from interrupted syscalls */ |
$r = $pipes; |
$e = $w = null; |
$n = @stream_select($r, $w, $e, 60); |
if ($n === 0) { |
/* timed out */ |
$data .= "\n ** ERROR: process timed out **\n"; |
proc_terminate($proc); |
return array(1234567890, $data); |
} else if ($n > 0) { |
$line = fread($pipes[1], 8192); |
if (strlen($line) == 0) { |
/* EOF */ |
break; |
} |
$data .= $line; |
} |
} |
if (function_exists('proc_get_status')) { |
$stat = proc_get_status($proc); |
if ($stat['signaled']) { |
$data .= "\nTermsig=".$stat['stopsig']; |
} |
} |
$code = proc_close($proc); |
if (function_exists('proc_get_status')) { |
$code = $stat['exitcode']; |
} |
return array($code, $data); |
} |
/** |
* Turns a PHP INI string into an array |
* |
* Turns -d "include_path=/foo/bar" into this: |
* array( |
* 'include_path' => array( |
* 'operator' => '-d', |
* 'value' => '/foo/bar', |
* ) |
* ) |
* Works both with quotes and without |
* |
* @param string an PHP INI string, -d "include_path=/foo/bar" |
* @return array |
*/ |
function iniString2array($ini_string) |
{ |
if (!$ini_string) { |
return array(); |
} |
$split = preg_split('/[\s]|=/', $ini_string, -1, PREG_SPLIT_NO_EMPTY); |
$key = $split[1][0] == '"' ? substr($split[1], 1) : $split[1]; |
$value = $split[2][strlen($split[2]) - 1] == '"' ? substr($split[2], 0, -1) : $split[2]; |
// FIXME review if this is really the struct to go with |
$array = array($key => array('operator' => $split[0], 'value' => $value)); |
return $array; |
} |
function settings2array($settings, $ini_settings) |
{ |
foreach ($settings as $setting) { |
if (strpos($setting, '=') !== false) { |
$setting = explode('=', $setting, 2); |
$name = trim(strtolower($setting[0])); |
$value = trim($setting[1]); |
$ini_settings[$name] = $value; |
} |
} |
return $ini_settings; |
} |
function settings2params($ini_settings) |
{ |
$settings = ''; |
foreach ($ini_settings as $name => $value) { |
if (is_array($value)) { |
$operator = $value['operator']; |
$value = $value['value']; |
} else { |
$operator = '-d'; |
} |
$value = addslashes($value); |
$settings .= " $operator \"$name=$value\""; |
} |
return $settings; |
} |
function _preparePhpBin($php, $file, $ini_settings) |
{ |
$file = escapeshellarg($file); |
$cmd = $php . $ini_settings . ' -f ' . $file; |
return $cmd; |
} |
function runPHPUnit($file, $ini_settings = '') |
{ |
if (!file_exists($file) && file_exists(getcwd() . DIRECTORY_SEPARATOR . $file)) { |
$file = realpath(getcwd() . DIRECTORY_SEPARATOR . $file); |
} elseif (file_exists($file)) { |
$file = realpath($file); |
} |
$cmd = $this->_preparePhpBin($this->_php, $file, $ini_settings); |
if (isset($this->_logger)) { |
$this->_logger->log(2, 'Running command "' . $cmd . '"'); |
} |
$savedir = getcwd(); // in case the test moves us around |
chdir(dirname($file)); |
echo `$cmd`; |
chdir($savedir); |
return 'PASSED'; // we have no way of knowing this information so assume passing |
} |
/** |
* Runs an individual test case. |
* |
* @param string The filename of the test |
* @param array|string INI settings to be applied to the test run |
* @param integer Number what the current running test is of the |
* whole test suite being runned. |
* |
* @return string|object Returns PASSED, WARNED, FAILED depending on how the |
* test came out. |
* PEAR Error when the tester it self fails |
*/ |
function run($file, $ini_settings = array(), $test_number = 1) |
{ |
$this->_restorePHPBinary(); |
if (empty($this->_options['cgi'])) { |
// try to see if php-cgi is in the path |
$res = $this->system_with_timeout('php-cgi -v'); |
if (false !== $res && !(is_array($res) && in_array($res[0], array(-1, 127)))) { |
$this->_options['cgi'] = 'php-cgi'; |
} |
} |
if (1 < $len = strlen($this->tests_count)) { |
$test_number = str_pad($test_number, $len, ' ', STR_PAD_LEFT); |
$test_nr = "[$test_number/$this->tests_count] "; |
} else { |
$test_nr = ''; |
} |
$file = realpath($file); |
$section_text = $this->_readFile($file); |
if (PEAR::isError($section_text)) { |
return $section_text; |
} |
if (isset($section_text['POST_RAW']) && isset($section_text['UPLOAD'])) { |
return PEAR::raiseError("Cannot contain both POST_RAW and UPLOAD in test file: $file"); |
} |
$cwd = getcwd(); |
$pass_options = ''; |
if (!empty($this->_options['ini'])) { |
$pass_options = $this->_options['ini']; |
} |
if (is_string($ini_settings)) { |
$ini_settings = $this->iniString2array($ini_settings); |
} |
$ini_settings = $this->settings2array($this->ini_overwrites, $ini_settings); |
if ($section_text['INI']) { |
if (strpos($section_text['INI'], '{PWD}') !== false) { |
$section_text['INI'] = str_replace('{PWD}', dirname($file), $section_text['INI']); |
} |
$ini = preg_split( "/[\n\r]+/", $section_text['INI']); |
$ini_settings = $this->settings2array($ini, $ini_settings); |
} |
$ini_settings = $this->settings2params($ini_settings); |
$shortname = str_replace($cwd . DIRECTORY_SEPARATOR, '', $file); |
$tested = trim($section_text['TEST']); |
$tested.= !isset($this->_options['simple']) ? "[$shortname]" : ' '; |
if (!empty($section_text['POST']) || !empty($section_text['POST_RAW']) || |
!empty($section_text['UPLOAD']) || !empty($section_text['GET']) || |
!empty($section_text['COOKIE']) || !empty($section_text['EXPECTHEADERS'])) { |
if (empty($this->_options['cgi'])) { |
if (!isset($this->_options['quiet'])) { |
$this->_logger->log(0, "SKIP $test_nr$tested (reason: --cgi option needed for this test, type 'pear help run-tests')"); |
} |
if (isset($this->_options['tapoutput'])) { |
return array('ok', ' # skip --cgi option needed for this test, "pear help run-tests" for info'); |
} |
return 'SKIPPED'; |
} |
$this->_savePHPBinary(); |
$this->_php = $this->_options['cgi']; |
} |
$temp_dir = realpath(dirname($file)); |
$main_file_name = basename($file, 'phpt'); |
$diff_filename = $temp_dir . DIRECTORY_SEPARATOR . $main_file_name.'diff'; |
$log_filename = $temp_dir . DIRECTORY_SEPARATOR . $main_file_name.'log'; |
$exp_filename = $temp_dir . DIRECTORY_SEPARATOR . $main_file_name.'exp'; |
$output_filename = $temp_dir . DIRECTORY_SEPARATOR . $main_file_name.'out'; |
$memcheck_filename = $temp_dir . DIRECTORY_SEPARATOR . $main_file_name.'mem'; |
$temp_file = $temp_dir . DIRECTORY_SEPARATOR . $main_file_name.'php'; |
$temp_skipif = $temp_dir . DIRECTORY_SEPARATOR . $main_file_name.'skip.php'; |
$temp_clean = $temp_dir . DIRECTORY_SEPARATOR . $main_file_name.'clean.php'; |
$tmp_post = $temp_dir . DIRECTORY_SEPARATOR . uniqid('phpt.'); |
// unlink old test results |
$this->_cleanupOldFiles($file); |
// Check if test should be skipped. |
$res = $this->_runSkipIf($section_text, $temp_skipif, $tested, $ini_settings); |
if (count($res) != 2) { |
return $res; |
} |
$info = $res['info']; |
$warn = $res['warn']; |
// We've satisfied the preconditions - run the test! |
if (isset($this->_options['coverage']) && $this->xdebug_loaded) { |
$xdebug_file = $temp_dir . DIRECTORY_SEPARATOR . $main_file_name . 'xdebug'; |
$text = "\n" . 'function coverage_shutdown() {' . |
"\n" . ' $xdebug = var_export(xdebug_get_code_coverage(), true);'; |
if (!function_exists('file_put_contents')) { |
$text .= "\n" . ' $fh = fopen(\'' . $xdebug_file . '\', "wb");' . |
"\n" . ' if ($fh !== false) {' . |
"\n" . ' fwrite($fh, $xdebug);' . |
"\n" . ' fclose($fh);' . |
"\n" . ' }'; |
} else { |
$text .= "\n" . ' file_put_contents(\'' . $xdebug_file . '\', $xdebug);'; |
} |
// Workaround for http://pear.php.net/bugs/bug.php?id=17292 |
$lines = explode("\n", $section_text['FILE']); |
$numLines = count($lines); |
$namespace = ''; |
$coverage_shutdown = 'coverage_shutdown'; |
if ( |
substr($lines[0], 0, 2) == '<?' || |
substr($lines[0], 0, 5) == '<?php' |
) { |
unset($lines[0]); |
} |
for ($i = 0; $i < $numLines; $i++) { |
if (isset($lines[$i]) && substr($lines[$i], 0, 9) == 'namespace') { |
$namespace = substr($lines[$i], 10, -1); |
$coverage_shutdown = $namespace . '\\coverage_shutdown'; |
$namespace = "namespace " . $namespace . ";\n"; |
unset($lines[$i]); |
break; |
} |
} |
$text .= "\n xdebug_stop_code_coverage();" . |
"\n" . '} // end coverage_shutdown()' . |
"\n\n" . 'register_shutdown_function("' . $coverage_shutdown . '");'; |
$text .= "\n" . 'xdebug_start_code_coverage(XDEBUG_CC_UNUSED | XDEBUG_CC_DEAD_CODE);' . "\n"; |
$this->save_text($temp_file, "<?php\n" . $namespace . $text . "\n" . implode("\n", $lines)); |
} else { |
$this->save_text($temp_file, $section_text['FILE']); |
} |
$args = $section_text['ARGS'] ? ' -- '.$section_text['ARGS'] : ''; |
$cmd = $this->_preparePhpBin($this->_php, $temp_file, $ini_settings); |
$cmd.= "$args 2>&1"; |
if (isset($this->_logger)) { |
$this->_logger->log(2, 'Running command "' . $cmd . '"'); |
} |
// Reset environment from any previous test. |
$env = $this->_resetEnv($section_text, $temp_file); |
$section_text = $this->_processUpload($section_text, $file); |
if (PEAR::isError($section_text)) { |
return $section_text; |
} |
if (array_key_exists('POST_RAW', $section_text) && !empty($section_text['POST_RAW'])) { |
$post = trim($section_text['POST_RAW']); |
$raw_lines = explode("\n", $post); |
$request = ''; |
$started = false; |
foreach ($raw_lines as $i => $line) { |
if (empty($env['CONTENT_TYPE']) && |
preg_match('/^Content-Type:(.*)/i', $line, $res)) { |
$env['CONTENT_TYPE'] = trim(str_replace("\r", '', $res[1])); |
continue; |
} |
if ($started) { |
$request .= "\n"; |
} |
$started = true; |
$request .= $line; |
} |
$env['CONTENT_LENGTH'] = strlen($request); |
$env['REQUEST_METHOD'] = 'POST'; |
$this->save_text($tmp_post, $request); |
$cmd = "$this->_php$pass_options$ini_settings \"$temp_file\" 2>&1 < $tmp_post"; |
} elseif (array_key_exists('POST', $section_text) && !empty($section_text['POST'])) { |
$post = trim($section_text['POST']); |
$this->save_text($tmp_post, $post); |
$content_length = strlen($post); |
$env['REQUEST_METHOD'] = 'POST'; |
$env['CONTENT_TYPE'] = 'application/x-www-form-urlencoded'; |
$env['CONTENT_LENGTH'] = $content_length; |
$cmd = "$this->_php$pass_options$ini_settings \"$temp_file\" 2>&1 < $tmp_post"; |
} else { |
$env['REQUEST_METHOD'] = 'GET'; |
$env['CONTENT_TYPE'] = ''; |
$env['CONTENT_LENGTH'] = ''; |
} |
if (OS_WINDOWS && isset($section_text['RETURNS'])) { |
ob_start(); |
system($cmd, $return_value); |
$out = ob_get_contents(); |
ob_end_clean(); |
$section_text['RETURNS'] = (int) trim($section_text['RETURNS']); |
$returnfail = ($return_value != $section_text['RETURNS']); |
} else { |
$returnfail = false; |
$stdin = isset($section_text['STDIN']) ? $section_text['STDIN'] : null; |
$out = $this->system_with_timeout($cmd, $env, $stdin); |
$return_value = $out[0]; |
$out = $out[1]; |
} |
$output = preg_replace('/\r\n/', "\n", trim($out)); |
if (isset($tmp_post) && realpath($tmp_post) && file_exists($tmp_post)) { |
@unlink(realpath($tmp_post)); |
} |
chdir($cwd); // in case the test moves us around |
/* when using CGI, strip the headers from the output */ |
$output = $this->_stripHeadersCGI($output); |
if (isset($section_text['EXPECTHEADERS'])) { |
$testheaders = $this->_processHeaders($section_text['EXPECTHEADERS']); |
$missing = array_diff_assoc($testheaders, $this->_headers); |
$changed = ''; |
foreach ($missing as $header => $value) { |
if (isset($this->_headers[$header])) { |
$changed .= "-$header: $value\n+$header: "; |
$changed .= $this->_headers[$header]; |
} else { |
$changed .= "-$header: $value\n"; |
} |
} |
if ($missing) { |
// tack on failed headers to output: |
$output .= "\n====EXPECTHEADERS FAILURE====:\n$changed"; |
} |
} |
$this->_testCleanup($section_text, $temp_clean); |
// Does the output match what is expected? |
do { |
if (isset($section_text['EXPECTF']) || isset($section_text['EXPECTREGEX'])) { |
if (isset($section_text['EXPECTF'])) { |
$wanted = trim($section_text['EXPECTF']); |
} else { |
$wanted = trim($section_text['EXPECTREGEX']); |
} |
$wanted_re = preg_replace('/\r\n/', "\n", $wanted); |
if (isset($section_text['EXPECTF'])) { |
$wanted_re = preg_quote($wanted_re, '/'); |
// Stick to basics |
$wanted_re = str_replace("%s", ".+?", $wanted_re); //not greedy |
$wanted_re = str_replace("%i", "[+\-]?[0-9]+", $wanted_re); |
$wanted_re = str_replace("%d", "[0-9]+", $wanted_re); |
$wanted_re = str_replace("%x", "[0-9a-fA-F]+", $wanted_re); |
$wanted_re = str_replace("%f", "[+\-]?\.?[0-9]+\.?[0-9]*(E-?[0-9]+)?", $wanted_re); |
$wanted_re = str_replace("%c", ".", $wanted_re); |
// %f allows two points "-.0.0" but that is the best *simple* expression |
} |
/* DEBUG YOUR REGEX HERE |
var_dump($wanted_re); |
print(str_repeat('=', 80) . "\n"); |
var_dump($output); |
*/ |
if (!$returnfail && preg_match("/^$wanted_re\$/s", $output)) { |
if (file_exists($temp_file)) { |
unlink($temp_file); |
} |
if (array_key_exists('FAIL', $section_text)) { |
break; |
} |
if (!isset($this->_options['quiet'])) { |
$this->_logger->log(0, "PASS $test_nr$tested$info"); |
} |
if (isset($this->_options['tapoutput'])) { |
return array('ok', ' - ' . $tested); |
} |
return 'PASSED'; |
} |
} else { |
if (isset($section_text['EXPECTFILE'])) { |
$f = $temp_dir . '/' . trim($section_text['EXPECTFILE']); |
if (!($fp = @fopen($f, 'rb'))) { |
return PEAR::raiseError('--EXPECTFILE-- section file ' . |
$f . ' not found'); |
} |
fclose($fp); |
$section_text['EXPECT'] = file_get_contents($f); |
} |
if (isset($section_text['EXPECT'])) { |
$wanted = preg_replace('/\r\n/', "\n", trim($section_text['EXPECT'])); |
} else { |
$wanted = ''; |
} |
// compare and leave on success |
if (!$returnfail && 0 == strcmp($output, $wanted)) { |
if (file_exists($temp_file)) { |
unlink($temp_file); |
} |
if (array_key_exists('FAIL', $section_text)) { |
break; |
} |
if (!isset($this->_options['quiet'])) { |
$this->_logger->log(0, "PASS $test_nr$tested$info"); |
} |
if (isset($this->_options['tapoutput'])) { |
return array('ok', ' - ' . $tested); |
} |
return 'PASSED'; |
} |
} |
} while (false); |
if (array_key_exists('FAIL', $section_text)) { |
// we expect a particular failure |
// this is only used for testing PEAR_RunTest |
$expectf = isset($section_text['EXPECTF']) ? $wanted_re : null; |
$faildiff = $this->generate_diff($wanted, $output, null, $expectf); |
$faildiff = preg_replace('/\r/', '', $faildiff); |
$wanted = preg_replace('/\r/', '', trim($section_text['FAIL'])); |
if ($faildiff == $wanted) { |
if (!isset($this->_options['quiet'])) { |
$this->_logger->log(0, "PASS $test_nr$tested$info"); |
} |
if (isset($this->_options['tapoutput'])) { |
return array('ok', ' - ' . $tested); |
} |
return 'PASSED'; |
} |
unset($section_text['EXPECTF']); |
$output = $faildiff; |
if (isset($section_text['RETURNS'])) { |
return PEAR::raiseError('Cannot have both RETURNS and FAIL in the same test: ' . |
$file); |
} |
} |
// Test failed so we need to report details. |
$txt = $warn ? 'WARN ' : 'FAIL '; |
$this->_logger->log(0, $txt . $test_nr . $tested . $info); |
// write .exp |
$res = $this->_writeLog($exp_filename, $wanted); |
if (PEAR::isError($res)) { |
return $res; |
} |
// write .out |
$res = $this->_writeLog($output_filename, $output); |
if (PEAR::isError($res)) { |
return $res; |
} |
// write .diff |
$returns = isset($section_text['RETURNS']) ? |
array(trim($section_text['RETURNS']), $return_value) : null; |
$expectf = isset($section_text['EXPECTF']) ? $wanted_re : null; |
$data = $this->generate_diff($wanted, $output, $returns, $expectf); |
$res = $this->_writeLog($diff_filename, $data); |
if (isset($this->_options['showdiff'])) { |
$this->_logger->log(0, "========DIFF========"); |
$this->_logger->log(0, $data); |
$this->_logger->log(0, "========DONE========"); |
} |
if (PEAR::isError($res)) { |
return $res; |
} |
// write .log |
$data = " |
---- EXPECTED OUTPUT |
$wanted |
---- ACTUAL OUTPUT |
$output |
---- FAILED |
"; |
if ($returnfail) { |
$data .= " |
---- EXPECTED RETURN |
$section_text[RETURNS] |
---- ACTUAL RETURN |
$return_value |
"; |
} |
$res = $this->_writeLog($log_filename, $data); |
if (PEAR::isError($res)) { |
return $res; |
} |
if (isset($this->_options['tapoutput'])) { |
$wanted = explode("\n", $wanted); |
$wanted = "# Expected output:\n#\n#" . implode("\n#", $wanted); |
$output = explode("\n", $output); |
$output = "#\n#\n# Actual output:\n#\n#" . implode("\n#", $output); |
return array($wanted . $output . 'not ok', ' - ' . $tested); |
} |
return $warn ? 'WARNED' : 'FAILED'; |
} |
function generate_diff($wanted, $output, $rvalue, $wanted_re) |
{ |
$w = explode("\n", $wanted); |
$o = explode("\n", $output); |
$wr = explode("\n", $wanted_re); |
$w1 = array_diff_assoc($w, $o); |
$o1 = array_diff_assoc($o, $w); |
$o2 = $w2 = array(); |
foreach ($w1 as $idx => $val) { |
if (!$wanted_re || !isset($wr[$idx]) || !isset($o1[$idx]) || |
!preg_match('/^' . $wr[$idx] . '\\z/', $o1[$idx])) { |
$w2[sprintf("%03d<", $idx)] = sprintf("%03d- ", $idx + 1) . $val; |
} |
} |
foreach ($o1 as $idx => $val) { |
if (!$wanted_re || !isset($wr[$idx]) || |
!preg_match('/^' . $wr[$idx] . '\\z/', $val)) { |
$o2[sprintf("%03d>", $idx)] = sprintf("%03d+ ", $idx + 1) . $val; |
} |
} |
$diff = array_merge($w2, $o2); |
ksort($diff); |
$extra = $rvalue ? "##EXPECTED: $rvalue[0]\r\n##RETURNED: $rvalue[1]" : ''; |
return implode("\r\n", $diff) . $extra; |
} |
// Write the given text to a temporary file, and return the filename. |
function save_text($filename, $text) |
{ |
if (!$fp = fopen($filename, 'w')) { |
return PEAR::raiseError("Cannot open file '" . $filename . "' (save_text)"); |
} |
fwrite($fp, $text); |
fclose($fp); |
if (1 < DETAILED) echo " |
FILE $filename {{{ |
$text |
}}} |
"; |
} |
function _cleanupOldFiles($file) |
{ |
$temp_dir = realpath(dirname($file)); |
$mainFileName = basename($file, 'phpt'); |
$diff_filename = $temp_dir . DIRECTORY_SEPARATOR . $mainFileName.'diff'; |
$log_filename = $temp_dir . DIRECTORY_SEPARATOR . $mainFileName.'log'; |
$exp_filename = $temp_dir . DIRECTORY_SEPARATOR . $mainFileName.'exp'; |
$output_filename = $temp_dir . DIRECTORY_SEPARATOR . $mainFileName.'out'; |
$memcheck_filename = $temp_dir . DIRECTORY_SEPARATOR . $mainFileName.'mem'; |
$temp_file = $temp_dir . DIRECTORY_SEPARATOR . $mainFileName.'php'; |
$temp_skipif = $temp_dir . DIRECTORY_SEPARATOR . $mainFileName.'skip.php'; |
$temp_clean = $temp_dir . DIRECTORY_SEPARATOR . $mainFileName.'clean.php'; |
$tmp_post = $temp_dir . DIRECTORY_SEPARATOR . uniqid('phpt.'); |
// unlink old test results |
@unlink($diff_filename); |
@unlink($log_filename); |
@unlink($exp_filename); |
@unlink($output_filename); |
@unlink($memcheck_filename); |
@unlink($temp_file); |
@unlink($temp_skipif); |
@unlink($tmp_post); |
@unlink($temp_clean); |
} |
function _runSkipIf($section_text, $temp_skipif, $tested, $ini_settings) |
{ |
$info = ''; |
$warn = false; |
if (array_key_exists('SKIPIF', $section_text) && trim($section_text['SKIPIF'])) { |
$this->save_text($temp_skipif, $section_text['SKIPIF']); |
$output = $this->system_with_timeout("$this->_php$ini_settings -f \"$temp_skipif\""); |
$output = $output[1]; |
$loutput = ltrim($output); |
unlink($temp_skipif); |
if (!strncasecmp('skip', $loutput, 4)) { |
$skipreason = "SKIP $tested"; |
if (preg_match('/^\s*skip\s*(.+)\s*/i', $output, $m)) { |
$skipreason .= '(reason: ' . $m[1] . ')'; |
} |
if (!isset($this->_options['quiet'])) { |
$this->_logger->log(0, $skipreason); |
} |
if (isset($this->_options['tapoutput'])) { |
return array('ok', ' # skip ' . $reason); |
} |
return 'SKIPPED'; |
} |
if (!strncasecmp('info', $loutput, 4) |
&& preg_match('/^\s*info\s*(.+)\s*/i', $output, $m)) { |
$info = " (info: $m[1])"; |
} |
if (!strncasecmp('warn', $loutput, 4) |
&& preg_match('/^\s*warn\s*(.+)\s*/i', $output, $m)) { |
$warn = true; /* only if there is a reason */ |
$info = " (warn: $m[1])"; |
} |
} |
return array('warn' => $warn, 'info' => $info); |
} |
function _stripHeadersCGI($output) |
{ |
$this->headers = array(); |
if (!empty($this->_options['cgi']) && |
$this->_php == $this->_options['cgi'] && |
preg_match("/^(.*?)(?:\n\n(.*)|\\z)/s", $output, $match)) { |
$output = isset($match[2]) ? trim($match[2]) : ''; |
$this->_headers = $this->_processHeaders($match[1]); |
} |
return $output; |
} |
/** |
* Return an array that can be used with array_diff() to compare headers |
* |
* @param string $text |
*/ |
function _processHeaders($text) |
{ |
$headers = array(); |
$rh = preg_split("/[\n\r]+/", $text); |
foreach ($rh as $line) { |
if (strpos($line, ':')!== false) { |
$line = explode(':', $line, 2); |
$headers[trim($line[0])] = trim($line[1]); |
} |
} |
return $headers; |
} |
function _readFile($file) |
{ |
// Load the sections of the test file. |
$section_text = array( |
'TEST' => '(unnamed test)', |
'SKIPIF' => '', |
'GET' => '', |
'COOKIE' => '', |
'POST' => '', |
'ARGS' => '', |
'INI' => '', |
'CLEAN' => '', |
); |
if (!is_file($file) || !$fp = fopen($file, "r")) { |
return PEAR::raiseError("Cannot open test file: $file"); |
} |
$section = ''; |
while (!feof($fp)) { |
$line = fgets($fp); |
// Match the beginning of a section. |
if (preg_match('/^--([_A-Z]+)--/', $line, $r)) { |
$section = $r[1]; |
$section_text[$section] = ''; |
continue; |
} elseif (empty($section)) { |
fclose($fp); |
return PEAR::raiseError("Invalid sections formats in test file: $file"); |
} |
// Add to the section text. |
$section_text[$section] .= $line; |
} |
fclose($fp); |
return $section_text; |
} |
function _writeLog($logname, $data) |
{ |
if (!$log = fopen($logname, 'w')) { |
return PEAR::raiseError("Cannot create test log - $logname"); |
} |
fwrite($log, $data); |
fclose($log); |
} |
function _resetEnv($section_text, $temp_file) |
{ |
$env = $_ENV; |
$env['REDIRECT_STATUS'] = ''; |
$env['QUERY_STRING'] = ''; |
$env['PATH_TRANSLATED'] = ''; |
$env['SCRIPT_FILENAME'] = ''; |
$env['REQUEST_METHOD'] = ''; |
$env['CONTENT_TYPE'] = ''; |
$env['CONTENT_LENGTH'] = ''; |
if (!empty($section_text['ENV'])) { |
if (strpos($section_text['ENV'], '{PWD}') !== false) { |
$section_text['ENV'] = str_replace('{PWD}', dirname($temp_file), $section_text['ENV']); |
} |
foreach (explode("\n", trim($section_text['ENV'])) as $e) { |
$e = explode('=', trim($e), 2); |
if (!empty($e[0]) && isset($e[1])) { |
$env[$e[0]] = $e[1]; |
} |
} |
} |
if (array_key_exists('GET', $section_text)) { |
$env['QUERY_STRING'] = trim($section_text['GET']); |
} else { |
$env['QUERY_STRING'] = ''; |
} |
if (array_key_exists('COOKIE', $section_text)) { |
$env['HTTP_COOKIE'] = trim($section_text['COOKIE']); |
} else { |
$env['HTTP_COOKIE'] = ''; |
} |
$env['REDIRECT_STATUS'] = '1'; |
$env['PATH_TRANSLATED'] = $temp_file; |
$env['SCRIPT_FILENAME'] = $temp_file; |
return $env; |
} |
function _processUpload($section_text, $file) |
{ |
if (array_key_exists('UPLOAD', $section_text) && !empty($section_text['UPLOAD'])) { |
$upload_files = trim($section_text['UPLOAD']); |
$upload_files = explode("\n", $upload_files); |
$request = "Content-Type: multipart/form-data; boundary=---------------------------20896060251896012921717172737\n" . |
"-----------------------------20896060251896012921717172737\n"; |
foreach ($upload_files as $fileinfo) { |
$fileinfo = explode('=', $fileinfo); |
if (count($fileinfo) != 2) { |
return PEAR::raiseError("Invalid UPLOAD section in test file: $file"); |
} |
if (!realpath(dirname($file) . '/' . $fileinfo[1])) { |
return PEAR::raiseError("File for upload does not exist: $fileinfo[1] " . |
"in test file: $file"); |
} |
$file_contents = file_get_contents(dirname($file) . '/' . $fileinfo[1]); |
$fileinfo[1] = basename($fileinfo[1]); |
$request .= "Content-Disposition: form-data; name=\"$fileinfo[0]\"; filename=\"$fileinfo[1]\"\n"; |
$request .= "Content-Type: text/plain\n\n"; |
$request .= $file_contents . "\n" . |
"-----------------------------20896060251896012921717172737\n"; |
} |
if (array_key_exists('POST', $section_text) && !empty($section_text['POST'])) { |
// encode POST raw |
$post = trim($section_text['POST']); |
$post = explode('&', $post); |
foreach ($post as $i => $post_info) { |
$post_info = explode('=', $post_info); |
if (count($post_info) != 2) { |
return PEAR::raiseError("Invalid POST data in test file: $file"); |
} |
$post_info[0] = rawurldecode($post_info[0]); |
$post_info[1] = rawurldecode($post_info[1]); |
$post[$i] = $post_info; |
} |
foreach ($post as $post_info) { |
$request .= "Content-Disposition: form-data; name=\"$post_info[0]\"\n\n"; |
$request .= $post_info[1] . "\n" . |
"-----------------------------20896060251896012921717172737\n"; |
} |
unset($section_text['POST']); |
} |
$section_text['POST_RAW'] = $request; |
} |
return $section_text; |
} |
function _testCleanup($section_text, $temp_clean) |
{ |
if ($section_text['CLEAN']) { |
$this->_restorePHPBinary(); |
// perform test cleanup |
$this->save_text($temp_clean, $section_text['CLEAN']); |
$output = $this->system_with_timeout("$this->_php $temp_clean 2>&1"); |
if (strlen($output[1])) { |
echo "BORKED --CLEAN-- section! output:\n", $output[1]; |
} |
if (file_exists($temp_clean)) { |
unlink($temp_clean); |
} |
} |
} |
function _savePHPBinary() |
{ |
$this->_savephp = $this->_php; |
} |
function _restorePHPBinary() |
{ |
if (isset($this->_savephp)) |
{ |
$this->_php = $this->_savephp; |
unset($this->_savephp); |
} |
} |
} |
/branches/v1.3-critias/bibliotheque/pear/PEAR/Config.php |
---|
New file |
0,0 → 1,2131 |
<?php |
/** |
* PEAR_Config, customized configuration handling for the PEAR Installer |
* |
* PHP versions 4 and 5 |
* |
* @category pear |
* @package PEAR |
* @author Stig Bakken <ssb@php.net> |
* @author Greg Beaver <cellog@php.net> |
* @copyright 1997-2009 The Authors |
* @license http://opensource.org/licenses/bsd-license.php New BSD License |
* @link http://pear.php.net/package/PEAR |
* @since File available since Release 0.1 |
*/ |
/** |
* Required for error handling |
*/ |
require_once 'PEAR.php'; |
require_once 'PEAR/Registry.php'; |
require_once 'PEAR/Installer/Role.php'; |
require_once 'System.php'; |
/** |
* Last created PEAR_Config instance. |
* @var object |
*/ |
$GLOBALS['_PEAR_Config_instance'] = null; |
if (!defined('PEAR_INSTALL_DIR') || !PEAR_INSTALL_DIR) { |
$PEAR_INSTALL_DIR = PHP_LIBDIR . DIRECTORY_SEPARATOR . 'pear'; |
} else { |
$PEAR_INSTALL_DIR = PEAR_INSTALL_DIR; |
} |
// Below we define constants with default values for all configuration |
// parameters except username/password. All of them can have their |
// defaults set through environment variables. The reason we use the |
// PHP_ prefix is for some security, PHP protects environment |
// variables starting with PHP_*. |
// default channel and preferred mirror is based on whether we are invoked through |
// the "pear" or the "pecl" command |
if (!defined('PEAR_RUNTYPE')) { |
define('PEAR_RUNTYPE', 'pear'); |
} |
if (PEAR_RUNTYPE == 'pear') { |
define('PEAR_CONFIG_DEFAULT_CHANNEL', 'pear.php.net'); |
} else { |
define('PEAR_CONFIG_DEFAULT_CHANNEL', 'pecl.php.net'); |
} |
if (getenv('PHP_PEAR_SYSCONF_DIR')) { |
define('PEAR_CONFIG_SYSCONFDIR', getenv('PHP_PEAR_SYSCONF_DIR')); |
} elseif (getenv('SystemRoot')) { |
define('PEAR_CONFIG_SYSCONFDIR', getenv('SystemRoot')); |
} else { |
define('PEAR_CONFIG_SYSCONFDIR', PHP_SYSCONFDIR); |
} |
// Default for master_server |
if (getenv('PHP_PEAR_MASTER_SERVER')) { |
define('PEAR_CONFIG_DEFAULT_MASTER_SERVER', getenv('PHP_PEAR_MASTER_SERVER')); |
} else { |
define('PEAR_CONFIG_DEFAULT_MASTER_SERVER', 'pear.php.net'); |
} |
// Default for http_proxy |
if (getenv('PHP_PEAR_HTTP_PROXY')) { |
define('PEAR_CONFIG_DEFAULT_HTTP_PROXY', getenv('PHP_PEAR_HTTP_PROXY')); |
} elseif (getenv('http_proxy')) { |
define('PEAR_CONFIG_DEFAULT_HTTP_PROXY', getenv('http_proxy')); |
} else { |
define('PEAR_CONFIG_DEFAULT_HTTP_PROXY', ''); |
} |
// Default for php_dir |
if (getenv('PHP_PEAR_INSTALL_DIR')) { |
define('PEAR_CONFIG_DEFAULT_PHP_DIR', getenv('PHP_PEAR_INSTALL_DIR')); |
} else { |
if (@file_exists($PEAR_INSTALL_DIR) && is_dir($PEAR_INSTALL_DIR)) { |
define('PEAR_CONFIG_DEFAULT_PHP_DIR', $PEAR_INSTALL_DIR); |
} else { |
define('PEAR_CONFIG_DEFAULT_PHP_DIR', $PEAR_INSTALL_DIR); |
} |
} |
// Default for metadata_dir |
if (getenv('PHP_PEAR_METADATA_DIR')) { |
define('PEAR_CONFIG_DEFAULT_METADATA_DIR', getenv('PHP_PEAR_METADATA_DIR')); |
} else { |
define('PEAR_CONFIG_DEFAULT_METADATA_DIR', ''); |
} |
// Default for ext_dir |
if (getenv('PHP_PEAR_EXTENSION_DIR')) { |
define('PEAR_CONFIG_DEFAULT_EXT_DIR', getenv('PHP_PEAR_EXTENSION_DIR')); |
} else { |
if (ini_get('extension_dir')) { |
define('PEAR_CONFIG_DEFAULT_EXT_DIR', ini_get('extension_dir')); |
} elseif (defined('PEAR_EXTENSION_DIR') && |
file_exists(PEAR_EXTENSION_DIR) && is_dir(PEAR_EXTENSION_DIR)) { |
define('PEAR_CONFIG_DEFAULT_EXT_DIR', PEAR_EXTENSION_DIR); |
} elseif (defined('PHP_EXTENSION_DIR')) { |
define('PEAR_CONFIG_DEFAULT_EXT_DIR', PHP_EXTENSION_DIR); |
} else { |
define('PEAR_CONFIG_DEFAULT_EXT_DIR', '.'); |
} |
} |
// Default for doc_dir |
if (getenv('PHP_PEAR_DOC_DIR')) { |
define('PEAR_CONFIG_DEFAULT_DOC_DIR', getenv('PHP_PEAR_DOC_DIR')); |
} else { |
define('PEAR_CONFIG_DEFAULT_DOC_DIR', |
$PEAR_INSTALL_DIR.DIRECTORY_SEPARATOR.'docs'); |
} |
// Default for bin_dir |
if (getenv('PHP_PEAR_BIN_DIR')) { |
define('PEAR_CONFIG_DEFAULT_BIN_DIR', getenv('PHP_PEAR_BIN_DIR')); |
} else { |
define('PEAR_CONFIG_DEFAULT_BIN_DIR', PHP_BINDIR); |
} |
// Default for data_dir |
if (getenv('PHP_PEAR_DATA_DIR')) { |
define('PEAR_CONFIG_DEFAULT_DATA_DIR', getenv('PHP_PEAR_DATA_DIR')); |
} else { |
define('PEAR_CONFIG_DEFAULT_DATA_DIR', |
$PEAR_INSTALL_DIR.DIRECTORY_SEPARATOR.'data'); |
} |
// Default for cfg_dir |
if (getenv('PHP_PEAR_CFG_DIR')) { |
define('PEAR_CONFIG_DEFAULT_CFG_DIR', getenv('PHP_PEAR_CFG_DIR')); |
} else { |
define('PEAR_CONFIG_DEFAULT_CFG_DIR', |
$PEAR_INSTALL_DIR.DIRECTORY_SEPARATOR.'cfg'); |
} |
// Default for www_dir |
if (getenv('PHP_PEAR_WWW_DIR')) { |
define('PEAR_CONFIG_DEFAULT_WWW_DIR', getenv('PHP_PEAR_WWW_DIR')); |
} else { |
define('PEAR_CONFIG_DEFAULT_WWW_DIR', |
$PEAR_INSTALL_DIR.DIRECTORY_SEPARATOR.'www'); |
} |
// Default for man_dir |
if (getenv('PHP_PEAR_MAN_DIR')) { |
define('PEAR_CONFIG_DEFAULT_MAN_DIR', getenv('PHP_PEAR_MAN_DIR')); |
} else { |
if (defined('PHP_MANDIR')) { // Added in PHP5.3.7 |
define('PEAR_CONFIG_DEFAULT_MAN_DIR', PHP_MANDIR); |
} else { |
define('PEAR_CONFIG_DEFAULT_MAN_DIR', PHP_PREFIX . DIRECTORY_SEPARATOR . |
'local' . DIRECTORY_SEPARATOR .'man'); |
} |
} |
// Default for test_dir |
if (getenv('PHP_PEAR_TEST_DIR')) { |
define('PEAR_CONFIG_DEFAULT_TEST_DIR', getenv('PHP_PEAR_TEST_DIR')); |
} else { |
define('PEAR_CONFIG_DEFAULT_TEST_DIR', |
$PEAR_INSTALL_DIR.DIRECTORY_SEPARATOR.'tests'); |
} |
// Default for temp_dir |
if (getenv('PHP_PEAR_TEMP_DIR')) { |
define('PEAR_CONFIG_DEFAULT_TEMP_DIR', getenv('PHP_PEAR_TEMP_DIR')); |
} else { |
define('PEAR_CONFIG_DEFAULT_TEMP_DIR', |
System::tmpdir() . DIRECTORY_SEPARATOR . 'pear' . |
DIRECTORY_SEPARATOR . 'temp'); |
} |
// Default for cache_dir |
if (getenv('PHP_PEAR_CACHE_DIR')) { |
define('PEAR_CONFIG_DEFAULT_CACHE_DIR', getenv('PHP_PEAR_CACHE_DIR')); |
} else { |
define('PEAR_CONFIG_DEFAULT_CACHE_DIR', |
System::tmpdir() . DIRECTORY_SEPARATOR . 'pear' . |
DIRECTORY_SEPARATOR . 'cache'); |
} |
// Default for download_dir |
if (getenv('PHP_PEAR_DOWNLOAD_DIR')) { |
define('PEAR_CONFIG_DEFAULT_DOWNLOAD_DIR', getenv('PHP_PEAR_DOWNLOAD_DIR')); |
} else { |
define('PEAR_CONFIG_DEFAULT_DOWNLOAD_DIR', |
System::tmpdir() . DIRECTORY_SEPARATOR . 'pear' . |
DIRECTORY_SEPARATOR . 'download'); |
} |
// Default for php_bin |
if (getenv('PHP_PEAR_PHP_BIN')) { |
define('PEAR_CONFIG_DEFAULT_PHP_BIN', getenv('PHP_PEAR_PHP_BIN')); |
} else { |
define('PEAR_CONFIG_DEFAULT_PHP_BIN', PEAR_CONFIG_DEFAULT_BIN_DIR. |
DIRECTORY_SEPARATOR.'php'.(OS_WINDOWS ? '.exe' : '')); |
} |
// Default for verbose |
if (getenv('PHP_PEAR_VERBOSE')) { |
define('PEAR_CONFIG_DEFAULT_VERBOSE', getenv('PHP_PEAR_VERBOSE')); |
} else { |
define('PEAR_CONFIG_DEFAULT_VERBOSE', 1); |
} |
// Default for preferred_state |
if (getenv('PHP_PEAR_PREFERRED_STATE')) { |
define('PEAR_CONFIG_DEFAULT_PREFERRED_STATE', getenv('PHP_PEAR_PREFERRED_STATE')); |
} else { |
define('PEAR_CONFIG_DEFAULT_PREFERRED_STATE', 'stable'); |
} |
// Default for umask |
if (getenv('PHP_PEAR_UMASK')) { |
define('PEAR_CONFIG_DEFAULT_UMASK', getenv('PHP_PEAR_UMASK')); |
} else { |
define('PEAR_CONFIG_DEFAULT_UMASK', decoct(umask())); |
} |
// Default for cache_ttl |
if (getenv('PHP_PEAR_CACHE_TTL')) { |
define('PEAR_CONFIG_DEFAULT_CACHE_TTL', getenv('PHP_PEAR_CACHE_TTL')); |
} else { |
define('PEAR_CONFIG_DEFAULT_CACHE_TTL', 3600); |
} |
// Default for sig_type |
if (getenv('PHP_PEAR_SIG_TYPE')) { |
define('PEAR_CONFIG_DEFAULT_SIG_TYPE', getenv('PHP_PEAR_SIG_TYPE')); |
} else { |
define('PEAR_CONFIG_DEFAULT_SIG_TYPE', 'gpg'); |
} |
// Default for sig_bin |
if (getenv('PHP_PEAR_SIG_BIN')) { |
define('PEAR_CONFIG_DEFAULT_SIG_BIN', getenv('PHP_PEAR_SIG_BIN')); |
} else { |
define('PEAR_CONFIG_DEFAULT_SIG_BIN', |
System::which( |
'gpg', OS_WINDOWS ? 'c:\gnupg\gpg.exe' : '/usr/local/bin/gpg')); |
} |
// Default for sig_keydir |
if (getenv('PHP_PEAR_SIG_KEYDIR')) { |
define('PEAR_CONFIG_DEFAULT_SIG_KEYDIR', getenv('PHP_PEAR_SIG_KEYDIR')); |
} else { |
define('PEAR_CONFIG_DEFAULT_SIG_KEYDIR', |
PEAR_CONFIG_SYSCONFDIR . DIRECTORY_SEPARATOR . 'pearkeys'); |
} |
/** |
* This is a class for storing configuration data, keeping track of |
* which are system-defined, user-defined or defaulted. |
* @category pear |
* @package PEAR |
* @author Stig Bakken <ssb@php.net> |
* @author Greg Beaver <cellog@php.net> |
* @copyright 1997-2009 The Authors |
* @license http://opensource.org/licenses/bsd-license.php New BSD License |
* @version Release: 1.10.1 |
* @link http://pear.php.net/package/PEAR |
* @since Class available since Release 0.1 |
*/ |
class PEAR_Config extends PEAR |
{ |
/** |
* Array of config files used. |
* |
* @var array layer => config file |
*/ |
var $files = array( |
'system' => '', |
'user' => '', |
); |
var $layers = array(); |
/** |
* Configuration data, two-dimensional array where the first |
* dimension is the config layer ('user', 'system' and 'default'), |
* and the second dimension is keyname => value. |
* |
* The order in the first dimension is important! Earlier |
* layers will shadow later ones when a config value is |
* requested (if a 'user' value exists, it will be returned first, |
* then 'system' and finally 'default'). |
* |
* @var array layer => array(keyname => value, ...) |
*/ |
var $configuration = array( |
'user' => array(), |
'system' => array(), |
'default' => array(), |
); |
/** |
* Configuration values that can be set for a channel |
* |
* All other configuration values can only have a global value |
* @var array |
* @access private |
*/ |
var $_channelConfigInfo = array( |
'php_dir', 'ext_dir', 'doc_dir', 'bin_dir', 'data_dir', 'cfg_dir', |
'test_dir', 'www_dir', 'php_bin', 'php_prefix', 'php_suffix', 'username', |
'password', 'verbose', 'preferred_state', 'umask', 'preferred_mirror', 'php_ini' |
); |
/** |
* Channels that can be accessed |
* @see setChannels() |
* @var array |
* @access private |
*/ |
var $_channels = array('pear.php.net', 'pecl.php.net', '__uri'); |
/** |
* This variable is used to control the directory values returned |
* @see setInstallRoot(); |
* @var string|false |
* @access private |
*/ |
var $_installRoot = false; |
/** |
* If requested, this will always refer to the registry |
* contained in php_dir |
* @var PEAR_Registry |
*/ |
var $_registry = array(); |
/** |
* @var array |
* @access private |
*/ |
var $_regInitialized = array(); |
/** |
* @var bool |
* @access private |
*/ |
var $_noRegistry = false; |
/** |
* amount of errors found while parsing config |
* @var integer |
* @access private |
*/ |
var $_errorsFound = 0; |
var $_lastError = null; |
/** |
* Information about the configuration data. Stores the type, |
* default value and a documentation string for each configuration |
* value. |
* |
* @var array layer => array(infotype => value, ...) |
*/ |
var $configuration_info = array( |
// Channels/Internet Access |
'default_channel' => array( |
'type' => 'string', |
'default' => PEAR_CONFIG_DEFAULT_CHANNEL, |
'doc' => 'the default channel to use for all non explicit commands', |
'prompt' => 'Default Channel', |
'group' => 'Internet Access', |
), |
'preferred_mirror' => array( |
'type' => 'string', |
'default' => PEAR_CONFIG_DEFAULT_CHANNEL, |
'doc' => 'the default server or mirror to use for channel actions', |
'prompt' => 'Default Channel Mirror', |
'group' => 'Internet Access', |
), |
'remote_config' => array( |
'type' => 'password', |
'default' => '', |
'doc' => 'ftp url of remote configuration file to use for synchronized install', |
'prompt' => 'Remote Configuration File', |
'group' => 'Internet Access', |
), |
'auto_discover' => array( |
'type' => 'integer', |
'default' => 0, |
'doc' => 'whether to automatically discover new channels', |
'prompt' => 'Auto-discover new Channels', |
'group' => 'Internet Access', |
), |
// Internet Access |
'master_server' => array( |
'type' => 'string', |
'default' => 'pear.php.net', |
'doc' => 'name of the main PEAR server [NOT USED IN THIS VERSION]', |
'prompt' => 'PEAR server [DEPRECATED]', |
'group' => 'Internet Access', |
), |
'http_proxy' => array( |
'type' => 'string', |
'default' => PEAR_CONFIG_DEFAULT_HTTP_PROXY, |
'doc' => 'HTTP proxy (host:port) to use when downloading packages', |
'prompt' => 'HTTP Proxy Server Address', |
'group' => 'Internet Access', |
), |
// File Locations |
'php_dir' => array( |
'type' => 'directory', |
'default' => PEAR_CONFIG_DEFAULT_PHP_DIR, |
'doc' => 'directory where .php files are installed', |
'prompt' => 'PEAR directory', |
'group' => 'File Locations', |
), |
'ext_dir' => array( |
'type' => 'directory', |
'default' => PEAR_CONFIG_DEFAULT_EXT_DIR, |
'doc' => 'directory where loadable extensions are installed', |
'prompt' => 'PHP extension directory', |
'group' => 'File Locations', |
), |
'doc_dir' => array( |
'type' => 'directory', |
'default' => PEAR_CONFIG_DEFAULT_DOC_DIR, |
'doc' => 'directory where documentation is installed', |
'prompt' => 'PEAR documentation directory', |
'group' => 'File Locations', |
), |
'bin_dir' => array( |
'type' => 'directory', |
'default' => PEAR_CONFIG_DEFAULT_BIN_DIR, |
'doc' => 'directory where executables are installed', |
'prompt' => 'PEAR executables directory', |
'group' => 'File Locations', |
), |
'data_dir' => array( |
'type' => 'directory', |
'default' => PEAR_CONFIG_DEFAULT_DATA_DIR, |
'doc' => 'directory where data files are installed', |
'prompt' => 'PEAR data directory', |
'group' => 'File Locations (Advanced)', |
), |
'cfg_dir' => array( |
'type' => 'directory', |
'default' => PEAR_CONFIG_DEFAULT_CFG_DIR, |
'doc' => 'directory where modifiable configuration files are installed', |
'prompt' => 'PEAR configuration file directory', |
'group' => 'File Locations (Advanced)', |
), |
'www_dir' => array( |
'type' => 'directory', |
'default' => PEAR_CONFIG_DEFAULT_WWW_DIR, |
'doc' => 'directory where www frontend files (html/js) are installed', |
'prompt' => 'PEAR www files directory', |
'group' => 'File Locations (Advanced)', |
), |
'man_dir' => array( |
'type' => 'directory', |
'default' => PEAR_CONFIG_DEFAULT_MAN_DIR, |
'doc' => 'directory where unix manual pages are installed', |
'prompt' => 'Systems manpage files directory', |
'group' => 'File Locations (Advanced)', |
), |
'test_dir' => array( |
'type' => 'directory', |
'default' => PEAR_CONFIG_DEFAULT_TEST_DIR, |
'doc' => 'directory where regression tests are installed', |
'prompt' => 'PEAR test directory', |
'group' => 'File Locations (Advanced)', |
), |
'cache_dir' => array( |
'type' => 'directory', |
'default' => PEAR_CONFIG_DEFAULT_CACHE_DIR, |
'doc' => 'directory which is used for web service cache', |
'prompt' => 'PEAR Installer cache directory', |
'group' => 'File Locations (Advanced)', |
), |
'temp_dir' => array( |
'type' => 'directory', |
'default' => PEAR_CONFIG_DEFAULT_TEMP_DIR, |
'doc' => 'directory which is used for all temp files', |
'prompt' => 'PEAR Installer temp directory', |
'group' => 'File Locations (Advanced)', |
), |
'download_dir' => array( |
'type' => 'directory', |
'default' => PEAR_CONFIG_DEFAULT_DOWNLOAD_DIR, |
'doc' => 'directory which is used for all downloaded files', |
'prompt' => 'PEAR Installer download directory', |
'group' => 'File Locations (Advanced)', |
), |
'php_bin' => array( |
'type' => 'file', |
'default' => PEAR_CONFIG_DEFAULT_PHP_BIN, |
'doc' => 'PHP CLI/CGI binary for executing scripts', |
'prompt' => 'PHP CLI/CGI binary', |
'group' => 'File Locations (Advanced)', |
), |
'php_prefix' => array( |
'type' => 'string', |
'default' => '', |
'doc' => '--program-prefix for php_bin\'s ./configure, used for pecl installs', |
'prompt' => '--program-prefix passed to PHP\'s ./configure', |
'group' => 'File Locations (Advanced)', |
), |
'php_suffix' => array( |
'type' => 'string', |
'default' => '', |
'doc' => '--program-suffix for php_bin\'s ./configure, used for pecl installs', |
'prompt' => '--program-suffix passed to PHP\'s ./configure', |
'group' => 'File Locations (Advanced)', |
), |
'php_ini' => array( |
'type' => 'file', |
'default' => '', |
'doc' => 'location of php.ini in which to enable PECL extensions on install', |
'prompt' => 'php.ini location', |
'group' => 'File Locations (Advanced)', |
), |
'metadata_dir' => array( |
'type' => 'directory', |
'default' => PEAR_CONFIG_DEFAULT_METADATA_DIR, |
'doc' => 'directory where metadata files are installed (registry, filemap, channels, ...)', |
'prompt' => 'PEAR metadata directory', |
'group' => 'File Locations (Advanced)', |
), |
// Maintainers |
'username' => array( |
'type' => 'string', |
'default' => '', |
'doc' => '(maintainers) your PEAR account name', |
'prompt' => 'PEAR username (for maintainers)', |
'group' => 'Maintainers', |
), |
'password' => array( |
'type' => 'password', |
'default' => '', |
'doc' => '(maintainers) your PEAR account password', |
'prompt' => 'PEAR password (for maintainers)', |
'group' => 'Maintainers', |
), |
// Advanced |
'verbose' => array( |
'type' => 'integer', |
'default' => PEAR_CONFIG_DEFAULT_VERBOSE, |
'doc' => 'verbosity level |
0: really quiet |
1: somewhat quiet |
2: verbose |
3: debug', |
'prompt' => 'Debug Log Level', |
'group' => 'Advanced', |
), |
'preferred_state' => array( |
'type' => 'set', |
'default' => PEAR_CONFIG_DEFAULT_PREFERRED_STATE, |
'doc' => 'the installer will prefer releases with this state when installing packages without a version or state specified', |
'valid_set' => array( |
'stable', 'beta', 'alpha', 'devel', 'snapshot'), |
'prompt' => 'Preferred Package State', |
'group' => 'Advanced', |
), |
'umask' => array( |
'type' => 'mask', |
'default' => PEAR_CONFIG_DEFAULT_UMASK, |
'doc' => 'umask used when creating files (Unix-like systems only)', |
'prompt' => 'Unix file mask', |
'group' => 'Advanced', |
), |
'cache_ttl' => array( |
'type' => 'integer', |
'default' => PEAR_CONFIG_DEFAULT_CACHE_TTL, |
'doc' => 'amount of secs where the local cache is used and not updated', |
'prompt' => 'Cache TimeToLive', |
'group' => 'Advanced', |
), |
'sig_type' => array( |
'type' => 'set', |
'default' => PEAR_CONFIG_DEFAULT_SIG_TYPE, |
'doc' => 'which package signature mechanism to use', |
'valid_set' => array('gpg'), |
'prompt' => 'Package Signature Type', |
'group' => 'Maintainers', |
), |
'sig_bin' => array( |
'type' => 'string', |
'default' => PEAR_CONFIG_DEFAULT_SIG_BIN, |
'doc' => 'which package signature mechanism to use', |
'prompt' => 'Signature Handling Program', |
'group' => 'Maintainers', |
), |
'sig_keyid' => array( |
'type' => 'string', |
'default' => '', |
'doc' => 'which key to use for signing with', |
'prompt' => 'Signature Key Id', |
'group' => 'Maintainers', |
), |
'sig_keydir' => array( |
'type' => 'directory', |
'default' => PEAR_CONFIG_DEFAULT_SIG_KEYDIR, |
'doc' => 'directory where signature keys are located', |
'prompt' => 'Signature Key Directory', |
'group' => 'Maintainers', |
), |
// __channels is reserved - used for channel-specific configuration |
); |
/** |
* Constructor. |
* |
* @param string file to read user-defined options from |
* @param string file to read system-wide defaults from |
* @param bool determines whether a registry object "follows" |
* the value of php_dir (is automatically created |
* and moved when php_dir is changed) |
* @param bool if true, fails if configuration files cannot be loaded |
* |
* @access public |
* |
* @see PEAR_Config::singleton |
*/ |
function __construct($user_file = '', $system_file = '', $ftp_file = false, |
$strict = true) |
{ |
parent::__construct(); |
PEAR_Installer_Role::initializeConfig($this); |
$sl = DIRECTORY_SEPARATOR; |
if (empty($user_file)) { |
if (OS_WINDOWS) { |
$user_file = PEAR_CONFIG_SYSCONFDIR . $sl . 'pear.ini'; |
} else { |
$user_file = getenv('HOME') . $sl . '.pearrc'; |
} |
} |
if (empty($system_file)) { |
$system_file = PEAR_CONFIG_SYSCONFDIR . $sl; |
if (OS_WINDOWS) { |
$system_file .= 'pearsys.ini'; |
} else { |
$system_file .= 'pear.conf'; |
} |
} |
$this->layers = array_keys($this->configuration); |
$this->files['user'] = $user_file; |
$this->files['system'] = $system_file; |
if ($user_file && file_exists($user_file)) { |
$this->pushErrorHandling(PEAR_ERROR_RETURN); |
$this->readConfigFile($user_file, 'user', $strict); |
$this->popErrorHandling(); |
if ($this->_errorsFound > 0) { |
return; |
} |
} |
if ($system_file && @file_exists($system_file)) { |
$this->mergeConfigFile($system_file, false, 'system', $strict); |
if ($this->_errorsFound > 0) { |
return; |
} |
} |
if (!$ftp_file) { |
$ftp_file = $this->get('remote_config'); |
} |
if ($ftp_file && defined('PEAR_REMOTEINSTALL_OK')) { |
$this->readFTPConfigFile($ftp_file); |
} |
foreach ($this->configuration_info as $key => $info) { |
$this->configuration['default'][$key] = $info['default']; |
} |
$this->_registry['default'] = new PEAR_Registry( |
$this->configuration['default']['php_dir'], false, false, |
$this->configuration['default']['metadata_dir']); |
$this->_registry['default']->setConfig($this, false); |
$this->_regInitialized['default'] = false; |
//$GLOBALS['_PEAR_Config_instance'] = &$this; |
} |
/** |
* Return the default locations of user and system configuration files |
*/ |
public static function getDefaultConfigFiles() |
{ |
$sl = DIRECTORY_SEPARATOR; |
if (OS_WINDOWS) { |
return array( |
'user' => PEAR_CONFIG_SYSCONFDIR . $sl . 'pear.ini', |
'system' => PEAR_CONFIG_SYSCONFDIR . $sl . 'pearsys.ini' |
); |
} |
return array( |
'user' => getenv('HOME') . $sl . '.pearrc', |
'system' => PEAR_CONFIG_SYSCONFDIR . $sl . 'pear.conf' |
); |
} |
/** |
* Static singleton method. If you want to keep only one instance |
* of this class in use, this method will give you a reference to |
* the last created PEAR_Config object if one exists, or create a |
* new object. |
* |
* @param string (optional) file to read user-defined options from |
* @param string (optional) file to read system-wide defaults from |
* |
* @return object an existing or new PEAR_Config instance |
* |
* @see PEAR_Config::PEAR_Config |
*/ |
public static function &singleton($user_file = '', $system_file = '', $strict = true) |
{ |
if (is_object($GLOBALS['_PEAR_Config_instance'])) { |
return $GLOBALS['_PEAR_Config_instance']; |
} |
$t_conf = new PEAR_Config($user_file, $system_file, false, $strict); |
if ($t_conf->_errorsFound > 0) { |
return $t_conf->lastError; |
} |
$GLOBALS['_PEAR_Config_instance'] = &$t_conf; |
return $GLOBALS['_PEAR_Config_instance']; |
} |
/** |
* Determine whether any configuration files have been detected, and whether a |
* registry object can be retrieved from this configuration. |
* @return bool |
* @since PEAR 1.4.0a1 |
*/ |
function validConfiguration() |
{ |
if ($this->isDefinedLayer('user') || $this->isDefinedLayer('system')) { |
return true; |
} |
return false; |
} |
/** |
* Reads configuration data from a file. All existing values in |
* the config layer are discarded and replaced with data from the |
* file. |
* @param string file to read from, if NULL or not specified, the |
* last-used file for the same layer (second param) is used |
* @param string config layer to insert data into ('user' or 'system') |
* @return bool TRUE on success or a PEAR error on failure |
*/ |
function readConfigFile($file = null, $layer = 'user', $strict = true) |
{ |
if (empty($this->files[$layer])) { |
return $this->raiseError("unknown config layer `$layer'"); |
} |
if ($file === null) { |
$file = $this->files[$layer]; |
} |
$data = $this->_readConfigDataFrom($file); |
if (PEAR::isError($data)) { |
if (!$strict) { |
return true; |
} |
$this->_errorsFound++; |
$this->lastError = $data; |
return $data; |
} |
$this->files[$layer] = $file; |
$this->_decodeInput($data); |
$this->configuration[$layer] = $data; |
$this->_setupChannels(); |
if (!$this->_noRegistry && ($phpdir = $this->get('php_dir', $layer, 'pear.php.net'))) { |
$this->_registry[$layer] = new PEAR_Registry( |
$phpdir, false, false, |
$this->get('metadata_dir', $layer, 'pear.php.net')); |
$this->_registry[$layer]->setConfig($this, false); |
$this->_regInitialized[$layer] = false; |
} else { |
unset($this->_registry[$layer]); |
} |
return true; |
} |
/** |
* @param string url to the remote config file, like ftp://www.example.com/pear/config.ini |
* @return true|PEAR_Error |
*/ |
function readFTPConfigFile($path) |
{ |
do { // poor man's try |
if (!class_exists('PEAR_FTP')) { |
if (!class_exists('PEAR_Common')) { |
require_once 'PEAR/Common.php'; |
} |
if (PEAR_Common::isIncludeable('PEAR/FTP.php')) { |
require_once 'PEAR/FTP.php'; |
} |
} |
if (!class_exists('PEAR_FTP')) { |
return PEAR::raiseError('PEAR_RemoteInstaller must be installed to use remote config'); |
} |
$this->_ftp = new PEAR_FTP; |
$this->_ftp->pushErrorHandling(PEAR_ERROR_RETURN); |
$e = $this->_ftp->init($path); |
if (PEAR::isError($e)) { |
$this->_ftp->popErrorHandling(); |
return $e; |
} |
$tmp = System::mktemp('-d'); |
PEAR_Common::addTempFile($tmp); |
$e = $this->_ftp->get(basename($path), $tmp . DIRECTORY_SEPARATOR . |
'pear.ini', false, FTP_BINARY); |
if (PEAR::isError($e)) { |
$this->_ftp->popErrorHandling(); |
return $e; |
} |
PEAR_Common::addTempFile($tmp . DIRECTORY_SEPARATOR . 'pear.ini'); |
$this->_ftp->disconnect(); |
$this->_ftp->popErrorHandling(); |
$this->files['ftp'] = $tmp . DIRECTORY_SEPARATOR . 'pear.ini'; |
$e = $this->readConfigFile(null, 'ftp'); |
if (PEAR::isError($e)) { |
return $e; |
} |
$fail = array(); |
foreach ($this->configuration_info as $key => $val) { |
if (in_array($this->getGroup($key), |
array('File Locations', 'File Locations (Advanced)')) && |
$this->getType($key) == 'directory') { |
// any directory configs must be set for this to work |
if (!isset($this->configuration['ftp'][$key])) { |
$fail[] = $key; |
} |
} |
} |
if (!count($fail)) { |
return true; |
} |
$fail = '"' . implode('", "', $fail) . '"'; |
unset($this->files['ftp']); |
unset($this->configuration['ftp']); |
return PEAR::raiseError('ERROR: Ftp configuration file must set all ' . |
'directory configuration variables. These variables were not set: ' . |
$fail); |
} while (false); // poor man's catch |
unset($this->files['ftp']); |
return PEAR::raiseError('no remote host specified'); |
} |
/** |
* Reads the existing configurations and creates the _channels array from it |
*/ |
function _setupChannels() |
{ |
$set = array_flip(array_values($this->_channels)); |
foreach ($this->configuration as $layer => $data) { |
$i = 1000; |
if (isset($data['__channels']) && is_array($data['__channels'])) { |
foreach ($data['__channels'] as $channel => $info) { |
$set[$channel] = $i++; |
} |
} |
} |
$this->_channels = array_values(array_flip($set)); |
$this->setChannels($this->_channels); |
} |
function deleteChannel($channel) |
{ |
$ch = strtolower($channel); |
foreach ($this->configuration as $layer => $data) { |
if (isset($data['__channels']) && isset($data['__channels'][$ch])) { |
unset($this->configuration[$layer]['__channels'][$ch]); |
} |
} |
$this->_channels = array_flip($this->_channels); |
unset($this->_channels[$ch]); |
$this->_channels = array_flip($this->_channels); |
} |
/** |
* Merges data into a config layer from a file. Does the same |
* thing as readConfigFile, except it does not replace all |
* existing values in the config layer. |
* @param string file to read from |
* @param bool whether to overwrite existing data (default TRUE) |
* @param string config layer to insert data into ('user' or 'system') |
* @param string if true, errors are returned if file opening fails |
* @return bool TRUE on success or a PEAR error on failure |
*/ |
function mergeConfigFile($file, $override = true, $layer = 'user', $strict = true) |
{ |
if (empty($this->files[$layer])) { |
return $this->raiseError("unknown config layer `$layer'"); |
} |
if ($file === null) { |
$file = $this->files[$layer]; |
} |
$data = $this->_readConfigDataFrom($file); |
if (PEAR::isError($data)) { |
if (!$strict) { |
return true; |
} |
$this->_errorsFound++; |
$this->lastError = $data; |
return $data; |
} |
$this->_decodeInput($data); |
if ($override) { |
$this->configuration[$layer] = |
PEAR_Config::arrayMergeRecursive($this->configuration[$layer], $data); |
} else { |
$this->configuration[$layer] = |
PEAR_Config::arrayMergeRecursive($data, $this->configuration[$layer]); |
} |
$this->_setupChannels(); |
if (!$this->_noRegistry && ($phpdir = $this->get('php_dir', $layer, 'pear.php.net'))) { |
$this->_registry[$layer] = new PEAR_Registry( |
$phpdir, false, false, |
$this->get('metadata_dir', $layer, 'pear.php.net')); |
$this->_registry[$layer]->setConfig($this, false); |
$this->_regInitialized[$layer] = false; |
} else { |
unset($this->_registry[$layer]); |
} |
return true; |
} |
/** |
* @param array |
* @param array |
* @return array |
*/ |
public static function arrayMergeRecursive($arr2, $arr1) |
{ |
$ret = array(); |
foreach ($arr2 as $key => $data) { |
if (!isset($arr1[$key])) { |
$ret[$key] = $data; |
unset($arr1[$key]); |
continue; |
} |
if (is_array($data)) { |
if (!is_array($arr1[$key])) { |
$ret[$key] = $arr1[$key]; |
unset($arr1[$key]); |
continue; |
} |
$ret[$key] = PEAR_Config::arrayMergeRecursive($arr1[$key], $arr2[$key]); |
unset($arr1[$key]); |
} |
} |
return array_merge($ret, $arr1); |
} |
/** |
* Writes data into a config layer from a file. |
* |
* @param string|null file to read from, or null for default |
* @param string config layer to insert data into ('user' or |
* 'system') |
* @param string|null data to write to config file or null for internal data [DEPRECATED] |
* @return bool TRUE on success or a PEAR error on failure |
*/ |
function writeConfigFile($file = null, $layer = 'user', $data = null) |
{ |
$this->_lazyChannelSetup($layer); |
if ($layer == 'both' || $layer == 'all') { |
foreach ($this->files as $type => $file) { |
$err = $this->writeConfigFile($file, $type, $data); |
if (PEAR::isError($err)) { |
return $err; |
} |
} |
return true; |
} |
if (empty($this->files[$layer])) { |
return $this->raiseError("unknown config file type `$layer'"); |
} |
if ($file === null) { |
$file = $this->files[$layer]; |
} |
$data = ($data === null) ? $this->configuration[$layer] : $data; |
$this->_encodeOutput($data); |
$opt = array('-p', dirname($file)); |
if (!@System::mkDir($opt)) { |
return $this->raiseError("could not create directory: " . dirname($file)); |
} |
if (file_exists($file) && is_file($file) && !is_writeable($file)) { |
return $this->raiseError("no write access to $file!"); |
} |
$fp = @fopen($file, "w"); |
if (!$fp) { |
return $this->raiseError("PEAR_Config::writeConfigFile fopen('$file','w') failed ($php_errormsg)"); |
} |
$contents = "#PEAR_Config 0.9\n" . serialize($data); |
if (!@fwrite($fp, $contents)) { |
return $this->raiseError("PEAR_Config::writeConfigFile: fwrite failed ($php_errormsg)"); |
} |
return true; |
} |
/** |
* Reads configuration data from a file and returns the parsed data |
* in an array. |
* |
* @param string file to read from |
* @return array configuration data or a PEAR error on failure |
* @access private |
*/ |
function _readConfigDataFrom($file) |
{ |
$fp = false; |
if (file_exists($file)) { |
$fp = @fopen($file, "r"); |
} |
if (!$fp) { |
return $this->raiseError("PEAR_Config::readConfigFile fopen('$file','r') failed"); |
} |
$size = filesize($file); |
fclose($fp); |
$contents = file_get_contents($file); |
if (empty($contents)) { |
return $this->raiseError('Configuration file "' . $file . '" is empty'); |
} |
$version = false; |
if (preg_match('/^#PEAR_Config\s+(\S+)\s+/si', $contents, $matches)) { |
$version = $matches[1]; |
$contents = substr($contents, strlen($matches[0])); |
} else { |
// Museum config file |
if (substr($contents,0,2) == 'a:') { |
$version = '0.1'; |
} |
} |
if ($version && version_compare("$version", '1', '<')) { |
// no '@', it is possible that unserialize |
// raises a notice but it seems to block IO to |
// STDOUT if a '@' is used and a notice is raise |
$data = unserialize($contents); |
if (!is_array($data) && !$data) { |
if ($contents == serialize(false)) { |
$data = array(); |
} else { |
$err = $this->raiseError("PEAR_Config: bad data in $file"); |
return $err; |
} |
} |
if (!is_array($data)) { |
if (strlen(trim($contents)) > 0) { |
$error = "PEAR_Config: bad data in $file"; |
$err = $this->raiseError($error); |
return $err; |
} |
$data = array(); |
} |
// add parsing of newer formats here... |
} else { |
$err = $this->raiseError("$file: unknown version `$version'"); |
return $err; |
} |
return $data; |
} |
/** |
* Gets the file used for storing the config for a layer |
* |
* @param string $layer 'user' or 'system' |
*/ |
function getConfFile($layer) |
{ |
return $this->files[$layer]; |
} |
/** |
* @param string Configuration class name, used for detecting duplicate calls |
* @param array information on a role as parsed from its xml file |
* @return true|PEAR_Error |
* @access private |
*/ |
function _addConfigVars($class, $vars) |
{ |
static $called = array(); |
if (isset($called[$class])) { |
return; |
} |
$called[$class] = 1; |
if (count($vars) > 3) { |
return $this->raiseError('Roles can only define 3 new config variables or less'); |
} |
foreach ($vars as $name => $var) { |
if (!is_array($var)) { |
return $this->raiseError('Configuration information must be an array'); |
} |
if (!isset($var['type'])) { |
return $this->raiseError('Configuration information must contain a type'); |
} elseif (!in_array($var['type'], |
array('string', 'mask', 'password', 'directory', 'file', 'set'))) { |
return $this->raiseError( |
'Configuration type must be one of directory, file, string, ' . |
'mask, set, or password'); |
} |
if (!isset($var['default'])) { |
return $this->raiseError( |
'Configuration information must contain a default value ("default" index)'); |
} |
if (is_array($var['default'])) { |
$real_default = ''; |
foreach ($var['default'] as $config_var => $val) { |
if (strpos($config_var, 'text') === 0) { |
$real_default .= $val; |
} elseif (strpos($config_var, 'constant') === 0) { |
if (!defined($val)) { |
return $this->raiseError( |
'Unknown constant "' . $val . '" requested in ' . |
'default value for configuration variable "' . |
$name . '"'); |
} |
$real_default .= constant($val); |
} elseif (isset($this->configuration_info[$config_var])) { |
$real_default .= |
$this->configuration_info[$config_var]['default']; |
} else { |
return $this->raiseError( |
'Unknown request for "' . $config_var . '" value in ' . |
'default value for configuration variable "' . |
$name . '"'); |
} |
} |
$var['default'] = $real_default; |
} |
if ($var['type'] == 'integer') { |
$var['default'] = (integer) $var['default']; |
} |
if (!isset($var['doc'])) { |
return $this->raiseError( |
'Configuration information must contain a summary ("doc" index)'); |
} |
if (!isset($var['prompt'])) { |
return $this->raiseError( |
'Configuration information must contain a simple prompt ("prompt" index)'); |
} |
if (!isset($var['group'])) { |
return $this->raiseError( |
'Configuration information must contain a simple group ("group" index)'); |
} |
if (isset($this->configuration_info[$name])) { |
return $this->raiseError('Configuration variable "' . $name . |
'" already exists'); |
} |
$this->configuration_info[$name] = $var; |
// fix bug #7351: setting custom config variable in a channel fails |
$this->_channelConfigInfo[] = $name; |
} |
return true; |
} |
/** |
* Encodes/scrambles configuration data before writing to files. |
* Currently, 'password' values will be base64-encoded as to avoid |
* that people spot cleartext passwords by accident. |
* |
* @param array (reference) array to encode values in |
* @return bool TRUE on success |
* @access private |
*/ |
function _encodeOutput(&$data) |
{ |
foreach ($data as $key => $value) { |
if ($key == '__channels') { |
foreach ($data['__channels'] as $channel => $blah) { |
$this->_encodeOutput($data['__channels'][$channel]); |
} |
} |
if (!isset($this->configuration_info[$key])) { |
continue; |
} |
$type = $this->configuration_info[$key]['type']; |
switch ($type) { |
// we base64-encode passwords so they are at least |
// not shown in plain by accident |
case 'password': { |
$data[$key] = base64_encode($data[$key]); |
break; |
} |
case 'mask': { |
$data[$key] = octdec($data[$key]); |
break; |
} |
} |
} |
return true; |
} |
/** |
* Decodes/unscrambles configuration data after reading from files. |
* |
* @param array (reference) array to encode values in |
* @return bool TRUE on success |
* @access private |
* |
* @see PEAR_Config::_encodeOutput |
*/ |
function _decodeInput(&$data) |
{ |
if (!is_array($data)) { |
return true; |
} |
foreach ($data as $key => $value) { |
if ($key == '__channels') { |
foreach ($data['__channels'] as $channel => $blah) { |
$this->_decodeInput($data['__channels'][$channel]); |
} |
} |
if (!isset($this->configuration_info[$key])) { |
continue; |
} |
$type = $this->configuration_info[$key]['type']; |
switch ($type) { |
case 'password': { |
$data[$key] = base64_decode($data[$key]); |
break; |
} |
case 'mask': { |
$data[$key] = decoct($data[$key]); |
break; |
} |
} |
} |
return true; |
} |
/** |
* Retrieve the default channel. |
* |
* On startup, channels are not initialized, so if the default channel is not |
* pear.php.net, then initialize the config. |
* @param string registry layer |
* @return string|false |
*/ |
function getDefaultChannel($layer = null) |
{ |
$ret = false; |
if ($layer === null) { |
foreach ($this->layers as $layer) { |
if (isset($this->configuration[$layer]['default_channel'])) { |
$ret = $this->configuration[$layer]['default_channel']; |
break; |
} |
} |
} elseif (isset($this->configuration[$layer]['default_channel'])) { |
$ret = $this->configuration[$layer]['default_channel']; |
} |
if ($ret == 'pear.php.net' && defined('PEAR_RUNTYPE') && PEAR_RUNTYPE == 'pecl') { |
$ret = 'pecl.php.net'; |
} |
if ($ret) { |
if ($ret != 'pear.php.net') { |
$this->_lazyChannelSetup(); |
} |
return $ret; |
} |
return PEAR_CONFIG_DEFAULT_CHANNEL; |
} |
/** |
* Returns a configuration value, prioritizing layers as per the |
* layers property. |
* |
* @param string config key |
* @return mixed the config value, or NULL if not found |
* @access public |
*/ |
function get($key, $layer = null, $channel = false) |
{ |
if (!isset($this->configuration_info[$key])) { |
return null; |
} |
if ($key == '__channels') { |
return null; |
} |
if ($key == 'default_channel') { |
return $this->getDefaultChannel($layer); |
} |
if (!$channel) { |
$channel = $this->getDefaultChannel(); |
} elseif ($channel != 'pear.php.net') { |
$this->_lazyChannelSetup(); |
} |
$channel = strtolower($channel); |
$test = (in_array($key, $this->_channelConfigInfo)) ? |
$this->_getChannelValue($key, $layer, $channel) : |
null; |
if ($test !== null) { |
if ($this->_installRoot) { |
if (in_array($this->getGroup($key), |
array('File Locations', 'File Locations (Advanced)')) && |
$this->getType($key) == 'directory') { |
return $this->_prependPath($test, $this->_installRoot); |
} |
} |
return $test; |
} |
if ($layer === null) { |
foreach ($this->layers as $layer) { |
if (isset($this->configuration[$layer][$key])) { |
$test = $this->configuration[$layer][$key]; |
if ($this->_installRoot) { |
if (in_array($this->getGroup($key), |
array('File Locations', 'File Locations (Advanced)')) && |
$this->getType($key) == 'directory') { |
return $this->_prependPath($test, $this->_installRoot); |
} |
} |
if ($key == 'preferred_mirror') { |
$reg = &$this->getRegistry(); |
if (is_object($reg)) { |
$chan = $reg->getChannel($channel); |
if (PEAR::isError($chan)) { |
return $channel; |
} |
if (!$chan->getMirror($test) && $chan->getName() != $test) { |
return $channel; // mirror does not exist |
} |
} |
} |
return $test; |
} |
} |
} elseif (isset($this->configuration[$layer][$key])) { |
$test = $this->configuration[$layer][$key]; |
if ($this->_installRoot) { |
if (in_array($this->getGroup($key), |
array('File Locations', 'File Locations (Advanced)')) && |
$this->getType($key) == 'directory') { |
return $this->_prependPath($test, $this->_installRoot); |
} |
} |
if ($key == 'preferred_mirror') { |
$reg = &$this->getRegistry(); |
if (is_object($reg)) { |
$chan = $reg->getChannel($channel); |
if (PEAR::isError($chan)) { |
return $channel; |
} |
if (!$chan->getMirror($test) && $chan->getName() != $test) { |
return $channel; // mirror does not exist |
} |
} |
} |
return $test; |
} |
return null; |
} |
/** |
* Returns a channel-specific configuration value, prioritizing layers as per the |
* layers property. |
* |
* @param string config key |
* @return mixed the config value, or NULL if not found |
* @access private |
*/ |
function _getChannelValue($key, $layer, $channel) |
{ |
if ($key == '__channels' || $channel == 'pear.php.net') { |
return null; |
} |
$ret = null; |
if ($layer === null) { |
foreach ($this->layers as $ilayer) { |
if (isset($this->configuration[$ilayer]['__channels'][$channel][$key])) { |
$ret = $this->configuration[$ilayer]['__channels'][$channel][$key]; |
break; |
} |
} |
} elseif (isset($this->configuration[$layer]['__channels'][$channel][$key])) { |
$ret = $this->configuration[$layer]['__channels'][$channel][$key]; |
} |
if ($key != 'preferred_mirror') { |
return $ret; |
} |
if ($ret !== null) { |
$reg = &$this->getRegistry($layer); |
if (is_object($reg)) { |
$chan = $reg->getChannel($channel); |
if (PEAR::isError($chan)) { |
return $channel; |
} |
if (!$chan->getMirror($ret) && $chan->getName() != $ret) { |
return $channel; // mirror does not exist |
} |
} |
return $ret; |
} |
if ($channel != $this->getDefaultChannel($layer)) { |
return $channel; // we must use the channel name as the preferred mirror |
// if the user has not chosen an alternate |
} |
return $this->getDefaultChannel($layer); |
} |
/** |
* Set a config value in a specific layer (defaults to 'user'). |
* Enforces the types defined in the configuration_info array. An |
* integer config variable will be cast to int, and a set config |
* variable will be validated against its legal values. |
* |
* @param string config key |
* @param string config value |
* @param string (optional) config layer |
* @param string channel to set this value for, or null for global value |
* @return bool TRUE on success, FALSE on failure |
*/ |
function set($key, $value, $layer = 'user', $channel = false) |
{ |
if ($key == '__channels') { |
return false; |
} |
if (!isset($this->configuration[$layer])) { |
return false; |
} |
if ($key == 'default_channel') { |
// can only set this value globally |
$channel = 'pear.php.net'; |
if ($value != 'pear.php.net') { |
$this->_lazyChannelSetup($layer); |
} |
} |
if ($key == 'preferred_mirror') { |
if ($channel == '__uri') { |
return false; // can't set the __uri pseudo-channel's mirror |
} |
$reg = &$this->getRegistry($layer); |
if (is_object($reg)) { |
$chan = $reg->getChannel($channel ? $channel : 'pear.php.net'); |
if (PEAR::isError($chan)) { |
return false; |
} |
if (!$chan->getMirror($value) && $chan->getName() != $value) { |
return false; // mirror does not exist |
} |
} |
} |
if (!isset($this->configuration_info[$key])) { |
return false; |
} |
extract($this->configuration_info[$key]); |
switch ($type) { |
case 'integer': |
$value = (int)$value; |
break; |
case 'set': { |
// If a valid_set is specified, require the value to |
// be in the set. If there is no valid_set, accept |
// any value. |
if ($valid_set) { |
reset($valid_set); |
if ((key($valid_set) === 0 && !in_array($value, $valid_set)) || |
(key($valid_set) !== 0 && empty($valid_set[$value]))) |
{ |
return false; |
} |
} |
break; |
} |
} |
if (!$channel) { |
$channel = $this->get('default_channel', null, 'pear.php.net'); |
} |
if (!in_array($channel, $this->_channels)) { |
$this->_lazyChannelSetup($layer); |
$reg = &$this->getRegistry($layer); |
if ($reg) { |
$channel = $reg->channelName($channel); |
} |
if (!in_array($channel, $this->_channels)) { |
return false; |
} |
} |
if ($channel != 'pear.php.net') { |
if (in_array($key, $this->_channelConfigInfo)) { |
$this->configuration[$layer]['__channels'][$channel][$key] = $value; |
return true; |
} |
return false; |
} |
if ($key == 'default_channel') { |
if (!isset($reg)) { |
$reg = &$this->getRegistry($layer); |
if (!$reg) { |
$reg = &$this->getRegistry(); |
} |
} |
if ($reg) { |
$value = $reg->channelName($value); |
} |
if (!$value) { |
return false; |
} |
} |
$this->configuration[$layer][$key] = $value; |
if ($key == 'php_dir' && !$this->_noRegistry) { |
if (!isset($this->_registry[$layer]) || |
$value != $this->_registry[$layer]->install_dir) { |
$this->_registry[$layer] = new PEAR_Registry($value); |
$this->_regInitialized[$layer] = false; |
$this->_registry[$layer]->setConfig($this, false); |
} |
} |
return true; |
} |
function _lazyChannelSetup($uselayer = false) |
{ |
if ($this->_noRegistry) { |
return; |
} |
$merge = false; |
foreach ($this->_registry as $layer => $p) { |
if ($uselayer && $uselayer != $layer) { |
continue; |
} |
if (!$this->_regInitialized[$layer]) { |
if ($layer == 'default' && isset($this->_registry['user']) || |
isset($this->_registry['system'])) { |
// only use the default registry if there are no alternatives |
continue; |
} |
if (!is_object($this->_registry[$layer])) { |
if ($phpdir = $this->get('php_dir', $layer, 'pear.php.net')) { |
$this->_registry[$layer] = new PEAR_Registry( |
$phpdir, false, false, |
$this->get('metadata_dir', $layer, 'pear.php.net')); |
$this->_registry[$layer]->setConfig($this, false); |
$this->_regInitialized[$layer] = false; |
} else { |
unset($this->_registry[$layer]); |
return; |
} |
} |
$this->setChannels($this->_registry[$layer]->listChannels(), $merge); |
$this->_regInitialized[$layer] = true; |
$merge = true; |
} |
} |
} |
/** |
* Set the list of channels. |
* |
* This should be set via a call to {@link PEAR_Registry::listChannels()} |
* @param array |
* @param bool |
* @return bool success of operation |
*/ |
function setChannels($channels, $merge = false) |
{ |
if (!is_array($channels)) { |
return false; |
} |
if ($merge) { |
$this->_channels = array_merge($this->_channels, $channels); |
} else { |
$this->_channels = $channels; |
} |
foreach ($channels as $channel) { |
$channel = strtolower($channel); |
if ($channel == 'pear.php.net') { |
continue; |
} |
foreach ($this->layers as $layer) { |
if (!isset($this->configuration[$layer]['__channels'])) { |
$this->configuration[$layer]['__channels'] = array(); |
} |
if (!isset($this->configuration[$layer]['__channels'][$channel]) |
|| !is_array($this->configuration[$layer]['__channels'][$channel])) { |
$this->configuration[$layer]['__channels'][$channel] = array(); |
} |
} |
} |
return true; |
} |
/** |
* Get the type of a config value. |
* |
* @param string config key |
* |
* @return string type, one of "string", "integer", "file", |
* "directory", "set" or "password". |
* |
* @access public |
* |
*/ |
function getType($key) |
{ |
if (isset($this->configuration_info[$key])) { |
return $this->configuration_info[$key]['type']; |
} |
return false; |
} |
/** |
* Get the documentation for a config value. |
* |
* @param string config key |
* @return string documentation string |
* |
* @access public |
* |
*/ |
function getDocs($key) |
{ |
if (isset($this->configuration_info[$key])) { |
return $this->configuration_info[$key]['doc']; |
} |
return false; |
} |
/** |
* Get the short documentation for a config value. |
* |
* @param string config key |
* @return string short documentation string |
* |
* @access public |
* |
*/ |
function getPrompt($key) |
{ |
if (isset($this->configuration_info[$key])) { |
return $this->configuration_info[$key]['prompt']; |
} |
return false; |
} |
/** |
* Get the parameter group for a config key. |
* |
* @param string config key |
* @return string parameter group |
* |
* @access public |
* |
*/ |
function getGroup($key) |
{ |
if (isset($this->configuration_info[$key])) { |
return $this->configuration_info[$key]['group']; |
} |
return false; |
} |
/** |
* Get the list of parameter groups. |
* |
* @return array list of parameter groups |
* |
* @access public |
* |
*/ |
function getGroups() |
{ |
$tmp = array(); |
foreach ($this->configuration_info as $key => $info) { |
$tmp[$info['group']] = 1; |
} |
return array_keys($tmp); |
} |
/** |
* Get the list of the parameters in a group. |
* |
* @param string $group parameter group |
* @return array list of parameters in $group |
* |
* @access public |
* |
*/ |
function getGroupKeys($group) |
{ |
$keys = array(); |
foreach ($this->configuration_info as $key => $info) { |
if ($info['group'] == $group) { |
$keys[] = $key; |
} |
} |
return $keys; |
} |
/** |
* Get the list of allowed set values for a config value. Returns |
* NULL for config values that are not sets. |
* |
* @param string config key |
* @return array enumerated array of set values, or NULL if the |
* config key is unknown or not a set |
* |
* @access public |
* |
*/ |
function getSetValues($key) |
{ |
if (isset($this->configuration_info[$key]) && |
isset($this->configuration_info[$key]['type']) && |
$this->configuration_info[$key]['type'] == 'set') |
{ |
$valid_set = $this->configuration_info[$key]['valid_set']; |
reset($valid_set); |
if (key($valid_set) === 0) { |
return $valid_set; |
} |
return array_keys($valid_set); |
} |
return null; |
} |
/** |
* Get all the current config keys. |
* |
* @return array simple array of config keys |
* |
* @access public |
*/ |
function getKeys() |
{ |
$keys = array(); |
foreach ($this->layers as $layer) { |
$test = $this->configuration[$layer]; |
if (isset($test['__channels'])) { |
foreach ($test['__channels'] as $channel => $configs) { |
$keys = array_merge($keys, $configs); |
} |
} |
unset($test['__channels']); |
$keys = array_merge($keys, $test); |
} |
return array_keys($keys); |
} |
/** |
* Remove the a config key from a specific config layer. |
* |
* @param string config key |
* @param string (optional) config layer |
* @param string (optional) channel (defaults to default channel) |
* @return bool TRUE on success, FALSE on failure |
* |
* @access public |
*/ |
function remove($key, $layer = 'user', $channel = null) |
{ |
if ($channel === null) { |
$channel = $this->getDefaultChannel(); |
} |
if ($channel !== 'pear.php.net') { |
if (isset($this->configuration[$layer]['__channels'][$channel][$key])) { |
unset($this->configuration[$layer]['__channels'][$channel][$key]); |
return true; |
} |
} |
if (isset($this->configuration[$layer][$key])) { |
unset($this->configuration[$layer][$key]); |
return true; |
} |
return false; |
} |
/** |
* Temporarily remove an entire config layer. USE WITH CARE! |
* |
* @param string config key |
* @param string (optional) config layer |
* @return bool TRUE on success, FALSE on failure |
* |
* @access public |
*/ |
function removeLayer($layer) |
{ |
if (isset($this->configuration[$layer])) { |
$this->configuration[$layer] = array(); |
return true; |
} |
return false; |
} |
/** |
* Stores configuration data in a layer. |
* |
* @param string config layer to store |
* @return bool TRUE on success, or PEAR error on failure |
* |
* @access public |
*/ |
function store($layer = 'user', $data = null) |
{ |
return $this->writeConfigFile(null, $layer, $data); |
} |
/** |
* Tells what config layer that gets to define a key. |
* |
* @param string config key |
* @param boolean return the defining channel |
* |
* @return string|array the config layer, or an empty string if not found. |
* |
* if $returnchannel, the return is an array array('layer' => layername, |
* 'channel' => channelname), or an empty string if not found |
* |
* @access public |
*/ |
function definedBy($key, $returnchannel = false) |
{ |
foreach ($this->layers as $layer) { |
$channel = $this->getDefaultChannel(); |
if ($channel !== 'pear.php.net') { |
if (isset($this->configuration[$layer]['__channels'][$channel][$key])) { |
if ($returnchannel) { |
return array('layer' => $layer, 'channel' => $channel); |
} |
return $layer; |
} |
} |
if (isset($this->configuration[$layer][$key])) { |
if ($returnchannel) { |
return array('layer' => $layer, 'channel' => 'pear.php.net'); |
} |
return $layer; |
} |
} |
return ''; |
} |
/** |
* Tells whether a given key exists as a config value. |
* |
* @param string config key |
* @return bool whether <config key> exists in this object |
* |
* @access public |
*/ |
function isDefined($key) |
{ |
foreach ($this->layers as $layer) { |
if (isset($this->configuration[$layer][$key])) { |
return true; |
} |
} |
return false; |
} |
/** |
* Tells whether a given config layer exists. |
* |
* @param string config layer |
* @return bool whether <config layer> exists in this object |
* |
* @access public |
*/ |
function isDefinedLayer($layer) |
{ |
return isset($this->configuration[$layer]); |
} |
/** |
* Returns the layers defined (except the 'default' one) |
* |
* @return array of the defined layers |
*/ |
function getLayers() |
{ |
$cf = $this->configuration; |
unset($cf['default']); |
return array_keys($cf); |
} |
function apiVersion() |
{ |
return '1.1'; |
} |
/** |
* @return PEAR_Registry |
*/ |
function &getRegistry($use = null) |
{ |
$layer = $use === null ? 'user' : $use; |
if (isset($this->_registry[$layer])) { |
return $this->_registry[$layer]; |
} elseif ($use === null && isset($this->_registry['system'])) { |
return $this->_registry['system']; |
} elseif ($use === null && isset($this->_registry['default'])) { |
return $this->_registry['default']; |
} elseif ($use) { |
$a = false; |
return $a; |
} |
// only go here if null was passed in |
echo "CRITICAL ERROR: Registry could not be initialized from any value"; |
exit(1); |
} |
/** |
* This is to allow customization like the use of installroot |
* @param PEAR_Registry |
* @return bool |
*/ |
function setRegistry(&$reg, $layer = 'user') |
{ |
if ($this->_noRegistry) { |
return false; |
} |
if (!in_array($layer, array('user', 'system'))) { |
return false; |
} |
$this->_registry[$layer] = &$reg; |
if (is_object($reg)) { |
$this->_registry[$layer]->setConfig($this, false); |
} |
return true; |
} |
function noRegistry() |
{ |
$this->_noRegistry = true; |
} |
/** |
* @return PEAR_REST |
*/ |
function &getREST($version, $options = array()) |
{ |
$version = str_replace('.', '', $version); |
if (!class_exists($class = 'PEAR_REST_' . $version)) { |
require_once 'PEAR/REST/' . $version . '.php'; |
} |
$remote = new $class($this, $options); |
return $remote; |
} |
/** |
* The ftp server is set in {@link readFTPConfigFile()}. It exists only if a |
* remote configuration file has been specified |
* @return PEAR_FTP|false |
*/ |
function &getFTP() |
{ |
if (isset($this->_ftp)) { |
return $this->_ftp; |
} |
$a = false; |
return $a; |
} |
function _prependPath($path, $prepend) |
{ |
if (strlen($prepend) > 0) { |
if (OS_WINDOWS && preg_match('/^[a-z]:/i', $path)) { |
if (preg_match('/^[a-z]:/i', $prepend)) { |
$prepend = substr($prepend, 2); |
} elseif ($prepend{0} != '\\') { |
$prepend = "\\$prepend"; |
} |
$path = substr($path, 0, 2) . $prepend . substr($path, 2); |
} else { |
$path = $prepend . $path; |
} |
} |
return $path; |
} |
/** |
* @param string|false installation directory to prepend to all _dir variables, or false to |
* disable |
*/ |
function setInstallRoot($root) |
{ |
if (substr($root, -1) == DIRECTORY_SEPARATOR) { |
$root = substr($root, 0, -1); |
} |
$old = $this->_installRoot; |
$this->_installRoot = $root; |
if (($old != $root) && !$this->_noRegistry) { |
foreach (array_keys($this->_registry) as $layer) { |
if ($layer == 'ftp' || !isset($this->_registry[$layer])) { |
continue; |
} |
$this->_registry[$layer] = |
new PEAR_Registry( |
$this->get('php_dir', $layer, 'pear.php.net'), false, false, |
$this->get('metadata_dir', $layer, 'pear.php.net')); |
$this->_registry[$layer]->setConfig($this, false); |
$this->_regInitialized[$layer] = false; |
} |
} |
} |
} |
/branches/v1.3-critias/bibliotheque/pear/PEAR/PackageFile/Generator/v1.php |
---|
New file |
0,0 → 1,1284 |
<?php |
/** |
* package.xml generation class, package.xml version 1.0 |
* |
* PHP versions 4 and 5 |
* |
* @category pear |
* @package PEAR |
* @author Greg Beaver <cellog@php.net> |
* @copyright 1997-2009 The Authors |
* @license http://opensource.org/licenses/bsd-license.php New BSD License |
* @link http://pear.php.net/package/PEAR |
* @since File available since Release 1.4.0a1 |
*/ |
/** |
* needed for PEAR_VALIDATE_* constants |
*/ |
require_once 'PEAR/Validate.php'; |
require_once 'System.php'; |
require_once 'PEAR/PackageFile/v2.php'; |
/** |
* This class converts a PEAR_PackageFile_v1 object into any output format. |
* |
* Supported output formats include array, XML string, and a PEAR_PackageFile_v2 |
* object, for converting package.xml 1.0 into package.xml 2.0 with no sweat. |
* @category pear |
* @package PEAR |
* @author Greg Beaver <cellog@php.net> |
* @copyright 1997-2009 The Authors |
* @license http://opensource.org/licenses/bsd-license.php New BSD License |
* @version Release: 1.10.1 |
* @link http://pear.php.net/package/PEAR |
* @since Class available since Release 1.4.0a1 |
*/ |
class PEAR_PackageFile_Generator_v1 |
{ |
/** |
* @var PEAR_PackageFile_v1 |
*/ |
var $_packagefile; |
function __construct(&$packagefile) |
{ |
$this->_packagefile = &$packagefile; |
} |
function getPackagerVersion() |
{ |
return '1.10.1'; |
} |
/** |
* @param PEAR_Packager |
* @param bool if true, a .tgz is written, otherwise a .tar is written |
* @param string|null directory in which to save the .tgz |
* @return string|PEAR_Error location of package or error object |
*/ |
function toTgz(&$packager, $compress = true, $where = null) |
{ |
require_once 'Archive/Tar.php'; |
if ($where === null) { |
if (!($where = System::mktemp(array('-d')))) { |
return PEAR::raiseError('PEAR_Packagefile_v1::toTgz: mktemp failed'); |
} |
} elseif (!@System::mkDir(array('-p', $where))) { |
return PEAR::raiseError('PEAR_Packagefile_v1::toTgz: "' . $where . '" could' . |
' not be created'); |
} |
if (file_exists($where . DIRECTORY_SEPARATOR . 'package.xml') && |
!is_file($where . DIRECTORY_SEPARATOR . 'package.xml')) { |
return PEAR::raiseError('PEAR_Packagefile_v1::toTgz: unable to save package.xml as' . |
' "' . $where . DIRECTORY_SEPARATOR . 'package.xml"'); |
} |
if (!$this->_packagefile->validate(PEAR_VALIDATE_PACKAGING)) { |
return PEAR::raiseError('PEAR_Packagefile_v1::toTgz: invalid package file'); |
} |
$pkginfo = $this->_packagefile->getArray(); |
$ext = $compress ? '.tgz' : '.tar'; |
$pkgver = $pkginfo['package'] . '-' . $pkginfo['version']; |
$dest_package = getcwd() . DIRECTORY_SEPARATOR . $pkgver . $ext; |
if (file_exists(getcwd() . DIRECTORY_SEPARATOR . $pkgver . $ext) && |
!is_file(getcwd() . DIRECTORY_SEPARATOR . $pkgver . $ext)) { |
return PEAR::raiseError('PEAR_Packagefile_v1::toTgz: cannot create tgz file "' . |
getcwd() . DIRECTORY_SEPARATOR . $pkgver . $ext . '"'); |
} |
if ($pkgfile = $this->_packagefile->getPackageFile()) { |
$pkgdir = dirname(realpath($pkgfile)); |
$pkgfile = basename($pkgfile); |
} else { |
return PEAR::raiseError('PEAR_Packagefile_v1::toTgz: package file object must ' . |
'be created from a real file'); |
} |
// {{{ Create the package file list |
$filelist = array(); |
$i = 0; |
foreach ($this->_packagefile->getFilelist() as $fname => $atts) { |
$file = $pkgdir . DIRECTORY_SEPARATOR . $fname; |
if (!file_exists($file)) { |
return PEAR::raiseError("File does not exist: $fname"); |
} else { |
$filelist[$i++] = $file; |
if (!isset($atts['md5sum'])) { |
$this->_packagefile->setFileAttribute($fname, 'md5sum', md5_file($file)); |
} |
$packager->log(2, "Adding file $fname"); |
} |
} |
// }}} |
$packagexml = $this->toPackageFile($where, PEAR_VALIDATE_PACKAGING, 'package.xml', true); |
if ($packagexml) { |
$tar = new Archive_Tar($dest_package, $compress); |
$tar->setErrorHandling(PEAR_ERROR_RETURN); // XXX Don't print errors |
// ----- Creates with the package.xml file |
$ok = $tar->createModify(array($packagexml), '', $where); |
if (PEAR::isError($ok)) { |
return $ok; |
} elseif (!$ok) { |
return PEAR::raiseError('PEAR_Packagefile_v1::toTgz: tarball creation failed'); |
} |
// ----- Add the content of the package |
if (!$tar->addModify($filelist, $pkgver, $pkgdir)) { |
return PEAR::raiseError('PEAR_Packagefile_v1::toTgz: tarball creation failed'); |
} |
return $dest_package; |
} |
} |
/** |
* @param string|null directory to place the package.xml in, or null for a temporary dir |
* @param int one of the PEAR_VALIDATE_* constants |
* @param string name of the generated file |
* @param bool if true, then no analysis will be performed on role="php" files |
* @return string|PEAR_Error path to the created file on success |
*/ |
function toPackageFile($where = null, $state = PEAR_VALIDATE_NORMAL, $name = 'package.xml', |
$nofilechecking = false) |
{ |
if (!$this->_packagefile->validate($state, $nofilechecking)) { |
return PEAR::raiseError('PEAR_Packagefile_v1::toPackageFile: invalid package.xml', |
null, null, null, $this->_packagefile->getValidationWarnings()); |
} |
if ($where === null) { |
if (!($where = System::mktemp(array('-d')))) { |
return PEAR::raiseError('PEAR_Packagefile_v1::toPackageFile: mktemp failed'); |
} |
} elseif (!@System::mkDir(array('-p', $where))) { |
return PEAR::raiseError('PEAR_Packagefile_v1::toPackageFile: "' . $where . '" could' . |
' not be created'); |
} |
$newpkgfile = $where . DIRECTORY_SEPARATOR . $name; |
$np = @fopen($newpkgfile, 'wb'); |
if (!$np) { |
return PEAR::raiseError('PEAR_Packagefile_v1::toPackageFile: unable to save ' . |
"$name as $newpkgfile"); |
} |
fwrite($np, $this->toXml($state, true)); |
fclose($np); |
return $newpkgfile; |
} |
/** |
* fix both XML encoding to be UTF8, and replace standard XML entities < > " & ' |
* |
* @param string $string |
* @return string |
* @access private |
*/ |
function _fixXmlEncoding($string) |
{ |
return strtr($string, array( |
'&' => '&', |
'>' => '>', |
'<' => '<', |
'"' => '"', |
'\'' => ''' )); |
} |
/** |
* Return an XML document based on the package info (as returned |
* by the PEAR_Common::infoFrom* methods). |
* |
* @return string XML data |
*/ |
function toXml($state = PEAR_VALIDATE_NORMAL, $nofilevalidation = false) |
{ |
$this->_packagefile->setDate(date('Y-m-d')); |
if (!$this->_packagefile->validate($state, $nofilevalidation)) { |
return false; |
} |
$pkginfo = $this->_packagefile->getArray(); |
static $maint_map = array( |
"handle" => "user", |
"name" => "name", |
"email" => "email", |
"role" => "role", |
); |
$ret = "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n"; |
$ret .= "<!DOCTYPE package SYSTEM \"http://pear.php.net/dtd/package-1.0\">\n"; |
$ret .= "<package version=\"1.0\" packagerversion=\"1.10.1\">\n" . |
" <name>$pkginfo[package]</name>"; |
if (isset($pkginfo['extends'])) { |
$ret .= "\n<extends>$pkginfo[extends]</extends>"; |
} |
$ret .= |
"\n <summary>".$this->_fixXmlEncoding($pkginfo['summary'])."</summary>\n" . |
" <description>".trim($this->_fixXmlEncoding($pkginfo['description']))."\n </description>\n" . |
" <maintainers>\n"; |
foreach ($pkginfo['maintainers'] as $maint) { |
$ret .= " <maintainer>\n"; |
foreach ($maint_map as $idx => $elm) { |
$ret .= " <$elm>"; |
$ret .= $this->_fixXmlEncoding($maint[$idx]); |
$ret .= "</$elm>\n"; |
} |
$ret .= " </maintainer>\n"; |
} |
$ret .= " </maintainers>\n"; |
$ret .= $this->_makeReleaseXml($pkginfo, false, $state); |
if (isset($pkginfo['changelog']) && count($pkginfo['changelog']) > 0) { |
$ret .= " <changelog>\n"; |
foreach ($pkginfo['changelog'] as $oldrelease) { |
$ret .= $this->_makeReleaseXml($oldrelease, true); |
} |
$ret .= " </changelog>\n"; |
} |
$ret .= "</package>\n"; |
return $ret; |
} |
// }}} |
// {{{ _makeReleaseXml() |
/** |
* Generate part of an XML description with release information. |
* |
* @param array $pkginfo array with release information |
* @param bool $changelog whether the result will be in a changelog element |
* |
* @return string XML data |
* |
* @access private |
*/ |
function _makeReleaseXml($pkginfo, $changelog = false, $state = PEAR_VALIDATE_NORMAL) |
{ |
// XXX QUOTE ENTITIES IN PCDATA, OR EMBED IN CDATA BLOCKS!! |
$indent = $changelog ? " " : ""; |
$ret = "$indent <release>\n"; |
if (!empty($pkginfo['version'])) { |
$ret .= "$indent <version>$pkginfo[version]</version>\n"; |
} |
if (!empty($pkginfo['release_date'])) { |
$ret .= "$indent <date>$pkginfo[release_date]</date>\n"; |
} |
if (!empty($pkginfo['release_license'])) { |
$ret .= "$indent <license>$pkginfo[release_license]</license>\n"; |
} |
if (!empty($pkginfo['release_state'])) { |
$ret .= "$indent <state>$pkginfo[release_state]</state>\n"; |
} |
if (!empty($pkginfo['release_notes'])) { |
$ret .= "$indent <notes>".trim($this->_fixXmlEncoding($pkginfo['release_notes'])) |
."\n$indent </notes>\n"; |
} |
if (!empty($pkginfo['release_warnings'])) { |
$ret .= "$indent <warnings>".$this->_fixXmlEncoding($pkginfo['release_warnings'])."</warnings>\n"; |
} |
if (isset($pkginfo['release_deps']) && sizeof($pkginfo['release_deps']) > 0) { |
$ret .= "$indent <deps>\n"; |
foreach ($pkginfo['release_deps'] as $dep) { |
$ret .= "$indent <dep type=\"$dep[type]\" rel=\"$dep[rel]\""; |
if (isset($dep['version'])) { |
$ret .= " version=\"$dep[version]\""; |
} |
if (isset($dep['optional'])) { |
$ret .= " optional=\"$dep[optional]\""; |
} |
if (isset($dep['name'])) { |
$ret .= ">$dep[name]</dep>\n"; |
} else { |
$ret .= "/>\n"; |
} |
} |
$ret .= "$indent </deps>\n"; |
} |
if (isset($pkginfo['configure_options'])) { |
$ret .= "$indent <configureoptions>\n"; |
foreach ($pkginfo['configure_options'] as $c) { |
$ret .= "$indent <configureoption name=\"". |
$this->_fixXmlEncoding($c['name']) . "\""; |
if (isset($c['default'])) { |
$ret .= " default=\"" . $this->_fixXmlEncoding($c['default']) . "\""; |
} |
$ret .= " prompt=\"" . $this->_fixXmlEncoding($c['prompt']) . "\""; |
$ret .= "/>\n"; |
} |
$ret .= "$indent </configureoptions>\n"; |
} |
if (isset($pkginfo['provides'])) { |
foreach ($pkginfo['provides'] as $key => $what) { |
$ret .= "$indent <provides type=\"$what[type]\" "; |
$ret .= "name=\"$what[name]\" "; |
if (isset($what['extends'])) { |
$ret .= "extends=\"$what[extends]\" "; |
} |
$ret .= "/>\n"; |
} |
} |
if (isset($pkginfo['filelist'])) { |
$ret .= "$indent <filelist>\n"; |
if ($state ^ PEAR_VALIDATE_PACKAGING) { |
$ret .= $this->recursiveXmlFilelist($pkginfo['filelist']); |
} else { |
foreach ($pkginfo['filelist'] as $file => $fa) { |
if (!isset($fa['role'])) { |
$fa['role'] = ''; |
} |
$ret .= "$indent <file role=\"$fa[role]\""; |
if (isset($fa['baseinstalldir'])) { |
$ret .= ' baseinstalldir="' . |
$this->_fixXmlEncoding($fa['baseinstalldir']) . '"'; |
} |
if (isset($fa['md5sum'])) { |
$ret .= " md5sum=\"$fa[md5sum]\""; |
} |
if (isset($fa['platform'])) { |
$ret .= " platform=\"$fa[platform]\""; |
} |
if (!empty($fa['install-as'])) { |
$ret .= ' install-as="' . |
$this->_fixXmlEncoding($fa['install-as']) . '"'; |
} |
$ret .= ' name="' . $this->_fixXmlEncoding($file) . '"'; |
if (empty($fa['replacements'])) { |
$ret .= "/>\n"; |
} else { |
$ret .= ">\n"; |
foreach ($fa['replacements'] as $r) { |
$ret .= "$indent <replace"; |
foreach ($r as $k => $v) { |
$ret .= " $k=\"" . $this->_fixXmlEncoding($v) .'"'; |
} |
$ret .= "/>\n"; |
} |
$ret .= "$indent </file>\n"; |
} |
} |
} |
$ret .= "$indent </filelist>\n"; |
} |
$ret .= "$indent </release>\n"; |
return $ret; |
} |
/** |
* @param array |
* @access protected |
*/ |
function recursiveXmlFilelist($list) |
{ |
$this->_dirs = array(); |
foreach ($list as $file => $attributes) { |
$this->_addDir($this->_dirs, explode('/', dirname($file)), $file, $attributes); |
} |
return $this->_formatDir($this->_dirs); |
} |
/** |
* @param array |
* @param array |
* @param string|null |
* @param array|null |
* @access private |
*/ |
function _addDir(&$dirs, $dir, $file = null, $attributes = null) |
{ |
if ($dir == array() || $dir == array('.')) { |
$dirs['files'][basename($file)] = $attributes; |
return; |
} |
$curdir = array_shift($dir); |
if (!isset($dirs['dirs'][$curdir])) { |
$dirs['dirs'][$curdir] = array(); |
} |
$this->_addDir($dirs['dirs'][$curdir], $dir, $file, $attributes); |
} |
/** |
* @param array |
* @param string |
* @param string |
* @access private |
*/ |
function _formatDir($dirs, $indent = '', $curdir = '') |
{ |
$ret = ''; |
if (!count($dirs)) { |
return ''; |
} |
if (isset($dirs['dirs'])) { |
uksort($dirs['dirs'], 'strnatcasecmp'); |
foreach ($dirs['dirs'] as $dir => $contents) { |
$usedir = "$curdir/$dir"; |
$ret .= "$indent <dir name=\"$dir\">\n"; |
$ret .= $this->_formatDir($contents, "$indent ", $usedir); |
$ret .= "$indent </dir> <!-- $usedir -->\n"; |
} |
} |
if (isset($dirs['files'])) { |
uksort($dirs['files'], 'strnatcasecmp'); |
foreach ($dirs['files'] as $file => $attribs) { |
$ret .= $this->_formatFile($file, $attribs, $indent); |
} |
} |
return $ret; |
} |
/** |
* @param string |
* @param array |
* @param string |
* @access private |
*/ |
function _formatFile($file, $attributes, $indent) |
{ |
$ret = "$indent <file role=\"$attributes[role]\""; |
if (isset($attributes['baseinstalldir'])) { |
$ret .= ' baseinstalldir="' . |
$this->_fixXmlEncoding($attributes['baseinstalldir']) . '"'; |
} |
if (isset($attributes['md5sum'])) { |
$ret .= " md5sum=\"$attributes[md5sum]\""; |
} |
if (isset($attributes['platform'])) { |
$ret .= " platform=\"$attributes[platform]\""; |
} |
if (!empty($attributes['install-as'])) { |
$ret .= ' install-as="' . |
$this->_fixXmlEncoding($attributes['install-as']) . '"'; |
} |
$ret .= ' name="' . $this->_fixXmlEncoding($file) . '"'; |
if (empty($attributes['replacements'])) { |
$ret .= "/>\n"; |
} else { |
$ret .= ">\n"; |
foreach ($attributes['replacements'] as $r) { |
$ret .= "$indent <replace"; |
foreach ($r as $k => $v) { |
$ret .= " $k=\"" . $this->_fixXmlEncoding($v) .'"'; |
} |
$ret .= "/>\n"; |
} |
$ret .= "$indent </file>\n"; |
} |
return $ret; |
} |
// {{{ _unIndent() |
/** |
* Unindent given string (?) |
* |
* @param string $str The string that has to be unindented. |
* @return string |
* @access private |
*/ |
function _unIndent($str) |
{ |
// remove leading newlines |
$str = preg_replace('/^[\r\n]+/', '', $str); |
// find whitespace at the beginning of the first line |
$indent_len = strspn($str, " \t"); |
$indent = substr($str, 0, $indent_len); |
$data = ''; |
// remove the same amount of whitespace from following lines |
foreach (explode("\n", $str) as $line) { |
if (substr($line, 0, $indent_len) == $indent) { |
$data .= substr($line, $indent_len) . "\n"; |
} |
} |
return $data; |
} |
/** |
* @return array |
*/ |
function dependenciesToV2() |
{ |
$arr = array(); |
$this->_convertDependencies2_0($arr); |
return $arr['dependencies']; |
} |
/** |
* Convert a package.xml version 1.0 into version 2.0 |
* |
* Note that this does a basic conversion, to allow more advanced |
* features like bundles and multiple releases |
* @param string the classname to instantiate and return. This must be |
* PEAR_PackageFile_v2 or a descendant |
* @param boolean if true, only valid, deterministic package.xml 1.0 as defined by the |
* strictest parameters will be converted |
* @return PEAR_PackageFile_v2|PEAR_Error |
*/ |
function &toV2($class = 'PEAR_PackageFile_v2', $strict = false) |
{ |
if ($strict) { |
if (!$this->_packagefile->validate()) { |
$a = PEAR::raiseError('invalid package.xml version 1.0 cannot be converted' . |
' to version 2.0', null, null, null, |
$this->_packagefile->getValidationWarnings(true)); |
return $a; |
} |
} |
$arr = array( |
'attribs' => array( |
'version' => '2.0', |
'xmlns' => 'http://pear.php.net/dtd/package-2.0', |
'xmlns:tasks' => 'http://pear.php.net/dtd/tasks-1.0', |
'xmlns:xsi' => 'http://www.w3.org/2001/XMLSchema-instance', |
'xsi:schemaLocation' => "http://pear.php.net/dtd/tasks-1.0\n" . |
"http://pear.php.net/dtd/tasks-1.0.xsd\n" . |
"http://pear.php.net/dtd/package-2.0\n" . |
'http://pear.php.net/dtd/package-2.0.xsd', |
), |
'name' => $this->_packagefile->getPackage(), |
'channel' => 'pear.php.net', |
); |
$arr['summary'] = $this->_packagefile->getSummary(); |
$arr['description'] = $this->_packagefile->getDescription(); |
$maintainers = $this->_packagefile->getMaintainers(); |
foreach ($maintainers as $maintainer) { |
if ($maintainer['role'] != 'lead') { |
continue; |
} |
$new = array( |
'name' => $maintainer['name'], |
'user' => $maintainer['handle'], |
'email' => $maintainer['email'], |
'active' => 'yes', |
); |
$arr['lead'][] = $new; |
} |
if (!isset($arr['lead'])) { // some people... you know? |
$arr['lead'] = array( |
'name' => 'unknown', |
'user' => 'unknown', |
'email' => 'noleadmaintainer@example.com', |
'active' => 'no', |
); |
} |
if (count($arr['lead']) == 1) { |
$arr['lead'] = $arr['lead'][0]; |
} |
foreach ($maintainers as $maintainer) { |
if ($maintainer['role'] == 'lead') { |
continue; |
} |
$new = array( |
'name' => $maintainer['name'], |
'user' => $maintainer['handle'], |
'email' => $maintainer['email'], |
'active' => 'yes', |
); |
$arr[$maintainer['role']][] = $new; |
} |
if (isset($arr['developer']) && count($arr['developer']) == 1) { |
$arr['developer'] = $arr['developer'][0]; |
} |
if (isset($arr['contributor']) && count($arr['contributor']) == 1) { |
$arr['contributor'] = $arr['contributor'][0]; |
} |
if (isset($arr['helper']) && count($arr['helper']) == 1) { |
$arr['helper'] = $arr['helper'][0]; |
} |
$arr['date'] = $this->_packagefile->getDate(); |
$arr['version'] = |
array( |
'release' => $this->_packagefile->getVersion(), |
'api' => $this->_packagefile->getVersion(), |
); |
$arr['stability'] = |
array( |
'release' => $this->_packagefile->getState(), |
'api' => $this->_packagefile->getState(), |
); |
$licensemap = |
array( |
'php' => 'http://www.php.net/license', |
'php license' => 'http://www.php.net/license', |
'lgpl' => 'http://www.gnu.org/copyleft/lesser.html', |
'bsd' => 'http://www.opensource.org/licenses/bsd-license.php', |
'bsd style' => 'http://www.opensource.org/licenses/bsd-license.php', |
'bsd-style' => 'http://www.opensource.org/licenses/bsd-license.php', |
'mit' => 'http://www.opensource.org/licenses/mit-license.php', |
'gpl' => 'http://www.gnu.org/copyleft/gpl.html', |
'apache' => 'http://www.opensource.org/licenses/apache2.0.php' |
); |
if (isset($licensemap[strtolower($this->_packagefile->getLicense())])) { |
$arr['license'] = array( |
'attribs' => array('uri' => |
$licensemap[strtolower($this->_packagefile->getLicense())]), |
'_content' => $this->_packagefile->getLicense() |
); |
} else { |
// don't use bogus uri |
$arr['license'] = $this->_packagefile->getLicense(); |
} |
$arr['notes'] = $this->_packagefile->getNotes(); |
$temp = array(); |
$arr['contents'] = $this->_convertFilelist2_0($temp); |
$this->_convertDependencies2_0($arr); |
$release = ($this->_packagefile->getConfigureOptions() || $this->_isExtension) ? |
'extsrcrelease' : 'phprelease'; |
if ($release == 'extsrcrelease') { |
$arr['channel'] = 'pecl.php.net'; |
$arr['providesextension'] = $arr['name']; // assumption |
} |
$arr[$release] = array(); |
if ($this->_packagefile->getConfigureOptions()) { |
$arr[$release]['configureoption'] = $this->_packagefile->getConfigureOptions(); |
foreach ($arr[$release]['configureoption'] as $i => $opt) { |
$arr[$release]['configureoption'][$i] = array('attribs' => $opt); |
} |
if (count($arr[$release]['configureoption']) == 1) { |
$arr[$release]['configureoption'] = $arr[$release]['configureoption'][0]; |
} |
} |
$this->_convertRelease2_0($arr[$release], $temp); |
if ($release == 'extsrcrelease' && count($arr[$release]) > 1) { |
// multiple extsrcrelease tags added in PEAR 1.4.1 |
$arr['dependencies']['required']['pearinstaller']['min'] = '1.4.1'; |
} |
if ($cl = $this->_packagefile->getChangelog()) { |
foreach ($cl as $release) { |
$rel = array(); |
$rel['version'] = |
array( |
'release' => $release['version'], |
'api' => $release['version'], |
); |
if (!isset($release['release_state'])) { |
$release['release_state'] = 'stable'; |
} |
$rel['stability'] = |
array( |
'release' => $release['release_state'], |
'api' => $release['release_state'], |
); |
if (isset($release['release_date'])) { |
$rel['date'] = $release['release_date']; |
} else { |
$rel['date'] = date('Y-m-d'); |
} |
if (isset($release['release_license'])) { |
if (isset($licensemap[strtolower($release['release_license'])])) { |
$uri = $licensemap[strtolower($release['release_license'])]; |
} else { |
$uri = 'http://www.example.com'; |
} |
$rel['license'] = array( |
'attribs' => array('uri' => $uri), |
'_content' => $release['release_license'] |
); |
} else { |
$rel['license'] = $arr['license']; |
} |
if (!isset($release['release_notes'])) { |
$release['release_notes'] = 'no release notes'; |
} |
$rel['notes'] = $release['release_notes']; |
$arr['changelog']['release'][] = $rel; |
} |
} |
$ret = new $class; |
$ret->setConfig($this->_packagefile->_config); |
if (isset($this->_packagefile->_logger) && is_object($this->_packagefile->_logger)) { |
$ret->setLogger($this->_packagefile->_logger); |
} |
$ret->fromArray($arr); |
return $ret; |
} |
/** |
* @param array |
* @param bool |
* @access private |
*/ |
function _convertDependencies2_0(&$release, $internal = false) |
{ |
$peardep = array('pearinstaller' => |
array('min' => '1.4.0b1')); // this is a lot safer |
$required = $optional = array(); |
$release['dependencies'] = array('required' => array()); |
if ($this->_packagefile->hasDeps()) { |
foreach ($this->_packagefile->getDeps() as $dep) { |
if (!isset($dep['optional']) || $dep['optional'] == 'no') { |
$required[] = $dep; |
} else { |
$optional[] = $dep; |
} |
} |
foreach (array('required', 'optional') as $arr) { |
$deps = array(); |
foreach ($$arr as $dep) { |
// organize deps by dependency type and name |
if (!isset($deps[$dep['type']])) { |
$deps[$dep['type']] = array(); |
} |
if (isset($dep['name'])) { |
$deps[$dep['type']][$dep['name']][] = $dep; |
} else { |
$deps[$dep['type']][] = $dep; |
} |
} |
do { |
if (isset($deps['php'])) { |
$php = array(); |
if (count($deps['php']) > 1) { |
$php = $this->_processPhpDeps($deps['php']); |
} else { |
if (!isset($deps['php'][0])) { |
list($key, $blah) = each ($deps['php']); // stupid buggy versions |
$deps['php'] = array($blah[0]); |
} |
$php = $this->_processDep($deps['php'][0]); |
if (!$php) { |
break; // poor mans throw |
} |
} |
$release['dependencies'][$arr]['php'] = $php; |
} |
} while (false); |
do { |
if (isset($deps['pkg'])) { |
$pkg = array(); |
$pkg = $this->_processMultipleDepsName($deps['pkg']); |
if (!$pkg) { |
break; // poor mans throw |
} |
$release['dependencies'][$arr]['package'] = $pkg; |
} |
} while (false); |
do { |
if (isset($deps['ext'])) { |
$pkg = array(); |
$pkg = $this->_processMultipleDepsName($deps['ext']); |
$release['dependencies'][$arr]['extension'] = $pkg; |
} |
} while (false); |
// skip sapi - it's not supported so nobody will have used it |
// skip os - it's not supported in 1.0 |
} |
} |
if (isset($release['dependencies']['required'])) { |
$release['dependencies']['required'] = |
array_merge($peardep, $release['dependencies']['required']); |
} else { |
$release['dependencies']['required'] = $peardep; |
} |
if (!isset($release['dependencies']['required']['php'])) { |
$release['dependencies']['required']['php'] = |
array('min' => '4.0.0'); |
} |
$order = array(); |
$bewm = $release['dependencies']['required']; |
$order['php'] = $bewm['php']; |
$order['pearinstaller'] = $bewm['pearinstaller']; |
isset($bewm['package']) ? $order['package'] = $bewm['package'] :0; |
isset($bewm['extension']) ? $order['extension'] = $bewm['extension'] :0; |
$release['dependencies']['required'] = $order; |
} |
/** |
* @param array |
* @access private |
*/ |
function _convertFilelist2_0(&$package) |
{ |
$ret = array('dir' => |
array( |
'attribs' => array('name' => '/'), |
'file' => array() |
) |
); |
$package['platform'] = |
$package['install-as'] = array(); |
$this->_isExtension = false; |
foreach ($this->_packagefile->getFilelist() as $name => $file) { |
$file['name'] = $name; |
if (isset($file['role']) && $file['role'] == 'src') { |
$this->_isExtension = true; |
} |
if (isset($file['replacements'])) { |
$repl = $file['replacements']; |
unset($file['replacements']); |
} else { |
unset($repl); |
} |
if (isset($file['install-as'])) { |
$package['install-as'][$name] = $file['install-as']; |
unset($file['install-as']); |
} |
if (isset($file['platform'])) { |
$package['platform'][$name] = $file['platform']; |
unset($file['platform']); |
} |
$file = array('attribs' => $file); |
if (isset($repl)) { |
foreach ($repl as $replace ) { |
$file['tasks:replace'][] = array('attribs' => $replace); |
} |
if (count($repl) == 1) { |
$file['tasks:replace'] = $file['tasks:replace'][0]; |
} |
} |
$ret['dir']['file'][] = $file; |
} |
return $ret; |
} |
/** |
* Post-process special files with install-as/platform attributes and |
* make the release tag. |
* |
* This complex method follows this work-flow to create the release tags: |
* |
* <pre> |
* - if any install-as/platform exist, create a generic release and fill it with |
* o <install as=..> tags for <file name=... install-as=...> |
* o <install as=..> tags for <file name=... platform=!... install-as=..> |
* o <ignore> tags for <file name=... platform=...> |
* o <ignore> tags for <file name=... platform=... install-as=..> |
* - create a release for each platform encountered and fill with |
* o <install as..> tags for <file name=... install-as=...> |
* o <install as..> tags for <file name=... platform=this platform install-as=..> |
* o <install as..> tags for <file name=... platform=!other platform install-as=..> |
* o <ignore> tags for <file name=... platform=!this platform> |
* o <ignore> tags for <file name=... platform=other platform> |
* o <ignore> tags for <file name=... platform=other platform install-as=..> |
* o <ignore> tags for <file name=... platform=!this platform install-as=..> |
* </pre> |
* |
* It does this by accessing the $package parameter, which contains an array with |
* indices: |
* |
* - platform: mapping of file => OS the file should be installed on |
* - install-as: mapping of file => installed name |
* - osmap: mapping of OS => list of files that should be installed |
* on that OS |
* - notosmap: mapping of OS => list of files that should not be |
* installed on that OS |
* |
* @param array |
* @param array |
* @access private |
*/ |
function _convertRelease2_0(&$release, $package) |
{ |
//- if any install-as/platform exist, create a generic release and fill it with |
if (count($package['platform']) || count($package['install-as'])) { |
$generic = array(); |
$genericIgnore = array(); |
foreach ($package['install-as'] as $file => $as) { |
//o <install as=..> tags for <file name=... install-as=...> |
if (!isset($package['platform'][$file])) { |
$generic[] = $file; |
continue; |
} |
//o <install as=..> tags for <file name=... platform=!... install-as=..> |
if (isset($package['platform'][$file]) && |
$package['platform'][$file]{0} == '!') { |
$generic[] = $file; |
continue; |
} |
//o <ignore> tags for <file name=... platform=... install-as=..> |
if (isset($package['platform'][$file]) && |
$package['platform'][$file]{0} != '!') { |
$genericIgnore[] = $file; |
continue; |
} |
} |
foreach ($package['platform'] as $file => $platform) { |
if (isset($package['install-as'][$file])) { |
continue; |
} |
if ($platform{0} != '!') { |
//o <ignore> tags for <file name=... platform=...> |
$genericIgnore[] = $file; |
} |
} |
if (count($package['platform'])) { |
$oses = $notplatform = $platform = array(); |
foreach ($package['platform'] as $file => $os) { |
// get a list of oses |
if ($os{0} == '!') { |
if (isset($oses[substr($os, 1)])) { |
continue; |
} |
$oses[substr($os, 1)] = count($oses); |
} else { |
if (isset($oses[$os])) { |
continue; |
} |
$oses[$os] = count($oses); |
} |
} |
//- create a release for each platform encountered and fill with |
foreach ($oses as $os => $releaseNum) { |
$release[$releaseNum]['installconditions']['os']['name'] = $os; |
$release[$releaseNum]['filelist'] = array('install' => array(), |
'ignore' => array()); |
foreach ($package['install-as'] as $file => $as) { |
//o <install as=..> tags for <file name=... install-as=...> |
if (!isset($package['platform'][$file])) { |
$release[$releaseNum]['filelist']['install'][] = |
array( |
'attribs' => array( |
'name' => $file, |
'as' => $as, |
), |
); |
continue; |
} |
//o <install as..> tags for |
// <file name=... platform=this platform install-as=..> |
if (isset($package['platform'][$file]) && |
$package['platform'][$file] == $os) { |
$release[$releaseNum]['filelist']['install'][] = |
array( |
'attribs' => array( |
'name' => $file, |
'as' => $as, |
), |
); |
continue; |
} |
//o <install as..> tags for |
// <file name=... platform=!other platform install-as=..> |
if (isset($package['platform'][$file]) && |
$package['platform'][$file] != "!$os" && |
$package['platform'][$file]{0} == '!') { |
$release[$releaseNum]['filelist']['install'][] = |
array( |
'attribs' => array( |
'name' => $file, |
'as' => $as, |
), |
); |
continue; |
} |
//o <ignore> tags for |
// <file name=... platform=!this platform install-as=..> |
if (isset($package['platform'][$file]) && |
$package['platform'][$file] == "!$os") { |
$release[$releaseNum]['filelist']['ignore'][] = |
array( |
'attribs' => array( |
'name' => $file, |
), |
); |
continue; |
} |
//o <ignore> tags for |
// <file name=... platform=other platform install-as=..> |
if (isset($package['platform'][$file]) && |
$package['platform'][$file]{0} != '!' && |
$package['platform'][$file] != $os) { |
$release[$releaseNum]['filelist']['ignore'][] = |
array( |
'attribs' => array( |
'name' => $file, |
), |
); |
continue; |
} |
} |
foreach ($package['platform'] as $file => $platform) { |
if (isset($package['install-as'][$file])) { |
continue; |
} |
//o <ignore> tags for <file name=... platform=!this platform> |
if ($platform == "!$os") { |
$release[$releaseNum]['filelist']['ignore'][] = |
array( |
'attribs' => array( |
'name' => $file, |
), |
); |
continue; |
} |
//o <ignore> tags for <file name=... platform=other platform> |
if ($platform{0} != '!' && $platform != $os) { |
$release[$releaseNum]['filelist']['ignore'][] = |
array( |
'attribs' => array( |
'name' => $file, |
), |
); |
} |
} |
if (!count($release[$releaseNum]['filelist']['install'])) { |
unset($release[$releaseNum]['filelist']['install']); |
} |
if (!count($release[$releaseNum]['filelist']['ignore'])) { |
unset($release[$releaseNum]['filelist']['ignore']); |
} |
} |
if (count($generic) || count($genericIgnore)) { |
$release[count($oses)] = array(); |
if (count($generic)) { |
foreach ($generic as $file) { |
if (isset($package['install-as'][$file])) { |
$installas = $package['install-as'][$file]; |
} else { |
$installas = $file; |
} |
$release[count($oses)]['filelist']['install'][] = |
array( |
'attribs' => array( |
'name' => $file, |
'as' => $installas, |
) |
); |
} |
} |
if (count($genericIgnore)) { |
foreach ($genericIgnore as $file) { |
$release[count($oses)]['filelist']['ignore'][] = |
array( |
'attribs' => array( |
'name' => $file, |
) |
); |
} |
} |
} |
// cleanup |
foreach ($release as $i => $rel) { |
if (isset($rel['filelist']['install']) && |
count($rel['filelist']['install']) == 1) { |
$release[$i]['filelist']['install'] = |
$release[$i]['filelist']['install'][0]; |
} |
if (isset($rel['filelist']['ignore']) && |
count($rel['filelist']['ignore']) == 1) { |
$release[$i]['filelist']['ignore'] = |
$release[$i]['filelist']['ignore'][0]; |
} |
} |
if (count($release) == 1) { |
$release = $release[0]; |
} |
} else { |
// no platform atts, but some install-as atts |
foreach ($package['install-as'] as $file => $value) { |
$release['filelist']['install'][] = |
array( |
'attribs' => array( |
'name' => $file, |
'as' => $value |
) |
); |
} |
if (count($release['filelist']['install']) == 1) { |
$release['filelist']['install'] = $release['filelist']['install'][0]; |
} |
} |
} |
} |
/** |
* @param array |
* @return array |
* @access private |
*/ |
function _processDep($dep) |
{ |
if ($dep['type'] == 'php') { |
if ($dep['rel'] == 'has') { |
// come on - everyone has php! |
return false; |
} |
} |
$php = array(); |
if ($dep['type'] != 'php') { |
$php['name'] = $dep['name']; |
if ($dep['type'] == 'pkg') { |
$php['channel'] = 'pear.php.net'; |
} |
} |
switch ($dep['rel']) { |
case 'gt' : |
$php['min'] = $dep['version']; |
$php['exclude'] = $dep['version']; |
break; |
case 'ge' : |
if (!isset($dep['version'])) { |
if ($dep['type'] == 'php') { |
if (isset($dep['name'])) { |
$dep['version'] = $dep['name']; |
} |
} |
} |
$php['min'] = $dep['version']; |
break; |
case 'lt' : |
$php['max'] = $dep['version']; |
$php['exclude'] = $dep['version']; |
break; |
case 'le' : |
$php['max'] = $dep['version']; |
break; |
case 'eq' : |
$php['min'] = $dep['version']; |
$php['max'] = $dep['version']; |
break; |
case 'ne' : |
$php['exclude'] = $dep['version']; |
break; |
case 'not' : |
$php['conflicts'] = 'yes'; |
break; |
} |
return $php; |
} |
/** |
* @param array |
* @return array |
*/ |
function _processPhpDeps($deps) |
{ |
$test = array(); |
foreach ($deps as $dep) { |
$test[] = $this->_processDep($dep); |
} |
$min = array(); |
$max = array(); |
foreach ($test as $dep) { |
if (!$dep) { |
continue; |
} |
if (isset($dep['min'])) { |
$min[$dep['min']] = count($min); |
} |
if (isset($dep['max'])) { |
$max[$dep['max']] = count($max); |
} |
} |
if (count($min) > 0) { |
uksort($min, 'version_compare'); |
} |
if (count($max) > 0) { |
uksort($max, 'version_compare'); |
} |
if (count($min)) { |
// get the highest minimum |
$a = array_flip($min); |
$min = array_pop($a); |
} else { |
$min = false; |
} |
if (count($max)) { |
// get the lowest maximum |
$a = array_flip($max); |
$max = array_shift($a); |
} else { |
$max = false; |
} |
if ($min) { |
$php['min'] = $min; |
} |
if ($max) { |
$php['max'] = $max; |
} |
$exclude = array(); |
foreach ($test as $dep) { |
if (!isset($dep['exclude'])) { |
continue; |
} |
$exclude[] = $dep['exclude']; |
} |
if (count($exclude)) { |
$php['exclude'] = $exclude; |
} |
return $php; |
} |
/** |
* process multiple dependencies that have a name, like package deps |
* @param array |
* @return array |
* @access private |
*/ |
function _processMultipleDepsName($deps) |
{ |
$ret = $tests = array(); |
foreach ($deps as $name => $dep) { |
foreach ($dep as $d) { |
$tests[$name][] = $this->_processDep($d); |
} |
} |
foreach ($tests as $name => $test) { |
$max = $min = $php = array(); |
$php['name'] = $name; |
foreach ($test as $dep) { |
if (!$dep) { |
continue; |
} |
if (isset($dep['channel'])) { |
$php['channel'] = 'pear.php.net'; |
} |
if (isset($dep['conflicts']) && $dep['conflicts'] == 'yes') { |
$php['conflicts'] = 'yes'; |
} |
if (isset($dep['min'])) { |
$min[$dep['min']] = count($min); |
} |
if (isset($dep['max'])) { |
$max[$dep['max']] = count($max); |
} |
} |
if (count($min) > 0) { |
uksort($min, 'version_compare'); |
} |
if (count($max) > 0) { |
uksort($max, 'version_compare'); |
} |
if (count($min)) { |
// get the highest minimum |
$a = array_flip($min); |
$min = array_pop($a); |
} else { |
$min = false; |
} |
if (count($max)) { |
// get the lowest maximum |
$a = array_flip($max); |
$max = array_shift($a); |
} else { |
$max = false; |
} |
if ($min) { |
$php['min'] = $min; |
} |
if ($max) { |
$php['max'] = $max; |
} |
$exclude = array(); |
foreach ($test as $dep) { |
if (!isset($dep['exclude'])) { |
continue; |
} |
$exclude[] = $dep['exclude']; |
} |
if (count($exclude)) { |
$php['exclude'] = $exclude; |
} |
$ret[] = $php; |
} |
return $ret; |
} |
} |
?> |
/branches/v1.3-critias/bibliotheque/pear/PEAR/PackageFile/Generator/v2.php |
---|
New file |
0,0 → 1,886 |
<?php |
/** |
* package.xml generation class, package.xml version 2.0 |
* |
* PHP versions 4 and 5 |
* |
* @category pear |
* @package PEAR |
* @author Greg Beaver <cellog@php.net> |
* @author Stephan Schmidt (original XML_Serializer code) |
* @copyright 1997-2009 The Authors |
* @license http://opensource.org/licenses/bsd-license.php New BSD License |
* @link http://pear.php.net/package/PEAR |
* @since File available since Release 1.4.0a1 |
*/ |
/** |
* file/dir manipulation routines |
*/ |
require_once 'System.php'; |
require_once 'XML/Util.php'; |
/** |
* This class converts a PEAR_PackageFile_v2 object into any output format. |
* |
* Supported output formats include array, XML string (using S. Schmidt's |
* XML_Serializer, slightly customized) |
* @category pear |
* @package PEAR |
* @author Greg Beaver <cellog@php.net> |
* @author Stephan Schmidt (original XML_Serializer code) |
* @copyright 1997-2009 The Authors |
* @license http://opensource.org/licenses/bsd-license.php New BSD License |
* @version Release: 1.10.1 |
* @link http://pear.php.net/package/PEAR |
* @since Class available since Release 1.4.0a1 |
*/ |
class PEAR_PackageFile_Generator_v2 |
{ |
/** |
* default options for the serialization |
* @access private |
* @var array $_defaultOptions |
*/ |
var $_defaultOptions = array( |
'indent' => ' ', // string used for indentation |
'linebreak' => "\n", // string used for newlines |
'typeHints' => false, // automatically add type hin attributes |
'addDecl' => true, // add an XML declaration |
'defaultTagName' => 'XML_Serializer_Tag', // tag used for indexed arrays or invalid names |
'classAsTagName' => false, // use classname for objects in indexed arrays |
'keyAttribute' => '_originalKey', // attribute where original key is stored |
'typeAttribute' => '_type', // attribute for type (only if typeHints => true) |
'classAttribute' => '_class', // attribute for class of objects (only if typeHints => true) |
'scalarAsAttributes' => false, // scalar values (strings, ints,..) will be serialized as attribute |
'prependAttributes' => '', // prepend string for attributes |
'indentAttributes' => false, // indent the attributes, if set to '_auto', it will indent attributes so they all start at the same column |
'mode' => 'simplexml', // use 'simplexml' to use parent name as tagname if transforming an indexed array |
'addDoctype' => false, // add a doctype declaration |
'doctype' => null, // supply a string or an array with id and uri ({@see XML_Util::getDoctypeDeclaration()} |
'rootName' => 'package', // name of the root tag |
'rootAttributes' => array( |
'version' => '2.0', |
'xmlns' => 'http://pear.php.net/dtd/package-2.0', |
'xmlns:tasks' => 'http://pear.php.net/dtd/tasks-1.0', |
'xmlns:xsi' => 'http://www.w3.org/2001/XMLSchema-instance', |
'xsi:schemaLocation' => 'http://pear.php.net/dtd/tasks-1.0 |
http://pear.php.net/dtd/tasks-1.0.xsd |
http://pear.php.net/dtd/package-2.0 |
http://pear.php.net/dtd/package-2.0.xsd', |
), // attributes of the root tag |
'attributesArray' => 'attribs', // all values in this key will be treated as attributes |
'contentName' => '_content', // this value will be used directly as content, instead of creating a new tag, may only be used in conjunction with attributesArray |
'beautifyFilelist' => false, |
'encoding' => 'UTF-8', |
); |
/** |
* options for the serialization |
* @access private |
* @var array $options |
*/ |
var $options = array(); |
/** |
* current tag depth |
* @var integer $_tagDepth |
*/ |
var $_tagDepth = 0; |
/** |
* serilialized representation of the data |
* @var string $_serializedData |
*/ |
var $_serializedData = null; |
/** |
* @var PEAR_PackageFile_v2 |
*/ |
var $_packagefile; |
/** |
* @param PEAR_PackageFile_v2 |
*/ |
function __construct(&$packagefile) |
{ |
$this->_packagefile = &$packagefile; |
if (isset($this->_packagefile->encoding)) { |
$this->_defaultOptions['encoding'] = $this->_packagefile->encoding; |
} |
} |
/** |
* @return string |
*/ |
function getPackagerVersion() |
{ |
return '1.10.1'; |
} |
/** |
* @param PEAR_Packager |
* @param bool generate a .tgz or a .tar |
* @param string|null temporary directory to package in |
*/ |
function toTgz(&$packager, $compress = true, $where = null) |
{ |
$a = null; |
return $this->toTgz2($packager, $a, $compress, $where); |
} |
/** |
* Package up both a package.xml and package2.xml for the same release |
* @param PEAR_Packager |
* @param PEAR_PackageFile_v1 |
* @param bool generate a .tgz or a .tar |
* @param string|null temporary directory to package in |
*/ |
function toTgz2(&$packager, &$pf1, $compress = true, $where = null) |
{ |
require_once 'Archive/Tar.php'; |
if (!$this->_packagefile->isEquivalent($pf1)) { |
return PEAR::raiseError('PEAR_Packagefile_v2::toTgz: "' . |
basename($pf1->getPackageFile()) . |
'" is not equivalent to "' . basename($this->_packagefile->getPackageFile()) |
. '"'); |
} |
if ($where === null) { |
if (!($where = System::mktemp(array('-d')))) { |
return PEAR::raiseError('PEAR_Packagefile_v2::toTgz: mktemp failed'); |
} |
} elseif (!@System::mkDir(array('-p', $where))) { |
return PEAR::raiseError('PEAR_Packagefile_v2::toTgz: "' . $where . '" could' . |
' not be created'); |
} |
$file = $where . DIRECTORY_SEPARATOR . 'package.xml'; |
if (file_exists($file) && !is_file($file)) { |
return PEAR::raiseError('PEAR_Packagefile_v2::toTgz: unable to save package.xml as' . |
' "' . $file .'"'); |
} |
if (!$this->_packagefile->validate(PEAR_VALIDATE_PACKAGING)) { |
return PEAR::raiseError('PEAR_Packagefile_v2::toTgz: invalid package.xml'); |
} |
$ext = $compress ? '.tgz' : '.tar'; |
$pkgver = $this->_packagefile->getPackage() . '-' . $this->_packagefile->getVersion(); |
$dest_package = getcwd() . DIRECTORY_SEPARATOR . $pkgver . $ext; |
if (file_exists($dest_package) && !is_file($dest_package)) { |
return PEAR::raiseError('PEAR_Packagefile_v2::toTgz: cannot create tgz file "' . |
$dest_package . '"'); |
} |
$pkgfile = $this->_packagefile->getPackageFile(); |
if (!$pkgfile) { |
return PEAR::raiseError('PEAR_Packagefile_v2::toTgz: package file object must ' . |
'be created from a real file'); |
} |
$pkgdir = dirname(realpath($pkgfile)); |
$pkgfile = basename($pkgfile); |
// {{{ Create the package file list |
$filelist = array(); |
$i = 0; |
$this->_packagefile->flattenFilelist(); |
$contents = $this->_packagefile->getContents(); |
if (isset($contents['bundledpackage'])) { // bundles of packages |
$contents = $contents['bundledpackage']; |
if (!isset($contents[0])) { |
$contents = array($contents); |
} |
$packageDir = $where; |
foreach ($contents as $i => $package) { |
$fname = $package; |
$file = $pkgdir . DIRECTORY_SEPARATOR . $fname; |
if (!file_exists($file)) { |
return $packager->raiseError("File does not exist: $fname"); |
} |
$tfile = $packageDir . DIRECTORY_SEPARATOR . $fname; |
System::mkdir(array('-p', dirname($tfile))); |
copy($file, $tfile); |
$filelist[$i++] = $tfile; |
$packager->log(2, "Adding package $fname"); |
} |
} else { // normal packages |
$contents = $contents['dir']['file']; |
if (!isset($contents[0])) { |
$contents = array($contents); |
} |
$packageDir = $where; |
foreach ($contents as $i => $file) { |
$fname = $file['attribs']['name']; |
$atts = $file['attribs']; |
$orig = $file; |
$file = $pkgdir . DIRECTORY_SEPARATOR . $fname; |
if (!file_exists($file)) { |
return $packager->raiseError("File does not exist: $fname"); |
} |
$origperms = fileperms($file); |
$tfile = $packageDir . DIRECTORY_SEPARATOR . $fname; |
unset($orig['attribs']); |
if (count($orig)) { // file with tasks |
// run any package-time tasks |
$contents = file_get_contents($file); |
foreach ($orig as $tag => $raw) { |
$tag = str_replace( |
array($this->_packagefile->getTasksNs() . ':', '-'), |
array('', '_'), $tag); |
$task = "PEAR_Task_$tag"; |
$task = new $task($this->_packagefile->_config, |
$this->_packagefile->_logger, |
PEAR_TASK_PACKAGE); |
$task->init($raw, $atts, null); |
$res = $task->startSession($this->_packagefile, $contents, $tfile); |
if (!$res) { |
continue; // skip this task |
} |
if (PEAR::isError($res)) { |
return $res; |
} |
$contents = $res; // save changes |
System::mkdir(array('-p', dirname($tfile))); |
$wp = fopen($tfile, "wb"); |
fwrite($wp, $contents); |
fclose($wp); |
} |
} |
if (!file_exists($tfile)) { |
System::mkdir(array('-p', dirname($tfile))); |
copy($file, $tfile); |
} |
chmod($tfile, $origperms); |
$filelist[$i++] = $tfile; |
$this->_packagefile->setFileAttribute($fname, 'md5sum', md5_file($tfile), $i - 1); |
$packager->log(2, "Adding file $fname"); |
} |
} |
// }}} |
$name = $pf1 !== null ? 'package2.xml' : 'package.xml'; |
$packagexml = $this->toPackageFile($where, PEAR_VALIDATE_PACKAGING, $name); |
if ($packagexml) { |
$tar = new Archive_Tar($dest_package, $compress); |
$tar->setErrorHandling(PEAR_ERROR_RETURN); // XXX Don't print errors |
// ----- Creates with the package.xml file |
$ok = $tar->createModify(array($packagexml), '', $where); |
if (PEAR::isError($ok)) { |
return $packager->raiseError($ok); |
} elseif (!$ok) { |
return $packager->raiseError('PEAR_Packagefile_v2::toTgz(): adding ' . $name . |
' failed'); |
} |
// ----- Add the content of the package |
if (!$tar->addModify($filelist, $pkgver, $where)) { |
return $packager->raiseError( |
'PEAR_Packagefile_v2::toTgz(): tarball creation failed'); |
} |
// add the package.xml version 1.0 |
if ($pf1 !== null) { |
$pfgen = &$pf1->getDefaultGenerator(); |
$packagexml1 = $pfgen->toPackageFile($where, PEAR_VALIDATE_PACKAGING, 'package.xml', true); |
if (!$tar->addModify(array($packagexml1), '', $where)) { |
return $packager->raiseError( |
'PEAR_Packagefile_v2::toTgz(): adding package.xml failed'); |
} |
} |
return $dest_package; |
} |
} |
function toPackageFile($where = null, $state = PEAR_VALIDATE_NORMAL, $name = 'package.xml') |
{ |
if (!$this->_packagefile->validate($state)) { |
return PEAR::raiseError('PEAR_Packagefile_v2::toPackageFile: invalid package.xml', |
null, null, null, $this->_packagefile->getValidationWarnings()); |
} |
if ($where === null) { |
if (!($where = System::mktemp(array('-d')))) { |
return PEAR::raiseError('PEAR_Packagefile_v2::toPackageFile: mktemp failed'); |
} |
} elseif (!@System::mkDir(array('-p', $where))) { |
return PEAR::raiseError('PEAR_Packagefile_v2::toPackageFile: "' . $where . '" could' . |
' not be created'); |
} |
$newpkgfile = $where . DIRECTORY_SEPARATOR . $name; |
$np = @fopen($newpkgfile, 'wb'); |
if (!$np) { |
return PEAR::raiseError('PEAR_Packagefile_v2::toPackageFile: unable to save ' . |
"$name as $newpkgfile"); |
} |
fwrite($np, $this->toXml($state)); |
fclose($np); |
return $newpkgfile; |
} |
function &toV2() |
{ |
return $this->_packagefile; |
} |
/** |
* Return an XML document based on the package info (as returned |
* by the PEAR_Common::infoFrom* methods). |
* |
* @return string XML data |
*/ |
function toXml($state = PEAR_VALIDATE_NORMAL, $options = array()) |
{ |
$this->_packagefile->setDate(date('Y-m-d')); |
$this->_packagefile->setTime(date('H:i:s')); |
if (!$this->_packagefile->validate($state)) { |
return false; |
} |
if (is_array($options)) { |
$this->options = array_merge($this->_defaultOptions, $options); |
} else { |
$this->options = $this->_defaultOptions; |
} |
$arr = $this->_packagefile->getArray(); |
if (isset($arr['filelist'])) { |
unset($arr['filelist']); |
} |
if (isset($arr['_lastversion'])) { |
unset($arr['_lastversion']); |
} |
// Fix the notes a little bit |
if (isset($arr['notes'])) { |
// This trims out the indenting, needs fixing |
$arr['notes'] = "\n" . trim($arr['notes']) . "\n"; |
} |
if (isset($arr['changelog']) && !empty($arr['changelog'])) { |
// Fix for inconsistency how the array is filled depending on the changelog release amount |
if (!isset($arr['changelog']['release'][0])) { |
$release = $arr['changelog']['release']; |
unset($arr['changelog']['release']); |
$arr['changelog']['release'] = array(); |
$arr['changelog']['release'][0] = $release; |
} |
foreach (array_keys($arr['changelog']['release']) as $key) { |
$c =& $arr['changelog']['release'][$key]; |
if (isset($c['notes'])) { |
// This trims out the indenting, needs fixing |
$c['notes'] = "\n" . trim($c['notes']) . "\n"; |
} |
} |
} |
if ($state ^ PEAR_VALIDATE_PACKAGING && !isset($arr['bundle'])) { |
$use = $this->_recursiveXmlFilelist($arr['contents']['dir']['file']); |
unset($arr['contents']['dir']['file']); |
if (isset($use['dir'])) { |
$arr['contents']['dir']['dir'] = $use['dir']; |
} |
if (isset($use['file'])) { |
$arr['contents']['dir']['file'] = $use['file']; |
} |
$this->options['beautifyFilelist'] = true; |
} |
$arr['attribs']['packagerversion'] = '1.10.1'; |
if ($this->serialize($arr, $options)) { |
return $this->_serializedData . "\n"; |
} |
return false; |
} |
function _recursiveXmlFilelist($list) |
{ |
$dirs = array(); |
if (isset($list['attribs'])) { |
$file = $list['attribs']['name']; |
unset($list['attribs']['name']); |
$attributes = $list['attribs']; |
$this->_addDir($dirs, explode('/', dirname($file)), $file, $attributes); |
} else { |
foreach ($list as $a) { |
$file = $a['attribs']['name']; |
$attributes = $a['attribs']; |
unset($a['attribs']); |
$this->_addDir($dirs, explode('/', dirname($file)), $file, $attributes, $a); |
} |
} |
$this->_formatDir($dirs); |
$this->_deFormat($dirs); |
return $dirs; |
} |
function _addDir(&$dirs, $dir, $file = null, $attributes = null, $tasks = null) |
{ |
if (!$tasks) { |
$tasks = array(); |
} |
if ($dir == array() || $dir == array('.')) { |
$dirs['file'][basename($file)] = $tasks; |
$attributes['name'] = basename($file); |
$dirs['file'][basename($file)]['attribs'] = $attributes; |
return; |
} |
$curdir = array_shift($dir); |
if (!isset($dirs['dir'][$curdir])) { |
$dirs['dir'][$curdir] = array(); |
} |
$this->_addDir($dirs['dir'][$curdir], $dir, $file, $attributes, $tasks); |
} |
function _formatDir(&$dirs) |
{ |
if (!count($dirs)) { |
return array(); |
} |
$newdirs = array(); |
if (isset($dirs['dir'])) { |
$newdirs['dir'] = $dirs['dir']; |
} |
if (isset($dirs['file'])) { |
$newdirs['file'] = $dirs['file']; |
} |
$dirs = $newdirs; |
if (isset($dirs['dir'])) { |
uksort($dirs['dir'], 'strnatcasecmp'); |
foreach ($dirs['dir'] as $dir => $contents) { |
$this->_formatDir($dirs['dir'][$dir]); |
} |
} |
if (isset($dirs['file'])) { |
uksort($dirs['file'], 'strnatcasecmp'); |
}; |
} |
function _deFormat(&$dirs) |
{ |
if (!count($dirs)) { |
return array(); |
} |
$newdirs = array(); |
if (isset($dirs['dir'])) { |
foreach ($dirs['dir'] as $dir => $contents) { |
$newdir = array(); |
$newdir['attribs']['name'] = $dir; |
$this->_deFormat($contents); |
foreach ($contents as $tag => $val) { |
$newdir[$tag] = $val; |
} |
$newdirs['dir'][] = $newdir; |
} |
if (count($newdirs['dir']) == 1) { |
$newdirs['dir'] = $newdirs['dir'][0]; |
} |
} |
if (isset($dirs['file'])) { |
foreach ($dirs['file'] as $name => $file) { |
$newdirs['file'][] = $file; |
} |
if (count($newdirs['file']) == 1) { |
$newdirs['file'] = $newdirs['file'][0]; |
} |
} |
$dirs = $newdirs; |
} |
/** |
* reset all options to default options |
* |
* @access public |
* @see setOption(), XML_Unserializer() |
*/ |
function resetOptions() |
{ |
$this->options = $this->_defaultOptions; |
} |
/** |
* set an option |
* |
* You can use this method if you do not want to set all options in the constructor |
* |
* @access public |
* @see resetOption(), XML_Serializer() |
*/ |
function setOption($name, $value) |
{ |
$this->options[$name] = $value; |
} |
/** |
* sets several options at once |
* |
* You can use this method if you do not want to set all options in the constructor |
* |
* @access public |
* @see resetOption(), XML_Unserializer(), setOption() |
*/ |
function setOptions($options) |
{ |
$this->options = array_merge($this->options, $options); |
} |
/** |
* serialize data |
* |
* @access public |
* @param mixed $data data to serialize |
* @return boolean true on success, pear error on failure |
*/ |
function serialize($data, $options = null) |
{ |
// if options have been specified, use them instead |
// of the previously defined ones |
if (is_array($options)) { |
$optionsBak = $this->options; |
if (isset($options['overrideOptions']) && $options['overrideOptions'] == true) { |
$this->options = array_merge($this->_defaultOptions, $options); |
} else { |
$this->options = array_merge($this->options, $options); |
} |
} else { |
$optionsBak = null; |
} |
// start depth is zero |
$this->_tagDepth = 0; |
$this->_serializedData = ''; |
// serialize an array |
if (is_array($data)) { |
$tagName = isset($this->options['rootName']) ? $this->options['rootName'] : 'array'; |
$this->_serializedData .= $this->_serializeArray($data, $tagName, $this->options['rootAttributes']); |
} |
// add doctype declaration |
if ($this->options['addDoctype'] === true) { |
$this->_serializedData = XML_Util::getDoctypeDeclaration($tagName, $this->options['doctype']) |
. $this->options['linebreak'] |
. $this->_serializedData; |
} |
// build xml declaration |
if ($this->options['addDecl']) { |
$atts = array(); |
$encoding = isset($this->options['encoding']) ? $this->options['encoding'] : null; |
$this->_serializedData = XML_Util::getXMLDeclaration('1.0', $encoding) |
. $this->options['linebreak'] |
. $this->_serializedData; |
} |
if ($optionsBak !== null) { |
$this->options = $optionsBak; |
} |
return true; |
} |
/** |
* get the result of the serialization |
* |
* @access public |
* @return string serialized XML |
*/ |
function getSerializedData() |
{ |
if ($this->_serializedData === null) { |
return $this->raiseError('No serialized data available. Use XML_Serializer::serialize() first.', XML_SERIALIZER_ERROR_NO_SERIALIZATION); |
} |
return $this->_serializedData; |
} |
/** |
* serialize any value |
* |
* This method checks for the type of the value and calls the appropriate method |
* |
* @access private |
* @param mixed $value |
* @param string $tagName |
* @param array $attributes |
* @return string |
*/ |
function _serializeValue($value, $tagName = null, $attributes = array()) |
{ |
if (is_array($value)) { |
$xml = $this->_serializeArray($value, $tagName, $attributes); |
} elseif (is_object($value)) { |
$xml = $this->_serializeObject($value, $tagName); |
} else { |
$tag = array( |
'qname' => $tagName, |
'attributes' => $attributes, |
'content' => $value |
); |
$xml = $this->_createXMLTag($tag); |
} |
return $xml; |
} |
/** |
* serialize an array |
* |
* @access private |
* @param array $array array to serialize |
* @param string $tagName name of the root tag |
* @param array $attributes attributes for the root tag |
* @return string $string serialized data |
* @uses XML_Util::isValidName() to check, whether key has to be substituted |
*/ |
function _serializeArray(&$array, $tagName = null, $attributes = array()) |
{ |
$_content = null; |
/** |
* check for special attributes |
*/ |
if ($this->options['attributesArray'] !== null) { |
if (isset($array[$this->options['attributesArray']])) { |
$attributes = $array[$this->options['attributesArray']]; |
unset($array[$this->options['attributesArray']]); |
} |
/** |
* check for special content |
*/ |
if ($this->options['contentName'] !== null) { |
if (isset($array[$this->options['contentName']])) { |
$_content = $array[$this->options['contentName']]; |
unset($array[$this->options['contentName']]); |
} |
} |
} |
/* |
* if mode is set to simpleXML, check whether |
* the array is associative or indexed |
*/ |
if (is_array($array) && $this->options['mode'] == 'simplexml') { |
$indexed = true; |
if (!count($array)) { |
$indexed = false; |
} |
foreach ($array as $key => $val) { |
if (!is_int($key)) { |
$indexed = false; |
break; |
} |
} |
if ($indexed && $this->options['mode'] == 'simplexml') { |
$string = ''; |
foreach ($array as $key => $val) { |
if ($this->options['beautifyFilelist'] && $tagName == 'dir') { |
if (!isset($this->_curdir)) { |
$this->_curdir = ''; |
} |
$savedir = $this->_curdir; |
if (isset($val['attribs'])) { |
if ($val['attribs']['name'] == '/') { |
$this->_curdir = '/'; |
} else { |
if ($this->_curdir == '/') { |
$this->_curdir = ''; |
} |
$this->_curdir .= '/' . $val['attribs']['name']; |
} |
} |
} |
$string .= $this->_serializeValue( $val, $tagName, $attributes); |
if ($this->options['beautifyFilelist'] && $tagName == 'dir') { |
$string .= ' <!-- ' . $this->_curdir . ' -->'; |
if (empty($savedir)) { |
unset($this->_curdir); |
} else { |
$this->_curdir = $savedir; |
} |
} |
$string .= $this->options['linebreak']; |
// do indentation |
if ($this->options['indent'] !== null && $this->_tagDepth > 0) { |
$string .= str_repeat($this->options['indent'], $this->_tagDepth); |
} |
} |
return rtrim($string); |
} |
} |
if ($this->options['scalarAsAttributes'] === true) { |
foreach ($array as $key => $value) { |
if (is_scalar($value) && (XML_Util::isValidName($key) === true)) { |
unset($array[$key]); |
$attributes[$this->options['prependAttributes'].$key] = $value; |
} |
} |
} |
// check for empty array => create empty tag |
if (empty($array)) { |
$tag = array( |
'qname' => $tagName, |
'content' => $_content, |
'attributes' => $attributes |
); |
} else { |
$this->_tagDepth++; |
$tmp = $this->options['linebreak']; |
foreach ($array as $key => $value) { |
// do indentation |
if ($this->options['indent'] !== null && $this->_tagDepth > 0) { |
$tmp .= str_repeat($this->options['indent'], $this->_tagDepth); |
} |
// copy key |
$origKey = $key; |
// key cannot be used as tagname => use default tag |
$valid = XML_Util::isValidName($key); |
if (PEAR::isError($valid)) { |
if ($this->options['classAsTagName'] && is_object($value)) { |
$key = get_class($value); |
} else { |
$key = $this->options['defaultTagName']; |
} |
} |
$atts = array(); |
if ($this->options['typeHints'] === true) { |
$atts[$this->options['typeAttribute']] = gettype($value); |
if ($key !== $origKey) { |
$atts[$this->options['keyAttribute']] = (string)$origKey; |
} |
} |
if ($this->options['beautifyFilelist'] && $key == 'dir') { |
if (!isset($this->_curdir)) { |
$this->_curdir = ''; |
} |
$savedir = $this->_curdir; |
if (isset($value['attribs'])) { |
if ($value['attribs']['name'] == '/') { |
$this->_curdir = '/'; |
} else { |
$this->_curdir .= '/' . $value['attribs']['name']; |
} |
} |
} |
if (is_string($value) && $value && ($value{strlen($value) - 1} == "\n")) { |
$value .= str_repeat($this->options['indent'], $this->_tagDepth); |
} |
$tmp .= $this->_createXMLTag(array( |
'qname' => $key, |
'attributes' => $atts, |
'content' => $value ) |
); |
if ($this->options['beautifyFilelist'] && $key == 'dir') { |
if (isset($value['attribs'])) { |
$tmp .= ' <!-- ' . $this->_curdir . ' -->'; |
if (empty($savedir)) { |
unset($this->_curdir); |
} else { |
$this->_curdir = $savedir; |
} |
} |
} |
$tmp .= $this->options['linebreak']; |
} |
$this->_tagDepth--; |
if ($this->options['indent']!==null && $this->_tagDepth>0) { |
$tmp .= str_repeat($this->options['indent'], $this->_tagDepth); |
} |
if (trim($tmp) === '') { |
$tmp = null; |
} |
$tag = array( |
'qname' => $tagName, |
'content' => $tmp, |
'attributes' => $attributes |
); |
} |
if ($this->options['typeHints'] === true) { |
if (!isset($tag['attributes'][$this->options['typeAttribute']])) { |
$tag['attributes'][$this->options['typeAttribute']] = 'array'; |
} |
} |
$string = $this->_createXMLTag($tag, false); |
return $string; |
} |
/** |
* create a tag from an array |
* this method awaits an array in the following format |
* array( |
* 'qname' => $tagName, |
* 'attributes' => array(), |
* 'content' => $content, // optional |
* 'namespace' => $namespace // optional |
* 'namespaceUri' => $namespaceUri // optional |
* ) |
* |
* @access private |
* @param array $tag tag definition |
* @param boolean $replaceEntities whether to replace XML entities in content or not |
* @return string $string XML tag |
*/ |
function _createXMLTag($tag, $replaceEntities = true) |
{ |
if ($this->options['indentAttributes'] !== false) { |
$multiline = true; |
$indent = str_repeat($this->options['indent'], $this->_tagDepth); |
if ($this->options['indentAttributes'] == '_auto') { |
$indent .= str_repeat(' ', (strlen($tag['qname'])+2)); |
} else { |
$indent .= $this->options['indentAttributes']; |
} |
} else { |
$indent = $multiline = false; |
} |
if (is_array($tag['content'])) { |
if (empty($tag['content'])) { |
$tag['content'] = ''; |
} |
} elseif(is_scalar($tag['content']) && (string)$tag['content'] == '') { |
$tag['content'] = ''; |
} |
if (is_scalar($tag['content']) || is_null($tag['content'])) { |
if ($replaceEntities === true) { |
$replaceEntities = XML_UTIL_ENTITIES_XML; |
} |
$tag = XML_Util::createTagFromArray($tag, $replaceEntities, $multiline, $indent, $this->options['linebreak']); |
} elseif (is_array($tag['content'])) { |
$tag = $this->_serializeArray($tag['content'], $tag['qname'], $tag['attributes']); |
} elseif (is_object($tag['content'])) { |
$tag = $this->_serializeObject($tag['content'], $tag['qname'], $tag['attributes']); |
} elseif (is_resource($tag['content'])) { |
settype($tag['content'], 'string'); |
$tag = XML_Util::createTagFromArray($tag, $replaceEntities); |
} |
return $tag; |
} |
} |
/branches/v1.3-critias/bibliotheque/pear/PEAR/PackageFile/v2/Validator.php |
---|
New file |
0,0 → 1,2135 |
<?php |
/** |
* PEAR_PackageFile_v2, package.xml version 2.0, read/write version |
* |
* PHP versions 4 and 5 |
* |
* @category pear |
* @package PEAR |
* @author Greg Beaver <cellog@php.net> |
* @copyright 1997-2009 The Authors |
* @license http://opensource.org/licenses/bsd-license.php New BSD License |
* @link http://pear.php.net/package/PEAR |
* @since File available since Release 1.4.0a8 |
*/ |
/** |
* Private validation class used by PEAR_PackageFile_v2 - do not use directly, its |
* sole purpose is to split up the PEAR/PackageFile/v2.php file to make it smaller |
* @category pear |
* @package PEAR |
* @author Greg Beaver <cellog@php.net> |
* @copyright 1997-2009 The Authors |
* @license http://opensource.org/licenses/bsd-license.php New BSD License |
* @version Release: 1.10.1 |
* @link http://pear.php.net/package/PEAR |
* @since Class available since Release 1.4.0a8 |
* @access private |
*/ |
class PEAR_PackageFile_v2_Validator |
{ |
/** |
* @var array |
*/ |
var $_packageInfo; |
/** |
* @var PEAR_PackageFile_v2 |
*/ |
var $_pf; |
/** |
* @var PEAR_ErrorStack |
*/ |
var $_stack; |
/** |
* @var int |
*/ |
var $_isValid = 0; |
/** |
* @var int |
*/ |
var $_filesValid = 0; |
/** |
* @var int |
*/ |
var $_curState = 0; |
/** |
* @param PEAR_PackageFile_v2 |
* @param int |
*/ |
function validate(&$pf, $state = PEAR_VALIDATE_NORMAL) |
{ |
$this->_pf = &$pf; |
$this->_curState = $state; |
$this->_packageInfo = $this->_pf->getArray(); |
$this->_isValid = $this->_pf->_isValid; |
$this->_filesValid = $this->_pf->_filesValid; |
$this->_stack = &$pf->_stack; |
$this->_stack->getErrors(true); |
if (($this->_isValid & $state) == $state) { |
return true; |
} |
if (!isset($this->_packageInfo) || !is_array($this->_packageInfo)) { |
return false; |
} |
if (!isset($this->_packageInfo['attribs']['version']) || |
($this->_packageInfo['attribs']['version'] != '2.0' && |
$this->_packageInfo['attribs']['version'] != '2.1') |
) { |
$this->_noPackageVersion(); |
} |
$structure = |
array( |
'name', |
'channel|uri', |
'*extends', // can't be multiple, but this works fine |
'summary', |
'description', |
'+lead', // these all need content checks |
'*developer', |
'*contributor', |
'*helper', |
'date', |
'*time', |
'version', |
'stability', |
'license->?uri->?filesource', |
'notes', |
'contents', //special validation needed |
'*compatible', |
'dependencies', //special validation needed |
'*usesrole', |
'*usestask', // reserve these for 1.4.0a1 to implement |
// this will allow a package.xml to gracefully say it |
// needs a certain package installed in order to implement a role or task |
'*providesextension', |
'*srcpackage|*srcuri', |
'+phprelease|+extsrcrelease|+extbinrelease|' . |
'+zendextsrcrelease|+zendextbinrelease|bundle', //special validation needed |
'*changelog', |
); |
$test = $this->_packageInfo; |
if (isset($test['dependencies']) && |
isset($test['dependencies']['required']) && |
isset($test['dependencies']['required']['pearinstaller']) && |
isset($test['dependencies']['required']['pearinstaller']['min']) && |
'1.10.1' != '@package' . '_version@' && |
version_compare('1.10.1', |
$test['dependencies']['required']['pearinstaller']['min'], '<') |
) { |
$this->_pearVersionTooLow($test['dependencies']['required']['pearinstaller']['min']); |
return false; |
} |
// ignore post-installation array fields |
if (array_key_exists('filelist', $test)) { |
unset($test['filelist']); |
} |
if (array_key_exists('_lastmodified', $test)) { |
unset($test['_lastmodified']); |
} |
if (array_key_exists('#binarypackage', $test)) { |
unset($test['#binarypackage']); |
} |
if (array_key_exists('old', $test)) { |
unset($test['old']); |
} |
if (array_key_exists('_lastversion', $test)) { |
unset($test['_lastversion']); |
} |
if (!$this->_stupidSchemaValidate($structure, $test, '<package>')) { |
return false; |
} |
if (empty($this->_packageInfo['name'])) { |
$this->_tagCannotBeEmpty('name'); |
} |
$test = isset($this->_packageInfo['uri']) ? 'uri' :'channel'; |
if (empty($this->_packageInfo[$test])) { |
$this->_tagCannotBeEmpty($test); |
} |
if (is_array($this->_packageInfo['license']) && |
(!isset($this->_packageInfo['license']['_content']) || |
empty($this->_packageInfo['license']['_content']))) { |
$this->_tagCannotBeEmpty('license'); |
} elseif (empty($this->_packageInfo['license'])) { |
$this->_tagCannotBeEmpty('license'); |
} |
if (empty($this->_packageInfo['summary'])) { |
$this->_tagCannotBeEmpty('summary'); |
} |
if (empty($this->_packageInfo['description'])) { |
$this->_tagCannotBeEmpty('description'); |
} |
if (empty($this->_packageInfo['date'])) { |
$this->_tagCannotBeEmpty('date'); |
} |
if (empty($this->_packageInfo['notes'])) { |
$this->_tagCannotBeEmpty('notes'); |
} |
if (isset($this->_packageInfo['time']) && empty($this->_packageInfo['time'])) { |
$this->_tagCannotBeEmpty('time'); |
} |
if (isset($this->_packageInfo['dependencies'])) { |
$this->_validateDependencies(); |
} |
if (isset($this->_packageInfo['compatible'])) { |
$this->_validateCompatible(); |
} |
if (!isset($this->_packageInfo['bundle'])) { |
if (empty($this->_packageInfo['contents'])) { |
$this->_tagCannotBeEmpty('contents'); |
} |
if (!isset($this->_packageInfo['contents']['dir'])) { |
$this->_filelistMustContainDir('contents'); |
return false; |
} |
if (isset($this->_packageInfo['contents']['file'])) { |
$this->_filelistCannotContainFile('contents'); |
return false; |
} |
} |
$this->_validateMaintainers(); |
$this->_validateStabilityVersion(); |
$fail = false; |
if (array_key_exists('usesrole', $this->_packageInfo)) { |
$roles = $this->_packageInfo['usesrole']; |
if (!is_array($roles) || !isset($roles[0])) { |
$roles = array($roles); |
} |
foreach ($roles as $role) { |
if (!isset($role['role'])) { |
$this->_usesroletaskMustHaveRoleTask('usesrole', 'role'); |
$fail = true; |
} else { |
if (!isset($role['channel'])) { |
if (!isset($role['uri'])) { |
$this->_usesroletaskMustHaveChannelOrUri($role['role'], 'usesrole'); |
$fail = true; |
} |
} elseif (!isset($role['package'])) { |
$this->_usesroletaskMustHavePackage($role['role'], 'usesrole'); |
$fail = true; |
} |
} |
} |
} |
if (array_key_exists('usestask', $this->_packageInfo)) { |
$roles = $this->_packageInfo['usestask']; |
if (!is_array($roles) || !isset($roles[0])) { |
$roles = array($roles); |
} |
foreach ($roles as $role) { |
if (!isset($role['task'])) { |
$this->_usesroletaskMustHaveRoleTask('usestask', 'task'); |
$fail = true; |
} else { |
if (!isset($role['channel'])) { |
if (!isset($role['uri'])) { |
$this->_usesroletaskMustHaveChannelOrUri($role['task'], 'usestask'); |
$fail = true; |
} |
} elseif (!isset($role['package'])) { |
$this->_usesroletaskMustHavePackage($role['task'], 'usestask'); |
$fail = true; |
} |
} |
} |
} |
if ($fail) { |
return false; |
} |
$list = $this->_packageInfo['contents']; |
if (isset($list['dir']) && is_array($list['dir']) && isset($list['dir'][0])) { |
$this->_multipleToplevelDirNotAllowed(); |
return $this->_isValid = 0; |
} |
$this->_validateFilelist(); |
$this->_validateRelease(); |
if (!$this->_stack->hasErrors()) { |
$chan = $this->_pf->_registry->getChannel($this->_pf->getChannel(), true); |
if (PEAR::isError($chan)) { |
$this->_unknownChannel($this->_pf->getChannel()); |
} else { |
$valpack = $chan->getValidationPackage(); |
// for channel validator packages, always use the default PEAR validator. |
// otherwise, they can't be installed or packaged |
$validator = $chan->getValidationObject($this->_pf->getPackage()); |
if (!$validator) { |
$this->_stack->push(__FUNCTION__, 'error', |
array('channel' => $chan->getName(), |
'package' => $this->_pf->getPackage(), |
'name' => $valpack['_content'], |
'version' => $valpack['attribs']['version']), |
'package "%channel%/%package%" cannot be properly validated without ' . |
'validation package "%channel%/%name%-%version%"'); |
return $this->_isValid = 0; |
} |
$validator->setPackageFile($this->_pf); |
$validator->validate($state); |
$failures = $validator->getFailures(); |
foreach ($failures['errors'] as $error) { |
$this->_stack->push(__FUNCTION__, 'error', $error, |
'Channel validator error: field "%field%" - %reason%'); |
} |
foreach ($failures['warnings'] as $warning) { |
$this->_stack->push(__FUNCTION__, 'warning', $warning, |
'Channel validator warning: field "%field%" - %reason%'); |
} |
} |
} |
$this->_pf->_isValid = $this->_isValid = !$this->_stack->hasErrors('error'); |
if ($this->_isValid && $state == PEAR_VALIDATE_PACKAGING && !$this->_filesValid) { |
if ($this->_pf->getPackageType() == 'bundle') { |
if ($this->_analyzeBundledPackages()) { |
$this->_filesValid = $this->_pf->_filesValid = true; |
} else { |
$this->_pf->_isValid = $this->_isValid = 0; |
} |
} else { |
if (!$this->_analyzePhpFiles()) { |
$this->_pf->_isValid = $this->_isValid = 0; |
} else { |
$this->_filesValid = $this->_pf->_filesValid = true; |
} |
} |
} |
if ($this->_isValid) { |
return $this->_pf->_isValid = $this->_isValid = $state; |
} |
return $this->_pf->_isValid = $this->_isValid = 0; |
} |
function _stupidSchemaValidate($structure, $xml, $root) |
{ |
if (!is_array($xml)) { |
$xml = array(); |
} |
$keys = array_keys($xml); |
reset($keys); |
$key = current($keys); |
while ($key == 'attribs' || $key == '_contents') { |
$key = next($keys); |
} |
$unfoundtags = $optionaltags = array(); |
$ret = true; |
$mismatch = false; |
foreach ($structure as $struc) { |
if ($key) { |
$tag = $xml[$key]; |
} |
$test = $this->_processStructure($struc); |
if (isset($test['choices'])) { |
$loose = true; |
foreach ($test['choices'] as $choice) { |
if ($key == $choice['tag']) { |
$key = next($keys); |
while ($key == 'attribs' || $key == '_contents') { |
$key = next($keys); |
} |
$unfoundtags = $optionaltags = array(); |
$mismatch = false; |
if ($key && $key != $choice['tag'] && isset($choice['multiple'])) { |
$unfoundtags[] = $choice['tag']; |
$optionaltags[] = $choice['tag']; |
if ($key) { |
$mismatch = true; |
} |
} |
$ret &= $this->_processAttribs($choice, $tag, $root); |
continue 2; |
} else { |
$unfoundtags[] = $choice['tag']; |
$mismatch = true; |
} |
if (!isset($choice['multiple']) || $choice['multiple'] != '*') { |
$loose = false; |
} else { |
$optionaltags[] = $choice['tag']; |
} |
} |
if (!$loose) { |
$this->_invalidTagOrder($unfoundtags, $key, $root); |
return false; |
} |
} else { |
if ($key != $test['tag']) { |
if (isset($test['multiple']) && $test['multiple'] != '*') { |
$unfoundtags[] = $test['tag']; |
$this->_invalidTagOrder($unfoundtags, $key, $root); |
return false; |
} else { |
if ($key) { |
$mismatch = true; |
} |
$unfoundtags[] = $test['tag']; |
$optionaltags[] = $test['tag']; |
} |
if (!isset($test['multiple'])) { |
$this->_invalidTagOrder($unfoundtags, $key, $root); |
return false; |
} |
continue; |
} else { |
$unfoundtags = $optionaltags = array(); |
$mismatch = false; |
} |
$key = next($keys); |
while ($key == 'attribs' || $key == '_contents') { |
$key = next($keys); |
} |
if ($key && $key != $test['tag'] && isset($test['multiple'])) { |
$unfoundtags[] = $test['tag']; |
$optionaltags[] = $test['tag']; |
$mismatch = true; |
} |
$ret &= $this->_processAttribs($test, $tag, $root); |
continue; |
} |
} |
if (!$mismatch && count($optionaltags)) { |
// don't error out on any optional tags |
$unfoundtags = array_diff($unfoundtags, $optionaltags); |
} |
if (count($unfoundtags)) { |
$this->_invalidTagOrder($unfoundtags, $key, $root); |
} elseif ($key) { |
// unknown tags |
$this->_invalidTagOrder('*no tags allowed here*', $key, $root); |
while ($key = next($keys)) { |
$this->_invalidTagOrder('*no tags allowed here*', $key, $root); |
} |
} |
return $ret; |
} |
function _processAttribs($choice, $tag, $context) |
{ |
if (isset($choice['attribs'])) { |
if (!is_array($tag)) { |
$tag = array($tag); |
} |
$tags = $tag; |
if (!isset($tags[0])) { |
$tags = array($tags); |
} |
$ret = true; |
foreach ($tags as $i => $tag) { |
if (!is_array($tag) || !isset($tag['attribs'])) { |
foreach ($choice['attribs'] as $attrib) { |
if ($attrib{0} != '?') { |
$ret &= $this->_tagHasNoAttribs($choice['tag'], |
$context); |
continue 2; |
} |
} |
} |
foreach ($choice['attribs'] as $attrib) { |
if ($attrib{0} != '?') { |
if (!isset($tag['attribs'][$attrib])) { |
$ret &= $this->_tagMissingAttribute($choice['tag'], |
$attrib, $context); |
} |
} |
} |
} |
return $ret; |
} |
return true; |
} |
function _processStructure($key) |
{ |
$ret = array(); |
if (count($pieces = explode('|', $key)) > 1) { |
$ret['choices'] = array(); |
foreach ($pieces as $piece) { |
$ret['choices'][] = $this->_processStructure($piece); |
} |
return $ret; |
} |
$multi = $key{0}; |
if ($multi == '+' || $multi == '*') { |
$ret['multiple'] = $key{0}; |
$key = substr($key, 1); |
} |
if (count($attrs = explode('->', $key)) > 1) { |
$ret['tag'] = array_shift($attrs); |
$ret['attribs'] = $attrs; |
} else { |
$ret['tag'] = $key; |
} |
return $ret; |
} |
function _validateStabilityVersion() |
{ |
$structure = array('release', 'api'); |
$a = $this->_stupidSchemaValidate($structure, $this->_packageInfo['version'], '<version>'); |
$a &= $this->_stupidSchemaValidate($structure, $this->_packageInfo['stability'], '<stability>'); |
if ($a) { |
if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?\\z/', |
$this->_packageInfo['version']['release'])) { |
$this->_invalidVersion('release', $this->_packageInfo['version']['release']); |
} |
if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?\\z/', |
$this->_packageInfo['version']['api'])) { |
$this->_invalidVersion('api', $this->_packageInfo['version']['api']); |
} |
if (!in_array($this->_packageInfo['stability']['release'], |
array('snapshot', 'devel', 'alpha', 'beta', 'stable'))) { |
$this->_invalidState('release', $this->_packageInfo['stability']['release']); |
} |
if (!in_array($this->_packageInfo['stability']['api'], |
array('devel', 'alpha', 'beta', 'stable'))) { |
$this->_invalidState('api', $this->_packageInfo['stability']['api']); |
} |
} |
} |
function _validateMaintainers() |
{ |
$structure = |
array( |
'name', |
'user', |
'email', |
'active', |
); |
foreach (array('lead', 'developer', 'contributor', 'helper') as $type) { |
if (!isset($this->_packageInfo[$type])) { |
continue; |
} |
if (isset($this->_packageInfo[$type][0])) { |
foreach ($this->_packageInfo[$type] as $lead) { |
$this->_stupidSchemaValidate($structure, $lead, '<' . $type . '>'); |
} |
} else { |
$this->_stupidSchemaValidate($structure, $this->_packageInfo[$type], |
'<' . $type . '>'); |
} |
} |
} |
function _validatePhpDep($dep, $installcondition = false) |
{ |
$structure = array( |
'min', |
'*max', |
'*exclude', |
); |
$type = $installcondition ? '<installcondition><php>' : '<dependencies><required><php>'; |
$this->_stupidSchemaValidate($structure, $dep, $type); |
if (isset($dep['min'])) { |
if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?(?:-[a-zA-Z0-9]+)?\\z/', |
$dep['min'])) { |
$this->_invalidVersion($type . '<min>', $dep['min']); |
} |
} |
if (isset($dep['max'])) { |
if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?(?:-[a-zA-Z0-9]+)?\\z/', |
$dep['max'])) { |
$this->_invalidVersion($type . '<max>', $dep['max']); |
} |
} |
if (isset($dep['exclude'])) { |
if (!is_array($dep['exclude'])) { |
$dep['exclude'] = array($dep['exclude']); |
} |
foreach ($dep['exclude'] as $exclude) { |
if (!preg_match( |
'/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?(?:-[a-zA-Z0-9]+)?\\z/', |
$exclude)) { |
$this->_invalidVersion($type . '<exclude>', $exclude); |
} |
} |
} |
} |
function _validatePearinstallerDep($dep) |
{ |
$structure = array( |
'min', |
'*max', |
'*recommended', |
'*exclude', |
); |
$this->_stupidSchemaValidate($structure, $dep, '<dependencies><required><pearinstaller>'); |
if (isset($dep['min'])) { |
if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?\\z/', |
$dep['min'])) { |
$this->_invalidVersion('<dependencies><required><pearinstaller><min>', |
$dep['min']); |
} |
} |
if (isset($dep['max'])) { |
if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?\\z/', |
$dep['max'])) { |
$this->_invalidVersion('<dependencies><required><pearinstaller><max>', |
$dep['max']); |
} |
} |
if (isset($dep['recommended'])) { |
if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?\\z/', |
$dep['recommended'])) { |
$this->_invalidVersion('<dependencies><required><pearinstaller><recommended>', |
$dep['recommended']); |
} |
} |
if (isset($dep['exclude'])) { |
if (!is_array($dep['exclude'])) { |
$dep['exclude'] = array($dep['exclude']); |
} |
foreach ($dep['exclude'] as $exclude) { |
if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?\\z/', |
$exclude)) { |
$this->_invalidVersion('<dependencies><required><pearinstaller><exclude>', |
$exclude); |
} |
} |
} |
} |
function _validatePackageDep($dep, $group, $type = '<package>') |
{ |
if (isset($dep['uri'])) { |
if (isset($dep['conflicts'])) { |
$structure = array( |
'name', |
'uri', |
'conflicts', |
'*providesextension', |
); |
} else { |
$structure = array( |
'name', |
'uri', |
'*providesextension', |
); |
} |
} else { |
if (isset($dep['conflicts'])) { |
$structure = array( |
'name', |
'channel', |
'*min', |
'*max', |
'*exclude', |
'conflicts', |
'*providesextension', |
); |
} else { |
$structure = array( |
'name', |
'channel', |
'*min', |
'*max', |
'*recommended', |
'*exclude', |
'*nodefault', |
'*providesextension', |
); |
} |
} |
if (isset($dep['name'])) { |
$type .= '<name>' . $dep['name'] . '</name>'; |
} |
$this->_stupidSchemaValidate($structure, $dep, '<dependencies>' . $group . $type); |
if (isset($dep['uri']) && (isset($dep['min']) || isset($dep['max']) || |
isset($dep['recommended']) || isset($dep['exclude']))) { |
$this->_uriDepsCannotHaveVersioning('<dependencies>' . $group . $type); |
} |
if (isset($dep['channel']) && strtolower($dep['channel']) == '__uri') { |
$this->_DepchannelCannotBeUri('<dependencies>' . $group . $type); |
} |
if (isset($dep['min'])) { |
if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?\\z/', |
$dep['min'])) { |
$this->_invalidVersion('<dependencies>' . $group . $type . '<min>', $dep['min']); |
} |
} |
if (isset($dep['max'])) { |
if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?\\z/', |
$dep['max'])) { |
$this->_invalidVersion('<dependencies>' . $group . $type . '<max>', $dep['max']); |
} |
} |
if (isset($dep['recommended'])) { |
if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?\\z/', |
$dep['recommended'])) { |
$this->_invalidVersion('<dependencies>' . $group . $type . '<recommended>', |
$dep['recommended']); |
} |
} |
if (isset($dep['exclude'])) { |
if (!is_array($dep['exclude'])) { |
$dep['exclude'] = array($dep['exclude']); |
} |
foreach ($dep['exclude'] as $exclude) { |
if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?\\z/', |
$exclude)) { |
$this->_invalidVersion('<dependencies>' . $group . $type . '<exclude>', |
$exclude); |
} |
} |
} |
} |
function _validateSubpackageDep($dep, $group) |
{ |
$this->_validatePackageDep($dep, $group, '<subpackage>'); |
if (isset($dep['providesextension'])) { |
$this->_subpackageCannotProvideExtension(isset($dep['name']) ? $dep['name'] : ''); |
} |
if (isset($dep['conflicts'])) { |
$this->_subpackagesCannotConflict(isset($dep['name']) ? $dep['name'] : ''); |
} |
} |
function _validateExtensionDep($dep, $group = false, $installcondition = false) |
{ |
if (isset($dep['conflicts'])) { |
$structure = array( |
'name', |
'*min', |
'*max', |
'*exclude', |
'conflicts', |
); |
} else { |
$structure = array( |
'name', |
'*min', |
'*max', |
'*recommended', |
'*exclude', |
); |
} |
if ($installcondition) { |
$type = '<installcondition><extension>'; |
} else { |
$type = '<dependencies>' . $group . '<extension>'; |
} |
if (isset($dep['name'])) { |
$type .= '<name>' . $dep['name'] . '</name>'; |
} |
$this->_stupidSchemaValidate($structure, $dep, $type); |
if (isset($dep['min'])) { |
if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?\\z/', |
$dep['min'])) { |
$this->_invalidVersion(substr($type, 1) . '<min', $dep['min']); |
} |
} |
if (isset($dep['max'])) { |
if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?\\z/', |
$dep['max'])) { |
$this->_invalidVersion(substr($type, 1) . '<max', $dep['max']); |
} |
} |
if (isset($dep['recommended'])) { |
if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?\\z/', |
$dep['recommended'])) { |
$this->_invalidVersion(substr($type, 1) . '<recommended', $dep['recommended']); |
} |
} |
if (isset($dep['exclude'])) { |
if (!is_array($dep['exclude'])) { |
$dep['exclude'] = array($dep['exclude']); |
} |
foreach ($dep['exclude'] as $exclude) { |
if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?\\z/', |
$exclude)) { |
$this->_invalidVersion(substr($type, 1) . '<exclude', $exclude); |
} |
} |
} |
} |
function _validateOsDep($dep, $installcondition = false) |
{ |
$structure = array( |
'name', |
'*conflicts', |
); |
$type = $installcondition ? '<installcondition><os>' : '<dependencies><required><os>'; |
if ($this->_stupidSchemaValidate($structure, $dep, $type)) { |
if ($dep['name'] == '*') { |
if (array_key_exists('conflicts', $dep)) { |
$this->_cannotConflictWithAllOs($type); |
} |
} |
} |
} |
function _validateArchDep($dep, $installcondition = false) |
{ |
$structure = array( |
'pattern', |
'*conflicts', |
); |
$type = $installcondition ? '<installcondition><arch>' : '<dependencies><required><arch>'; |
$this->_stupidSchemaValidate($structure, $dep, $type); |
} |
function _validateInstallConditions($cond, $release) |
{ |
$structure = array( |
'*php', |
'*extension', |
'*os', |
'*arch', |
); |
if (!$this->_stupidSchemaValidate($structure, |
$cond, $release)) { |
return false; |
} |
foreach (array('php', 'extension', 'os', 'arch') as $type) { |
if (isset($cond[$type])) { |
$iter = $cond[$type]; |
if (!is_array($iter) || !isset($iter[0])) { |
$iter = array($iter); |
} |
foreach ($iter as $package) { |
if ($type == 'extension') { |
$this->{"_validate{$type}Dep"}($package, false, true); |
} else { |
$this->{"_validate{$type}Dep"}($package, true); |
} |
} |
} |
} |
} |
function _validateDependencies() |
{ |
$structure = array( |
'required', |
'*optional', |
'*group->name->hint' |
); |
if (!$this->_stupidSchemaValidate($structure, |
$this->_packageInfo['dependencies'], '<dependencies>')) { |
return false; |
} |
foreach (array('required', 'optional') as $simpledep) { |
if (isset($this->_packageInfo['dependencies'][$simpledep])) { |
if ($simpledep == 'optional') { |
$structure = array( |
'*package', |
'*subpackage', |
'*extension', |
); |
} else { |
$structure = array( |
'php', |
'pearinstaller', |
'*package', |
'*subpackage', |
'*extension', |
'*os', |
'*arch', |
); |
} |
if ($this->_stupidSchemaValidate($structure, |
$this->_packageInfo['dependencies'][$simpledep], |
"<dependencies><$simpledep>")) { |
foreach (array('package', 'subpackage', 'extension') as $type) { |
if (isset($this->_packageInfo['dependencies'][$simpledep][$type])) { |
$iter = $this->_packageInfo['dependencies'][$simpledep][$type]; |
if (!isset($iter[0])) { |
$iter = array($iter); |
} |
foreach ($iter as $package) { |
if ($type != 'extension') { |
if (isset($package['uri'])) { |
if (isset($package['channel'])) { |
$this->_UrlOrChannel($type, |
$package['name']); |
} |
} else { |
if (!isset($package['channel'])) { |
$this->_NoChannel($type, $package['name']); |
} |
} |
} |
$this->{"_validate{$type}Dep"}($package, "<$simpledep>"); |
} |
} |
} |
if ($simpledep == 'optional') { |
continue; |
} |
foreach (array('php', 'pearinstaller', 'os', 'arch') as $type) { |
if (isset($this->_packageInfo['dependencies'][$simpledep][$type])) { |
$iter = $this->_packageInfo['dependencies'][$simpledep][$type]; |
if (!isset($iter[0])) { |
$iter = array($iter); |
} |
foreach ($iter as $package) { |
$this->{"_validate{$type}Dep"}($package); |
} |
} |
} |
} |
} |
} |
if (isset($this->_packageInfo['dependencies']['group'])) { |
$groups = $this->_packageInfo['dependencies']['group']; |
if (!isset($groups[0])) { |
$groups = array($groups); |
} |
$structure = array( |
'*package', |
'*subpackage', |
'*extension', |
); |
foreach ($groups as $group) { |
if ($this->_stupidSchemaValidate($structure, $group, '<group>')) { |
if (!PEAR_Validate::validGroupName($group['attribs']['name'])) { |
$this->_invalidDepGroupName($group['attribs']['name']); |
} |
foreach (array('package', 'subpackage', 'extension') as $type) { |
if (isset($group[$type])) { |
$iter = $group[$type]; |
if (!isset($iter[0])) { |
$iter = array($iter); |
} |
foreach ($iter as $package) { |
if ($type != 'extension') { |
if (isset($package['uri'])) { |
if (isset($package['channel'])) { |
$this->_UrlOrChannelGroup($type, |
$package['name'], |
$group['name']); |
} |
} else { |
if (!isset($package['channel'])) { |
$this->_NoChannelGroup($type, |
$package['name'], |
$group['name']); |
} |
} |
} |
$this->{"_validate{$type}Dep"}($package, '<group name="' . |
$group['attribs']['name'] . '">'); |
} |
} |
} |
} |
} |
} |
} |
function _validateCompatible() |
{ |
$compat = $this->_packageInfo['compatible']; |
if (!isset($compat[0])) { |
$compat = array($compat); |
} |
$required = array('name', 'channel', 'min', 'max', '*exclude'); |
foreach ($compat as $package) { |
$type = '<compatible>'; |
if (is_array($package) && array_key_exists('name', $package)) { |
$type .= '<name>' . $package['name'] . '</name>'; |
} |
$this->_stupidSchemaValidate($required, $package, $type); |
if (is_array($package) && array_key_exists('min', $package)) { |
if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?\\z/', |
$package['min'])) { |
$this->_invalidVersion(substr($type, 1) . '<min', $package['min']); |
} |
} |
if (is_array($package) && array_key_exists('max', $package)) { |
if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?\\z/', |
$package['max'])) { |
$this->_invalidVersion(substr($type, 1) . '<max', $package['max']); |
} |
} |
if (is_array($package) && array_key_exists('exclude', $package)) { |
if (!is_array($package['exclude'])) { |
$package['exclude'] = array($package['exclude']); |
} |
foreach ($package['exclude'] as $exclude) { |
if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?\\z/', |
$exclude)) { |
$this->_invalidVersion(substr($type, 1) . '<exclude', $exclude); |
} |
} |
} |
} |
} |
function _validateBundle($list) |
{ |
if (!is_array($list) || !isset($list['bundledpackage'])) { |
return $this->_NoBundledPackages(); |
} |
if (!is_array($list['bundledpackage']) || !isset($list['bundledpackage'][0])) { |
return $this->_AtLeast2BundledPackages(); |
} |
foreach ($list['bundledpackage'] as $package) { |
if (!is_string($package)) { |
$this->_bundledPackagesMustBeFilename(); |
} |
} |
} |
function _validateFilelist($list = false, $allowignore = false, $dirs = '') |
{ |
$iscontents = false; |
if (!$list) { |
$iscontents = true; |
$list = $this->_packageInfo['contents']; |
if (isset($this->_packageInfo['bundle'])) { |
return $this->_validateBundle($list); |
} |
} |
if ($allowignore) { |
$struc = array( |
'*install->name->as', |
'*ignore->name' |
); |
} else { |
$struc = array( |
'*dir->name->?baseinstalldir', |
'*file->name->role->?baseinstalldir->?md5sum' |
); |
if (isset($list['dir']) && isset($list['file'])) { |
// stave off validation errors without requiring a set order. |
$_old = $list; |
if (isset($list['attribs'])) { |
$list = array('attribs' => $_old['attribs']); |
} |
$list['dir'] = $_old['dir']; |
$list['file'] = $_old['file']; |
} |
} |
if (!isset($list['attribs']) || !isset($list['attribs']['name'])) { |
$unknown = $allowignore ? '<filelist>' : '<dir name="*unknown*">'; |
$dirname = $iscontents ? '<contents>' : $unknown; |
} else { |
$dirname = '<dir name="' . $list['attribs']['name'] . '">'; |
if (preg_match('~/\.\.?(/|\\z)|^\.\.?/~', |
str_replace('\\', '/', $list['attribs']['name']))) { |
// file contains .. parent directory or . cur directory |
$this->_invalidDirName($list['attribs']['name']); |
} |
} |
$res = $this->_stupidSchemaValidate($struc, $list, $dirname); |
if ($allowignore && $res) { |
$ignored_or_installed = array(); |
$this->_pf->getFilelist(); |
$fcontents = $this->_pf->getContents(); |
$filelist = array(); |
if (!isset($fcontents['dir']['file'][0])) { |
$fcontents['dir']['file'] = array($fcontents['dir']['file']); |
} |
foreach ($fcontents['dir']['file'] as $file) { |
$filelist[$file['attribs']['name']] = true; |
} |
if (isset($list['install'])) { |
if (!isset($list['install'][0])) { |
$list['install'] = array($list['install']); |
} |
foreach ($list['install'] as $file) { |
if (!isset($filelist[$file['attribs']['name']])) { |
$this->_notInContents($file['attribs']['name'], 'install'); |
continue; |
} |
if (array_key_exists($file['attribs']['name'], $ignored_or_installed)) { |
$this->_multipleInstallAs($file['attribs']['name']); |
} |
if (!isset($ignored_or_installed[$file['attribs']['name']])) { |
$ignored_or_installed[$file['attribs']['name']] = array(); |
} |
$ignored_or_installed[$file['attribs']['name']][] = 1; |
if (preg_match('~/\.\.?(/|\\z)|^\.\.?/~', |
str_replace('\\', '/', $file['attribs']['as']))) { |
// file contains .. parent directory or . cur directory references |
$this->_invalidFileInstallAs($file['attribs']['name'], |
$file['attribs']['as']); |
} |
} |
} |
if (isset($list['ignore'])) { |
if (!isset($list['ignore'][0])) { |
$list['ignore'] = array($list['ignore']); |
} |
foreach ($list['ignore'] as $file) { |
if (!isset($filelist[$file['attribs']['name']])) { |
$this->_notInContents($file['attribs']['name'], 'ignore'); |
continue; |
} |
if (array_key_exists($file['attribs']['name'], $ignored_or_installed)) { |
$this->_ignoreAndInstallAs($file['attribs']['name']); |
} |
} |
} |
} |
if (!$allowignore && isset($list['file'])) { |
if (is_string($list['file'])) { |
$this->_oldStyleFileNotAllowed(); |
return false; |
} |
if (!isset($list['file'][0])) { |
// single file |
$list['file'] = array($list['file']); |
} |
foreach ($list['file'] as $i => $file) |
{ |
if (isset($file['attribs']) && isset($file['attribs']['name'])) { |
if ($file['attribs']['name']{0} == '.' && |
$file['attribs']['name']{1} == '/') { |
// name is something like "./doc/whatever.txt" |
$this->_invalidFileName($file['attribs']['name'], $dirname); |
} |
if (preg_match('~/\.\.?(/|\\z)|^\.\.?/~', |
str_replace('\\', '/', $file['attribs']['name']))) { |
// file contains .. parent directory or . cur directory |
$this->_invalidFileName($file['attribs']['name'], $dirname); |
} |
} |
if (isset($file['attribs']) && isset($file['attribs']['role'])) { |
if (!$this->_validateRole($file['attribs']['role'])) { |
if (isset($this->_packageInfo['usesrole'])) { |
$roles = $this->_packageInfo['usesrole']; |
if (!isset($roles[0])) { |
$roles = array($roles); |
} |
foreach ($roles as $role) { |
if ($role['role'] = $file['attribs']['role']) { |
$msg = 'This package contains role "%role%" and requires ' . |
'package "%package%" to be used'; |
if (isset($role['uri'])) { |
$params = array('role' => $role['role'], |
'package' => $role['uri']); |
} else { |
$params = array('role' => $role['role'], |
'package' => $this->_pf->_registry-> |
parsedPackageNameToString(array('package' => |
$role['package'], 'channel' => $role['channel']), |
true)); |
} |
$this->_stack->push('_mustInstallRole', 'error', $params, $msg); |
} |
} |
} |
$this->_invalidFileRole($file['attribs']['name'], |
$dirname, $file['attribs']['role']); |
} |
} |
if (!isset($file['attribs'])) { |
continue; |
} |
$save = $file['attribs']; |
if ($dirs) { |
$save['name'] = $dirs . '/' . $save['name']; |
} |
unset($file['attribs']); |
if (count($file) && $this->_curState != PEAR_VALIDATE_DOWNLOADING) { // has tasks |
foreach ($file as $task => $value) { |
if ($tagClass = $this->_pf->getTask($task)) { |
if (!is_array($value) || !isset($value[0])) { |
$value = array($value); |
} |
foreach ($value as $v) { |
$ret = call_user_func(array($tagClass, 'validateXml'), |
$this->_pf, $v, $this->_pf->_config, $save); |
if (is_array($ret)) { |
$this->_invalidTask($task, $ret, isset($save['name']) ? |
$save['name'] : ''); |
} |
} |
} else { |
if (isset($this->_packageInfo['usestask'])) { |
$roles = $this->_packageInfo['usestask']; |
if (!isset($roles[0])) { |
$roles = array($roles); |
} |
foreach ($roles as $role) { |
if ($role['task'] = $task) { |
$msg = 'This package contains task "%task%" and requires ' . |
'package "%package%" to be used'; |
if (isset($role['uri'])) { |
$params = array('task' => $role['task'], |
'package' => $role['uri']); |
} else { |
$params = array('task' => $role['task'], |
'package' => $this->_pf->_registry-> |
parsedPackageNameToString(array('package' => |
$role['package'], 'channel' => $role['channel']), |
true)); |
} |
$this->_stack->push('_mustInstallTask', 'error', |
$params, $msg); |
} |
} |
} |
$this->_unknownTask($task, $save['name']); |
} |
} |
} |
} |
} |
if (isset($list['ignore'])) { |
if (!$allowignore) { |
$this->_ignoreNotAllowed('ignore'); |
} |
} |
if (isset($list['install'])) { |
if (!$allowignore) { |
$this->_ignoreNotAllowed('install'); |
} |
} |
if (isset($list['file'])) { |
if ($allowignore) { |
$this->_fileNotAllowed('file'); |
} |
} |
if (isset($list['dir'])) { |
if ($allowignore) { |
$this->_fileNotAllowed('dir'); |
} else { |
if (!isset($list['dir'][0])) { |
$list['dir'] = array($list['dir']); |
} |
foreach ($list['dir'] as $dir) { |
if (isset($dir['attribs']) && isset($dir['attribs']['name'])) { |
if ($dir['attribs']['name'] == '/' || |
!isset($this->_packageInfo['contents']['dir']['dir'])) { |
// always use nothing if the filelist has already been flattened |
$newdirs = ''; |
} elseif ($dirs == '') { |
$newdirs = $dir['attribs']['name']; |
} else { |
$newdirs = $dirs . '/' . $dir['attribs']['name']; |
} |
} else { |
$newdirs = $dirs; |
} |
$this->_validateFilelist($dir, $allowignore, $newdirs); |
} |
} |
} |
} |
function _validateRelease() |
{ |
if (isset($this->_packageInfo['phprelease'])) { |
$release = 'phprelease'; |
if (isset($this->_packageInfo['providesextension'])) { |
$this->_cannotProvideExtension($release); |
} |
if (isset($this->_packageInfo['srcpackage']) || isset($this->_packageInfo['srcuri'])) { |
$this->_cannotHaveSrcpackage($release); |
} |
$releases = $this->_packageInfo['phprelease']; |
if (!is_array($releases)) { |
return true; |
} |
if (!isset($releases[0])) { |
$releases = array($releases); |
} |
foreach ($releases as $rel) { |
$this->_stupidSchemaValidate(array( |
'*installconditions', |
'*filelist', |
), $rel, '<phprelease>'); |
} |
} |
foreach (array('', 'zend') as $prefix) { |
$releasetype = $prefix . 'extsrcrelease'; |
if (isset($this->_packageInfo[$releasetype])) { |
$release = $releasetype; |
if (!isset($this->_packageInfo['providesextension'])) { |
$this->_mustProvideExtension($release); |
} |
if (isset($this->_packageInfo['srcpackage']) || isset($this->_packageInfo['srcuri'])) { |
$this->_cannotHaveSrcpackage($release); |
} |
$releases = $this->_packageInfo[$releasetype]; |
if (!is_array($releases)) { |
return true; |
} |
if (!isset($releases[0])) { |
$releases = array($releases); |
} |
foreach ($releases as $rel) { |
$this->_stupidSchemaValidate(array( |
'*installconditions', |
'*configureoption->name->prompt->?default', |
'*binarypackage', |
'*filelist', |
), $rel, '<' . $releasetype . '>'); |
if (isset($rel['binarypackage'])) { |
if (!is_array($rel['binarypackage']) || !isset($rel['binarypackage'][0])) { |
$rel['binarypackage'] = array($rel['binarypackage']); |
} |
foreach ($rel['binarypackage'] as $bin) { |
if (!is_string($bin)) { |
$this->_binaryPackageMustBePackagename(); |
} |
} |
} |
} |
} |
$releasetype = 'extbinrelease'; |
if (isset($this->_packageInfo[$releasetype])) { |
$release = $releasetype; |
if (!isset($this->_packageInfo['providesextension'])) { |
$this->_mustProvideExtension($release); |
} |
if (isset($this->_packageInfo['channel']) && |
!isset($this->_packageInfo['srcpackage'])) { |
$this->_mustSrcPackage($release); |
} |
if (isset($this->_packageInfo['uri']) && !isset($this->_packageInfo['srcuri'])) { |
$this->_mustSrcuri($release); |
} |
$releases = $this->_packageInfo[$releasetype]; |
if (!is_array($releases)) { |
return true; |
} |
if (!isset($releases[0])) { |
$releases = array($releases); |
} |
foreach ($releases as $rel) { |
$this->_stupidSchemaValidate(array( |
'*installconditions', |
'*filelist', |
), $rel, '<' . $releasetype . '>'); |
} |
} |
} |
if (isset($this->_packageInfo['bundle'])) { |
$release = 'bundle'; |
if (isset($this->_packageInfo['providesextension'])) { |
$this->_cannotProvideExtension($release); |
} |
if (isset($this->_packageInfo['srcpackage']) || isset($this->_packageInfo['srcuri'])) { |
$this->_cannotHaveSrcpackage($release); |
} |
$releases = $this->_packageInfo['bundle']; |
if (!is_array($releases) || !isset($releases[0])) { |
$releases = array($releases); |
} |
foreach ($releases as $rel) { |
$this->_stupidSchemaValidate(array( |
'*installconditions', |
'*filelist', |
), $rel, '<bundle>'); |
} |
} |
foreach ($releases as $rel) { |
if (is_array($rel) && array_key_exists('installconditions', $rel)) { |
$this->_validateInstallConditions($rel['installconditions'], |
"<$release><installconditions>"); |
} |
if (is_array($rel) && array_key_exists('filelist', $rel)) { |
if ($rel['filelist']) { |
$this->_validateFilelist($rel['filelist'], true); |
} |
} |
} |
} |
/** |
* This is here to allow role extension through plugins |
* @param string |
*/ |
function _validateRole($role) |
{ |
return in_array($role, PEAR_Installer_Role::getValidRoles($this->_pf->getPackageType())); |
} |
function _pearVersionTooLow($version) |
{ |
$this->_stack->push(__FUNCTION__, 'error', |
array('version' => $version), |
'This package.xml requires PEAR version %version% to parse properly, we are ' . |
'version 1.10.1'); |
} |
function _invalidTagOrder($oktags, $actual, $root) |
{ |
$this->_stack->push(__FUNCTION__, 'error', |
array('oktags' => $oktags, 'actual' => $actual, 'root' => $root), |
'Invalid tag order in %root%, found <%actual%> expected one of "%oktags%"'); |
} |
function _ignoreNotAllowed($type) |
{ |
$this->_stack->push(__FUNCTION__, 'error', array('type' => $type), |
'<%type%> is not allowed inside global <contents>, only inside ' . |
'<phprelease>/<extbinrelease>/<zendextbinrelease>, use <dir> and <file> only'); |
} |
function _fileNotAllowed($type) |
{ |
$this->_stack->push(__FUNCTION__, 'error', array('type' => $type), |
'<%type%> is not allowed inside release <filelist>, only inside ' . |
'<contents>, use <ignore> and <install> only'); |
} |
function _oldStyleFileNotAllowed() |
{ |
$this->_stack->push(__FUNCTION__, 'error', array(), |
'Old-style <file>name</file> is not allowed. Use' . |
'<file name="name" role="role"/>'); |
} |
function _tagMissingAttribute($tag, $attr, $context) |
{ |
$this->_stack->push(__FUNCTION__, 'error', array('tag' => $tag, |
'attribute' => $attr, 'context' => $context), |
'tag <%tag%> in context "%context%" has no attribute "%attribute%"'); |
} |
function _tagHasNoAttribs($tag, $context) |
{ |
$this->_stack->push(__FUNCTION__, 'error', array('tag' => $tag, |
'context' => $context), |
'tag <%tag%> has no attributes in context "%context%"'); |
} |
function _invalidInternalStructure() |
{ |
$this->_stack->push(__FUNCTION__, 'exception', array(), |
'internal array was not generated by compatible parser, or extreme parser error, cannot continue'); |
} |
function _invalidFileRole($file, $dir, $role) |
{ |
$this->_stack->push(__FUNCTION__, 'error', array( |
'file' => $file, 'dir' => $dir, 'role' => $role, |
'roles' => PEAR_Installer_Role::getValidRoles($this->_pf->getPackageType())), |
'File "%file%" in directory "%dir%" has invalid role "%role%", should be one of %roles%'); |
} |
function _invalidFileName($file, $dir) |
{ |
$this->_stack->push(__FUNCTION__, 'error', array( |
'file' => $file), |
'File "%file%" in directory "%dir%" cannot begin with "./" or contain ".."'); |
} |
function _invalidFileInstallAs($file, $as) |
{ |
$this->_stack->push(__FUNCTION__, 'error', array( |
'file' => $file, 'as' => $as), |
'File "%file%" <install as="%as%"/> cannot contain "./" or contain ".."'); |
} |
function _invalidDirName($dir) |
{ |
$this->_stack->push(__FUNCTION__, 'error', array( |
'dir' => $file), |
'Directory "%dir%" cannot begin with "./" or contain ".."'); |
} |
function _filelistCannotContainFile($filelist) |
{ |
$this->_stack->push(__FUNCTION__, 'error', array('tag' => $filelist), |
'<%tag%> can only contain <dir>, contains <file>. Use ' . |
'<dir name="/"> as the first dir element'); |
} |
function _filelistMustContainDir($filelist) |
{ |
$this->_stack->push(__FUNCTION__, 'error', array('tag' => $filelist), |
'<%tag%> must contain <dir>. Use <dir name="/"> as the ' . |
'first dir element'); |
} |
function _tagCannotBeEmpty($tag) |
{ |
$this->_stack->push(__FUNCTION__, 'error', array('tag' => $tag), |
'<%tag%> cannot be empty (<%tag%/>)'); |
} |
function _UrlOrChannel($type, $name) |
{ |
$this->_stack->push(__FUNCTION__, 'error', array('type' => $type, |
'name' => $name), |
'Required dependency <%type%> "%name%" can have either url OR ' . |
'channel attributes, and not both'); |
} |
function _NoChannel($type, $name) |
{ |
$this->_stack->push(__FUNCTION__, 'error', array('type' => $type, |
'name' => $name), |
'Required dependency <%type%> "%name%" must have either url OR ' . |
'channel attributes'); |
} |
function _UrlOrChannelGroup($type, $name, $group) |
{ |
$this->_stack->push(__FUNCTION__, 'error', array('type' => $type, |
'name' => $name, 'group' => $group), |
'Group "%group%" dependency <%type%> "%name%" can have either url OR ' . |
'channel attributes, and not both'); |
} |
function _NoChannelGroup($type, $name, $group) |
{ |
$this->_stack->push(__FUNCTION__, 'error', array('type' => $type, |
'name' => $name, 'group' => $group), |
'Group "%group%" dependency <%type%> "%name%" must have either url OR ' . |
'channel attributes'); |
} |
function _unknownChannel($channel) |
{ |
$this->_stack->push(__FUNCTION__, 'error', array('channel' => $channel), |
'Unknown channel "%channel%"'); |
} |
function _noPackageVersion() |
{ |
$this->_stack->push(__FUNCTION__, 'error', array(), |
'package.xml <package> tag has no version attribute, or version is not 2.0'); |
} |
function _NoBundledPackages() |
{ |
$this->_stack->push(__FUNCTION__, 'error', array(), |
'No <bundledpackage> tag was found in <contents>, required for bundle packages'); |
} |
function _AtLeast2BundledPackages() |
{ |
$this->_stack->push(__FUNCTION__, 'error', array(), |
'At least 2 packages must be bundled in a bundle package'); |
} |
function _ChannelOrUri($name) |
{ |
$this->_stack->push(__FUNCTION__, 'error', array('name' => $name), |
'Bundled package "%name%" can have either a uri or a channel, not both'); |
} |
function _noChildTag($child, $tag) |
{ |
$this->_stack->push(__FUNCTION__, 'error', array('child' => $child, 'tag' => $tag), |
'Tag <%tag%> is missing child tag <%child%>'); |
} |
function _invalidVersion($type, $value) |
{ |
$this->_stack->push(__FUNCTION__, 'error', array('type' => $type, 'value' => $value), |
'Version type <%type%> is not a valid version (%value%)'); |
} |
function _invalidState($type, $value) |
{ |
$states = array('stable', 'beta', 'alpha', 'devel'); |
if ($type != 'api') { |
$states[] = 'snapshot'; |
} |
if (strtolower($value) == 'rc') { |
$this->_stack->push(__FUNCTION__, 'error', |
array('version' => $this->_packageInfo['version']['release']), |
'RC is not a state, it is a version postfix, try %version%RC1, stability beta'); |
} |
$this->_stack->push(__FUNCTION__, 'error', array('type' => $type, 'value' => $value, |
'types' => $states), |
'Stability type <%type%> is not a valid stability (%value%), must be one of ' . |
'%types%'); |
} |
function _invalidTask($task, $ret, $file) |
{ |
switch ($ret[0]) { |
case PEAR_TASK_ERROR_MISSING_ATTRIB : |
$info = array('attrib' => $ret[1], 'task' => $task, 'file' => $file); |
$msg = 'task <%task%> is missing attribute "%attrib%" in file %file%'; |
break; |
case PEAR_TASK_ERROR_NOATTRIBS : |
$info = array('task' => $task, 'file' => $file); |
$msg = 'task <%task%> has no attributes in file %file%'; |
break; |
case PEAR_TASK_ERROR_WRONG_ATTRIB_VALUE : |
$info = array('attrib' => $ret[1], 'values' => $ret[3], |
'was' => $ret[2], 'task' => $task, 'file' => $file); |
$msg = 'task <%task%> attribute "%attrib%" has the wrong value "%was%" '. |
'in file %file%, expecting one of "%values%"'; |
break; |
case PEAR_TASK_ERROR_INVALID : |
$info = array('reason' => $ret[1], 'task' => $task, 'file' => $file); |
$msg = 'task <%task%> in file %file% is invalid because of "%reason%"'; |
break; |
} |
$this->_stack->push(__FUNCTION__, 'error', $info, $msg); |
} |
function _unknownTask($task, $file) |
{ |
$this->_stack->push(__FUNCTION__, 'error', array('task' => $task, 'file' => $file), |
'Unknown task "%task%" passed in file <file name="%file%">'); |
} |
function _subpackageCannotProvideExtension($name) |
{ |
$this->_stack->push(__FUNCTION__, 'error', array('name' => $name), |
'Subpackage dependency "%name%" cannot use <providesextension>, ' . |
'only package dependencies can use this tag'); |
} |
function _subpackagesCannotConflict($name) |
{ |
$this->_stack->push(__FUNCTION__, 'error', array('name' => $name), |
'Subpackage dependency "%name%" cannot use <conflicts/>, ' . |
'only package dependencies can use this tag'); |
} |
function _cannotProvideExtension($release) |
{ |
$this->_stack->push(__FUNCTION__, 'error', array('release' => $release), |
'<%release%> packages cannot use <providesextension>, only extbinrelease, extsrcrelease, zendextsrcrelease, and zendextbinrelease can provide a PHP extension'); |
} |
function _mustProvideExtension($release) |
{ |
$this->_stack->push(__FUNCTION__, 'error', array('release' => $release), |
'<%release%> packages must use <providesextension> to indicate which PHP extension is provided'); |
} |
function _cannotHaveSrcpackage($release) |
{ |
$this->_stack->push(__FUNCTION__, 'error', array('release' => $release), |
'<%release%> packages cannot specify a source code package, only extension binaries may use the <srcpackage> tag'); |
} |
function _mustSrcPackage($release) |
{ |
$this->_stack->push(__FUNCTION__, 'error', array('release' => $release), |
'<extbinrelease>/<zendextbinrelease> packages must specify a source code package with <srcpackage>'); |
} |
function _mustSrcuri($release) |
{ |
$this->_stack->push(__FUNCTION__, 'error', array('release' => $release), |
'<extbinrelease>/<zendextbinrelease> packages must specify a source code package with <srcuri>'); |
} |
function _uriDepsCannotHaveVersioning($type) |
{ |
$this->_stack->push(__FUNCTION__, 'error', array('type' => $type), |
'%type%: dependencies with a <uri> tag cannot have any versioning information'); |
} |
function _conflictingDepsCannotHaveVersioning($type) |
{ |
$this->_stack->push(__FUNCTION__, 'error', array('type' => $type), |
'%type%: conflicting dependencies cannot have versioning info, use <exclude> to ' . |
'exclude specific versions of a dependency'); |
} |
function _DepchannelCannotBeUri($type) |
{ |
$this->_stack->push(__FUNCTION__, 'error', array('type' => $type), |
'%type%: channel cannot be __uri, this is a pseudo-channel reserved for uri ' . |
'dependencies only'); |
} |
function _bundledPackagesMustBeFilename() |
{ |
$this->_stack->push(__FUNCTION__, 'error', array(), |
'<bundledpackage> tags must contain only the filename of a package release ' . |
'in the bundle'); |
} |
function _binaryPackageMustBePackagename() |
{ |
$this->_stack->push(__FUNCTION__, 'error', array(), |
'<binarypackage> tags must contain the name of a package that is ' . |
'a compiled version of this extsrc/zendextsrc package'); |
} |
function _fileNotFound($file) |
{ |
$this->_stack->push(__FUNCTION__, 'error', array('file' => $file), |
'File "%file%" in package.xml does not exist'); |
} |
function _notInContents($file, $tag) |
{ |
$this->_stack->push(__FUNCTION__, 'error', array('file' => $file, 'tag' => $tag), |
'<%tag% name="%file%"> is invalid, file is not in <contents>'); |
} |
function _cannotValidateNoPathSet() |
{ |
$this->_stack->push(__FUNCTION__, 'error', array(), |
'Cannot validate files, no path to package file is set (use setPackageFile())'); |
} |
function _usesroletaskMustHaveChannelOrUri($role, $tag) |
{ |
$this->_stack->push(__FUNCTION__, 'error', array('role' => $role, 'tag' => $tag), |
'<%tag%> for role "%role%" must contain either <uri>, or <channel> and <package>'); |
} |
function _usesroletaskMustHavePackage($role, $tag) |
{ |
$this->_stack->push(__FUNCTION__, 'error', array('role' => $role, 'tag' => $tag), |
'<%tag%> for role "%role%" must contain <package>'); |
} |
function _usesroletaskMustHaveRoleTask($tag, $type) |
{ |
$this->_stack->push(__FUNCTION__, 'error', array('tag' => $tag, 'type' => $type), |
'<%tag%> must contain <%type%> defining the %type% to be used'); |
} |
function _cannotConflictWithAllOs($type) |
{ |
$this->_stack->push(__FUNCTION__, 'error', array('tag' => $tag), |
'%tag% cannot conflict with all OSes'); |
} |
function _invalidDepGroupName($name) |
{ |
$this->_stack->push(__FUNCTION__, 'error', array('name' => $name), |
'Invalid dependency group name "%name%"'); |
} |
function _multipleToplevelDirNotAllowed() |
{ |
$this->_stack->push(__FUNCTION__, 'error', array(), |
'Multiple top-level <dir> tags are not allowed. Enclose them ' . |
'in a <dir name="/">'); |
} |
function _multipleInstallAs($file) |
{ |
$this->_stack->push(__FUNCTION__, 'error', array('file' => $file), |
'Only one <install> tag is allowed for file "%file%"'); |
} |
function _ignoreAndInstallAs($file) |
{ |
$this->_stack->push(__FUNCTION__, 'error', array('file' => $file), |
'Cannot have both <ignore> and <install> tags for file "%file%"'); |
} |
function _analyzeBundledPackages() |
{ |
if (!$this->_isValid) { |
return false; |
} |
if (!$this->_pf->getPackageType() == 'bundle') { |
return false; |
} |
if (!isset($this->_pf->_packageFile)) { |
return false; |
} |
$dir_prefix = dirname($this->_pf->_packageFile); |
$common = new PEAR_Common; |
$log = isset($this->_pf->_logger) ? array(&$this->_pf->_logger, 'log') : |
array($common, 'log'); |
$info = $this->_pf->getContents(); |
$info = $info['bundledpackage']; |
if (!is_array($info)) { |
$info = array($info); |
} |
$pkg = new PEAR_PackageFile($this->_pf->_config); |
foreach ($info as $package) { |
if (!file_exists($dir_prefix . DIRECTORY_SEPARATOR . $package)) { |
$this->_fileNotFound($dir_prefix . DIRECTORY_SEPARATOR . $package); |
$this->_isValid = 0; |
continue; |
} |
call_user_func_array($log, array(1, "Analyzing bundled package $package")); |
PEAR::pushErrorHandling(PEAR_ERROR_RETURN); |
$ret = $pkg->fromAnyFile($dir_prefix . DIRECTORY_SEPARATOR . $package, |
PEAR_VALIDATE_NORMAL); |
PEAR::popErrorHandling(); |
if (PEAR::isError($ret)) { |
call_user_func_array($log, array(0, "ERROR: package $package is not a valid " . |
'package')); |
$inf = $ret->getUserInfo(); |
if (is_array($inf)) { |
foreach ($inf as $err) { |
call_user_func_array($log, array(1, $err['message'])); |
} |
} |
return false; |
} |
} |
return true; |
} |
function _analyzePhpFiles() |
{ |
if (!$this->_isValid) { |
return false; |
} |
if (!isset($this->_pf->_packageFile)) { |
$this->_cannotValidateNoPathSet(); |
return false; |
} |
$dir_prefix = dirname($this->_pf->_packageFile); |
$common = new PEAR_Common; |
$log = isset($this->_pf->_logger) ? array(&$this->_pf->_logger, 'log') : |
array(&$common, 'log'); |
$info = $this->_pf->getContents(); |
if (!$info || !isset($info['dir']['file'])) { |
$this->_tagCannotBeEmpty('contents><dir'); |
return false; |
} |
$info = $info['dir']['file']; |
if (isset($info['attribs'])) { |
$info = array($info); |
} |
$provides = array(); |
foreach ($info as $fa) { |
$fa = $fa['attribs']; |
$file = $fa['name']; |
if (!file_exists($dir_prefix . DIRECTORY_SEPARATOR . $file)) { |
$this->_fileNotFound($dir_prefix . DIRECTORY_SEPARATOR . $file); |
$this->_isValid = 0; |
continue; |
} |
if (in_array($fa['role'], PEAR_Installer_Role::getPhpRoles()) && $dir_prefix) { |
call_user_func_array($log, array(1, "Analyzing $file")); |
$srcinfo = $this->analyzeSourceCode($dir_prefix . DIRECTORY_SEPARATOR . $file); |
if ($srcinfo) { |
$provides = array_merge($provides, $this->_buildProvidesArray($srcinfo)); |
} |
} |
} |
$this->_packageName = $pn = $this->_pf->getPackage(); |
$pnl = strlen($pn); |
foreach ($provides as $key => $what) { |
if (isset($what['explicit']) || !$what) { |
// skip conformance checks if the provides entry is |
// specified in the package.xml file |
continue; |
} |
extract($what); |
if ($type == 'class') { |
if (!strncasecmp($name, $pn, $pnl)) { |
continue; |
} |
$this->_stack->push(__FUNCTION__, 'warning', |
array('file' => $file, 'type' => $type, 'name' => $name, 'package' => $pn), |
'in %file%: %type% "%name%" not prefixed with package name "%package%"'); |
} elseif ($type == 'function') { |
if (strstr($name, '::') || !strncasecmp($name, $pn, $pnl)) { |
continue; |
} |
$this->_stack->push(__FUNCTION__, 'warning', |
array('file' => $file, 'type' => $type, 'name' => $name, 'package' => $pn), |
'in %file%: %type% "%name%" not prefixed with package name "%package%"'); |
} |
} |
return $this->_isValid; |
} |
/** |
* Analyze the source code of the given PHP file |
* |
* @param string Filename of the PHP file |
* @param boolean whether to analyze $file as the file contents |
* @return mixed |
*/ |
function analyzeSourceCode($file, $string = false) |
{ |
if (!function_exists("token_get_all")) { |
$this->_stack->push(__FUNCTION__, 'error', array('file' => $file), |
'Parser error: token_get_all() function must exist to analyze source code, PHP may have been compiled with --disable-tokenizer'); |
return false; |
} |
if (!defined('T_DOC_COMMENT')) { |
define('T_DOC_COMMENT', T_COMMENT); |
} |
if (!defined('T_INTERFACE')) { |
define('T_INTERFACE', -1); |
} |
if (!defined('T_IMPLEMENTS')) { |
define('T_IMPLEMENTS', -1); |
} |
if ($string) { |
$contents = $file; |
} else { |
if (!$fp = @fopen($file, "r")) { |
return false; |
} |
fclose($fp); |
$contents = file_get_contents($file); |
} |
// Silence this function so we can catch PHP Warnings and show our own custom message |
$tokens = @token_get_all($contents); |
if (isset($php_errormsg)) { |
if (isset($this->_stack)) { |
$pn = $this->_pf->getPackage(); |
$this->_stack->push(__FUNCTION__, 'warning', |
array('file' => $file, 'package' => $pn), |
'in %file%: Could not process file for unknown reasons,' . |
' possibly a PHP parse error in %file% from %package%'); |
} |
} |
/* |
for ($i = 0; $i < sizeof($tokens); $i++) { |
@list($token, $data) = $tokens[$i]; |
if (is_string($token)) { |
var_dump($token); |
} else { |
print token_name($token) . ' '; |
var_dump(rtrim($data)); |
} |
} |
*/ |
$look_for = 0; |
$paren_level = 0; |
$bracket_level = 0; |
$brace_level = 0; |
$lastphpdoc = ''; |
$current_class = ''; |
$current_interface = ''; |
$current_class_level = -1; |
$current_function = ''; |
$current_function_level = -1; |
$declared_classes = array(); |
$declared_interfaces = array(); |
$declared_functions = array(); |
$declared_methods = array(); |
$used_classes = array(); |
$used_functions = array(); |
$extends = array(); |
$implements = array(); |
$nodeps = array(); |
$inquote = false; |
$interface = false; |
for ($i = 0; $i < sizeof($tokens); $i++) { |
if (is_array($tokens[$i])) { |
list($token, $data) = $tokens[$i]; |
} else { |
$token = $tokens[$i]; |
$data = ''; |
} |
if ($inquote) { |
if ($token != '"' && $token != T_END_HEREDOC) { |
continue; |
} else { |
$inquote = false; |
continue; |
} |
} |
switch ($token) { |
case T_WHITESPACE : |
continue; |
case ';': |
if ($interface) { |
$current_function = ''; |
$current_function_level = -1; |
} |
break; |
case '"': |
case T_START_HEREDOC: |
$inquote = true; |
break; |
case T_CURLY_OPEN: |
case T_DOLLAR_OPEN_CURLY_BRACES: |
case '{': $brace_level++; continue 2; |
case '}': |
$brace_level--; |
if ($current_class_level == $brace_level) { |
$current_class = ''; |
$current_class_level = -1; |
} |
if ($current_function_level == $brace_level) { |
$current_function = ''; |
$current_function_level = -1; |
} |
continue 2; |
case '[': $bracket_level++; continue 2; |
case ']': $bracket_level--; continue 2; |
case '(': $paren_level++; continue 2; |
case ')': $paren_level--; continue 2; |
case T_INTERFACE: |
$interface = true; |
case T_CLASS: |
if (($current_class_level != -1) || ($current_function_level != -1)) { |
if (isset($this->_stack)) { |
$this->_stack->push(__FUNCTION__, 'error', array('file' => $file), |
'Parser error: invalid PHP found in file "%file%"'); |
} else { |
PEAR::raiseError("Parser error: invalid PHP found in file \"$file\"", |
PEAR_COMMON_ERROR_INVALIDPHP); |
} |
return false; |
} |
case T_FUNCTION: |
case T_NEW: |
case T_EXTENDS: |
case T_IMPLEMENTS: |
$look_for = $token; |
continue 2; |
case T_STRING: |
if ($look_for == T_CLASS) { |
$current_class = $data; |
$current_class_level = $brace_level; |
$declared_classes[] = $current_class; |
} elseif ($look_for == T_INTERFACE) { |
$current_interface = $data; |
$current_class_level = $brace_level; |
$declared_interfaces[] = $current_interface; |
} elseif ($look_for == T_IMPLEMENTS) { |
$implements[$current_class] = $data; |
} elseif ($look_for == T_EXTENDS) { |
$extends[$current_class] = $data; |
} elseif ($look_for == T_FUNCTION) { |
if ($current_class) { |
$current_function = "$current_class::$data"; |
$declared_methods[$current_class][] = $data; |
} elseif ($current_interface) { |
$current_function = "$current_interface::$data"; |
$declared_methods[$current_interface][] = $data; |
} else { |
$current_function = $data; |
$declared_functions[] = $current_function; |
} |
$current_function_level = $brace_level; |
$m = array(); |
} elseif ($look_for == T_NEW) { |
$used_classes[$data] = true; |
} |
$look_for = 0; |
continue 2; |
case T_VARIABLE: |
$look_for = 0; |
continue 2; |
case T_DOC_COMMENT: |
case T_COMMENT: |
if (preg_match('!^/\*\*\s!', $data)) { |
$lastphpdoc = $data; |
if (preg_match_all('/@nodep\s+(\S+)/', $lastphpdoc, $m)) { |
$nodeps = array_merge($nodeps, $m[1]); |
} |
} |
continue 2; |
case T_DOUBLE_COLON: |
$token = $tokens[$i - 1][0]; |
if (!($token == T_WHITESPACE || $token == T_STRING || $token == T_STATIC || $token == T_VARIABLE)) { |
if (isset($this->_stack)) { |
$this->_stack->push(__FUNCTION__, 'warning', array('file' => $file), |
'Parser error: invalid PHP found in file "%file%"'); |
} else { |
PEAR::raiseError("Parser error: invalid PHP found in file \"$file\"", |
PEAR_COMMON_ERROR_INVALIDPHP); |
} |
return false; |
} |
$class = $tokens[$i - 1][1]; |
if (strtolower($class) != 'parent') { |
$used_classes[$class] = true; |
} |
continue 2; |
} |
} |
return array( |
"source_file" => $file, |
"declared_classes" => $declared_classes, |
"declared_interfaces" => $declared_interfaces, |
"declared_methods" => $declared_methods, |
"declared_functions" => $declared_functions, |
"used_classes" => array_diff(array_keys($used_classes), $nodeps), |
"inheritance" => $extends, |
"implements" => $implements, |
); |
} |
/** |
* Build a "provides" array from data returned by |
* analyzeSourceCode(). The format of the built array is like |
* this: |
* |
* array( |
* 'class;MyClass' => 'array('type' => 'class', 'name' => 'MyClass'), |
* ... |
* ) |
* |
* |
* @param array $srcinfo array with information about a source file |
* as returned by the analyzeSourceCode() method. |
* |
* @return void |
* |
* @access private |
* |
*/ |
function _buildProvidesArray($srcinfo) |
{ |
if (!$this->_isValid) { |
return array(); |
} |
$providesret = array(); |
$file = basename($srcinfo['source_file']); |
$pn = isset($this->_pf) ? $this->_pf->getPackage() : ''; |
$pnl = strlen($pn); |
foreach ($srcinfo['declared_classes'] as $class) { |
$key = "class;$class"; |
if (isset($providesret[$key])) { |
continue; |
} |
$providesret[$key] = |
array('file'=> $file, 'type' => 'class', 'name' => $class); |
if (isset($srcinfo['inheritance'][$class])) { |
$providesret[$key]['extends'] = |
$srcinfo['inheritance'][$class]; |
} |
} |
foreach ($srcinfo['declared_methods'] as $class => $methods) { |
foreach ($methods as $method) { |
$function = "$class::$method"; |
$key = "function;$function"; |
if ($method{0} == '_' || !strcasecmp($method, $class) || |
isset($providesret[$key])) { |
continue; |
} |
$providesret[$key] = |
array('file'=> $file, 'type' => 'function', 'name' => $function); |
} |
} |
foreach ($srcinfo['declared_functions'] as $function) { |
$key = "function;$function"; |
if ($function{0} == '_' || isset($providesret[$key])) { |
continue; |
} |
if (!strstr($function, '::') && strncasecmp($function, $pn, $pnl)) { |
$warnings[] = "in1 " . $file . ": function \"$function\" not prefixed with package name \"$pn\""; |
} |
$providesret[$key] = |
array('file'=> $file, 'type' => 'function', 'name' => $function); |
} |
return $providesret; |
} |
} |
/branches/v1.3-critias/bibliotheque/pear/PEAR/PackageFile/v2/rw.php |
---|
New file |
0,0 → 1,1603 |
<?php |
/** |
* PEAR_PackageFile_v2, package.xml version 2.0, read/write version |
* |
* PHP versions 4 and 5 |
* |
* @category pear |
* @package PEAR |
* @author Greg Beaver <cellog@php.net> |
* @copyright 1997-2009 The Authors |
* @license http://opensource.org/licenses/bsd-license.php New BSD License |
* @link http://pear.php.net/package/PEAR |
* @since File available since Release 1.4.0a8 |
*/ |
/** |
* For base class |
*/ |
require_once 'PEAR/PackageFile/v2.php'; |
/** |
* @category pear |
* @package PEAR |
* @author Greg Beaver <cellog@php.net> |
* @copyright 1997-2009 The Authors |
* @license http://opensource.org/licenses/bsd-license.php New BSD License |
* @version Release: 1.10.1 |
* @link http://pear.php.net/package/PEAR |
* @since Class available since Release 1.4.0a8 |
*/ |
class PEAR_PackageFile_v2_rw extends PEAR_PackageFile_v2 |
{ |
/** |
* @param string Extension name |
* @return bool success of operation |
*/ |
function setProvidesExtension($extension) |
{ |
if (in_array($this->getPackageType(), |
array('extsrc', 'extbin', 'zendextsrc', 'zendextbin'))) { |
if (!isset($this->_packageInfo['providesextension'])) { |
// ensure that the channel tag is set up in the right location |
$this->_packageInfo = $this->_insertBefore($this->_packageInfo, |
array('usesrole', 'usestask', 'srcpackage', 'srcuri', 'phprelease', |
'extsrcrelease', 'extbinrelease', 'zendextsrcrelease', 'zendextbinrelease', |
'bundle', 'changelog'), |
$extension, 'providesextension'); |
} |
$this->_packageInfo['providesextension'] = $extension; |
return true; |
} |
return false; |
} |
function setPackage($package) |
{ |
$this->_isValid = 0; |
if (!isset($this->_packageInfo['attribs'])) { |
$this->_packageInfo = array_merge(array('attribs' => array( |
'version' => '2.0', |
'xmlns' => 'http://pear.php.net/dtd/package-2.0', |
'xmlns:tasks' => 'http://pear.php.net/dtd/tasks-1.0', |
'xmlns:xsi' => 'http://www.w3.org/2001/XMLSchema-instance', |
'xsi:schemaLocation' => 'http://pear.php.net/dtd/tasks-1.0 |
http://pear.php.net/dtd/tasks-1.0.xsd |
http://pear.php.net/dtd/package-2.0 |
http://pear.php.net/dtd/package-2.0.xsd', |
)), $this->_packageInfo); |
} |
if (!isset($this->_packageInfo['name'])) { |
return $this->_packageInfo = array_merge(array('name' => $package), |
$this->_packageInfo); |
} |
$this->_packageInfo['name'] = $package; |
} |
/** |
* set this as a package.xml version 2.1 |
* @access private |
*/ |
function _setPackageVersion2_1() |
{ |
$info = array( |
'version' => '2.1', |
'xmlns' => 'http://pear.php.net/dtd/package-2.1', |
'xmlns:tasks' => 'http://pear.php.net/dtd/tasks-1.0', |
'xmlns:xsi' => 'http://www.w3.org/2001/XMLSchema-instance', |
'xsi:schemaLocation' => 'http://pear.php.net/dtd/tasks-1.0 |
http://pear.php.net/dtd/tasks-1.0.xsd |
http://pear.php.net/dtd/package-2.1 |
http://pear.php.net/dtd/package-2.1.xsd', |
); |
if (!isset($this->_packageInfo['attribs'])) { |
$this->_packageInfo = array_merge(array('attribs' => $info), $this->_packageInfo); |
} else { |
$this->_packageInfo['attribs'] = $info; |
} |
} |
function setUri($uri) |
{ |
unset($this->_packageInfo['channel']); |
$this->_isValid = 0; |
if (!isset($this->_packageInfo['uri'])) { |
// ensure that the uri tag is set up in the right location |
$this->_packageInfo = $this->_insertBefore($this->_packageInfo, |
array('extends', 'summary', 'description', 'lead', |
'developer', 'contributor', 'helper', 'date', 'time', 'version', |
'stability', 'license', 'notes', 'contents', 'compatible', |
'dependencies', 'providesextension', 'usesrole', 'usestask', 'srcpackage', 'srcuri', |
'phprelease', 'extsrcrelease', 'zendextsrcrelease', 'zendextbinrelease', |
'extbinrelease', 'bundle', 'changelog'), $uri, 'uri'); |
} |
$this->_packageInfo['uri'] = $uri; |
} |
function setChannel($channel) |
{ |
unset($this->_packageInfo['uri']); |
$this->_isValid = 0; |
if (!isset($this->_packageInfo['channel'])) { |
// ensure that the channel tag is set up in the right location |
$this->_packageInfo = $this->_insertBefore($this->_packageInfo, |
array('extends', 'summary', 'description', 'lead', |
'developer', 'contributor', 'helper', 'date', 'time', 'version', |
'stability', 'license', 'notes', 'contents', 'compatible', |
'dependencies', 'providesextension', 'usesrole', 'usestask', 'srcpackage', 'srcuri', |
'phprelease', 'extsrcrelease', 'zendextsrcrelease', 'zendextbinrelease', |
'extbinrelease', 'bundle', 'changelog'), $channel, 'channel'); |
} |
$this->_packageInfo['channel'] = $channel; |
} |
function setExtends($extends) |
{ |
$this->_isValid = 0; |
if (!isset($this->_packageInfo['extends'])) { |
// ensure that the extends tag is set up in the right location |
$this->_packageInfo = $this->_insertBefore($this->_packageInfo, |
array('summary', 'description', 'lead', |
'developer', 'contributor', 'helper', 'date', 'time', 'version', |
'stability', 'license', 'notes', 'contents', 'compatible', |
'dependencies', 'providesextension', 'usesrole', 'usestask', 'srcpackage', 'srcuri', |
'phprelease', 'extsrcrelease', 'zendextsrcrelease', 'zendextbinrelease', |
'extbinrelease', 'bundle', 'changelog'), $extends, 'extends'); |
} |
$this->_packageInfo['extends'] = $extends; |
} |
function setSummary($summary) |
{ |
$this->_isValid = 0; |
if (!isset($this->_packageInfo['summary'])) { |
// ensure that the summary tag is set up in the right location |
$this->_packageInfo = $this->_insertBefore($this->_packageInfo, |
array('description', 'lead', |
'developer', 'contributor', 'helper', 'date', 'time', 'version', |
'stability', 'license', 'notes', 'contents', 'compatible', |
'dependencies', 'providesextension', 'usesrole', 'usestask', 'srcpackage', 'srcuri', |
'phprelease', 'extsrcrelease', 'zendextsrcrelease', 'zendextbinrelease', |
'extbinrelease', 'bundle', 'changelog'), $summary, 'summary'); |
} |
$this->_packageInfo['summary'] = $summary; |
} |
function setDescription($desc) |
{ |
$this->_isValid = 0; |
if (!isset($this->_packageInfo['description'])) { |
// ensure that the description tag is set up in the right location |
$this->_packageInfo = $this->_insertBefore($this->_packageInfo, |
array('lead', |
'developer', 'contributor', 'helper', 'date', 'time', 'version', |
'stability', 'license', 'notes', 'contents', 'compatible', |
'dependencies', 'providesextension', 'usesrole', 'usestask', 'srcpackage', 'srcuri', |
'phprelease', 'extsrcrelease', 'zendextsrcrelease', 'zendextbinrelease', |
'extbinrelease', 'bundle', 'changelog'), $desc, 'description'); |
} |
$this->_packageInfo['description'] = $desc; |
} |
/** |
* Adds a new maintainer - no checking of duplicates is performed, use |
* updatemaintainer for that purpose. |
*/ |
function addMaintainer($role, $handle, $name, $email, $active = 'yes') |
{ |
if (!in_array($role, array('lead', 'developer', 'contributor', 'helper'))) { |
return false; |
} |
if (isset($this->_packageInfo[$role])) { |
if (!isset($this->_packageInfo[$role][0])) { |
$this->_packageInfo[$role] = array($this->_packageInfo[$role]); |
} |
$this->_packageInfo[$role][] = |
array( |
'name' => $name, |
'user' => $handle, |
'email' => $email, |
'active' => $active, |
); |
} else { |
$testarr = array('lead', |
'developer', 'contributor', 'helper', 'date', 'time', 'version', |
'stability', 'license', 'notes', 'contents', 'compatible', |
'dependencies', 'providesextension', 'usesrole', 'usestask', |
'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', |
'extbinrelease', 'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog'); |
foreach (array('lead', 'developer', 'contributor', 'helper') as $testrole) { |
array_shift($testarr); |
if ($role == $testrole) { |
break; |
} |
} |
if (!isset($this->_packageInfo[$role])) { |
// ensure that the extends tag is set up in the right location |
$this->_packageInfo = $this->_insertBefore($this->_packageInfo, $testarr, |
array(), $role); |
} |
$this->_packageInfo[$role] = |
array( |
'name' => $name, |
'user' => $handle, |
'email' => $email, |
'active' => $active, |
); |
} |
$this->_isValid = 0; |
} |
function updateMaintainer($newrole, $handle, $name, $email, $active = 'yes') |
{ |
$found = false; |
foreach (array('lead', 'developer', 'contributor', 'helper') as $role) { |
if (!isset($this->_packageInfo[$role])) { |
continue; |
} |
$info = $this->_packageInfo[$role]; |
if (!isset($info[0])) { |
if ($info['user'] == $handle) { |
$found = true; |
break; |
} |
} |
foreach ($info as $i => $maintainer) { |
if (is_array($maintainer) && $maintainer['user'] == $handle) { |
$found = $i; |
break 2; |
} |
} |
} |
if ($found === false) { |
return $this->addMaintainer($newrole, $handle, $name, $email, $active); |
} |
if ($found !== false) { |
if ($found === true) { |
unset($this->_packageInfo[$role]); |
} else { |
unset($this->_packageInfo[$role][$found]); |
$this->_packageInfo[$role] = array_values($this->_packageInfo[$role]); |
} |
} |
$this->addMaintainer($newrole, $handle, $name, $email, $active); |
$this->_isValid = 0; |
} |
function deleteMaintainer($handle) |
{ |
$found = false; |
foreach (array('lead', 'developer', 'contributor', 'helper') as $role) { |
if (!isset($this->_packageInfo[$role])) { |
continue; |
} |
if (!isset($this->_packageInfo[$role][0])) { |
$this->_packageInfo[$role] = array($this->_packageInfo[$role]); |
} |
foreach ($this->_packageInfo[$role] as $i => $maintainer) { |
if ($maintainer['user'] == $handle) { |
$found = $i; |
break; |
} |
} |
if ($found !== false) { |
unset($this->_packageInfo[$role][$found]); |
if (!count($this->_packageInfo[$role]) && $role == 'lead') { |
$this->_isValid = 0; |
} |
if (!count($this->_packageInfo[$role])) { |
unset($this->_packageInfo[$role]); |
return true; |
} |
$this->_packageInfo[$role] = |
array_values($this->_packageInfo[$role]); |
if (count($this->_packageInfo[$role]) == 1) { |
$this->_packageInfo[$role] = $this->_packageInfo[$role][0]; |
} |
return true; |
} |
if (count($this->_packageInfo[$role]) == 1) { |
$this->_packageInfo[$role] = $this->_packageInfo[$role][0]; |
} |
} |
return false; |
} |
function setReleaseVersion($version) |
{ |
if (isset($this->_packageInfo['version']) && |
isset($this->_packageInfo['version']['release'])) { |
unset($this->_packageInfo['version']['release']); |
} |
$this->_packageInfo = $this->_mergeTag($this->_packageInfo, $version, array( |
'version' => array('stability', 'license', 'notes', 'contents', 'compatible', |
'dependencies', 'providesextension', 'usesrole', 'usestask', 'srcpackage', 'srcuri', |
'phprelease', 'extsrcrelease', 'zendextsrcrelease', 'zendextbinrelease', |
'extbinrelease', 'bundle', 'changelog'), |
'release' => array('api'))); |
$this->_isValid = 0; |
} |
function setAPIVersion($version) |
{ |
if (isset($this->_packageInfo['version']) && |
isset($this->_packageInfo['version']['api'])) { |
unset($this->_packageInfo['version']['api']); |
} |
$this->_packageInfo = $this->_mergeTag($this->_packageInfo, $version, array( |
'version' => array('stability', 'license', 'notes', 'contents', 'compatible', |
'dependencies', 'providesextension', 'usesrole', 'usestask', 'srcpackage', 'srcuri', |
'phprelease', 'extsrcrelease', 'zendextsrcrelease', 'zendextbinrelease', |
'extbinrelease', 'bundle', 'changelog'), |
'api' => array())); |
$this->_isValid = 0; |
} |
/** |
* snapshot|devel|alpha|beta|stable |
*/ |
function setReleaseStability($state) |
{ |
if (isset($this->_packageInfo['stability']) && |
isset($this->_packageInfo['stability']['release'])) { |
unset($this->_packageInfo['stability']['release']); |
} |
$this->_packageInfo = $this->_mergeTag($this->_packageInfo, $state, array( |
'stability' => array('license', 'notes', 'contents', 'compatible', |
'dependencies', 'providesextension', 'usesrole', 'usestask', 'srcpackage', 'srcuri', |
'phprelease', 'extsrcrelease', 'zendextsrcrelease', 'zendextbinrelease', |
'extbinrelease', 'bundle', 'changelog'), |
'release' => array('api'))); |
$this->_isValid = 0; |
} |
/** |
* @param devel|alpha|beta|stable |
*/ |
function setAPIStability($state) |
{ |
if (isset($this->_packageInfo['stability']) && |
isset($this->_packageInfo['stability']['api'])) { |
unset($this->_packageInfo['stability']['api']); |
} |
$this->_packageInfo = $this->_mergeTag($this->_packageInfo, $state, array( |
'stability' => array('license', 'notes', 'contents', 'compatible', |
'dependencies', 'providesextension', 'usesrole', 'usestask', 'srcpackage', 'srcuri', |
'phprelease', 'extsrcrelease', 'zendextsrcrelease', 'zendextbinrelease', |
'extbinrelease', 'bundle', 'changelog'), |
'api' => array())); |
$this->_isValid = 0; |
} |
function setLicense($license, $uri = false, $filesource = false) |
{ |
if (!isset($this->_packageInfo['license'])) { |
// ensure that the license tag is set up in the right location |
$this->_packageInfo = $this->_insertBefore($this->_packageInfo, |
array('notes', 'contents', 'compatible', |
'dependencies', 'providesextension', 'usesrole', 'usestask', 'srcpackage', 'srcuri', |
'phprelease', 'extsrcrelease', 'zendextsrcrelease', 'zendextbinrelease', |
'extbinrelease', 'bundle', 'changelog'), 0, 'license'); |
} |
if ($uri || $filesource) { |
$attribs = array(); |
if ($uri) { |
$attribs['uri'] = $uri; |
} |
$uri = true; // for test below |
if ($filesource) { |
$attribs['filesource'] = $filesource; |
} |
} |
$license = $uri ? array('attribs' => $attribs, '_content' => $license) : $license; |
$this->_packageInfo['license'] = $license; |
$this->_isValid = 0; |
} |
function setNotes($notes) |
{ |
$this->_isValid = 0; |
if (!isset($this->_packageInfo['notes'])) { |
// ensure that the notes tag is set up in the right location |
$this->_packageInfo = $this->_insertBefore($this->_packageInfo, |
array('contents', 'compatible', |
'dependencies', 'providesextension', 'usesrole', 'usestask', 'srcpackage', 'srcuri', |
'phprelease', 'extsrcrelease', 'zendextsrcrelease', 'zendextbinrelease', |
'extbinrelease', 'bundle', 'changelog'), $notes, 'notes'); |
} |
$this->_packageInfo['notes'] = $notes; |
} |
/** |
* This is only used at install-time, after all serialization |
* is over. |
* @param string file name |
* @param string installed path |
*/ |
function setInstalledAs($file, $path) |
{ |
if ($path) { |
return $this->_packageInfo['filelist'][$file]['installed_as'] = $path; |
} |
unset($this->_packageInfo['filelist'][$file]['installed_as']); |
} |
/** |
* This is only used at install-time, after all serialization |
* is over. |
*/ |
function installedFile($file, $atts) |
{ |
if (isset($this->_packageInfo['filelist'][$file])) { |
$this->_packageInfo['filelist'][$file] = |
array_merge($this->_packageInfo['filelist'][$file], $atts['attribs']); |
} else { |
$this->_packageInfo['filelist'][$file] = $atts['attribs']; |
} |
} |
/** |
* Reset the listing of package contents |
* @param string base installation dir for the whole package, if any |
*/ |
function clearContents($baseinstall = false) |
{ |
$this->_filesValid = false; |
$this->_isValid = 0; |
if (!isset($this->_packageInfo['contents'])) { |
$this->_packageInfo = $this->_insertBefore($this->_packageInfo, |
array('compatible', |
'dependencies', 'providesextension', 'usesrole', 'usestask', |
'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', |
'extbinrelease', 'zendextsrcrelease', 'zendextbinrelease', |
'bundle', 'changelog'), array(), 'contents'); |
} |
if ($this->getPackageType() != 'bundle') { |
$this->_packageInfo['contents'] = |
array('dir' => array('attribs' => array('name' => '/'))); |
if ($baseinstall) { |
$this->_packageInfo['contents']['dir']['attribs']['baseinstalldir'] = $baseinstall; |
} |
} else { |
$this->_packageInfo['contents'] = array('bundledpackage' => array()); |
} |
} |
/** |
* @param string relative path of the bundled package. |
*/ |
function addBundledPackage($path) |
{ |
if ($this->getPackageType() != 'bundle') { |
return false; |
} |
$this->_filesValid = false; |
$this->_isValid = 0; |
$this->_packageInfo = $this->_mergeTag($this->_packageInfo, $path, array( |
'contents' => array('compatible', 'dependencies', 'providesextension', |
'usesrole', 'usestask', 'srcpackage', 'srcuri', 'phprelease', |
'extsrcrelease', 'extbinrelease', 'zendextsrcrelease', 'zendextbinrelease', |
'bundle', 'changelog'), |
'bundledpackage' => array())); |
} |
/** |
* @param string file name |
* @param PEAR_Task_Common a read/write task |
*/ |
function addTaskToFile($filename, $task) |
{ |
if (!method_exists($task, 'getXml')) { |
return false; |
} |
if (!method_exists($task, 'getName')) { |
return false; |
} |
if (!method_exists($task, 'validate')) { |
return false; |
} |
if (!$task->validate()) { |
return false; |
} |
if (!isset($this->_packageInfo['contents']['dir']['file'])) { |
return false; |
} |
$this->getTasksNs(); // discover the tasks namespace if not done already |
$files = $this->_packageInfo['contents']['dir']['file']; |
if (!isset($files[0])) { |
$files = array($files); |
$ind = false; |
} else { |
$ind = true; |
} |
foreach ($files as $i => $file) { |
if (isset($file['attribs'])) { |
if ($file['attribs']['name'] == $filename) { |
if ($ind) { |
$t = isset($this->_packageInfo['contents']['dir']['file'][$i] |
['attribs'][$this->_tasksNs . |
':' . $task->getName()]) ? |
$this->_packageInfo['contents']['dir']['file'][$i] |
['attribs'][$this->_tasksNs . |
':' . $task->getName()] : false; |
if ($t && !isset($t[0])) { |
$this->_packageInfo['contents']['dir']['file'][$i] |
[$this->_tasksNs . ':' . $task->getName()] = array($t); |
} |
$this->_packageInfo['contents']['dir']['file'][$i][$this->_tasksNs . |
':' . $task->getName()][] = $task->getXml(); |
} else { |
$t = isset($this->_packageInfo['contents']['dir']['file'] |
['attribs'][$this->_tasksNs . |
':' . $task->getName()]) ? $this->_packageInfo['contents']['dir']['file'] |
['attribs'][$this->_tasksNs . |
':' . $task->getName()] : false; |
if ($t && !isset($t[0])) { |
$this->_packageInfo['contents']['dir']['file'] |
[$this->_tasksNs . ':' . $task->getName()] = array($t); |
} |
$this->_packageInfo['contents']['dir']['file'][$this->_tasksNs . |
':' . $task->getName()][] = $task->getXml(); |
} |
return true; |
} |
} |
} |
return false; |
} |
/** |
* @param string path to the file |
* @param string filename |
* @param array extra attributes |
*/ |
function addFile($dir, $file, $attrs) |
{ |
if ($this->getPackageType() == 'bundle') { |
return false; |
} |
$this->_filesValid = false; |
$this->_isValid = 0; |
$dir = preg_replace(array('!\\\\+!', '!/+!'), array('/', '/'), $dir); |
if ($dir == '/' || $dir == '') { |
$dir = ''; |
} else { |
$dir .= '/'; |
} |
$attrs['name'] = $dir . $file; |
if (!isset($this->_packageInfo['contents'])) { |
// ensure that the contents tag is set up |
$this->_packageInfo = $this->_insertBefore($this->_packageInfo, |
array('compatible', 'dependencies', 'providesextension', 'usesrole', 'usestask', |
'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', |
'extbinrelease', 'zendextsrcrelease', 'zendextbinrelease', |
'bundle', 'changelog'), array(), 'contents'); |
} |
if (isset($this->_packageInfo['contents']['dir']['file'])) { |
if (!isset($this->_packageInfo['contents']['dir']['file'][0])) { |
$this->_packageInfo['contents']['dir']['file'] = |
array($this->_packageInfo['contents']['dir']['file']); |
} |
$this->_packageInfo['contents']['dir']['file'][]['attribs'] = $attrs; |
} else { |
$this->_packageInfo['contents']['dir']['file']['attribs'] = $attrs; |
} |
} |
/** |
* @param string Dependent package name |
* @param string Dependent package's channel name |
* @param string minimum version of specified package that this release is guaranteed to be |
* compatible with |
* @param string maximum version of specified package that this release is guaranteed to be |
* compatible with |
* @param string versions of specified package that this release is not compatible with |
*/ |
function addCompatiblePackage($name, $channel, $min, $max, $exclude = false) |
{ |
$this->_isValid = 0; |
$set = array( |
'name' => $name, |
'channel' => $channel, |
'min' => $min, |
'max' => $max, |
); |
if ($exclude) { |
$set['exclude'] = $exclude; |
} |
$this->_isValid = 0; |
$this->_packageInfo = $this->_mergeTag($this->_packageInfo, $set, array( |
'compatible' => array('dependencies', 'providesextension', 'usesrole', 'usestask', |
'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease', |
'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog') |
)); |
} |
/** |
* Removes the <usesrole> tag entirely |
*/ |
function resetUsesrole() |
{ |
if (isset($this->_packageInfo['usesrole'])) { |
unset($this->_packageInfo['usesrole']); |
} |
} |
/** |
* @param string |
* @param string package name or uri |
* @param string channel name if non-uri |
*/ |
function addUsesrole($role, $packageOrUri, $channel = false) { |
$set = array('role' => $role); |
if ($channel) { |
$set['package'] = $packageOrUri; |
$set['channel'] = $channel; |
} else { |
$set['uri'] = $packageOrUri; |
} |
$this->_isValid = 0; |
$this->_packageInfo = $this->_mergeTag($this->_packageInfo, $set, array( |
'usesrole' => array('usestask', 'srcpackage', 'srcuri', |
'phprelease', 'extsrcrelease', 'extbinrelease', |
'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog') |
)); |
} |
/** |
* Removes the <usestask> tag entirely |
*/ |
function resetUsestask() |
{ |
if (isset($this->_packageInfo['usestask'])) { |
unset($this->_packageInfo['usestask']); |
} |
} |
/** |
* @param string |
* @param string package name or uri |
* @param string channel name if non-uri |
*/ |
function addUsestask($task, $packageOrUri, $channel = false) { |
$set = array('task' => $task); |
if ($channel) { |
$set['package'] = $packageOrUri; |
$set['channel'] = $channel; |
} else { |
$set['uri'] = $packageOrUri; |
} |
$this->_isValid = 0; |
$this->_packageInfo = $this->_mergeTag($this->_packageInfo, $set, array( |
'usestask' => array('srcpackage', 'srcuri', |
'phprelease', 'extsrcrelease', 'extbinrelease', |
'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog') |
)); |
} |
/** |
* Remove all compatible tags |
*/ |
function clearCompatible() |
{ |
unset($this->_packageInfo['compatible']); |
} |
/** |
* Reset dependencies prior to adding new ones |
*/ |
function clearDeps() |
{ |
if (!isset($this->_packageInfo['dependencies'])) { |
$this->_packageInfo = $this->_mergeTag($this->_packageInfo, array(), |
array( |
'dependencies' => array('providesextension', 'usesrole', 'usestask', |
'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease', |
'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog'))); |
} |
$this->_packageInfo['dependencies'] = array(); |
} |
/** |
* @param string minimum PHP version allowed |
* @param string maximum PHP version allowed |
* @param array $exclude incompatible PHP versions |
*/ |
function setPhpDep($min, $max = false, $exclude = false) |
{ |
$this->_isValid = 0; |
$dep = |
array( |
'min' => $min, |
); |
if ($max) { |
$dep['max'] = $max; |
} |
if ($exclude) { |
if (count($exclude) == 1) { |
$exclude = $exclude[0]; |
} |
$dep['exclude'] = $exclude; |
} |
if (isset($this->_packageInfo['dependencies']['required']['php'])) { |
$this->_stack->push(__FUNCTION__, 'warning', array('dep' => |
$this->_packageInfo['dependencies']['required']['php']), |
'warning: PHP dependency already exists, overwriting'); |
unset($this->_packageInfo['dependencies']['required']['php']); |
} |
$this->_packageInfo = $this->_mergeTag($this->_packageInfo, $dep, |
array( |
'dependencies' => array('providesextension', 'usesrole', 'usestask', |
'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease', |
'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog'), |
'required' => array('optional', 'group'), |
'php' => array('pearinstaller', 'package', 'subpackage', 'extension', 'os', 'arch') |
)); |
return true; |
} |
/** |
* @param string minimum allowed PEAR installer version |
* @param string maximum allowed PEAR installer version |
* @param string recommended PEAR installer version |
* @param array incompatible version of the PEAR installer |
*/ |
function setPearinstallerDep($min, $max = false, $recommended = false, $exclude = false) |
{ |
$this->_isValid = 0; |
$dep = |
array( |
'min' => $min, |
); |
if ($max) { |
$dep['max'] = $max; |
} |
if ($recommended) { |
$dep['recommended'] = $recommended; |
} |
if ($exclude) { |
if (count($exclude) == 1) { |
$exclude = $exclude[0]; |
} |
$dep['exclude'] = $exclude; |
} |
if (isset($this->_packageInfo['dependencies']['required']['pearinstaller'])) { |
$this->_stack->push(__FUNCTION__, 'warning', array('dep' => |
$this->_packageInfo['dependencies']['required']['pearinstaller']), |
'warning: PEAR Installer dependency already exists, overwriting'); |
unset($this->_packageInfo['dependencies']['required']['pearinstaller']); |
} |
$this->_packageInfo = $this->_mergeTag($this->_packageInfo, $dep, |
array( |
'dependencies' => array('providesextension', 'usesrole', 'usestask', |
'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease', |
'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog'), |
'required' => array('optional', 'group'), |
'pearinstaller' => array('package', 'subpackage', 'extension', 'os', 'arch') |
)); |
} |
/** |
* Mark a package as conflicting with this package |
* @param string package name |
* @param string package channel |
* @param string extension this package provides, if any |
* @param string|false minimum version required |
* @param string|false maximum version allowed |
* @param array|false versions to exclude from installation |
*/ |
function addConflictingPackageDepWithChannel($name, $channel, |
$providesextension = false, $min = false, $max = false, $exclude = false) |
{ |
$this->_isValid = 0; |
$dep = $this->_constructDep($name, $channel, false, $min, $max, false, |
$exclude, $providesextension, false, true); |
$this->_packageInfo = $this->_mergeTag($this->_packageInfo, $dep, |
array( |
'dependencies' => array('providesextension', 'usesrole', 'usestask', |
'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease', |
'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog'), |
'required' => array('optional', 'group'), |
'package' => array('subpackage', 'extension', 'os', 'arch') |
)); |
} |
/** |
* Mark a package as conflicting with this package |
* @param string package name |
* @param string package channel |
* @param string extension this package provides, if any |
*/ |
function addConflictingPackageDepWithUri($name, $uri, $providesextension = false) |
{ |
$this->_isValid = 0; |
$dep = |
array( |
'name' => $name, |
'uri' => $uri, |
'conflicts' => '', |
); |
if ($providesextension) { |
$dep['providesextension'] = $providesextension; |
} |
$this->_packageInfo = $this->_mergeTag($this->_packageInfo, $dep, |
array( |
'dependencies' => array('providesextension', 'usesrole', 'usestask', |
'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease', |
'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog'), |
'required' => array('optional', 'group'), |
'package' => array('subpackage', 'extension', 'os', 'arch') |
)); |
} |
function addDependencyGroup($name, $hint) |
{ |
$this->_isValid = 0; |
$this->_packageInfo = $this->_mergeTag($this->_packageInfo, |
array('attribs' => array('name' => $name, 'hint' => $hint)), |
array( |
'dependencies' => array('providesextension', 'usesrole', 'usestask', |
'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease', |
'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog'), |
'group' => array(), |
)); |
} |
/** |
* @param string package name |
* @param string|false channel name, false if this is a uri |
* @param string|false uri name, false if this is a channel |
* @param string|false minimum version required |
* @param string|false maximum version allowed |
* @param string|false recommended installation version |
* @param array|false versions to exclude from installation |
* @param string extension this package provides, if any |
* @param bool if true, tells the installer to ignore the default optional dependency group |
* when installing this package |
* @param bool if true, tells the installer to negate this dependency (conflicts) |
* @return array |
* @access private |
*/ |
function _constructDep($name, $channel, $uri, $min, $max, $recommended, $exclude, |
$providesextension = false, $nodefault = false, |
$conflicts = false) |
{ |
$dep = |
array( |
'name' => $name, |
); |
if ($channel) { |
$dep['channel'] = $channel; |
} elseif ($uri) { |
$dep['uri'] = $uri; |
} |
if ($min) { |
$dep['min'] = $min; |
} |
if ($max) { |
$dep['max'] = $max; |
} |
if ($recommended) { |
$dep['recommended'] = $recommended; |
} |
if ($exclude) { |
if (is_array($exclude) && count($exclude) == 1) { |
$exclude = $exclude[0]; |
} |
$dep['exclude'] = $exclude; |
} |
if ($conflicts) { |
$dep['conflicts'] = ''; |
} |
if ($nodefault) { |
$dep['nodefault'] = ''; |
} |
if ($providesextension) { |
$dep['providesextension'] = $providesextension; |
} |
return $dep; |
} |
/** |
* @param package|subpackage |
* @param string group name |
* @param string package name |
* @param string package channel |
* @param string minimum version |
* @param string maximum version |
* @param string recommended version |
* @param array|false optional excluded versions |
* @param string extension this package provides, if any |
* @param bool if true, tells the installer to ignore the default optional dependency group |
* when installing this package |
* @return bool false if the dependency group has not been initialized with |
* {@link addDependencyGroup()}, or a subpackage is added with |
* a providesextension |
*/ |
function addGroupPackageDepWithChannel($type, $groupname, $name, $channel, $min = false, |
$max = false, $recommended = false, $exclude = false, |
$providesextension = false, $nodefault = false) |
{ |
if ($type == 'subpackage' && $providesextension) { |
return false; // subpackages must be php packages |
} |
$dep = $this->_constructDep($name, $channel, false, $min, $max, $recommended, $exclude, |
$providesextension, $nodefault); |
return $this->_addGroupDependency($type, $dep, $groupname); |
} |
/** |
* @param package|subpackage |
* @param string group name |
* @param string package name |
* @param string package uri |
* @param string extension this package provides, if any |
* @param bool if true, tells the installer to ignore the default optional dependency group |
* when installing this package |
* @return bool false if the dependency group has not been initialized with |
* {@link addDependencyGroup()} |
*/ |
function addGroupPackageDepWithURI($type, $groupname, $name, $uri, $providesextension = false, |
$nodefault = false) |
{ |
if ($type == 'subpackage' && $providesextension) { |
return false; // subpackages must be php packages |
} |
$dep = $this->_constructDep($name, false, $uri, false, false, false, false, |
$providesextension, $nodefault); |
return $this->_addGroupDependency($type, $dep, $groupname); |
} |
/** |
* @param string group name (must be pre-existing) |
* @param string extension name |
* @param string minimum version allowed |
* @param string maximum version allowed |
* @param string recommended version |
* @param array incompatible versions |
*/ |
function addGroupExtensionDep($groupname, $name, $min = false, $max = false, |
$recommended = false, $exclude = false) |
{ |
$this->_isValid = 0; |
$dep = $this->_constructDep($name, false, false, $min, $max, $recommended, $exclude); |
return $this->_addGroupDependency('extension', $dep, $groupname); |
} |
/** |
* @param package|subpackage|extension |
* @param array dependency contents |
* @param string name of the dependency group to add this to |
* @return boolean |
* @access private |
*/ |
function _addGroupDependency($type, $dep, $groupname) |
{ |
$arr = array('subpackage', 'extension'); |
if ($type != 'package') { |
array_shift($arr); |
} |
if ($type == 'extension') { |
array_shift($arr); |
} |
if (!isset($this->_packageInfo['dependencies']['group'])) { |
return false; |
} else { |
if (!isset($this->_packageInfo['dependencies']['group'][0])) { |
if ($this->_packageInfo['dependencies']['group']['attribs']['name'] == $groupname) { |
$this->_packageInfo['dependencies']['group'] = $this->_mergeTag( |
$this->_packageInfo['dependencies']['group'], $dep, |
array( |
$type => $arr |
)); |
$this->_isValid = 0; |
return true; |
} else { |
return false; |
} |
} else { |
foreach ($this->_packageInfo['dependencies']['group'] as $i => $group) { |
if ($group['attribs']['name'] == $groupname) { |
$this->_packageInfo['dependencies']['group'][$i] = $this->_mergeTag( |
$this->_packageInfo['dependencies']['group'][$i], $dep, |
array( |
$type => $arr |
)); |
$this->_isValid = 0; |
return true; |
} |
} |
return false; |
} |
} |
} |
/** |
* @param optional|required |
* @param string package name |
* @param string package channel |
* @param string minimum version |
* @param string maximum version |
* @param string recommended version |
* @param string extension this package provides, if any |
* @param bool if true, tells the installer to ignore the default optional dependency group |
* when installing this package |
* @param array|false optional excluded versions |
*/ |
function addPackageDepWithChannel($type, $name, $channel, $min = false, $max = false, |
$recommended = false, $exclude = false, |
$providesextension = false, $nodefault = false) |
{ |
if (!in_array($type, array('optional', 'required'), true)) { |
$type = 'required'; |
} |
$this->_isValid = 0; |
$arr = array('optional', 'group'); |
if ($type != 'required') { |
array_shift($arr); |
} |
$dep = $this->_constructDep($name, $channel, false, $min, $max, $recommended, $exclude, |
$providesextension, $nodefault); |
$this->_packageInfo = $this->_mergeTag($this->_packageInfo, $dep, |
array( |
'dependencies' => array('providesextension', 'usesrole', 'usestask', |
'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease', |
'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog'), |
$type => $arr, |
'package' => array('subpackage', 'extension', 'os', 'arch') |
)); |
} |
/** |
* @param optional|required |
* @param string name of the package |
* @param string uri of the package |
* @param string extension this package provides, if any |
* @param bool if true, tells the installer to ignore the default optional dependency group |
* when installing this package |
*/ |
function addPackageDepWithUri($type, $name, $uri, $providesextension = false, |
$nodefault = false) |
{ |
$this->_isValid = 0; |
$arr = array('optional', 'group'); |
if ($type != 'required') { |
array_shift($arr); |
} |
$dep = $this->_constructDep($name, false, $uri, false, false, false, false, |
$providesextension, $nodefault); |
$this->_packageInfo = $this->_mergeTag($this->_packageInfo, $dep, |
array( |
'dependencies' => array('providesextension', 'usesrole', 'usestask', |
'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease', |
'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog'), |
$type => $arr, |
'package' => array('subpackage', 'extension', 'os', 'arch') |
)); |
} |
/** |
* @param optional|required optional, required |
* @param string package name |
* @param string package channel |
* @param string minimum version |
* @param string maximum version |
* @param string recommended version |
* @param array incompatible versions |
* @param bool if true, tells the installer to ignore the default optional dependency group |
* when installing this package |
*/ |
function addSubpackageDepWithChannel($type, $name, $channel, $min = false, $max = false, |
$recommended = false, $exclude = false, |
$nodefault = false) |
{ |
$this->_isValid = 0; |
$arr = array('optional', 'group'); |
if ($type != 'required') { |
array_shift($arr); |
} |
$dep = $this->_constructDep($name, $channel, false, $min, $max, $recommended, $exclude, |
$nodefault); |
$this->_packageInfo = $this->_mergeTag($this->_packageInfo, $dep, |
array( |
'dependencies' => array('providesextension', 'usesrole', 'usestask', |
'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease', |
'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog'), |
$type => $arr, |
'subpackage' => array('extension', 'os', 'arch') |
)); |
} |
/** |
* @param optional|required optional, required |
* @param string package name |
* @param string package uri for download |
* @param bool if true, tells the installer to ignore the default optional dependency group |
* when installing this package |
*/ |
function addSubpackageDepWithUri($type, $name, $uri, $nodefault = false) |
{ |
$this->_isValid = 0; |
$arr = array('optional', 'group'); |
if ($type != 'required') { |
array_shift($arr); |
} |
$dep = $this->_constructDep($name, false, $uri, false, false, false, false, $nodefault); |
$this->_packageInfo = $this->_mergeTag($this->_packageInfo, $dep, |
array( |
'dependencies' => array('providesextension', 'usesrole', 'usestask', |
'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease', |
'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog'), |
$type => $arr, |
'subpackage' => array('extension', 'os', 'arch') |
)); |
} |
/** |
* @param optional|required optional, required |
* @param string extension name |
* @param string minimum version |
* @param string maximum version |
* @param string recommended version |
* @param array incompatible versions |
*/ |
function addExtensionDep($type, $name, $min = false, $max = false, $recommended = false, |
$exclude = false) |
{ |
$this->_isValid = 0; |
$arr = array('optional', 'group'); |
if ($type != 'required') { |
array_shift($arr); |
} |
$dep = $this->_constructDep($name, false, false, $min, $max, $recommended, $exclude); |
$this->_packageInfo = $this->_mergeTag($this->_packageInfo, $dep, |
array( |
'dependencies' => array('providesextension', 'usesrole', 'usestask', |
'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease', |
'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog'), |
$type => $arr, |
'extension' => array('os', 'arch') |
)); |
} |
/** |
* @param string Operating system name |
* @param boolean true if this package cannot be installed on this OS |
*/ |
function addOsDep($name, $conflicts = false) |
{ |
$this->_isValid = 0; |
$dep = array('name' => $name); |
if ($conflicts) { |
$dep['conflicts'] = ''; |
} |
$this->_packageInfo = $this->_mergeTag($this->_packageInfo, $dep, |
array( |
'dependencies' => array('providesextension', 'usesrole', 'usestask', |
'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease', |
'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog'), |
'required' => array('optional', 'group'), |
'os' => array('arch') |
)); |
} |
/** |
* @param string Architecture matching pattern |
* @param boolean true if this package cannot be installed on this architecture |
*/ |
function addArchDep($pattern, $conflicts = false) |
{ |
$this->_isValid = 0; |
$dep = array('pattern' => $pattern); |
if ($conflicts) { |
$dep['conflicts'] = ''; |
} |
$this->_packageInfo = $this->_mergeTag($this->_packageInfo, $dep, |
array( |
'dependencies' => array('providesextension', 'usesrole', 'usestask', |
'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease', |
'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog'), |
'required' => array('optional', 'group'), |
'arch' => array() |
)); |
} |
/** |
* Set the kind of package, and erase all release tags |
* |
* - a php package is a PEAR-style package |
* - an extbin package is a PECL-style extension binary |
* - an extsrc package is a PECL-style source for a binary |
* - an zendextbin package is a PECL-style zend extension binary |
* - an zendextsrc package is a PECL-style source for a zend extension binary |
* - a bundle package is a collection of other pre-packaged packages |
* @param php|extbin|extsrc|zendextsrc|zendextbin|bundle |
* @return bool success |
*/ |
function setPackageType($type) |
{ |
$this->_isValid = 0; |
if (!in_array($type, array('php', 'extbin', 'extsrc', 'zendextsrc', |
'zendextbin', 'bundle'))) { |
return false; |
} |
if (in_array($type, array('zendextsrc', 'zendextbin'))) { |
$this->_setPackageVersion2_1(); |
} |
if ($type != 'bundle') { |
$type .= 'release'; |
} |
foreach (array('phprelease', 'extbinrelease', 'extsrcrelease', |
'zendextsrcrelease', 'zendextbinrelease', 'bundle') as $test) { |
unset($this->_packageInfo[$test]); |
} |
if (!isset($this->_packageInfo[$type])) { |
// ensure that the release tag is set up |
$this->_packageInfo = $this->_insertBefore($this->_packageInfo, array('changelog'), |
array(), $type); |
} |
$this->_packageInfo[$type] = array(); |
return true; |
} |
/** |
* @return bool true if package type is set up |
*/ |
function addRelease() |
{ |
if ($type = $this->getPackageType()) { |
if ($type != 'bundle') { |
$type .= 'release'; |
} |
$this->_packageInfo = $this->_mergeTag($this->_packageInfo, array(), |
array($type => array('changelog'))); |
return true; |
} |
return false; |
} |
/** |
* Get the current release tag in order to add to it |
* @param bool returns only releases that have installcondition if true |
* @return array|null |
*/ |
function &_getCurrentRelease($strict = true) |
{ |
if ($p = $this->getPackageType()) { |
if ($strict) { |
if ($p == 'extsrc' || $p == 'zendextsrc') { |
$a = null; |
return $a; |
} |
} |
if ($p != 'bundle') { |
$p .= 'release'; |
} |
if (isset($this->_packageInfo[$p][0])) { |
return $this->_packageInfo[$p][count($this->_packageInfo[$p]) - 1]; |
} else { |
return $this->_packageInfo[$p]; |
} |
} else { |
$a = null; |
return $a; |
} |
} |
/** |
* Add a file to the current release that should be installed under a different name |
* @param string <contents> path to file |
* @param string name the file should be installed as |
*/ |
function addInstallAs($path, $as) |
{ |
$r = &$this->_getCurrentRelease(); |
if ($r === null) { |
return false; |
} |
$this->_isValid = 0; |
$r = $this->_mergeTag($r, array('attribs' => array('name' => $path, 'as' => $as)), |
array( |
'filelist' => array(), |
'install' => array('ignore') |
)); |
} |
/** |
* Add a file to the current release that should be ignored |
* @param string <contents> path to file |
* @return bool success of operation |
*/ |
function addIgnore($path) |
{ |
$r = &$this->_getCurrentRelease(); |
if ($r === null) { |
return false; |
} |
$this->_isValid = 0; |
$r = $this->_mergeTag($r, array('attribs' => array('name' => $path)), |
array( |
'filelist' => array(), |
'ignore' => array() |
)); |
} |
/** |
* Add an extension binary package for this extension source code release |
* |
* Note that the package must be from the same channel as the extension source package |
* @param string |
*/ |
function addBinarypackage($package) |
{ |
if ($this->getPackageType() != 'extsrc' && $this->getPackageType() != 'zendextsrc') { |
return false; |
} |
$r = &$this->_getCurrentRelease(false); |
if ($r === null) { |
return false; |
} |
$this->_isValid = 0; |
$r = $this->_mergeTag($r, $package, |
array( |
'binarypackage' => array('filelist'), |
)); |
} |
/** |
* Add a configureoption to an extension source package |
* @param string |
* @param string |
* @param string |
*/ |
function addConfigureOption($name, $prompt, $default = null) |
{ |
if ($this->getPackageType() != 'extsrc' && $this->getPackageType() != 'zendextsrc') { |
return false; |
} |
$r = &$this->_getCurrentRelease(false); |
if ($r === null) { |
return false; |
} |
$opt = array('attribs' => array('name' => $name, 'prompt' => $prompt)); |
if ($default !== null) { |
$opt['attribs']['default'] = $default; |
} |
$this->_isValid = 0; |
$r = $this->_mergeTag($r, $opt, |
array( |
'configureoption' => array('binarypackage', 'filelist'), |
)); |
} |
/** |
* Set an installation condition based on php version for the current release set |
* @param string minimum version |
* @param string maximum version |
* @param false|array incompatible versions of PHP |
*/ |
function setPhpInstallCondition($min, $max, $exclude = false) |
{ |
$r = &$this->_getCurrentRelease(); |
if ($r === null) { |
return false; |
} |
$this->_isValid = 0; |
if (isset($r['installconditions']['php'])) { |
unset($r['installconditions']['php']); |
} |
$dep = array('min' => $min, 'max' => $max); |
if ($exclude) { |
if (is_array($exclude) && count($exclude) == 1) { |
$exclude = $exclude[0]; |
} |
$dep['exclude'] = $exclude; |
} |
if ($this->getPackageType() == 'extsrc' || $this->getPackageType() == 'zendextsrc') { |
$r = $this->_mergeTag($r, $dep, |
array( |
'installconditions' => array('configureoption', 'binarypackage', |
'filelist'), |
'php' => array('extension', 'os', 'arch') |
)); |
} else { |
$r = $this->_mergeTag($r, $dep, |
array( |
'installconditions' => array('filelist'), |
'php' => array('extension', 'os', 'arch') |
)); |
} |
} |
/** |
* @param optional|required optional, required |
* @param string extension name |
* @param string minimum version |
* @param string maximum version |
* @param string recommended version |
* @param array incompatible versions |
*/ |
function addExtensionInstallCondition($name, $min = false, $max = false, $recommended = false, |
$exclude = false) |
{ |
$r = &$this->_getCurrentRelease(); |
if ($r === null) { |
return false; |
} |
$this->_isValid = 0; |
$dep = $this->_constructDep($name, false, false, $min, $max, $recommended, $exclude); |
if ($this->getPackageType() == 'extsrc' || $this->getPackageType() == 'zendextsrc') { |
$r = $this->_mergeTag($r, $dep, |
array( |
'installconditions' => array('configureoption', 'binarypackage', |
'filelist'), |
'extension' => array('os', 'arch') |
)); |
} else { |
$r = $this->_mergeTag($r, $dep, |
array( |
'installconditions' => array('filelist'), |
'extension' => array('os', 'arch') |
)); |
} |
} |
/** |
* Set an installation condition based on operating system for the current release set |
* @param string OS name |
* @param bool whether this OS is incompatible with the current release |
*/ |
function setOsInstallCondition($name, $conflicts = false) |
{ |
$r = &$this->_getCurrentRelease(); |
if ($r === null) { |
return false; |
} |
$this->_isValid = 0; |
if (isset($r['installconditions']['os'])) { |
unset($r['installconditions']['os']); |
} |
$dep = array('name' => $name); |
if ($conflicts) { |
$dep['conflicts'] = ''; |
} |
if ($this->getPackageType() == 'extsrc' || $this->getPackageType() == 'zendextsrc') { |
$r = $this->_mergeTag($r, $dep, |
array( |
'installconditions' => array('configureoption', 'binarypackage', |
'filelist'), |
'os' => array('arch') |
)); |
} else { |
$r = $this->_mergeTag($r, $dep, |
array( |
'installconditions' => array('filelist'), |
'os' => array('arch') |
)); |
} |
} |
/** |
* Set an installation condition based on architecture for the current release set |
* @param string architecture pattern |
* @param bool whether this arch is incompatible with the current release |
*/ |
function setArchInstallCondition($pattern, $conflicts = false) |
{ |
$r = &$this->_getCurrentRelease(); |
if ($r === null) { |
return false; |
} |
$this->_isValid = 0; |
if (isset($r['installconditions']['arch'])) { |
unset($r['installconditions']['arch']); |
} |
$dep = array('pattern' => $pattern); |
if ($conflicts) { |
$dep['conflicts'] = ''; |
} |
if ($this->getPackageType() == 'extsrc' || $this->getPackageType() == 'zendextsrc') { |
$r = $this->_mergeTag($r, $dep, |
array( |
'installconditions' => array('configureoption', 'binarypackage', |
'filelist'), |
'arch' => array() |
)); |
} else { |
$r = $this->_mergeTag($r, $dep, |
array( |
'installconditions' => array('filelist'), |
'arch' => array() |
)); |
} |
} |
/** |
* For extension binary releases, this is used to specify either the |
* static URI to a source package, or the package name and channel of the extsrc/zendextsrc |
* package it is based on. |
* @param string Package name, or full URI to source package (extsrc/zendextsrc type) |
*/ |
function setSourcePackage($packageOrUri) |
{ |
$this->_isValid = 0; |
if (isset($this->_packageInfo['channel'])) { |
$this->_packageInfo = $this->_insertBefore($this->_packageInfo, array('phprelease', |
'extsrcrelease', 'extbinrelease', 'zendextsrcrelease', 'zendextbinrelease', |
'bundle', 'changelog'), |
$packageOrUri, 'srcpackage'); |
} else { |
$this->_packageInfo = $this->_insertBefore($this->_packageInfo, array('phprelease', |
'extsrcrelease', 'extbinrelease', 'zendextsrcrelease', 'zendextbinrelease', |
'bundle', 'changelog'), $packageOrUri, 'srcuri'); |
} |
} |
/** |
* Generate a valid change log entry from the current package.xml |
* @param string|false |
*/ |
function generateChangeLogEntry($notes = false) |
{ |
return array( |
'version' => |
array( |
'release' => $this->getVersion('release'), |
'api' => $this->getVersion('api'), |
), |
'stability' => |
$this->getStability(), |
'date' => $this->getDate(), |
'license' => $this->getLicense(true), |
'notes' => $notes ? $notes : $this->getNotes() |
); |
} |
/** |
* @param string release version to set change log notes for |
* @param array output of {@link generateChangeLogEntry()} |
*/ |
function setChangelogEntry($releaseversion, $contents) |
{ |
if (!isset($this->_packageInfo['changelog'])) { |
$this->_packageInfo['changelog']['release'] = $contents; |
return; |
} |
if (!isset($this->_packageInfo['changelog']['release'][0])) { |
if ($this->_packageInfo['changelog']['release']['version']['release'] == $releaseversion) { |
$this->_packageInfo['changelog']['release'] = array( |
$this->_packageInfo['changelog']['release']); |
} else { |
$this->_packageInfo['changelog']['release'] = array( |
$this->_packageInfo['changelog']['release']); |
return $this->_packageInfo['changelog']['release'][] = $contents; |
} |
} |
foreach($this->_packageInfo['changelog']['release'] as $index => $changelog) { |
if (isset($changelog['version']) && |
strnatcasecmp($changelog['version']['release'], $releaseversion) == 0) { |
$curlog = $index; |
} |
} |
if (isset($curlog)) { |
$this->_packageInfo['changelog']['release'][$curlog] = $contents; |
} else { |
$this->_packageInfo['changelog']['release'][] = $contents; |
} |
} |
/** |
* Remove the changelog entirely |
*/ |
function clearChangeLog() |
{ |
unset($this->_packageInfo['changelog']); |
} |
} |
/branches/v1.3-critias/bibliotheque/pear/PEAR/PackageFile/Parser/v1.php |
---|
New file |
0,0 → 1,458 |
<?php |
/** |
* package.xml parsing class, package.xml version 1.0 |
* |
* PHP versions 4 and 5 |
* |
* @category pear |
* @package PEAR |
* @author Greg Beaver <cellog@php.net> |
* @copyright 1997-2009 The Authors |
* @license http://opensource.org/licenses/bsd-license.php New BSD License |
* @link http://pear.php.net/package/PEAR |
* @since File available since Release 1.4.0a1 |
*/ |
/** |
* package.xml abstraction class |
*/ |
require_once 'PEAR/PackageFile/v1.php'; |
/** |
* Parser for package.xml version 1.0 |
* @category pear |
* @package PEAR |
* @author Greg Beaver <cellog@php.net> |
* @copyright 1997-2009 The Authors |
* @license http://opensource.org/licenses/bsd-license.php New BSD License |
* @version Release: @PEAR-VER@ |
* @link http://pear.php.net/package/PEAR |
* @since Class available since Release 1.4.0a1 |
*/ |
class PEAR_PackageFile_Parser_v1 |
{ |
var $_registry; |
var $_config; |
var $_logger; |
/** |
* BC hack to allow PEAR_Common::infoFromString() to sort of |
* work with the version 2.0 format - there's no filelist though |
* @param PEAR_PackageFile_v2 |
*/ |
function fromV2($packagefile) |
{ |
$info = $packagefile->getArray(true); |
$ret = new PEAR_PackageFile_v1; |
$ret->fromArray($info['old']); |
} |
function setConfig(&$c) |
{ |
$this->_config = &$c; |
$this->_registry = &$c->getRegistry(); |
} |
function setLogger(&$l) |
{ |
$this->_logger = &$l; |
} |
/** |
* @param string contents of package.xml file, version 1.0 |
* @return bool success of parsing |
*/ |
function &parse($data, $file, $archive = false) |
{ |
if (!extension_loaded('xml')) { |
return PEAR::raiseError('Cannot create xml parser for parsing package.xml, no xml extension'); |
} |
$xp = xml_parser_create(); |
if (!$xp) { |
$a = &PEAR::raiseError('Cannot create xml parser for parsing package.xml'); |
return $a; |
} |
xml_set_object($xp, $this); |
xml_set_element_handler($xp, '_element_start_1_0', '_element_end_1_0'); |
xml_set_character_data_handler($xp, '_pkginfo_cdata_1_0'); |
xml_parser_set_option($xp, XML_OPTION_CASE_FOLDING, false); |
$this->element_stack = array(); |
$this->_packageInfo = array('provides' => array()); |
$this->current_element = false; |
unset($this->dir_install); |
$this->_packageInfo['filelist'] = array(); |
$this->filelist =& $this->_packageInfo['filelist']; |
$this->dir_names = array(); |
$this->in_changelog = false; |
$this->d_i = 0; |
$this->cdata = ''; |
$this->_isValid = true; |
if (!xml_parse($xp, $data, 1)) { |
$code = xml_get_error_code($xp); |
$line = xml_get_current_line_number($xp); |
xml_parser_free($xp); |
$a = PEAR::raiseError(sprintf("XML error: %s at line %d", |
$str = xml_error_string($code), $line), 2); |
return $a; |
} |
xml_parser_free($xp); |
$pf = new PEAR_PackageFile_v1; |
$pf->setConfig($this->_config); |
if (isset($this->_logger)) { |
$pf->setLogger($this->_logger); |
} |
$pf->setPackagefile($file, $archive); |
$pf->fromArray($this->_packageInfo); |
return $pf; |
} |
// {{{ _unIndent() |
/** |
* Unindent given string |
* |
* @param string $str The string that has to be unindented. |
* @return string |
* @access private |
*/ |
function _unIndent($str) |
{ |
// remove leading newlines |
$str = preg_replace('/^[\r\n]+/', '', $str); |
// find whitespace at the beginning of the first line |
$indent_len = strspn($str, " \t"); |
$indent = substr($str, 0, $indent_len); |
$data = ''; |
// remove the same amount of whitespace from following lines |
foreach (explode("\n", $str) as $line) { |
if (substr($line, 0, $indent_len) == $indent) { |
$data .= substr($line, $indent_len) . "\n"; |
} elseif (trim(substr($line, 0, $indent_len))) { |
$data .= ltrim($line); |
} |
} |
return $data; |
} |
// Support for package DTD v1.0: |
// {{{ _element_start_1_0() |
/** |
* XML parser callback for ending elements. Used for version 1.0 |
* packages. |
* |
* @param resource $xp XML parser resource |
* @param string $name name of ending element |
* |
* @return void |
* |
* @access private |
*/ |
function _element_start_1_0($xp, $name, $attribs) |
{ |
array_push($this->element_stack, $name); |
$this->current_element = $name; |
$spos = sizeof($this->element_stack) - 2; |
$this->prev_element = ($spos >= 0) ? $this->element_stack[$spos] : ''; |
$this->current_attributes = $attribs; |
$this->cdata = ''; |
switch ($name) { |
case 'dir': |
if ($this->in_changelog) { |
break; |
} |
if (array_key_exists('name', $attribs) && $attribs['name'] != '/') { |
$attribs['name'] = preg_replace(array('!\\\\+!', '!/+!'), array('/', '/'), |
$attribs['name']); |
if (strrpos($attribs['name'], '/') === strlen($attribs['name']) - 1) { |
$attribs['name'] = substr($attribs['name'], 0, |
strlen($attribs['name']) - 1); |
} |
if (strpos($attribs['name'], '/') === 0) { |
$attribs['name'] = substr($attribs['name'], 1); |
} |
$this->dir_names[] = $attribs['name']; |
} |
if (isset($attribs['baseinstalldir'])) { |
$this->dir_install = $attribs['baseinstalldir']; |
} |
if (isset($attribs['role'])) { |
$this->dir_role = $attribs['role']; |
} |
break; |
case 'file': |
if ($this->in_changelog) { |
break; |
} |
if (isset($attribs['name'])) { |
$path = ''; |
if (count($this->dir_names)) { |
foreach ($this->dir_names as $dir) { |
$path .= $dir . '/'; |
} |
} |
$path .= preg_replace(array('!\\\\+!', '!/+!'), array('/', '/'), |
$attribs['name']); |
unset($attribs['name']); |
$this->current_path = $path; |
$this->filelist[$path] = $attribs; |
// Set the baseinstalldir only if the file don't have this attrib |
if (!isset($this->filelist[$path]['baseinstalldir']) && |
isset($this->dir_install)) |
{ |
$this->filelist[$path]['baseinstalldir'] = $this->dir_install; |
} |
// Set the Role |
if (!isset($this->filelist[$path]['role']) && isset($this->dir_role)) { |
$this->filelist[$path]['role'] = $this->dir_role; |
} |
} |
break; |
case 'replace': |
if (!$this->in_changelog) { |
$this->filelist[$this->current_path]['replacements'][] = $attribs; |
} |
break; |
case 'maintainers': |
$this->_packageInfo['maintainers'] = array(); |
$this->m_i = 0; // maintainers array index |
break; |
case 'maintainer': |
// compatibility check |
if (!isset($this->_packageInfo['maintainers'])) { |
$this->_packageInfo['maintainers'] = array(); |
$this->m_i = 0; |
} |
$this->_packageInfo['maintainers'][$this->m_i] = array(); |
$this->current_maintainer =& $this->_packageInfo['maintainers'][$this->m_i]; |
break; |
case 'changelog': |
$this->_packageInfo['changelog'] = array(); |
$this->c_i = 0; // changelog array index |
$this->in_changelog = true; |
break; |
case 'release': |
if ($this->in_changelog) { |
$this->_packageInfo['changelog'][$this->c_i] = array(); |
$this->current_release = &$this->_packageInfo['changelog'][$this->c_i]; |
} else { |
$this->current_release = &$this->_packageInfo; |
} |
break; |
case 'deps': |
if (!$this->in_changelog) { |
$this->_packageInfo['release_deps'] = array(); |
} |
break; |
case 'dep': |
// dependencies array index |
if (!$this->in_changelog) { |
$this->d_i++; |
isset($attribs['type']) ? ($attribs['type'] = strtolower($attribs['type'])) : false; |
$this->_packageInfo['release_deps'][$this->d_i] = $attribs; |
} |
break; |
case 'configureoptions': |
if (!$this->in_changelog) { |
$this->_packageInfo['configure_options'] = array(); |
} |
break; |
case 'configureoption': |
if (!$this->in_changelog) { |
$this->_packageInfo['configure_options'][] = $attribs; |
} |
break; |
case 'provides': |
if (empty($attribs['type']) || empty($attribs['name'])) { |
break; |
} |
$attribs['explicit'] = true; |
$this->_packageInfo['provides']["$attribs[type];$attribs[name]"] = $attribs; |
break; |
case 'package' : |
if (isset($attribs['version'])) { |
$this->_packageInfo['xsdversion'] = trim($attribs['version']); |
} else { |
$this->_packageInfo['xsdversion'] = '1.0'; |
} |
if (isset($attribs['packagerversion'])) { |
$this->_packageInfo['packagerversion'] = $attribs['packagerversion']; |
} |
break; |
} |
} |
// }}} |
// {{{ _element_end_1_0() |
/** |
* XML parser callback for ending elements. Used for version 1.0 |
* packages. |
* |
* @param resource $xp XML parser resource |
* @param string $name name of ending element |
* |
* @return void |
* |
* @access private |
*/ |
function _element_end_1_0($xp, $name) |
{ |
$data = trim($this->cdata); |
switch ($name) { |
case 'name': |
switch ($this->prev_element) { |
case 'package': |
$this->_packageInfo['package'] = $data; |
break; |
case 'maintainer': |
$this->current_maintainer['name'] = $data; |
break; |
} |
break; |
case 'extends' : |
$this->_packageInfo['extends'] = $data; |
break; |
case 'summary': |
$this->_packageInfo['summary'] = $data; |
break; |
case 'description': |
$data = $this->_unIndent($this->cdata); |
$this->_packageInfo['description'] = $data; |
break; |
case 'user': |
$this->current_maintainer['handle'] = $data; |
break; |
case 'email': |
$this->current_maintainer['email'] = $data; |
break; |
case 'role': |
$this->current_maintainer['role'] = $data; |
break; |
case 'version': |
if ($this->in_changelog) { |
$this->current_release['version'] = $data; |
} else { |
$this->_packageInfo['version'] = $data; |
} |
break; |
case 'date': |
if ($this->in_changelog) { |
$this->current_release['release_date'] = $data; |
} else { |
$this->_packageInfo['release_date'] = $data; |
} |
break; |
case 'notes': |
// try to "de-indent" release notes in case someone |
// has been over-indenting their xml ;-) |
// Trim only on the right side |
$data = rtrim($this->_unIndent($this->cdata)); |
if ($this->in_changelog) { |
$this->current_release['release_notes'] = $data; |
} else { |
$this->_packageInfo['release_notes'] = $data; |
} |
break; |
case 'warnings': |
if ($this->in_changelog) { |
$this->current_release['release_warnings'] = $data; |
} else { |
$this->_packageInfo['release_warnings'] = $data; |
} |
break; |
case 'state': |
if ($this->in_changelog) { |
$this->current_release['release_state'] = $data; |
} else { |
$this->_packageInfo['release_state'] = $data; |
} |
break; |
case 'license': |
if ($this->in_changelog) { |
$this->current_release['release_license'] = $data; |
} else { |
$this->_packageInfo['release_license'] = $data; |
} |
break; |
case 'dep': |
if ($data && !$this->in_changelog) { |
$this->_packageInfo['release_deps'][$this->d_i]['name'] = $data; |
} |
break; |
case 'dir': |
if ($this->in_changelog) { |
break; |
} |
array_pop($this->dir_names); |
break; |
case 'file': |
if ($this->in_changelog) { |
break; |
} |
if ($data) { |
$path = ''; |
if (count($this->dir_names)) { |
foreach ($this->dir_names as $dir) { |
$path .= $dir . '/'; |
} |
} |
$path .= $data; |
$this->filelist[$path] = $this->current_attributes; |
// Set the baseinstalldir only if the file don't have this attrib |
if (!isset($this->filelist[$path]['baseinstalldir']) && |
isset($this->dir_install)) |
{ |
$this->filelist[$path]['baseinstalldir'] = $this->dir_install; |
} |
// Set the Role |
if (!isset($this->filelist[$path]['role']) && isset($this->dir_role)) { |
$this->filelist[$path]['role'] = $this->dir_role; |
} |
} |
break; |
case 'maintainer': |
if (empty($this->_packageInfo['maintainers'][$this->m_i]['role'])) { |
$this->_packageInfo['maintainers'][$this->m_i]['role'] = 'lead'; |
} |
$this->m_i++; |
break; |
case 'release': |
if ($this->in_changelog) { |
$this->c_i++; |
} |
break; |
case 'changelog': |
$this->in_changelog = false; |
break; |
} |
array_pop($this->element_stack); |
$spos = sizeof($this->element_stack) - 1; |
$this->current_element = ($spos > 0) ? $this->element_stack[$spos] : ''; |
$this->cdata = ''; |
} |
// }}} |
// {{{ _pkginfo_cdata_1_0() |
/** |
* XML parser callback for character data. Used for version 1.0 |
* packages. |
* |
* @param resource $xp XML parser resource |
* @param string $name character data |
* |
* @return void |
* |
* @access private |
*/ |
function _pkginfo_cdata_1_0($xp, $data) |
{ |
if (isset($this->cdata)) { |
$this->cdata .= $data; |
} |
} |
// }}} |
} |
?> |
/branches/v1.3-critias/bibliotheque/pear/PEAR/PackageFile/Parser/v2.php |
---|
New file |
0,0 → 1,112 |
<?php |
/** |
* package.xml parsing class, package.xml version 2.0 |
* |
* PHP versions 4 and 5 |
* |
* @category pear |
* @package PEAR |
* @author Greg Beaver <cellog@php.net> |
* @copyright 1997-2009 The Authors |
* @license http://opensource.org/licenses/bsd-license.php New BSD License |
* @link http://pear.php.net/package/PEAR |
* @since File available since Release 1.4.0a1 |
*/ |
/** |
* base xml parser class |
*/ |
require_once 'PEAR/XMLParser.php'; |
require_once 'PEAR/PackageFile/v2.php'; |
/** |
* Parser for package.xml version 2.0 |
* @category pear |
* @package PEAR |
* @author Greg Beaver <cellog@php.net> |
* @copyright 1997-2009 The Authors |
* @license http://opensource.org/licenses/bsd-license.php New BSD License |
* @version Release: @PEAR-VER@ |
* @link http://pear.php.net/package/PEAR |
* @since Class available since Release 1.4.0a1 |
*/ |
class PEAR_PackageFile_Parser_v2 extends PEAR_XMLParser |
{ |
var $_config; |
var $_logger; |
var $_registry; |
function setConfig(&$c) |
{ |
$this->_config = &$c; |
$this->_registry = &$c->getRegistry(); |
} |
function setLogger(&$l) |
{ |
$this->_logger = &$l; |
} |
/** |
* Unindent given string |
* |
* @param string $str The string that has to be unindented. |
* @return string |
* @access private |
*/ |
function _unIndent($str) |
{ |
// remove leading newlines |
$str = preg_replace('/^[\r\n]+/', '', $str); |
// find whitespace at the beginning of the first line |
$indent_len = strspn($str, " \t"); |
$indent = substr($str, 0, $indent_len); |
$data = ''; |
// remove the same amount of whitespace from following lines |
foreach (explode("\n", $str) as $line) { |
if (substr($line, 0, $indent_len) == $indent) { |
$data .= substr($line, $indent_len) . "\n"; |
} else { |
$data .= $line . "\n"; |
} |
} |
return $data; |
} |
/** |
* post-process data |
* |
* @param string $data |
* @param string $element element name |
*/ |
function postProcess($data, $element) |
{ |
if ($element == 'notes') { |
return trim($this->_unIndent($data)); |
} |
return trim($data); |
} |
/** |
* @param string |
* @param string file name of the package.xml |
* @param string|false name of the archive this package.xml came from, if any |
* @param string class name to instantiate and return. This must be PEAR_PackageFile_v2 or |
* a subclass |
* @return PEAR_PackageFile_v2 |
*/ |
function parse($data, $file = null, $archive = false, $class = 'PEAR_PackageFile_v2') |
{ |
if (PEAR::isError($err = parent::parse($data))) { |
return $err; |
} |
$ret = new $class; |
$ret->encoding = $this->encoding; |
$ret->setConfig($this->_config); |
if (isset($this->_logger)) { |
$ret->setLogger($this->_logger); |
} |
$ret->fromArray($this->_unserializedData); |
$ret->setPackagefile($file, $archive); |
return $ret; |
} |
} |
/branches/v1.3-critias/bibliotheque/pear/PEAR/PackageFile/v1.php |
---|
New file |
0,0 → 1,1602 |
<?php |
/** |
* PEAR_PackageFile_v1, package.xml version 1.0 |
* |
* PHP versions 4 and 5 |
* |
* @category pear |
* @package PEAR |
* @author Greg Beaver <cellog@php.net> |
* @copyright 1997-2009 The Authors |
* @license http://opensource.org/licenses/bsd-license.php New BSD License |
* @link http://pear.php.net/package/PEAR |
* @since File available since Release 1.4.0a1 |
*/ |
/** |
* For error handling |
*/ |
require_once 'PEAR/ErrorStack.php'; |
/** |
* Error code if parsing is attempted with no xml extension |
*/ |
define('PEAR_PACKAGEFILE_ERROR_NO_XML_EXT', 3); |
/** |
* Error code if creating the xml parser resource fails |
*/ |
define('PEAR_PACKAGEFILE_ERROR_CANT_MAKE_PARSER', 4); |
/** |
* Error code used for all sax xml parsing errors |
*/ |
define('PEAR_PACKAGEFILE_ERROR_PARSER_ERROR', 5); |
/** |
* Error code used when there is no name |
*/ |
define('PEAR_PACKAGEFILE_ERROR_NO_NAME', 6); |
/** |
* Error code when a package name is not valid |
*/ |
define('PEAR_PACKAGEFILE_ERROR_INVALID_NAME', 7); |
/** |
* Error code used when no summary is parsed |
*/ |
define('PEAR_PACKAGEFILE_ERROR_NO_SUMMARY', 8); |
/** |
* Error code for summaries that are more than 1 line |
*/ |
define('PEAR_PACKAGEFILE_ERROR_MULTILINE_SUMMARY', 9); |
/** |
* Error code used when no description is present |
*/ |
define('PEAR_PACKAGEFILE_ERROR_NO_DESCRIPTION', 10); |
/** |
* Error code used when no license is present |
*/ |
define('PEAR_PACKAGEFILE_ERROR_NO_LICENSE', 11); |
/** |
* Error code used when a <version> version number is not present |
*/ |
define('PEAR_PACKAGEFILE_ERROR_NO_VERSION', 12); |
/** |
* Error code used when a <version> version number is invalid |
*/ |
define('PEAR_PACKAGEFILE_ERROR_INVALID_VERSION', 13); |
/** |
* Error code when release state is missing |
*/ |
define('PEAR_PACKAGEFILE_ERROR_NO_STATE', 14); |
/** |
* Error code when release state is invalid |
*/ |
define('PEAR_PACKAGEFILE_ERROR_INVALID_STATE', 15); |
/** |
* Error code when release state is missing |
*/ |
define('PEAR_PACKAGEFILE_ERROR_NO_DATE', 16); |
/** |
* Error code when release state is invalid |
*/ |
define('PEAR_PACKAGEFILE_ERROR_INVALID_DATE', 17); |
/** |
* Error code when no release notes are found |
*/ |
define('PEAR_PACKAGEFILE_ERROR_NO_NOTES', 18); |
/** |
* Error code when no maintainers are found |
*/ |
define('PEAR_PACKAGEFILE_ERROR_NO_MAINTAINERS', 19); |
/** |
* Error code when a maintainer has no handle |
*/ |
define('PEAR_PACKAGEFILE_ERROR_NO_MAINTHANDLE', 20); |
/** |
* Error code when a maintainer has no handle |
*/ |
define('PEAR_PACKAGEFILE_ERROR_NO_MAINTROLE', 21); |
/** |
* Error code when a maintainer has no name |
*/ |
define('PEAR_PACKAGEFILE_ERROR_NO_MAINTNAME', 22); |
/** |
* Error code when a maintainer has no email |
*/ |
define('PEAR_PACKAGEFILE_ERROR_NO_MAINTEMAIL', 23); |
/** |
* Error code when a maintainer has no handle |
*/ |
define('PEAR_PACKAGEFILE_ERROR_INVALID_MAINTROLE', 24); |
/** |
* Error code when a dependency is not a PHP dependency, but has no name |
*/ |
define('PEAR_PACKAGEFILE_ERROR_NO_DEPNAME', 25); |
/** |
* Error code when a dependency has no type (pkg, php, etc.) |
*/ |
define('PEAR_PACKAGEFILE_ERROR_NO_DEPTYPE', 26); |
/** |
* Error code when a dependency has no relation (lt, ge, has, etc.) |
*/ |
define('PEAR_PACKAGEFILE_ERROR_NO_DEPREL', 27); |
/** |
* Error code when a dependency is not a 'has' relation, but has no version |
*/ |
define('PEAR_PACKAGEFILE_ERROR_NO_DEPVERSION', 28); |
/** |
* Error code when a dependency has an invalid relation |
*/ |
define('PEAR_PACKAGEFILE_ERROR_INVALID_DEPREL', 29); |
/** |
* Error code when a dependency has an invalid type |
*/ |
define('PEAR_PACKAGEFILE_ERROR_INVALID_DEPTYPE', 30); |
/** |
* Error code when a dependency has an invalid optional option |
*/ |
define('PEAR_PACKAGEFILE_ERROR_INVALID_DEPOPTIONAL', 31); |
/** |
* Error code when a dependency is a pkg dependency, and has an invalid package name |
*/ |
define('PEAR_PACKAGEFILE_ERROR_INVALID_DEPNAME', 32); |
/** |
* Error code when a dependency has a channel="foo" attribute, and foo is not a registered channel |
*/ |
define('PEAR_PACKAGEFILE_ERROR_UNKNOWN_DEPCHANNEL', 33); |
/** |
* Error code when rel="has" and version attribute is present. |
*/ |
define('PEAR_PACKAGEFILE_ERROR_DEPVERSION_IGNORED', 34); |
/** |
* Error code when type="php" and dependency name is present |
*/ |
define('PEAR_PACKAGEFILE_ERROR_DEPNAME_IGNORED', 35); |
/** |
* Error code when a configure option has no name |
*/ |
define('PEAR_PACKAGEFILE_ERROR_NO_CONFNAME', 36); |
/** |
* Error code when a configure option has no name |
*/ |
define('PEAR_PACKAGEFILE_ERROR_NO_CONFPROMPT', 37); |
/** |
* Error code when a file in the filelist has an invalid role |
*/ |
define('PEAR_PACKAGEFILE_ERROR_INVALID_FILEROLE', 38); |
/** |
* Error code when a file in the filelist has no role |
*/ |
define('PEAR_PACKAGEFILE_ERROR_NO_FILEROLE', 39); |
/** |
* Error code when analyzing a php source file that has parse errors |
*/ |
define('PEAR_PACKAGEFILE_ERROR_INVALID_PHPFILE', 40); |
/** |
* Error code when analyzing a php source file reveals a source element |
* without a package name prefix |
*/ |
define('PEAR_PACKAGEFILE_ERROR_NO_PNAME_PREFIX', 41); |
/** |
* Error code when an unknown channel is specified |
*/ |
define('PEAR_PACKAGEFILE_ERROR_UNKNOWN_CHANNEL', 42); |
/** |
* Error code when no files are found in the filelist |
*/ |
define('PEAR_PACKAGEFILE_ERROR_NO_FILES', 43); |
/** |
* Error code when a file is not valid php according to _analyzeSourceCode() |
*/ |
define('PEAR_PACKAGEFILE_ERROR_INVALID_FILE', 44); |
/** |
* Error code when the channel validator returns an error or warning |
*/ |
define('PEAR_PACKAGEFILE_ERROR_CHANNELVAL', 45); |
/** |
* Error code when a php5 package is packaged in php4 (analysis doesn't work) |
*/ |
define('PEAR_PACKAGEFILE_ERROR_PHP5', 46); |
/** |
* Error code when a file is listed in package.xml but does not exist |
*/ |
define('PEAR_PACKAGEFILE_ERROR_FILE_NOTFOUND', 47); |
/** |
* Error code when a <dep type="php" rel="not"... is encountered (use rel="ne") |
*/ |
define('PEAR_PACKAGEFILE_PHP_NO_NOT', 48); |
/** |
* Error code when a package.xml contains non-ISO-8859-1 characters |
*/ |
define('PEAR_PACKAGEFILE_ERROR_NON_ISO_CHARS', 49); |
/** |
* Error code when a dependency is not a 'has' relation, but has no version |
*/ |
define('PEAR_PACKAGEFILE_ERROR_NO_DEPPHPVERSION', 50); |
/** |
* Error code when a package has no lead developer |
*/ |
define('PEAR_PACKAGEFILE_ERROR_NO_LEAD', 51); |
/** |
* Error code when a filename begins with "." |
*/ |
define('PEAR_PACKAGEFILE_ERROR_INVALID_FILENAME', 52); |
/** |
* package.xml encapsulator |
* @category pear |
* @package PEAR |
* @author Greg Beaver <cellog@php.net> |
* @copyright 1997-2009 The Authors |
* @license http://opensource.org/licenses/bsd-license.php New BSD License |
* @version Release: 1.10.1 |
* @link http://pear.php.net/package/PEAR |
* @since Class available since Release 1.4.0a1 |
*/ |
class PEAR_PackageFile_v1 |
{ |
/** |
* @access private |
* @var PEAR_ErrorStack |
* @access private |
*/ |
var $_stack; |
/** |
* A registry object, used to access the package name validation regex for non-standard channels |
* @var PEAR_Registry |
* @access private |
*/ |
var $_registry; |
/** |
* An object that contains a log method that matches PEAR_Common::log's signature |
* @var object |
* @access private |
*/ |
var $_logger; |
/** |
* Parsed package information |
* @var array |
* @access private |
*/ |
var $_packageInfo; |
/** |
* path to package.xml |
* @var string |
* @access private |
*/ |
var $_packageFile; |
/** |
* path to package .tgz or false if this is a local/extracted package.xml |
* @var string |
* @access private |
*/ |
var $_archiveFile; |
/** |
* @var int |
* @access private |
*/ |
var $_isValid = 0; |
/** |
* Determines whether this packagefile was initialized only with partial package info |
* |
* If this package file was constructed via parsing REST, it will only contain |
* |
* - package name |
* - channel name |
* - dependencies |
* @var boolean |
* @access private |
*/ |
var $_incomplete = true; |
/** |
* @param bool determines whether to return a PEAR_Error object, or use the PEAR_ErrorStack |
* @param string Name of Error Stack class to use. |
*/ |
function __construct() |
{ |
$this->_stack = new PEAR_ErrorStack('PEAR_PackageFile_v1'); |
$this->_stack->setErrorMessageTemplate($this->_getErrorMessage()); |
$this->_isValid = 0; |
} |
function installBinary($installer) |
{ |
return false; |
} |
function isExtension($name) |
{ |
return false; |
} |
function setConfig(&$config) |
{ |
$this->_config = &$config; |
$this->_registry = &$config->getRegistry(); |
} |
function setRequestedGroup() |
{ |
// placeholder |
} |
/** |
* For saving in the registry. |
* |
* Set the last version that was installed |
* @param string |
*/ |
function setLastInstalledVersion($version) |
{ |
$this->_packageInfo['_lastversion'] = $version; |
} |
/** |
* @return string|false |
*/ |
function getLastInstalledVersion() |
{ |
if (isset($this->_packageInfo['_lastversion'])) { |
return $this->_packageInfo['_lastversion']; |
} |
return false; |
} |
function getInstalledBinary() |
{ |
return false; |
} |
function listPostinstallScripts() |
{ |
return false; |
} |
function initPostinstallScripts() |
{ |
return false; |
} |
function setLogger(&$logger) |
{ |
if ($logger && (!is_object($logger) || !method_exists($logger, 'log'))) { |
return PEAR::raiseError('Logger must be compatible with PEAR_Common::log'); |
} |
$this->_logger = &$logger; |
} |
function setPackagefile($file, $archive = false) |
{ |
$this->_packageFile = $file; |
$this->_archiveFile = $archive ? $archive : $file; |
} |
function getPackageFile() |
{ |
return isset($this->_packageFile) ? $this->_packageFile : false; |
} |
function getPackageType() |
{ |
return 'php'; |
} |
function getArchiveFile() |
{ |
return $this->_archiveFile; |
} |
function packageInfo($field) |
{ |
if (!is_string($field) || empty($field) || |
!isset($this->_packageInfo[$field])) { |
return false; |
} |
return $this->_packageInfo[$field]; |
} |
function setDirtree($path) |
{ |
if (!isset($this->_packageInfo['dirtree'])) { |
$this->_packageInfo['dirtree'] = array(); |
} |
$this->_packageInfo['dirtree'][$path] = true; |
} |
function getDirtree() |
{ |
if (isset($this->_packageInfo['dirtree']) && count($this->_packageInfo['dirtree'])) { |
return $this->_packageInfo['dirtree']; |
} |
return false; |
} |
function resetDirtree() |
{ |
unset($this->_packageInfo['dirtree']); |
} |
function fromArray($pinfo) |
{ |
$this->_incomplete = false; |
$this->_packageInfo = $pinfo; |
} |
function isIncomplete() |
{ |
return $this->_incomplete; |
} |
function getChannel() |
{ |
return 'pear.php.net'; |
} |
function getUri() |
{ |
return false; |
} |
function getTime() |
{ |
return false; |
} |
function getExtends() |
{ |
if (isset($this->_packageInfo['extends'])) { |
return $this->_packageInfo['extends']; |
} |
return false; |
} |
/** |
* @return array |
*/ |
function toArray() |
{ |
if (!$this->validate(PEAR_VALIDATE_NORMAL)) { |
return false; |
} |
return $this->getArray(); |
} |
function getArray() |
{ |
return $this->_packageInfo; |
} |
function getName() |
{ |
return $this->getPackage(); |
} |
function getPackage() |
{ |
if (isset($this->_packageInfo['package'])) { |
return $this->_packageInfo['package']; |
} |
return false; |
} |
/** |
* WARNING - don't use this unless you know what you are doing |
*/ |
function setRawPackage($package) |
{ |
$this->_packageInfo['package'] = $package; |
} |
function setPackage($package) |
{ |
$this->_packageInfo['package'] = $package; |
$this->_isValid = false; |
} |
function getVersion() |
{ |
if (isset($this->_packageInfo['version'])) { |
return $this->_packageInfo['version']; |
} |
return false; |
} |
function setVersion($version) |
{ |
$this->_packageInfo['version'] = $version; |
$this->_isValid = false; |
} |
function clearMaintainers() |
{ |
unset($this->_packageInfo['maintainers']); |
} |
function getMaintainers() |
{ |
if (isset($this->_packageInfo['maintainers'])) { |
return $this->_packageInfo['maintainers']; |
} |
return false; |
} |
/** |
* Adds a new maintainer - no checking of duplicates is performed, use |
* updatemaintainer for that purpose. |
*/ |
function addMaintainer($role, $handle, $name, $email) |
{ |
$this->_packageInfo['maintainers'][] = |
array('handle' => $handle, 'role' => $role, 'email' => $email, 'name' => $name); |
$this->_isValid = false; |
} |
function updateMaintainer($role, $handle, $name, $email) |
{ |
$found = false; |
if (!isset($this->_packageInfo['maintainers']) || |
!is_array($this->_packageInfo['maintainers'])) { |
return $this->addMaintainer($role, $handle, $name, $email); |
} |
foreach ($this->_packageInfo['maintainers'] as $i => $maintainer) { |
if ($maintainer['handle'] == $handle) { |
$found = $i; |
break; |
} |
} |
if ($found !== false) { |
unset($this->_packageInfo['maintainers'][$found]); |
$this->_packageInfo['maintainers'] = |
array_values($this->_packageInfo['maintainers']); |
} |
$this->addMaintainer($role, $handle, $name, $email); |
} |
function deleteMaintainer($handle) |
{ |
$found = false; |
foreach ($this->_packageInfo['maintainers'] as $i => $maintainer) { |
if ($maintainer['handle'] == $handle) { |
$found = $i; |
break; |
} |
} |
if ($found !== false) { |
unset($this->_packageInfo['maintainers'][$found]); |
$this->_packageInfo['maintainers'] = |
array_values($this->_packageInfo['maintainers']); |
return true; |
} |
return false; |
} |
function getState() |
{ |
if (isset($this->_packageInfo['release_state'])) { |
return $this->_packageInfo['release_state']; |
} |
return false; |
} |
function setRawState($state) |
{ |
$this->_packageInfo['release_state'] = $state; |
} |
function setState($state) |
{ |
$this->_packageInfo['release_state'] = $state; |
$this->_isValid = false; |
} |
function getDate() |
{ |
if (isset($this->_packageInfo['release_date'])) { |
return $this->_packageInfo['release_date']; |
} |
return false; |
} |
function setDate($date) |
{ |
$this->_packageInfo['release_date'] = $date; |
$this->_isValid = false; |
} |
function getLicense() |
{ |
if (isset($this->_packageInfo['release_license'])) { |
return $this->_packageInfo['release_license']; |
} |
return false; |
} |
function setLicense($date) |
{ |
$this->_packageInfo['release_license'] = $date; |
$this->_isValid = false; |
} |
function getSummary() |
{ |
if (isset($this->_packageInfo['summary'])) { |
return $this->_packageInfo['summary']; |
} |
return false; |
} |
function setSummary($summary) |
{ |
$this->_packageInfo['summary'] = $summary; |
$this->_isValid = false; |
} |
function getDescription() |
{ |
if (isset($this->_packageInfo['description'])) { |
return $this->_packageInfo['description']; |
} |
return false; |
} |
function setDescription($desc) |
{ |
$this->_packageInfo['description'] = $desc; |
$this->_isValid = false; |
} |
function getNotes() |
{ |
if (isset($this->_packageInfo['release_notes'])) { |
return $this->_packageInfo['release_notes']; |
} |
return false; |
} |
function setNotes($notes) |
{ |
$this->_packageInfo['release_notes'] = $notes; |
$this->_isValid = false; |
} |
function getDeps() |
{ |
if (isset($this->_packageInfo['release_deps'])) { |
return $this->_packageInfo['release_deps']; |
} |
return false; |
} |
/** |
* Reset dependencies prior to adding new ones |
*/ |
function clearDeps() |
{ |
unset($this->_packageInfo['release_deps']); |
} |
function addPhpDep($version, $rel) |
{ |
$this->_isValid = false; |
$this->_packageInfo['release_deps'][] = |
array('type' => 'php', |
'rel' => $rel, |
'version' => $version); |
} |
function addPackageDep($name, $version, $rel, $optional = 'no') |
{ |
$this->_isValid = false; |
$dep = |
array('type' => 'pkg', |
'name' => $name, |
'rel' => $rel, |
'optional' => $optional); |
if ($rel != 'has' && $rel != 'not') { |
$dep['version'] = $version; |
} |
$this->_packageInfo['release_deps'][] = $dep; |
} |
function addExtensionDep($name, $version, $rel, $optional = 'no') |
{ |
$this->_isValid = false; |
$this->_packageInfo['release_deps'][] = |
array('type' => 'ext', |
'name' => $name, |
'rel' => $rel, |
'version' => $version, |
'optional' => $optional); |
} |
/** |
* WARNING - do not use this function directly unless you know what you're doing |
*/ |
function setDeps($deps) |
{ |
$this->_packageInfo['release_deps'] = $deps; |
} |
function hasDeps() |
{ |
return isset($this->_packageInfo['release_deps']) && |
count($this->_packageInfo['release_deps']); |
} |
function getDependencyGroup($group) |
{ |
return false; |
} |
function isCompatible($pf) |
{ |
return false; |
} |
function isSubpackageOf($p) |
{ |
return $p->isSubpackage($this); |
} |
function isSubpackage($p) |
{ |
return false; |
} |
function dependsOn($package, $channel) |
{ |
if (strtolower($channel) != 'pear.php.net') { |
return false; |
} |
if (!($deps = $this->getDeps())) { |
return false; |
} |
foreach ($deps as $dep) { |
if ($dep['type'] != 'pkg') { |
continue; |
} |
if (strtolower($dep['name']) == strtolower($package)) { |
return true; |
} |
} |
return false; |
} |
function getConfigureOptions() |
{ |
if (isset($this->_packageInfo['configure_options'])) { |
return $this->_packageInfo['configure_options']; |
} |
return false; |
} |
function hasConfigureOptions() |
{ |
return isset($this->_packageInfo['configure_options']) && |
count($this->_packageInfo['configure_options']); |
} |
function addConfigureOption($name, $prompt, $default = false) |
{ |
$o = array('name' => $name, 'prompt' => $prompt); |
if ($default !== false) { |
$o['default'] = $default; |
} |
if (!isset($this->_packageInfo['configure_options'])) { |
$this->_packageInfo['configure_options'] = array(); |
} |
$this->_packageInfo['configure_options'][] = $o; |
} |
function clearConfigureOptions() |
{ |
unset($this->_packageInfo['configure_options']); |
} |
function getProvides() |
{ |
if (isset($this->_packageInfo['provides'])) { |
return $this->_packageInfo['provides']; |
} |
return false; |
} |
function getProvidesExtension() |
{ |
return false; |
} |
function addFile($dir, $file, $attrs) |
{ |
$dir = preg_replace(array('!\\\\+!', '!/+!'), array('/', '/'), $dir); |
if ($dir == '/' || $dir == '') { |
$dir = ''; |
} else { |
$dir .= '/'; |
} |
$file = $dir . $file; |
$file = preg_replace('![\\/]+!', '/', $file); |
$this->_packageInfo['filelist'][$file] = $attrs; |
} |
function getInstallationFilelist() |
{ |
return $this->getFilelist(); |
} |
function getFilelist() |
{ |
if (isset($this->_packageInfo['filelist'])) { |
return $this->_packageInfo['filelist']; |
} |
return false; |
} |
function setFileAttribute($file, $attr, $value) |
{ |
$this->_packageInfo['filelist'][$file][$attr] = $value; |
} |
function resetFilelist() |
{ |
$this->_packageInfo['filelist'] = array(); |
} |
function setInstalledAs($file, $path) |
{ |
if ($path) { |
return $this->_packageInfo['filelist'][$file]['installed_as'] = $path; |
} |
unset($this->_packageInfo['filelist'][$file]['installed_as']); |
} |
function installedFile($file, $atts) |
{ |
if (isset($this->_packageInfo['filelist'][$file])) { |
$this->_packageInfo['filelist'][$file] = |
array_merge($this->_packageInfo['filelist'][$file], $atts); |
} else { |
$this->_packageInfo['filelist'][$file] = $atts; |
} |
} |
function getChangelog() |
{ |
if (isset($this->_packageInfo['changelog'])) { |
return $this->_packageInfo['changelog']; |
} |
return false; |
} |
function getPackagexmlVersion() |
{ |
return '1.0'; |
} |
/** |
* Wrapper to {@link PEAR_ErrorStack::getErrors()} |
* @param boolean determines whether to purge the error stack after retrieving |
* @return array |
*/ |
function getValidationWarnings($purge = true) |
{ |
return $this->_stack->getErrors($purge); |
} |
// }}} |
/** |
* Validation error. Also marks the object contents as invalid |
* @param error code |
* @param array error information |
* @access private |
*/ |
function _validateError($code, $params = array()) |
{ |
$this->_stack->push($code, 'error', $params, false, false, debug_backtrace()); |
$this->_isValid = false; |
} |
/** |
* Validation warning. Does not mark the object contents invalid. |
* @param error code |
* @param array error information |
* @access private |
*/ |
function _validateWarning($code, $params = array()) |
{ |
$this->_stack->push($code, 'warning', $params, false, false, debug_backtrace()); |
} |
/** |
* @param integer error code |
* @access protected |
*/ |
function _getErrorMessage() |
{ |
return array( |
PEAR_PACKAGEFILE_ERROR_NO_NAME => |
'Missing Package Name', |
PEAR_PACKAGEFILE_ERROR_NO_SUMMARY => |
'No summary found', |
PEAR_PACKAGEFILE_ERROR_MULTILINE_SUMMARY => |
'Summary should be on one line', |
PEAR_PACKAGEFILE_ERROR_NO_DESCRIPTION => |
'Missing description', |
PEAR_PACKAGEFILE_ERROR_NO_LICENSE => |
'Missing license', |
PEAR_PACKAGEFILE_ERROR_NO_VERSION => |
'No release version found', |
PEAR_PACKAGEFILE_ERROR_NO_STATE => |
'No release state found', |
PEAR_PACKAGEFILE_ERROR_NO_DATE => |
'No release date found', |
PEAR_PACKAGEFILE_ERROR_NO_NOTES => |
'No release notes found', |
PEAR_PACKAGEFILE_ERROR_NO_LEAD => |
'Package must have at least one lead maintainer', |
PEAR_PACKAGEFILE_ERROR_NO_MAINTAINERS => |
'No maintainers found, at least one must be defined', |
PEAR_PACKAGEFILE_ERROR_NO_MAINTHANDLE => |
'Maintainer %index% has no handle (user ID at channel server)', |
PEAR_PACKAGEFILE_ERROR_NO_MAINTROLE => |
'Maintainer %index% has no role', |
PEAR_PACKAGEFILE_ERROR_NO_MAINTNAME => |
'Maintainer %index% has no name', |
PEAR_PACKAGEFILE_ERROR_NO_MAINTEMAIL => |
'Maintainer %index% has no email', |
PEAR_PACKAGEFILE_ERROR_NO_DEPNAME => |
'Dependency %index% is not a php dependency, and has no name', |
PEAR_PACKAGEFILE_ERROR_NO_DEPREL => |
'Dependency %index% has no relation (rel)', |
PEAR_PACKAGEFILE_ERROR_NO_DEPTYPE => |
'Dependency %index% has no type', |
PEAR_PACKAGEFILE_ERROR_DEPNAME_IGNORED => |
'PHP Dependency %index% has a name attribute of "%name%" which will be' . |
' ignored!', |
PEAR_PACKAGEFILE_ERROR_NO_DEPVERSION => |
'Dependency %index% is not a rel="has" or rel="not" dependency, ' . |
'and has no version', |
PEAR_PACKAGEFILE_ERROR_NO_DEPPHPVERSION => |
'Dependency %index% is a type="php" dependency, ' . |
'and has no version', |
PEAR_PACKAGEFILE_ERROR_DEPVERSION_IGNORED => |
'Dependency %index% is a rel="%rel%" dependency, versioning is ignored', |
PEAR_PACKAGEFILE_ERROR_INVALID_DEPOPTIONAL => |
'Dependency %index% has invalid optional value "%opt%", should be yes or no', |
PEAR_PACKAGEFILE_PHP_NO_NOT => |
'Dependency %index%: php dependencies cannot use "not" rel, use "ne"' . |
' to exclude specific versions', |
PEAR_PACKAGEFILE_ERROR_NO_CONFNAME => |
'Configure Option %index% has no name', |
PEAR_PACKAGEFILE_ERROR_NO_CONFPROMPT => |
'Configure Option %index% has no prompt', |
PEAR_PACKAGEFILE_ERROR_NO_FILES => |
'No files in <filelist> section of package.xml', |
PEAR_PACKAGEFILE_ERROR_NO_FILEROLE => |
'File "%file%" has no role, expecting one of "%roles%"', |
PEAR_PACKAGEFILE_ERROR_INVALID_FILEROLE => |
'File "%file%" has invalid role "%role%", expecting one of "%roles%"', |
PEAR_PACKAGEFILE_ERROR_INVALID_FILENAME => |
'File "%file%" cannot start with ".", cannot package or install', |
PEAR_PACKAGEFILE_ERROR_INVALID_PHPFILE => |
'Parser error: invalid PHP found in file "%file%"', |
PEAR_PACKAGEFILE_ERROR_NO_PNAME_PREFIX => |
'in %file%: %type% "%name%" not prefixed with package name "%package%"', |
PEAR_PACKAGEFILE_ERROR_INVALID_FILE => |
'Parser error: invalid PHP file "%file%"', |
PEAR_PACKAGEFILE_ERROR_CHANNELVAL => |
'Channel validator error: field "%field%" - %reason%', |
PEAR_PACKAGEFILE_ERROR_PHP5 => |
'Error, PHP5 token encountered in %file%, analysis should be in PHP5', |
PEAR_PACKAGEFILE_ERROR_FILE_NOTFOUND => |
'File "%file%" in package.xml does not exist', |
PEAR_PACKAGEFILE_ERROR_NON_ISO_CHARS => |
'Package.xml contains non-ISO-8859-1 characters, and may not validate', |
); |
} |
/** |
* Validate XML package definition file. |
* |
* @access public |
* @return boolean |
*/ |
function validate($state = PEAR_VALIDATE_NORMAL, $nofilechecking = false) |
{ |
if (($this->_isValid & $state) == $state) { |
return true; |
} |
$this->_isValid = true; |
$info = $this->_packageInfo; |
if (empty($info['package'])) { |
$this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_NAME); |
$this->_packageName = $pn = 'unknown'; |
} else { |
$this->_packageName = $pn = $info['package']; |
} |
if (empty($info['summary'])) { |
$this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_SUMMARY); |
} elseif (strpos(trim($info['summary']), "\n") !== false) { |
$this->_validateWarning(PEAR_PACKAGEFILE_ERROR_MULTILINE_SUMMARY, |
array('summary' => $info['summary'])); |
} |
if (empty($info['description'])) { |
$this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_DESCRIPTION); |
} |
if (empty($info['release_license'])) { |
$this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_LICENSE); |
} |
if (empty($info['version'])) { |
$this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_VERSION); |
} |
if (empty($info['release_state'])) { |
$this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_STATE); |
} |
if (empty($info['release_date'])) { |
$this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_DATE); |
} |
if (empty($info['release_notes'])) { |
$this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_NOTES); |
} |
if (empty($info['maintainers'])) { |
$this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_MAINTAINERS); |
} else { |
$haslead = false; |
$i = 1; |
foreach ($info['maintainers'] as $m) { |
if (empty($m['handle'])) { |
$this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_MAINTHANDLE, |
array('index' => $i)); |
} |
if (empty($m['role'])) { |
$this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_MAINTROLE, |
array('index' => $i, 'roles' => PEAR_Common::getUserRoles())); |
} elseif ($m['role'] == 'lead') { |
$haslead = true; |
} |
if (empty($m['name'])) { |
$this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_MAINTNAME, |
array('index' => $i)); |
} |
if (empty($m['email'])) { |
$this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_MAINTEMAIL, |
array('index' => $i)); |
} |
$i++; |
} |
if (!$haslead) { |
$this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_LEAD); |
} |
} |
if (!empty($info['release_deps'])) { |
$i = 1; |
foreach ($info['release_deps'] as $d) { |
if (!isset($d['type']) || empty($d['type'])) { |
$this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_DEPTYPE, |
array('index' => $i, 'types' => PEAR_Common::getDependencyTypes())); |
continue; |
} |
if (!isset($d['rel']) || empty($d['rel'])) { |
$this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_DEPREL, |
array('index' => $i, 'rels' => PEAR_Common::getDependencyRelations())); |
continue; |
} |
if (!empty($d['optional'])) { |
if (!in_array($d['optional'], array('yes', 'no'))) { |
$this->_validateError(PEAR_PACKAGEFILE_ERROR_INVALID_DEPOPTIONAL, |
array('index' => $i, 'opt' => $d['optional'])); |
} |
} |
if ($d['rel'] != 'has' && $d['rel'] != 'not' && empty($d['version'])) { |
$this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_DEPVERSION, |
array('index' => $i)); |
} elseif (($d['rel'] == 'has' || $d['rel'] == 'not') && !empty($d['version'])) { |
$this->_validateWarning(PEAR_PACKAGEFILE_ERROR_DEPVERSION_IGNORED, |
array('index' => $i, 'rel' => $d['rel'])); |
} |
if ($d['type'] == 'php' && !empty($d['name'])) { |
$this->_validateWarning(PEAR_PACKAGEFILE_ERROR_DEPNAME_IGNORED, |
array('index' => $i, 'name' => $d['name'])); |
} elseif ($d['type'] != 'php' && empty($d['name'])) { |
$this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_DEPNAME, |
array('index' => $i)); |
} |
if ($d['type'] == 'php' && empty($d['version'])) { |
$this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_DEPPHPVERSION, |
array('index' => $i)); |
} |
if (($d['rel'] == 'not') && ($d['type'] == 'php')) { |
$this->_validateError(PEAR_PACKAGEFILE_PHP_NO_NOT, |
array('index' => $i)); |
} |
$i++; |
} |
} |
if (!empty($info['configure_options'])) { |
$i = 1; |
foreach ($info['configure_options'] as $c) { |
if (empty($c['name'])) { |
$this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_CONFNAME, |
array('index' => $i)); |
} |
if (empty($c['prompt'])) { |
$this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_CONFPROMPT, |
array('index' => $i)); |
} |
$i++; |
} |
} |
if (empty($info['filelist'])) { |
$this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_FILES); |
$errors[] = 'no files'; |
} else { |
foreach ($info['filelist'] as $file => $fa) { |
if (empty($fa['role'])) { |
$this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_FILEROLE, |
array('file' => $file, 'roles' => PEAR_Common::getFileRoles())); |
continue; |
} elseif (!in_array($fa['role'], PEAR_Common::getFileRoles())) { |
$this->_validateError(PEAR_PACKAGEFILE_ERROR_INVALID_FILEROLE, |
array('file' => $file, 'role' => $fa['role'], 'roles' => PEAR_Common::getFileRoles())); |
} |
if (preg_match('~/\.\.?(/|\\z)|^\.\.?/~', str_replace('\\', '/', $file))) { |
// file contains .. parent directory or . cur directory references |
$this->_validateError(PEAR_PACKAGEFILE_ERROR_INVALID_FILENAME, |
array('file' => $file)); |
} |
if (isset($fa['install-as']) && |
preg_match('~/\.\.?(/|\\z)|^\.\.?/~', |
str_replace('\\', '/', $fa['install-as']))) { |
// install-as contains .. parent directory or . cur directory references |
$this->_validateError(PEAR_PACKAGEFILE_ERROR_INVALID_FILENAME, |
array('file' => $file . ' [installed as ' . $fa['install-as'] . ']')); |
} |
if (isset($fa['baseinstalldir']) && |
preg_match('~/\.\.?(/|\\z)|^\.\.?/~', |
str_replace('\\', '/', $fa['baseinstalldir']))) { |
// install-as contains .. parent directory or . cur directory references |
$this->_validateError(PEAR_PACKAGEFILE_ERROR_INVALID_FILENAME, |
array('file' => $file . ' [baseinstalldir ' . $fa['baseinstalldir'] . ']')); |
} |
} |
} |
if (isset($this->_registry) && $this->_isValid) { |
$chan = $this->_registry->getChannel('pear.php.net'); |
if (PEAR::isError($chan)) { |
$this->_validateError(PEAR_PACKAGEFILE_ERROR_CHANNELVAL, $chan->getMessage()); |
return $this->_isValid = 0; |
} |
$validator = $chan->getValidationObject(); |
$validator->setPackageFile($this); |
$validator->validate($state); |
$failures = $validator->getFailures(); |
foreach ($failures['errors'] as $error) { |
$this->_validateError(PEAR_PACKAGEFILE_ERROR_CHANNELVAL, $error); |
} |
foreach ($failures['warnings'] as $warning) { |
$this->_validateWarning(PEAR_PACKAGEFILE_ERROR_CHANNELVAL, $warning); |
} |
} |
if ($this->_isValid && $state == PEAR_VALIDATE_PACKAGING && !$nofilechecking) { |
if ($this->_analyzePhpFiles()) { |
$this->_isValid = true; |
} |
} |
if ($this->_isValid) { |
return $this->_isValid = $state; |
} |
return $this->_isValid = 0; |
} |
function _analyzePhpFiles() |
{ |
if (!$this->_isValid) { |
return false; |
} |
if (!isset($this->_packageFile)) { |
return false; |
} |
$dir_prefix = dirname($this->_packageFile); |
$common = new PEAR_Common; |
$log = isset($this->_logger) ? array(&$this->_logger, 'log') : |
array($common, 'log'); |
$info = $this->getFilelist(); |
foreach ($info as $file => $fa) { |
if (!file_exists($dir_prefix . DIRECTORY_SEPARATOR . $file)) { |
$this->_validateError(PEAR_PACKAGEFILE_ERROR_FILE_NOTFOUND, |
array('file' => realpath($dir_prefix) . DIRECTORY_SEPARATOR . $file)); |
continue; |
} |
if ($fa['role'] == 'php' && $dir_prefix) { |
call_user_func_array($log, array(1, "Analyzing $file")); |
$srcinfo = $this->_analyzeSourceCode($dir_prefix . DIRECTORY_SEPARATOR . $file); |
if ($srcinfo) { |
$this->_buildProvidesArray($srcinfo); |
} |
} |
} |
$this->_packageName = $pn = $this->getPackage(); |
$pnl = strlen($pn); |
if (isset($this->_packageInfo['provides'])) { |
foreach ((array) $this->_packageInfo['provides'] as $key => $what) { |
if (isset($what['explicit'])) { |
// skip conformance checks if the provides entry is |
// specified in the package.xml file |
continue; |
} |
extract($what); |
if ($type == 'class') { |
if (!strncasecmp($name, $pn, $pnl)) { |
continue; |
} |
$this->_validateWarning(PEAR_PACKAGEFILE_ERROR_NO_PNAME_PREFIX, |
array('file' => $file, 'type' => $type, 'name' => $name, 'package' => $pn)); |
} elseif ($type == 'function') { |
if (strstr($name, '::') || !strncasecmp($name, $pn, $pnl)) { |
continue; |
} |
$this->_validateWarning(PEAR_PACKAGEFILE_ERROR_NO_PNAME_PREFIX, |
array('file' => $file, 'type' => $type, 'name' => $name, 'package' => $pn)); |
} |
} |
} |
return $this->_isValid; |
} |
/** |
* Get the default xml generator object |
* |
* @return PEAR_PackageFile_Generator_v1 |
*/ |
function &getDefaultGenerator() |
{ |
if (!class_exists('PEAR_PackageFile_Generator_v1')) { |
require_once 'PEAR/PackageFile/Generator/v1.php'; |
} |
$a = new PEAR_PackageFile_Generator_v1($this); |
return $a; |
} |
/** |
* Get the contents of a file listed within the package.xml |
* @param string |
* @return string |
*/ |
function getFileContents($file) |
{ |
if ($this->_archiveFile == $this->_packageFile) { // unpacked |
$dir = dirname($this->_packageFile); |
$file = $dir . DIRECTORY_SEPARATOR . $file; |
$file = str_replace(array('/', '\\'), |
array(DIRECTORY_SEPARATOR, DIRECTORY_SEPARATOR), $file); |
if (file_exists($file) && is_readable($file)) { |
return implode('', file($file)); |
} |
} else { // tgz |
if (!class_exists('Archive_Tar')) { |
require_once 'Archive/Tar.php'; |
} |
$tar = new Archive_Tar($this->_archiveFile); |
$tar->pushErrorHandling(PEAR_ERROR_RETURN); |
if ($file != 'package.xml' && $file != 'package2.xml') { |
$file = $this->getPackage() . '-' . $this->getVersion() . '/' . $file; |
} |
$file = $tar->extractInString($file); |
$tar->popErrorHandling(); |
if (PEAR::isError($file)) { |
return PEAR::raiseError("Cannot locate file '$file' in archive"); |
} |
return $file; |
} |
} |
// {{{ analyzeSourceCode() |
/** |
* Analyze the source code of the given PHP file |
* |
* @param string Filename of the PHP file |
* @return mixed |
* @access private |
*/ |
function _analyzeSourceCode($file) |
{ |
if (!function_exists("token_get_all")) { |
return false; |
} |
if (!defined('T_DOC_COMMENT')) { |
define('T_DOC_COMMENT', T_COMMENT); |
} |
if (!defined('T_INTERFACE')) { |
define('T_INTERFACE', -1); |
} |
if (!defined('T_IMPLEMENTS')) { |
define('T_IMPLEMENTS', -1); |
} |
if (!$fp = @fopen($file, "r")) { |
return false; |
} |
fclose($fp); |
$contents = file_get_contents($file); |
$tokens = token_get_all($contents); |
/* |
for ($i = 0; $i < sizeof($tokens); $i++) { |
@list($token, $data) = $tokens[$i]; |
if (is_string($token)) { |
var_dump($token); |
} else { |
print token_name($token) . ' '; |
var_dump(rtrim($data)); |
} |
} |
*/ |
$look_for = 0; |
$paren_level = 0; |
$bracket_level = 0; |
$brace_level = 0; |
$lastphpdoc = ''; |
$current_class = ''; |
$current_interface = ''; |
$current_class_level = -1; |
$current_function = ''; |
$current_function_level = -1; |
$declared_classes = array(); |
$declared_interfaces = array(); |
$declared_functions = array(); |
$declared_methods = array(); |
$used_classes = array(); |
$used_functions = array(); |
$extends = array(); |
$implements = array(); |
$nodeps = array(); |
$inquote = false; |
$interface = false; |
for ($i = 0; $i < sizeof($tokens); $i++) { |
if (is_array($tokens[$i])) { |
list($token, $data) = $tokens[$i]; |
} else { |
$token = $tokens[$i]; |
$data = ''; |
} |
if ($inquote) { |
if ($token != '"' && $token != T_END_HEREDOC) { |
continue; |
} else { |
$inquote = false; |
continue; |
} |
} |
switch ($token) { |
case T_WHITESPACE : |
continue; |
case ';': |
if ($interface) { |
$current_function = ''; |
$current_function_level = -1; |
} |
break; |
case '"': |
case T_START_HEREDOC: |
$inquote = true; |
break; |
case T_CURLY_OPEN: |
case T_DOLLAR_OPEN_CURLY_BRACES: |
case '{': $brace_level++; continue 2; |
case '}': |
$brace_level--; |
if ($current_class_level == $brace_level) { |
$current_class = ''; |
$current_class_level = -1; |
} |
if ($current_function_level == $brace_level) { |
$current_function = ''; |
$current_function_level = -1; |
} |
continue 2; |
case '[': $bracket_level++; continue 2; |
case ']': $bracket_level--; continue 2; |
case '(': $paren_level++; continue 2; |
case ')': $paren_level--; continue 2; |
case T_INTERFACE: |
$interface = true; |
case T_CLASS: |
if (($current_class_level != -1) || ($current_function_level != -1)) { |
$this->_validateError(PEAR_PACKAGEFILE_ERROR_INVALID_PHPFILE, |
array('file' => $file)); |
return false; |
} |
case T_FUNCTION: |
case T_NEW: |
case T_EXTENDS: |
case T_IMPLEMENTS: |
$look_for = $token; |
continue 2; |
case T_STRING: |
if ($look_for == T_CLASS) { |
$current_class = $data; |
$current_class_level = $brace_level; |
$declared_classes[] = $current_class; |
} elseif ($look_for == T_INTERFACE) { |
$current_interface = $data; |
$current_class_level = $brace_level; |
$declared_interfaces[] = $current_interface; |
} elseif ($look_for == T_IMPLEMENTS) { |
$implements[$current_class] = $data; |
} elseif ($look_for == T_EXTENDS) { |
$extends[$current_class] = $data; |
} elseif ($look_for == T_FUNCTION) { |
if ($current_class) { |
$current_function = "$current_class::$data"; |
$declared_methods[$current_class][] = $data; |
} elseif ($current_interface) { |
$current_function = "$current_interface::$data"; |
$declared_methods[$current_interface][] = $data; |
} else { |
$current_function = $data; |
$declared_functions[] = $current_function; |
} |
$current_function_level = $brace_level; |
$m = array(); |
} elseif ($look_for == T_NEW) { |
$used_classes[$data] = true; |
} |
$look_for = 0; |
continue 2; |
case T_VARIABLE: |
$look_for = 0; |
continue 2; |
case T_DOC_COMMENT: |
case T_COMMENT: |
if (preg_match('!^/\*\*\s!', $data)) { |
$lastphpdoc = $data; |
if (preg_match_all('/@nodep\s+(\S+)/', $lastphpdoc, $m)) { |
$nodeps = array_merge($nodeps, $m[1]); |
} |
} |
continue 2; |
case T_DOUBLE_COLON: |
if (!($tokens[$i - 1][0] == T_WHITESPACE || $tokens[$i - 1][0] == T_STRING)) { |
$this->_validateError(PEAR_PACKAGEFILE_ERROR_INVALID_PHPFILE, |
array('file' => $file)); |
return false; |
} |
$class = $tokens[$i - 1][1]; |
if (strtolower($class) != 'parent') { |
$used_classes[$class] = true; |
} |
continue 2; |
} |
} |
return array( |
"source_file" => $file, |
"declared_classes" => $declared_classes, |
"declared_interfaces" => $declared_interfaces, |
"declared_methods" => $declared_methods, |
"declared_functions" => $declared_functions, |
"used_classes" => array_diff(array_keys($used_classes), $nodeps), |
"inheritance" => $extends, |
"implements" => $implements, |
); |
} |
/** |
* Build a "provides" array from data returned by |
* analyzeSourceCode(). The format of the built array is like |
* this: |
* |
* array( |
* 'class;MyClass' => 'array('type' => 'class', 'name' => 'MyClass'), |
* ... |
* ) |
* |
* |
* @param array $srcinfo array with information about a source file |
* as returned by the analyzeSourceCode() method. |
* |
* @return void |
* |
* @access private |
* |
*/ |
function _buildProvidesArray($srcinfo) |
{ |
if (!$this->_isValid) { |
return false; |
} |
$file = basename($srcinfo['source_file']); |
$pn = $this->getPackage(); |
$pnl = strlen($pn); |
foreach ($srcinfo['declared_classes'] as $class) { |
$key = "class;$class"; |
if (isset($this->_packageInfo['provides'][$key])) { |
continue; |
} |
$this->_packageInfo['provides'][$key] = |
array('file'=> $file, 'type' => 'class', 'name' => $class); |
if (isset($srcinfo['inheritance'][$class])) { |
$this->_packageInfo['provides'][$key]['extends'] = |
$srcinfo['inheritance'][$class]; |
} |
} |
foreach ($srcinfo['declared_methods'] as $class => $methods) { |
foreach ($methods as $method) { |
$function = "$class::$method"; |
$key = "function;$function"; |
if ($method{0} == '_' || !strcasecmp($method, $class) || |
isset($this->_packageInfo['provides'][$key])) { |
continue; |
} |
$this->_packageInfo['provides'][$key] = |
array('file'=> $file, 'type' => 'function', 'name' => $function); |
} |
} |
foreach ($srcinfo['declared_functions'] as $function) { |
$key = "function;$function"; |
if ($function{0} == '_' || isset($this->_packageInfo['provides'][$key])) { |
continue; |
} |
if (!strstr($function, '::') && strncasecmp($function, $pn, $pnl)) { |
$warnings[] = "in1 " . $file . ": function \"$function\" not prefixed with package name \"$pn\""; |
} |
$this->_packageInfo['provides'][$key] = |
array('file'=> $file, 'type' => 'function', 'name' => $function); |
} |
} |
// }}} |
} |
?> |
/branches/v1.3-critias/bibliotheque/pear/PEAR/PackageFile/v2.php |
---|
New file |
0,0 → 1,2060 |
<?php |
/** |
* PEAR_PackageFile_v2, package.xml version 2.0 |
* |
* PHP versions 4 and 5 |
* |
* @category pear |
* @package PEAR |
* @author Greg Beaver <cellog@php.net> |
* @copyright 1997-2009 The Authors |
* @license http://opensource.org/licenses/bsd-license.php New BSD License |
* @link http://pear.php.net/package/PEAR |
* @since File available since Release 1.4.0a1 |
*/ |
/** |
* For error handling |
*/ |
require_once 'PEAR/ErrorStack.php'; |
/** |
* @category pear |
* @package PEAR |
* @author Greg Beaver <cellog@php.net> |
* @copyright 1997-2009 The Authors |
* @license http://opensource.org/licenses/bsd-license.php New BSD License |
* @version Release: 1.10.1 |
* @link http://pear.php.net/package/PEAR |
* @since Class available since Release 1.4.0a1 |
*/ |
class PEAR_PackageFile_v2 |
{ |
/** |
* Parsed package information |
* @var array |
* @access private |
*/ |
var $_packageInfo = array(); |
/** |
* path to package .tgz or false if this is a local/extracted package.xml |
* @var string|false |
* @access private |
*/ |
var $_archiveFile; |
/** |
* path to package .xml or false if this is an abstract parsed-from-string xml |
* @var string|false |
* @access private |
*/ |
var $_packageFile; |
/** |
* This is used by file analysis routines to log progress information |
* @var PEAR_Common |
* @access protected |
*/ |
var $_logger; |
/** |
* This is set to the highest validation level that has been validated |
* |
* If the package.xml is invalid or unknown, this is set to 0. If |
* normal validation has occurred, this is set to PEAR_VALIDATE_NORMAL. If |
* downloading/installation validation has occurred it is set to PEAR_VALIDATE_DOWNLOADING |
* or INSTALLING, and so on up to PEAR_VALIDATE_PACKAGING. This allows validation |
* "caching" to occur, which is particularly important for package validation, so |
* that PHP files are not validated twice |
* @var int |
* @access private |
*/ |
var $_isValid = 0; |
/** |
* True if the filelist has been validated |
* @param bool |
*/ |
var $_filesValid = false; |
/** |
* @var PEAR_Registry |
* @access protected |
*/ |
var $_registry; |
/** |
* @var PEAR_Config |
* @access protected |
*/ |
var $_config; |
/** |
* Optional Dependency group requested for installation |
* @var string |
* @access private |
*/ |
var $_requestedGroup = false; |
/** |
* @var PEAR_ErrorStack |
* @access protected |
*/ |
var $_stack; |
/** |
* Namespace prefix used for tasks in this package.xml - use tasks: whenever possible |
*/ |
var $_tasksNs; |
/** |
* Determines whether this packagefile was initialized only with partial package info |
* |
* If this package file was constructed via parsing REST, it will only contain |
* |
* - package name |
* - channel name |
* - dependencies |
* @var boolean |
* @access private |
*/ |
var $_incomplete = true; |
/** |
* @var PEAR_PackageFile_v2_Validator |
*/ |
var $_v2Validator; |
/** |
* The constructor merely sets up the private error stack |
*/ |
function __construct() |
{ |
$this->_stack = new PEAR_ErrorStack('PEAR_PackageFile_v2', false, null); |
$this->_isValid = false; |
} |
/** |
* PHP 4 style constructor for backwards compatibility. |
* Used by PEAR_PackageFileManager2 |
*/ |
public function PEAR_PackageFile_v2() |
{ |
$this->__construct(); |
} |
/** |
* To make unit-testing easier |
* @param PEAR_Frontend_* |
* @param array options |
* @param PEAR_Config |
* @return PEAR_Downloader |
* @access protected |
*/ |
function &getPEARDownloader(&$i, $o, &$c) |
{ |
$z = new PEAR_Downloader($i, $o, $c); |
return $z; |
} |
/** |
* To make unit-testing easier |
* @param PEAR_Config |
* @param array options |
* @param array package name as returned from {@link PEAR_Registry::parsePackageName()} |
* @param int PEAR_VALIDATE_* constant |
* @return PEAR_Dependency2 |
* @access protected |
*/ |
function &getPEARDependency2(&$c, $o, $p, $s = PEAR_VALIDATE_INSTALLING) |
{ |
if (!class_exists('PEAR_Dependency2')) { |
require_once 'PEAR/Dependency2.php'; |
} |
$z = new PEAR_Dependency2($c, $o, $p, $s); |
return $z; |
} |
function getInstalledBinary() |
{ |
return isset($this->_packageInfo['#binarypackage']) ? $this->_packageInfo['#binarypackage'] : |
false; |
} |
/** |
* Installation of source package has failed, attempt to download and install the |
* binary version of this package. |
* @param PEAR_Installer |
* @return array|false |
*/ |
function installBinary(&$installer) |
{ |
if (!OS_WINDOWS) { |
$a = false; |
return $a; |
} |
if ($this->getPackageType() == 'extsrc' || $this->getPackageType() == 'zendextsrc') { |
$releasetype = $this->getPackageType() . 'release'; |
if (!is_array($installer->getInstallPackages())) { |
$a = false; |
return $a; |
} |
foreach ($installer->getInstallPackages() as $p) { |
if ($p->isExtension($this->_packageInfo['providesextension'])) { |
if ($p->getPackageType() != 'extsrc' && $p->getPackageType() != 'zendextsrc') { |
$a = false; |
return $a; // the user probably downloaded it separately |
} |
} |
} |
if (isset($this->_packageInfo[$releasetype]['binarypackage'])) { |
$installer->log(0, 'Attempting to download binary version of extension "' . |
$this->_packageInfo['providesextension'] . '"'); |
$params = $this->_packageInfo[$releasetype]['binarypackage']; |
if (!is_array($params) || !isset($params[0])) { |
$params = array($params); |
} |
if (isset($this->_packageInfo['channel'])) { |
foreach ($params as $i => $param) { |
$params[$i] = array('channel' => $this->_packageInfo['channel'], |
'package' => $param, 'version' => $this->getVersion()); |
} |
} |
$dl = &$this->getPEARDownloader($installer->ui, $installer->getOptions(), |
$installer->config); |
$verbose = $dl->config->get('verbose'); |
$dl->config->set('verbose', -1); |
foreach ($params as $param) { |
PEAR::pushErrorHandling(PEAR_ERROR_RETURN); |
$ret = $dl->download(array($param)); |
PEAR::popErrorHandling(); |
if (is_array($ret) && count($ret)) { |
break; |
} |
} |
$dl->config->set('verbose', $verbose); |
if (is_array($ret)) { |
if (count($ret) == 1) { |
$pf = $ret[0]->getPackageFile(); |
PEAR::pushErrorHandling(PEAR_ERROR_RETURN); |
$err = $installer->install($ret[0]); |
PEAR::popErrorHandling(); |
if (is_array($err)) { |
$this->_packageInfo['#binarypackage'] = $ret[0]->getPackage(); |
// "install" self, so all dependencies will work transparently |
$this->_registry->addPackage2($this); |
$installer->log(0, 'Download and install of binary extension "' . |
$this->_registry->parsedPackageNameToString( |
array('channel' => $pf->getChannel(), |
'package' => $pf->getPackage()), true) . '" successful'); |
$a = array($ret[0], $err); |
return $a; |
} |
$installer->log(0, 'Download and install of binary extension "' . |
$this->_registry->parsedPackageNameToString( |
array('channel' => $pf->getChannel(), |
'package' => $pf->getPackage()), true) . '" failed'); |
} |
} |
} |
} |
$a = false; |
return $a; |
} |
/** |
* @return string|false Extension name |
*/ |
function getProvidesExtension() |
{ |
if (in_array($this->getPackageType(), |
array('extsrc', 'extbin', 'zendextsrc', 'zendextbin'))) { |
if (isset($this->_packageInfo['providesextension'])) { |
return $this->_packageInfo['providesextension']; |
} |
} |
return false; |
} |
/** |
* @param string Extension name |
* @return bool |
*/ |
function isExtension($extension) |
{ |
if (in_array($this->getPackageType(), |
array('extsrc', 'extbin', 'zendextsrc', 'zendextbin'))) { |
return $this->_packageInfo['providesextension'] == $extension; |
} |
return false; |
} |
/** |
* Tests whether every part of the package.xml 1.0 is represented in |
* this package.xml 2.0 |
* @param PEAR_PackageFile_v1 |
* @return bool |
*/ |
function isEquivalent($pf1) |
{ |
if (!$pf1) { |
return true; |
} |
if ($this->getPackageType() == 'bundle') { |
return false; |
} |
$this->_stack->getErrors(true); |
if (!$pf1->validate(PEAR_VALIDATE_NORMAL)) { |
return false; |
} |
$pass = true; |
if ($pf1->getPackage() != $this->getPackage()) { |
$this->_differentPackage($pf1->getPackage()); |
$pass = false; |
} |
if ($pf1->getVersion() != $this->getVersion()) { |
$this->_differentVersion($pf1->getVersion()); |
$pass = false; |
} |
if (trim($pf1->getSummary()) != $this->getSummary()) { |
$this->_differentSummary($pf1->getSummary()); |
$pass = false; |
} |
if (preg_replace('/\s+/', '', $pf1->getDescription()) != |
preg_replace('/\s+/', '', $this->getDescription())) { |
$this->_differentDescription($pf1->getDescription()); |
$pass = false; |
} |
if ($pf1->getState() != $this->getState()) { |
$this->_differentState($pf1->getState()); |
$pass = false; |
} |
if (!strstr(preg_replace('/\s+/', '', $this->getNotes()), |
preg_replace('/\s+/', '', $pf1->getNotes()))) { |
$this->_differentNotes($pf1->getNotes()); |
$pass = false; |
} |
$mymaintainers = $this->getMaintainers(); |
$yourmaintainers = $pf1->getMaintainers(); |
for ($i1 = 0; $i1 < count($yourmaintainers); $i1++) { |
$reset = false; |
for ($i2 = 0; $i2 < count($mymaintainers); $i2++) { |
if ($mymaintainers[$i2]['handle'] == $yourmaintainers[$i1]['handle']) { |
if ($mymaintainers[$i2]['role'] != $yourmaintainers[$i1]['role']) { |
$this->_differentRole($mymaintainers[$i2]['handle'], |
$yourmaintainers[$i1]['role'], $mymaintainers[$i2]['role']); |
$pass = false; |
} |
if ($mymaintainers[$i2]['email'] != $yourmaintainers[$i1]['email']) { |
$this->_differentEmail($mymaintainers[$i2]['handle'], |
$yourmaintainers[$i1]['email'], $mymaintainers[$i2]['email']); |
$pass = false; |
} |
if ($mymaintainers[$i2]['name'] != $yourmaintainers[$i1]['name']) { |
$this->_differentName($mymaintainers[$i2]['handle'], |
$yourmaintainers[$i1]['name'], $mymaintainers[$i2]['name']); |
$pass = false; |
} |
unset($mymaintainers[$i2]); |
$mymaintainers = array_values($mymaintainers); |
unset($yourmaintainers[$i1]); |
$yourmaintainers = array_values($yourmaintainers); |
$reset = true; |
break; |
} |
} |
if ($reset) { |
$i1 = -1; |
} |
} |
$this->_unmatchedMaintainers($mymaintainers, $yourmaintainers); |
$filelist = $this->getFilelist(); |
foreach ($pf1->getFilelist() as $file => $atts) { |
if (!isset($filelist[$file])) { |
$this->_missingFile($file); |
$pass = false; |
} |
} |
return $pass; |
} |
function _differentPackage($package) |
{ |
$this->_stack->push(__FUNCTION__, 'error', array('package' => $package, |
'self' => $this->getPackage()), |
'package.xml 1.0 package "%package%" does not match "%self%"'); |
} |
function _differentVersion($version) |
{ |
$this->_stack->push(__FUNCTION__, 'error', array('version' => $version, |
'self' => $this->getVersion()), |
'package.xml 1.0 version "%version%" does not match "%self%"'); |
} |
function _differentState($state) |
{ |
$this->_stack->push(__FUNCTION__, 'error', array('state' => $state, |
'self' => $this->getState()), |
'package.xml 1.0 state "%state%" does not match "%self%"'); |
} |
function _differentRole($handle, $role, $selfrole) |
{ |
$this->_stack->push(__FUNCTION__, 'error', array('handle' => $handle, |
'role' => $role, 'self' => $selfrole), |
'package.xml 1.0 maintainer "%handle%" role "%role%" does not match "%self%"'); |
} |
function _differentEmail($handle, $email, $selfemail) |
{ |
$this->_stack->push(__FUNCTION__, 'error', array('handle' => $handle, |
'email' => $email, 'self' => $selfemail), |
'package.xml 1.0 maintainer "%handle%" email "%email%" does not match "%self%"'); |
} |
function _differentName($handle, $name, $selfname) |
{ |
$this->_stack->push(__FUNCTION__, 'error', array('handle' => $handle, |
'name' => $name, 'self' => $selfname), |
'package.xml 1.0 maintainer "%handle%" name "%name%" does not match "%self%"'); |
} |
function _unmatchedMaintainers($my, $yours) |
{ |
if ($my) { |
array_walk($my, create_function('&$i, $k', '$i = $i["handle"];')); |
$this->_stack->push(__FUNCTION__, 'error', array('handles' => $my), |
'package.xml 2.0 has unmatched extra maintainers "%handles%"'); |
} |
if ($yours) { |
array_walk($yours, create_function('&$i, $k', '$i = $i["handle"];')); |
$this->_stack->push(__FUNCTION__, 'error', array('handles' => $yours), |
'package.xml 1.0 has unmatched extra maintainers "%handles%"'); |
} |
} |
function _differentNotes($notes) |
{ |
$truncnotes = strlen($notes) < 25 ? $notes : substr($notes, 0, 24) . '...'; |
$truncmynotes = strlen($this->getNotes()) < 25 ? $this->getNotes() : |
substr($this->getNotes(), 0, 24) . '...'; |
$this->_stack->push(__FUNCTION__, 'error', array('notes' => $truncnotes, |
'self' => $truncmynotes), |
'package.xml 1.0 release notes "%notes%" do not match "%self%"'); |
} |
function _differentSummary($summary) |
{ |
$truncsummary = strlen($summary) < 25 ? $summary : substr($summary, 0, 24) . '...'; |
$truncmysummary = strlen($this->getsummary()) < 25 ? $this->getSummary() : |
substr($this->getsummary(), 0, 24) . '...'; |
$this->_stack->push(__FUNCTION__, 'error', array('summary' => $truncsummary, |
'self' => $truncmysummary), |
'package.xml 1.0 summary "%summary%" does not match "%self%"'); |
} |
function _differentDescription($description) |
{ |
$truncdescription = trim(strlen($description) < 25 ? $description : substr($description, 0, 24) . '...'); |
$truncmydescription = trim(strlen($this->getDescription()) < 25 ? $this->getDescription() : |
substr($this->getdescription(), 0, 24) . '...'); |
$this->_stack->push(__FUNCTION__, 'error', array('description' => $truncdescription, |
'self' => $truncmydescription), |
'package.xml 1.0 description "%description%" does not match "%self%"'); |
} |
function _missingFile($file) |
{ |
$this->_stack->push(__FUNCTION__, 'error', array('file' => $file), |
'package.xml 1.0 file "%file%" is not present in <contents>'); |
} |
/** |
* WARNING - do not use this function unless you know what you're doing |
*/ |
function setRawState($state) |
{ |
if (!isset($this->_packageInfo['stability'])) { |
$this->_packageInfo['stability'] = array(); |
} |
$this->_packageInfo['stability']['release'] = $state; |
} |
/** |
* WARNING - do not use this function unless you know what you're doing |
*/ |
function setRawCompatible($compatible) |
{ |
$this->_packageInfo['compatible'] = $compatible; |
} |
/** |
* WARNING - do not use this function unless you know what you're doing |
*/ |
function setRawPackage($package) |
{ |
$this->_packageInfo['name'] = $package; |
} |
/** |
* WARNING - do not use this function unless you know what you're doing |
*/ |
function setRawChannel($channel) |
{ |
$this->_packageInfo['channel'] = $channel; |
} |
function setRequestedGroup($group) |
{ |
$this->_requestedGroup = $group; |
} |
function getRequestedGroup() |
{ |
if (isset($this->_requestedGroup)) { |
return $this->_requestedGroup; |
} |
return false; |
} |
/** |
* For saving in the registry. |
* |
* Set the last version that was installed |
* @param string |
*/ |
function setLastInstalledVersion($version) |
{ |
$this->_packageInfo['_lastversion'] = $version; |
} |
/** |
* @return string|false |
*/ |
function getLastInstalledVersion() |
{ |
if (isset($this->_packageInfo['_lastversion'])) { |
return $this->_packageInfo['_lastversion']; |
} |
return false; |
} |
/** |
* Determines whether this package.xml has post-install scripts or not |
* @return array|false |
*/ |
function listPostinstallScripts() |
{ |
$filelist = $this->getFilelist(); |
$contents = $this->getContents(); |
$contents = $contents['dir']['file']; |
if (!is_array($contents) || !isset($contents[0])) { |
$contents = array($contents); |
} |
$taskfiles = array(); |
foreach ($contents as $file) { |
$atts = $file['attribs']; |
unset($file['attribs']); |
if (count($file)) { |
$taskfiles[$atts['name']] = $file; |
} |
} |
$common = new PEAR_Common; |
$common->debug = $this->_config->get('verbose'); |
$this->_scripts = array(); |
$ret = array(); |
foreach ($taskfiles as $name => $tasks) { |
if (!isset($filelist[$name])) { |
// ignored files will not be in the filelist |
continue; |
} |
$atts = $filelist[$name]; |
foreach ($tasks as $tag => $raw) { |
$task = $this->getTask($tag); |
$task = new $task($this->_config, $common, PEAR_TASK_INSTALL); |
if ($task->isScript()) { |
$ret[] = $filelist[$name]['installed_as']; |
} |
} |
} |
if (count($ret)) { |
return $ret; |
} |
return false; |
} |
/** |
* Initialize post-install scripts for running |
* |
* This method can be used to detect post-install scripts, as the return value |
* indicates whether any exist |
* @return bool |
*/ |
function initPostinstallScripts() |
{ |
$filelist = $this->getFilelist(); |
$contents = $this->getContents(); |
$contents = $contents['dir']['file']; |
if (!is_array($contents) || !isset($contents[0])) { |
$contents = array($contents); |
} |
$taskfiles = array(); |
foreach ($contents as $file) { |
$atts = $file['attribs']; |
unset($file['attribs']); |
if (count($file)) { |
$taskfiles[$atts['name']] = $file; |
} |
} |
$common = new PEAR_Common; |
$common->debug = $this->_config->get('verbose'); |
$this->_scripts = array(); |
foreach ($taskfiles as $name => $tasks) { |
if (!isset($filelist[$name])) { |
// file was not installed due to installconditions |
continue; |
} |
$atts = $filelist[$name]; |
foreach ($tasks as $tag => $raw) { |
$taskname = $this->getTask($tag); |
$task = new $taskname($this->_config, $common, PEAR_TASK_INSTALL); |
if (!$task->isScript()) { |
continue; // scripts are only handled after installation |
} |
$lastversion = isset($this->_packageInfo['_lastversion']) ? |
$this->_packageInfo['_lastversion'] : null; |
$task->init($raw, $atts, $lastversion); |
$res = $task->startSession($this, $atts['installed_as']); |
if (!$res) { |
continue; // skip this file |
} |
if (PEAR::isError($res)) { |
return $res; |
} |
$assign = &$task; |
$this->_scripts[] = &$assign; |
} |
} |
if (count($this->_scripts)) { |
return true; |
} |
return false; |
} |
function runPostinstallScripts() |
{ |
if ($this->initPostinstallScripts()) { |
$ui = &PEAR_Frontend::singleton(); |
if ($ui) { |
$ui->runPostinstallScripts($this->_scripts, $this); |
} |
} |
} |
/** |
* Convert a recursive set of <dir> and <file> tags into a single <dir> tag with |
* <file> tags. |
*/ |
function flattenFilelist() |
{ |
if (isset($this->_packageInfo['bundle'])) { |
return; |
} |
$filelist = array(); |
if (isset($this->_packageInfo['contents']['dir']['dir'])) { |
$this->_getFlattenedFilelist($filelist, $this->_packageInfo['contents']['dir']); |
if (!isset($filelist[1])) { |
$filelist = $filelist[0]; |
} |
$this->_packageInfo['contents']['dir']['file'] = $filelist; |
unset($this->_packageInfo['contents']['dir']['dir']); |
} else { |
// else already flattened but check for baseinstalldir propagation |
if (isset($this->_packageInfo['contents']['dir']['attribs']['baseinstalldir'])) { |
if (isset($this->_packageInfo['contents']['dir']['file'][0])) { |
foreach ($this->_packageInfo['contents']['dir']['file'] as $i => $file) { |
if (isset($file['attribs']['baseinstalldir'])) { |
continue; |
} |
$this->_packageInfo['contents']['dir']['file'][$i]['attribs']['baseinstalldir'] |
= $this->_packageInfo['contents']['dir']['attribs']['baseinstalldir']; |
} |
} else { |
if (!isset($this->_packageInfo['contents']['dir']['file']['attribs']['baseinstalldir'])) { |
$this->_packageInfo['contents']['dir']['file']['attribs']['baseinstalldir'] |
= $this->_packageInfo['contents']['dir']['attribs']['baseinstalldir']; |
} |
} |
} |
} |
} |
/** |
* @param array the final flattened file list |
* @param array the current directory being processed |
* @param string|false any recursively inherited baeinstalldir attribute |
* @param string private recursion variable |
* @return array |
* @access protected |
*/ |
function _getFlattenedFilelist(&$files, $dir, $baseinstall = false, $path = '') |
{ |
if (isset($dir['attribs']) && isset($dir['attribs']['baseinstalldir'])) { |
$baseinstall = $dir['attribs']['baseinstalldir']; |
} |
if (isset($dir['dir'])) { |
if (!isset($dir['dir'][0])) { |
$dir['dir'] = array($dir['dir']); |
} |
foreach ($dir['dir'] as $subdir) { |
if (!isset($subdir['attribs']) || !isset($subdir['attribs']['name'])) { |
$name = '*unknown*'; |
} else { |
$name = $subdir['attribs']['name']; |
} |
$newpath = empty($path) ? $name : |
$path . '/' . $name; |
$this->_getFlattenedFilelist($files, $subdir, |
$baseinstall, $newpath); |
} |
} |
if (isset($dir['file'])) { |
if (!isset($dir['file'][0])) { |
$dir['file'] = array($dir['file']); |
} |
foreach ($dir['file'] as $file) { |
$attrs = $file['attribs']; |
$name = $attrs['name']; |
if ($baseinstall && !isset($attrs['baseinstalldir'])) { |
$attrs['baseinstalldir'] = $baseinstall; |
} |
$attrs['name'] = empty($path) ? $name : $path . '/' . $name; |
$attrs['name'] = preg_replace(array('!\\\\+!', '!/+!'), array('/', '/'), |
$attrs['name']); |
$file['attribs'] = $attrs; |
$files[] = $file; |
} |
} |
} |
function setConfig(&$config) |
{ |
$this->_config = &$config; |
$this->_registry = &$config->getRegistry(); |
} |
function setLogger(&$logger) |
{ |
if (!is_object($logger) || !method_exists($logger, 'log')) { |
return PEAR::raiseError('Logger must be compatible with PEAR_Common::log'); |
} |
$this->_logger = &$logger; |
} |
/** |
* WARNING - do not use this function directly unless you know what you're doing |
*/ |
function setDeps($deps) |
{ |
$this->_packageInfo['dependencies'] = $deps; |
} |
/** |
* WARNING - do not use this function directly unless you know what you're doing |
*/ |
function setCompatible($compat) |
{ |
$this->_packageInfo['compatible'] = $compat; |
} |
function setPackagefile($file, $archive = false) |
{ |
$this->_packageFile = $file; |
$this->_archiveFile = $archive ? $archive : $file; |
} |
/** |
* Wrapper to {@link PEAR_ErrorStack::getErrors()} |
* @param boolean determines whether to purge the error stack after retrieving |
* @return array |
*/ |
function getValidationWarnings($purge = true) |
{ |
return $this->_stack->getErrors($purge); |
} |
function getPackageFile() |
{ |
return $this->_packageFile; |
} |
function getArchiveFile() |
{ |
return $this->_archiveFile; |
} |
/** |
* Directly set the array that defines this packagefile |
* |
* WARNING: no validation. This should only be performed by internal methods |
* inside PEAR or by inputting an array saved from an existing PEAR_PackageFile_v2 |
* @param array |
*/ |
function fromArray($pinfo) |
{ |
unset($pinfo['old']); |
unset($pinfo['xsdversion']); |
// If the changelog isn't an array then it was passed in as an empty tag |
if (isset($pinfo['changelog']) && !is_array($pinfo['changelog'])) { |
unset($pinfo['changelog']); |
} |
$this->_incomplete = false; |
$this->_packageInfo = $pinfo; |
} |
function isIncomplete() |
{ |
return $this->_incomplete; |
} |
/** |
* @return array |
*/ |
function toArray($forreg = false) |
{ |
if (!$this->validate(PEAR_VALIDATE_NORMAL)) { |
return false; |
} |
return $this->getArray($forreg); |
} |
function getArray($forReg = false) |
{ |
if ($forReg) { |
$arr = $this->_packageInfo; |
$arr['old'] = array(); |
$arr['old']['version'] = $this->getVersion(); |
$arr['old']['release_date'] = $this->getDate(); |
$arr['old']['release_state'] = $this->getState(); |
$arr['old']['release_license'] = $this->getLicense(); |
$arr['old']['release_notes'] = $this->getNotes(); |
$arr['old']['release_deps'] = $this->getDeps(); |
$arr['old']['maintainers'] = $this->getMaintainers(); |
$arr['xsdversion'] = '2.0'; |
return $arr; |
} else { |
$info = $this->_packageInfo; |
unset($info['dirtree']); |
if (isset($info['_lastversion'])) { |
unset($info['_lastversion']); |
} |
if (isset($info['#binarypackage'])) { |
unset($info['#binarypackage']); |
} |
return $info; |
} |
} |
function packageInfo($field) |
{ |
$arr = $this->getArray(true); |
if ($field == 'state') { |
return $arr['stability']['release']; |
} |
if ($field == 'api-version') { |
return $arr['version']['api']; |
} |
if ($field == 'api-state') { |
return $arr['stability']['api']; |
} |
if (isset($arr['old'][$field])) { |
if (!is_string($arr['old'][$field])) { |
return null; |
} |
return $arr['old'][$field]; |
} |
if (isset($arr[$field])) { |
if (!is_string($arr[$field])) { |
return null; |
} |
return $arr[$field]; |
} |
return null; |
} |
function getName() |
{ |
return $this->getPackage(); |
} |
function getPackage() |
{ |
if (isset($this->_packageInfo['name'])) { |
return $this->_packageInfo['name']; |
} |
return false; |
} |
function getChannel() |
{ |
if (isset($this->_packageInfo['uri'])) { |
return '__uri'; |
} |
if (isset($this->_packageInfo['channel'])) { |
return strtolower($this->_packageInfo['channel']); |
} |
return false; |
} |
function getUri() |
{ |
if (isset($this->_packageInfo['uri'])) { |
return $this->_packageInfo['uri']; |
} |
return false; |
} |
function getExtends() |
{ |
if (isset($this->_packageInfo['extends'])) { |
return $this->_packageInfo['extends']; |
} |
return false; |
} |
function getSummary() |
{ |
if (isset($this->_packageInfo['summary'])) { |
return $this->_packageInfo['summary']; |
} |
return false; |
} |
function getDescription() |
{ |
if (isset($this->_packageInfo['description'])) { |
return $this->_packageInfo['description']; |
} |
return false; |
} |
function getMaintainers($raw = false) |
{ |
if (!isset($this->_packageInfo['lead'])) { |
return false; |
} |
if ($raw) { |
$ret = array('lead' => $this->_packageInfo['lead']); |
(isset($this->_packageInfo['developer'])) ? |
$ret['developer'] = $this->_packageInfo['developer'] :null; |
(isset($this->_packageInfo['contributor'])) ? |
$ret['contributor'] = $this->_packageInfo['contributor'] :null; |
(isset($this->_packageInfo['helper'])) ? |
$ret['helper'] = $this->_packageInfo['helper'] :null; |
return $ret; |
} else { |
$ret = array(); |
$leads = isset($this->_packageInfo['lead'][0]) ? $this->_packageInfo['lead'] : |
array($this->_packageInfo['lead']); |
foreach ($leads as $lead) { |
$s = $lead; |
$s['handle'] = $s['user']; |
unset($s['user']); |
$s['role'] = 'lead'; |
$ret[] = $s; |
} |
if (isset($this->_packageInfo['developer'])) { |
$leads = isset($this->_packageInfo['developer'][0]) ? |
$this->_packageInfo['developer'] : |
array($this->_packageInfo['developer']); |
foreach ($leads as $maintainer) { |
$s = $maintainer; |
$s['handle'] = $s['user']; |
unset($s['user']); |
$s['role'] = 'developer'; |
$ret[] = $s; |
} |
} |
if (isset($this->_packageInfo['contributor'])) { |
$leads = isset($this->_packageInfo['contributor'][0]) ? |
$this->_packageInfo['contributor'] : |
array($this->_packageInfo['contributor']); |
foreach ($leads as $maintainer) { |
$s = $maintainer; |
$s['handle'] = $s['user']; |
unset($s['user']); |
$s['role'] = 'contributor'; |
$ret[] = $s; |
} |
} |
if (isset($this->_packageInfo['helper'])) { |
$leads = isset($this->_packageInfo['helper'][0]) ? |
$this->_packageInfo['helper'] : |
array($this->_packageInfo['helper']); |
foreach ($leads as $maintainer) { |
$s = $maintainer; |
$s['handle'] = $s['user']; |
unset($s['user']); |
$s['role'] = 'helper'; |
$ret[] = $s; |
} |
} |
return $ret; |
} |
return false; |
} |
function getLeads() |
{ |
if (isset($this->_packageInfo['lead'])) { |
return $this->_packageInfo['lead']; |
} |
return false; |
} |
function getDevelopers() |
{ |
if (isset($this->_packageInfo['developer'])) { |
return $this->_packageInfo['developer']; |
} |
return false; |
} |
function getContributors() |
{ |
if (isset($this->_packageInfo['contributor'])) { |
return $this->_packageInfo['contributor']; |
} |
return false; |
} |
function getHelpers() |
{ |
if (isset($this->_packageInfo['helper'])) { |
return $this->_packageInfo['helper']; |
} |
return false; |
} |
function setDate($date) |
{ |
if (!isset($this->_packageInfo['date'])) { |
// ensure that the extends tag is set up in the right location |
$this->_packageInfo = $this->_insertBefore($this->_packageInfo, |
array('time', 'version', |
'stability', 'license', 'notes', 'contents', 'compatible', |
'dependencies', 'providesextension', 'srcpackage', 'srcuri', |
'phprelease', 'extsrcrelease', 'extbinrelease', 'zendextsrcrelease', |
'zendextbinrelease', 'bundle', 'changelog'), array(), 'date'); |
} |
$this->_packageInfo['date'] = $date; |
$this->_isValid = 0; |
} |
function setTime($time) |
{ |
$this->_isValid = 0; |
if (!isset($this->_packageInfo['time'])) { |
// ensure that the time tag is set up in the right location |
$this->_packageInfo = $this->_insertBefore($this->_packageInfo, |
array('version', |
'stability', 'license', 'notes', 'contents', 'compatible', |
'dependencies', 'providesextension', 'srcpackage', 'srcuri', |
'phprelease', 'extsrcrelease', 'extbinrelease', 'zendextsrcrelease', |
'zendextbinrelease', 'bundle', 'changelog'), $time, 'time'); |
} |
$this->_packageInfo['time'] = $time; |
} |
function getDate() |
{ |
if (isset($this->_packageInfo['date'])) { |
return $this->_packageInfo['date']; |
} |
return false; |
} |
function getTime() |
{ |
if (isset($this->_packageInfo['time'])) { |
return $this->_packageInfo['time']; |
} |
return false; |
} |
/** |
* @param package|api version category to return |
*/ |
function getVersion($key = 'release') |
{ |
if (isset($this->_packageInfo['version'][$key])) { |
return $this->_packageInfo['version'][$key]; |
} |
return false; |
} |
function getStability() |
{ |
if (isset($this->_packageInfo['stability'])) { |
return $this->_packageInfo['stability']; |
} |
return false; |
} |
function getState($key = 'release') |
{ |
if (isset($this->_packageInfo['stability'][$key])) { |
return $this->_packageInfo['stability'][$key]; |
} |
return false; |
} |
function getLicense($raw = false) |
{ |
if (isset($this->_packageInfo['license'])) { |
if ($raw) { |
return $this->_packageInfo['license']; |
} |
if (is_array($this->_packageInfo['license'])) { |
return $this->_packageInfo['license']['_content']; |
} else { |
return $this->_packageInfo['license']; |
} |
} |
return false; |
} |
function getLicenseLocation() |
{ |
if (!isset($this->_packageInfo['license']) || !is_array($this->_packageInfo['license'])) { |
return false; |
} |
return $this->_packageInfo['license']['attribs']; |
} |
function getNotes() |
{ |
if (isset($this->_packageInfo['notes'])) { |
return $this->_packageInfo['notes']; |
} |
return false; |
} |
/** |
* Return the <usesrole> tag contents, if any |
* @return array|false |
*/ |
function getUsesrole() |
{ |
if (isset($this->_packageInfo['usesrole'])) { |
return $this->_packageInfo['usesrole']; |
} |
return false; |
} |
/** |
* Return the <usestask> tag contents, if any |
* @return array|false |
*/ |
function getUsestask() |
{ |
if (isset($this->_packageInfo['usestask'])) { |
return $this->_packageInfo['usestask']; |
} |
return false; |
} |
/** |
* This should only be used to retrieve filenames and install attributes |
*/ |
function getFilelist($preserve = false) |
{ |
if (isset($this->_packageInfo['filelist']) && !$preserve) { |
return $this->_packageInfo['filelist']; |
} |
$this->flattenFilelist(); |
if ($contents = $this->getContents()) { |
$ret = array(); |
if (!isset($contents['dir'])) { |
return false; |
} |
if (!isset($contents['dir']['file'][0])) { |
$contents['dir']['file'] = array($contents['dir']['file']); |
} |
foreach ($contents['dir']['file'] as $file) { |
if (!isset($file['attribs']['name'])) { |
continue; |
} |
$name = $file['attribs']['name']; |
if (!$preserve) { |
$file = $file['attribs']; |
} |
$ret[$name] = $file; |
} |
if (!$preserve) { |
$this->_packageInfo['filelist'] = $ret; |
} |
return $ret; |
} |
return false; |
} |
/** |
* Return configure options array, if any |
* |
* @return array|false |
*/ |
function getConfigureOptions() |
{ |
if ($this->getPackageType() != 'extsrc' && $this->getPackageType() != 'zendextsrc') { |
return false; |
} |
$releases = $this->getReleases(); |
if (isset($releases[0])) { |
$releases = $releases[0]; |
} |
if (isset($releases['configureoption'])) { |
if (!isset($releases['configureoption'][0])) { |
$releases['configureoption'] = array($releases['configureoption']); |
} |
for ($i = 0; $i < count($releases['configureoption']); $i++) { |
$releases['configureoption'][$i] = $releases['configureoption'][$i]['attribs']; |
} |
return $releases['configureoption']; |
} |
return false; |
} |
/** |
* This is only used at install-time, after all serialization |
* is over. |
*/ |
function resetFilelist() |
{ |
$this->_packageInfo['filelist'] = array(); |
} |
/** |
* Retrieve a list of files that should be installed on this computer |
* @return array |
*/ |
function getInstallationFilelist($forfilecheck = false) |
{ |
$contents = $this->getFilelist(true); |
if (isset($contents['dir']['attribs']['baseinstalldir'])) { |
$base = $contents['dir']['attribs']['baseinstalldir']; |
} |
if (isset($this->_packageInfo['bundle'])) { |
return PEAR::raiseError( |
'Exception: bundles should be handled in download code only'); |
} |
$release = $this->getReleases(); |
if ($release) { |
if (!isset($release[0])) { |
if (!isset($release['installconditions']) && !isset($release['filelist'])) { |
if ($forfilecheck) { |
return $this->getFilelist(); |
} |
return $contents; |
} |
$release = array($release); |
} |
$depchecker = &$this->getPEARDependency2($this->_config, array(), |
array('channel' => $this->getChannel(), 'package' => $this->getPackage()), |
PEAR_VALIDATE_INSTALLING); |
foreach ($release as $instance) { |
if (isset($instance['installconditions'])) { |
$installconditions = $instance['installconditions']; |
if (is_array($installconditions)) { |
PEAR::pushErrorHandling(PEAR_ERROR_RETURN); |
foreach ($installconditions as $type => $conditions) { |
if (!isset($conditions[0])) { |
$conditions = array($conditions); |
} |
foreach ($conditions as $condition) { |
$ret = $depchecker->{"validate{$type}Dependency"}($condition); |
if (PEAR::isError($ret)) { |
PEAR::popErrorHandling(); |
continue 3; // skip this release |
} |
} |
} |
PEAR::popErrorHandling(); |
} |
} |
// this is the release to use |
if (isset($instance['filelist'])) { |
// ignore files |
if (isset($instance['filelist']['ignore'])) { |
$ignore = isset($instance['filelist']['ignore'][0]) ? |
$instance['filelist']['ignore'] : |
array($instance['filelist']['ignore']); |
foreach ($ignore as $ig) { |
unset ($contents[$ig['attribs']['name']]); |
} |
} |
// install files as this name |
if (isset($instance['filelist']['install'])) { |
$installas = isset($instance['filelist']['install'][0]) ? |
$instance['filelist']['install'] : |
array($instance['filelist']['install']); |
foreach ($installas as $as) { |
$contents[$as['attribs']['name']]['attribs']['install-as'] = |
$as['attribs']['as']; |
} |
} |
} |
if ($forfilecheck) { |
foreach ($contents as $file => $attrs) { |
$contents[$file] = $attrs['attribs']; |
} |
} |
return $contents; |
} |
} else { // simple release - no installconditions or install-as |
if ($forfilecheck) { |
return $this->getFilelist(); |
} |
return $contents; |
} |
// no releases matched |
return PEAR::raiseError('No releases in package.xml matched the existing operating ' . |
'system, extensions installed, or architecture, cannot install'); |
} |
/** |
* This is only used at install-time, after all serialization |
* is over. |
* @param string file name |
* @param string installed path |
*/ |
function setInstalledAs($file, $path) |
{ |
if ($path) { |
return $this->_packageInfo['filelist'][$file]['installed_as'] = $path; |
} |
unset($this->_packageInfo['filelist'][$file]['installed_as']); |
} |
function getInstalledLocation($file) |
{ |
if (isset($this->_packageInfo['filelist'][$file]['installed_as'])) { |
return $this->_packageInfo['filelist'][$file]['installed_as']; |
} |
return false; |
} |
/** |
* This is only used at install-time, after all serialization |
* is over. |
*/ |
function installedFile($file, $atts) |
{ |
if (isset($this->_packageInfo['filelist'][$file])) { |
$this->_packageInfo['filelist'][$file] = |
array_merge($this->_packageInfo['filelist'][$file], $atts['attribs']); |
} else { |
$this->_packageInfo['filelist'][$file] = $atts['attribs']; |
} |
} |
/** |
* Retrieve the contents tag |
*/ |
function getContents() |
{ |
if (isset($this->_packageInfo['contents'])) { |
return $this->_packageInfo['contents']; |
} |
return false; |
} |
/** |
* @param string full path to file |
* @param string attribute name |
* @param string attribute value |
* @param int risky but fast - use this to choose a file based on its position in the list |
* of files. Index is zero-based like PHP arrays. |
* @return bool success of operation |
*/ |
function setFileAttribute($filename, $attr, $value, $index = false) |
{ |
$this->_isValid = 0; |
if (in_array($attr, array('role', 'name', 'baseinstalldir'))) { |
$this->_filesValid = false; |
} |
if ($index !== false && |
isset($this->_packageInfo['contents']['dir']['file'][$index]['attribs'])) { |
$this->_packageInfo['contents']['dir']['file'][$index]['attribs'][$attr] = $value; |
return true; |
} |
if (!isset($this->_packageInfo['contents']['dir']['file'])) { |
return false; |
} |
$files = $this->_packageInfo['contents']['dir']['file']; |
if (!isset($files[0])) { |
$files = array($files); |
$ind = false; |
} else { |
$ind = true; |
} |
foreach ($files as $i => $file) { |
if (isset($file['attribs'])) { |
if ($file['attribs']['name'] == $filename) { |
if ($ind) { |
$this->_packageInfo['contents']['dir']['file'][$i]['attribs'][$attr] = $value; |
} else { |
$this->_packageInfo['contents']['dir']['file']['attribs'][$attr] = $value; |
} |
return true; |
} |
} |
} |
return false; |
} |
function setDirtree($path) |
{ |
if (!isset($this->_packageInfo['dirtree'])) { |
$this->_packageInfo['dirtree'] = array(); |
} |
$this->_packageInfo['dirtree'][$path] = true; |
} |
function getDirtree() |
{ |
if (isset($this->_packageInfo['dirtree']) && count($this->_packageInfo['dirtree'])) { |
return $this->_packageInfo['dirtree']; |
} |
return false; |
} |
function resetDirtree() |
{ |
unset($this->_packageInfo['dirtree']); |
} |
/** |
* Determines whether this package claims it is compatible with the version of |
* the package that has a recommended version dependency |
* @param PEAR_PackageFile_v2|PEAR_PackageFile_v1|PEAR_Downloader_Package |
* @return boolean |
*/ |
function isCompatible($pf) |
{ |
if (!isset($this->_packageInfo['compatible'])) { |
return false; |
} |
if (!isset($this->_packageInfo['channel'])) { |
return false; |
} |
$me = $pf->getVersion(); |
$compatible = $this->_packageInfo['compatible']; |
if (!isset($compatible[0])) { |
$compatible = array($compatible); |
} |
$found = false; |
foreach ($compatible as $info) { |
if (strtolower($info['name']) == strtolower($pf->getPackage())) { |
if (strtolower($info['channel']) == strtolower($pf->getChannel())) { |
$found = true; |
break; |
} |
} |
} |
if (!$found) { |
return false; |
} |
if (isset($info['exclude'])) { |
if (!isset($info['exclude'][0])) { |
$info['exclude'] = array($info['exclude']); |
} |
foreach ($info['exclude'] as $exclude) { |
if (version_compare($me, $exclude, '==')) { |
return false; |
} |
} |
} |
if (version_compare($me, $info['min'], '>=') && version_compare($me, $info['max'], '<=')) { |
return true; |
} |
return false; |
} |
/** |
* @return array|false |
*/ |
function getCompatible() |
{ |
if (isset($this->_packageInfo['compatible'])) { |
return $this->_packageInfo['compatible']; |
} |
return false; |
} |
function getDependencies() |
{ |
if (isset($this->_packageInfo['dependencies'])) { |
return $this->_packageInfo['dependencies']; |
} |
return false; |
} |
function isSubpackageOf($p) |
{ |
return $p->isSubpackage($this); |
} |
/** |
* Determines whether the passed in package is a subpackage of this package. |
* |
* No version checking is done, only name verification. |
* @param PEAR_PackageFile_v1|PEAR_PackageFile_v2 |
* @return bool |
*/ |
function isSubpackage($p) |
{ |
$sub = array(); |
if (isset($this->_packageInfo['dependencies']['required']['subpackage'])) { |
$sub = $this->_packageInfo['dependencies']['required']['subpackage']; |
if (!isset($sub[0])) { |
$sub = array($sub); |
} |
} |
if (isset($this->_packageInfo['dependencies']['optional']['subpackage'])) { |
$sub1 = $this->_packageInfo['dependencies']['optional']['subpackage']; |
if (!isset($sub1[0])) { |
$sub1 = array($sub1); |
} |
$sub = array_merge($sub, $sub1); |
} |
if (isset($this->_packageInfo['dependencies']['group'])) { |
$group = $this->_packageInfo['dependencies']['group']; |
if (!isset($group[0])) { |
$group = array($group); |
} |
foreach ($group as $deps) { |
if (isset($deps['subpackage'])) { |
$sub2 = $deps['subpackage']; |
if (!isset($sub2[0])) { |
$sub2 = array($sub2); |
} |
$sub = array_merge($sub, $sub2); |
} |
} |
} |
foreach ($sub as $dep) { |
if (strtolower($dep['name']) == strtolower($p->getPackage())) { |
if (isset($dep['channel'])) { |
if (strtolower($dep['channel']) == strtolower($p->getChannel())) { |
return true; |
} |
} else { |
if ($dep['uri'] == $p->getURI()) { |
return true; |
} |
} |
} |
} |
return false; |
} |
function dependsOn($package, $channel) |
{ |
if (!($deps = $this->getDependencies())) { |
return false; |
} |
foreach (array('package', 'subpackage') as $type) { |
foreach (array('required', 'optional') as $needed) { |
if (isset($deps[$needed][$type])) { |
if (!isset($deps[$needed][$type][0])) { |
$deps[$needed][$type] = array($deps[$needed][$type]); |
} |
foreach ($deps[$needed][$type] as $dep) { |
$depchannel = isset($dep['channel']) ? $dep['channel'] : '__uri'; |
if (strtolower($dep['name']) == strtolower($package) && |
$depchannel == $channel) { |
return true; |
} |
} |
} |
} |
if (isset($deps['group'])) { |
if (!isset($deps['group'][0])) { |
$dep['group'] = array($deps['group']); |
} |
foreach ($deps['group'] as $group) { |
if (isset($group[$type])) { |
if (!is_array($group[$type])) { |
$group[$type] = array($group[$type]); |
} |
foreach ($group[$type] as $dep) { |
$depchannel = isset($dep['channel']) ? $dep['channel'] : '__uri'; |
if (strtolower($dep['name']) == strtolower($package) && |
$depchannel == $channel) { |
return true; |
} |
} |
} |
} |
} |
} |
return false; |
} |
/** |
* Get the contents of a dependency group |
* @param string |
* @return array|false |
*/ |
function getDependencyGroup($name) |
{ |
$name = strtolower($name); |
if (!isset($this->_packageInfo['dependencies']['group'])) { |
return false; |
} |
$groups = $this->_packageInfo['dependencies']['group']; |
if (!isset($groups[0])) { |
$groups = array($groups); |
} |
foreach ($groups as $group) { |
if (strtolower($group['attribs']['name']) == $name) { |
return $group; |
} |
} |
return false; |
} |
/** |
* Retrieve a partial package.xml 1.0 representation of dependencies |
* |
* a very limited representation of dependencies is returned by this method. |
* The <exclude> tag for excluding certain versions of a dependency is |
* completely ignored. In addition, dependency groups are ignored, with the |
* assumption that all dependencies in dependency groups are also listed in |
* the optional group that work with all dependency groups |
* @param boolean return package.xml 2.0 <dependencies> tag |
* @return array|false |
*/ |
function getDeps($raw = false, $nopearinstaller = false) |
{ |
if (isset($this->_packageInfo['dependencies'])) { |
if ($raw) { |
return $this->_packageInfo['dependencies']; |
} |
$ret = array(); |
$map = array( |
'php' => 'php', |
'package' => 'pkg', |
'subpackage' => 'pkg', |
'extension' => 'ext', |
'os' => 'os', |
'pearinstaller' => 'pkg', |
); |
foreach (array('required', 'optional') as $type) { |
$optional = ($type == 'optional') ? 'yes' : 'no'; |
if (!isset($this->_packageInfo['dependencies'][$type]) |
|| empty($this->_packageInfo['dependencies'][$type])) { |
continue; |
} |
foreach ($this->_packageInfo['dependencies'][$type] as $dtype => $deps) { |
if ($dtype == 'pearinstaller' && $nopearinstaller) { |
continue; |
} |
if (!isset($deps[0])) { |
$deps = array($deps); |
} |
foreach ($deps as $dep) { |
if (!isset($map[$dtype])) { |
// no support for arch type |
continue; |
} |
if ($dtype == 'pearinstaller') { |
$dep['name'] = 'PEAR'; |
$dep['channel'] = 'pear.php.net'; |
} |
$s = array('type' => $map[$dtype]); |
if (isset($dep['channel'])) { |
$s['channel'] = $dep['channel']; |
} |
if (isset($dep['uri'])) { |
$s['uri'] = $dep['uri']; |
} |
if (isset($dep['name'])) { |
$s['name'] = $dep['name']; |
} |
if (isset($dep['conflicts'])) { |
$s['rel'] = 'not'; |
} else { |
if (!isset($dep['min']) && |
!isset($dep['max'])) { |
$s['rel'] = 'has'; |
$s['optional'] = $optional; |
} elseif (isset($dep['min']) && |
isset($dep['max'])) { |
$s['rel'] = 'ge'; |
$s1 = $s; |
$s1['rel'] = 'le'; |
$s['version'] = $dep['min']; |
$s1['version'] = $dep['max']; |
if (isset($dep['channel'])) { |
$s1['channel'] = $dep['channel']; |
} |
if ($dtype != 'php') { |
$s['name'] = $dep['name']; |
$s1['name'] = $dep['name']; |
} |
$s['optional'] = $optional; |
$s1['optional'] = $optional; |
$ret[] = $s1; |
} elseif (isset($dep['min'])) { |
if (isset($dep['exclude']) && |
$dep['exclude'] == $dep['min']) { |
$s['rel'] = 'gt'; |
} else { |
$s['rel'] = 'ge'; |
} |
$s['version'] = $dep['min']; |
$s['optional'] = $optional; |
if ($dtype != 'php') { |
$s['name'] = $dep['name']; |
} |
} elseif (isset($dep['max'])) { |
if (isset($dep['exclude']) && |
$dep['exclude'] == $dep['max']) { |
$s['rel'] = 'lt'; |
} else { |
$s['rel'] = 'le'; |
} |
$s['version'] = $dep['max']; |
$s['optional'] = $optional; |
if ($dtype != 'php') { |
$s['name'] = $dep['name']; |
} |
} |
} |
$ret[] = $s; |
} |
} |
} |
if (count($ret)) { |
return $ret; |
} |
} |
return false; |
} |
/** |
* @return php|extsrc|extbin|zendextsrc|zendextbin|bundle|false |
*/ |
function getPackageType() |
{ |
if (isset($this->_packageInfo['phprelease'])) { |
return 'php'; |
} |
if (isset($this->_packageInfo['extsrcrelease'])) { |
return 'extsrc'; |
} |
if (isset($this->_packageInfo['extbinrelease'])) { |
return 'extbin'; |
} |
if (isset($this->_packageInfo['zendextsrcrelease'])) { |
return 'zendextsrc'; |
} |
if (isset($this->_packageInfo['zendextbinrelease'])) { |
return 'zendextbin'; |
} |
if (isset($this->_packageInfo['bundle'])) { |
return 'bundle'; |
} |
return false; |
} |
/** |
* @return array|false |
*/ |
function getReleases() |
{ |
$type = $this->getPackageType(); |
if ($type != 'bundle') { |
$type .= 'release'; |
} |
if ($this->getPackageType() && isset($this->_packageInfo[$type])) { |
return $this->_packageInfo[$type]; |
} |
return false; |
} |
/** |
* @return array |
*/ |
function getChangelog() |
{ |
if (isset($this->_packageInfo['changelog'])) { |
return $this->_packageInfo['changelog']; |
} |
return false; |
} |
function hasDeps() |
{ |
return isset($this->_packageInfo['dependencies']); |
} |
function getPackagexmlVersion() |
{ |
if (isset($this->_packageInfo['zendextsrcrelease'])) { |
return '2.1'; |
} |
if (isset($this->_packageInfo['zendextbinrelease'])) { |
return '2.1'; |
} |
return '2.0'; |
} |
/** |
* @return array|false |
*/ |
function getSourcePackage() |
{ |
if (isset($this->_packageInfo['extbinrelease']) || |
isset($this->_packageInfo['zendextbinrelease'])) { |
return array('channel' => $this->_packageInfo['srcchannel'], |
'package' => $this->_packageInfo['srcpackage']); |
} |
return false; |
} |
function getBundledPackages() |
{ |
if (isset($this->_packageInfo['bundle'])) { |
return $this->_packageInfo['contents']['bundledpackage']; |
} |
return false; |
} |
function getLastModified() |
{ |
if (isset($this->_packageInfo['_lastmodified'])) { |
return $this->_packageInfo['_lastmodified']; |
} |
return false; |
} |
/** |
* Get the contents of a file listed within the package.xml |
* @param string |
* @return string |
*/ |
function getFileContents($file) |
{ |
if ($this->_archiveFile == $this->_packageFile) { // unpacked |
$dir = dirname($this->_packageFile); |
$file = $dir . DIRECTORY_SEPARATOR . $file; |
$file = str_replace(array('/', '\\'), |
array(DIRECTORY_SEPARATOR, DIRECTORY_SEPARATOR), $file); |
if (file_exists($file) && is_readable($file)) { |
return implode('', file($file)); |
} |
} else { // tgz |
$tar = new Archive_Tar($this->_archiveFile); |
$tar->pushErrorHandling(PEAR_ERROR_RETURN); |
if ($file != 'package.xml' && $file != 'package2.xml') { |
$file = $this->getPackage() . '-' . $this->getVersion() . '/' . $file; |
} |
$file = $tar->extractInString($file); |
$tar->popErrorHandling(); |
if (PEAR::isError($file)) { |
return PEAR::raiseError("Cannot locate file '$file' in archive"); |
} |
return $file; |
} |
} |
function &getRW() |
{ |
if (!class_exists('PEAR_PackageFile_v2_rw')) { |
require_once 'PEAR/PackageFile/v2/rw.php'; |
} |
$a = new PEAR_PackageFile_v2_rw; |
foreach (get_object_vars($this) as $name => $unused) { |
if (!isset($this->$name)) { |
continue; |
} |
if ($name == '_config' || $name == '_logger'|| $name == '_registry' || |
$name == '_stack') { |
$a->$name = &$this->$name; |
} else { |
$a->$name = $this->$name; |
} |
} |
return $a; |
} |
function &getDefaultGenerator() |
{ |
if (!class_exists('PEAR_PackageFile_Generator_v2')) { |
require_once 'PEAR/PackageFile/Generator/v2.php'; |
} |
$a = new PEAR_PackageFile_Generator_v2($this); |
return $a; |
} |
function analyzeSourceCode($file, $string = false) |
{ |
if (!isset($this->_v2Validator) || |
!is_a($this->_v2Validator, 'PEAR_PackageFile_v2_Validator')) { |
if (!class_exists('PEAR_PackageFile_v2_Validator')) { |
require_once 'PEAR/PackageFile/v2/Validator.php'; |
} |
$this->_v2Validator = new PEAR_PackageFile_v2_Validator; |
} |
return $this->_v2Validator->analyzeSourceCode($file, $string); |
} |
function validate($state = PEAR_VALIDATE_NORMAL) |
{ |
if (!isset($this->_packageInfo) || !is_array($this->_packageInfo)) { |
return false; |
} |
if (!isset($this->_v2Validator) || |
!is_a($this->_v2Validator, 'PEAR_PackageFile_v2_Validator')) { |
if (!class_exists('PEAR_PackageFile_v2_Validator')) { |
require_once 'PEAR/PackageFile/v2/Validator.php'; |
} |
$this->_v2Validator = new PEAR_PackageFile_v2_Validator; |
} |
if (isset($this->_packageInfo['xsdversion'])) { |
unset($this->_packageInfo['xsdversion']); |
} |
return $this->_v2Validator->validate($this, $state); |
} |
function getTasksNs() |
{ |
if (!isset($this->_tasksNs)) { |
if (isset($this->_packageInfo['attribs'])) { |
foreach ($this->_packageInfo['attribs'] as $name => $value) { |
if ($value == 'http://pear.php.net/dtd/tasks-1.0') { |
$this->_tasksNs = str_replace('xmlns:', '', $name); |
break; |
} |
} |
} |
} |
return $this->_tasksNs; |
} |
/** |
* Determine whether a task name is a valid task. Custom tasks may be defined |
* using subdirectories by putting a "-" in the name, as in <tasks:mycustom-task> |
* |
* Note that this method will auto-load the task class file and test for the existence |
* of the name with "-" replaced by "_" as in PEAR/Task/mycustom/task.php makes class |
* PEAR_Task_mycustom_task |
* @param string |
* @return boolean |
*/ |
function getTask($task) |
{ |
$this->getTasksNs(); |
// transform all '-' to '/' and 'tasks:' to '' so tasks:replace becomes replace |
$task = str_replace(array($this->_tasksNs . ':', '-'), array('', ' '), $task); |
$taskfile = str_replace(' ', '/', ucwords($task)); |
$task = str_replace(array(' ', '/'), '_', ucwords($task)); |
if (class_exists("PEAR_Task_$task")) { |
return "PEAR_Task_$task"; |
} |
$fp = @fopen("PEAR/Task/$taskfile.php", 'r', true); |
if ($fp) { |
fclose($fp); |
require_once "PEAR/Task/$taskfile.php"; |
return "PEAR_Task_$task"; |
} |
return false; |
} |
/** |
* Key-friendly array_splice |
* @param tagname to splice a value in before |
* @param mixed the value to splice in |
* @param string the new tag name |
*/ |
function _ksplice($array, $key, $value, $newkey) |
{ |
$offset = array_search($key, array_keys($array)); |
$after = array_slice($array, $offset); |
$before = array_slice($array, 0, $offset); |
$before[$newkey] = $value; |
return array_merge($before, $after); |
} |
/** |
* @param array a list of possible keys, in the order they may occur |
* @param mixed contents of the new package.xml tag |
* @param string tag name |
* @access private |
*/ |
function _insertBefore($array, $keys, $contents, $newkey) |
{ |
foreach ($keys as $key) { |
if (isset($array[$key])) { |
return $array = $this->_ksplice($array, $key, $contents, $newkey); |
} |
} |
$array[$newkey] = $contents; |
return $array; |
} |
/** |
* @param subsection of {@link $_packageInfo} |
* @param array|string tag contents |
* @param array format: |
* <pre> |
* array( |
* tagname => array(list of tag names that follow this one), |
* childtagname => array(list of child tag names that follow this one), |
* ) |
* </pre> |
* |
* This allows construction of nested tags |
* @access private |
*/ |
function _mergeTag($manip, $contents, $order) |
{ |
if (count($order)) { |
foreach ($order as $tag => $curorder) { |
if (!isset($manip[$tag])) { |
// ensure that the tag is set up |
$manip = $this->_insertBefore($manip, $curorder, array(), $tag); |
} |
if (count($order) > 1) { |
$manip[$tag] = $this->_mergeTag($manip[$tag], $contents, array_slice($order, 1)); |
return $manip; |
} |
} |
} else { |
return $manip; |
} |
if (is_array($manip[$tag]) && !empty($manip[$tag]) && isset($manip[$tag][0])) { |
$manip[$tag][] = $contents; |
} else { |
if (!count($manip[$tag])) { |
$manip[$tag] = $contents; |
} else { |
$manip[$tag] = array($manip[$tag]); |
$manip[$tag][] = $contents; |
} |
} |
return $manip; |
} |
} |
?> |
/branches/v1.3-critias/bibliotheque/pear/PEAR/Installer/Role.php |
---|
New file |
0,0 → 1,266 |
<?php |
/** |
* PEAR_Installer_Role |
* |
* PHP versions 4 and 5 |
* |
* @category pear |
* @package PEAR |
* @author Greg Beaver <cellog@php.net> |
* @copyright 1997-2009 The Authors |
* @license http://opensource.org/licenses/bsd-license.php New BSD License |
* @link http://pear.php.net/package/PEAR |
* @since File available since Release 1.4.0a1 |
*/ |
/** |
* base class for installer roles |
*/ |
require_once 'PEAR/Installer/Role/Common.php'; |
require_once 'PEAR/XMLParser.php'; |
/** |
* @category pear |
* @package PEAR |
* @author Greg Beaver <cellog@php.net> |
* @copyright 1997-2009 The Authors |
* @license http://opensource.org/licenses/bsd-license.php New BSD License |
* @version Release: 1.10.1 |
* @link http://pear.php.net/package/PEAR |
* @since Class available since Release 1.4.0a1 |
*/ |
class PEAR_Installer_Role |
{ |
/** |
* Set up any additional configuration variables that file roles require |
* |
* Never call this directly, it is called by the PEAR_Config constructor |
* @param PEAR_Config |
*/ |
public static function initializeConfig(&$config) |
{ |
if (!isset($GLOBALS['_PEAR_INSTALLER_ROLES'])) { |
PEAR_Installer_Role::registerRoles(); |
} |
foreach ($GLOBALS['_PEAR_INSTALLER_ROLES'] as $class => $info) { |
if (!$info['config_vars']) { |
continue; |
} |
$config->_addConfigVars($class, $info['config_vars']); |
} |
} |
/** |
* @param PEAR_PackageFile_v2 |
* @param string role name |
* @param PEAR_Config |
* @return PEAR_Installer_Role_Common |
*/ |
public static function &factory($pkg, $role, &$config) |
{ |
if (!isset($GLOBALS['_PEAR_INSTALLER_ROLES'])) { |
PEAR_Installer_Role::registerRoles(); |
} |
if (!in_array($role, PEAR_Installer_Role::getValidRoles($pkg->getPackageType()))) { |
$a = false; |
return $a; |
} |
$a = 'PEAR_Installer_Role_' . ucfirst($role); |
if (!class_exists($a)) { |
require_once str_replace('_', '/', $a) . '.php'; |
} |
$b = new $a($config); |
return $b; |
} |
/** |
* Get a list of file roles that are valid for the particular release type. |
* |
* For instance, src files serve no purpose in regular php releases. |
* @param string |
* @param bool clear cache |
* @return array |
*/ |
public static function getValidRoles($release, $clear = false) |
{ |
if (!isset($GLOBALS['_PEAR_INSTALLER_ROLES'])) { |
PEAR_Installer_Role::registerRoles(); |
} |
static $ret = array(); |
if ($clear) { |
$ret = array(); |
} |
if (isset($ret[$release])) { |
return $ret[$release]; |
} |
$ret[$release] = array(); |
foreach ($GLOBALS['_PEAR_INSTALLER_ROLES'] as $role => $okreleases) { |
if (in_array($release, $okreleases['releasetypes'])) { |
$ret[$release][] = strtolower(str_replace('PEAR_Installer_Role_', '', $role)); |
} |
} |
return $ret[$release]; |
} |
/** |
* Get a list of roles that require their files to be installed |
* |
* Most roles must be installed, but src and package roles, for instance |
* are pseudo-roles. src files are compiled into a new extension. Package |
* roles are actually fully bundled releases of a package |
* @param bool clear cache |
* @return array |
*/ |
public static function getInstallableRoles($clear = false) |
{ |
if (!isset($GLOBALS['_PEAR_INSTALLER_ROLES'])) { |
PEAR_Installer_Role::registerRoles(); |
} |
static $ret; |
if ($clear) { |
unset($ret); |
} |
if (isset($ret)) { |
return $ret; |
} |
$ret = array(); |
foreach ($GLOBALS['_PEAR_INSTALLER_ROLES'] as $role => $okreleases) { |
if ($okreleases['installable']) { |
$ret[] = strtolower(str_replace('PEAR_Installer_Role_', '', $role)); |
} |
} |
return $ret; |
} |
/** |
* Return an array of roles that are affected by the baseinstalldir attribute |
* |
* Most roles ignore this attribute, and instead install directly into: |
* PackageName/filepath |
* so a tests file tests/file.phpt is installed into PackageName/tests/filepath.php |
* @param bool clear cache |
* @return array |
*/ |
public static function getBaseinstallRoles($clear = false) |
{ |
if (!isset($GLOBALS['_PEAR_INSTALLER_ROLES'])) { |
PEAR_Installer_Role::registerRoles(); |
} |
static $ret; |
if ($clear) { |
unset($ret); |
} |
if (isset($ret)) { |
return $ret; |
} |
$ret = array(); |
foreach ($GLOBALS['_PEAR_INSTALLER_ROLES'] as $role => $okreleases) { |
if ($okreleases['honorsbaseinstall']) { |
$ret[] = strtolower(str_replace('PEAR_Installer_Role_', '', $role)); |
} |
} |
return $ret; |
} |
/** |
* Return an array of file roles that should be analyzed for PHP content at package time, |
* like the "php" role. |
* @param bool clear cache |
* @return array |
*/ |
public static function getPhpRoles($clear = false) |
{ |
if (!isset($GLOBALS['_PEAR_INSTALLER_ROLES'])) { |
PEAR_Installer_Role::registerRoles(); |
} |
static $ret; |
if ($clear) { |
unset($ret); |
} |
if (isset($ret)) { |
return $ret; |
} |
$ret = array(); |
foreach ($GLOBALS['_PEAR_INSTALLER_ROLES'] as $role => $okreleases) { |
if ($okreleases['phpfile']) { |
$ret[] = strtolower(str_replace('PEAR_Installer_Role_', '', $role)); |
} |
} |
return $ret; |
} |
/** |
* Scan through the Command directory looking for classes |
* and see what commands they implement. |
* @param string which directory to look for classes, defaults to |
* the Installer/Roles subdirectory of |
* the directory from where this file (__FILE__) is |
* included. |
* |
* @return bool TRUE on success, a PEAR error on failure |
*/ |
public static function registerRoles($dir = null) |
{ |
$GLOBALS['_PEAR_INSTALLER_ROLES'] = array(); |
$parser = new PEAR_XMLParser; |
if ($dir === null) { |
$dir = dirname(__FILE__) . '/Role'; |
} |
if (!file_exists($dir) || !is_dir($dir)) { |
return PEAR::raiseError("registerRoles: opendir($dir) failed: does not exist/is not directory"); |
} |
$dp = @opendir($dir); |
if (empty($dp)) { |
return PEAR::raiseError("registerRoles: opendir($dir) failed: $php_errmsg"); |
} |
while ($entry = readdir($dp)) { |
if ($entry{0} == '.' || substr($entry, -4) != '.xml') { |
continue; |
} |
$class = "PEAR_Installer_Role_".substr($entry, 0, -4); |
// List of roles |
if (!isset($GLOBALS['_PEAR_INSTALLER_ROLES'][$class])) { |
$file = "$dir/$entry"; |
$parser->parse(file_get_contents($file)); |
$data = $parser->getData(); |
if (!is_array($data['releasetypes'])) { |
$data['releasetypes'] = array($data['releasetypes']); |
} |
$GLOBALS['_PEAR_INSTALLER_ROLES'][$class] = $data; |
} |
} |
closedir($dp); |
ksort($GLOBALS['_PEAR_INSTALLER_ROLES']); |
PEAR_Installer_Role::getBaseinstallRoles(true); |
PEAR_Installer_Role::getInstallableRoles(true); |
PEAR_Installer_Role::getPhpRoles(true); |
PEAR_Installer_Role::getValidRoles('****', true); |
return true; |
} |
} |
/branches/v1.3-critias/bibliotheque/pear/PEAR/Installer/Role/Www.xml |
---|
New file |
0,0 → 1,15 |
<role version="1.0"> |
<releasetypes>php</releasetypes> |
<releasetypes>extsrc</releasetypes> |
<releasetypes>extbin</releasetypes> |
<releasetypes>zendextsrc</releasetypes> |
<releasetypes>zendextbin</releasetypes> |
<installable>1</installable> |
<locationconfig>www_dir</locationconfig> |
<honorsbaseinstall>1</honorsbaseinstall> |
<unusualbaseinstall /> |
<phpfile /> |
<executable /> |
<phpextension /> |
<config_vars /> |
</role> |
/branches/v1.3-critias/bibliotheque/pear/PEAR/Installer/Role/Cfg.php |
---|
New file |
0,0 → 1,105 |
<?php |
/** |
* PEAR_Installer_Role_Cfg |
* |
* PHP versions 4 and 5 |
* |
* @category pear |
* @package PEAR |
* @author Greg Beaver <cellog@php.net> |
* @copyright 2007-2009 The Authors |
* @license http://opensource.org/licenses/bsd-license.php New BSD License |
* @link http://pear.php.net/package/PEAR |
* @since File available since Release 1.7.0 |
*/ |
/** |
* @category pear |
* @package PEAR |
* @author Greg Beaver <cellog@php.net> |
* @copyright 2007-2009 The Authors |
* @license http://opensource.org/licenses/bsd-license.php New BSD License |
* @version Release: 1.10.1 |
* @link http://pear.php.net/package/PEAR |
* @since Class available since Release 1.7.0 |
*/ |
class PEAR_Installer_Role_Cfg extends PEAR_Installer_Role_Common |
{ |
/** |
* @var PEAR_Installer |
*/ |
var $installer; |
/** |
* the md5 of the original file |
* |
* @var unknown_type |
*/ |
var $md5 = null; |
/** |
* Do any unusual setup here |
* @param PEAR_Installer |
* @param PEAR_PackageFile_v2 |
* @param array file attributes |
* @param string file name |
*/ |
function setup(&$installer, $pkg, $atts, $file) |
{ |
$this->installer = &$installer; |
$reg = &$this->installer->config->getRegistry(); |
$package = $reg->getPackage($pkg->getPackage(), $pkg->getChannel()); |
if ($package) { |
$filelist = $package->getFilelist(); |
if (isset($filelist[$file]) && isset($filelist[$file]['md5sum'])) { |
$this->md5 = $filelist[$file]['md5sum']; |
} |
} |
} |
function processInstallation($pkg, $atts, $file, $tmp_path, $layer = null) |
{ |
$test = parent::processInstallation($pkg, $atts, $file, $tmp_path, $layer); |
if (@file_exists($test[2]) && @file_exists($test[3])) { |
$md5 = md5_file($test[2]); |
// configuration has already been installed, check for mods |
if ($md5 !== $this->md5 && $md5 !== md5_file($test[3])) { |
// configuration has been modified, so save our version as |
// configfile-version |
$old = $test[2]; |
$test[2] .= '.new-' . $pkg->getVersion(); |
// backup original and re-install it |
PEAR::pushErrorHandling(PEAR_ERROR_RETURN); |
$tmpcfg = $this->config->get('temp_dir'); |
$newloc = System::mkdir(array('-p', $tmpcfg)); |
if (!$newloc) { |
// try temp_dir |
$newloc = System::mktemp(array('-d')); |
if (!$newloc || PEAR::isError($newloc)) { |
PEAR::popErrorHandling(); |
return PEAR::raiseError('Could not save existing configuration file '. |
$old . ', unable to install. Please set temp_dir ' . |
'configuration variable to a writeable location and try again'); |
} |
} else { |
$newloc = $tmpcfg; |
} |
$temp_file = $newloc . DIRECTORY_SEPARATOR . uniqid('savefile'); |
if (!@copy($old, $temp_file)) { |
PEAR::popErrorHandling(); |
return PEAR::raiseError('Could not save existing configuration file '. |
$old . ', unable to install. Please set temp_dir ' . |
'configuration variable to a writeable location and try again'); |
} |
PEAR::popErrorHandling(); |
$this->installer->log(0, "WARNING: configuration file $old is being installed as $test[2], you should manually merge in changes to the existing configuration file"); |
$this->installer->addFileOperation('rename', array($temp_file, $old, false)); |
$this->installer->addFileOperation('delete', array($temp_file)); |
} |
} |
return $test; |
} |
} |
/branches/v1.3-critias/bibliotheque/pear/PEAR/Installer/Role/Php.xml |
---|
New file |
0,0 → 1,15 |
<role version="1.0"> |
<releasetypes>php</releasetypes> |
<releasetypes>extsrc</releasetypes> |
<releasetypes>extbin</releasetypes> |
<releasetypes>zendextsrc</releasetypes> |
<releasetypes>zendextbin</releasetypes> |
<installable>1</installable> |
<locationconfig>php_dir</locationconfig> |
<honorsbaseinstall>1</honorsbaseinstall> |
<unusualbaseinstall /> |
<phpfile>1</phpfile> |
<executable /> |
<phpextension /> |
<config_vars /> |
</role> |
/branches/v1.3-critias/bibliotheque/pear/PEAR/Installer/Role/Ext.php |
---|
New file |
0,0 → 1,27 |
<?php |
/** |
* PEAR_Installer_Role_Ext |
* |
* PHP versions 4 and 5 |
* |
* @category pear |
* @package PEAR |
* @author Greg Beaver <cellog@php.net> |
* @copyright 1997-2009 The Authors |
* @license http://opensource.org/licenses/bsd-license.php New BSD License |
* @link http://pear.php.net/package/PEAR |
* @since File available since Release 1.4.0a1 |
*/ |
/** |
* @category pear |
* @package PEAR |
* @author Greg Beaver <cellog@php.net> |
* @copyright 1997-2009 The Authors |
* @license http://opensource.org/licenses/bsd-license.php New BSD License |
* @version Release: 1.10.1 |
* @link http://pear.php.net/package/PEAR |
* @since Class available since Release 1.4.0a1 |
*/ |
class PEAR_Installer_Role_Ext extends PEAR_Installer_Role_Common {} |
?> |
/branches/v1.3-critias/bibliotheque/pear/PEAR/Installer/Role/Src.xml |
---|
New file |
0,0 → 1,12 |
<role version="1.0"> |
<releasetypes>extsrc</releasetypes> |
<releasetypes>zendextsrc</releasetypes> |
<installable>1</installable> |
<locationconfig>temp_dir</locationconfig> |
<honorsbaseinstall /> |
<unusualbaseinstall /> |
<phpfile /> |
<executable /> |
<phpextension /> |
<config_vars /> |
</role> |
/branches/v1.3-critias/bibliotheque/pear/PEAR/Installer/Role/Script.php |
---|
New file |
0,0 → 1,27 |
<?php |
/** |
* PEAR_Installer_Role_Script |
* |
* PHP versions 4 and 5 |
* |
* @category pear |
* @package PEAR |
* @author Greg Beaver <cellog@php.net> |
* @copyright 1997-2009 The Authors |
* @license http://opensource.org/licenses/bsd-license.php New BSD License |
* @link http://pear.php.net/package/PEAR |
* @since File available since Release 1.4.0a1 |
*/ |
/** |
* @category pear |
* @package PEAR |
* @author Greg Beaver <cellog@php.net> |
* @copyright 1997-2009 The Authors |
* @license http://opensource.org/licenses/bsd-license.php New BSD License |
* @version Release: 1.10.1 |
* @link http://pear.php.net/package/PEAR |
* @since Class available since Release 1.4.0a1 |
*/ |
class PEAR_Installer_Role_Script extends PEAR_Installer_Role_Common {} |
?> |
/branches/v1.3-critias/bibliotheque/pear/PEAR/Installer/Role/Doc.php |
---|
New file |
0,0 → 1,27 |
<?php |
/** |
* PEAR_Installer_Role_Doc |
* |
* PHP versions 4 and 5 |
* |
* @category pear |
* @package PEAR |
* @author Greg Beaver <cellog@php.net> |
* @copyright 1997-2009 The Authors |
* @license http://opensource.org/licenses/bsd-license.php New BSD License |
* @link http://pear.php.net/package/PEAR |
* @since File available since Release 1.4.0a1 |
*/ |
/** |
* @category pear |
* @package PEAR |
* @author Greg Beaver <cellog@php.net> |
* @copyright 1997-2009 The Authors |
* @license http://opensource.org/licenses/bsd-license.php New BSD License |
* @version Release: 1.10.1 |
* @link http://pear.php.net/package/PEAR |
* @since Class available since Release 1.4.0a1 |
*/ |
class PEAR_Installer_Role_Doc extends PEAR_Installer_Role_Common {} |
?> |
/branches/v1.3-critias/bibliotheque/pear/PEAR/Installer/Role/Cfg.xml |
---|
New file |
0,0 → 1,15 |
<role version="1.0"> |
<releasetypes>php</releasetypes> |
<releasetypes>extsrc</releasetypes> |
<releasetypes>extbin</releasetypes> |
<releasetypes>zendextsrc</releasetypes> |
<releasetypes>zendextbin</releasetypes> |
<installable>1</installable> |
<locationconfig>cfg_dir</locationconfig> |
<honorsbaseinstall /> |
<unusualbaseinstall>1</unusualbaseinstall> |
<phpfile /> |
<executable /> |
<phpextension /> |
<config_vars /> |
</role> |
/branches/v1.3-critias/bibliotheque/pear/PEAR/Installer/Role/Data.php |
---|
New file |
0,0 → 1,27 |
<?php |
/** |
* PEAR_Installer_Role_Data |
* |
* PHP versions 4 and 5 |
* |
* @category pear |
* @package PEAR |
* @author Greg Beaver <cellog@php.net> |
* @copyright 1997-2009 The Authors |
* @license http://opensource.org/licenses/bsd-license.php New BSD License |
* @link http://pear.php.net/package/PEAR |
* @since File available since Release 1.4.0a1 |
*/ |
/** |
* @category pear |
* @package PEAR |
* @author Greg Beaver <cellog@php.net> |
* @copyright 1997-2009 The Authors |
* @license http://opensource.org/licenses/bsd-license.php New BSD License |
* @version Release: 1.10.1 |
* @link http://pear.php.net/package/PEAR |
* @since Class available since Release 1.4.0a1 |
*/ |
class PEAR_Installer_Role_Data extends PEAR_Installer_Role_Common {} |
?> |
/branches/v1.3-critias/bibliotheque/pear/PEAR/Installer/Role/Ext.xml |
---|
New file |
0,0 → 1,12 |
<role version="1.0"> |
<releasetypes>extbin</releasetypes> |
<releasetypes>zendextbin</releasetypes> |
<installable>1</installable> |
<locationconfig>ext_dir</locationconfig> |
<honorsbaseinstall>1</honorsbaseinstall> |
<unusualbaseinstall /> |
<phpfile /> |
<executable /> |
<phpextension>1</phpextension> |
<config_vars /> |
</role> |
/branches/v1.3-critias/bibliotheque/pear/PEAR/Installer/Role/Man.php |
---|
New file |
0,0 → 1,28 |
<?php |
/** |
* PEAR_Installer_Role_Man |
* |
* PHP versions 4 and 5 |
* |
* @category pear |
* @package PEAR |
* @author Hannes Magnusson <bjori@php.net> |
* @copyright 2011 The Authors |
* @license http://opensource.org/licenses/bsd-license.php New BSD License |
* @version SVN: $Id: $ |
* @link http://pear.php.net/package/PEAR |
* @since File available since Release 1.10.0 |
*/ |
/** |
* @category pear |
* @package PEAR |
* @author Hannes Magnusson <bjori@php.net> |
* @copyright 2011 The Authors |
* @license http://opensource.org/licenses/bsd-license.php New BSD License |
* @version Release: 1.10.1 |
* @link http://pear.php.net/package/PEAR |
* @since Class available since Release 1.10.0 |
*/ |
class PEAR_Installer_Role_Man extends PEAR_Installer_Role_Common {} |
?> |
/branches/v1.3-critias/bibliotheque/pear/PEAR/Installer/Role/Script.xml |
---|
New file |
0,0 → 1,15 |
<role version="1.0"> |
<releasetypes>php</releasetypes> |
<releasetypes>extsrc</releasetypes> |
<releasetypes>extbin</releasetypes> |
<releasetypes>zendextsrc</releasetypes> |
<releasetypes>zendextbin</releasetypes> |
<installable>1</installable> |
<locationconfig>bin_dir</locationconfig> |
<honorsbaseinstall>1</honorsbaseinstall> |
<unusualbaseinstall /> |
<phpfile /> |
<executable>1</executable> |
<phpextension /> |
<config_vars /> |
</role> |
/branches/v1.3-critias/bibliotheque/pear/PEAR/Installer/Role/Doc.xml |
---|
New file |
0,0 → 1,15 |
<role version="1.0"> |
<releasetypes>php</releasetypes> |
<releasetypes>extsrc</releasetypes> |
<releasetypes>extbin</releasetypes> |
<releasetypes>zendextsrc</releasetypes> |
<releasetypes>zendextbin</releasetypes> |
<installable>1</installable> |
<locationconfig>doc_dir</locationconfig> |
<honorsbaseinstall /> |
<unusualbaseinstall /> |
<phpfile /> |
<executable /> |
<phpextension /> |
<config_vars /> |
</role> |
/branches/v1.3-critias/bibliotheque/pear/PEAR/Installer/Role/Test.php |
---|
New file |
0,0 → 1,27 |
<?php |
/** |
* PEAR_Installer_Role_Test |
* |
* PHP versions 4 and 5 |
* |
* @category pear |
* @package PEAR |
* @author Greg Beaver <cellog@php.net> |
* @copyright 1997-2009 The Authors |
* @license http://opensource.org/licenses/bsd-license.php New BSD License |
* @link http://pear.php.net/package/PEAR |
* @since File available since Release 1.4.0a1 |
*/ |
/** |
* @category pear |
* @package PEAR |
* @author Greg Beaver <cellog@php.net> |
* @copyright 1997-2009 The Authors |
* @license http://opensource.org/licenses/bsd-license.php New BSD License |
* @version Release: 1.10.1 |
* @link http://pear.php.net/package/PEAR |
* @since Class available since Release 1.4.0a1 |
*/ |
class PEAR_Installer_Role_Test extends PEAR_Installer_Role_Common {} |
?> |
/branches/v1.3-critias/bibliotheque/pear/PEAR/Installer/Role/Data.xml |
---|
New file |
0,0 → 1,15 |
<role version="1.0"> |
<releasetypes>php</releasetypes> |
<releasetypes>extsrc</releasetypes> |
<releasetypes>extbin</releasetypes> |
<releasetypes>zendextsrc</releasetypes> |
<releasetypes>zendextbin</releasetypes> |
<installable>1</installable> |
<locationconfig>data_dir</locationconfig> |
<honorsbaseinstall /> |
<unusualbaseinstall /> |
<phpfile /> |
<executable /> |
<phpextension /> |
<config_vars /> |
</role> |
/branches/v1.3-critias/bibliotheque/pear/PEAR/Installer/Role/Www.php |
---|
New file |
0,0 → 1,27 |
<?php |
/** |
* PEAR_Installer_Role_Www |
* |
* PHP versions 4 and 5 |
* |
* @category pear |
* @package PEAR |
* @author Greg Beaver <cellog@php.net> |
* @copyright 2007-2009 The Authors |
* @license http://opensource.org/licenses/bsd-license.php New BSD License |
* @link http://pear.php.net/package/PEAR |
* @since File available since Release 1.7.0 |
*/ |
/** |
* @category pear |
* @package PEAR |
* @author Greg Beaver <cellog@php.net> |
* @copyright 2007-2009 The Authors |
* @license http://opensource.org/licenses/bsd-license.php New BSD License |
* @version Release: 1.10.1 |
* @link http://pear.php.net/package/PEAR |
* @since Class available since Release 1.7.0 |
*/ |
class PEAR_Installer_Role_Www extends PEAR_Installer_Role_Common {} |
?> |
/branches/v1.3-critias/bibliotheque/pear/PEAR/Installer/Role/Man.xml |
---|
New file |
0,0 → 1,15 |
<role version="1.0"> |
<releasetypes>php</releasetypes> |
<releasetypes>extsrc</releasetypes> |
<releasetypes>extbin</releasetypes> |
<releasetypes>zendextsrc</releasetypes> |
<releasetypes>zendextbin</releasetypes> |
<installable>1</installable> |
<locationconfig>man_dir</locationconfig> |
<honorsbaseinstall>1</honorsbaseinstall> |
<unusualbaseinstall /> |
<phpfile /> |
<executable /> |
<phpextension /> |
<config_vars /> |
</role> |
/branches/v1.3-critias/bibliotheque/pear/PEAR/Installer/Role/Php.php |
---|
New file |
0,0 → 1,27 |
<?php |
/** |
* PEAR_Installer_Role_Php |
* |
* PHP versions 4 and 5 |
* |
* @category pear |
* @package PEAR |
* @author Greg Beaver <cellog@php.net> |
* @copyright 1997-2009 The Authors |
* @license http://opensource.org/licenses/bsd-license.php New BSD License |
* @link http://pear.php.net/package/PEAR |
* @since File available since Release 1.4.0a1 |
*/ |
/** |
* @category pear |
* @package PEAR |
* @author Greg Beaver <cellog@php.net> |
* @copyright 1997-2009 The Authors |
* @license http://opensource.org/licenses/bsd-license.php New BSD License |
* @version Release: 1.10.1 |
* @link http://pear.php.net/package/PEAR |
* @since Class available since Release 1.4.0a1 |
*/ |
class PEAR_Installer_Role_Php extends PEAR_Installer_Role_Common {} |
?> |
/branches/v1.3-critias/bibliotheque/pear/PEAR/Installer/Role/Src.php |
---|
New file |
0,0 → 1,33 |
<?php |
/** |
* PEAR_Installer_Role_Src |
* |
* PHP versions 4 and 5 |
* |
* @category pear |
* @package PEAR |
* @author Greg Beaver <cellog@php.net> |
* @copyright 1997-2009 The Authors |
* @license http://opensource.org/licenses/bsd-license.php New BSD License |
* @link http://pear.php.net/package/PEAR |
* @since File available since Release 1.4.0a1 |
*/ |
/** |
* @category pear |
* @package PEAR |
* @author Greg Beaver <cellog@php.net> |
* @copyright 1997-2009 The Authors |
* @license http://opensource.org/licenses/bsd-license.php New BSD License |
* @version Release: 1.10.1 |
* @link http://pear.php.net/package/PEAR |
* @since Class available since Release 1.4.0a1 |
*/ |
class PEAR_Installer_Role_Src extends PEAR_Installer_Role_Common |
{ |
function setup(&$installer, $pkg, $atts, $file) |
{ |
$installer->source_files++; |
} |
} |
?> |
/branches/v1.3-critias/bibliotheque/pear/PEAR/Installer/Role/Test.xml |
---|
New file |
0,0 → 1,15 |
<role version="1.0"> |
<releasetypes>php</releasetypes> |
<releasetypes>extsrc</releasetypes> |
<releasetypes>extbin</releasetypes> |
<releasetypes>zendextsrc</releasetypes> |
<releasetypes>zendextbin</releasetypes> |
<installable>1</installable> |
<locationconfig>test_dir</locationconfig> |
<honorsbaseinstall /> |
<unusualbaseinstall /> |
<phpfile /> |
<executable /> |
<phpextension /> |
<config_vars /> |
</role> |
/branches/v1.3-critias/bibliotheque/pear/PEAR/Installer/Role/Common.php |
---|
New file |
0,0 → 1,173 |
<?php |
/** |
* Base class for all installation roles. |
* |
* PHP versions 4 and 5 |
* |
* @category pear |
* @package PEAR |
* @author Greg Beaver <cellog@php.net> |
* @copyright 1997-2006 The PHP Group |
* @license http://opensource.org/licenses/bsd-license.php New BSD License |
* @link http://pear.php.net/package/PEAR |
* @since File available since Release 1.4.0a1 |
*/ |
/** |
* Base class for all installation roles. |
* |
* This class allows extensibility of file roles. Packages with complex |
* customization can now provide custom file roles along with the possibility of |
* adding configuration values to match. |
* @category pear |
* @package PEAR |
* @author Greg Beaver <cellog@php.net> |
* @copyright 1997-2006 The PHP Group |
* @license http://opensource.org/licenses/bsd-license.php New BSD License |
* @version Release: 1.10.1 |
* @link http://pear.php.net/package/PEAR |
* @since Class available since Release 1.4.0a1 |
*/ |
class PEAR_Installer_Role_Common |
{ |
/** |
* @var PEAR_Config |
* @access protected |
*/ |
var $config; |
/** |
* @param PEAR_Config |
*/ |
function __construct(&$config) |
{ |
$this->config = $config; |
} |
/** |
* Retrieve configuration information about a file role from its XML info |
* |
* @param string $role Role Classname, as in "PEAR_Installer_Role_Data" |
* @return array |
*/ |
function getInfo($role) |
{ |
if (empty($GLOBALS['_PEAR_INSTALLER_ROLES'][$role])) { |
return PEAR::raiseError('Unknown Role class: "' . $role . '"'); |
} |
return $GLOBALS['_PEAR_INSTALLER_ROLES'][$role]; |
} |
/** |
* This is called for each file to set up the directories and files |
* @param PEAR_PackageFile_v1|PEAR_PackageFile_v2 |
* @param array attributes from the <file> tag |
* @param string file name |
* @return array an array consisting of: |
* |
* 1 the original, pre-baseinstalldir installation directory |
* 2 the final installation directory |
* 3 the full path to the final location of the file |
* 4 the location of the pre-installation file |
*/ |
function processInstallation($pkg, $atts, $file, $tmp_path, $layer = null) |
{ |
$roleInfo = PEAR_Installer_Role_Common::getInfo('PEAR_Installer_Role_' . |
ucfirst(str_replace('pear_installer_role_', '', strtolower(get_class($this))))); |
if (PEAR::isError($roleInfo)) { |
return $roleInfo; |
} |
if (!$roleInfo['locationconfig']) { |
return false; |
} |
if ($roleInfo['honorsbaseinstall']) { |
$dest_dir = $save_destdir = $this->config->get($roleInfo['locationconfig'], $layer, |
$pkg->getChannel()); |
if (!empty($atts['baseinstalldir'])) { |
$dest_dir .= DIRECTORY_SEPARATOR . $atts['baseinstalldir']; |
} |
} elseif ($roleInfo['unusualbaseinstall']) { |
$dest_dir = $save_destdir = $this->config->get($roleInfo['locationconfig'], |
$layer, $pkg->getChannel()) . DIRECTORY_SEPARATOR . $pkg->getPackage(); |
if (!empty($atts['baseinstalldir'])) { |
$dest_dir .= DIRECTORY_SEPARATOR . $atts['baseinstalldir']; |
} |
} else { |
$dest_dir = $save_destdir = $this->config->get($roleInfo['locationconfig'], |
$layer, $pkg->getChannel()) . DIRECTORY_SEPARATOR . $pkg->getPackage(); |
} |
if (dirname($file) != '.' && empty($atts['install-as'])) { |
$dest_dir .= DIRECTORY_SEPARATOR . dirname($file); |
} |
if (empty($atts['install-as'])) { |
$dest_file = $dest_dir . DIRECTORY_SEPARATOR . basename($file); |
} else { |
$dest_file = $dest_dir . DIRECTORY_SEPARATOR . $atts['install-as']; |
} |
$orig_file = $tmp_path . DIRECTORY_SEPARATOR . $file; |
// Clean up the DIRECTORY_SEPARATOR mess |
$ds2 = DIRECTORY_SEPARATOR . DIRECTORY_SEPARATOR; |
list($dest_dir, $dest_file, $orig_file) = preg_replace(array('!\\\\+!', '!/!', "!$ds2+!"), |
array(DIRECTORY_SEPARATOR, DIRECTORY_SEPARATOR, |
DIRECTORY_SEPARATOR), |
array($dest_dir, $dest_file, $orig_file)); |
return array($save_destdir, $dest_dir, $dest_file, $orig_file); |
} |
/** |
* Get the name of the configuration variable that specifies the location of this file |
* @return string|false |
*/ |
function getLocationConfig() |
{ |
$roleInfo = PEAR_Installer_Role_Common::getInfo('PEAR_Installer_Role_' . |
ucfirst(str_replace('pear_installer_role_', '', strtolower(get_class($this))))); |
if (PEAR::isError($roleInfo)) { |
return $roleInfo; |
} |
return $roleInfo['locationconfig']; |
} |
/** |
* Do any unusual setup here |
* @param PEAR_Installer |
* @param PEAR_PackageFile_v2 |
* @param array file attributes |
* @param string file name |
*/ |
function setup(&$installer, $pkg, $atts, $file) |
{ |
} |
function isExecutable() |
{ |
$roleInfo = PEAR_Installer_Role_Common::getInfo('PEAR_Installer_Role_' . |
ucfirst(str_replace('pear_installer_role_', '', strtolower(get_class($this))))); |
if (PEAR::isError($roleInfo)) { |
return $roleInfo; |
} |
return $roleInfo['executable']; |
} |
function isInstallable() |
{ |
$roleInfo = PEAR_Installer_Role_Common::getInfo('PEAR_Installer_Role_' . |
ucfirst(str_replace('pear_installer_role_', '', strtolower(get_class($this))))); |
if (PEAR::isError($roleInfo)) { |
return $roleInfo; |
} |
return $roleInfo['installable']; |
} |
function isExtension() |
{ |
$roleInfo = PEAR_Installer_Role_Common::getInfo('PEAR_Installer_Role_' . |
ucfirst(str_replace('pear_installer_role_', '', strtolower(get_class($this))))); |
if (PEAR::isError($roleInfo)) { |
return $roleInfo; |
} |
return $roleInfo['phpextension']; |
} |
} |
?> |
/branches/v1.3-critias/bibliotheque/pear/PEAR/Downloader/Package.php |
---|
New file |
0,0 → 1,1981 |
<?php |
/** |
* PEAR_Downloader_Package |
* |
* PHP versions 4 and 5 |
* |
* @category pear |
* @package PEAR |
* @author Greg Beaver <cellog@php.net> |
* @copyright 1997-2009 The Authors |
* @license http://opensource.org/licenses/bsd-license.php New BSD License |
* @link http://pear.php.net/package/PEAR |
* @since File available since Release 1.4.0a1 |
*/ |
/** |
* Error code when parameter initialization fails because no releases |
* exist within preferred_state, but releases do exist |
*/ |
define('PEAR_DOWNLOADER_PACKAGE_STATE', -1003); |
/** |
* Error code when parameter initialization fails because no releases |
* exist that will work with the existing PHP version |
*/ |
define('PEAR_DOWNLOADER_PACKAGE_PHPVERSION', -1004); |
/** |
* Coordinates download parameters and manages their dependencies |
* prior to downloading them. |
* |
* Input can come from three sources: |
* |
* - local files (archives or package.xml) |
* - remote files (downloadable urls) |
* - abstract package names |
* |
* The first two elements are handled cleanly by PEAR_PackageFile, but the third requires |
* accessing pearweb's xml-rpc interface to determine necessary dependencies, and the |
* format returned of dependencies is slightly different from that used in package.xml. |
* |
* This class hides the differences between these elements, and makes automatic |
* dependency resolution a piece of cake. It also manages conflicts when |
* two classes depend on incompatible dependencies, or differing versions of the same |
* package dependency. In addition, download will not be attempted if the php version is |
* not supported, PEAR installer version is not supported, or non-PECL extensions are not |
* installed. |
* @category pear |
* @package PEAR |
* @author Greg Beaver <cellog@php.net> |
* @copyright 1997-2009 The Authors |
* @license http://opensource.org/licenses/bsd-license.php New BSD License |
* @version Release: 1.10.1 |
* @link http://pear.php.net/package/PEAR |
* @since Class available since Release 1.4.0a1 |
*/ |
class PEAR_Downloader_Package |
{ |
/** |
* @var PEAR_Downloader |
*/ |
var $_downloader; |
/** |
* @var PEAR_Config |
*/ |
var $_config; |
/** |
* @var PEAR_Registry |
*/ |
var $_registry; |
/** |
* Used to implement packagingroot properly |
* @var PEAR_Registry |
*/ |
var $_installRegistry; |
/** |
* @var PEAR_PackageFile_v1|PEAR_PackageFile|v2 |
*/ |
var $_packagefile; |
/** |
* @var array |
*/ |
var $_parsedname; |
/** |
* @var array |
*/ |
var $_downloadURL; |
/** |
* @var array |
*/ |
var $_downloadDeps = array(); |
/** |
* @var boolean |
*/ |
var $_valid = false; |
/** |
* @var boolean |
*/ |
var $_analyzed = false; |
/** |
* if this or a parent package was invoked with Package-state, this is set to the |
* state variable. |
* |
* This allows temporary reassignment of preferred_state for a parent package and all of |
* its dependencies. |
* @var string|false |
*/ |
var $_explicitState = false; |
/** |
* If this package is invoked with Package#group, this variable will be true |
*/ |
var $_explicitGroup = false; |
/** |
* Package type local|url |
* @var string |
*/ |
var $_type; |
/** |
* Contents of package.xml, if downloaded from a remote channel |
* @var string|false |
* @access private |
*/ |
var $_rawpackagefile; |
/** |
* @var boolean |
* @access private |
*/ |
var $_validated = false; |
/** |
* @param PEAR_Downloader |
*/ |
function __construct(&$downloader) |
{ |
$this->_downloader = &$downloader; |
$this->_config = &$this->_downloader->config; |
$this->_registry = &$this->_config->getRegistry(); |
$options = $downloader->getOptions(); |
if (isset($options['packagingroot'])) { |
$this->_config->setInstallRoot($options['packagingroot']); |
$this->_installRegistry = &$this->_config->getRegistry(); |
$this->_config->setInstallRoot(false); |
} else { |
$this->_installRegistry = &$this->_registry; |
} |
$this->_valid = $this->_analyzed = false; |
} |
/** |
* Parse the input and determine whether this is a local file, a remote uri, or an |
* abstract package name. |
* |
* This is the heart of the PEAR_Downloader_Package(), and is used in |
* {@link PEAR_Downloader::download()} |
* @param string |
* @return bool|PEAR_Error |
*/ |
function initialize($param) |
{ |
$origErr = $this->_fromFile($param); |
if ($this->_valid) { |
return true; |
} |
$options = $this->_downloader->getOptions(); |
if (isset($options['offline'])) { |
if (PEAR::isError($origErr) && !isset($options['soft'])) { |
foreach ($origErr->getUserInfo() as $userInfo) { |
if (isset($userInfo['message'])) { |
$this->_downloader->log(0, $userInfo['message']); |
} |
} |
$this->_downloader->log(0, $origErr->getMessage()); |
} |
return PEAR::raiseError('Cannot download non-local package "' . $param . '"'); |
} |
$err = $this->_fromUrl($param); |
if (PEAR::isError($err) || !$this->_valid) { |
if ($this->_type == 'url') { |
if (PEAR::isError($err) && !isset($options['soft'])) { |
$this->_downloader->log(0, $err->getMessage()); |
} |
return PEAR::raiseError("Invalid or missing remote package file"); |
} |
$err = $this->_fromString($param); |
if (PEAR::isError($err) || !$this->_valid) { |
if (PEAR::isError($err) && $err->getCode() == PEAR_DOWNLOADER_PACKAGE_STATE) { |
return false; // instruct the downloader to silently skip |
} |
if (isset($this->_type) && $this->_type == 'local' && PEAR::isError($origErr)) { |
if (is_array($origErr->getUserInfo())) { |
foreach ($origErr->getUserInfo() as $err) { |
if (is_array($err)) { |
$err = $err['message']; |
} |
if (!isset($options['soft'])) { |
$this->_downloader->log(0, $err); |
} |
} |
} |
if (!isset($options['soft'])) { |
$this->_downloader->log(0, $origErr->getMessage()); |
} |
if (is_array($param)) { |
$param = $this->_registry->parsedPackageNameToString($param, true); |
} |
if (!isset($options['soft'])) { |
$this->_downloader->log(2, "Cannot initialize '$param', invalid or missing package file"); |
} |
// Passing no message back - already logged above |
return PEAR::raiseError(); |
} |
if (PEAR::isError($err) && !isset($options['soft'])) { |
$this->_downloader->log(0, $err->getMessage()); |
} |
if (is_array($param)) { |
$param = $this->_registry->parsedPackageNameToString($param, true); |
} |
if (!isset($options['soft'])) { |
$this->_downloader->log(2, "Cannot initialize '$param', invalid or missing package file"); |
} |
// Passing no message back - already logged above |
return PEAR::raiseError(); |
} |
} |
return true; |
} |
/** |
* Retrieve any non-local packages |
* @return PEAR_PackageFile_v1|PEAR_PackageFile_v2|PEAR_Error |
*/ |
function &download() |
{ |
if (isset($this->_packagefile)) { |
return $this->_packagefile; |
} |
if (isset($this->_downloadURL['url'])) { |
$this->_isvalid = false; |
$info = $this->getParsedPackage(); |
foreach ($info as $i => $p) { |
$info[$i] = strtolower($p); |
} |
$err = $this->_fromUrl($this->_downloadURL['url'], |
$this->_registry->parsedPackageNameToString($this->_parsedname, true)); |
$newinfo = $this->getParsedPackage(); |
foreach ($newinfo as $i => $p) { |
$newinfo[$i] = strtolower($p); |
} |
if ($info != $newinfo) { |
do { |
if ($info['channel'] == 'pecl.php.net' && $newinfo['channel'] == 'pear.php.net') { |
$info['channel'] = 'pear.php.net'; |
if ($info == $newinfo) { |
// skip the channel check if a pecl package says it's a PEAR package |
break; |
} |
} |
if ($info['channel'] == 'pear.php.net' && $newinfo['channel'] == 'pecl.php.net') { |
$info['channel'] = 'pecl.php.net'; |
if ($info == $newinfo) { |
// skip the channel check if a pecl package says it's a PEAR package |
break; |
} |
} |
return PEAR::raiseError('CRITICAL ERROR: We are ' . |
$this->_registry->parsedPackageNameToString($info) . ', but the file ' . |
'downloaded claims to be ' . |
$this->_registry->parsedPackageNameToString($this->getParsedPackage())); |
} while (false); |
} |
if (PEAR::isError($err) || !$this->_valid) { |
return $err; |
} |
} |
$this->_type = 'local'; |
return $this->_packagefile; |
} |
function &getPackageFile() |
{ |
return $this->_packagefile; |
} |
function &getDownloader() |
{ |
return $this->_downloader; |
} |
function getType() |
{ |
return $this->_type; |
} |
/** |
* Like {@link initialize()}, but operates on a dependency |
*/ |
function fromDepURL($dep) |
{ |
$this->_downloadURL = $dep; |
if (isset($dep['uri'])) { |
$options = $this->_downloader->getOptions(); |
if (!extension_loaded("zlib") || isset($options['nocompress'])) { |
$ext = '.tar'; |
} else { |
$ext = '.tgz'; |
} |
PEAR::pushErrorHandling(PEAR_ERROR_RETURN); |
$err = $this->_fromUrl($dep['uri'] . $ext); |
PEAR::popErrorHandling(); |
if (PEAR::isError($err)) { |
if (!isset($options['soft'])) { |
$this->_downloader->log(0, $err->getMessage()); |
} |
return PEAR::raiseError('Invalid uri dependency "' . $dep['uri'] . $ext . '", ' . |
'cannot download'); |
} |
} else { |
$this->_parsedname = |
array( |
'package' => $dep['info']->getPackage(), |
'channel' => $dep['info']->getChannel(), |
'version' => $dep['version'] |
); |
if (!isset($dep['nodefault'])) { |
$this->_parsedname['group'] = 'default'; // download the default dependency group |
$this->_explicitGroup = false; |
} |
$this->_rawpackagefile = $dep['raw']; |
} |
} |
function detectDependencies($params) |
{ |
$options = $this->_downloader->getOptions(); |
if (isset($options['downloadonly'])) { |
return; |
} |
if (isset($options['offline'])) { |
$this->_downloader->log(3, 'Skipping dependency download check, --offline specified'); |
return; |
} |
$pname = $this->getParsedPackage(); |
if (!$pname) { |
return; |
} |
$deps = $this->getDeps(); |
if (!$deps) { |
return; |
} |
if (isset($deps['required'])) { // package.xml 2.0 |
return $this->_detect2($deps, $pname, $options, $params); |
} |
return $this->_detect1($deps, $pname, $options, $params); |
} |
function setValidated() |
{ |
$this->_validated = true; |
} |
function alreadyValidated() |
{ |
return $this->_validated; |
} |
/** |
* Remove packages to be downloaded that are already installed |
* @param array of PEAR_Downloader_Package objects |
*/ |
public static function removeInstalled(&$params) |
{ |
if (!isset($params[0])) { |
return; |
} |
$options = $params[0]->_downloader->getOptions(); |
if (!isset($options['downloadonly'])) { |
foreach ($params as $i => $param) { |
$package = $param->getPackage(); |
$channel = $param->getChannel(); |
// remove self if already installed with this version |
// this does not need any pecl magic - we only remove exact matches |
if ($param->_installRegistry->packageExists($package, $channel)) { |
$packageVersion = $param->_installRegistry->packageInfo($package, 'version', $channel); |
if (version_compare($packageVersion, $param->getVersion(), '==')) { |
if (!isset($options['force']) && !isset($options['packagingroot'])) { |
$info = $param->getParsedPackage(); |
unset($info['version']); |
unset($info['state']); |
if (!isset($options['soft'])) { |
$param->_downloader->log(1, 'Skipping package "' . |
$param->getShortName() . |
'", already installed as version ' . $packageVersion); |
} |
$params[$i] = false; |
} |
} elseif (!isset($options['force']) && !isset($options['upgrade']) && |
!isset($options['soft']) && !isset($options['packagingroot'])) { |
$info = $param->getParsedPackage(); |
$param->_downloader->log(1, 'Skipping package "' . |
$param->getShortName() . |
'", already installed as version ' . $packageVersion); |
$params[$i] = false; |
} |
} |
} |
} |
PEAR_Downloader_Package::removeDuplicates($params); |
} |
function _detect2($deps, $pname, $options, $params) |
{ |
$this->_downloadDeps = array(); |
$groupnotfound = false; |
foreach (array('package', 'subpackage') as $packagetype) { |
// get required dependency group |
if (isset($deps['required'][$packagetype])) { |
if (isset($deps['required'][$packagetype][0])) { |
foreach ($deps['required'][$packagetype] as $dep) { |
if (isset($dep['conflicts'])) { |
// skip any package that this package conflicts with |
continue; |
} |
$ret = $this->_detect2Dep($dep, $pname, 'required', $params); |
if (is_array($ret)) { |
$this->_downloadDeps[] = $ret; |
} elseif (PEAR::isError($ret) && !isset($options['soft'])) { |
$this->_downloader->log(0, $ret->getMessage()); |
} |
} |
} else { |
$dep = $deps['required'][$packagetype]; |
if (!isset($dep['conflicts'])) { |
// skip any package that this package conflicts with |
$ret = $this->_detect2Dep($dep, $pname, 'required', $params); |
if (is_array($ret)) { |
$this->_downloadDeps[] = $ret; |
} elseif (PEAR::isError($ret) && !isset($options['soft'])) { |
$this->_downloader->log(0, $ret->getMessage()); |
} |
} |
} |
} |
// get optional dependency group, if any |
if (isset($deps['optional'][$packagetype])) { |
$skipnames = array(); |
if (!isset($deps['optional'][$packagetype][0])) { |
$deps['optional'][$packagetype] = array($deps['optional'][$packagetype]); |
} |
foreach ($deps['optional'][$packagetype] as $dep) { |
$skip = false; |
if (!isset($options['alldeps'])) { |
$dep['package'] = $dep['name']; |
if (!isset($options['soft'])) { |
$this->_downloader->log(3, 'Notice: package "' . |
$this->_registry->parsedPackageNameToString($this->getParsedPackage(), |
true) . '" optional dependency "' . |
$this->_registry->parsedPackageNameToString(array('package' => |
$dep['name'], 'channel' => 'pear.php.net'), true) . |
'" will not be automatically downloaded'); |
} |
$skipnames[] = $this->_registry->parsedPackageNameToString($dep, true); |
$skip = true; |
unset($dep['package']); |
} |
$ret = $this->_detect2Dep($dep, $pname, 'optional', $params); |
if (PEAR::isError($ret) && !isset($options['soft'])) { |
$this->_downloader->log(0, $ret->getMessage()); |
} |
if (!$ret) { |
$dep['package'] = $dep['name']; |
$skip = count($skipnames) ? |
$skipnames[count($skipnames) - 1] : ''; |
if ($skip == |
$this->_registry->parsedPackageNameToString($dep, true)) { |
array_pop($skipnames); |
} |
} |
if (!$skip && is_array($ret)) { |
$this->_downloadDeps[] = $ret; |
} |
} |
if (count($skipnames)) { |
if (!isset($options['soft'])) { |
$this->_downloader->log(1, 'Did not download optional dependencies: ' . |
implode(', ', $skipnames) . |
', use --alldeps to download automatically'); |
} |
} |
} |
// get requested dependency group, if any |
$groupname = $this->getGroup(); |
$explicit = $this->_explicitGroup; |
if (!$groupname) { |
if (!$this->canDefault()) { |
continue; |
} |
$groupname = 'default'; // try the default dependency group |
} |
if ($groupnotfound) { |
continue; |
} |
if (isset($deps['group'])) { |
if (isset($deps['group']['attribs'])) { |
if (strtolower($deps['group']['attribs']['name']) == strtolower($groupname)) { |
$group = $deps['group']; |
} elseif ($explicit) { |
if (!isset($options['soft'])) { |
$this->_downloader->log(0, 'Warning: package "' . |
$this->_registry->parsedPackageNameToString($pname, true) . |
'" has no dependency ' . 'group named "' . $groupname . '"'); |
} |
$groupnotfound = true; |
continue; |
} |
} else { |
$found = false; |
foreach ($deps['group'] as $group) { |
if (strtolower($group['attribs']['name']) == strtolower($groupname)) { |
$found = true; |
break; |
} |
} |
if (!$found) { |
if ($explicit) { |
if (!isset($options['soft'])) { |
$this->_downloader->log(0, 'Warning: package "' . |
$this->_registry->parsedPackageNameToString($pname, true) . |
'" has no dependency ' . 'group named "' . $groupname . '"'); |
} |
} |
$groupnotfound = true; |
continue; |
} |
} |
} |
if (isset($group) && isset($group[$packagetype])) { |
if (isset($group[$packagetype][0])) { |
foreach ($group[$packagetype] as $dep) { |
$ret = $this->_detect2Dep($dep, $pname, 'dependency group "' . |
$group['attribs']['name'] . '"', $params); |
if (is_array($ret)) { |
$this->_downloadDeps[] = $ret; |
} elseif (PEAR::isError($ret) && !isset($options['soft'])) { |
$this->_downloader->log(0, $ret->getMessage()); |
} |
} |
} else { |
$ret = $this->_detect2Dep($group[$packagetype], $pname, |
'dependency group "' . |
$group['attribs']['name'] . '"', $params); |
if (is_array($ret)) { |
$this->_downloadDeps[] = $ret; |
} elseif (PEAR::isError($ret) && !isset($options['soft'])) { |
$this->_downloader->log(0, $ret->getMessage()); |
} |
} |
} |
} |
} |
function _detect2Dep($dep, $pname, $group, $params) |
{ |
if (isset($dep['conflicts'])) { |
return true; |
} |
$options = $this->_downloader->getOptions(); |
if (isset($dep['uri'])) { |
return array('uri' => $dep['uri'], 'dep' => $dep);; |
} |
$testdep = $dep; |
$testdep['package'] = $dep['name']; |
if (PEAR_Downloader_Package::willDownload($testdep, $params)) { |
$dep['package'] = $dep['name']; |
if (!isset($options['soft'])) { |
$this->_downloader->log(2, $this->getShortName() . ': Skipping ' . $group . |
' dependency "' . |
$this->_registry->parsedPackageNameToString($dep, true) . |
'", will be installed'); |
} |
return false; |
} |
$options = $this->_downloader->getOptions(); |
PEAR::pushErrorHandling(PEAR_ERROR_RETURN); |
if ($this->_explicitState) { |
$pname['state'] = $this->_explicitState; |
} |
$url = $this->_downloader->_getDepPackageDownloadUrl($dep, $pname); |
if (PEAR::isError($url)) { |
PEAR::popErrorHandling(); |
return $url; |
} |
$dep['package'] = $dep['name']; |
$ret = $this->_analyzeDownloadURL($url, 'dependency', $dep, $params, $group == 'optional' && |
!isset($options['alldeps']), true); |
PEAR::popErrorHandling(); |
if (PEAR::isError($ret)) { |
if (!isset($options['soft'])) { |
$this->_downloader->log(0, $ret->getMessage()); |
} |
return false; |
} |
// check to see if a dep is already installed and is the same or newer |
if (!isset($dep['min']) && !isset($dep['max']) && !isset($dep['recommended'])) { |
$oper = 'has'; |
} else { |
$oper = 'gt'; |
} |
// do not try to move this before getDepPackageDownloadURL |
// we can't determine whether upgrade is necessary until we know what |
// version would be downloaded |
if (!isset($options['force']) && $this->isInstalled($ret, $oper)) { |
$version = $this->_installRegistry->packageInfo($dep['name'], 'version', $dep['channel']); |
$dep['package'] = $dep['name']; |
if (!isset($options['soft'])) { |
$this->_downloader->log(3, $this->getShortName() . ': Skipping ' . $group . |
' dependency "' . |
$this->_registry->parsedPackageNameToString($dep, true) . |
'" version ' . $url['version'] . ', already installed as version ' . |
$version); |
} |
return false; |
} |
if (isset($dep['nodefault'])) { |
$ret['nodefault'] = true; |
} |
return $ret; |
} |
function _detect1($deps, $pname, $options, $params) |
{ |
$this->_downloadDeps = array(); |
$skipnames = array(); |
foreach ($deps as $dep) { |
$nodownload = false; |
if (isset ($dep['type']) && $dep['type'] === 'pkg') { |
$dep['channel'] = 'pear.php.net'; |
$dep['package'] = $dep['name']; |
switch ($dep['rel']) { |
case 'not' : |
continue 2; |
case 'ge' : |
case 'eq' : |
case 'gt' : |
case 'has' : |
$group = (!isset($dep['optional']) || $dep['optional'] == 'no') ? |
'required' : |
'optional'; |
if (PEAR_Downloader_Package::willDownload($dep, $params)) { |
$this->_downloader->log(2, $this->getShortName() . ': Skipping ' . $group |
. ' dependency "' . |
$this->_registry->parsedPackageNameToString($dep, true) . |
'", will be installed'); |
continue 2; |
} |
$fakedp = new PEAR_PackageFile_v1; |
$fakedp->setPackage($dep['name']); |
// skip internet check if we are not upgrading (bug #5810) |
if (!isset($options['upgrade']) && $this->isInstalled( |
$fakedp, $dep['rel'])) { |
$this->_downloader->log(2, $this->getShortName() . ': Skipping ' . $group |
. ' dependency "' . |
$this->_registry->parsedPackageNameToString($dep, true) . |
'", is already installed'); |
continue 2; |
} |
} |
PEAR::pushErrorHandling(PEAR_ERROR_RETURN); |
if ($this->_explicitState) { |
$pname['state'] = $this->_explicitState; |
} |
$url = $this->_downloader->_getDepPackageDownloadUrl($dep, $pname); |
$chan = 'pear.php.net'; |
if (PEAR::isError($url)) { |
// check to see if this is a pecl package that has jumped |
// from pear.php.net to pecl.php.net channel |
if (!class_exists('PEAR_Dependency2')) { |
require_once 'PEAR/Dependency2.php'; |
} |
$newdep = PEAR_Dependency2::normalizeDep($dep); |
$newdep = $newdep[0]; |
$newdep['channel'] = 'pecl.php.net'; |
$chan = 'pecl.php.net'; |
$url = $this->_downloader->_getDepPackageDownloadUrl($newdep, $pname); |
$obj = &$this->_installRegistry->getPackage($dep['name']); |
if (PEAR::isError($url)) { |
PEAR::popErrorHandling(); |
if ($obj !== null && $this->isInstalled($obj, $dep['rel'])) { |
$group = (!isset($dep['optional']) || $dep['optional'] == 'no') ? |
'required' : |
'optional'; |
$dep['package'] = $dep['name']; |
if (!isset($options['soft'])) { |
$this->_downloader->log(3, $this->getShortName() . |
': Skipping ' . $group . ' dependency "' . |
$this->_registry->parsedPackageNameToString($dep, true) . |
'", already installed as version ' . $obj->getVersion()); |
} |
$skip = count($skipnames) ? |
$skipnames[count($skipnames) - 1] : ''; |
if ($skip == |
$this->_registry->parsedPackageNameToString($dep, true)) { |
array_pop($skipnames); |
} |
continue; |
} else { |
if (isset($dep['optional']) && $dep['optional'] == 'yes') { |
$this->_downloader->log(2, $this->getShortName() . |
': Skipping optional dependency "' . |
$this->_registry->parsedPackageNameToString($dep, true) . |
'", no releases exist'); |
continue; |
} else { |
return $url; |
} |
} |
} |
} |
PEAR::popErrorHandling(); |
if (!isset($options['alldeps'])) { |
if (isset($dep['optional']) && $dep['optional'] == 'yes') { |
if (!isset($options['soft'])) { |
$this->_downloader->log(3, 'Notice: package "' . |
$this->getShortName() . |
'" optional dependency "' . |
$this->_registry->parsedPackageNameToString( |
array('channel' => $chan, 'package' => |
$dep['name']), true) . |
'" will not be automatically downloaded'); |
} |
$skipnames[] = $this->_registry->parsedPackageNameToString( |
array('channel' => $chan, 'package' => |
$dep['name']), true); |
$nodownload = true; |
} |
} |
if (!isset($options['alldeps']) && !isset($options['onlyreqdeps'])) { |
if (!isset($dep['optional']) || $dep['optional'] == 'no') { |
if (!isset($options['soft'])) { |
$this->_downloader->log(3, 'Notice: package "' . |
$this->getShortName() . |
'" required dependency "' . |
$this->_registry->parsedPackageNameToString( |
array('channel' => $chan, 'package' => |
$dep['name']), true) . |
'" will not be automatically downloaded'); |
} |
$skipnames[] = $this->_registry->parsedPackageNameToString( |
array('channel' => $chan, 'package' => |
$dep['name']), true); |
$nodownload = true; |
} |
} |
// check to see if a dep is already installed |
// do not try to move this before getDepPackageDownloadURL |
// we can't determine whether upgrade is necessary until we know what |
// version would be downloaded |
if (!isset($options['force']) && $this->isInstalled( |
$url, $dep['rel'])) { |
$group = (!isset($dep['optional']) || $dep['optional'] == 'no') ? |
'required' : |
'optional'; |
$dep['package'] = $dep['name']; |
if (isset($newdep)) { |
$version = $this->_installRegistry->packageInfo($newdep['name'], 'version', $newdep['channel']); |
} else { |
$version = $this->_installRegistry->packageInfo($dep['name'], 'version'); |
} |
$dep['version'] = $url['version']; |
if (!isset($options['soft'])) { |
$this->_downloader->log(3, $this->getShortName() . ': Skipping ' . $group . |
' dependency "' . |
$this->_registry->parsedPackageNameToString($dep, true) . |
'", already installed as version ' . $version); |
} |
$skip = count($skipnames) ? |
$skipnames[count($skipnames) - 1] : ''; |
if ($skip == |
$this->_registry->parsedPackageNameToString($dep, true)) { |
array_pop($skipnames); |
} |
continue; |
} |
if ($nodownload) { |
continue; |
} |
PEAR::pushErrorHandling(PEAR_ERROR_RETURN); |
if (isset($newdep)) { |
$dep = $newdep; |
} |
$dep['package'] = $dep['name']; |
$ret = $this->_analyzeDownloadURL($url, 'dependency', $dep, $params, |
isset($dep['optional']) && $dep['optional'] == 'yes' && |
!isset($options['alldeps']), true); |
PEAR::popErrorHandling(); |
if (PEAR::isError($ret)) { |
if (!isset($options['soft'])) { |
$this->_downloader->log(0, $ret->getMessage()); |
} |
continue; |
} |
$this->_downloadDeps[] = $ret; |
} |
} |
if (count($skipnames)) { |
if (!isset($options['soft'])) { |
$this->_downloader->log(1, 'Did not download dependencies: ' . |
implode(', ', $skipnames) . |
', use --alldeps or --onlyreqdeps to download automatically'); |
} |
} |
} |
function setDownloadURL($pkg) |
{ |
$this->_downloadURL = $pkg; |
} |
/** |
* Set the package.xml object for this downloaded package |
* |
* @param PEAR_PackageFile_v1|PEAR_PackageFile_v2 $pkg |
*/ |
function setPackageFile(&$pkg) |
{ |
$this->_packagefile = &$pkg; |
} |
function getShortName() |
{ |
return $this->_registry->parsedPackageNameToString(array('channel' => $this->getChannel(), |
'package' => $this->getPackage()), true); |
} |
function getParsedPackage() |
{ |
if (isset($this->_packagefile) || isset($this->_parsedname)) { |
return array('channel' => $this->getChannel(), |
'package' => $this->getPackage(), |
'version' => $this->getVersion()); |
} |
return false; |
} |
function getDownloadURL() |
{ |
return $this->_downloadURL; |
} |
function canDefault() |
{ |
if (isset($this->_downloadURL) && isset($this->_downloadURL['nodefault'])) { |
return false; |
} |
return true; |
} |
function getPackage() |
{ |
if (isset($this->_packagefile)) { |
return $this->_packagefile->getPackage(); |
} elseif (isset($this->_downloadURL['info'])) { |
return $this->_downloadURL['info']->getPackage(); |
} |
return false; |
} |
/** |
* @param PEAR_PackageFile_v1|PEAR_PackageFile_v2 |
*/ |
function isSubpackage(&$pf) |
{ |
if (isset($this->_packagefile)) { |
return $this->_packagefile->isSubpackage($pf); |
} elseif (isset($this->_downloadURL['info'])) { |
return $this->_downloadURL['info']->isSubpackage($pf); |
} |
return false; |
} |
function getPackageType() |
{ |
if (isset($this->_packagefile)) { |
return $this->_packagefile->getPackageType(); |
} elseif (isset($this->_downloadURL['info'])) { |
return $this->_downloadURL['info']->getPackageType(); |
} |
return false; |
} |
function isBundle() |
{ |
if (isset($this->_packagefile)) { |
return $this->_packagefile->getPackageType() == 'bundle'; |
} |
return false; |
} |
function getPackageXmlVersion() |
{ |
if (isset($this->_packagefile)) { |
return $this->_packagefile->getPackagexmlVersion(); |
} elseif (isset($this->_downloadURL['info'])) { |
return $this->_downloadURL['info']->getPackagexmlVersion(); |
} |
return '1.0'; |
} |
function getChannel() |
{ |
if (isset($this->_packagefile)) { |
return $this->_packagefile->getChannel(); |
} elseif (isset($this->_downloadURL['info'])) { |
return $this->_downloadURL['info']->getChannel(); |
} |
return false; |
} |
function getURI() |
{ |
if (isset($this->_packagefile)) { |
return $this->_packagefile->getURI(); |
} elseif (isset($this->_downloadURL['info'])) { |
return $this->_downloadURL['info']->getURI(); |
} |
return false; |
} |
function getVersion() |
{ |
if (isset($this->_packagefile)) { |
return $this->_packagefile->getVersion(); |
} elseif (isset($this->_downloadURL['version'])) { |
return $this->_downloadURL['version']; |
} |
return false; |
} |
function isCompatible($pf) |
{ |
if (isset($this->_packagefile)) { |
return $this->_packagefile->isCompatible($pf); |
} elseif (isset($this->_downloadURL['info'])) { |
return $this->_downloadURL['info']->isCompatible($pf); |
} |
return true; |
} |
function setGroup($group) |
{ |
$this->_parsedname['group'] = $group; |
} |
function getGroup() |
{ |
if (isset($this->_parsedname['group'])) { |
return $this->_parsedname['group']; |
} |
return ''; |
} |
function isExtension($name) |
{ |
if (isset($this->_packagefile)) { |
return $this->_packagefile->isExtension($name); |
} elseif (isset($this->_downloadURL['info'])) { |
if ($this->_downloadURL['info']->getPackagexmlVersion() == '2.0') { |
return $this->_downloadURL['info']->getProvidesExtension() == $name; |
} |
return false; |
} |
return false; |
} |
function getDeps() |
{ |
if (isset($this->_packagefile)) { |
$ver = $this->_packagefile->getPackagexmlVersion(); |
if (version_compare($ver, '2.0', '>=')) { |
return $this->_packagefile->getDeps(true); |
} |
return $this->_packagefile->getDeps(); |
} elseif (isset($this->_downloadURL['info'])) { |
$ver = $this->_downloadURL['info']->getPackagexmlVersion(); |
if (version_compare($ver, '2.0', '>=')) { |
return $this->_downloadURL['info']->getDeps(true); |
} |
return $this->_downloadURL['info']->getDeps(); |
} |
return array(); |
} |
/** |
* @param array Parsed array from {@link PEAR_Registry::parsePackageName()} or a dependency |
* returned from getDepDownloadURL() |
*/ |
function isEqual($param) |
{ |
if (is_object($param)) { |
$channel = $param->getChannel(); |
$package = $param->getPackage(); |
if ($param->getURI()) { |
$param = array( |
'channel' => $param->getChannel(), |
'package' => $param->getPackage(), |
'version' => $param->getVersion(), |
'uri' => $param->getURI(), |
); |
} else { |
$param = array( |
'channel' => $param->getChannel(), |
'package' => $param->getPackage(), |
'version' => $param->getVersion(), |
); |
} |
} else { |
if (isset($param['uri'])) { |
if ($this->getChannel() != '__uri') { |
return false; |
} |
return $param['uri'] == $this->getURI(); |
} |
$package = isset($param['package']) ? $param['package'] : $param['info']->getPackage(); |
$channel = isset($param['channel']) ? $param['channel'] : $param['info']->getChannel(); |
if (isset($param['rel'])) { |
if (!class_exists('PEAR_Dependency2')) { |
require_once 'PEAR/Dependency2.php'; |
} |
$newdep = PEAR_Dependency2::normalizeDep($param); |
$newdep = $newdep[0]; |
} elseif (isset($param['min'])) { |
$newdep = $param; |
} |
} |
if (isset($newdep)) { |
if (!isset($newdep['min'])) { |
$newdep['min'] = '0'; |
} |
if (!isset($newdep['max'])) { |
$newdep['max'] = '100000000000000000000'; |
} |
// use magic to support pecl packages suddenly jumping to the pecl channel |
// we need to support both dependency possibilities |
if ($channel == 'pear.php.net' && $this->getChannel() == 'pecl.php.net') { |
if ($package == $this->getPackage()) { |
$channel = 'pecl.php.net'; |
} |
} |
if ($channel == 'pecl.php.net' && $this->getChannel() == 'pear.php.net') { |
if ($package == $this->getPackage()) { |
$channel = 'pear.php.net'; |
} |
} |
return (strtolower($package) == strtolower($this->getPackage()) && |
$channel == $this->getChannel() && |
version_compare($newdep['min'], $this->getVersion(), '<=') && |
version_compare($newdep['max'], $this->getVersion(), '>=')); |
} |
// use magic to support pecl packages suddenly jumping to the pecl channel |
if ($channel == 'pecl.php.net' && $this->getChannel() == 'pear.php.net') { |
if (strtolower($package) == strtolower($this->getPackage())) { |
$channel = 'pear.php.net'; |
} |
} |
if (isset($param['version'])) { |
return (strtolower($package) == strtolower($this->getPackage()) && |
$channel == $this->getChannel() && |
$param['version'] == $this->getVersion()); |
} |
return strtolower($package) == strtolower($this->getPackage()) && |
$channel == $this->getChannel(); |
} |
function isInstalled($dep, $oper = '==') |
{ |
if (!$dep) { |
return false; |
} |
if ($oper != 'ge' && $oper != 'gt' && $oper != 'has' && $oper != '==') { |
return false; |
} |
if (is_object($dep)) { |
$package = $dep->getPackage(); |
$channel = $dep->getChannel(); |
if ($dep->getURI()) { |
$dep = array( |
'uri' => $dep->getURI(), |
'version' => $dep->getVersion(), |
); |
} else { |
$dep = array( |
'version' => $dep->getVersion(), |
); |
} |
} else { |
if (isset($dep['uri'])) { |
$channel = '__uri'; |
$package = $dep['dep']['name']; |
} else { |
$channel = $dep['info']->getChannel(); |
$package = $dep['info']->getPackage(); |
} |
} |
$options = $this->_downloader->getOptions(); |
$test = $this->_installRegistry->packageExists($package, $channel); |
if (!$test && $channel == 'pecl.php.net') { |
// do magic to allow upgrading from old pecl packages to new ones |
$test = $this->_installRegistry->packageExists($package, 'pear.php.net'); |
$channel = 'pear.php.net'; |
} |
if ($test) { |
if (isset($dep['uri'])) { |
if ($this->_installRegistry->packageInfo($package, 'uri', '__uri') == $dep['uri']) { |
return true; |
} |
} |
if (isset($options['upgrade'])) { |
$packageVersion = $this->_installRegistry->packageInfo($package, 'version', $channel); |
if (version_compare($packageVersion, $dep['version'], '>=')) { |
return true; |
} |
return false; |
} |
return true; |
} |
return false; |
} |
/** |
* Detect duplicate package names with differing versions |
* |
* If a user requests to install Date 1.4.6 and Date 1.4.7, |
* for instance, this is a logic error. This method |
* detects this situation. |
* |
* @param array $params array of PEAR_Downloader_Package objects |
* @param array $errorparams empty array |
* @return array array of stupid duplicated packages in PEAR_Downloader_Package obejcts |
*/ |
public static function detectStupidDuplicates($params, &$errorparams) |
{ |
$existing = array(); |
foreach ($params as $i => $param) { |
$package = $param->getPackage(); |
$channel = $param->getChannel(); |
$group = $param->getGroup(); |
if (!isset($existing[$channel . '/' . $package])) { |
$existing[$channel . '/' . $package] = array(); |
} |
if (!isset($existing[$channel . '/' . $package][$group])) { |
$existing[$channel . '/' . $package][$group] = array(); |
} |
$existing[$channel . '/' . $package][$group][] = $i; |
} |
$indices = array(); |
foreach ($existing as $package => $groups) { |
foreach ($groups as $group => $dupes) { |
if (count($dupes) > 1) { |
$indices = $indices + $dupes; |
} |
} |
} |
$indices = array_unique($indices); |
foreach ($indices as $index) { |
$errorparams[] = $params[$index]; |
} |
return count($errorparams); |
} |
/** |
* @param array |
* @param bool ignore install groups - for final removal of dupe packages |
*/ |
public static function removeDuplicates(&$params, $ignoreGroups = false) |
{ |
$pnames = array(); |
foreach ($params as $i => $param) { |
if (!$param) { |
continue; |
} |
if ($param->getPackage()) { |
$group = $ignoreGroups ? '' : $param->getGroup(); |
$pnames[$i] = $param->getChannel() . '/' . |
$param->getPackage() . '-' . $param->getVersion() . '#' . $group; |
} |
} |
$pnames = array_unique($pnames); |
$unset = array_diff(array_keys($params), array_keys($pnames)); |
$testp = array_flip($pnames); |
foreach ($params as $i => $param) { |
if (!$param) { |
$unset[] = $i; |
continue; |
} |
if (!is_a($param, 'PEAR_Downloader_Package')) { |
$unset[] = $i; |
continue; |
} |
$group = $ignoreGroups ? '' : $param->getGroup(); |
if (!isset($testp[$param->getChannel() . '/' . $param->getPackage() . '-' . |
$param->getVersion() . '#' . $group])) { |
$unset[] = $i; |
} |
} |
foreach ($unset as $i) { |
unset($params[$i]); |
} |
$ret = array(); |
foreach ($params as $i => $param) { |
$ret[] = &$params[$i]; |
} |
$params = array(); |
foreach ($ret as $i => $param) { |
$params[] = &$ret[$i]; |
} |
} |
function explicitState() |
{ |
return $this->_explicitState; |
} |
function setExplicitState($s) |
{ |
$this->_explicitState = $s; |
} |
/** |
*/ |
public static function mergeDependencies(&$params) |
{ |
$bundles = $newparams = array(); |
foreach ($params as $i => $param) { |
if (!$param->isBundle()) { |
continue; |
} |
$bundles[] = $i; |
$pf = &$param->getPackageFile(); |
$newdeps = array(); |
$contents = $pf->getBundledPackages(); |
if (!is_array($contents)) { |
$contents = array($contents); |
} |
foreach ($contents as $file) { |
$filecontents = $pf->getFileContents($file); |
$dl = &$param->getDownloader(); |
$options = $dl->getOptions(); |
if (PEAR::isError($dir = $dl->getDownloadDir())) { |
return $dir; |
} |
$fp = @fopen($dir . DIRECTORY_SEPARATOR . $file, 'wb'); |
if (!$fp) { |
continue; |
} |
// FIXME do symlink check |
fwrite($fp, $filecontents, strlen($filecontents)); |
fclose($fp); |
if ($s = $params[$i]->explicitState()) { |
$obj->setExplicitState($s); |
} |
$obj = new PEAR_Downloader_Package($params[$i]->getDownloader()); |
PEAR::pushErrorHandling(PEAR_ERROR_RETURN); |
if (PEAR::isError($dir = $dl->getDownloadDir())) { |
PEAR::popErrorHandling(); |
return $dir; |
} |
$a = $dir . DIRECTORY_SEPARATOR . $file; |
$e = $obj->_fromFile($a); |
PEAR::popErrorHandling(); |
if (PEAR::isError($e)) { |
if (!isset($options['soft'])) { |
$dl->log(0, $e->getMessage()); |
} |
continue; |
} |
if (!PEAR_Downloader_Package::willDownload($obj, |
array_merge($params, $newparams)) && !$param->isInstalled($obj)) { |
$newparams[] = $obj; |
} |
} |
} |
foreach ($bundles as $i) { |
unset($params[$i]); // remove bundles - only their contents matter for installation |
} |
PEAR_Downloader_Package::removeDuplicates($params); // strip any unset indices |
if (count($newparams)) { // add in bundled packages for install |
foreach ($newparams as $i => $unused) { |
$params[] = &$newparams[$i]; |
} |
$newparams = array(); |
} |
foreach ($params as $i => $param) { |
$newdeps = array(); |
foreach ($param->_downloadDeps as $dep) { |
$merge = array_merge($params, $newparams); |
if (!PEAR_Downloader_Package::willDownload($dep, $merge) |
&& !$param->isInstalled($dep) |
) { |
$newdeps[] = $dep; |
} else { |
//var_dump($dep); |
// detect versioning conflicts here |
} |
} |
// convert the dependencies into PEAR_Downloader_Package objects for the next time around |
$params[$i]->_downloadDeps = array(); |
foreach ($newdeps as $dep) { |
$obj = new PEAR_Downloader_Package($params[$i]->getDownloader()); |
if ($s = $params[$i]->explicitState()) { |
$obj->setExplicitState($s); |
} |
PEAR::pushErrorHandling(PEAR_ERROR_RETURN); |
$e = $obj->fromDepURL($dep); |
PEAR::popErrorHandling(); |
if (PEAR::isError($e)) { |
if (!isset($options['soft'])) { |
$obj->_downloader->log(0, $e->getMessage()); |
} |
continue; |
} |
$e = $obj->detectDependencies($params); |
if (PEAR::isError($e)) { |
if (!isset($options['soft'])) { |
$obj->_downloader->log(0, $e->getMessage()); |
} |
} |
$newparams[] = $obj; |
} |
} |
if (count($newparams)) { |
foreach ($newparams as $i => $unused) { |
$params[] = &$newparams[$i]; |
} |
return true; |
} |
return false; |
} |
/** |
*/ |
public static function willDownload($param, $params) |
{ |
if (!is_array($params)) { |
return false; |
} |
foreach ($params as $obj) { |
if ($obj->isEqual($param)) { |
return true; |
} |
} |
return false; |
} |
/** |
* For simpler unit-testing |
* @param PEAR_Config |
* @param int |
* @param string |
*/ |
function &getPackagefileObject(&$c, $d) |
{ |
$a = new PEAR_PackageFile($c, $d); |
return $a; |
} |
/** |
* This will retrieve from a local file if possible, and parse out |
* a group name as well. The original parameter will be modified to reflect this. |
* @param string|array can be a parsed package name as well |
* @access private |
*/ |
function _fromFile(&$param) |
{ |
$saveparam = $param; |
if (is_string($param)) { |
if (!@file_exists($param)) { |
$test = explode('#', $param); |
$group = array_pop($test); |
if (@file_exists(implode('#', $test))) { |
$this->setGroup($group); |
$param = implode('#', $test); |
$this->_explicitGroup = true; |
} |
} |
if (@is_file($param)) { |
$this->_type = 'local'; |
$options = $this->_downloader->getOptions(); |
$pkg = &$this->getPackagefileObject($this->_config, $this->_downloader->_debug); |
PEAR::pushErrorHandling(PEAR_ERROR_RETURN); |
$pf = &$pkg->fromAnyFile($param, PEAR_VALIDATE_INSTALLING); |
PEAR::popErrorHandling(); |
if (PEAR::isError($pf)) { |
$this->_valid = false; |
$param = $saveparam; |
return $pf; |
} |
$this->_packagefile = &$pf; |
if (!$this->getGroup()) { |
$this->setGroup('default'); // install the default dependency group |
} |
return $this->_valid = true; |
} |
} |
$param = $saveparam; |
return $this->_valid = false; |
} |
function _fromUrl($param, $saveparam = '') |
{ |
if (!is_array($param) && (preg_match('#^(http|https|ftp)://#', $param))) { |
$options = $this->_downloader->getOptions(); |
$this->_type = 'url'; |
$callback = $this->_downloader->ui ? |
array(&$this->_downloader, '_downloadCallback') : null; |
$this->_downloader->pushErrorHandling(PEAR_ERROR_RETURN); |
if (PEAR::isError($dir = $this->_downloader->getDownloadDir())) { |
$this->_downloader->popErrorHandling(); |
return $dir; |
} |
$this->_downloader->log(3, 'Downloading "' . $param . '"'); |
$file = $this->_downloader->downloadHttp($param, $this->_downloader->ui, |
$dir, $callback, null, false, $this->getChannel()); |
$this->_downloader->popErrorHandling(); |
if (PEAR::isError($file)) { |
if (!empty($saveparam)) { |
$saveparam = ", cannot download \"$saveparam\""; |
} |
$err = PEAR::raiseError('Could not download from "' . $param . |
'"' . $saveparam . ' (' . $file->getMessage() . ')'); |
return $err; |
} |
if ($this->_rawpackagefile) { |
require_once 'Archive/Tar.php'; |
$tar = new Archive_Tar($file); |
$packagexml = $tar->extractInString('package2.xml'); |
if (!$packagexml) { |
$packagexml = $tar->extractInString('package.xml'); |
} |
if (str_replace(array("\n", "\r"), array('',''), $packagexml) != |
str_replace(array("\n", "\r"), array('',''), $this->_rawpackagefile)) { |
if ($this->getChannel() != 'pear.php.net') { |
return PEAR::raiseError('CRITICAL ERROR: package.xml downloaded does ' . |
'not match value returned from xml-rpc'); |
} |
// be more lax for the existing PEAR packages that have not-ok |
// characters in their package.xml |
$this->_downloader->log(0, 'CRITICAL WARNING: The "' . |
$this->getPackage() . '" package has invalid characters in its ' . |
'package.xml. The next version of PEAR may not be able to install ' . |
'this package for security reasons. Please open a bug report at ' . |
'http://pear.php.net/package/' . $this->getPackage() . '/bugs'); |
} |
} |
// whew, download worked! |
$pkg = &$this->getPackagefileObject($this->_config, $this->_downloader->debug); |
PEAR::pushErrorHandling(PEAR_ERROR_RETURN); |
$pf = &$pkg->fromAnyFile($file, PEAR_VALIDATE_INSTALLING); |
PEAR::popErrorHandling(); |
if (PEAR::isError($pf)) { |
if (is_array($pf->getUserInfo())) { |
foreach ($pf->getUserInfo() as $err) { |
if (is_array($err)) { |
$err = $err['message']; |
} |
if (!isset($options['soft'])) { |
$this->_downloader->log(0, "Validation Error: $err"); |
} |
} |
} |
if (!isset($options['soft'])) { |
$this->_downloader->log(0, $pf->getMessage()); |
} |
///FIXME need to pass back some error code that we can use to match with to cancel all further operations |
/// At least stop all deps of this package from being installed |
$out = $saveparam ? $saveparam : $param; |
$err = PEAR::raiseError('Download of "' . $out . '" succeeded, but it is not a valid package archive'); |
$this->_valid = false; |
return $err; |
} |
$this->_packagefile = &$pf; |
$this->setGroup('default'); // install the default dependency group |
return $this->_valid = true; |
} |
return $this->_valid = false; |
} |
/** |
* |
* @param string|array pass in an array of format |
* array( |
* 'package' => 'pname', |
* ['channel' => 'channame',] |
* ['version' => 'version',] |
* ['state' => 'state',]) |
* or a string of format [channame/]pname[-version|-state] |
*/ |
function _fromString($param) |
{ |
$options = $this->_downloader->getOptions(); |
$channel = $this->_config->get('default_channel'); |
PEAR::pushErrorHandling(PEAR_ERROR_RETURN); |
$pname = $this->_registry->parsePackageName($param, $channel); |
PEAR::popErrorHandling(); |
if (PEAR::isError($pname)) { |
if ($pname->getCode() == 'invalid') { |
$this->_valid = false; |
return false; |
} |
if ($pname->getCode() == 'channel') { |
$parsed = $pname->getUserInfo(); |
if ($this->_downloader->discover($parsed['channel'])) { |
if ($this->_config->get('auto_discover')) { |
PEAR::pushErrorHandling(PEAR_ERROR_RETURN); |
$pname = $this->_registry->parsePackageName($param, $channel); |
PEAR::popErrorHandling(); |
} else { |
if (!isset($options['soft'])) { |
$this->_downloader->log(0, 'Channel "' . $parsed['channel'] . |
'" is not initialized, use ' . |
'"pear channel-discover ' . $parsed['channel'] . '" to initialize' . |
'or pear config-set auto_discover 1'); |
} |
} |
} |
if (PEAR::isError($pname)) { |
if (!isset($options['soft'])) { |
$this->_downloader->log(0, $pname->getMessage()); |
} |
if (is_array($param)) { |
$param = $this->_registry->parsedPackageNameToString($param); |
} |
$err = PEAR::raiseError('invalid package name/package file "' . $param . '"'); |
$this->_valid = false; |
return $err; |
} |
} else { |
if (!isset($options['soft'])) { |
$this->_downloader->log(0, $pname->getMessage()); |
} |
$err = PEAR::raiseError('invalid package name/package file "' . $param . '"'); |
$this->_valid = false; |
return $err; |
} |
} |
if (!isset($this->_type)) { |
$this->_type = 'rest'; |
} |
$this->_parsedname = $pname; |
$this->_explicitState = isset($pname['state']) ? $pname['state'] : false; |
$this->_explicitGroup = isset($pname['group']) ? true : false; |
$info = $this->_downloader->_getPackageDownloadUrl($pname); |
if (PEAR::isError($info)) { |
if ($info->getCode() != -976 && $pname['channel'] == 'pear.php.net') { |
// try pecl |
$pname['channel'] = 'pecl.php.net'; |
if ($test = $this->_downloader->_getPackageDownloadUrl($pname)) { |
if (!PEAR::isError($test)) { |
$info = PEAR::raiseError($info->getMessage() . ' - package ' . |
$this->_registry->parsedPackageNameToString($pname, true) . |
' can be installed with "pecl install ' . $pname['package'] . |
'"'); |
} else { |
$pname['channel'] = 'pear.php.net'; |
} |
} else { |
$pname['channel'] = 'pear.php.net'; |
} |
} |
return $info; |
} |
$this->_rawpackagefile = $info['raw']; |
$ret = $this->_analyzeDownloadURL($info, $param, $pname); |
if (PEAR::isError($ret)) { |
return $ret; |
} |
if ($ret) { |
$this->_downloadURL = $ret; |
return $this->_valid = (bool) $ret; |
} |
} |
/** |
* @param array output of package.getDownloadURL |
* @param string|array|object information for detecting packages to be downloaded, and |
* for errors |
* @param array name information of the package |
* @param array|null packages to be downloaded |
* @param bool is this an optional dependency? |
* @param bool is this any kind of dependency? |
* @access private |
*/ |
function _analyzeDownloadURL($info, $param, $pname, $params = null, $optional = false, |
$isdependency = false) |
{ |
if (!is_string($param) && PEAR_Downloader_Package::willDownload($param, $params)) { |
return false; |
} |
if ($info === false) { |
$saveparam = !is_string($param) ? ", cannot download \"$param\"" : ''; |
// no releases exist |
return PEAR::raiseError('No releases for package "' . |
$this->_registry->parsedPackageNameToString($pname, true) . '" exist' . $saveparam); |
} |
if (strtolower($info['info']->getChannel()) != strtolower($pname['channel'])) { |
$err = false; |
if ($pname['channel'] == 'pecl.php.net') { |
if ($info['info']->getChannel() != 'pear.php.net') { |
$err = true; |
} |
} elseif ($info['info']->getChannel() == 'pecl.php.net') { |
if ($pname['channel'] != 'pear.php.net') { |
$err = true; |
} |
} else { |
$err = true; |
} |
if ($err) { |
return PEAR::raiseError('SECURITY ERROR: package in channel "' . $pname['channel'] . |
'" retrieved another channel\'s name for download! ("' . |
$info['info']->getChannel() . '")'); |
} |
} |
$preferred_state = $this->_config->get('preferred_state'); |
if (!isset($info['url'])) { |
$package_version = $this->_registry->packageInfo($info['info']->getPackage(), |
'version', $info['info']->getChannel()); |
if ($this->isInstalled($info)) { |
if ($isdependency && version_compare($info['version'], $package_version, '<=')) { |
// ignore bogus errors of "failed to download dependency" |
// if it is already installed and the one that would be |
// downloaded is older or the same version (Bug #7219) |
return false; |
} |
} |
if ($info['version'] === $package_version) { |
if (!isset($options['soft'])) { |
$this->_downloader->log(1, 'WARNING: failed to download ' . $pname['channel'] . |
'/' . $pname['package'] . '-' . $package_version. ', additionally the suggested version' . |
' (' . $package_version . ') is the same as the locally installed one.'); |
} |
return false; |
} |
if (version_compare($info['version'], $package_version, '<=')) { |
if (!isset($options['soft'])) { |
$this->_downloader->log(1, 'WARNING: failed to download ' . $pname['channel'] . |
'/' . $pname['package'] . '-' . $package_version . ', additionally the suggested version' . |
' (' . $info['version'] . ') is a lower version than the locally installed one (' . $package_version . ').'); |
} |
return false; |
} |
$instead = ', will instead download version ' . $info['version'] . |
', stability "' . $info['info']->getState() . '"'; |
// releases exist, but we failed to get any |
if (isset($this->_downloader->_options['force'])) { |
if (isset($pname['version'])) { |
$vs = ', version "' . $pname['version'] . '"'; |
} elseif (isset($pname['state'])) { |
$vs = ', stability "' . $pname['state'] . '"'; |
} elseif ($param == 'dependency') { |
if (!class_exists('PEAR_Common')) { |
require_once 'PEAR/Common.php'; |
} |
if (!in_array($info['info']->getState(), |
PEAR_Common::betterStates($preferred_state, true))) { |
if ($optional) { |
// don't spit out confusing error message |
return $this->_downloader->_getPackageDownloadUrl( |
array('package' => $pname['package'], |
'channel' => $pname['channel'], |
'version' => $info['version'])); |
} |
$vs = ' within preferred state "' . $preferred_state . |
'"'; |
} else { |
if (!class_exists('PEAR_Dependency2')) { |
require_once 'PEAR/Dependency2.php'; |
} |
if ($optional) { |
// don't spit out confusing error message |
return $this->_downloader->_getPackageDownloadUrl( |
array('package' => $pname['package'], |
'channel' => $pname['channel'], |
'version' => $info['version'])); |
} |
$vs = PEAR_Dependency2::_getExtraString($pname); |
$instead = ''; |
} |
} else { |
$vs = ' within preferred state "' . $preferred_state . '"'; |
} |
if (!isset($options['soft'])) { |
$this->_downloader->log(1, 'WARNING: failed to download ' . $pname['channel'] . |
'/' . $pname['package'] . $vs . $instead); |
} |
// download the latest release |
return $this->_downloader->_getPackageDownloadUrl( |
array('package' => $pname['package'], |
'channel' => $pname['channel'], |
'version' => $info['version'])); |
} else { |
if (isset($info['php']) && $info['php']) { |
$err = PEAR::raiseError('Failed to download ' . |
$this->_registry->parsedPackageNameToString( |
array('channel' => $pname['channel'], |
'package' => $pname['package']), |
true) . |
', latest release is version ' . $info['php']['v'] . |
', but it requires PHP version "' . |
$info['php']['m'] . '", use "' . |
$this->_registry->parsedPackageNameToString( |
array('channel' => $pname['channel'], 'package' => $pname['package'], |
'version' => $info['php']['v'])) . '" to install', |
PEAR_DOWNLOADER_PACKAGE_PHPVERSION); |
return $err; |
} |
// construct helpful error message |
if (isset($pname['version'])) { |
$vs = ', version "' . $pname['version'] . '"'; |
} elseif (isset($pname['state'])) { |
$vs = ', stability "' . $pname['state'] . '"'; |
} elseif ($param == 'dependency') { |
if (!class_exists('PEAR_Common')) { |
require_once 'PEAR/Common.php'; |
} |
if (!in_array($info['info']->getState(), |
PEAR_Common::betterStates($preferred_state, true))) { |
if ($optional) { |
// don't spit out confusing error message, and don't die on |
// optional dep failure! |
return $this->_downloader->_getPackageDownloadUrl( |
array('package' => $pname['package'], |
'channel' => $pname['channel'], |
'version' => $info['version'])); |
} |
$vs = ' within preferred state "' . $preferred_state . '"'; |
} else { |
if (!class_exists('PEAR_Dependency2')) { |
require_once 'PEAR/Dependency2.php'; |
} |
if ($optional) { |
// don't spit out confusing error message, and don't die on |
// optional dep failure! |
return $this->_downloader->_getPackageDownloadUrl( |
array('package' => $pname['package'], |
'channel' => $pname['channel'], |
'version' => $info['version'])); |
} |
$vs = PEAR_Dependency2::_getExtraString($pname); |
} |
} else { |
$vs = ' within preferred state "' . $this->_downloader->config->get('preferred_state') . '"'; |
} |
$options = $this->_downloader->getOptions(); |
// this is only set by the "download-all" command |
if (isset($options['ignorepreferred_state'])) { |
$err = PEAR::raiseError( |
'Failed to download ' . $this->_registry->parsedPackageNameToString( |
array('channel' => $pname['channel'], 'package' => $pname['package']), |
true) |
. $vs . |
', latest release is version ' . $info['version'] . |
', stability "' . $info['info']->getState() . '", use "' . |
$this->_registry->parsedPackageNameToString( |
array('channel' => $pname['channel'], 'package' => $pname['package'], |
'version' => $info['version'])) . '" to install', |
PEAR_DOWNLOADER_PACKAGE_STATE); |
return $err; |
} |
// Checks if the user has a package installed already and checks the release against |
// the state against the installed package, this allows upgrades for packages |
// with lower stability than the preferred_state |
$stability = $this->_registry->packageInfo($pname['package'], 'stability', $pname['channel']); |
if (!$this->isInstalled($info) |
|| !in_array($info['info']->getState(), PEAR_Common::betterStates($stability['release'], true)) |
) { |
$err = PEAR::raiseError( |
'Failed to download ' . $this->_registry->parsedPackageNameToString( |
array('channel' => $pname['channel'], 'package' => $pname['package']), |
true) |
. $vs . |
', latest release is version ' . $info['version'] . |
', stability "' . $info['info']->getState() . '", use "' . |
$this->_registry->parsedPackageNameToString( |
array('channel' => $pname['channel'], 'package' => $pname['package'], |
'version' => $info['version'])) . '" to install'); |
return $err; |
} |
} |
} |
if (isset($info['deprecated']) && $info['deprecated']) { |
$this->_downloader->log(0, |
'WARNING: "' . |
$this->_registry->parsedPackageNameToString( |
array('channel' => $info['info']->getChannel(), |
'package' => $info['info']->getPackage()), true) . |
'" is deprecated in favor of "' . |
$this->_registry->parsedPackageNameToString($info['deprecated'], true) . |
'"'); |
} |
return $info; |
} |
} |
/branches/v1.3-critias/bibliotheque/pear/PEAR/ChannelFile.php |
---|
New file |
0,0 → 1,1560 |
<?php |
/** |
* PEAR_ChannelFile, the channel handling class |
* |
* PHP versions 4 and 5 |
* |
* @category pear |
* @package PEAR |
* @author Greg Beaver <cellog@php.net> |
* @copyright 1997-2009 The Authors |
* @license http://opensource.org/licenses/bsd-license.php New BSD License |
* @link http://pear.php.net/package/PEAR |
* @since File available since Release 1.4.0a1 |
*/ |
/** |
* Needed for error handling |
*/ |
require_once 'PEAR/ErrorStack.php'; |
require_once 'PEAR/XMLParser.php'; |
require_once 'PEAR/Common.php'; |
/** |
* Error code if the channel.xml <channel> tag does not contain a valid version |
*/ |
define('PEAR_CHANNELFILE_ERROR_NO_VERSION', 1); |
/** |
* Error code if the channel.xml <channel> tag version is not supported (version 1.0 is the only supported version, |
* currently |
*/ |
define('PEAR_CHANNELFILE_ERROR_INVALID_VERSION', 2); |
/** |
* Error code if parsing is attempted with no xml extension |
*/ |
define('PEAR_CHANNELFILE_ERROR_NO_XML_EXT', 3); |
/** |
* Error code if creating the xml parser resource fails |
*/ |
define('PEAR_CHANNELFILE_ERROR_CANT_MAKE_PARSER', 4); |
/** |
* Error code used for all sax xml parsing errors |
*/ |
define('PEAR_CHANNELFILE_ERROR_PARSER_ERROR', 5); |
/**#@+ |
* Validation errors |
*/ |
/** |
* Error code when channel name is missing |
*/ |
define('PEAR_CHANNELFILE_ERROR_NO_NAME', 6); |
/** |
* Error code when channel name is invalid |
*/ |
define('PEAR_CHANNELFILE_ERROR_INVALID_NAME', 7); |
/** |
* Error code when channel summary is missing |
*/ |
define('PEAR_CHANNELFILE_ERROR_NO_SUMMARY', 8); |
/** |
* Error code when channel summary is multi-line |
*/ |
define('PEAR_CHANNELFILE_ERROR_MULTILINE_SUMMARY', 9); |
/** |
* Error code when channel server is missing for protocol |
*/ |
define('PEAR_CHANNELFILE_ERROR_NO_HOST', 10); |
/** |
* Error code when channel server is invalid for protocol |
*/ |
define('PEAR_CHANNELFILE_ERROR_INVALID_HOST', 11); |
/** |
* Error code when a mirror name is invalid |
*/ |
define('PEAR_CHANNELFILE_ERROR_INVALID_MIRROR', 21); |
/** |
* Error code when a mirror type is invalid |
*/ |
define('PEAR_CHANNELFILE_ERROR_INVALID_MIRRORTYPE', 22); |
/** |
* Error code when an attempt is made to generate xml, but the parsed content is invalid |
*/ |
define('PEAR_CHANNELFILE_ERROR_INVALID', 23); |
/** |
* Error code when an empty package name validate regex is passed in |
*/ |
define('PEAR_CHANNELFILE_ERROR_EMPTY_REGEX', 24); |
/** |
* Error code when a <function> tag has no version |
*/ |
define('PEAR_CHANNELFILE_ERROR_NO_FUNCTIONVERSION', 25); |
/** |
* Error code when a <function> tag has no name |
*/ |
define('PEAR_CHANNELFILE_ERROR_NO_FUNCTIONNAME', 26); |
/** |
* Error code when a <validatepackage> tag has no name |
*/ |
define('PEAR_CHANNELFILE_ERROR_NOVALIDATE_NAME', 27); |
/** |
* Error code when a <validatepackage> tag has no version attribute |
*/ |
define('PEAR_CHANNELFILE_ERROR_NOVALIDATE_VERSION', 28); |
/** |
* Error code when a mirror does not exist but is called for in one of the set* |
* methods. |
*/ |
define('PEAR_CHANNELFILE_ERROR_MIRROR_NOT_FOUND', 32); |
/** |
* Error code when a server port is not numeric |
*/ |
define('PEAR_CHANNELFILE_ERROR_INVALID_PORT', 33); |
/** |
* Error code when <static> contains no version attribute |
*/ |
define('PEAR_CHANNELFILE_ERROR_NO_STATICVERSION', 34); |
/** |
* Error code when <baseurl> contains no type attribute in a <rest> protocol definition |
*/ |
define('PEAR_CHANNELFILE_ERROR_NOBASEURLTYPE', 35); |
/** |
* Error code when a mirror is defined and the channel.xml represents the __uri pseudo-channel |
*/ |
define('PEAR_CHANNELFILE_URI_CANT_MIRROR', 36); |
/** |
* Error code when ssl attribute is present and is not "yes" |
*/ |
define('PEAR_CHANNELFILE_ERROR_INVALID_SSL', 37); |
/**#@-*/ |
/** |
* Mirror types allowed. Currently only internet servers are recognized. |
*/ |
$GLOBALS['_PEAR_CHANNELS_MIRROR_TYPES'] = array('server'); |
/** |
* The Channel handling class |
* |
* @category pear |
* @package PEAR |
* @author Greg Beaver <cellog@php.net> |
* @copyright 1997-2009 The Authors |
* @license http://opensource.org/licenses/bsd-license.php New BSD License |
* @version Release: 1.10.1 |
* @link http://pear.php.net/package/PEAR |
* @since Class available since Release 1.4.0a1 |
*/ |
class PEAR_ChannelFile |
{ |
/** |
* @access private |
* @var PEAR_ErrorStack |
* @access private |
*/ |
var $_stack; |
/** |
* Supported channel.xml versions, for parsing |
* @var array |
* @access private |
*/ |
var $_supportedVersions = array('1.0'); |
/** |
* Parsed channel information |
* @var array |
* @access private |
*/ |
var $_channelInfo; |
/** |
* index into the subchannels array, used for parsing xml |
* @var int |
* @access private |
*/ |
var $_subchannelIndex; |
/** |
* index into the mirrors array, used for parsing xml |
* @var int |
* @access private |
*/ |
var $_mirrorIndex; |
/** |
* Flag used to determine the validity of parsed content |
* @var boolean |
* @access private |
*/ |
var $_isValid = false; |
function __construct() |
{ |
$this->_stack = new PEAR_ErrorStack('PEAR_ChannelFile'); |
$this->_stack->setErrorMessageTemplate($this->_getErrorMessage()); |
$this->_isValid = false; |
} |
/** |
* @return array |
* @access protected |
*/ |
function _getErrorMessage() |
{ |
return |
array( |
PEAR_CHANNELFILE_ERROR_INVALID_VERSION => |
'While parsing channel.xml, an invalid version number "%version% was passed in, expecting one of %versions%', |
PEAR_CHANNELFILE_ERROR_NO_VERSION => |
'No version number found in <channel> tag', |
PEAR_CHANNELFILE_ERROR_NO_XML_EXT => |
'%error%', |
PEAR_CHANNELFILE_ERROR_CANT_MAKE_PARSER => |
'Unable to create XML parser', |
PEAR_CHANNELFILE_ERROR_PARSER_ERROR => |
'%error%', |
PEAR_CHANNELFILE_ERROR_NO_NAME => |
'Missing channel name', |
PEAR_CHANNELFILE_ERROR_INVALID_NAME => |
'Invalid channel %tag% "%name%"', |
PEAR_CHANNELFILE_ERROR_NO_SUMMARY => |
'Missing channel summary', |
PEAR_CHANNELFILE_ERROR_MULTILINE_SUMMARY => |
'Channel summary should be on one line, but is multi-line', |
PEAR_CHANNELFILE_ERROR_NO_HOST => |
'Missing channel server for %type% server', |
PEAR_CHANNELFILE_ERROR_INVALID_HOST => |
'Server name "%server%" is invalid for %type% server', |
PEAR_CHANNELFILE_ERROR_INVALID_MIRROR => |
'Invalid mirror name "%name%", mirror type %type%', |
PEAR_CHANNELFILE_ERROR_INVALID_MIRRORTYPE => |
'Invalid mirror type "%type%"', |
PEAR_CHANNELFILE_ERROR_INVALID => |
'Cannot generate xml, contents are invalid', |
PEAR_CHANNELFILE_ERROR_EMPTY_REGEX => |
'packagenameregex cannot be empty', |
PEAR_CHANNELFILE_ERROR_NO_FUNCTIONVERSION => |
'%parent% %protocol% function has no version', |
PEAR_CHANNELFILE_ERROR_NO_FUNCTIONNAME => |
'%parent% %protocol% function has no name', |
PEAR_CHANNELFILE_ERROR_NOBASEURLTYPE => |
'%parent% rest baseurl has no type', |
PEAR_CHANNELFILE_ERROR_NOVALIDATE_NAME => |
'Validation package has no name in <validatepackage> tag', |
PEAR_CHANNELFILE_ERROR_NOVALIDATE_VERSION => |
'Validation package "%package%" has no version', |
PEAR_CHANNELFILE_ERROR_MIRROR_NOT_FOUND => |
'Mirror "%mirror%" does not exist', |
PEAR_CHANNELFILE_ERROR_INVALID_PORT => |
'Port "%port%" must be numeric', |
PEAR_CHANNELFILE_ERROR_NO_STATICVERSION => |
'<static> tag must contain version attribute', |
PEAR_CHANNELFILE_URI_CANT_MIRROR => |
'The __uri pseudo-channel cannot have mirrors', |
PEAR_CHANNELFILE_ERROR_INVALID_SSL => |
'%server% has invalid ssl attribute "%ssl%" can only be yes or not present', |
); |
} |
/** |
* @param string contents of package.xml file |
* @return bool success of parsing |
*/ |
function fromXmlString($data) |
{ |
if (preg_match('/<channel\s+version="([0-9]+\.[0-9]+)"/', $data, $channelversion)) { |
if (!in_array($channelversion[1], $this->_supportedVersions)) { |
$this->_stack->push(PEAR_CHANNELFILE_ERROR_INVALID_VERSION, 'error', |
array('version' => $channelversion[1])); |
return false; |
} |
$parser = new PEAR_XMLParser; |
$result = $parser->parse($data); |
if ($result !== true) { |
if ($result->getCode() == 1) { |
$this->_stack->push(PEAR_CHANNELFILE_ERROR_NO_XML_EXT, 'error', |
array('error' => $result->getMessage())); |
} else { |
$this->_stack->push(PEAR_CHANNELFILE_ERROR_CANT_MAKE_PARSER, 'error'); |
} |
return false; |
} |
$this->_channelInfo = $parser->getData(); |
return true; |
} else { |
$this->_stack->push(PEAR_CHANNELFILE_ERROR_NO_VERSION, 'error', array('xml' => $data)); |
return false; |
} |
} |
/** |
* @return array |
*/ |
function toArray() |
{ |
if (!$this->_isValid && !$this->validate()) { |
return false; |
} |
return $this->_channelInfo; |
} |
/** |
* @param array |
* |
* @return PEAR_ChannelFile|false false if invalid |
*/ |
public static function &fromArray( |
$data, $compatibility = false, $stackClass = 'PEAR_ErrorStack' |
) { |
$a = new PEAR_ChannelFile($compatibility, $stackClass); |
$a->_fromArray($data); |
if (!$a->validate()) { |
$a = false; |
return $a; |
} |
return $a; |
} |
/** |
* Unlike {@link fromArray()} this does not do any validation |
* |
* @param array |
* |
* @return PEAR_ChannelFile |
*/ |
public static function &fromArrayWithErrors( |
$data, $compatibility = false, $stackClass = 'PEAR_ErrorStack' |
) { |
$a = new PEAR_ChannelFile($compatibility, $stackClass); |
$a->_fromArray($data); |
return $a; |
} |
/** |
* @param array |
* @access private |
*/ |
function _fromArray($data) |
{ |
$this->_channelInfo = $data; |
} |
/** |
* Wrapper to {@link PEAR_ErrorStack::getErrors()} |
* @param boolean determines whether to purge the error stack after retrieving |
* @return array |
*/ |
function getErrors($purge = false) |
{ |
return $this->_stack->getErrors($purge); |
} |
/** |
* Unindent given string (?) |
* |
* @param string $str The string that has to be unindented. |
* @return string |
* @access private |
*/ |
function _unIndent($str) |
{ |
// remove leading newlines |
$str = preg_replace('/^[\r\n]+/', '', $str); |
// find whitespace at the beginning of the first line |
$indent_len = strspn($str, " \t"); |
$indent = substr($str, 0, $indent_len); |
$data = ''; |
// remove the same amount of whitespace from following lines |
foreach (explode("\n", $str) as $line) { |
if (substr($line, 0, $indent_len) == $indent) { |
$data .= substr($line, $indent_len) . "\n"; |
} |
} |
return $data; |
} |
/** |
* Parse a channel.xml file. Expects the name of |
* a channel xml file as input. |
* |
* @param string $descfile name of channel xml file |
* @return bool success of parsing |
*/ |
function fromXmlFile($descfile) |
{ |
if (!file_exists($descfile) || !is_file($descfile) || !is_readable($descfile) || |
(!$fp = fopen($descfile, 'r'))) { |
require_once 'PEAR.php'; |
return PEAR::raiseError("Unable to open $descfile"); |
} |
// read the whole thing so we only get one cdata callback |
// for each block of cdata |
fclose($fp); |
$data = file_get_contents($descfile); |
return $this->fromXmlString($data); |
} |
/** |
* Parse channel information from different sources |
* |
* This method is able to extract information about a channel |
* from an .xml file or a string |
* |
* @access public |
* @param string Filename of the source or the source itself |
* @return bool |
*/ |
function fromAny($info) |
{ |
if (is_string($info) && file_exists($info) && strlen($info) < 255) { |
$tmp = substr($info, -4); |
if ($tmp == '.xml') { |
$info = $this->fromXmlFile($info); |
} else { |
$fp = fopen($info, "r"); |
$test = fread($fp, 5); |
fclose($fp); |
if ($test == "<?xml") { |
$info = $this->fromXmlFile($info); |
} |
} |
if (PEAR::isError($info)) { |
require_once 'PEAR.php'; |
return PEAR::raiseError($info); |
} |
} |
if (is_string($info)) { |
$info = $this->fromXmlString($info); |
} |
return $info; |
} |
/** |
* Return an XML document based on previous parsing and modifications |
* |
* @return string XML data |
* |
* @access public |
*/ |
function toXml() |
{ |
if (!$this->_isValid && !$this->validate()) { |
$this->_validateError(PEAR_CHANNELFILE_ERROR_INVALID); |
return false; |
} |
if (!isset($this->_channelInfo['attribs']['version'])) { |
$this->_channelInfo['attribs']['version'] = '1.0'; |
} |
$channelInfo = $this->_channelInfo; |
$ret = "<?xml version=\"1.0\" encoding=\"ISO-8859-1\" ?>\n"; |
$ret .= "<channel version=\"" . |
$channelInfo['attribs']['version'] . "\" xmlns=\"http://pear.php.net/channel-1.0\" |
xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" |
xsi:schemaLocation=\"http://pear.php.net/dtd/channel-" |
. $channelInfo['attribs']['version'] . " http://pear.php.net/dtd/channel-" . |
$channelInfo['attribs']['version'] . ".xsd\"> |
<name>$channelInfo[name]</name> |
<summary>" . htmlspecialchars($channelInfo['summary'])."</summary> |
"; |
if (isset($channelInfo['suggestedalias'])) { |
$ret .= ' <suggestedalias>' . $channelInfo['suggestedalias'] . "</suggestedalias>\n"; |
} |
if (isset($channelInfo['validatepackage'])) { |
$ret .= ' <validatepackage version="' . |
$channelInfo['validatepackage']['attribs']['version']. '">' . |
htmlspecialchars($channelInfo['validatepackage']['_content']) . |
"</validatepackage>\n"; |
} |
$ret .= " <servers>\n"; |
$ret .= ' <primary'; |
if (isset($channelInfo['servers']['primary']['attribs']['ssl'])) { |
$ret .= ' ssl="' . $channelInfo['servers']['primary']['attribs']['ssl'] . '"'; |
} |
if (isset($channelInfo['servers']['primary']['attribs']['port'])) { |
$ret .= ' port="' . $channelInfo['servers']['primary']['attribs']['port'] . '"'; |
} |
$ret .= ">\n"; |
if (isset($channelInfo['servers']['primary']['rest'])) { |
$ret .= $this->_makeRestXml($channelInfo['servers']['primary']['rest'], ' '); |
} |
$ret .= " </primary>\n"; |
if (isset($channelInfo['servers']['mirror'])) { |
$ret .= $this->_makeMirrorsXml($channelInfo); |
} |
$ret .= " </servers>\n"; |
$ret .= "</channel>"; |
return str_replace("\r", "\n", str_replace("\r\n", "\n", $ret)); |
} |
/** |
* Generate the <rest> tag |
* @access private |
*/ |
function _makeRestXml($info, $indent) |
{ |
$ret = $indent . "<rest>\n"; |
if (isset($info['baseurl']) && !isset($info['baseurl'][0])) { |
$info['baseurl'] = array($info['baseurl']); |
} |
if (isset($info['baseurl'])) { |
foreach ($info['baseurl'] as $url) { |
$ret .= "$indent <baseurl type=\"" . $url['attribs']['type'] . "\""; |
$ret .= ">" . $url['_content'] . "</baseurl>\n"; |
} |
} |
$ret .= $indent . "</rest>\n"; |
return $ret; |
} |
/** |
* Generate the <mirrors> tag |
* @access private |
*/ |
function _makeMirrorsXml($channelInfo) |
{ |
$ret = ""; |
if (!isset($channelInfo['servers']['mirror'][0])) { |
$channelInfo['servers']['mirror'] = array($channelInfo['servers']['mirror']); |
} |
foreach ($channelInfo['servers']['mirror'] as $mirror) { |
$ret .= ' <mirror host="' . $mirror['attribs']['host'] . '"'; |
if (isset($mirror['attribs']['port'])) { |
$ret .= ' port="' . $mirror['attribs']['port'] . '"'; |
} |
if (isset($mirror['attribs']['ssl'])) { |
$ret .= ' ssl="' . $mirror['attribs']['ssl'] . '"'; |
} |
$ret .= ">\n"; |
if (isset($mirror['rest'])) { |
if (isset($mirror['rest'])) { |
$ret .= $this->_makeRestXml($mirror['rest'], ' '); |
} |
$ret .= " </mirror>\n"; |
} else { |
$ret .= "/>\n"; |
} |
} |
return $ret; |
} |
/** |
* Generate the <functions> tag |
* @access private |
*/ |
function _makeFunctionsXml($functions, $indent, $rest = false) |
{ |
$ret = ''; |
if (!isset($functions[0])) { |
$functions = array($functions); |
} |
foreach ($functions as $function) { |
$ret .= "$indent<function version=\"" . $function['attribs']['version'] . "\""; |
if ($rest) { |
$ret .= ' uri="' . $function['attribs']['uri'] . '"'; |
} |
$ret .= ">" . $function['_content'] . "</function>\n"; |
} |
return $ret; |
} |
/** |
* Validation error. Also marks the object contents as invalid |
* @param error code |
* @param array error information |
* @access private |
*/ |
function _validateError($code, $params = array()) |
{ |
$this->_stack->push($code, 'error', $params); |
$this->_isValid = false; |
} |
/** |
* Validation warning. Does not mark the object contents invalid. |
* @param error code |
* @param array error information |
* @access private |
*/ |
function _validateWarning($code, $params = array()) |
{ |
$this->_stack->push($code, 'warning', $params); |
} |
/** |
* Validate parsed file. |
* |
* @access public |
* @return boolean |
*/ |
function validate() |
{ |
$this->_isValid = true; |
$info = $this->_channelInfo; |
if (empty($info['name'])) { |
$this->_validateError(PEAR_CHANNELFILE_ERROR_NO_NAME); |
} elseif (!$this->validChannelServer($info['name'])) { |
if ($info['name'] != '__uri') { |
$this->_validateError(PEAR_CHANNELFILE_ERROR_INVALID_NAME, array('tag' => 'name', |
'name' => $info['name'])); |
} |
} |
if (empty($info['summary'])) { |
$this->_validateError(PEAR_CHANNELFILE_ERROR_NO_SUMMARY); |
} elseif (strpos(trim($info['summary']), "\n") !== false) { |
$this->_validateWarning(PEAR_CHANNELFILE_ERROR_MULTILINE_SUMMARY, |
array('summary' => $info['summary'])); |
} |
if (isset($info['suggestedalias'])) { |
if (!$this->validChannelServer($info['suggestedalias'])) { |
$this->_validateError(PEAR_CHANNELFILE_ERROR_INVALID_NAME, |
array('tag' => 'suggestedalias', 'name' =>$info['suggestedalias'])); |
} |
} |
if (isset($info['localalias'])) { |
if (!$this->validChannelServer($info['localalias'])) { |
$this->_validateError(PEAR_CHANNELFILE_ERROR_INVALID_NAME, |
array('tag' => 'localalias', 'name' =>$info['localalias'])); |
} |
} |
if (isset($info['validatepackage'])) { |
if (!isset($info['validatepackage']['_content'])) { |
$this->_validateError(PEAR_CHANNELFILE_ERROR_NOVALIDATE_NAME); |
} |
if (!isset($info['validatepackage']['attribs']['version'])) { |
$content = isset($info['validatepackage']['_content']) ? |
$info['validatepackage']['_content'] : |
null; |
$this->_validateError(PEAR_CHANNELFILE_ERROR_NOVALIDATE_VERSION, |
array('package' => $content)); |
} |
} |
if (isset($info['servers']['primary']['attribs'], $info['servers']['primary']['attribs']['port']) && |
!is_numeric($info['servers']['primary']['attribs']['port'])) { |
$this->_validateError(PEAR_CHANNELFILE_ERROR_INVALID_PORT, |
array('port' => $info['servers']['primary']['attribs']['port'])); |
} |
if (isset($info['servers']['primary']['attribs'], $info['servers']['primary']['attribs']['ssl']) && |
$info['servers']['primary']['attribs']['ssl'] != 'yes') { |
$this->_validateError(PEAR_CHANNELFILE_ERROR_INVALID_SSL, |
array('ssl' => $info['servers']['primary']['attribs']['ssl'], |
'server' => $info['name'])); |
} |
if (isset($info['servers']['primary']['rest']) && |
isset($info['servers']['primary']['rest']['baseurl'])) { |
$this->_validateFunctions('rest', $info['servers']['primary']['rest']['baseurl']); |
} |
if (isset($info['servers']['mirror'])) { |
if ($this->_channelInfo['name'] == '__uri') { |
$this->_validateError(PEAR_CHANNELFILE_URI_CANT_MIRROR); |
} |
if (!isset($info['servers']['mirror'][0])) { |
$info['servers']['mirror'] = array($info['servers']['mirror']); |
} |
foreach ($info['servers']['mirror'] as $mirror) { |
if (!isset($mirror['attribs']['host'])) { |
$this->_validateError(PEAR_CHANNELFILE_ERROR_NO_HOST, |
array('type' => 'mirror')); |
} elseif (!$this->validChannelServer($mirror['attribs']['host'])) { |
$this->_validateError(PEAR_CHANNELFILE_ERROR_INVALID_HOST, |
array('server' => $mirror['attribs']['host'], 'type' => 'mirror')); |
} |
if (isset($mirror['attribs']['ssl']) && $mirror['attribs']['ssl'] != 'yes') { |
$this->_validateError(PEAR_CHANNELFILE_ERROR_INVALID_SSL, |
array('ssl' => $info['ssl'], 'server' => $mirror['attribs']['host'])); |
} |
if (isset($mirror['rest'])) { |
$this->_validateFunctions('rest', $mirror['rest']['baseurl'], |
$mirror['attribs']['host']); |
} |
} |
} |
return $this->_isValid; |
} |
/** |
* @param string rest - protocol name this function applies to |
* @param array the functions |
* @param string the name of the parent element (mirror name, for instance) |
*/ |
function _validateFunctions($protocol, $functions, $parent = '') |
{ |
if (!isset($functions[0])) { |
$functions = array($functions); |
} |
foreach ($functions as $function) { |
if (!isset($function['_content']) || empty($function['_content'])) { |
$this->_validateError(PEAR_CHANNELFILE_ERROR_NO_FUNCTIONNAME, |
array('parent' => $parent, 'protocol' => $protocol)); |
} |
if ($protocol == 'rest') { |
if (!isset($function['attribs']['type']) || |
empty($function['attribs']['type'])) { |
$this->_validateError(PEAR_CHANNELFILE_ERROR_NOBASEURLTYPE, |
array('parent' => $parent, 'protocol' => $protocol)); |
} |
} else { |
if (!isset($function['attribs']['version']) || |
empty($function['attribs']['version'])) { |
$this->_validateError(PEAR_CHANNELFILE_ERROR_NO_FUNCTIONVERSION, |
array('parent' => $parent, 'protocol' => $protocol)); |
} |
} |
} |
} |
/** |
* Test whether a string contains a valid channel server. |
* @param string $ver the package version to test |
* @return bool |
*/ |
function validChannelServer($server) |
{ |
if ($server == '__uri') { |
return true; |
} |
return (bool) preg_match(PEAR_CHANNELS_SERVER_PREG, $server); |
} |
/** |
* @return string|false |
*/ |
function getName() |
{ |
if (isset($this->_channelInfo['name'])) { |
return $this->_channelInfo['name']; |
} |
return false; |
} |
/** |
* @return string|false |
*/ |
function getServer() |
{ |
if (isset($this->_channelInfo['name'])) { |
return $this->_channelInfo['name']; |
} |
return false; |
} |
/** |
* @return int|80 port number to connect to |
*/ |
function getPort($mirror = false) |
{ |
if ($mirror) { |
if ($mir = $this->getMirror($mirror)) { |
if (isset($mir['attribs']['port'])) { |
return $mir['attribs']['port']; |
} |
if ($this->getSSL($mirror)) { |
return 443; |
} |
return 80; |
} |
return false; |
} |
if (isset($this->_channelInfo['servers']['primary']['attribs']['port'])) { |
return $this->_channelInfo['servers']['primary']['attribs']['port']; |
} |
if ($this->getSSL()) { |
return 443; |
} |
return 80; |
} |
/** |
* @return bool Determines whether secure sockets layer (SSL) is used to connect to this channel |
*/ |
function getSSL($mirror = false) |
{ |
if ($mirror) { |
if ($mir = $this->getMirror($mirror)) { |
if (isset($mir['attribs']['ssl'])) { |
return true; |
} |
return false; |
} |
return false; |
} |
if (isset($this->_channelInfo['servers']['primary']['attribs']['ssl'])) { |
return true; |
} |
return false; |
} |
/** |
* @return string|false |
*/ |
function getSummary() |
{ |
if (isset($this->_channelInfo['summary'])) { |
return $this->_channelInfo['summary']; |
} |
return false; |
} |
/** |
* @param string protocol type |
* @param string Mirror name |
* @return array|false |
*/ |
function getFunctions($protocol, $mirror = false) |
{ |
if ($this->getName() == '__uri') { |
return false; |
} |
$function = $protocol == 'rest' ? 'baseurl' : 'function'; |
if ($mirror) { |
if ($mir = $this->getMirror($mirror)) { |
if (isset($mir[$protocol][$function])) { |
return $mir[$protocol][$function]; |
} |
} |
return false; |
} |
if (isset($this->_channelInfo['servers']['primary'][$protocol][$function])) { |
return $this->_channelInfo['servers']['primary'][$protocol][$function]; |
} |
return false; |
} |
/** |
* @param string Protocol type |
* @param string Function name (null to return the |
* first protocol of the type requested) |
* @param string Mirror name, if any |
* @return array |
*/ |
function getFunction($type, $name = null, $mirror = false) |
{ |
$protocols = $this->getFunctions($type, $mirror); |
if (!$protocols) { |
return false; |
} |
foreach ($protocols as $protocol) { |
if ($name === null) { |
return $protocol; |
} |
if ($protocol['_content'] != $name) { |
continue; |
} |
return $protocol; |
} |
return false; |
} |
/** |
* @param string protocol type |
* @param string protocol name |
* @param string version |
* @param string mirror name |
* @return boolean |
*/ |
function supports($type, $name = null, $mirror = false, $version = '1.0') |
{ |
$protocols = $this->getFunctions($type, $mirror); |
if (!$protocols) { |
return false; |
} |
foreach ($protocols as $protocol) { |
if ($protocol['attribs']['version'] != $version) { |
continue; |
} |
if ($name === null) { |
return true; |
} |
if ($protocol['_content'] != $name) { |
continue; |
} |
return true; |
} |
return false; |
} |
/** |
* Determines whether a channel supports Representational State Transfer (REST) protocols |
* for retrieving channel information |
* @param string |
* @return bool |
*/ |
function supportsREST($mirror = false) |
{ |
if ($mirror == $this->_channelInfo['name']) { |
$mirror = false; |
} |
if ($mirror) { |
if ($mir = $this->getMirror($mirror)) { |
return isset($mir['rest']); |
} |
return false; |
} |
return isset($this->_channelInfo['servers']['primary']['rest']); |
} |
/** |
* Get the URL to access a base resource. |
* |
* Hyperlinks in the returned xml will be used to retrieve the proper information |
* needed. This allows extreme extensibility and flexibility in implementation |
* @param string Resource Type to retrieve |
*/ |
function getBaseURL($resourceType, $mirror = false) |
{ |
if ($mirror == $this->_channelInfo['name']) { |
$mirror = false; |
} |
if ($mirror) { |
$mir = $this->getMirror($mirror); |
if (!$mir) { |
return false; |
} |
$rest = $mir['rest']; |
} else { |
$rest = $this->_channelInfo['servers']['primary']['rest']; |
} |
if (!isset($rest['baseurl'][0])) { |
$rest['baseurl'] = array($rest['baseurl']); |
} |
foreach ($rest['baseurl'] as $baseurl) { |
if (strtolower($baseurl['attribs']['type']) == strtolower($resourceType)) { |
return $baseurl['_content']; |
} |
} |
return false; |
} |
/** |
* Since REST does not implement RPC, provide this as a logical wrapper around |
* resetFunctions for REST |
* @param string|false mirror name, if any |
*/ |
function resetREST($mirror = false) |
{ |
return $this->resetFunctions('rest', $mirror); |
} |
/** |
* Empty all protocol definitions |
* @param string protocol type |
* @param string|false mirror name, if any |
*/ |
function resetFunctions($type, $mirror = false) |
{ |
if ($mirror) { |
if (isset($this->_channelInfo['servers']['mirror'])) { |
$mirrors = $this->_channelInfo['servers']['mirror']; |
if (!isset($mirrors[0])) { |
$mirrors = array($mirrors); |
} |
foreach ($mirrors as $i => $mir) { |
if ($mir['attribs']['host'] == $mirror) { |
if (isset($this->_channelInfo['servers']['mirror'][$i][$type])) { |
unset($this->_channelInfo['servers']['mirror'][$i][$type]); |
} |
return true; |
} |
} |
return false; |
} |
return false; |
} |
if (isset($this->_channelInfo['servers']['primary'][$type])) { |
unset($this->_channelInfo['servers']['primary'][$type]); |
} |
return true; |
} |
/** |
* Set a channel's protocols to the protocols supported by pearweb |
*/ |
function setDefaultPEARProtocols($version = '1.0', $mirror = false) |
{ |
switch ($version) { |
case '1.0' : |
$this->resetREST($mirror); |
if (!isset($this->_channelInfo['servers'])) { |
$this->_channelInfo['servers'] = array('primary' => |
array('rest' => array())); |
} elseif (!isset($this->_channelInfo['servers']['primary'])) { |
$this->_channelInfo['servers']['primary'] = array('rest' => array()); |
} |
return true; |
break; |
default : |
return false; |
break; |
} |
} |
/** |
* @return array |
*/ |
function getMirrors() |
{ |
if (isset($this->_channelInfo['servers']['mirror'])) { |
$mirrors = $this->_channelInfo['servers']['mirror']; |
if (!isset($mirrors[0])) { |
$mirrors = array($mirrors); |
} |
return $mirrors; |
} |
return array(); |
} |
/** |
* Get the unserialized XML representing a mirror |
* @return array|false |
*/ |
function getMirror($server) |
{ |
foreach ($this->getMirrors() as $mirror) { |
if ($mirror['attribs']['host'] == $server) { |
return $mirror; |
} |
} |
return false; |
} |
/** |
* @param string |
* @return string|false |
* @error PEAR_CHANNELFILE_ERROR_NO_NAME |
* @error PEAR_CHANNELFILE_ERROR_INVALID_NAME |
*/ |
function setName($name) |
{ |
return $this->setServer($name); |
} |
/** |
* Set the socket number (port) that is used to connect to this channel |
* @param integer |
* @param string|false name of the mirror server, or false for the primary |
*/ |
function setPort($port, $mirror = false) |
{ |
if ($mirror) { |
if (!isset($this->_channelInfo['servers']['mirror'])) { |
$this->_validateError(PEAR_CHANNELFILE_ERROR_MIRROR_NOT_FOUND, |
array('mirror' => $mirror)); |
return false; |
} |
if (isset($this->_channelInfo['servers']['mirror'][0])) { |
foreach ($this->_channelInfo['servers']['mirror'] as $i => $mir) { |
if ($mirror == $mir['attribs']['host']) { |
$this->_channelInfo['servers']['mirror'][$i]['attribs']['port'] = $port; |
return true; |
} |
} |
return false; |
} elseif ($this->_channelInfo['servers']['mirror']['attribs']['host'] == $mirror) { |
$this->_channelInfo['servers']['mirror']['attribs']['port'] = $port; |
$this->_isValid = false; |
return true; |
} |
} |
$this->_channelInfo['servers']['primary']['attribs']['port'] = $port; |
$this->_isValid = false; |
return true; |
} |
/** |
* Set the socket number (port) that is used to connect to this channel |
* @param bool Determines whether to turn on SSL support or turn it off |
* @param string|false name of the mirror server, or false for the primary |
*/ |
function setSSL($ssl = true, $mirror = false) |
{ |
if ($mirror) { |
if (!isset($this->_channelInfo['servers']['mirror'])) { |
$this->_validateError(PEAR_CHANNELFILE_ERROR_MIRROR_NOT_FOUND, |
array('mirror' => $mirror)); |
return false; |
} |
if (isset($this->_channelInfo['servers']['mirror'][0])) { |
foreach ($this->_channelInfo['servers']['mirror'] as $i => $mir) { |
if ($mirror == $mir['attribs']['host']) { |
if (!$ssl) { |
if (isset($this->_channelInfo['servers']['mirror'][$i] |
['attribs']['ssl'])) { |
unset($this->_channelInfo['servers']['mirror'][$i]['attribs']['ssl']); |
} |
} else { |
$this->_channelInfo['servers']['mirror'][$i]['attribs']['ssl'] = 'yes'; |
} |
return true; |
} |
} |
return false; |
} elseif ($this->_channelInfo['servers']['mirror']['attribs']['host'] == $mirror) { |
if (!$ssl) { |
if (isset($this->_channelInfo['servers']['mirror']['attribs']['ssl'])) { |
unset($this->_channelInfo['servers']['mirror']['attribs']['ssl']); |
} |
} else { |
$this->_channelInfo['servers']['mirror']['attribs']['ssl'] = 'yes'; |
} |
$this->_isValid = false; |
return true; |
} |
} |
if ($ssl) { |
$this->_channelInfo['servers']['primary']['attribs']['ssl'] = 'yes'; |
} else { |
if (isset($this->_channelInfo['servers']['primary']['attribs']['ssl'])) { |
unset($this->_channelInfo['servers']['primary']['attribs']['ssl']); |
} |
} |
$this->_isValid = false; |
return true; |
} |
/** |
* @param string |
* @return string|false |
* @error PEAR_CHANNELFILE_ERROR_NO_SERVER |
* @error PEAR_CHANNELFILE_ERROR_INVALID_SERVER |
*/ |
function setServer($server, $mirror = false) |
{ |
if (empty($server)) { |
$this->_validateError(PEAR_CHANNELFILE_ERROR_NO_SERVER); |
return false; |
} elseif (!$this->validChannelServer($server)) { |
$this->_validateError(PEAR_CHANNELFILE_ERROR_INVALID_NAME, |
array('tag' => 'name', 'name' => $server)); |
return false; |
} |
if ($mirror) { |
$found = false; |
foreach ($this->_channelInfo['servers']['mirror'] as $i => $mir) { |
if ($mirror == $mir['attribs']['host']) { |
$found = true; |
break; |
} |
} |
if (!$found) { |
$this->_validateError(PEAR_CHANNELFILE_ERROR_MIRROR_NOT_FOUND, |
array('mirror' => $mirror)); |
return false; |
} |
$this->_channelInfo['mirror'][$i]['attribs']['host'] = $server; |
return true; |
} |
$this->_channelInfo['name'] = $server; |
return true; |
} |
/** |
* @param string |
* @return boolean success |
* @error PEAR_CHANNELFILE_ERROR_NO_SUMMARY |
* @warning PEAR_CHANNELFILE_ERROR_MULTILINE_SUMMARY |
*/ |
function setSummary($summary) |
{ |
if (empty($summary)) { |
$this->_validateError(PEAR_CHANNELFILE_ERROR_NO_SUMMARY); |
return false; |
} elseif (strpos(trim($summary), "\n") !== false) { |
$this->_validateWarning(PEAR_CHANNELFILE_ERROR_MULTILINE_SUMMARY, |
array('summary' => $summary)); |
} |
$this->_channelInfo['summary'] = $summary; |
return true; |
} |
/** |
* @param string |
* @param boolean determines whether the alias is in channel.xml or local |
* @return boolean success |
*/ |
function setAlias($alias, $local = false) |
{ |
if (!$this->validChannelServer($alias)) { |
$this->_validateError(PEAR_CHANNELFILE_ERROR_INVALID_NAME, |
array('tag' => 'suggestedalias', 'name' => $alias)); |
return false; |
} |
if ($local) { |
$this->_channelInfo['localalias'] = $alias; |
} else { |
$this->_channelInfo['suggestedalias'] = $alias; |
} |
return true; |
} |
/** |
* @return string |
*/ |
function getAlias() |
{ |
if (isset($this->_channelInfo['localalias'])) { |
return $this->_channelInfo['localalias']; |
} |
if (isset($this->_channelInfo['suggestedalias'])) { |
return $this->_channelInfo['suggestedalias']; |
} |
if (isset($this->_channelInfo['name'])) { |
return $this->_channelInfo['name']; |
} |
return ''; |
} |
/** |
* Set the package validation object if it differs from PEAR's default |
* The class must be includeable via changing _ in the classname to path separator, |
* but no checking of this is made. |
* @param string|false pass in false to reset to the default packagename regex |
* @return boolean success |
*/ |
function setValidationPackage($validateclass, $version) |
{ |
if (empty($validateclass)) { |
unset($this->_channelInfo['validatepackage']); |
} |
$this->_channelInfo['validatepackage'] = array('_content' => $validateclass); |
$this->_channelInfo['validatepackage']['attribs'] = array('version' => $version); |
} |
/** |
* Add a protocol to the provides section |
* @param string protocol type |
* @param string protocol version |
* @param string protocol name, if any |
* @param string mirror name, if this is a mirror's protocol |
* @return bool |
*/ |
function addFunction($type, $version, $name = '', $mirror = false) |
{ |
if ($mirror) { |
return $this->addMirrorFunction($mirror, $type, $version, $name); |
} |
$set = array('attribs' => array('version' => $version), '_content' => $name); |
if (!isset($this->_channelInfo['servers']['primary'][$type]['function'])) { |
if (!isset($this->_channelInfo['servers'])) { |
$this->_channelInfo['servers'] = array('primary' => |
array($type => array())); |
} elseif (!isset($this->_channelInfo['servers']['primary'])) { |
$this->_channelInfo['servers']['primary'] = array($type => array()); |
} |
$this->_channelInfo['servers']['primary'][$type]['function'] = $set; |
$this->_isValid = false; |
return true; |
} elseif (!isset($this->_channelInfo['servers']['primary'][$type]['function'][0])) { |
$this->_channelInfo['servers']['primary'][$type]['function'] = array( |
$this->_channelInfo['servers']['primary'][$type]['function']); |
} |
$this->_channelInfo['servers']['primary'][$type]['function'][] = $set; |
return true; |
} |
/** |
* Add a protocol to a mirror's provides section |
* @param string mirror name (server) |
* @param string protocol type |
* @param string protocol version |
* @param string protocol name, if any |
*/ |
function addMirrorFunction($mirror, $type, $version, $name = '') |
{ |
if (!isset($this->_channelInfo['servers']['mirror'])) { |
$this->_validateError(PEAR_CHANNELFILE_ERROR_MIRROR_NOT_FOUND, |
array('mirror' => $mirror)); |
return false; |
} |
$setmirror = false; |
if (isset($this->_channelInfo['servers']['mirror'][0])) { |
foreach ($this->_channelInfo['servers']['mirror'] as $i => $mir) { |
if ($mirror == $mir['attribs']['host']) { |
$setmirror = &$this->_channelInfo['servers']['mirror'][$i]; |
break; |
} |
} |
} else { |
if ($this->_channelInfo['servers']['mirror']['attribs']['host'] == $mirror) { |
$setmirror = &$this->_channelInfo['servers']['mirror']; |
} |
} |
if (!$setmirror) { |
$this->_validateError(PEAR_CHANNELFILE_ERROR_MIRROR_NOT_FOUND, |
array('mirror' => $mirror)); |
return false; |
} |
$set = array('attribs' => array('version' => $version), '_content' => $name); |
if (!isset($setmirror[$type]['function'])) { |
$setmirror[$type]['function'] = $set; |
$this->_isValid = false; |
return true; |
} elseif (!isset($setmirror[$type]['function'][0])) { |
$setmirror[$type]['function'] = array($setmirror[$type]['function']); |
} |
$setmirror[$type]['function'][] = $set; |
$this->_isValid = false; |
return true; |
} |
/** |
* @param string Resource Type this url links to |
* @param string URL |
* @param string|false mirror name, if this is not a primary server REST base URL |
*/ |
function setBaseURL($resourceType, $url, $mirror = false) |
{ |
if ($mirror) { |
if (!isset($this->_channelInfo['servers']['mirror'])) { |
$this->_validateError(PEAR_CHANNELFILE_ERROR_MIRROR_NOT_FOUND, |
array('mirror' => $mirror)); |
return false; |
} |
$setmirror = false; |
if (isset($this->_channelInfo['servers']['mirror'][0])) { |
foreach ($this->_channelInfo['servers']['mirror'] as $i => $mir) { |
if ($mirror == $mir['attribs']['host']) { |
$setmirror = &$this->_channelInfo['servers']['mirror'][$i]; |
break; |
} |
} |
} else { |
if ($this->_channelInfo['servers']['mirror']['attribs']['host'] == $mirror) { |
$setmirror = &$this->_channelInfo['servers']['mirror']; |
} |
} |
} else { |
$setmirror = &$this->_channelInfo['servers']['primary']; |
} |
$set = array('attribs' => array('type' => $resourceType), '_content' => $url); |
if (!isset($setmirror['rest'])) { |
$setmirror['rest'] = array(); |
} |
if (!isset($setmirror['rest']['baseurl'])) { |
$setmirror['rest']['baseurl'] = $set; |
$this->_isValid = false; |
return true; |
} elseif (!isset($setmirror['rest']['baseurl'][0])) { |
$setmirror['rest']['baseurl'] = array($setmirror['rest']['baseurl']); |
} |
foreach ($setmirror['rest']['baseurl'] as $i => $url) { |
if ($url['attribs']['type'] == $resourceType) { |
$this->_isValid = false; |
$setmirror['rest']['baseurl'][$i] = $set; |
return true; |
} |
} |
$setmirror['rest']['baseurl'][] = $set; |
$this->_isValid = false; |
return true; |
} |
/** |
* @param string mirror server |
* @param int mirror http port |
* @return boolean |
*/ |
function addMirror($server, $port = null) |
{ |
if ($this->_channelInfo['name'] == '__uri') { |
return false; // the __uri channel cannot have mirrors by definition |
} |
$set = array('attribs' => array('host' => $server)); |
if (is_numeric($port)) { |
$set['attribs']['port'] = $port; |
} |
if (!isset($this->_channelInfo['servers']['mirror'])) { |
$this->_channelInfo['servers']['mirror'] = $set; |
return true; |
} |
if (!isset($this->_channelInfo['servers']['mirror'][0])) { |
$this->_channelInfo['servers']['mirror'] = |
array($this->_channelInfo['servers']['mirror']); |
} |
$this->_channelInfo['servers']['mirror'][] = $set; |
return true; |
} |
/** |
* Retrieve the name of the validation package for this channel |
* @return string|false |
*/ |
function getValidationPackage() |
{ |
if (!$this->_isValid && !$this->validate()) { |
return false; |
} |
if (!isset($this->_channelInfo['validatepackage'])) { |
return array('attribs' => array('version' => 'default'), |
'_content' => 'PEAR_Validate'); |
} |
return $this->_channelInfo['validatepackage']; |
} |
/** |
* Retrieve the object that can be used for custom validation |
* @param string|false the name of the package to validate. If the package is |
* the channel validation package, PEAR_Validate is returned |
* @return PEAR_Validate|false false is returned if the validation package |
* cannot be located |
*/ |
function &getValidationObject($package = false) |
{ |
if (!class_exists('PEAR_Validate')) { |
require_once 'PEAR/Validate.php'; |
} |
if (!$this->_isValid) { |
if (!$this->validate()) { |
$a = false; |
return $a; |
} |
} |
if (isset($this->_channelInfo['validatepackage'])) { |
if ($package == $this->_channelInfo['validatepackage']) { |
// channel validation packages are always validated by PEAR_Validate |
$val = new PEAR_Validate; |
return $val; |
} |
if (!class_exists(str_replace('.', '_', |
$this->_channelInfo['validatepackage']['_content']))) { |
if ($this->isIncludeable(str_replace('_', '/', |
$this->_channelInfo['validatepackage']['_content']) . '.php')) { |
include_once str_replace('_', '/', |
$this->_channelInfo['validatepackage']['_content']) . '.php'; |
$vclass = str_replace('.', '_', |
$this->_channelInfo['validatepackage']['_content']); |
$val = new $vclass; |
} else { |
$a = false; |
return $a; |
} |
} else { |
$vclass = str_replace('.', '_', |
$this->_channelInfo['validatepackage']['_content']); |
$val = new $vclass; |
} |
} else { |
$val = new PEAR_Validate; |
} |
return $val; |
} |
function isIncludeable($path) |
{ |
$possibilities = explode(PATH_SEPARATOR, ini_get('include_path')); |
foreach ($possibilities as $dir) { |
if (file_exists($dir . DIRECTORY_SEPARATOR . $path) |
&& is_readable($dir . DIRECTORY_SEPARATOR . $path)) { |
return true; |
} |
} |
return false; |
} |
/** |
* This function is used by the channel updater and retrieves a value set by |
* the registry, or the current time if it has not been set |
* @return string |
*/ |
function lastModified() |
{ |
if (isset($this->_channelInfo['_lastmodified'])) { |
return $this->_channelInfo['_lastmodified']; |
} |
return time(); |
} |
} |
/branches/v1.3-critias/bibliotheque/pear/PEAR/Registry.php |
---|
New file |
0,0 → 1,2388 |
<?php |
/** |
* PEAR_Registry |
* |
* PHP versions 4 and 5 |
* |
* @category pear |
* @package PEAR |
* @author Stig Bakken <ssb@php.net> |
* @author Tomas V. V. Cox <cox@idecnet.com> |
* @author Greg Beaver <cellog@php.net> |
* @copyright 1997-2009 The Authors |
* @license http://opensource.org/licenses/bsd-license.php New BSD License |
* @link http://pear.php.net/package/PEAR |
* @since File available since Release 0.1 |
*/ |
/** |
* for PEAR_Error |
*/ |
require_once 'PEAR.php'; |
require_once 'PEAR/DependencyDB.php'; |
define('PEAR_REGISTRY_ERROR_LOCK', -2); |
define('PEAR_REGISTRY_ERROR_FORMAT', -3); |
define('PEAR_REGISTRY_ERROR_FILE', -4); |
define('PEAR_REGISTRY_ERROR_CONFLICT', -5); |
define('PEAR_REGISTRY_ERROR_CHANNEL_FILE', -6); |
/** |
* Administration class used to maintain the installed package database. |
* @category pear |
* @package PEAR |
* @author Stig Bakken <ssb@php.net> |
* @author Tomas V. V. Cox <cox@idecnet.com> |
* @author Greg Beaver <cellog@php.net> |
* @copyright 1997-2009 The Authors |
* @license http://opensource.org/licenses/bsd-license.php New BSD License |
* @version Release: 1.10.1 |
* @link http://pear.php.net/package/PEAR |
* @since Class available since Release 1.4.0a1 |
*/ |
class PEAR_Registry extends PEAR |
{ |
/** |
* File containing all channel information. |
* @var string |
*/ |
var $channels = ''; |
/** Directory where registry files are stored. |
* @var string |
*/ |
var $statedir = ''; |
/** File where the file map is stored |
* @var string |
*/ |
var $filemap = ''; |
/** Directory where registry files for channels are stored. |
* @var string |
*/ |
var $channelsdir = ''; |
/** Name of file used for locking the registry |
* @var string |
*/ |
var $lockfile = ''; |
/** File descriptor used during locking |
* @var resource |
*/ |
var $lock_fp = null; |
/** Mode used during locking |
* @var int |
*/ |
var $lock_mode = 0; // XXX UNUSED |
/** Cache of package information. Structure: |
* array( |
* 'package' => array('id' => ... ), |
* ... ) |
* @var array |
*/ |
var $pkginfo_cache = array(); |
/** Cache of file map. Structure: |
* array( '/path/to/file' => 'package', ... ) |
* @var array |
*/ |
var $filemap_cache = array(); |
/** |
* @var false|PEAR_ChannelFile |
*/ |
var $_pearChannel; |
/** |
* @var false|PEAR_ChannelFile |
*/ |
var $_peclChannel; |
/** |
* @var false|PEAR_ChannelFile |
*/ |
var $_docChannel; |
/** |
* @var PEAR_DependencyDB |
*/ |
var $_dependencyDB; |
/** |
* @var PEAR_Config |
*/ |
var $_config; |
/** |
* PEAR_Registry constructor. |
* |
* @param string (optional) PEAR install directory (for .php files) |
* @param PEAR_ChannelFile PEAR_ChannelFile object representing the PEAR channel, if |
* default values are not desired. Only used the very first time a PEAR |
* repository is initialized |
* @param PEAR_ChannelFile PEAR_ChannelFile object representing the PECL channel, if |
* default values are not desired. Only used the very first time a PEAR |
* repository is initialized |
* |
* @access public |
*/ |
function __construct($pear_install_dir = PEAR_INSTALL_DIR, $pear_channel = false, |
$pecl_channel = false, $pear_metadata_dir = '') |
{ |
parent::__construct(); |
$this->setInstallDir($pear_install_dir, $pear_metadata_dir); |
$this->_pearChannel = $pear_channel; |
$this->_peclChannel = $pecl_channel; |
$this->_config = false; |
} |
function setInstallDir($pear_install_dir = PEAR_INSTALL_DIR, $pear_metadata_dir = '') |
{ |
$ds = DIRECTORY_SEPARATOR; |
$this->install_dir = $pear_install_dir; |
if (!$pear_metadata_dir) { |
$pear_metadata_dir = $pear_install_dir; |
} |
$this->channelsdir = $pear_metadata_dir.$ds.'.channels'; |
$this->statedir = $pear_metadata_dir.$ds.'.registry'; |
$this->filemap = $pear_metadata_dir.$ds.'.filemap'; |
$this->lockfile = $pear_metadata_dir.$ds.'.lock'; |
} |
function hasWriteAccess() |
{ |
if (!file_exists($this->install_dir)) { |
$dir = $this->install_dir; |
while ($dir && $dir != '.') { |
$olddir = $dir; |
$dir = dirname($dir); |
if ($dir != '.' && file_exists($dir)) { |
if (is_writeable($dir)) { |
return true; |
} |
return false; |
} |
if ($dir == $olddir) { // this can happen in safe mode |
return @is_writable($dir); |
} |
} |
return false; |
} |
return is_writeable($this->install_dir); |
} |
function setConfig(&$config, $resetInstallDir = true) |
{ |
$this->_config = &$config; |
if ($resetInstallDir) { |
$this->setInstallDir($config->get('php_dir'), $config->get('metadata_dir')); |
} |
} |
function _initializeChannelDirs() |
{ |
static $running = false; |
if (!$running) { |
$running = true; |
$ds = DIRECTORY_SEPARATOR; |
if (!is_dir($this->channelsdir) || |
!file_exists($this->channelsdir . $ds . 'pear.php.net.reg') || |
!file_exists($this->channelsdir . $ds . 'pecl.php.net.reg') || |
!file_exists($this->channelsdir . $ds . 'doc.php.net.reg') || |
!file_exists($this->channelsdir . $ds . '__uri.reg')) { |
if (!file_exists($this->channelsdir . $ds . 'pear.php.net.reg')) { |
$pear_channel = $this->_pearChannel; |
if (!is_a($pear_channel, 'PEAR_ChannelFile') || !$pear_channel->validate()) { |
if (!class_exists('PEAR_ChannelFile')) { |
require_once 'PEAR/ChannelFile.php'; |
} |
$pear_channel = new PEAR_ChannelFile; |
$pear_channel->setAlias('pear'); |
$pear_channel->setServer('pear.php.net'); |
$pear_channel->setSummary('PHP Extension and Application Repository'); |
$pear_channel->setDefaultPEARProtocols(); |
$pear_channel->setBaseURL('REST1.0', 'http://pear.php.net/rest/'); |
$pear_channel->setBaseURL('REST1.1', 'http://pear.php.net/rest/'); |
$pear_channel->setBaseURL('REST1.3', 'http://pear.php.net/rest/'); |
//$pear_channel->setBaseURL('REST1.4', 'http://pear.php.net/rest/'); |
} else { |
$pear_channel->setServer('pear.php.net'); |
$pear_channel->setAlias('pear'); |
} |
$pear_channel->validate(); |
$this->_addChannel($pear_channel); |
} |
if (!file_exists($this->channelsdir . $ds . 'pecl.php.net.reg')) { |
$pecl_channel = $this->_peclChannel; |
if (!is_a($pecl_channel, 'PEAR_ChannelFile') || !$pecl_channel->validate()) { |
if (!class_exists('PEAR_ChannelFile')) { |
require_once 'PEAR/ChannelFile.php'; |
} |
$pecl_channel = new PEAR_ChannelFile; |
$pecl_channel->setAlias('pecl'); |
$pecl_channel->setServer('pecl.php.net'); |
$pecl_channel->setSummary('PHP Extension Community Library'); |
$pecl_channel->setDefaultPEARProtocols(); |
$pecl_channel->setBaseURL('REST1.0', 'http://pecl.php.net/rest/'); |
$pecl_channel->setBaseURL('REST1.1', 'http://pecl.php.net/rest/'); |
$pecl_channel->setValidationPackage('PEAR_Validator_PECL', '1.0'); |
} else { |
$pecl_channel->setServer('pecl.php.net'); |
$pecl_channel->setAlias('pecl'); |
} |
$pecl_channel->validate(); |
$this->_addChannel($pecl_channel); |
} |
if (!file_exists($this->channelsdir . $ds . 'doc.php.net.reg')) { |
$doc_channel = $this->_docChannel; |
if (!is_a($doc_channel, 'PEAR_ChannelFile') || !$doc_channel->validate()) { |
if (!class_exists('PEAR_ChannelFile')) { |
require_once 'PEAR/ChannelFile.php'; |
} |
$doc_channel = new PEAR_ChannelFile; |
$doc_channel->setAlias('phpdocs'); |
$doc_channel->setServer('doc.php.net'); |
$doc_channel->setSummary('PHP Documentation Team'); |
$doc_channel->setDefaultPEARProtocols(); |
$doc_channel->setBaseURL('REST1.0', 'http://doc.php.net/rest/'); |
$doc_channel->setBaseURL('REST1.1', 'http://doc.php.net/rest/'); |
$doc_channel->setBaseURL('REST1.3', 'http://doc.php.net/rest/'); |
} else { |
$doc_channel->setServer('doc.php.net'); |
$doc_channel->setAlias('doc'); |
} |
$doc_channel->validate(); |
$this->_addChannel($doc_channel); |
} |
if (!file_exists($this->channelsdir . $ds . '__uri.reg')) { |
if (!class_exists('PEAR_ChannelFile')) { |
require_once 'PEAR/ChannelFile.php'; |
} |
$private = new PEAR_ChannelFile; |
$private->setName('__uri'); |
$private->setDefaultPEARProtocols(); |
$private->setBaseURL('REST1.0', '****'); |
$private->setSummary('Pseudo-channel for static packages'); |
$this->_addChannel($private); |
} |
$this->_rebuildFileMap(); |
} |
$running = false; |
} |
} |
function _initializeDirs() |
{ |
$ds = DIRECTORY_SEPARATOR; |
// XXX Compatibility code should be removed in the future |
// rename all registry files if any to lowercase |
if (!OS_WINDOWS && file_exists($this->statedir) && is_dir($this->statedir) && |
$handle = opendir($this->statedir)) { |
$dest = $this->statedir . $ds; |
while (false !== ($file = readdir($handle))) { |
if (preg_match('/^.*[A-Z].*\.reg\\z/', $file)) { |
rename($dest . $file, $dest . strtolower($file)); |
} |
} |
closedir($handle); |
} |
$this->_initializeChannelDirs(); |
if (!file_exists($this->filemap)) { |
$this->_rebuildFileMap(); |
} |
$this->_initializeDepDB(); |
} |
function _initializeDepDB() |
{ |
if (!isset($this->_dependencyDB)) { |
static $initializing = false; |
if (!$initializing) { |
$initializing = true; |
if (!$this->_config) { // never used? |
$file = OS_WINDOWS ? 'pear.ini' : '.pearrc'; |
$this->_config = new PEAR_Config($this->statedir . DIRECTORY_SEPARATOR . |
$file); |
$this->_config->setRegistry($this); |
$this->_config->set('php_dir', $this->install_dir); |
} |
$this->_dependencyDB = &PEAR_DependencyDB::singleton($this->_config); |
if (PEAR::isError($this->_dependencyDB)) { |
// attempt to recover by removing the dep db |
if (file_exists($this->_config->get('metadata_dir', null, 'pear.php.net') . |
DIRECTORY_SEPARATOR . '.depdb')) { |
@unlink($this->_config->get('metadata_dir', null, 'pear.php.net') . |
DIRECTORY_SEPARATOR . '.depdb'); |
} |
$this->_dependencyDB = &PEAR_DependencyDB::singleton($this->_config); |
if (PEAR::isError($this->_dependencyDB)) { |
echo $this->_dependencyDB->getMessage(); |
echo 'Unrecoverable error'; |
exit(1); |
} |
} |
$initializing = false; |
} |
} |
} |
/** |
* PEAR_Registry destructor. Makes sure no locks are forgotten. |
* |
* @access private |
*/ |
function _PEAR_Registry() |
{ |
parent::_PEAR(); |
if (is_resource($this->lock_fp)) { |
$this->_unlock(); |
} |
} |
/** |
* Make sure the directory where we keep registry files exists. |
* |
* @return bool TRUE if directory exists, FALSE if it could not be |
* created |
* |
* @access private |
*/ |
function _assertStateDir($channel = false) |
{ |
if ($channel && $this->_getChannelFromAlias($channel) != 'pear.php.net') { |
return $this->_assertChannelStateDir($channel); |
} |
static $init = false; |
if (!file_exists($this->statedir)) { |
if (!$this->hasWriteAccess()) { |
return false; |
} |
require_once 'System.php'; |
if (!System::mkdir(array('-p', $this->statedir))) { |
return $this->raiseError("could not create directory '{$this->statedir}'"); |
} |
$init = true; |
} elseif (!is_dir($this->statedir)) { |
return $this->raiseError('Cannot create directory ' . $this->statedir . ', ' . |
'it already exists and is not a directory'); |
} |
$ds = DIRECTORY_SEPARATOR; |
if (!file_exists($this->channelsdir)) { |
if (!file_exists($this->channelsdir . $ds . 'pear.php.net.reg') || |
!file_exists($this->channelsdir . $ds . 'pecl.php.net.reg') || |
!file_exists($this->channelsdir . $ds . 'doc.php.net.reg') || |
!file_exists($this->channelsdir . $ds . '__uri.reg')) { |
$init = true; |
} |
} elseif (!is_dir($this->channelsdir)) { |
return $this->raiseError('Cannot create directory ' . $this->channelsdir . ', ' . |
'it already exists and is not a directory'); |
} |
if ($init) { |
static $running = false; |
if (!$running) { |
$running = true; |
$this->_initializeDirs(); |
$running = false; |
$init = false; |
} |
} else { |
$this->_initializeDepDB(); |
} |
return true; |
} |
/** |
* Make sure the directory where we keep registry files exists for a non-standard channel. |
* |
* @param string channel name |
* @return bool TRUE if directory exists, FALSE if it could not be |
* created |
* |
* @access private |
*/ |
function _assertChannelStateDir($channel) |
{ |
$ds = DIRECTORY_SEPARATOR; |
if (!$channel || $this->_getChannelFromAlias($channel) == 'pear.php.net') { |
if (!file_exists($this->channelsdir . $ds . 'pear.php.net.reg')) { |
$this->_initializeChannelDirs(); |
} |
return $this->_assertStateDir($channel); |
} |
$channelDir = $this->_channelDirectoryName($channel); |
if (!is_dir($this->channelsdir) || |
!file_exists($this->channelsdir . $ds . 'pear.php.net.reg')) { |
$this->_initializeChannelDirs(); |
} |
if (!file_exists($channelDir)) { |
if (!$this->hasWriteAccess()) { |
return false; |
} |
require_once 'System.php'; |
if (!System::mkdir(array('-p', $channelDir))) { |
return $this->raiseError("could not create directory '" . $channelDir . |
"'"); |
} |
} elseif (!is_dir($channelDir)) { |
return $this->raiseError("could not create directory '" . $channelDir . |
"', already exists and is not a directory"); |
} |
return true; |
} |
/** |
* Make sure the directory where we keep registry files for channels exists |
* |
* @return bool TRUE if directory exists, FALSE if it could not be |
* created |
* |
* @access private |
*/ |
function _assertChannelDir() |
{ |
if (!file_exists($this->channelsdir)) { |
if (!$this->hasWriteAccess()) { |
return false; |
} |
require_once 'System.php'; |
if (!System::mkdir(array('-p', $this->channelsdir))) { |
return $this->raiseError("could not create directory '{$this->channelsdir}'"); |
} |
} elseif (!is_dir($this->channelsdir)) { |
return $this->raiseError("could not create directory '{$this->channelsdir}" . |
"', it already exists and is not a directory"); |
} |
if (!file_exists($this->channelsdir . DIRECTORY_SEPARATOR . '.alias')) { |
if (!$this->hasWriteAccess()) { |
return false; |
} |
require_once 'System.php'; |
if (!System::mkdir(array('-p', $this->channelsdir . DIRECTORY_SEPARATOR . '.alias'))) { |
return $this->raiseError("could not create directory '{$this->channelsdir}/.alias'"); |
} |
} elseif (!is_dir($this->channelsdir . DIRECTORY_SEPARATOR . '.alias')) { |
return $this->raiseError("could not create directory '{$this->channelsdir}" . |
"/.alias', it already exists and is not a directory"); |
} |
return true; |
} |
/** |
* Get the name of the file where data for a given package is stored. |
* |
* @param string channel name, or false if this is a PEAR package |
* @param string package name |
* |
* @return string registry file name |
* |
* @access public |
*/ |
function _packageFileName($package, $channel = false) |
{ |
if ($channel && $this->_getChannelFromAlias($channel) != 'pear.php.net') { |
return $this->_channelDirectoryName($channel) . DIRECTORY_SEPARATOR . |
strtolower($package) . '.reg'; |
} |
return $this->statedir . DIRECTORY_SEPARATOR . strtolower($package) . '.reg'; |
} |
/** |
* Get the name of the file where data for a given channel is stored. |
* @param string channel name |
* @return string registry file name |
*/ |
function _channelFileName($channel, $noaliases = false) |
{ |
if (!$noaliases) { |
if (file_exists($this->_getChannelAliasFileName($channel))) { |
$channel = implode('', file($this->_getChannelAliasFileName($channel))); |
} |
} |
return $this->channelsdir . DIRECTORY_SEPARATOR . str_replace('/', '_', |
strtolower($channel)) . '.reg'; |
} |
/** |
* @param string |
* @return string |
*/ |
function _getChannelAliasFileName($alias) |
{ |
return $this->channelsdir . DIRECTORY_SEPARATOR . '.alias' . |
DIRECTORY_SEPARATOR . str_replace('/', '_', strtolower($alias)) . '.txt'; |
} |
/** |
* Get the name of a channel from its alias |
*/ |
function _getChannelFromAlias($channel) |
{ |
if (!$this->_channelExists($channel)) { |
if ($channel == 'pear.php.net') { |
return 'pear.php.net'; |
} |
if ($channel == 'pecl.php.net') { |
return 'pecl.php.net'; |
} |
if ($channel == 'doc.php.net') { |
return 'doc.php.net'; |
} |
if ($channel == '__uri') { |
return '__uri'; |
} |
return false; |
} |
$channel = strtolower($channel); |
if (file_exists($this->_getChannelAliasFileName($channel))) { |
// translate an alias to an actual channel |
return implode('', file($this->_getChannelAliasFileName($channel))); |
} |
return $channel; |
} |
/** |
* Get the alias of a channel from its alias or its name |
*/ |
function _getAlias($channel) |
{ |
if (!$this->_channelExists($channel)) { |
if ($channel == 'pear.php.net') { |
return 'pear'; |
} |
if ($channel == 'pecl.php.net') { |
return 'pecl'; |
} |
if ($channel == 'doc.php.net') { |
return 'phpdocs'; |
} |
return false; |
} |
$channel = $this->_getChannel($channel); |
if (PEAR::isError($channel)) { |
return $channel; |
} |
return $channel->getAlias(); |
} |
/** |
* Get the name of the file where data for a given package is stored. |
* |
* @param string channel name, or false if this is a PEAR package |
* @param string package name |
* |
* @return string registry file name |
* |
* @access public |
*/ |
function _channelDirectoryName($channel) |
{ |
if (!$channel || $this->_getChannelFromAlias($channel) == 'pear.php.net') { |
return $this->statedir; |
} |
$ch = $this->_getChannelFromAlias($channel); |
if (!$ch) { |
$ch = $channel; |
} |
return $this->statedir . DIRECTORY_SEPARATOR . strtolower('.channel.' . |
str_replace('/', '_', $ch)); |
} |
function _openPackageFile($package, $mode, $channel = false) |
{ |
if (!$this->_assertStateDir($channel)) { |
return null; |
} |
if (!in_array($mode, array('r', 'rb')) && !$this->hasWriteAccess()) { |
return null; |
} |
$file = $this->_packageFileName($package, $channel); |
if (!file_exists($file) && $mode == 'r' || $mode == 'rb') { |
return null; |
} |
$fp = @fopen($file, $mode); |
if (!$fp) { |
return null; |
} |
return $fp; |
} |
function _closePackageFile($fp) |
{ |
fclose($fp); |
} |
function _openChannelFile($channel, $mode) |
{ |
if (!$this->_assertChannelDir()) { |
return null; |
} |
if (!in_array($mode, array('r', 'rb')) && !$this->hasWriteAccess()) { |
return null; |
} |
$file = $this->_channelFileName($channel); |
if (!file_exists($file) && $mode == 'r' || $mode == 'rb') { |
return null; |
} |
$fp = @fopen($file, $mode); |
if (!$fp) { |
return null; |
} |
return $fp; |
} |
function _closeChannelFile($fp) |
{ |
fclose($fp); |
} |
function _rebuildFileMap() |
{ |
if (!class_exists('PEAR_Installer_Role')) { |
require_once 'PEAR/Installer/Role.php'; |
} |
$channels = $this->_listAllPackages(); |
$files = array(); |
foreach ($channels as $channel => $packages) { |
foreach ($packages as $package) { |
$version = $this->_packageInfo($package, 'version', $channel); |
$filelist = $this->_packageInfo($package, 'filelist', $channel); |
if (!is_array($filelist)) { |
continue; |
} |
foreach ($filelist as $name => $attrs) { |
if (isset($attrs['attribs'])) { |
$attrs = $attrs['attribs']; |
} |
// it is possible for conflicting packages in different channels to |
// conflict with data files/doc files |
if ($name == 'dirtree') { |
continue; |
} |
if (isset($attrs['role']) && !in_array($attrs['role'], |
PEAR_Installer_Role::getInstallableRoles())) { |
// these are not installed |
continue; |
} |
if (isset($attrs['role']) && !in_array($attrs['role'], |
PEAR_Installer_Role::getBaseinstallRoles())) { |
$attrs['baseinstalldir'] = $package; |
} |
if (isset($attrs['baseinstalldir'])) { |
$file = $attrs['baseinstalldir'].DIRECTORY_SEPARATOR.$name; |
} else { |
$file = $name; |
} |
$file = preg_replace(',^/+,', '', $file); |
if ($channel != 'pear.php.net') { |
if (!isset($files[$attrs['role']])) { |
$files[$attrs['role']] = array(); |
} |
$files[$attrs['role']][$file] = array(strtolower($channel), |
strtolower($package)); |
} else { |
if (!isset($files[$attrs['role']])) { |
$files[$attrs['role']] = array(); |
} |
$files[$attrs['role']][$file] = strtolower($package); |
} |
} |
} |
} |
$this->_assertStateDir(); |
if (!$this->hasWriteAccess()) { |
return false; |
} |
$fp = @fopen($this->filemap, 'wb'); |
if (!$fp) { |
return false; |
} |
$this->filemap_cache = $files; |
fwrite($fp, serialize($files)); |
fclose($fp); |
return true; |
} |
function _readFileMap() |
{ |
if (!file_exists($this->filemap)) { |
return array(); |
} |
$fp = @fopen($this->filemap, 'r'); |
if (!$fp) { |
return $this->raiseError('PEAR_Registry: could not open filemap "' . $this->filemap . '"', PEAR_REGISTRY_ERROR_FILE, null, null, $php_errormsg); |
} |
clearstatcache(); |
$fsize = filesize($this->filemap); |
fclose($fp); |
$data = file_get_contents($this->filemap); |
$tmp = unserialize($data); |
if (!$tmp && $fsize > 7) { |
return $this->raiseError('PEAR_Registry: invalid filemap data', PEAR_REGISTRY_ERROR_FORMAT, null, null, $data); |
} |
$this->filemap_cache = $tmp; |
return true; |
} |
/** |
* Lock the registry. |
* |
* @param integer lock mode, one of LOCK_EX, LOCK_SH or LOCK_UN. |
* See flock manual for more information. |
* |
* @return bool TRUE on success, FALSE if locking failed, or a |
* PEAR error if some other error occurs (such as the |
* lock file not being writable). |
* |
* @access private |
*/ |
function _lock($mode = LOCK_EX) |
{ |
if (stristr(php_uname(), 'Windows 9')) { |
return true; |
} |
if ($mode != LOCK_UN && is_resource($this->lock_fp)) { |
// XXX does not check type of lock (LOCK_SH/LOCK_EX) |
return true; |
} |
if (!$this->_assertStateDir()) { |
if ($mode == LOCK_EX) { |
return $this->raiseError('Registry directory is not writeable by the current user'); |
} |
return true; |
} |
$open_mode = 'w'; |
// XXX People reported problems with LOCK_SH and 'w' |
if ($mode === LOCK_SH || $mode === LOCK_UN) { |
if (!file_exists($this->lockfile)) { |
touch($this->lockfile); |
} |
$open_mode = 'r'; |
} |
if (!is_resource($this->lock_fp)) { |
$this->lock_fp = @fopen($this->lockfile, $open_mode); |
} |
if (!is_resource($this->lock_fp)) { |
$this->lock_fp = null; |
return $this->raiseError("could not create lock file" . |
(isset($php_errormsg) ? ": " . $php_errormsg : "")); |
} |
if (!(int)flock($this->lock_fp, $mode)) { |
switch ($mode) { |
case LOCK_SH: $str = 'shared'; break; |
case LOCK_EX: $str = 'exclusive'; break; |
case LOCK_UN: $str = 'unlock'; break; |
default: $str = 'unknown'; break; |
} |
//is resource at this point, close it on error. |
fclose($this->lock_fp); |
$this->lock_fp = null; |
return $this->raiseError("could not acquire $str lock ($this->lockfile)", |
PEAR_REGISTRY_ERROR_LOCK); |
} |
return true; |
} |
function _unlock() |
{ |
$ret = $this->_lock(LOCK_UN); |
if (is_resource($this->lock_fp)) { |
fclose($this->lock_fp); |
} |
$this->lock_fp = null; |
return $ret; |
} |
function _packageExists($package, $channel = false) |
{ |
return file_exists($this->_packageFileName($package, $channel)); |
} |
/** |
* Determine whether a channel exists in the registry |
* |
* @param string Channel name |
* @param bool if true, then aliases will be ignored |
* @return boolean |
*/ |
function _channelExists($channel, $noaliases = false) |
{ |
$a = file_exists($this->_channelFileName($channel, $noaliases)); |
if (!$a && $channel == 'pear.php.net') { |
return true; |
} |
if (!$a && $channel == 'pecl.php.net') { |
return true; |
} |
if (!$a && $channel == 'doc.php.net') { |
return true; |
} |
return $a; |
} |
/** |
* Determine whether a mirror exists within the deafult channel in the registry |
* |
* @param string Channel name |
* @param string Mirror name |
* |
* @return boolean |
*/ |
function _mirrorExists($channel, $mirror) |
{ |
$data = $this->_channelInfo($channel); |
if (!isset($data['servers']['mirror'])) { |
return false; |
} |
foreach ($data['servers']['mirror'] as $m) { |
if ($m['attribs']['host'] == $mirror) { |
return true; |
} |
} |
return false; |
} |
/** |
* @param PEAR_ChannelFile Channel object |
* @param donotuse |
* @param string Last-Modified HTTP tag from remote request |
* @return boolean|PEAR_Error True on creation, false if it already exists |
*/ |
function _addChannel($channel, $update = false, $lastmodified = false) |
{ |
if (!is_a($channel, 'PEAR_ChannelFile')) { |
return false; |
} |
if (!$channel->validate()) { |
return false; |
} |
if (file_exists($this->_channelFileName($channel->getName()))) { |
if (!$update) { |
return false; |
} |
$checker = $this->_getChannel($channel->getName()); |
if (PEAR::isError($checker)) { |
return $checker; |
} |
if ($channel->getAlias() != $checker->getAlias()) { |
if (file_exists($this->_getChannelAliasFileName($checker->getAlias()))) { |
@unlink($this->_getChannelAliasFileName($checker->getAlias())); |
} |
} |
} else { |
if ($update && !in_array($channel->getName(), array('pear.php.net', 'pecl.php.net', 'doc.php.net'))) { |
return false; |
} |
} |
$ret = $this->_assertChannelDir(); |
if (PEAR::isError($ret)) { |
return $ret; |
} |
$ret = $this->_assertChannelStateDir($channel->getName()); |
if (PEAR::isError($ret)) { |
return $ret; |
} |
if ($channel->getAlias() != $channel->getName()) { |
if (file_exists($this->_getChannelAliasFileName($channel->getAlias())) && |
$this->_getChannelFromAlias($channel->getAlias()) != $channel->getName()) { |
$channel->setAlias($channel->getName()); |
} |
if (!$this->hasWriteAccess()) { |
return false; |
} |
$fp = @fopen($this->_getChannelAliasFileName($channel->getAlias()), 'w'); |
if (!$fp) { |
return false; |
} |
fwrite($fp, $channel->getName()); |
fclose($fp); |
} |
if (!$this->hasWriteAccess()) { |
return false; |
} |
$fp = @fopen($this->_channelFileName($channel->getName()), 'wb'); |
if (!$fp) { |
return false; |
} |
$info = $channel->toArray(); |
if ($lastmodified) { |
$info['_lastmodified'] = $lastmodified; |
} else { |
$info['_lastmodified'] = date('r'); |
} |
fwrite($fp, serialize($info)); |
fclose($fp); |
return true; |
} |
/** |
* Deletion fails if there are any packages installed from the channel |
* @param string|PEAR_ChannelFile channel name |
* @return boolean|PEAR_Error True on deletion, false if it doesn't exist |
*/ |
function _deleteChannel($channel) |
{ |
if (!is_string($channel)) { |
if (!is_a($channel, 'PEAR_ChannelFile')) { |
return false; |
} |
if (!$channel->validate()) { |
return false; |
} |
$channel = $channel->getName(); |
} |
if ($this->_getChannelFromAlias($channel) == '__uri') { |
return false; |
} |
if ($this->_getChannelFromAlias($channel) == 'pecl.php.net') { |
return false; |
} |
if ($this->_getChannelFromAlias($channel) == 'doc.php.net') { |
return false; |
} |
if (!$this->_channelExists($channel)) { |
return false; |
} |
if (!$channel || $this->_getChannelFromAlias($channel) == 'pear.php.net') { |
return false; |
} |
$channel = $this->_getChannelFromAlias($channel); |
if ($channel == 'pear.php.net') { |
return false; |
} |
$test = $this->_listChannelPackages($channel); |
if (count($test)) { |
return false; |
} |
$test = @rmdir($this->_channelDirectoryName($channel)); |
if (!$test) { |
return false; |
} |
$file = $this->_getChannelAliasFileName($this->_getAlias($channel)); |
if (file_exists($file)) { |
$test = @unlink($file); |
if (!$test) { |
return false; |
} |
} |
$file = $this->_channelFileName($channel); |
$ret = true; |
if (file_exists($file)) { |
$ret = @unlink($file); |
} |
return $ret; |
} |
/** |
* Determine whether a channel exists in the registry |
* @param string Channel Alias |
* @return boolean |
*/ |
function _isChannelAlias($alias) |
{ |
return file_exists($this->_getChannelAliasFileName($alias)); |
} |
/** |
* @param string|null |
* @param string|null |
* @param string|null |
* @return array|null |
* @access private |
*/ |
function _packageInfo($package = null, $key = null, $channel = 'pear.php.net') |
{ |
if ($package === null) { |
if ($channel === null) { |
$channels = $this->_listChannels(); |
$ret = array(); |
foreach ($channels as $channel) { |
$channel = strtolower($channel); |
$ret[$channel] = array(); |
$packages = $this->_listPackages($channel); |
foreach ($packages as $package) { |
$ret[$channel][] = $this->_packageInfo($package, null, $channel); |
} |
} |
return $ret; |
} |
$ps = $this->_listPackages($channel); |
if (!count($ps)) { |
return array(); |
} |
return array_map(array(&$this, '_packageInfo'), |
$ps, array_fill(0, count($ps), null), |
array_fill(0, count($ps), $channel)); |
} |
$fp = $this->_openPackageFile($package, 'r', $channel); |
if ($fp === null) { |
return null; |
} |
clearstatcache(); |
$this->_closePackageFile($fp); |
$data = file_get_contents($this->_packageFileName($package, $channel)); |
$data = unserialize($data); |
if ($key === null) { |
return $data; |
} |
// compatibility for package.xml version 2.0 |
if (isset($data['old'][$key])) { |
return $data['old'][$key]; |
} |
if (isset($data[$key])) { |
return $data[$key]; |
} |
return null; |
} |
/** |
* @param string Channel name |
* @param bool whether to strictly retrieve info of channels, not just aliases |
* @return array|null |
*/ |
function _channelInfo($channel, $noaliases = false) |
{ |
if (!$this->_channelExists($channel, $noaliases)) { |
return null; |
} |
$fp = $this->_openChannelFile($channel, 'r'); |
if ($fp === null) { |
return null; |
} |
clearstatcache(); |
$this->_closeChannelFile($fp); |
$data = file_get_contents($this->_channelFileName($channel)); |
$data = unserialize($data); |
return $data; |
} |
function _listChannels() |
{ |
$channellist = array(); |
if (!file_exists($this->channelsdir) || !is_dir($this->channelsdir)) { |
return array('pear.php.net', 'pecl.php.net', 'doc.php.net', '__uri'); |
} |
$dp = opendir($this->channelsdir); |
while ($ent = readdir($dp)) { |
if ($ent{0} == '.' || substr($ent, -4) != '.reg') { |
continue; |
} |
if ($ent == '__uri.reg') { |
$channellist[] = '__uri'; |
continue; |
} |
$channellist[] = str_replace('_', '/', substr($ent, 0, -4)); |
} |
closedir($dp); |
if (!in_array('pear.php.net', $channellist)) { |
$channellist[] = 'pear.php.net'; |
} |
if (!in_array('pecl.php.net', $channellist)) { |
$channellist[] = 'pecl.php.net'; |
} |
if (!in_array('doc.php.net', $channellist)) { |
$channellist[] = 'doc.php.net'; |
} |
if (!in_array('__uri', $channellist)) { |
$channellist[] = '__uri'; |
} |
natsort($channellist); |
return $channellist; |
} |
function _listPackages($channel = false) |
{ |
if ($channel && $this->_getChannelFromAlias($channel) != 'pear.php.net') { |
return $this->_listChannelPackages($channel); |
} |
if (!file_exists($this->statedir) || !is_dir($this->statedir)) { |
return array(); |
} |
$pkglist = array(); |
$dp = opendir($this->statedir); |
if (!$dp) { |
return $pkglist; |
} |
while ($ent = readdir($dp)) { |
if ($ent{0} == '.' || substr($ent, -4) != '.reg') { |
continue; |
} |
$pkglist[] = substr($ent, 0, -4); |
} |
closedir($dp); |
return $pkglist; |
} |
function _listChannelPackages($channel) |
{ |
$pkglist = array(); |
if (!file_exists($this->_channelDirectoryName($channel)) || |
!is_dir($this->_channelDirectoryName($channel))) { |
return array(); |
} |
$dp = opendir($this->_channelDirectoryName($channel)); |
if (!$dp) { |
return $pkglist; |
} |
while ($ent = readdir($dp)) { |
if ($ent{0} == '.' || substr($ent, -4) != '.reg') { |
continue; |
} |
$pkglist[] = substr($ent, 0, -4); |
} |
closedir($dp); |
return $pkglist; |
} |
function _listAllPackages() |
{ |
$ret = array(); |
foreach ($this->_listChannels() as $channel) { |
$ret[$channel] = $this->_listPackages($channel); |
} |
return $ret; |
} |
/** |
* Add an installed package to the registry |
* @param string package name |
* @param array package info (parsed by PEAR_Common::infoFrom*() methods) |
* @return bool success of saving |
* @access private |
*/ |
function _addPackage($package, $info) |
{ |
if ($this->_packageExists($package)) { |
return false; |
} |
$fp = $this->_openPackageFile($package, 'wb'); |
if ($fp === null) { |
return false; |
} |
$info['_lastmodified'] = time(); |
fwrite($fp, serialize($info)); |
$this->_closePackageFile($fp); |
if (isset($info['filelist'])) { |
$this->_rebuildFileMap(); |
} |
return true; |
} |
/** |
* @param PEAR_PackageFile_v1|PEAR_PackageFile_v2 |
* @return bool |
* @access private |
*/ |
function _addPackage2($info) |
{ |
if (!is_a($info, 'PEAR_PackageFile_v1') && !is_a($info, 'PEAR_PackageFile_v2')) { |
return false; |
} |
if (!$info->validate()) { |
if (class_exists('PEAR_Common')) { |
$ui = PEAR_Frontend::singleton(); |
if ($ui) { |
foreach ($info->getValidationWarnings() as $err) { |
$ui->log($err['message'], true); |
} |
} |
} |
return false; |
} |
$channel = $info->getChannel(); |
$package = $info->getPackage(); |
$save = $info; |
if ($this->_packageExists($package, $channel)) { |
return false; |
} |
if (!$this->_channelExists($channel, true)) { |
return false; |
} |
$info = $info->toArray(true); |
if (!$info) { |
return false; |
} |
$fp = $this->_openPackageFile($package, 'wb', $channel); |
if ($fp === null) { |
return false; |
} |
$info['_lastmodified'] = time(); |
fwrite($fp, serialize($info)); |
$this->_closePackageFile($fp); |
$this->_rebuildFileMap(); |
return true; |
} |
/** |
* @param string Package name |
* @param array parsed package.xml 1.0 |
* @param bool this parameter is only here for BC. Don't use it. |
* @access private |
*/ |
function _updatePackage($package, $info, $merge = true) |
{ |
$oldinfo = $this->_packageInfo($package); |
if (empty($oldinfo)) { |
return false; |
} |
$fp = $this->_openPackageFile($package, 'w'); |
if ($fp === null) { |
return false; |
} |
if (is_object($info)) { |
$info = $info->toArray(); |
} |
$info['_lastmodified'] = time(); |
$newinfo = $info; |
if ($merge) { |
$info = array_merge($oldinfo, $info); |
} else { |
$diff = $info; |
} |
fwrite($fp, serialize($info)); |
$this->_closePackageFile($fp); |
if (isset($newinfo['filelist'])) { |
$this->_rebuildFileMap(); |
} |
return true; |
} |
/** |
* @param PEAR_PackageFile_v1|PEAR_PackageFile_v2 |
* @return bool |
* @access private |
*/ |
function _updatePackage2($info) |
{ |
if (!$this->_packageExists($info->getPackage(), $info->getChannel())) { |
return false; |
} |
$fp = $this->_openPackageFile($info->getPackage(), 'w', $info->getChannel()); |
if ($fp === null) { |
return false; |
} |
$save = $info; |
$info = $save->getArray(true); |
$info['_lastmodified'] = time(); |
fwrite($fp, serialize($info)); |
$this->_closePackageFile($fp); |
$this->_rebuildFileMap(); |
return true; |
} |
/** |
* @param string Package name |
* @param string Channel name |
* @return PEAR_PackageFile_v1|PEAR_PackageFile_v2|null |
* @access private |
*/ |
function &_getPackage($package, $channel = 'pear.php.net') |
{ |
$info = $this->_packageInfo($package, null, $channel); |
if ($info === null) { |
return $info; |
} |
$a = $this->_config; |
if (!$a) { |
$this->_config = new PEAR_Config; |
$this->_config->set('php_dir', $this->statedir); |
} |
if (!class_exists('PEAR_PackageFile')) { |
require_once 'PEAR/PackageFile.php'; |
} |
$pkg = new PEAR_PackageFile($this->_config); |
$pf = &$pkg->fromArray($info); |
return $pf; |
} |
/** |
* @param string channel name |
* @param bool whether to strictly retrieve channel names |
* @return PEAR_ChannelFile|PEAR_Error |
* @access private |
*/ |
function &_getChannel($channel, $noaliases = false) |
{ |
$ch = false; |
if ($this->_channelExists($channel, $noaliases)) { |
$chinfo = $this->_channelInfo($channel, $noaliases); |
if ($chinfo) { |
if (!class_exists('PEAR_ChannelFile')) { |
require_once 'PEAR/ChannelFile.php'; |
} |
$ch = &PEAR_ChannelFile::fromArrayWithErrors($chinfo); |
} |
} |
if ($ch) { |
if ($ch->validate()) { |
return $ch; |
} |
foreach ($ch->getErrors(true) as $err) { |
$message = $err['message'] . "\n"; |
} |
$ch = PEAR::raiseError($message); |
return $ch; |
} |
if ($this->_getChannelFromAlias($channel) == 'pear.php.net') { |
// the registry is not properly set up, so use defaults |
if (!class_exists('PEAR_ChannelFile')) { |
require_once 'PEAR/ChannelFile.php'; |
} |
$pear_channel = new PEAR_ChannelFile; |
$pear_channel->setServer('pear.php.net'); |
$pear_channel->setAlias('pear'); |
$pear_channel->setSummary('PHP Extension and Application Repository'); |
$pear_channel->setDefaultPEARProtocols(); |
$pear_channel->setBaseURL('REST1.0', 'http://pear.php.net/rest/'); |
$pear_channel->setBaseURL('REST1.1', 'http://pear.php.net/rest/'); |
$pear_channel->setBaseURL('REST1.3', 'http://pear.php.net/rest/'); |
return $pear_channel; |
} |
if ($this->_getChannelFromAlias($channel) == 'pecl.php.net') { |
// the registry is not properly set up, so use defaults |
if (!class_exists('PEAR_ChannelFile')) { |
require_once 'PEAR/ChannelFile.php'; |
} |
$pear_channel = new PEAR_ChannelFile; |
$pear_channel->setServer('pecl.php.net'); |
$pear_channel->setAlias('pecl'); |
$pear_channel->setSummary('PHP Extension Community Library'); |
$pear_channel->setDefaultPEARProtocols(); |
$pear_channel->setBaseURL('REST1.0', 'http://pecl.php.net/rest/'); |
$pear_channel->setBaseURL('REST1.1', 'http://pecl.php.net/rest/'); |
$pear_channel->setValidationPackage('PEAR_Validator_PECL', '1.0'); |
return $pear_channel; |
} |
if ($this->_getChannelFromAlias($channel) == 'doc.php.net') { |
// the registry is not properly set up, so use defaults |
if (!class_exists('PEAR_ChannelFile')) { |
require_once 'PEAR/ChannelFile.php'; |
} |
$doc_channel = new PEAR_ChannelFile; |
$doc_channel->setServer('doc.php.net'); |
$doc_channel->setAlias('phpdocs'); |
$doc_channel->setSummary('PHP Documentation Team'); |
$doc_channel->setDefaultPEARProtocols(); |
$doc_channel->setBaseURL('REST1.0', 'http://doc.php.net/rest/'); |
$doc_channel->setBaseURL('REST1.1', 'http://doc.php.net/rest/'); |
$doc_channel->setBaseURL('REST1.3', 'http://doc.php.net/rest/'); |
return $doc_channel; |
} |
if ($this->_getChannelFromAlias($channel) == '__uri') { |
// the registry is not properly set up, so use defaults |
if (!class_exists('PEAR_ChannelFile')) { |
require_once 'PEAR/ChannelFile.php'; |
} |
$private = new PEAR_ChannelFile; |
$private->setName('__uri'); |
$private->setDefaultPEARProtocols(); |
$private->setBaseURL('REST1.0', '****'); |
$private->setSummary('Pseudo-channel for static packages'); |
return $private; |
} |
return $ch; |
} |
/** |
* @param string Package name |
* @param string Channel name |
* @return bool |
*/ |
function packageExists($package, $channel = 'pear.php.net') |
{ |
if (PEAR::isError($e = $this->_lock(LOCK_SH))) { |
return $e; |
} |
$ret = $this->_packageExists($package, $channel); |
$this->_unlock(); |
return $ret; |
} |
// }}} |
// {{{ channelExists() |
/** |
* @param string channel name |
* @param bool if true, then aliases will be ignored |
* @return bool |
*/ |
function channelExists($channel, $noaliases = false) |
{ |
if (PEAR::isError($e = $this->_lock(LOCK_SH))) { |
return $e; |
} |
$ret = $this->_channelExists($channel, $noaliases); |
$this->_unlock(); |
return $ret; |
} |
// }}} |
/** |
* @param string channel name mirror is in |
* @param string mirror name |
* |
* @return bool |
*/ |
function mirrorExists($channel, $mirror) |
{ |
if (PEAR::isError($e = $this->_lock(LOCK_SH))) { |
return $e; |
} |
$ret = $this->_mirrorExists($channel, $mirror); |
$this->_unlock(); |
return $ret; |
} |
// {{{ isAlias() |
/** |
* Determines whether the parameter is an alias of a channel |
* @param string |
* @return bool |
*/ |
function isAlias($alias) |
{ |
if (PEAR::isError($e = $this->_lock(LOCK_SH))) { |
return $e; |
} |
$ret = $this->_isChannelAlias($alias); |
$this->_unlock(); |
return $ret; |
} |
// }}} |
// {{{ packageInfo() |
/** |
* @param string|null |
* @param string|null |
* @param string |
* @return array|null |
*/ |
function packageInfo($package = null, $key = null, $channel = 'pear.php.net') |
{ |
if (PEAR::isError($e = $this->_lock(LOCK_SH))) { |
return $e; |
} |
$ret = $this->_packageInfo($package, $key, $channel); |
$this->_unlock(); |
return $ret; |
} |
// }}} |
// {{{ channelInfo() |
/** |
* Retrieve a raw array of channel data. |
* |
* Do not use this, instead use {@link getChannel()} for normal |
* operations. Array structure is undefined in this method |
* @param string channel name |
* @param bool whether to strictly retrieve information only on non-aliases |
* @return array|null|PEAR_Error |
*/ |
function channelInfo($channel = null, $noaliases = false) |
{ |
if (PEAR::isError($e = $this->_lock(LOCK_SH))) { |
return $e; |
} |
$ret = $this->_channelInfo($channel, $noaliases); |
$this->_unlock(); |
return $ret; |
} |
// }}} |
/** |
* @param string |
*/ |
function channelName($channel) |
{ |
if (PEAR::isError($e = $this->_lock(LOCK_SH))) { |
return $e; |
} |
$ret = $this->_getChannelFromAlias($channel); |
$this->_unlock(); |
return $ret; |
} |
/** |
* @param string |
*/ |
function channelAlias($channel) |
{ |
if (PEAR::isError($e = $this->_lock(LOCK_SH))) { |
return $e; |
} |
$ret = $this->_getAlias($channel); |
$this->_unlock(); |
return $ret; |
} |
// {{{ listPackages() |
function listPackages($channel = false) |
{ |
if (PEAR::isError($e = $this->_lock(LOCK_SH))) { |
return $e; |
} |
$ret = $this->_listPackages($channel); |
$this->_unlock(); |
return $ret; |
} |
// }}} |
// {{{ listAllPackages() |
function listAllPackages() |
{ |
if (PEAR::isError($e = $this->_lock(LOCK_SH))) { |
return $e; |
} |
$ret = $this->_listAllPackages(); |
$this->_unlock(); |
return $ret; |
} |
// }}} |
// {{{ listChannel() |
function listChannels() |
{ |
if (PEAR::isError($e = $this->_lock(LOCK_SH))) { |
return $e; |
} |
$ret = $this->_listChannels(); |
$this->_unlock(); |
return $ret; |
} |
// }}} |
// {{{ addPackage() |
/** |
* Add an installed package to the registry |
* @param string|PEAR_PackageFile_v1|PEAR_PackageFile_v2 package name or object |
* that will be passed to {@link addPackage2()} |
* @param array package info (parsed by PEAR_Common::infoFrom*() methods) |
* @return bool success of saving |
*/ |
function addPackage($package, $info) |
{ |
if (is_object($info)) { |
return $this->addPackage2($info); |
} |
if (PEAR::isError($e = $this->_lock(LOCK_EX))) { |
return $e; |
} |
$ret = $this->_addPackage($package, $info); |
$this->_unlock(); |
if ($ret) { |
if (!class_exists('PEAR_PackageFile_v1')) { |
require_once 'PEAR/PackageFile/v1.php'; |
} |
$pf = new PEAR_PackageFile_v1; |
$pf->setConfig($this->_config); |
$pf->fromArray($info); |
$this->_dependencyDB->uninstallPackage($pf); |
$this->_dependencyDB->installPackage($pf); |
} |
return $ret; |
} |
// }}} |
// {{{ addPackage2() |
function addPackage2($info) |
{ |
if (!is_object($info)) { |
return $this->addPackage($info['package'], $info); |
} |
if (PEAR::isError($e = $this->_lock(LOCK_EX))) { |
return $e; |
} |
$ret = $this->_addPackage2($info); |
$this->_unlock(); |
if ($ret) { |
$this->_dependencyDB->uninstallPackage($info); |
$this->_dependencyDB->installPackage($info); |
} |
return $ret; |
} |
// }}} |
// {{{ updateChannel() |
/** |
* For future expandibility purposes, separate this |
* @param PEAR_ChannelFile |
*/ |
function updateChannel($channel, $lastmodified = null) |
{ |
if ($channel->getName() == '__uri') { |
return false; |
} |
return $this->addChannel($channel, $lastmodified, true); |
} |
// }}} |
// {{{ deleteChannel() |
/** |
* Deletion fails if there are any packages installed from the channel |
* @param string|PEAR_ChannelFile channel name |
* @return boolean|PEAR_Error True on deletion, false if it doesn't exist |
*/ |
function deleteChannel($channel) |
{ |
if (PEAR::isError($e = $this->_lock(LOCK_EX))) { |
return $e; |
} |
$ret = $this->_deleteChannel($channel); |
$this->_unlock(); |
if ($ret && is_a($this->_config, 'PEAR_Config')) { |
$this->_config->setChannels($this->listChannels()); |
} |
return $ret; |
} |
// }}} |
// {{{ addChannel() |
/** |
* @param PEAR_ChannelFile Channel object |
* @param string Last-Modified header from HTTP for caching |
* @return boolean|PEAR_Error True on creation, false if it already exists |
*/ |
function addChannel($channel, $lastmodified = false, $update = false) |
{ |
if (!is_a($channel, 'PEAR_ChannelFile') || !$channel->validate()) { |
return false; |
} |
if (PEAR::isError($e = $this->_lock(LOCK_EX))) { |
return $e; |
} |
$ret = $this->_addChannel($channel, $update, $lastmodified); |
$this->_unlock(); |
if (!$update && $ret && is_a($this->_config, 'PEAR_Config')) { |
$this->_config->setChannels($this->listChannels()); |
} |
return $ret; |
} |
// }}} |
// {{{ deletePackage() |
function deletePackage($package, $channel = 'pear.php.net') |
{ |
if (PEAR::isError($e = $this->_lock(LOCK_EX))) { |
return $e; |
} |
$file = $this->_packageFileName($package, $channel); |
$ret = file_exists($file) ? @unlink($file) : false; |
$this->_rebuildFileMap(); |
$this->_unlock(); |
$p = array('channel' => $channel, 'package' => $package); |
$this->_dependencyDB->uninstallPackage($p); |
return $ret; |
} |
// }}} |
// {{{ updatePackage() |
function updatePackage($package, $info, $merge = true) |
{ |
if (is_object($info)) { |
return $this->updatePackage2($info, $merge); |
} |
if (PEAR::isError($e = $this->_lock(LOCK_EX))) { |
return $e; |
} |
$ret = $this->_updatePackage($package, $info, $merge); |
$this->_unlock(); |
if ($ret) { |
if (!class_exists('PEAR_PackageFile_v1')) { |
require_once 'PEAR/PackageFile/v1.php'; |
} |
$pf = new PEAR_PackageFile_v1; |
$pf->setConfig($this->_config); |
$pf->fromArray($this->packageInfo($package)); |
$this->_dependencyDB->uninstallPackage($pf); |
$this->_dependencyDB->installPackage($pf); |
} |
return $ret; |
} |
// }}} |
// {{{ updatePackage2() |
function updatePackage2($info) |
{ |
if (!is_object($info)) { |
return $this->updatePackage($info['package'], $info, $merge); |
} |
if (!$info->validate(PEAR_VALIDATE_DOWNLOADING)) { |
return false; |
} |
if (PEAR::isError($e = $this->_lock(LOCK_EX))) { |
return $e; |
} |
$ret = $this->_updatePackage2($info); |
$this->_unlock(); |
if ($ret) { |
$this->_dependencyDB->uninstallPackage($info); |
$this->_dependencyDB->installPackage($info); |
} |
return $ret; |
} |
// }}} |
// {{{ getChannel() |
/** |
* @param string channel name |
* @param bool whether to strictly return raw channels (no aliases) |
* @return PEAR_ChannelFile|PEAR_Error |
*/ |
function getChannel($channel, $noaliases = false) |
{ |
if (PEAR::isError($e = $this->_lock(LOCK_SH))) { |
return $e; |
} |
$ret = $this->_getChannel($channel, $noaliases); |
$this->_unlock(); |
if (!$ret) { |
return PEAR::raiseError('Unknown channel: ' . $channel); |
} |
return $ret; |
} |
// }}} |
// {{{ getPackage() |
/** |
* @param string package name |
* @param string channel name |
* @return PEAR_PackageFile_v1|PEAR_PackageFile_v2|null |
*/ |
function &getPackage($package, $channel = 'pear.php.net') |
{ |
if (PEAR::isError($e = $this->_lock(LOCK_SH))) { |
return $e; |
} |
$pf = &$this->_getPackage($package, $channel); |
$this->_unlock(); |
return $pf; |
} |
// }}} |
/** |
* Get PEAR_PackageFile_v[1/2] objects representing the contents of |
* a dependency group that are installed. |
* |
* This is used at uninstall-time |
* @param array |
* @return array|false |
*/ |
function getInstalledGroup($group) |
{ |
$ret = array(); |
if (isset($group['package'])) { |
if (!isset($group['package'][0])) { |
$group['package'] = array($group['package']); |
} |
foreach ($group['package'] as $package) { |
$depchannel = isset($package['channel']) ? $package['channel'] : '__uri'; |
$p = &$this->getPackage($package['name'], $depchannel); |
if ($p) { |
$save = &$p; |
$ret[] = &$save; |
} |
} |
} |
if (isset($group['subpackage'])) { |
if (!isset($group['subpackage'][0])) { |
$group['subpackage'] = array($group['subpackage']); |
} |
foreach ($group['subpackage'] as $package) { |
$depchannel = isset($package['channel']) ? $package['channel'] : '__uri'; |
$p = &$this->getPackage($package['name'], $depchannel); |
if ($p) { |
$save = &$p; |
$ret[] = &$save; |
} |
} |
} |
if (!count($ret)) { |
return false; |
} |
return $ret; |
} |
// {{{ getChannelValidator() |
/** |
* @param string channel name |
* @return PEAR_Validate|false |
*/ |
function &getChannelValidator($channel) |
{ |
$chan = $this->getChannel($channel); |
if (PEAR::isError($chan)) { |
return $chan; |
} |
$val = $chan->getValidationObject(); |
return $val; |
} |
// }}} |
// {{{ getChannels() |
/** |
* @param string channel name |
* @return array an array of PEAR_ChannelFile objects representing every installed channel |
*/ |
function &getChannels() |
{ |
$ret = array(); |
if (PEAR::isError($e = $this->_lock(LOCK_SH))) { |
return $e; |
} |
foreach ($this->_listChannels() as $channel) { |
$e = &$this->_getChannel($channel); |
if (!$e || PEAR::isError($e)) { |
continue; |
} |
$ret[] = $e; |
} |
$this->_unlock(); |
return $ret; |
} |
// }}} |
// {{{ checkFileMap() |
/** |
* Test whether a file or set of files belongs to a package. |
* |
* If an array is passed in |
* @param string|array file path, absolute or relative to the pear |
* install dir |
* @param string|array name of PEAR package or array('package' => name, 'channel' => |
* channel) of a package that will be ignored |
* @param string API version - 1.1 will exclude any files belonging to a package |
* @param array private recursion variable |
* @return array|false which package and channel the file belongs to, or an empty |
* string if the file does not belong to an installed package, |
* or belongs to the second parameter's package |
*/ |
function checkFileMap($path, $package = false, $api = '1.0', $attrs = false) |
{ |
if (is_array($path)) { |
static $notempty; |
if (empty($notempty)) { |
if (!class_exists('PEAR_Installer_Role')) { |
require_once 'PEAR/Installer/Role.php'; |
} |
$notempty = create_function('$a','return !empty($a);'); |
} |
$package = is_array($package) ? array(strtolower($package[0]), strtolower($package[1])) |
: strtolower($package); |
$pkgs = array(); |
foreach ($path as $name => $attrs) { |
if (is_array($attrs)) { |
if (isset($attrs['install-as'])) { |
$name = $attrs['install-as']; |
} |
if (!in_array($attrs['role'], PEAR_Installer_Role::getInstallableRoles())) { |
// these are not installed |
continue; |
} |
if (!in_array($attrs['role'], PEAR_Installer_Role::getBaseinstallRoles())) { |
$attrs['baseinstalldir'] = is_array($package) ? $package[1] : $package; |
} |
if (isset($attrs['baseinstalldir'])) { |
$name = $attrs['baseinstalldir'] . DIRECTORY_SEPARATOR . $name; |
} |
} |
$pkgs[$name] = $this->checkFileMap($name, $package, $api, $attrs); |
if (PEAR::isError($pkgs[$name])) { |
return $pkgs[$name]; |
} |
} |
return array_filter($pkgs, $notempty); |
} |
if (empty($this->filemap_cache)) { |
if (PEAR::isError($e = $this->_lock(LOCK_SH))) { |
return $e; |
} |
$err = $this->_readFileMap(); |
$this->_unlock(); |
if (PEAR::isError($err)) { |
return $err; |
} |
} |
if (!$attrs) { |
$attrs = array('role' => 'php'); // any old call would be for PHP role only |
} |
if (isset($this->filemap_cache[$attrs['role']][$path])) { |
if ($api >= '1.1' && $this->filemap_cache[$attrs['role']][$path] == $package) { |
return false; |
} |
return $this->filemap_cache[$attrs['role']][$path]; |
} |
$l = strlen($this->install_dir); |
if (substr($path, 0, $l) == $this->install_dir) { |
$path = preg_replace('!^'.DIRECTORY_SEPARATOR.'+!', '', substr($path, $l)); |
} |
if (isset($this->filemap_cache[$attrs['role']][$path])) { |
if ($api >= '1.1' && $this->filemap_cache[$attrs['role']][$path] == $package) { |
return false; |
} |
return $this->filemap_cache[$attrs['role']][$path]; |
} |
return false; |
} |
// }}} |
// {{{ flush() |
/** |
* Force a reload of the filemap |
* @since 1.5.0RC3 |
*/ |
function flushFileMap() |
{ |
$this->filemap_cache = null; |
clearstatcache(); // ensure that the next read gets the full, current filemap |
} |
// }}} |
// {{{ apiVersion() |
/** |
* Get the expected API version. Channels API is version 1.1, as it is backwards |
* compatible with 1.0 |
* @return string |
*/ |
function apiVersion() |
{ |
return '1.1'; |
} |
// }}} |
/** |
* Parse a package name, or validate a parsed package name array |
* @param string|array pass in an array of format |
* array( |
* 'package' => 'pname', |
* ['channel' => 'channame',] |
* ['version' => 'version',] |
* ['state' => 'state',] |
* ['group' => 'groupname']) |
* or a string of format |
* [channel://][channame/]pname[-version|-state][/group=groupname] |
* @return array|PEAR_Error |
*/ |
function parsePackageName($param, $defaultchannel = 'pear.php.net') |
{ |
$saveparam = $param; |
if (is_array($param)) { |
// convert to string for error messages |
$saveparam = $this->parsedPackageNameToString($param); |
// process the array |
if (!isset($param['package'])) { |
return PEAR::raiseError('parsePackageName(): array $param ' . |
'must contain a valid package name in index "param"', |
'package', null, null, $param); |
} |
if (!isset($param['uri'])) { |
if (!isset($param['channel'])) { |
$param['channel'] = $defaultchannel; |
} |
} else { |
$param['channel'] = '__uri'; |
} |
} else { |
$components = @parse_url((string) $param); |
if (isset($components['scheme'])) { |
if ($components['scheme'] == 'http') { |
// uri package |
$param = array('uri' => $param, 'channel' => '__uri'); |
} elseif($components['scheme'] != 'channel') { |
return PEAR::raiseError('parsePackageName(): only channel:// uris may ' . |
'be downloaded, not "' . $param . '"', 'invalid', null, null, $param); |
} |
} |
if (!isset($components['path'])) { |
return PEAR::raiseError('parsePackageName(): array $param ' . |
'must contain a valid package name in "' . $param . '"', |
'package', null, null, $param); |
} |
if (isset($components['host'])) { |
// remove the leading "/" |
$components['path'] = substr($components['path'], 1); |
} |
if (!isset($components['scheme'])) { |
if (strpos($components['path'], '/') !== false) { |
if ($components['path']{0} == '/') { |
return PEAR::raiseError('parsePackageName(): this is not ' . |
'a package name, it begins with "/" in "' . $param . '"', |
'invalid', null, null, $param); |
} |
$parts = explode('/', $components['path']); |
$components['host'] = array_shift($parts); |
if (count($parts) > 1) { |
$components['path'] = array_pop($parts); |
$components['host'] .= '/' . implode('/', $parts); |
} else { |
$components['path'] = implode('/', $parts); |
} |
} else { |
$components['host'] = $defaultchannel; |
} |
} else { |
if (strpos($components['path'], '/')) { |
$parts = explode('/', $components['path']); |
$components['path'] = array_pop($parts); |
$components['host'] .= '/' . implode('/', $parts); |
} |
} |
if (is_array($param)) { |
$param['package'] = $components['path']; |
} else { |
$param = array( |
'package' => $components['path'] |
); |
if (isset($components['host'])) { |
$param['channel'] = $components['host']; |
} |
} |
if (isset($components['fragment'])) { |
$param['group'] = $components['fragment']; |
} |
if (isset($components['user'])) { |
$param['user'] = $components['user']; |
} |
if (isset($components['pass'])) { |
$param['pass'] = $components['pass']; |
} |
if (isset($components['query'])) { |
parse_str($components['query'], $param['opts']); |
} |
// check for extension |
$pathinfo = pathinfo($param['package']); |
if (isset($pathinfo['extension']) && |
in_array(strtolower($pathinfo['extension']), array('tgz', 'tar'))) { |
$param['extension'] = $pathinfo['extension']; |
$param['package'] = substr($pathinfo['basename'], 0, |
strlen($pathinfo['basename']) - 4); |
} |
// check for version |
if (strpos($param['package'], '-')) { |
$test = explode('-', $param['package']); |
if (count($test) != 2) { |
return PEAR::raiseError('parsePackageName(): only one version/state ' . |
'delimiter "-" is allowed in "' . $saveparam . '"', |
'version', null, null, $param); |
} |
list($param['package'], $param['version']) = $test; |
} |
} |
// validation |
$info = $this->channelExists($param['channel']); |
if (PEAR::isError($info)) { |
return $info; |
} |
if (!$info) { |
return PEAR::raiseError('unknown channel "' . $param['channel'] . |
'" in "' . $saveparam . '"', 'channel', null, null, $param); |
} |
$chan = $this->getChannel($param['channel']); |
if (PEAR::isError($chan)) { |
return $chan; |
} |
if (!$chan) { |
return PEAR::raiseError("Exception: corrupt registry, could not " . |
"retrieve channel " . $param['channel'] . " information", |
'registry', null, null, $param); |
} |
$param['channel'] = $chan->getName(); |
$validate = $chan->getValidationObject(); |
$vpackage = $chan->getValidationPackage(); |
// validate package name |
if (!$validate->validPackageName($param['package'], $vpackage['_content'])) { |
return PEAR::raiseError('parsePackageName(): invalid package name "' . |
$param['package'] . '" in "' . $saveparam . '"', |
'package', null, null, $param); |
} |
if (isset($param['group'])) { |
if (!PEAR_Validate::validGroupName($param['group'])) { |
return PEAR::raiseError('parsePackageName(): dependency group "' . $param['group'] . |
'" is not a valid group name in "' . $saveparam . '"', 'group', null, null, |
$param); |
} |
} |
if (isset($param['state'])) { |
if (!in_array(strtolower($param['state']), $validate->getValidStates())) { |
return PEAR::raiseError('parsePackageName(): state "' . $param['state'] |
. '" is not a valid state in "' . $saveparam . '"', |
'state', null, null, $param); |
} |
} |
if (isset($param['version'])) { |
if (isset($param['state'])) { |
return PEAR::raiseError('parsePackageName(): cannot contain both ' . |
'a version and a stability (state) in "' . $saveparam . '"', |
'version/state', null, null, $param); |
} |
// check whether version is actually a state |
if (in_array(strtolower($param['version']), $validate->getValidStates())) { |
$param['state'] = strtolower($param['version']); |
unset($param['version']); |
} else { |
if (!$validate->validVersion($param['version'])) { |
return PEAR::raiseError('parsePackageName(): "' . $param['version'] . |
'" is neither a valid version nor a valid state in "' . |
$saveparam . '"', 'version/state', null, null, $param); |
} |
} |
} |
return $param; |
} |
/** |
* @param array |
* @return string |
*/ |
function parsedPackageNameToString($parsed, $brief = false) |
{ |
if (is_string($parsed)) { |
return $parsed; |
} |
if (is_object($parsed)) { |
$p = $parsed; |
$parsed = array( |
'package' => $p->getPackage(), |
'channel' => $p->getChannel(), |
'version' => $p->getVersion(), |
); |
} |
if (isset($parsed['uri'])) { |
return $parsed['uri']; |
} |
if ($brief) { |
if ($channel = $this->channelAlias($parsed['channel'])) { |
return $channel . '/' . $parsed['package']; |
} |
} |
$upass = ''; |
if (isset($parsed['user'])) { |
$upass = $parsed['user']; |
if (isset($parsed['pass'])) { |
$upass .= ':' . $parsed['pass']; |
} |
$upass = "$upass@"; |
} |
$ret = 'channel://' . $upass . $parsed['channel'] . '/' . $parsed['package']; |
if (isset($parsed['version']) || isset($parsed['state'])) { |
$ver = isset($parsed['version']) ? $parsed['version'] : ''; |
$ver .= isset($parsed['state']) ? $parsed['state'] : ''; |
$ret .= '-' . $ver; |
} |
if (isset($parsed['extension'])) { |
$ret .= '.' . $parsed['extension']; |
} |
if (isset($parsed['opts'])) { |
$ret .= '?'; |
foreach ($parsed['opts'] as $name => $value) { |
$parsed['opts'][$name] = "$name=$value"; |
} |
$ret .= implode('&', $parsed['opts']); |
} |
if (isset($parsed['group'])) { |
$ret .= '#' . $parsed['group']; |
} |
return $ret; |
} |
} |
/branches/v1.3-critias/bibliotheque/pear/PEAR/Task/Postinstallscript.php |
---|
New file |
0,0 → 1,349 |
<?php |
/** |
* <tasks:postinstallscript> |
* |
* PHP versions 4 and 5 |
* |
* @category pear |
* @package PEAR |
* @author Greg Beaver <cellog@php.net> |
* @copyright 1997-2009 The Authors |
* @license http://opensource.org/licenses/bsd-license.php New BSD License |
* @link http://pear.php.net/package/PEAR |
* @since File available since Release 1.4.0a1 |
*/ |
/** |
* Base class |
*/ |
require_once 'PEAR/Task/Common.php'; |
/** |
* Implements the postinstallscript file task. |
* |
* Note that post-install scripts are handled separately from installation, by the |
* "pear run-scripts" command |
* |
* @category pear |
* @package PEAR |
* @author Greg Beaver <cellog@php.net> |
* @copyright 1997-2009 The Authors |
* @license http://opensource.org/licenses/bsd-license.php New BSD License |
* @version Release: 1.10.1 |
* @link http://pear.php.net/package/PEAR |
* @since Class available since Release 1.4.0a1 |
*/ |
class PEAR_Task_Postinstallscript extends PEAR_Task_Common |
{ |
public $type = 'script'; |
public $_class; |
public $_params; |
public $_obj; |
/** |
* |
* @var PEAR_PackageFile_v2 |
*/ |
public $_pkg; |
public $_contents; |
public $phase = PEAR_TASK_INSTALL; |
/** |
* Validate the raw xml at parsing-time. |
* |
* This also attempts to validate the script to make sure it meets the criteria |
* for a post-install script |
* |
* @param PEAR_PackageFile_v2 |
* @param array The XML contents of the <postinstallscript> tag |
* @param PEAR_Config |
* @param array the entire parsed <file> tag |
*/ |
public static function validateXml($pkg, $xml, $config, $fileXml) |
{ |
if ($fileXml['role'] != 'php') { |
return array(PEAR_TASK_ERROR_INVALID, 'Post-install script "'. |
$fileXml['name'].'" must be role="php"', ); |
} |
PEAR::pushErrorHandling(PEAR_ERROR_RETURN); |
$file = $pkg->getFileContents($fileXml['name']); |
if (PEAR::isError($file)) { |
PEAR::popErrorHandling(); |
return array(PEAR_TASK_ERROR_INVALID, 'Post-install script "'. |
$fileXml['name'].'" is not valid: '. |
$file->getMessage(), ); |
} elseif ($file === null) { |
return array(PEAR_TASK_ERROR_INVALID, 'Post-install script "'. |
$fileXml['name'].'" could not be retrieved for processing!', ); |
} else { |
$analysis = $pkg->analyzeSourceCode($file, true); |
if (!$analysis) { |
PEAR::popErrorHandling(); |
$warnings = ''; |
foreach ($pkg->getValidationWarnings() as $warn) { |
$warnings .= $warn['message']."\n"; |
} |
return array(PEAR_TASK_ERROR_INVALID, 'Analysis of post-install script "'. |
$fileXml['name'].'" failed: '.$warnings, ); |
} |
if (count($analysis['declared_classes']) != 1) { |
PEAR::popErrorHandling(); |
return array(PEAR_TASK_ERROR_INVALID, 'Post-install script "'. |
$fileXml['name'].'" must declare exactly 1 class', ); |
} |
$class = $analysis['declared_classes'][0]; |
if ($class != str_replace( |
array('/', '.php'), array('_', ''), |
$fileXml['name'] |
).'_postinstall') { |
PEAR::popErrorHandling(); |
return array(PEAR_TASK_ERROR_INVALID, 'Post-install script "'. |
$fileXml['name'].'" class "'.$class.'" must be named "'. |
str_replace( |
array('/', '.php'), array('_', ''), |
$fileXml['name'] |
).'_postinstall"', ); |
} |
if (!isset($analysis['declared_methods'][$class])) { |
PEAR::popErrorHandling(); |
return array(PEAR_TASK_ERROR_INVALID, 'Post-install script "'. |
$fileXml['name'].'" must declare methods init() and run()', ); |
} |
$methods = array('init' => 0, 'run' => 1); |
foreach ($analysis['declared_methods'][$class] as $method) { |
if (isset($methods[$method])) { |
unset($methods[$method]); |
} |
} |
if (count($methods)) { |
PEAR::popErrorHandling(); |
return array(PEAR_TASK_ERROR_INVALID, 'Post-install script "'. |
$fileXml['name'].'" must declare methods init() and run()', ); |
} |
} |
PEAR::popErrorHandling(); |
$definedparams = array(); |
$tasksNamespace = $pkg->getTasksNs().':'; |
if (!isset($xml[$tasksNamespace.'paramgroup']) && isset($xml['paramgroup'])) { |
// in order to support the older betas, which did not expect internal tags |
// to also use the namespace |
$tasksNamespace = ''; |
} |
if (isset($xml[$tasksNamespace.'paramgroup'])) { |
$params = $xml[$tasksNamespace.'paramgroup']; |
if (!is_array($params) || !isset($params[0])) { |
$params = array($params); |
} |
foreach ($params as $param) { |
if (!isset($param[$tasksNamespace.'id'])) { |
return array(PEAR_TASK_ERROR_INVALID, 'Post-install script "'. |
$fileXml['name'].'" <paramgroup> must have '. |
'an '.$tasksNamespace.'id> tag', ); |
} |
if (isset($param[$tasksNamespace.'name'])) { |
if (!in_array($param[$tasksNamespace.'name'], $definedparams)) { |
return array(PEAR_TASK_ERROR_INVALID, 'Post-install script "'. |
$fileXml['name'].'" '.$tasksNamespace. |
'paramgroup> id "'.$param[$tasksNamespace.'id']. |
'" parameter "'.$param[$tasksNamespace.'name']. |
'" has not been previously defined', ); |
} |
if (!isset($param[$tasksNamespace.'conditiontype'])) { |
return array(PEAR_TASK_ERROR_INVALID, 'Post-install script "'. |
$fileXml['name'].'" '.$tasksNamespace. |
'paramgroup> id "'.$param[$tasksNamespace.'id']. |
'" must have a '.$tasksNamespace. |
'conditiontype> tag containing either "=", '. |
'"!=", or "preg_match"', ); |
} |
if (!in_array( |
$param[$tasksNamespace.'conditiontype'], |
array('=', '!=', 'preg_match') |
)) { |
return array(PEAR_TASK_ERROR_INVALID, 'Post-install script "'. |
$fileXml['name'].'" '.$tasksNamespace. |
'paramgroup> id "'.$param[$tasksNamespace.'id']. |
'" must have a '.$tasksNamespace. |
'conditiontype> tag containing either "=", '. |
'"!=", or "preg_match"', ); |
} |
if (!isset($param[$tasksNamespace.'value'])) { |
return array(PEAR_TASK_ERROR_INVALID, 'Post-install script "'. |
$fileXml['name'].'" '.$tasksNamespace. |
'paramgroup> id "'.$param[$tasksNamespace.'id']. |
'" must have a '.$tasksNamespace. |
'value> tag containing expected parameter value', ); |
} |
} |
if (isset($param[$tasksNamespace.'instructions'])) { |
if (!is_string($param[$tasksNamespace.'instructions'])) { |
return array(PEAR_TASK_ERROR_INVALID, 'Post-install script "'. |
$fileXml['name'].'" '.$tasksNamespace. |
'paramgroup> id "'.$param[$tasksNamespace.'id']. |
'" '.$tasksNamespace.'instructions> must be simple text', ); |
} |
} |
if (!isset($param[$tasksNamespace.'param'])) { |
continue; // <param> is no longer required |
} |
$subparams = $param[$tasksNamespace.'param']; |
if (!is_array($subparams) || !isset($subparams[0])) { |
$subparams = array($subparams); |
} |
foreach ($subparams as $subparam) { |
if (!isset($subparam[$tasksNamespace.'name'])) { |
return array(PEAR_TASK_ERROR_INVALID, 'Post-install script "'. |
$fileXml['name'].'" parameter for '. |
$tasksNamespace.'paramgroup> id "'. |
$param[$tasksNamespace.'id'].'" must have '. |
'a '.$tasksNamespace.'name> tag', ); |
} |
if (!preg_match( |
'/[a-zA-Z0-9]+/', |
$subparam[$tasksNamespace.'name'] |
)) { |
return array(PEAR_TASK_ERROR_INVALID, 'Post-install script "'. |
$fileXml['name'].'" parameter "'. |
$subparam[$tasksNamespace.'name']. |
'" for '.$tasksNamespace.'paramgroup> id "'. |
$param[$tasksNamespace.'id']. |
'" is not a valid name. Must contain only alphanumeric characters', ); |
} |
if (!isset($subparam[$tasksNamespace.'prompt'])) { |
return array(PEAR_TASK_ERROR_INVALID, 'Post-install script "'. |
$fileXml['name'].'" parameter "'. |
$subparam[$tasksNamespace.'name']. |
'" for '.$tasksNamespace.'paramgroup> id "'. |
$param[$tasksNamespace.'id']. |
'" must have a '.$tasksNamespace.'prompt> tag', ); |
} |
if (!isset($subparam[$tasksNamespace.'type'])) { |
return array(PEAR_TASK_ERROR_INVALID, 'Post-install script "'. |
$fileXml['name'].'" parameter "'. |
$subparam[$tasksNamespace.'name']. |
'" for '.$tasksNamespace.'paramgroup> id "'. |
$param[$tasksNamespace.'id']. |
'" must have a '.$tasksNamespace.'type> tag', ); |
} |
$definedparams[] = $param[$tasksNamespace.'id'].'::'. |
$subparam[$tasksNamespace.'name']; |
} |
} |
} |
return true; |
} |
/** |
* Initialize a task instance with the parameters |
* @param array $xml raw, parsed xml |
* @param array $fileattribs attributes from the <file> tag containing |
* this task |
* @param string|null $lastversion last installed version of this package, |
* if any (useful for upgrades) |
*/ |
public function init($xml, $fileattribs, $lastversion) |
{ |
$this->_class = str_replace('/', '_', $fileattribs['name']); |
$this->_filename = $fileattribs['name']; |
$this->_class = str_replace('.php', '', $this->_class).'_postinstall'; |
$this->_params = $xml; |
$this->_lastversion = $lastversion; |
} |
/** |
* Strip the tasks: namespace from internal params |
* |
* @access private |
*/ |
public function _stripNamespace($params = null) |
{ |
if ($params === null) { |
$params = array(); |
if (!is_array($this->_params)) { |
return; |
} |
foreach ($this->_params as $i => $param) { |
if (is_array($param)) { |
$param = $this->_stripNamespace($param); |
} |
$params[str_replace($this->_pkg->getTasksNs().':', '', $i)] = $param; |
} |
$this->_params = $params; |
} else { |
$newparams = array(); |
foreach ($params as $i => $param) { |
if (is_array($param)) { |
$param = $this->_stripNamespace($param); |
} |
$newparams[str_replace($this->_pkg->getTasksNs().':', '', $i)] = $param; |
} |
return $newparams; |
} |
} |
/** |
* Unlike other tasks, the installed file name is passed in instead of the |
* file contents, because this task is handled post-installation |
* |
* @param mixed $pkg PEAR_PackageFile_v1|PEAR_PackageFile_v2 |
* @param string $contents file name |
* |
* @return bool|PEAR_Error false to skip this file, PEAR_Error to fail |
* (use $this->throwError) |
*/ |
public function startSession($pkg, $contents) |
{ |
if ($this->installphase != PEAR_TASK_INSTALL) { |
return false; |
} |
// remove the tasks: namespace if present |
$this->_pkg = $pkg; |
$this->_stripNamespace(); |
$this->logger->log( |
0, 'Including external post-installation script "'. |
$contents.'" - any errors are in this script' |
); |
include_once $contents; |
if (class_exists($this->_class)) { |
$this->logger->log(0, 'Inclusion succeeded'); |
} else { |
return $this->throwError( |
'init of post-install script class "'.$this->_class |
.'" failed' |
); |
} |
$this->_obj = new $this->_class(); |
$this->logger->log(1, 'running post-install script "'.$this->_class.'->init()"'); |
PEAR::pushErrorHandling(PEAR_ERROR_RETURN); |
$res = $this->_obj->init($this->config, $pkg, $this->_lastversion); |
PEAR::popErrorHandling(); |
if ($res) { |
$this->logger->log(0, 'init succeeded'); |
} else { |
return $this->throwError( |
'init of post-install script "'.$this->_class. |
'->init()" failed' |
); |
} |
$this->_contents = $contents; |
return true; |
} |
/** |
* No longer used |
* |
* @see PEAR_PackageFile_v2::runPostinstallScripts() |
* @param array an array of tasks |
* @param string install or upgrade |
* @access protected |
*/ |
public static function run() |
{ |
} |
} |
/branches/v1.3-critias/bibliotheque/pear/PEAR/Task/Unixeol.php |
---|
New file |
0,0 → 1,79 |
<?php |
/** |
* <tasks:unixeol> |
* |
* PHP versions 4 and 5 |
* |
* @category pear |
* @package PEAR |
* @author Greg Beaver <cellog@php.net> |
* @copyright 1997-2009 The Authors |
* @license http://opensource.org/licenses/bsd-license.php New BSD License |
* @link http://pear.php.net/package/PEAR |
* @since File available since Release 1.4.0a1 |
*/ |
/** |
* Base class |
*/ |
require_once 'PEAR/Task/Common.php'; |
/** |
* Implements the unix line endings file task. |
* @category pear |
* @package PEAR |
* @author Greg Beaver <cellog@php.net> |
* @copyright 1997-2009 The Authors |
* @license http://opensource.org/licenses/bsd-license.php New BSD License |
* @version Release: 1.10.1 |
* @link http://pear.php.net/package/PEAR |
* @since Class available since Release 1.4.0a1 |
*/ |
class PEAR_Task_Unixeol extends PEAR_Task_Common |
{ |
public $type = 'simple'; |
public $phase = PEAR_TASK_PACKAGE; |
public $_replacements; |
/** |
* Validate the raw xml at parsing-time. |
* |
* @param PEAR_PackageFile_v2 |
* @param array raw, parsed xml |
* @param PEAR_Config |
*/ |
public static function validateXml($pkg, $xml, $config, $fileXml) |
{ |
if ($xml != '') { |
return array(PEAR_TASK_ERROR_INVALID, 'no attributes allowed'); |
} |
return true; |
} |
/** |
* Initialize a task instance with the parameters |
* @param array raw, parsed xml |
* @param unused |
* @param unused |
*/ |
public function init($xml, $attribs, $lastVersion = null) |
{ |
} |
/** |
* Replace all line endings with line endings customized for the current OS |
* |
* See validateXml() source for the complete list of allowed fields |
* |
* @param PEAR_PackageFile_v1|PEAR_PackageFile_v2 |
* @param string file contents |
* @param string the eventual final file location (informational only) |
* @return string|false|PEAR_Error false to skip this file, PEAR_Error to fail |
* (use $this->throwError), otherwise return the new contents |
*/ |
public function startSession($pkg, $contents, $dest) |
{ |
$this->logger->log(3, "replacing all line endings with \\n in $dest"); |
return preg_replace("/\r\n|\n\r|\r|\n/", "\n", $contents); |
} |
} |
/branches/v1.3-critias/bibliotheque/pear/PEAR/Task/Windowseol/rw.php |
---|
New file |
0,0 → 1,56 |
<?php |
/** |
* <tasks:windowseol> - read/write version |
* |
* PHP versions 4 and 5 |
* |
* @category pear |
* @package PEAR |
* @author Greg Beaver <cellog@php.net> |
* @copyright 1997-2009 The Authors |
* @license http://opensource.org/licenses/bsd-license.php New BSD License |
* @link http://pear.php.net/package/PEAR |
* @since File available since Release 1.4.0a10 |
*/ |
/** |
* Base class |
*/ |
require_once 'PEAR/Task/Windowseol.php'; |
/** |
* Abstracts the windowseol task xml. |
* |
* @category pear |
* @package PEAR |
* @author Greg Beaver <cellog@php.net> |
* @copyright 1997-2009 The Authors |
* @license http://opensource.org/licenses/bsd-license.php New BSD License |
* @version Release: 1.10.1 |
* @link http://pear.php.net/package/PEAR |
* @since Class available since Release 1.4.0a10 |
*/ |
class PEAR_Task_Windowseol_rw extends PEAR_Task_Windowseol |
{ |
function __construct(&$pkg, &$config, &$logger, $fileXml) |
{ |
parent::__construct($config, $logger, PEAR_TASK_PACKAGE); |
$this->_contents = $fileXml; |
$this->_pkg = &$pkg; |
$this->_params = array(); |
} |
public function validate() |
{ |
return true; |
} |
public function getName() |
{ |
return 'windowseol'; |
} |
public function getXml() |
{ |
return ''; |
} |
} |
?> |
/branches/v1.3-critias/bibliotheque/pear/PEAR/Task/Replace/rw.php |
---|
New file |
0,0 → 1,59 |
<?php |
/** |
* <tasks:replace> - read/write version |
* |
* PHP versions 4 and 5 |
* |
* @category pear |
* @package PEAR |
* @author Greg Beaver <cellog@php.net> |
* @copyright 1997-2009 The Authors |
* @license http://opensource.org/licenses/bsd-license.php New BSD License |
* @link http://pear.php.net/package/PEAR |
* @since File available since Release 1.4.0a10 |
*/ |
/** |
* Base class |
*/ |
require_once 'PEAR/Task/Replace.php'; |
/** |
* Abstracts the replace task xml. |
* @category pear |
* @package PEAR |
* @author Greg Beaver <cellog@php.net> |
* @copyright 1997-2009 The Authors |
* @license http://opensource.org/licenses/bsd-license.php New BSD License |
* @version Release: 1.10.1 |
* @link http://pear.php.net/package/PEAR |
* @since Class available since Release 1.4.0a10 |
*/ |
class PEAR_Task_Replace_rw extends PEAR_Task_Replace |
{ |
public function __construct(&$pkg, &$config, &$logger, $fileXml) |
{ |
parent::__construct($config, $logger, PEAR_TASK_PACKAGE); |
$this->_contents = $fileXml; |
$this->_pkg = &$pkg; |
$this->_params = array(); |
} |
public function validate() |
{ |
return $this->validateXml($this->_pkg, $this->_params, $this->config, $this->_contents); |
} |
public function setInfo($from, $to, $type) |
{ |
$this->_params = array('attribs' => array('from' => $from, 'to' => $to, 'type' => $type)); |
} |
public function getName() |
{ |
return 'replace'; |
} |
public function getXml() |
{ |
return $this->_params; |
} |
} |
/branches/v1.3-critias/bibliotheque/pear/PEAR/Task/Common.php |
---|
New file |
0,0 → 1,207 |
<?php |
/** |
* PEAR_Task_Common, base class for installer tasks |
* |
* PHP versions 4 and 5 |
* |
* @category pear |
* @package PEAR |
* @author Greg Beaver <cellog@php.net> |
* @copyright 1997-2009 The Authors |
* @license http://opensource.org/licenses/bsd-license.php New BSD License |
* @link http://pear.php.net/package/PEAR |
* @since File available since Release 1.4.0a1 |
*/ |
/**#@+ |
* Error codes for task validation routines |
*/ |
define('PEAR_TASK_ERROR_NOATTRIBS', 1); |
define('PEAR_TASK_ERROR_MISSING_ATTRIB', 2); |
define('PEAR_TASK_ERROR_WRONG_ATTRIB_VALUE', 3); |
define('PEAR_TASK_ERROR_INVALID', 4); |
/**#@-*/ |
define('PEAR_TASK_PACKAGE', 1); |
define('PEAR_TASK_INSTALL', 2); |
define('PEAR_TASK_PACKAGEANDINSTALL', 3); |
/** |
* A task is an operation that manipulates the contents of a file. |
* |
* Simple tasks operate on 1 file. Multiple tasks are executed after all files have been |
* processed and installed, and are designed to operate on all files containing the task. |
* The Post-install script task simply takes advantage of the fact that it will be run |
* after installation, replace is a simple task. |
* |
* Combining tasks is possible, but ordering is significant. |
* |
* <file name="test.php" role="php"> |
* <tasks:replace from="@data-dir@" to="data_dir" type="pear-config"/> |
* <tasks:postinstallscript/> |
* </file> |
* |
* This will first replace any instance of @data-dir@ in the test.php file |
* with the path to the current data directory. Then, it will include the |
* test.php file and run the script it contains to configure the package post-installation. |
* |
* @category pear |
* @package PEAR |
* @author Greg Beaver <cellog@php.net> |
* @copyright 1997-2009 The Authors |
* @license http://opensource.org/licenses/bsd-license.php New BSD License |
* @version Release: 1.10.1 |
* @link http://pear.php.net/package/PEAR |
* @since Class available since Release 1.4.0a1 |
* @abstract |
*/ |
class PEAR_Task_Common |
{ |
/** |
* Valid types for this version are 'simple' and 'multiple' |
* |
* - simple tasks operate on the contents of a file and write out changes to disk |
* - multiple tasks operate on the contents of many files and write out the |
* changes directly to disk |
* |
* Child task classes must override this property. |
* |
* @access protected |
*/ |
protected $type = 'simple'; |
/** |
* Determines which install phase this task is executed under |
*/ |
public $phase = PEAR_TASK_INSTALL; |
/** |
* @access protected |
*/ |
protected $config; |
/** |
* @access protected |
*/ |
protected $registry; |
/** |
* @access protected |
*/ |
public $logger; |
/** |
* @access protected |
*/ |
protected $installphase; |
/** |
* @param PEAR_Config |
* @param PEAR_Common |
*/ |
function __construct(&$config, &$logger, $phase) |
{ |
$this->config = &$config; |
$this->registry = &$config->getRegistry(); |
$this->logger = &$logger; |
$this->installphase = $phase; |
if ($this->type == 'multiple') { |
$GLOBALS['_PEAR_TASK_POSTINSTANCES'][get_class($this)][] = &$this; |
} |
} |
/** |
* Validate the basic contents of a task tag. |
* |
* @param PEAR_PackageFile_v2 |
* @param array |
* @param PEAR_Config |
* @param array the entire parsed <file> tag |
* |
* @return true|array On error, return an array in format: |
* array(PEAR_TASK_ERROR_???[, param1][, param2][, ...]) |
* |
* For PEAR_TASK_ERROR_MISSING_ATTRIB, pass the attribute name in |
* For PEAR_TASK_ERROR_WRONG_ATTRIB_VALUE, pass the attribute name and |
* an array of legal values in |
* |
* @abstract |
*/ |
public static function validateXml($pkg, $xml, $config, $fileXml) |
{ |
} |
/** |
* Initialize a task instance with the parameters |
* |
* @param array raw, parsed xml |
* @param array attributes from the <file> tag containing this task |
* @param string|null last installed version of this package |
* @abstract |
*/ |
public function init($xml, $fileAttributes, $lastVersion) |
{ |
} |
/** |
* Begin a task processing session. All multiple tasks will be processed |
* after each file has been successfully installed, all simple tasks should |
* perform their task here and return any errors using the custom |
* throwError() method to allow forward compatibility |
* |
* This method MUST NOT write out any changes to disk |
* |
* @param PEAR_PackageFile_v2 |
* @param string file contents |
* @param string the eventual final file location (informational only) |
* @return string|false|PEAR_Error false to skip this file, PEAR_Error to fail |
* (use $this->throwError), otherwise return the new contents |
* @abstract |
*/ |
public function startSession($pkg, $contents, $dest) |
{ |
} |
/** |
* This method is used to process each of the tasks for a particular |
* multiple class type. Simple tasks need not implement this method. |
* |
* @param array an array of tasks |
* @access protected |
*/ |
public static function run($tasks) |
{ |
} |
/** |
* @final |
*/ |
public static function hasPostinstallTasks() |
{ |
return isset($GLOBALS['_PEAR_TASK_POSTINSTANCES']); |
} |
/** |
* @final |
*/ |
public static function runPostinstallTasks() |
{ |
foreach ($GLOBALS['_PEAR_TASK_POSTINSTANCES'] as $class => $tasks) { |
$err = call_user_func( |
array($class, 'run'), |
$GLOBALS['_PEAR_TASK_POSTINSTANCES'][$class] |
); |
if ($err) { |
return PEAR_Task_Common::throwError($err); |
} |
} |
unset($GLOBALS['_PEAR_TASK_POSTINSTANCES']); |
} |
/** |
* Determines whether a role is a script |
* @return bool |
*/ |
public function isScript() |
{ |
return $this->type == 'script'; |
} |
public function throwError($msg, $code = -1) |
{ |
include_once 'PEAR.php'; |
return PEAR::raiseError($msg, $code); |
} |
} |
/branches/v1.3-critias/bibliotheque/pear/PEAR/Task/Windowseol.php |
---|
New file |
0,0 → 1,80 |
<?php |
/** |
* <tasks:windowseol> |
* |
* PHP versions 4 and 5 |
* |
* @category pear |
* @package PEAR |
* @author Greg Beaver <cellog@php.net> |
* @copyright 1997-2009 The Authors |
* @license http://opensource.org/licenses/bsd-license.php New BSD License |
* @link http://pear.php.net/package/PEAR |
* @since File available since Release 1.4.0a1 |
*/ |
/** |
* Base class |
*/ |
require_once 'PEAR/Task/Common.php'; |
/** |
* Implements the windows line endsings file task. |
* |
* @category pear |
* @package PEAR |
* @author Greg Beaver <cellog@php.net> |
* @copyright 1997-2009 The Authors |
* @license http://opensource.org/licenses/bsd-license.php New BSD License |
* @version Release: 1.10.1 |
* @link http://pear.php.net/package/PEAR |
* @since Class available since Release 1.4.0a1 |
*/ |
class PEAR_Task_Windowseol extends PEAR_Task_Common |
{ |
public $type = 'simple'; |
public $phase = PEAR_TASK_PACKAGE; |
public $_replacements; |
/** |
* Validate the raw xml at parsing-time. |
* |
* @param PEAR_PackageFile_v2 |
* @param array raw, parsed xml |
* @param PEAR_Config |
*/ |
public static function validateXml($pkg, $xml, $config, $fileXml) |
{ |
if ($xml != '') { |
return array(PEAR_TASK_ERROR_INVALID, 'no attributes allowed'); |
} |
return true; |
} |
/** |
* Initialize a task instance with the parameters |
* @param array raw, parsed xml |
* @param unused |
* @param unused |
*/ |
public function init($xml, $attribs, $lastVersion = null) |
{ |
} |
/** |
* Replace all line endings with windows line endings |
* |
* See validateXml() source for the complete list of allowed fields |
* |
* @param PEAR_PackageFile_v1|PEAR_PackageFile_v2 |
* @param string file contents |
* @param string the eventual final file location (informational only) |
* @return string|false|PEAR_Error false to skip this file, PEAR_Error to fail |
* (use $this->throwError), otherwise return the new contents |
*/ |
public function startSession($pkg, $contents, $dest) |
{ |
$this->logger->log(3, "replacing all line endings with \\r\\n in $dest"); |
return preg_replace("/\r\n|\n\r|\r|\n/", "\r\n", $contents); |
} |
} |
/branches/v1.3-critias/bibliotheque/pear/PEAR/Task/Postinstallscript/rw.php |
---|
New file |
0,0 → 1,182 |
<?php |
/** |
* <tasks:postinstallscript> - read/write version |
* |
* PHP versions 4 and 5 |
* |
* @category pear |
* @package PEAR |
* @author Greg Beaver <cellog@php.net> |
* @copyright 1997-2009 The Authors |
* @license http://opensource.org/licenses/bsd-license.php New BSD License |
* @link http://pear.php.net/package/PEAR |
* @since File available since Release 1.4.0a10 |
*/ |
/** |
* Base class |
*/ |
require_once 'PEAR/Task/Postinstallscript.php'; |
/** |
* Abstracts the postinstallscript file task xml. |
* @category pear |
* @package PEAR |
* @author Greg Beaver <cellog@php.net> |
* @copyright 1997-2009 The Authors |
* @license http://opensource.org/licenses/bsd-license.php New BSD License |
* @version Release: 1.10.1 |
* @link http://pear.php.net/package/PEAR |
* @since Class available since Release 1.4.0a10 |
*/ |
class PEAR_Task_Postinstallscript_rw extends PEAR_Task_Postinstallscript |
{ |
/** |
* parent package file object |
* |
* @var PEAR_PackageFile_v2_rw |
*/ |
public $_pkg; |
/** |
* Enter description here... |
* |
* @param PEAR_PackageFile_v2_rw $pkg Package |
* @param PEAR_Config $config Config |
* @param PEAR_Frontend $logger Logger |
* @param array $fileXml XML |
* |
* @return PEAR_Task_Postinstallscript_rw |
*/ |
function __construct(&$pkg, &$config, &$logger, $fileXml) |
{ |
parent::__construct($config, $logger, PEAR_TASK_PACKAGE); |
$this->_contents = $fileXml; |
$this->_pkg = &$pkg; |
$this->_params = array(); |
} |
public function validate() |
{ |
return $this->validateXml($this->_pkg, $this->_params, $this->config, $this->_contents); |
} |
public function getName() |
{ |
return 'postinstallscript'; |
} |
/** |
* add a simple <paramgroup> to the post-install script |
* |
* Order is significant, so call this method in the same |
* sequence the users should see the paramgroups. The $params |
* parameter should either be the result of a call to {@link getParam()} |
* or an array of calls to getParam(). |
* |
* Use {@link addConditionTypeGroup()} to add a <paramgroup> containing |
* a <conditiontype> tag |
* |
* @param string $id <paramgroup> id as seen by the script |
* @param array|false $params array of getParam() calls, or false for no params |
* @param string|false $instructions |
*/ |
public function addParamGroup($id, $params = false, $instructions = false) |
{ |
if ($params && isset($params[0]) && !isset($params[1])) { |
$params = $params[0]; |
} |
$stuff = |
array( |
$this->_pkg->getTasksNs().':id' => $id, |
); |
if ($instructions) { |
$stuff[$this->_pkg->getTasksNs().':instructions'] = $instructions; |
} |
if ($params) { |
$stuff[$this->_pkg->getTasksNs().':param'] = $params; |
} |
$this->_params[$this->_pkg->getTasksNs().':paramgroup'][] = $stuff; |
} |
/** |
* Add a complex <paramgroup> to the post-install script with conditions |
* |
* This inserts a <paramgroup> with |
* |
* Order is significant, so call this method in the same |
* sequence the users should see the paramgroups. The $params |
* parameter should either be the result of a call to {@link getParam()} |
* or an array of calls to getParam(). |
* |
* Use {@link addParamGroup()} to add a simple <paramgroup> |
* |
* @param string $id <paramgroup> id as seen by the script |
* @param string $oldgroup <paramgroup> id of the section referenced by |
* <conditiontype> |
* @param string $param name of the <param> from the older section referenced |
* by <contitiontype> |
* @param string $value value to match of the parameter |
* @param string $conditiontype one of '=', '!=', 'preg_match' |
* @param array|false $params array of getParam() calls, or false for no params |
* @param string|false $instructions |
*/ |
public function addConditionTypeGroup($id, |
$oldgroup, |
$param, |
$value, |
$conditiontype = '=', |
$params = false, |
$instructions = false |
) { |
if ($params && isset($params[0]) && !isset($params[1])) { |
$params = $params[0]; |
} |
$stuff = array( |
$this->_pkg->getTasksNs().':id' => $id, |
); |
if ($instructions) { |
$stuff[$this->_pkg->getTasksNs().':instructions'] = $instructions; |
} |
$stuff[$this->_pkg->getTasksNs().':name'] = $oldgroup.'::'.$param; |
$stuff[$this->_pkg->getTasksNs().':conditiontype'] = $conditiontype; |
$stuff[$this->_pkg->getTasksNs().':value'] = $value; |
if ($params) { |
$stuff[$this->_pkg->getTasksNs().':param'] = $params; |
} |
$this->_params[$this->_pkg->getTasksNs().':paramgroup'][] = $stuff; |
} |
public function getXml() |
{ |
return $this->_params; |
} |
/** |
* Use to set up a param tag for use in creating a paramgroup |
* |
* @param mixed $name Name of parameter |
* @param mixed $prompt Prompt |
* @param string $type Type, defaults to 'string' |
* @param mixed $default Default value |
* |
* @return array |
*/ |
public static function getParam( |
$name, $prompt, $type = 'string', $default = null |
) { |
if ($default !== null) { |
return |
array( |
$this->_pkg->getTasksNs().':name' => $name, |
$this->_pkg->getTasksNs().':prompt' => $prompt, |
$this->_pkg->getTasksNs().':type' => $type, |
$this->_pkg->getTasksNs().':default' => $default, |
); |
} |
return |
array( |
$this->_pkg->getTasksNs().':name' => $name, |
$this->_pkg->getTasksNs().':prompt' => $prompt, |
$this->_pkg->getTasksNs().':type' => $type, |
); |
} |
} |
/branches/v1.3-critias/bibliotheque/pear/PEAR/Task/Replace.php |
---|
New file |
0,0 → 1,186 |
<?php |
/** |
* <tasks:replace> |
* |
* PHP versions 4 and 5 |
* |
* @category pear |
* @package PEAR |
* @author Greg Beaver <cellog@php.net> |
* @copyright 1997-2009 The Authors |
* @license http://opensource.org/licenses/bsd-license.php New BSD License |
* @link http://pear.php.net/package/PEAR |
* @since File available since Release 1.4.0a1 |
*/ |
/** |
* Base class |
*/ |
require_once 'PEAR/Task/Common.php'; |
/** |
* Implements the replace file task. |
* @category pear |
* @package PEAR |
* @author Greg Beaver <cellog@php.net> |
* @copyright 1997-2009 The Authors |
* @license http://opensource.org/licenses/bsd-license.php New BSD License |
* @version Release: 1.10.1 |
* @link http://pear.php.net/package/PEAR |
* @since Class available since Release 1.4.0a1 |
*/ |
class PEAR_Task_Replace extends PEAR_Task_Common |
{ |
public $type = 'simple'; |
public $phase = PEAR_TASK_PACKAGEANDINSTALL; |
public $_replacements; |
/** |
* Validate the raw xml at parsing-time. |
* |
* @param PEAR_PackageFile_v2 |
* @param array raw, parsed xml |
* @param PEAR_Config |
*/ |
public static function validateXml($pkg, $xml, $config, $fileXml) |
{ |
if (!isset($xml['attribs'])) { |
return array(PEAR_TASK_ERROR_NOATTRIBS); |
} |
if (!isset($xml['attribs']['type'])) { |
return array(PEAR_TASK_ERROR_MISSING_ATTRIB, 'type'); |
} |
if (!isset($xml['attribs']['to'])) { |
return array(PEAR_TASK_ERROR_MISSING_ATTRIB, 'to'); |
} |
if (!isset($xml['attribs']['from'])) { |
return array(PEAR_TASK_ERROR_MISSING_ATTRIB, 'from'); |
} |
if ($xml['attribs']['type'] == 'pear-config') { |
if (!in_array($xml['attribs']['to'], $config->getKeys())) { |
return array(PEAR_TASK_ERROR_WRONG_ATTRIB_VALUE, 'to', $xml['attribs']['to'], |
$config->getKeys(), ); |
} |
} elseif ($xml['attribs']['type'] == 'php-const') { |
if (defined($xml['attribs']['to'])) { |
return true; |
} else { |
return array(PEAR_TASK_ERROR_WRONG_ATTRIB_VALUE, 'to', $xml['attribs']['to'], |
array('valid PHP constant'), ); |
} |
} elseif ($xml['attribs']['type'] == 'package-info') { |
if (in_array( |
$xml['attribs']['to'], |
array('name', 'summary', 'channel', 'notes', 'extends', 'description', |
'release_notes', 'license', 'release-license', 'license-uri', |
'version', 'api-version', 'state', 'api-state', 'release_date', |
'date', 'time', ) |
)) { |
return true; |
} else { |
return array(PEAR_TASK_ERROR_WRONG_ATTRIB_VALUE, 'to', $xml['attribs']['to'], |
array('name', 'summary', 'channel', 'notes', 'extends', 'description', |
'release_notes', 'license', 'release-license', 'license-uri', |
'version', 'api-version', 'state', 'api-state', 'release_date', |
'date', 'time', ), ); |
} |
} else { |
return array(PEAR_TASK_ERROR_WRONG_ATTRIB_VALUE, 'type', $xml['attribs']['type'], |
array('pear-config', 'package-info', 'php-const'), ); |
} |
return true; |
} |
/** |
* Initialize a task instance with the parameters |
* @param array raw, parsed xml |
* @param unused |
* @param unused |
*/ |
public function init($xml, $attribs, $lastVersion = null) |
{ |
$this->_replacements = isset($xml['attribs']) ? array($xml) : $xml; |
} |
/** |
* Do a package.xml 1.0 replacement, with additional package-info fields available |
* |
* See validateXml() source for the complete list of allowed fields |
* |
* @param PEAR_PackageFile_v1|PEAR_PackageFile_v2 |
* @param string file contents |
* @param string the eventual final file location (informational only) |
* @return string|false|PEAR_Error false to skip this file, PEAR_Error to fail |
* (use $this->throwError), otherwise return the new contents |
*/ |
public function startSession($pkg, $contents, $dest) |
{ |
$subst_from = $subst_to = array(); |
foreach ($this->_replacements as $a) { |
$a = $a['attribs']; |
$to = ''; |
if ($a['type'] == 'pear-config') { |
if ($this->installphase == PEAR_TASK_PACKAGE) { |
return false; |
} |
if ($a['to'] == 'master_server') { |
$chan = $this->registry->getChannel($pkg->getChannel()); |
if (!PEAR::isError($chan)) { |
$to = $chan->getServer(); |
} else { |
$this->logger->log(0, "$dest: invalid pear-config replacement: $a[to]"); |
return false; |
} |
} else { |
if ($this->config->isDefinedLayer('ftp')) { |
// try the remote config file first |
$to = $this->config->get($a['to'], 'ftp', $pkg->getChannel()); |
if (is_null($to)) { |
// then default to local |
$to = $this->config->get($a['to'], null, $pkg->getChannel()); |
} |
} else { |
$to = $this->config->get($a['to'], null, $pkg->getChannel()); |
} |
} |
if (is_null($to)) { |
$this->logger->log(0, "$dest: invalid pear-config replacement: $a[to]"); |
return false; |
} |
} elseif ($a['type'] == 'php-const') { |
if ($this->installphase == PEAR_TASK_PACKAGE) { |
return false; |
} |
if (defined($a['to'])) { |
$to = constant($a['to']); |
} else { |
$this->logger->log(0, "$dest: invalid php-const replacement: $a[to]"); |
return false; |
} |
} else { |
if ($t = $pkg->packageInfo($a['to'])) { |
$to = $t; |
} else { |
$this->logger->log(0, "$dest: invalid package-info replacement: $a[to]"); |
return false; |
} |
} |
if (!is_null($to)) { |
$subst_from[] = $a['from']; |
$subst_to[] = $to; |
} |
} |
$this->logger->log( |
3, "doing ".sizeof($subst_from). |
" substitution(s) for $dest" |
); |
if (sizeof($subst_from)) { |
$contents = str_replace($subst_from, $subst_to, $contents); |
} |
return $contents; |
} |
} |
/branches/v1.3-critias/bibliotheque/pear/PEAR/Task/Unixeol/rw.php |
---|
New file |
0,0 → 1,55 |
<?php |
/** |
* <tasks:unixeol> - read/write version |
* |
* PHP versions 4 and 5 |
* |
* @category pear |
* @package PEAR |
* @author Greg Beaver <cellog@php.net> |
* @copyright 1997-2009 The Authors |
* @license http://opensource.org/licenses/bsd-license.php New BSD License |
* @link http://pear.php.net/package/PEAR |
* @since File available since Release 1.4.0a10 |
*/ |
/** |
* Base class |
*/ |
require_once 'PEAR/Task/Unixeol.php'; |
/** |
* Abstracts the unixeol task xml. |
* @category pear |
* @package PEAR |
* @author Greg Beaver <cellog@php.net> |
* @copyright 1997-2009 The Authors |
* @license http://opensource.org/licenses/bsd-license.php New BSD License |
* @version Release: 1.10.1 |
* @link http://pear.php.net/package/PEAR |
* @since Class available since Release 1.4.0a10 |
*/ |
class PEAR_Task_Unixeol_rw extends PEAR_Task_Unixeol |
{ |
function __construct(&$pkg, &$config, &$logger, $fileXml) |
{ |
parent::__construct($config, $logger, PEAR_TASK_PACKAGE); |
$this->_contents = $fileXml; |
$this->_pkg = &$pkg; |
$this->_params = array(); |
} |
public function validate() |
{ |
return true; |
} |
public function getName() |
{ |
return 'unixeol'; |
} |
public function getXml() |
{ |
return ''; |
} |
} |
?> |
/branches/v1.3-critias/bibliotheque/pear/PEAR/Packager.php |
---|
New file |
0,0 → 1,200 |
<?php |
/** |
* PEAR_Packager for generating releases |
* |
* PHP versions 4 and 5 |
* |
* @category pear |
* @package PEAR |
* @author Stig Bakken <ssb@php.net> |
* @author Tomas V. V. Cox <cox@idecnet.com> |
* @author Greg Beaver <cellog@php.net> |
* @copyright 1997-2009 The Authors |
* @license http://opensource.org/licenses/bsd-license.php New BSD License |
* @link http://pear.php.net/package/PEAR |
* @since File available since Release 0.1 |
*/ |
/** |
* base class |
*/ |
require_once 'PEAR/Common.php'; |
require_once 'PEAR/PackageFile.php'; |
require_once 'System.php'; |
/** |
* Administration class used to make a PEAR release tarball. |
* |
* @category pear |
* @package PEAR |
* @author Greg Beaver <cellog@php.net> |
* @copyright 1997-2009 The Authors |
* @license http://opensource.org/licenses/bsd-license.php New BSD License |
* @version Release: 1.10.1 |
* @link http://pear.php.net/package/PEAR |
* @since Class available since Release 0.1 |
*/ |
class PEAR_Packager extends PEAR_Common |
{ |
/** |
* @var PEAR_Registry |
*/ |
var $_registry; |
function package($pkgfile = null, $compress = true, $pkg2 = null) |
{ |
// {{{ validate supplied package.xml file |
if (empty($pkgfile)) { |
$pkgfile = 'package.xml'; |
} |
PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN); |
$pkg = new PEAR_PackageFile($this->config, $this->debug); |
$pf = &$pkg->fromPackageFile($pkgfile, PEAR_VALIDATE_NORMAL); |
$main = &$pf; |
PEAR::staticPopErrorHandling(); |
if (PEAR::isError($pf)) { |
if (is_array($pf->getUserInfo())) { |
foreach ($pf->getUserInfo() as $error) { |
$this->log(0, 'Error: ' . $error['message']); |
} |
} |
$this->log(0, $pf->getMessage()); |
return $this->raiseError("Cannot package, errors in package file"); |
} |
foreach ($pf->getValidationWarnings() as $warning) { |
$this->log(1, 'Warning: ' . $warning['message']); |
} |
// }}} |
if ($pkg2) { |
$this->log(0, 'Attempting to process the second package file'); |
PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN); |
$pf2 = &$pkg->fromPackageFile($pkg2, PEAR_VALIDATE_NORMAL); |
PEAR::staticPopErrorHandling(); |
if (PEAR::isError($pf2)) { |
if (is_array($pf2->getUserInfo())) { |
foreach ($pf2->getUserInfo() as $error) { |
$this->log(0, 'Error: ' . $error['message']); |
} |
} |
$this->log(0, $pf2->getMessage()); |
return $this->raiseError("Cannot package, errors in second package file"); |
} |
foreach ($pf2->getValidationWarnings() as $warning) { |
$this->log(1, 'Warning: ' . $warning['message']); |
} |
if ($pf2->getPackagexmlVersion() == '2.0' || |
$pf2->getPackagexmlVersion() == '2.1' |
) { |
$main = &$pf2; |
$other = &$pf; |
} else { |
$main = &$pf; |
$other = &$pf2; |
} |
if ($main->getPackagexmlVersion() != '2.0' && |
$main->getPackagexmlVersion() != '2.1') { |
return PEAR::raiseError('Error: cannot package two package.xml version 1.0, can ' . |
'only package together a package.xml 1.0 and package.xml 2.0'); |
} |
if ($other->getPackagexmlVersion() != '1.0') { |
return PEAR::raiseError('Error: cannot package two package.xml version 2.0, can ' . |
'only package together a package.xml 1.0 and package.xml 2.0'); |
} |
} |
$main->setLogger($this); |
if (!$main->validate(PEAR_VALIDATE_PACKAGING)) { |
foreach ($main->getValidationWarnings() as $warning) { |
$this->log(0, 'Error: ' . $warning['message']); |
} |
return $this->raiseError("Cannot package, errors in package"); |
} |
foreach ($main->getValidationWarnings() as $warning) { |
$this->log(1, 'Warning: ' . $warning['message']); |
} |
if ($pkg2) { |
$other->setLogger($this); |
$a = false; |
if (!$other->validate(PEAR_VALIDATE_NORMAL) || $a = !$main->isEquivalent($other)) { |
foreach ($other->getValidationWarnings() as $warning) { |
$this->log(0, 'Error: ' . $warning['message']); |
} |
foreach ($main->getValidationWarnings() as $warning) { |
$this->log(0, 'Error: ' . $warning['message']); |
} |
if ($a) { |
return $this->raiseError('The two package.xml files are not equivalent!'); |
} |
return $this->raiseError("Cannot package, errors in package"); |
} |
foreach ($other->getValidationWarnings() as $warning) { |
$this->log(1, 'Warning: ' . $warning['message']); |
} |
$gen = &$main->getDefaultGenerator(); |
$tgzfile = $gen->toTgz2($this, $other, $compress); |
if (PEAR::isError($tgzfile)) { |
return $tgzfile; |
} |
$dest_package = basename($tgzfile); |
$pkgdir = dirname($pkgfile); |
// TAR the Package ------------------------------------------- |
$this->log(1, "Package $dest_package done"); |
if (file_exists("$pkgdir/CVS/Root")) { |
$cvsversion = preg_replace('/[^a-z0-9]/i', '_', $pf->getVersion()); |
$cvstag = "RELEASE_$cvsversion"; |
$this->log(1, 'Tag the released code with "pear cvstag ' . |
$main->getPackageFile() . '"'); |
$this->log(1, "(or set the CVS tag $cvstag by hand)"); |
} elseif (file_exists("$pkgdir/.svn")) { |
$svnversion = preg_replace('/[^a-z0-9]/i', '.', $pf->getVersion()); |
$svntag = $pf->getName() . "-$svnversion"; |
$this->log(1, 'Tag the released code with "pear svntag ' . |
$main->getPackageFile() . '"'); |
$this->log(1, "(or set the SVN tag $svntag by hand)"); |
} |
} else { // this branch is executed for single packagefile packaging |
$gen = &$pf->getDefaultGenerator(); |
$tgzfile = $gen->toTgz($this, $compress); |
if (PEAR::isError($tgzfile)) { |
$this->log(0, $tgzfile->getMessage()); |
return $this->raiseError("Cannot package, errors in package"); |
} |
$dest_package = basename($tgzfile); |
$pkgdir = dirname($pkgfile); |
// TAR the Package ------------------------------------------- |
$this->log(1, "Package $dest_package done"); |
if (file_exists("$pkgdir/CVS/Root")) { |
$cvsversion = preg_replace('/[^a-z0-9]/i', '_', $pf->getVersion()); |
$cvstag = "RELEASE_$cvsversion"; |
$this->log(1, "Tag the released code with `pear cvstag $pkgfile'"); |
$this->log(1, "(or set the CVS tag $cvstag by hand)"); |
} elseif (file_exists("$pkgdir/.svn")) { |
$svnversion = preg_replace('/[^a-z0-9]/i', '.', $pf->getVersion()); |
$svntag = $pf->getName() . "-$svnversion"; |
$this->log(1, "Tag the released code with `pear svntag $pkgfile'"); |
$this->log(1, "(or set the SVN tag $svntag by hand)"); |
} |
} |
return $dest_package; |
} |
} |
/branches/v1.3-critias/bibliotheque/pear/PEAR/REST.php |
---|
New file |
0,0 → 1,496 |
<?php |
/** |
* PEAR_REST |
* |
* PHP versions 4 and 5 |
* |
* @category pear |
* @package PEAR |
* @author Greg Beaver <cellog@php.net> |
* @copyright 1997-2009 The Authors |
* @license http://opensource.org/licenses/bsd-license.php New BSD License |
* @link http://pear.php.net/package/PEAR |
* @since File available since Release 1.4.0a1 |
*/ |
/** |
* For downloading xml files |
*/ |
require_once 'PEAR.php'; |
require_once 'PEAR/XMLParser.php'; |
/** |
* Intelligently retrieve data, following hyperlinks if necessary, and re-directing |
* as well |
* @category pear |
* @package PEAR |
* @author Greg Beaver <cellog@php.net> |
* @copyright 1997-2009 The Authors |
* @license http://opensource.org/licenses/bsd-license.php New BSD License |
* @version Release: 1.10.1 |
* @link http://pear.php.net/package/PEAR |
* @since Class available since Release 1.4.0a1 |
*/ |
class PEAR_REST |
{ |
var $config; |
var $_options; |
function __construct(&$config, $options = array()) |
{ |
$this->config = &$config; |
$this->_options = $options; |
} |
/** |
* Retrieve REST data, but always retrieve the local cache if it is available. |
* |
* This is useful for elements that should never change, such as information on a particular |
* release |
* @param string full URL to this resource |
* @param array|false contents of the accept-encoding header |
* @param boolean if true, xml will be returned as a string, otherwise, xml will be |
* parsed using PEAR_XMLParser |
* @return string|array |
*/ |
function retrieveCacheFirst($url, $accept = false, $forcestring = false, $channel = false) |
{ |
$cachefile = $this->config->get('cache_dir') . DIRECTORY_SEPARATOR . |
md5($url) . 'rest.cachefile'; |
if (file_exists($cachefile)) { |
return unserialize(implode('', file($cachefile))); |
} |
return $this->retrieveData($url, $accept, $forcestring, $channel); |
} |
/** |
* Retrieve a remote REST resource |
* @param string full URL to this resource |
* @param array|false contents of the accept-encoding header |
* @param boolean if true, xml will be returned as a string, otherwise, xml will be |
* parsed using PEAR_XMLParser |
* @return string|array |
*/ |
function retrieveData($url, $accept = false, $forcestring = false, $channel = false) |
{ |
$cacheId = $this->getCacheId($url); |
if ($ret = $this->useLocalCache($url, $cacheId)) { |
return $ret; |
} |
$file = $trieddownload = false; |
if (!isset($this->_options['offline'])) { |
$trieddownload = true; |
$file = $this->downloadHttp($url, $cacheId ? $cacheId['lastChange'] : false, $accept, $channel); |
} |
if (PEAR::isError($file)) { |
if ($file->getCode() !== -9276) { |
return $file; |
} |
$trieddownload = false; |
$file = false; // use local copy if available on socket connect error |
} |
if (!$file) { |
$ret = $this->getCache($url); |
if (!PEAR::isError($ret) && $trieddownload) { |
// reset the age of the cache if the server says it was unmodified |
$result = $this->saveCache($url, $ret, null, true, $cacheId); |
if (PEAR::isError($result)) { |
return PEAR::raiseError($result->getMessage()); |
} |
} |
return $ret; |
} |
if (is_array($file)) { |
$headers = $file[2]; |
$lastmodified = $file[1]; |
$content = $file[0]; |
} else { |
$headers = array(); |
$lastmodified = false; |
$content = $file; |
} |
if ($forcestring) { |
$result = $this->saveCache($url, $content, $lastmodified, false, $cacheId); |
if (PEAR::isError($result)) { |
return PEAR::raiseError($result->getMessage()); |
} |
return $content; |
} |
if (isset($headers['content-type'])) { |
$content_type = explode(";", $headers['content-type']); |
$content_type = $content_type[0]; |
switch ($content_type) { |
case 'text/xml' : |
case 'application/xml' : |
case 'text/plain' : |
if ($content_type === 'text/plain') { |
$check = substr($content, 0, 5); |
if ($check !== '<?xml') { |
break; |
} |
} |
$parser = new PEAR_XMLParser; |
PEAR::pushErrorHandling(PEAR_ERROR_RETURN); |
$err = $parser->parse($content); |
PEAR::popErrorHandling(); |
if (PEAR::isError($err)) { |
return PEAR::raiseError('Invalid xml downloaded from "' . $url . '": ' . |
$err->getMessage()); |
} |
$content = $parser->getData(); |
case 'text/html' : |
default : |
// use it as a string |
} |
} else { |
// assume XML |
$parser = new PEAR_XMLParser; |
$parser->parse($content); |
$content = $parser->getData(); |
} |
$result = $this->saveCache($url, $content, $lastmodified, false, $cacheId); |
if (PEAR::isError($result)) { |
return PEAR::raiseError($result->getMessage()); |
} |
return $content; |
} |
function useLocalCache($url, $cacheid = null) |
{ |
if ($cacheid === null) { |
$cacheidfile = $this->config->get('cache_dir') . DIRECTORY_SEPARATOR . |
md5($url) . 'rest.cacheid'; |
if (!file_exists($cacheidfile)) { |
return false; |
} |
$cacheid = unserialize(implode('', file($cacheidfile))); |
} |
$cachettl = $this->config->get('cache_ttl'); |
// If cache is newer than $cachettl seconds, we use the cache! |
if (time() - $cacheid['age'] < $cachettl) { |
return $this->getCache($url); |
} |
return false; |
} |
function getCacheId($url) |
{ |
$cacheidfile = $this->config->get('cache_dir') . DIRECTORY_SEPARATOR . |
md5($url) . 'rest.cacheid'; |
if (!file_exists($cacheidfile)) { |
return false; |
} |
$ret = unserialize(implode('', file($cacheidfile))); |
return $ret; |
} |
function getCache($url) |
{ |
$cachefile = $this->config->get('cache_dir') . DIRECTORY_SEPARATOR . |
md5($url) . 'rest.cachefile'; |
if (!file_exists($cachefile)) { |
return PEAR::raiseError('No cached content available for "' . $url . '"'); |
} |
return unserialize(implode('', file($cachefile))); |
} |
/** |
* @param string full URL to REST resource |
* @param string original contents of the REST resource |
* @param array HTTP Last-Modified and ETag headers |
* @param bool if true, then the cache id file should be regenerated to |
* trigger a new time-to-live value |
*/ |
function saveCache($url, $contents, $lastmodified, $nochange = false, $cacheid = null) |
{ |
$cache_dir = $this->config->get('cache_dir'); |
$d = $cache_dir . DIRECTORY_SEPARATOR . md5($url); |
$cacheidfile = $d . 'rest.cacheid'; |
$cachefile = $d . 'rest.cachefile'; |
if (!is_dir($cache_dir)) { |
if (System::mkdir(array('-p', $cache_dir)) === false) { |
return PEAR::raiseError("The value of config option cache_dir ($cache_dir) is not a directory and attempts to create the directory failed."); |
} |
} |
if (!is_writeable($cache_dir)) { |
// If writing to the cache dir is not going to work, silently do nothing. |
// An ugly hack, but retains compat with PEAR 1.9.1 where many commands |
// work fine as non-root user (w/out write access to default cache dir). |
return true; |
} |
if ($cacheid === null && $nochange) { |
$cacheid = unserialize(implode('', file($cacheidfile))); |
} |
$idData = serialize(array( |
'age' => time(), |
'lastChange' => ($nochange ? $cacheid['lastChange'] : $lastmodified), |
)); |
$result = $this->saveCacheFile($cacheidfile, $idData); |
if (PEAR::isError($result)) { |
return $result; |
} elseif ($nochange) { |
return true; |
} |
$result = $this->saveCacheFile($cachefile, serialize($contents)); |
if (PEAR::isError($result)) { |
if (file_exists($cacheidfile)) { |
@unlink($cacheidfile); |
} |
return $result; |
} |
return true; |
} |
function saveCacheFile($file, $contents) |
{ |
$len = strlen($contents); |
$cachefile_fp = @fopen($file, 'xb'); // x is the O_CREAT|O_EXCL mode |
if ($cachefile_fp !== false) { // create file |
if (fwrite($cachefile_fp, $contents, $len) < $len) { |
fclose($cachefile_fp); |
return PEAR::raiseError("Could not write $file."); |
} |
} else { // update file |
$cachefile_fp = @fopen($file, 'r+b'); // do not truncate file |
if (!$cachefile_fp) { |
return PEAR::raiseError("Could not open $file for writing."); |
} |
if (OS_WINDOWS) { |
$not_symlink = !is_link($file); // see bug #18834 |
} else { |
$cachefile_lstat = lstat($file); |
$cachefile_fstat = fstat($cachefile_fp); |
$not_symlink = $cachefile_lstat['mode'] == $cachefile_fstat['mode'] |
&& $cachefile_lstat['ino'] == $cachefile_fstat['ino'] |
&& $cachefile_lstat['dev'] == $cachefile_fstat['dev'] |
&& $cachefile_fstat['nlink'] === 1; |
} |
if ($not_symlink) { |
ftruncate($cachefile_fp, 0); // NOW truncate |
if (fwrite($cachefile_fp, $contents, $len) < $len) { |
fclose($cachefile_fp); |
return PEAR::raiseError("Could not write $file."); |
} |
} else { |
fclose($cachefile_fp); |
$link = function_exists('readlink') ? readlink($file) : $file; |
return PEAR::raiseError('SECURITY ERROR: Will not write to ' . $file . ' as it is symlinked to ' . $link . ' - Possible symlink attack'); |
} |
} |
fclose($cachefile_fp); |
return true; |
} |
/** |
* Efficiently Download a file through HTTP. Returns downloaded file as a string in-memory |
* This is best used for small files |
* |
* If an HTTP proxy has been configured (http_proxy PEAR_Config |
* setting), the proxy will be used. |
* |
* @param string $url the URL to download |
* @param string $save_dir directory to save file in |
* @param false|string|array $lastmodified header values to check against for caching |
* use false to return the header values from this download |
* @param false|array $accept Accept headers to send |
* @return string|array Returns the contents of the downloaded file or a PEAR |
* error on failure. If the error is caused by |
* socket-related errors, the error object will |
* have the fsockopen error code available through |
* getCode(). If caching is requested, then return the header |
* values. |
* |
* @access public |
*/ |
function downloadHttp($url, $lastmodified = null, $accept = false, $channel = false) |
{ |
static $redirect = 0; |
// always reset , so we are clean case of error |
$wasredirect = $redirect; |
$redirect = 0; |
$info = parse_url($url); |
if (!isset($info['scheme']) || !in_array($info['scheme'], array('http', 'https'))) { |
return PEAR::raiseError('Cannot download non-http URL "' . $url . '"'); |
} |
if (!isset($info['host'])) { |
return PEAR::raiseError('Cannot download from non-URL "' . $url . '"'); |
} |
$host = isset($info['host']) ? $info['host'] : null; |
$port = isset($info['port']) ? $info['port'] : null; |
$path = isset($info['path']) ? $info['path'] : null; |
$schema = (isset($info['scheme']) && $info['scheme'] == 'https') ? 'https' : 'http'; |
$proxy_host = $proxy_port = $proxy_user = $proxy_pass = ''; |
if ($this->config->get('http_proxy')&& |
$proxy = parse_url($this->config->get('http_proxy')) |
) { |
$proxy_host = isset($proxy['host']) ? $proxy['host'] : null; |
if ($schema === 'https') { |
$proxy_host = 'ssl://' . $proxy_host; |
} |
$proxy_port = isset($proxy['port']) ? $proxy['port'] : 8080; |
$proxy_user = isset($proxy['user']) ? urldecode($proxy['user']) : null; |
$proxy_pass = isset($proxy['pass']) ? urldecode($proxy['pass']) : null; |
$proxy_schema = (isset($proxy['scheme']) && $proxy['scheme'] == 'https') ? 'https' : 'http'; |
} |
if (empty($port)) { |
$port = (isset($info['scheme']) && $info['scheme'] == 'https') ? 443 : 80; |
} |
if (isset($proxy['host'])) { |
$request = "GET $url HTTP/1.1\r\n"; |
} else { |
$request = "GET $path HTTP/1.1\r\n"; |
} |
$request .= "Host: $host\r\n"; |
$ifmodifiedsince = ''; |
if (is_array($lastmodified)) { |
if (isset($lastmodified['Last-Modified'])) { |
$ifmodifiedsince = 'If-Modified-Since: ' . $lastmodified['Last-Modified'] . "\r\n"; |
} |
if (isset($lastmodified['ETag'])) { |
$ifmodifiedsince .= "If-None-Match: $lastmodified[ETag]\r\n"; |
} |
} else { |
$ifmodifiedsince = ($lastmodified ? "If-Modified-Since: $lastmodified\r\n" : ''); |
} |
$request .= $ifmodifiedsince . |
"User-Agent: PEAR/1.10.1/PHP/" . PHP_VERSION . "\r\n"; |
$username = $this->config->get('username', null, $channel); |
$password = $this->config->get('password', null, $channel); |
if ($username && $password) { |
$tmp = base64_encode("$username:$password"); |
$request .= "Authorization: Basic $tmp\r\n"; |
} |
if ($proxy_host != '' && $proxy_user != '') { |
$request .= 'Proxy-Authorization: Basic ' . |
base64_encode($proxy_user . ':' . $proxy_pass) . "\r\n"; |
} |
if ($accept) { |
$request .= 'Accept: ' . implode(', ', $accept) . "\r\n"; |
} |
$request .= "Accept-Encoding:\r\n"; |
$request .= "Connection: close\r\n"; |
$request .= "\r\n"; |
if ($proxy_host != '') { |
$fp = @fsockopen($proxy_host, $proxy_port, $errno, $errstr, 15); |
if (!$fp) { |
return PEAR::raiseError("Connection to `$proxy_host:$proxy_port' failed: $errstr", -9276); |
} |
} else { |
if ($schema === 'https') { |
$host = 'ssl://' . $host; |
} |
$fp = @fsockopen($host, $port, $errno, $errstr); |
if (!$fp) { |
return PEAR::raiseError("Connection to `$host:$port' failed: $errstr", $errno); |
} |
} |
fwrite($fp, $request); |
$headers = array(); |
$reply = 0; |
while ($line = trim(fgets($fp, 1024))) { |
if (preg_match('/^([^:]+):\s+(.*)\s*\\z/', $line, $matches)) { |
$headers[strtolower($matches[1])] = trim($matches[2]); |
} elseif (preg_match('|^HTTP/1.[01] ([0-9]{3}) |', $line, $matches)) { |
$reply = (int)$matches[1]; |
if ($reply == 304 && ($lastmodified || ($lastmodified === false))) { |
return false; |
} |
if (!in_array($reply, array(200, 301, 302, 303, 305, 307))) { |
return PEAR::raiseError("File $schema://$host:$port$path not valid (received: $line)"); |
} |
} |
} |
if ($reply != 200) { |
if (!isset($headers['location'])) { |
return PEAR::raiseError("File $schema://$host:$port$path not valid (redirected but no location)"); |
} |
if ($wasredirect > 4) { |
return PEAR::raiseError("File $schema://$host:$port$path not valid (redirection looped more than 5 times)"); |
} |
$redirect = $wasredirect + 1; |
return $this->downloadHttp($headers['location'], $lastmodified, $accept, $channel); |
} |
$length = isset($headers['content-length']) ? $headers['content-length'] : -1; |
$data = ''; |
while ($chunk = @fread($fp, 8192)) { |
$data .= $chunk; |
} |
fclose($fp); |
if ($lastmodified === false || $lastmodified) { |
if (isset($headers['etag'])) { |
$lastmodified = array('ETag' => $headers['etag']); |
} |
if (isset($headers['last-modified'])) { |
if (is_array($lastmodified)) { |
$lastmodified['Last-Modified'] = $headers['last-modified']; |
} else { |
$lastmodified = $headers['last-modified']; |
} |
} |
return array($data, $lastmodified, $headers); |
} |
return $data; |
} |
} |
/branches/v1.3-critias/bibliotheque/pear/PEAR/XMLParser.php |
---|
New file |
0,0 → 1,247 |
<?php |
/** |
* PEAR_XMLParser |
* |
* PHP versions 4 and 5 |
* |
* @category pear |
* @package PEAR |
* @author Greg Beaver <cellog@php.net> |
* @author Stephan Schmidt (original XML_Unserializer code) |
* @copyright 1997-2009 The Authors |
* @license http://opensource.org/licenses/bsd-license New BSD License |
* @link http://pear.php.net/package/PEAR |
* @since File available since Release 1.4.0a1 |
*/ |
/** |
* Parser for any xml file |
* @category pear |
* @package PEAR |
* @author Greg Beaver <cellog@php.net> |
* @author Stephan Schmidt (original XML_Unserializer code) |
* @copyright 1997-2009 The Authors |
* @license http://opensource.org/licenses/bsd-license New BSD License |
* @version Release: 1.10.1 |
* @link http://pear.php.net/package/PEAR |
* @since Class available since Release 1.4.0a1 |
*/ |
class PEAR_XMLParser |
{ |
/** |
* unserilialized data |
* @var string $_serializedData |
*/ |
var $_unserializedData = null; |
/** |
* name of the root tag |
* @var string $_root |
*/ |
var $_root = null; |
/** |
* stack for all data that is found |
* @var array $_dataStack |
*/ |
var $_dataStack = array(); |
/** |
* stack for all values that are generated |
* @var array $_valStack |
*/ |
var $_valStack = array(); |
/** |
* current tag depth |
* @var int $_depth |
*/ |
var $_depth = 0; |
/** |
* The XML encoding to use |
* @var string $encoding |
*/ |
var $encoding = 'ISO-8859-1'; |
/** |
* @return array |
*/ |
function getData() |
{ |
return $this->_unserializedData; |
} |
/** |
* @param string xml content |
* @return true|PEAR_Error |
*/ |
function parse($data) |
{ |
if (!extension_loaded('xml')) { |
include_once 'PEAR.php'; |
return PEAR::raiseError("XML Extension not found", 1); |
} |
$this->_dataStack = $this->_valStack = array(); |
$this->_depth = 0; |
if ( |
strpos($data, 'encoding="UTF-8"') |
|| strpos($data, 'encoding="utf-8"') |
|| strpos($data, "encoding='UTF-8'") |
|| strpos($data, "encoding='utf-8'") |
) { |
$this->encoding = 'UTF-8'; |
} |
$xp = xml_parser_create($this->encoding); |
xml_parser_set_option($xp, XML_OPTION_CASE_FOLDING, 0); |
xml_set_object($xp, $this); |
xml_set_element_handler($xp, 'startHandler', 'endHandler'); |
xml_set_character_data_handler($xp, 'cdataHandler'); |
if (!xml_parse($xp, $data)) { |
$msg = xml_error_string(xml_get_error_code($xp)); |
$line = xml_get_current_line_number($xp); |
xml_parser_free($xp); |
include_once 'PEAR.php'; |
return PEAR::raiseError("XML Error: '$msg' on line '$line'", 2); |
} |
xml_parser_free($xp); |
return true; |
} |
/** |
* Start element handler for XML parser |
* |
* @access private |
* @param object $parser XML parser object |
* @param string $element XML element |
* @param array $attribs attributes of XML tag |
* @return void |
*/ |
function startHandler($parser, $element, $attribs) |
{ |
$this->_depth++; |
$this->_dataStack[$this->_depth] = null; |
$val = array( |
'name' => $element, |
'value' => null, |
'type' => 'string', |
'childrenKeys' => array(), |
'aggregKeys' => array() |
); |
if (count($attribs) > 0) { |
$val['children'] = array(); |
$val['type'] = 'array'; |
$val['children']['attribs'] = $attribs; |
} |
array_push($this->_valStack, $val); |
} |
/** |
* post-process data |
* |
* @param string $data |
* @param string $element element name |
*/ |
function postProcess($data, $element) |
{ |
return trim($data); |
} |
/** |
* End element handler for XML parser |
* |
* @access private |
* @param object XML parser object |
* @param string |
* @return void |
*/ |
function endHandler($parser, $element) |
{ |
$value = array_pop($this->_valStack); |
$data = $this->postProcess($this->_dataStack[$this->_depth], $element); |
// adjust type of the value |
switch (strtolower($value['type'])) { |
// unserialize an array |
case 'array': |
if ($data !== '') { |
$value['children']['_content'] = $data; |
} |
$value['value'] = isset($value['children']) ? $value['children'] : array(); |
break; |
/* |
* unserialize a null value |
*/ |
case 'null': |
$data = null; |
break; |
/* |
* unserialize any scalar value |
*/ |
default: |
settype($data, $value['type']); |
$value['value'] = $data; |
break; |
} |
$parent = array_pop($this->_valStack); |
if ($parent === null) { |
$this->_unserializedData = &$value['value']; |
$this->_root = &$value['name']; |
return true; |
} |
// parent has to be an array |
if (!isset($parent['children']) || !is_array($parent['children'])) { |
$parent['children'] = array(); |
if ($parent['type'] != 'array') { |
$parent['type'] = 'array'; |
} |
} |
if (!empty($value['name'])) { |
// there already has been a tag with this name |
if (in_array($value['name'], $parent['childrenKeys'])) { |
// no aggregate has been created for this tag |
if (!in_array($value['name'], $parent['aggregKeys'])) { |
if (isset($parent['children'][$value['name']])) { |
$parent['children'][$value['name']] = array($parent['children'][$value['name']]); |
} else { |
$parent['children'][$value['name']] = array(); |
} |
array_push($parent['aggregKeys'], $value['name']); |
} |
array_push($parent['children'][$value['name']], $value['value']); |
} else { |
$parent['children'][$value['name']] = &$value['value']; |
array_push($parent['childrenKeys'], $value['name']); |
} |
} else { |
array_push($parent['children'],$value['value']); |
} |
array_push($this->_valStack, $parent); |
$this->_depth--; |
} |
/** |
* Handler for character data |
* |
* @access private |
* @param object XML parser object |
* @param string CDATA |
* @return void |
*/ |
function cdataHandler($parser, $cdata) |
{ |
$this->_dataStack[$this->_depth] .= $cdata; |
} |
} |
/branches/v1.3-critias/bibliotheque/pear/PEAR/Command.php |
---|
New file |
0,0 → 1,389 |
<?php |
/** |
* PEAR_Command, command pattern class |
* |
* PHP versions 4 and 5 |
* |
* @category pear |
* @package PEAR |
* @author Stig Bakken <ssb@php.net> |
* @author Greg Beaver <cellog@php.net> |
* @copyright 1997-2009 The Authors |
* @license http://opensource.org/licenses/bsd-license.php New BSD License |
* @link http://pear.php.net/package/PEAR |
* @since File available since Release 0.1 |
*/ |
/** |
* Needed for error handling |
*/ |
require_once 'PEAR.php'; |
require_once 'PEAR/Frontend.php'; |
require_once 'PEAR/XMLParser.php'; |
/** |
* List of commands and what classes they are implemented in. |
* @var array command => implementing class |
*/ |
$GLOBALS['_PEAR_Command_commandlist'] = array(); |
/** |
* List of commands and their descriptions |
* @var array command => description |
*/ |
$GLOBALS['_PEAR_Command_commanddesc'] = array(); |
/** |
* List of shortcuts to common commands. |
* @var array shortcut => command |
*/ |
$GLOBALS['_PEAR_Command_shortcuts'] = array(); |
/** |
* Array of command objects |
* @var array class => object |
*/ |
$GLOBALS['_PEAR_Command_objects'] = array(); |
/** |
* PEAR command class, a simple factory class for administrative |
* commands. |
* |
* How to implement command classes: |
* |
* - The class must be called PEAR_Command_Nnn, installed in the |
* "PEAR/Common" subdir, with a method called getCommands() that |
* returns an array of the commands implemented by the class (see |
* PEAR/Command/Install.php for an example). |
* |
* - The class must implement a run() function that is called with three |
* params: |
* |
* (string) command name |
* (array) assoc array with options, freely defined by each |
* command, for example: |
* array('force' => true) |
* (array) list of the other parameters |
* |
* The run() function returns a PEAR_CommandResponse object. Use |
* these methods to get information: |
* |
* int getStatus() Returns PEAR_COMMAND_(SUCCESS|FAILURE|PARTIAL) |
* *_PARTIAL means that you need to issue at least |
* one more command to complete the operation |
* (used for example for validation steps). |
* |
* string getMessage() Returns a message for the user. Remember, |
* no HTML or other interface-specific markup. |
* |
* If something unexpected happens, run() returns a PEAR error. |
* |
* - DON'T OUTPUT ANYTHING! Return text for output instead. |
* |
* - DON'T USE HTML! The text you return will be used from both Gtk, |
* web and command-line interfaces, so for now, keep everything to |
* plain text. |
* |
* - DON'T USE EXIT OR DIE! Always use pear errors. From static |
* classes do PEAR::raiseError(), from other classes do |
* $this->raiseError(). |
* @category pear |
* @package PEAR |
* @author Stig Bakken <ssb@php.net> |
* @author Greg Beaver <cellog@php.net> |
* @copyright 1997-2009 The Authors |
* @license http://opensource.org/licenses/bsd-license.php New BSD License |
* @version Release: 1.10.1 |
* @link http://pear.php.net/package/PEAR |
* @since Class available since Release 0.1 |
*/ |
class PEAR_Command |
{ |
// {{{ factory() |
/** |
* Get the right object for executing a command. |
* |
* @param string $command The name of the command |
* @param object $config Instance of PEAR_Config object |
* |
* @return object the command object or a PEAR error |
*/ |
public static function &factory($command, &$config) |
{ |
if (empty($GLOBALS['_PEAR_Command_commandlist'])) { |
PEAR_Command::registerCommands(); |
} |
if (isset($GLOBALS['_PEAR_Command_shortcuts'][$command])) { |
$command = $GLOBALS['_PEAR_Command_shortcuts'][$command]; |
} |
if (!isset($GLOBALS['_PEAR_Command_commandlist'][$command])) { |
$a = PEAR::raiseError("unknown command `$command'"); |
return $a; |
} |
$class = $GLOBALS['_PEAR_Command_commandlist'][$command]; |
if (!class_exists($class)) { |
require_once $GLOBALS['_PEAR_Command_objects'][$class]; |
} |
if (!class_exists($class)) { |
$a = PEAR::raiseError("unknown command `$command'"); |
return $a; |
} |
$ui =& PEAR_Command::getFrontendObject(); |
$obj = new $class($ui, $config); |
return $obj; |
} |
// }}} |
// {{{ & getObject() |
public static function &getObject($command) |
{ |
$class = $GLOBALS['_PEAR_Command_commandlist'][$command]; |
if (!class_exists($class)) { |
require_once $GLOBALS['_PEAR_Command_objects'][$class]; |
} |
if (!class_exists($class)) { |
return PEAR::raiseError("unknown command `$command'"); |
} |
$ui =& PEAR_Command::getFrontendObject(); |
$config = &PEAR_Config::singleton(); |
$obj = new $class($ui, $config); |
return $obj; |
} |
// }}} |
// {{{ & getFrontendObject() |
/** |
* Get instance of frontend object. |
* |
* @return object|PEAR_Error |
*/ |
public static function &getFrontendObject() |
{ |
$a = &PEAR_Frontend::singleton(); |
return $a; |
} |
// }}} |
// {{{ & setFrontendClass() |
/** |
* Load current frontend class. |
* |
* @param string $uiclass Name of class implementing the frontend |
* |
* @return object the frontend object, or a PEAR error |
*/ |
public static function &setFrontendClass($uiclass) |
{ |
$a = &PEAR_Frontend::setFrontendClass($uiclass); |
return $a; |
} |
// }}} |
// {{{ setFrontendType() |
/** |
* Set current frontend. |
* |
* @param string $uitype Name of the frontend type (for example "CLI") |
* |
* @return object the frontend object, or a PEAR error |
*/ |
public static function setFrontendType($uitype) |
{ |
$uiclass = 'PEAR_Frontend_' . $uitype; |
return PEAR_Command::setFrontendClass($uiclass); |
} |
// }}} |
// {{{ registerCommands() |
/** |
* Scan through the Command directory looking for classes |
* and see what commands they implement. |
* |
* @param bool (optional) if FALSE (default), the new list of |
* commands should replace the current one. If TRUE, |
* new entries will be merged with old. |
* |
* @param string (optional) where (what directory) to look for |
* classes, defaults to the Command subdirectory of |
* the directory from where this file (__FILE__) is |
* included. |
* |
* @return bool TRUE on success, a PEAR error on failure |
*/ |
public static function registerCommands($merge = false, $dir = null) |
{ |
$parser = new PEAR_XMLParser; |
if ($dir === null) { |
$dir = dirname(__FILE__) . '/Command'; |
} |
if (!is_dir($dir)) { |
return PEAR::raiseError("registerCommands: opendir($dir) '$dir' does not exist or is not a directory"); |
} |
$dp = @opendir($dir); |
if (empty($dp)) { |
return PEAR::raiseError("registerCommands: opendir($dir) failed"); |
} |
if (!$merge) { |
$GLOBALS['_PEAR_Command_commandlist'] = array(); |
} |
while ($file = readdir($dp)) { |
if ($file{0} == '.' || substr($file, -4) != '.xml') { |
continue; |
} |
$f = substr($file, 0, -4); |
$class = "PEAR_Command_" . $f; |
// List of commands |
if (empty($GLOBALS['_PEAR_Command_objects'][$class])) { |
$GLOBALS['_PEAR_Command_objects'][$class] = "$dir/" . $f . '.php'; |
} |
$parser->parse(file_get_contents("$dir/$file")); |
$implements = $parser->getData(); |
foreach ($implements as $command => $desc) { |
if ($command == 'attribs') { |
continue; |
} |
if (isset($GLOBALS['_PEAR_Command_commandlist'][$command])) { |
return PEAR::raiseError('Command "' . $command . '" already registered in ' . |
'class "' . $GLOBALS['_PEAR_Command_commandlist'][$command] . '"'); |
} |
$GLOBALS['_PEAR_Command_commandlist'][$command] = $class; |
$GLOBALS['_PEAR_Command_commanddesc'][$command] = $desc['summary']; |
if (isset($desc['shortcut'])) { |
$shortcut = $desc['shortcut']; |
if (isset($GLOBALS['_PEAR_Command_shortcuts'][$shortcut])) { |
return PEAR::raiseError('Command shortcut "' . $shortcut . '" already ' . |
'registered to command "' . $command . '" in class "' . |
$GLOBALS['_PEAR_Command_commandlist'][$command] . '"'); |
} |
$GLOBALS['_PEAR_Command_shortcuts'][$shortcut] = $command; |
} |
if (isset($desc['options']) && $desc['options']) { |
foreach ($desc['options'] as $oname => $option) { |
if (isset($option['shortopt']) && strlen($option['shortopt']) > 1) { |
return PEAR::raiseError('Option "' . $oname . '" short option "' . |
$option['shortopt'] . '" must be ' . |
'only 1 character in Command "' . $command . '" in class "' . |
$class . '"'); |
} |
} |
} |
} |
} |
ksort($GLOBALS['_PEAR_Command_shortcuts']); |
ksort($GLOBALS['_PEAR_Command_commandlist']); |
@closedir($dp); |
return true; |
} |
// }}} |
// {{{ getCommands() |
/** |
* Get the list of currently supported commands, and what |
* classes implement them. |
* |
* @return array command => implementing class |
*/ |
public static function getCommands() |
{ |
if (empty($GLOBALS['_PEAR_Command_commandlist'])) { |
PEAR_Command::registerCommands(); |
} |
return $GLOBALS['_PEAR_Command_commandlist']; |
} |
// }}} |
// {{{ getShortcuts() |
/** |
* Get the list of command shortcuts. |
* |
* @return array shortcut => command |
*/ |
public static function getShortcuts() |
{ |
if (empty($GLOBALS['_PEAR_Command_shortcuts'])) { |
PEAR_Command::registerCommands(); |
} |
return $GLOBALS['_PEAR_Command_shortcuts']; |
} |
// }}} |
// {{{ getGetoptArgs() |
/** |
* Compiles arguments for getopt. |
* |
* @param string $command command to get optstring for |
* @param string $short_args (reference) short getopt format |
* @param array $long_args (reference) long getopt format |
* |
* @return void |
*/ |
public static function getGetoptArgs($command, &$short_args, &$long_args) |
{ |
if (empty($GLOBALS['_PEAR_Command_commandlist'])) { |
PEAR_Command::registerCommands(); |
} |
if (isset($GLOBALS['_PEAR_Command_shortcuts'][$command])) { |
$command = $GLOBALS['_PEAR_Command_shortcuts'][$command]; |
} |
if (!isset($GLOBALS['_PEAR_Command_commandlist'][$command])) { |
return null; |
} |
$obj = &PEAR_Command::getObject($command); |
return $obj->getGetoptArgs($command, $short_args, $long_args); |
} |
// }}} |
// {{{ getDescription() |
/** |
* Get description for a command. |
* |
* @param string $command Name of the command |
* |
* @return string command description |
*/ |
public static function getDescription($command) |
{ |
if (!isset($GLOBALS['_PEAR_Command_commanddesc'][$command])) { |
return null; |
} |
return $GLOBALS['_PEAR_Command_commanddesc'][$command]; |
} |
// }}} |
// {{{ getHelp() |
/** |
* Get help for command. |
* |
* @param string $command Name of the command to return help for |
*/ |
public static function getHelp($command) |
{ |
$cmds = PEAR_Command::getCommands(); |
if (isset($GLOBALS['_PEAR_Command_shortcuts'][$command])) { |
$command = $GLOBALS['_PEAR_Command_shortcuts'][$command]; |
} |
if (isset($cmds[$command])) { |
$obj = &PEAR_Command::getObject($command); |
return $obj->getHelp($command); |
} |
return false; |
} |
// }}} |
} |
/branches/v1.3-critias/bibliotheque/pear/PEAR/Frontend.php |
---|
New file |
0,0 → 1,223 |
<?php |
/** |
* PEAR_Frontend, the singleton-based frontend for user input/output |
* |
* PHP versions 4 and 5 |
* |
* @category pear |
* @package PEAR |
* @author Greg Beaver <cellog@php.net> |
* @copyright 1997-2009 The Authors |
* @license http://opensource.org/licenses/bsd-license.php New BSD License |
* @link http://pear.php.net/package/PEAR |
* @since File available since Release 1.4.0a1 |
*/ |
/** |
* Include error handling |
*/ |
//require_once 'PEAR.php'; |
/** |
* Which user interface class is being used. |
* @var string class name |
*/ |
$GLOBALS['_PEAR_FRONTEND_CLASS'] = 'PEAR_Frontend_CLI'; |
/** |
* Instance of $_PEAR_Command_uiclass. |
* @var object |
*/ |
$GLOBALS['_PEAR_FRONTEND_SINGLETON'] = null; |
/** |
* Singleton-based frontend for PEAR user input/output |
* |
* @category pear |
* @package PEAR |
* @author Greg Beaver <cellog@php.net> |
* @copyright 1997-2009 The Authors |
* @license http://opensource.org/licenses/bsd-license.php New BSD License |
* @version Release: 1.10.1 |
* @link http://pear.php.net/package/PEAR |
* @since Class available since Release 1.4.0a1 |
*/ |
class PEAR_Frontend extends PEAR |
{ |
/** |
* Retrieve the frontend object |
* @return PEAR_Frontend_CLI|PEAR_Frontend_Web|PEAR_Frontend_Gtk |
*/ |
public static function &singleton($type = null) |
{ |
if ($type === null) { |
if (!isset($GLOBALS['_PEAR_FRONTEND_SINGLETON'])) { |
$a = false; |
return $a; |
} |
return $GLOBALS['_PEAR_FRONTEND_SINGLETON']; |
} |
$a = PEAR_Frontend::setFrontendClass($type); |
return $a; |
} |
/** |
* Set the frontend class that will be used by calls to {@link singleton()} |
* |
* Frontends are expected to conform to the PEAR naming standard of |
* _ => DIRECTORY_SEPARATOR (PEAR_Frontend_CLI is in PEAR/Frontend/CLI.php) |
* @param string $uiclass full class name |
* @return PEAR_Frontend |
*/ |
public static function &setFrontendClass($uiclass) |
{ |
if (is_object($GLOBALS['_PEAR_FRONTEND_SINGLETON']) && |
is_a($GLOBALS['_PEAR_FRONTEND_SINGLETON'], $uiclass)) { |
return $GLOBALS['_PEAR_FRONTEND_SINGLETON']; |
} |
if (!class_exists($uiclass)) { |
$file = str_replace('_', '/', $uiclass) . '.php'; |
if (PEAR_Frontend::isIncludeable($file)) { |
include_once $file; |
} |
} |
if (class_exists($uiclass)) { |
$obj = new $uiclass; |
// quick test to see if this class implements a few of the most |
// important frontend methods |
if (is_a($obj, 'PEAR_Frontend')) { |
$GLOBALS['_PEAR_FRONTEND_SINGLETON'] = &$obj; |
$GLOBALS['_PEAR_FRONTEND_CLASS'] = $uiclass; |
return $obj; |
} |
$err = PEAR::raiseError("not a frontend class: $uiclass"); |
return $err; |
} |
$err = PEAR::raiseError("no such class: $uiclass"); |
return $err; |
} |
/** |
* Set the frontend class that will be used by calls to {@link singleton()} |
* |
* Frontends are expected to be a descendant of PEAR_Frontend |
* @param PEAR_Frontend |
* @return PEAR_Frontend |
*/ |
public static function &setFrontendObject($uiobject) |
{ |
if (is_object($GLOBALS['_PEAR_FRONTEND_SINGLETON']) && |
is_a($GLOBALS['_PEAR_FRONTEND_SINGLETON'], get_class($uiobject))) { |
return $GLOBALS['_PEAR_FRONTEND_SINGLETON']; |
} |
if (!is_a($uiobject, 'PEAR_Frontend')) { |
$err = PEAR::raiseError('not a valid frontend class: (' . |
get_class($uiobject) . ')'); |
return $err; |
} |
$GLOBALS['_PEAR_FRONTEND_SINGLETON'] = &$uiobject; |
$GLOBALS['_PEAR_FRONTEND_CLASS'] = get_class($uiobject); |
return $uiobject; |
} |
/** |
* @param string $path relative or absolute include path |
* @return boolean |
*/ |
public static function isIncludeable($path) |
{ |
if (file_exists($path) && is_readable($path)) { |
return true; |
} |
$fp = @fopen($path, 'r', true); |
if ($fp) { |
fclose($fp); |
return true; |
} |
return false; |
} |
/** |
* @param PEAR_Config |
*/ |
function setConfig(&$config) |
{ |
} |
/** |
* This can be overridden to allow session-based temporary file management |
* |
* By default, all files are deleted at the end of a session. The web installer |
* needs to be able to sustain a list over many sessions in order to support |
* user interaction with install scripts |
*/ |
function addTempFile($file) |
{ |
$GLOBALS['_PEAR_Common_tempfiles'][] = $file; |
} |
/** |
* Log an action |
* |
* @param string $msg the message to log |
* @param boolean $append_crlf |
* @return boolean true |
* @abstract |
*/ |
function log($msg, $append_crlf = true) |
{ |
} |
/** |
* Run a post-installation script |
* |
* @param array $scripts array of post-install scripts |
* @abstract |
*/ |
function runPostinstallScripts(&$scripts) |
{ |
} |
/** |
* Display human-friendly output formatted depending on the |
* $command parameter. |
* |
* This should be able to handle basic output data with no command |
* @param mixed $data data structure containing the information to display |
* @param string $command command from which this method was called |
* @abstract |
*/ |
function outputData($data, $command = '_default') |
{ |
} |
/** |
* Display a modal form dialog and return the given input |
* |
* A frontend that requires multiple requests to retrieve and process |
* data must take these needs into account, and implement the request |
* handling code. |
* @param string $command command from which this method was called |
* @param array $prompts associative array. keys are the input field names |
* and values are the description |
* @param array $types array of input field types (text, password, |
* etc.) keys have to be the same like in $prompts |
* @param array $defaults array of default values. again keys have |
* to be the same like in $prompts. Do not depend |
* on a default value being set. |
* @return array input sent by the user |
* @abstract |
*/ |
function userDialog($command, $prompts, $types = array(), $defaults = array()) |
{ |
} |
} |
/branches/v1.3-critias/bibliotheque/pear/PEAR/ErrorStack.php |
---|
New file |
0,0 → 1,979 |
<?php |
/** |
* Error Stack Implementation |
* |
* This is an incredibly simple implementation of a very complex error handling |
* facility. It contains the ability |
* to track multiple errors from multiple packages simultaneously. In addition, |
* it can track errors of many levels, save data along with the error, context |
* information such as the exact file, line number, class and function that |
* generated the error, and if necessary, it can raise a traditional PEAR_Error. |
* It has built-in support for PEAR::Log, to log errors as they occur |
* |
* Since version 0.2alpha, it is also possible to selectively ignore errors, |
* through the use of an error callback, see {@link pushCallback()} |
* |
* Since version 0.3alpha, it is possible to specify the exception class |
* returned from {@link push()} |
* |
* Since version PEAR1.3.2, ErrorStack no longer instantiates an exception class. This can |
* still be done quite handily in an error callback or by manipulating the returned array |
* @category Debugging |
* @package PEAR_ErrorStack |
* @author Greg Beaver <cellog@php.net> |
* @copyright 2004-2008 Greg Beaver |
* @license http://opensource.org/licenses/bsd-license.php New BSD License |
* @link http://pear.php.net/package/PEAR_ErrorStack |
*/ |
/** |
* Singleton storage |
* |
* Format: |
* <pre> |
* array( |
* 'package1' => PEAR_ErrorStack object, |
* 'package2' => PEAR_ErrorStack object, |
* ... |
* ) |
* </pre> |
* @access private |
* @global array $GLOBALS['_PEAR_ERRORSTACK_SINGLETON'] |
*/ |
$GLOBALS['_PEAR_ERRORSTACK_SINGLETON'] = array(); |
/** |
* Global error callback (default) |
* |
* This is only used if set to non-false. * is the default callback for |
* all packages, whereas specific packages may set a default callback |
* for all instances, regardless of whether they are a singleton or not. |
* |
* To exclude non-singletons, only set the local callback for the singleton |
* @see PEAR_ErrorStack::setDefaultCallback() |
* @access private |
* @global array $GLOBALS['_PEAR_ERRORSTACK_DEFAULT_CALLBACK'] |
*/ |
$GLOBALS['_PEAR_ERRORSTACK_DEFAULT_CALLBACK'] = array( |
'*' => false, |
); |
/** |
* Global Log object (default) |
* |
* This is only used if set to non-false. Use to set a default log object for |
* all stacks, regardless of instantiation order or location |
* @see PEAR_ErrorStack::setDefaultLogger() |
* @access private |
* @global array $GLOBALS['_PEAR_ERRORSTACK_DEFAULT_LOGGER'] |
*/ |
$GLOBALS['_PEAR_ERRORSTACK_DEFAULT_LOGGER'] = false; |
/** |
* Global Overriding Callback |
* |
* This callback will override any error callbacks that specific loggers have set. |
* Use with EXTREME caution |
* @see PEAR_ErrorStack::staticPushCallback() |
* @access private |
* @global array $GLOBALS['_PEAR_ERRORSTACK_DEFAULT_LOGGER'] |
*/ |
$GLOBALS['_PEAR_ERRORSTACK_OVERRIDE_CALLBACK'] = array(); |
/**#@+ |
* One of four possible return values from the error Callback |
* @see PEAR_ErrorStack::_errorCallback() |
*/ |
/** |
* If this is returned, then the error will be both pushed onto the stack |
* and logged. |
*/ |
define('PEAR_ERRORSTACK_PUSHANDLOG', 1); |
/** |
* If this is returned, then the error will only be pushed onto the stack, |
* and not logged. |
*/ |
define('PEAR_ERRORSTACK_PUSH', 2); |
/** |
* If this is returned, then the error will only be logged, but not pushed |
* onto the error stack. |
*/ |
define('PEAR_ERRORSTACK_LOG', 3); |
/** |
* If this is returned, then the error is completely ignored. |
*/ |
define('PEAR_ERRORSTACK_IGNORE', 4); |
/** |
* If this is returned, then the error is logged and die() is called. |
*/ |
define('PEAR_ERRORSTACK_DIE', 5); |
/**#@-*/ |
/** |
* Error code for an attempt to instantiate a non-class as a PEAR_ErrorStack in |
* the singleton method. |
*/ |
define('PEAR_ERRORSTACK_ERR_NONCLASS', 1); |
/** |
* Error code for an attempt to pass an object into {@link PEAR_ErrorStack::getMessage()} |
* that has no __toString() method |
*/ |
define('PEAR_ERRORSTACK_ERR_OBJTOSTRING', 2); |
/** |
* Error Stack Implementation |
* |
* Usage: |
* <code> |
* // global error stack |
* $global_stack = &PEAR_ErrorStack::singleton('MyPackage'); |
* // local error stack |
* $local_stack = new PEAR_ErrorStack('MyPackage'); |
* </code> |
* @author Greg Beaver <cellog@php.net> |
* @version 1.10.1 |
* @package PEAR_ErrorStack |
* @category Debugging |
* @copyright 2004-2008 Greg Beaver |
* @license http://opensource.org/licenses/bsd-license.php New BSD License |
* @link http://pear.php.net/package/PEAR_ErrorStack |
*/ |
class PEAR_ErrorStack { |
/** |
* Errors are stored in the order that they are pushed on the stack. |
* @since 0.4alpha Errors are no longer organized by error level. |
* This renders pop() nearly unusable, and levels could be more easily |
* handled in a callback anyway |
* @var array |
* @access private |
*/ |
var $_errors = array(); |
/** |
* Storage of errors by level. |
* |
* Allows easy retrieval and deletion of only errors from a particular level |
* @since PEAR 1.4.0dev |
* @var array |
* @access private |
*/ |
var $_errorsByLevel = array(); |
/** |
* Package name this error stack represents |
* @var string |
* @access protected |
*/ |
var $_package; |
/** |
* Determines whether a PEAR_Error is thrown upon every error addition |
* @var boolean |
* @access private |
*/ |
var $_compat = false; |
/** |
* If set to a valid callback, this will be used to generate the error |
* message from the error code, otherwise the message passed in will be |
* used |
* @var false|string|array |
* @access private |
*/ |
var $_msgCallback = false; |
/** |
* If set to a valid callback, this will be used to generate the error |
* context for an error. For PHP-related errors, this will be a file |
* and line number as retrieved from debug_backtrace(), but can be |
* customized for other purposes. The error might actually be in a separate |
* configuration file, or in a database query. |
* @var false|string|array |
* @access protected |
*/ |
var $_contextCallback = false; |
/** |
* If set to a valid callback, this will be called every time an error |
* is pushed onto the stack. The return value will be used to determine |
* whether to allow an error to be pushed or logged. |
* |
* The return value must be one an PEAR_ERRORSTACK_* constant |
* @see PEAR_ERRORSTACK_PUSHANDLOG, PEAR_ERRORSTACK_PUSH, PEAR_ERRORSTACK_LOG |
* @var false|string|array |
* @access protected |
*/ |
var $_errorCallback = array(); |
/** |
* PEAR::Log object for logging errors |
* @var false|Log |
* @access protected |
*/ |
var $_logger = false; |
/** |
* Error messages - designed to be overridden |
* @var array |
* @abstract |
*/ |
var $_errorMsgs = array(); |
/** |
* Set up a new error stack |
* |
* @param string $package name of the package this error stack represents |
* @param callback $msgCallback callback used for error message generation |
* @param callback $contextCallback callback used for context generation, |
* defaults to {@link getFileLine()} |
* @param boolean $throwPEAR_Error |
*/ |
function __construct($package, $msgCallback = false, $contextCallback = false, |
$throwPEAR_Error = false) |
{ |
$this->_package = $package; |
$this->setMessageCallback($msgCallback); |
$this->setContextCallback($contextCallback); |
$this->_compat = $throwPEAR_Error; |
} |
/** |
* Return a single error stack for this package. |
* |
* Note that all parameters are ignored if the stack for package $package |
* has already been instantiated |
* @param string $package name of the package this error stack represents |
* @param callback $msgCallback callback used for error message generation |
* @param callback $contextCallback callback used for context generation, |
* defaults to {@link getFileLine()} |
* @param boolean $throwPEAR_Error |
* @param string $stackClass class to instantiate |
* |
* @return PEAR_ErrorStack |
*/ |
public static function &singleton( |
$package, $msgCallback = false, $contextCallback = false, |
$throwPEAR_Error = false, $stackClass = 'PEAR_ErrorStack' |
) { |
if (isset($GLOBALS['_PEAR_ERRORSTACK_SINGLETON'][$package])) { |
return $GLOBALS['_PEAR_ERRORSTACK_SINGLETON'][$package]; |
} |
if (!class_exists($stackClass)) { |
if (function_exists('debug_backtrace')) { |
$trace = debug_backtrace(); |
} |
PEAR_ErrorStack::staticPush('PEAR_ErrorStack', PEAR_ERRORSTACK_ERR_NONCLASS, |
'exception', array('stackclass' => $stackClass), |
'stack class "%stackclass%" is not a valid class name (should be like PEAR_ErrorStack)', |
false, $trace); |
} |
$GLOBALS['_PEAR_ERRORSTACK_SINGLETON'][$package] = |
new $stackClass($package, $msgCallback, $contextCallback, $throwPEAR_Error); |
return $GLOBALS['_PEAR_ERRORSTACK_SINGLETON'][$package]; |
} |
/** |
* Internal error handler for PEAR_ErrorStack class |
* |
* Dies if the error is an exception (and would have died anyway) |
* @access private |
*/ |
function _handleError($err) |
{ |
if ($err['level'] == 'exception') { |
$message = $err['message']; |
if (isset($_SERVER['REQUEST_URI'])) { |
echo '<br />'; |
} else { |
echo "\n"; |
} |
var_dump($err['context']); |
die($message); |
} |
} |
/** |
* Set up a PEAR::Log object for all error stacks that don't have one |
* @param Log $log |
*/ |
public static function setDefaultLogger(&$log) |
{ |
if (is_object($log) && method_exists($log, 'log') ) { |
$GLOBALS['_PEAR_ERRORSTACK_DEFAULT_LOGGER'] = &$log; |
} elseif (is_callable($log)) { |
$GLOBALS['_PEAR_ERRORSTACK_DEFAULT_LOGGER'] = &$log; |
} |
} |
/** |
* Set up a PEAR::Log object for this error stack |
* @param Log $log |
*/ |
function setLogger(&$log) |
{ |
if (is_object($log) && method_exists($log, 'log') ) { |
$this->_logger = &$log; |
} elseif (is_callable($log)) { |
$this->_logger = &$log; |
} |
} |
/** |
* Set an error code => error message mapping callback |
* |
* This method sets the callback that can be used to generate error |
* messages for any instance |
* @param array|string Callback function/method |
*/ |
function setMessageCallback($msgCallback) |
{ |
if (!$msgCallback) { |
$this->_msgCallback = array(&$this, 'getErrorMessage'); |
} else { |
if (is_callable($msgCallback)) { |
$this->_msgCallback = $msgCallback; |
} |
} |
} |
/** |
* Get an error code => error message mapping callback |
* |
* This method returns the current callback that can be used to generate error |
* messages |
* @return array|string|false Callback function/method or false if none |
*/ |
function getMessageCallback() |
{ |
return $this->_msgCallback; |
} |
/** |
* Sets a default callback to be used by all error stacks |
* |
* This method sets the callback that can be used to generate error |
* messages for a singleton |
* @param array|string Callback function/method |
* @param string Package name, or false for all packages |
*/ |
public static function setDefaultCallback($callback = false, $package = false) |
{ |
if (!is_callable($callback)) { |
$callback = false; |
} |
$package = $package ? $package : '*'; |
$GLOBALS['_PEAR_ERRORSTACK_DEFAULT_CALLBACK'][$package] = $callback; |
} |
/** |
* Set a callback that generates context information (location of error) for an error stack |
* |
* This method sets the callback that can be used to generate context |
* information for an error. Passing in NULL will disable context generation |
* and remove the expensive call to debug_backtrace() |
* @param array|string|null Callback function/method |
*/ |
function setContextCallback($contextCallback) |
{ |
if ($contextCallback === null) { |
return $this->_contextCallback = false; |
} |
if (!$contextCallback) { |
$this->_contextCallback = array(&$this, 'getFileLine'); |
} else { |
if (is_callable($contextCallback)) { |
$this->_contextCallback = $contextCallback; |
} |
} |
} |
/** |
* Set an error Callback |
* If set to a valid callback, this will be called every time an error |
* is pushed onto the stack. The return value will be used to determine |
* whether to allow an error to be pushed or logged. |
* |
* The return value must be one of the ERRORSTACK_* constants. |
* |
* This functionality can be used to emulate PEAR's pushErrorHandling, and |
* the PEAR_ERROR_CALLBACK mode, without affecting the integrity of |
* the error stack or logging |
* @see PEAR_ERRORSTACK_PUSHANDLOG, PEAR_ERRORSTACK_PUSH, PEAR_ERRORSTACK_LOG |
* @see popCallback() |
* @param string|array $cb |
*/ |
function pushCallback($cb) |
{ |
array_push($this->_errorCallback, $cb); |
} |
/** |
* Remove a callback from the error callback stack |
* @see pushCallback() |
* @return array|string|false |
*/ |
function popCallback() |
{ |
if (!count($this->_errorCallback)) { |
return false; |
} |
return array_pop($this->_errorCallback); |
} |
/** |
* Set a temporary overriding error callback for every package error stack |
* |
* Use this to temporarily disable all existing callbacks (can be used |
* to emulate the @ operator, for instance) |
* @see PEAR_ERRORSTACK_PUSHANDLOG, PEAR_ERRORSTACK_PUSH, PEAR_ERRORSTACK_LOG |
* @see staticPopCallback(), pushCallback() |
* @param string|array $cb |
*/ |
public static function staticPushCallback($cb) |
{ |
array_push($GLOBALS['_PEAR_ERRORSTACK_OVERRIDE_CALLBACK'], $cb); |
} |
/** |
* Remove a temporary overriding error callback |
* @see staticPushCallback() |
* @return array|string|false |
*/ |
public static function staticPopCallback() |
{ |
$ret = array_pop($GLOBALS['_PEAR_ERRORSTACK_OVERRIDE_CALLBACK']); |
if (!is_array($GLOBALS['_PEAR_ERRORSTACK_OVERRIDE_CALLBACK'])) { |
$GLOBALS['_PEAR_ERRORSTACK_OVERRIDE_CALLBACK'] = array(); |
} |
return $ret; |
} |
/** |
* Add an error to the stack |
* |
* If the message generator exists, it is called with 2 parameters. |
* - the current Error Stack object |
* - an array that is in the same format as an error. Available indices |
* are 'code', 'package', 'time', 'params', 'level', and 'context' |
* |
* Next, if the error should contain context information, this is |
* handled by the context grabbing method. |
* Finally, the error is pushed onto the proper error stack |
* @param int $code Package-specific error code |
* @param string $level Error level. This is NOT spell-checked |
* @param array $params associative array of error parameters |
* @param string $msg Error message, or a portion of it if the message |
* is to be generated |
* @param array $repackage If this error re-packages an error pushed by |
* another package, place the array returned from |
* {@link pop()} in this parameter |
* @param array $backtrace Protected parameter: use this to pass in the |
* {@link debug_backtrace()} that should be used |
* to find error context |
* @return PEAR_Error|array if compatibility mode is on, a PEAR_Error is also |
* thrown. If a PEAR_Error is returned, the userinfo |
* property is set to the following array: |
* |
* <code> |
* array( |
* 'code' => $code, |
* 'params' => $params, |
* 'package' => $this->_package, |
* 'level' => $level, |
* 'time' => time(), |
* 'context' => $context, |
* 'message' => $msg, |
* //['repackage' => $err] repackaged error array/Exception class |
* ); |
* </code> |
* |
* Normally, the previous array is returned. |
*/ |
function push($code, $level = 'error', $params = array(), $msg = false, |
$repackage = false, $backtrace = false) |
{ |
$context = false; |
// grab error context |
if ($this->_contextCallback) { |
if (!$backtrace) { |
$backtrace = debug_backtrace(); |
} |
$context = call_user_func($this->_contextCallback, $code, $params, $backtrace); |
} |
// save error |
$time = explode(' ', microtime()); |
$time = $time[1] + $time[0]; |
$err = array( |
'code' => $code, |
'params' => $params, |
'package' => $this->_package, |
'level' => $level, |
'time' => $time, |
'context' => $context, |
'message' => $msg, |
); |
if ($repackage) { |
$err['repackage'] = $repackage; |
} |
// set up the error message, if necessary |
if ($this->_msgCallback) { |
$msg = call_user_func_array($this->_msgCallback, |
array(&$this, $err)); |
$err['message'] = $msg; |
} |
$push = $log = true; |
$die = false; |
// try the overriding callback first |
$callback = $this->staticPopCallback(); |
if ($callback) { |
$this->staticPushCallback($callback); |
} |
if (!is_callable($callback)) { |
// try the local callback next |
$callback = $this->popCallback(); |
if (is_callable($callback)) { |
$this->pushCallback($callback); |
} else { |
// try the default callback |
$callback = isset($GLOBALS['_PEAR_ERRORSTACK_DEFAULT_CALLBACK'][$this->_package]) ? |
$GLOBALS['_PEAR_ERRORSTACK_DEFAULT_CALLBACK'][$this->_package] : |
$GLOBALS['_PEAR_ERRORSTACK_DEFAULT_CALLBACK']['*']; |
} |
} |
if (is_callable($callback)) { |
switch(call_user_func($callback, $err)){ |
case PEAR_ERRORSTACK_IGNORE: |
return $err; |
break; |
case PEAR_ERRORSTACK_PUSH: |
$log = false; |
break; |
case PEAR_ERRORSTACK_LOG: |
$push = false; |
break; |
case PEAR_ERRORSTACK_DIE: |
$die = true; |
break; |
// anything else returned has the same effect as pushandlog |
} |
} |
if ($push) { |
array_unshift($this->_errors, $err); |
if (!isset($this->_errorsByLevel[$err['level']])) { |
$this->_errorsByLevel[$err['level']] = array(); |
} |
$this->_errorsByLevel[$err['level']][] = &$this->_errors[0]; |
} |
if ($log) { |
if ($this->_logger || $GLOBALS['_PEAR_ERRORSTACK_DEFAULT_LOGGER']) { |
$this->_log($err); |
} |
} |
if ($die) { |
die(); |
} |
if ($this->_compat && $push) { |
return $this->raiseError($msg, $code, null, null, $err); |
} |
return $err; |
} |
/** |
* Static version of {@link push()} |
* |
* @param string $package Package name this error belongs to |
* @param int $code Package-specific error code |
* @param string $level Error level. This is NOT spell-checked |
* @param array $params associative array of error parameters |
* @param string $msg Error message, or a portion of it if the message |
* is to be generated |
* @param array $repackage If this error re-packages an error pushed by |
* another package, place the array returned from |
* {@link pop()} in this parameter |
* @param array $backtrace Protected parameter: use this to pass in the |
* {@link debug_backtrace()} that should be used |
* to find error context |
* @return PEAR_Error|array if compatibility mode is on, a PEAR_Error is also |
* thrown. see docs for {@link push()} |
*/ |
public static function staticPush( |
$package, $code, $level = 'error', $params = array(), |
$msg = false, $repackage = false, $backtrace = false |
) { |
$s = &PEAR_ErrorStack::singleton($package); |
if ($s->_contextCallback) { |
if (!$backtrace) { |
if (function_exists('debug_backtrace')) { |
$backtrace = debug_backtrace(); |
} |
} |
} |
return $s->push($code, $level, $params, $msg, $repackage, $backtrace); |
} |
/** |
* Log an error using PEAR::Log |
* @param array $err Error array |
* @param array $levels Error level => Log constant map |
* @access protected |
*/ |
function _log($err) |
{ |
if ($this->_logger) { |
$logger = &$this->_logger; |
} else { |
$logger = &$GLOBALS['_PEAR_ERRORSTACK_DEFAULT_LOGGER']; |
} |
if (is_a($logger, 'Log')) { |
$levels = array( |
'exception' => PEAR_LOG_CRIT, |
'alert' => PEAR_LOG_ALERT, |
'critical' => PEAR_LOG_CRIT, |
'error' => PEAR_LOG_ERR, |
'warning' => PEAR_LOG_WARNING, |
'notice' => PEAR_LOG_NOTICE, |
'info' => PEAR_LOG_INFO, |
'debug' => PEAR_LOG_DEBUG); |
if (isset($levels[$err['level']])) { |
$level = $levels[$err['level']]; |
} else { |
$level = PEAR_LOG_INFO; |
} |
$logger->log($err['message'], $level, $err); |
} else { // support non-standard logs |
call_user_func($logger, $err); |
} |
} |
/** |
* Pop an error off of the error stack |
* |
* @return false|array |
* @since 0.4alpha it is no longer possible to specify a specific error |
* level to return - the last error pushed will be returned, instead |
*/ |
function pop() |
{ |
$err = @array_shift($this->_errors); |
if (!is_null($err)) { |
@array_pop($this->_errorsByLevel[$err['level']]); |
if (!count($this->_errorsByLevel[$err['level']])) { |
unset($this->_errorsByLevel[$err['level']]); |
} |
} |
return $err; |
} |
/** |
* Pop an error off of the error stack, static method |
* |
* @param string package name |
* @return boolean |
* @since PEAR1.5.0a1 |
*/ |
function staticPop($package) |
{ |
if ($package) { |
if (!isset($GLOBALS['_PEAR_ERRORSTACK_SINGLETON'][$package])) { |
return false; |
} |
return $GLOBALS['_PEAR_ERRORSTACK_SINGLETON'][$package]->pop(); |
} |
} |
/** |
* Determine whether there are any errors on the stack |
* @param string|array Level name. Use to determine if any errors |
* of level (string), or levels (array) have been pushed |
* @return boolean |
*/ |
function hasErrors($level = false) |
{ |
if ($level) { |
return isset($this->_errorsByLevel[$level]); |
} |
return count($this->_errors); |
} |
/** |
* Retrieve all errors since last purge |
* |
* @param boolean set in order to empty the error stack |
* @param string level name, to return only errors of a particular severity |
* @return array |
*/ |
function getErrors($purge = false, $level = false) |
{ |
if (!$purge) { |
if ($level) { |
if (!isset($this->_errorsByLevel[$level])) { |
return array(); |
} else { |
return $this->_errorsByLevel[$level]; |
} |
} else { |
return $this->_errors; |
} |
} |
if ($level) { |
$ret = $this->_errorsByLevel[$level]; |
foreach ($this->_errorsByLevel[$level] as $i => $unused) { |
// entries are references to the $_errors array |
$this->_errorsByLevel[$level][$i] = false; |
} |
// array_filter removes all entries === false |
$this->_errors = array_filter($this->_errors); |
unset($this->_errorsByLevel[$level]); |
return $ret; |
} |
$ret = $this->_errors; |
$this->_errors = array(); |
$this->_errorsByLevel = array(); |
return $ret; |
} |
/** |
* Determine whether there are any errors on a single error stack, or on any error stack |
* |
* The optional parameter can be used to test the existence of any errors without the need of |
* singleton instantiation |
* @param string|false Package name to check for errors |
* @param string Level name to check for a particular severity |
* @return boolean |
*/ |
public static function staticHasErrors($package = false, $level = false) |
{ |
if ($package) { |
if (!isset($GLOBALS['_PEAR_ERRORSTACK_SINGLETON'][$package])) { |
return false; |
} |
return $GLOBALS['_PEAR_ERRORSTACK_SINGLETON'][$package]->hasErrors($level); |
} |
foreach ($GLOBALS['_PEAR_ERRORSTACK_SINGLETON'] as $package => $obj) { |
if ($obj->hasErrors($level)) { |
return true; |
} |
} |
return false; |
} |
/** |
* Get a list of all errors since last purge, organized by package |
* @since PEAR 1.4.0dev BC break! $level is now in the place $merge used to be |
* @param boolean $purge Set to purge the error stack of existing errors |
* @param string $level Set to a level name in order to retrieve only errors of a particular level |
* @param boolean $merge Set to return a flat array, not organized by package |
* @param array $sortfunc Function used to sort a merged array - default |
* sorts by time, and should be good for most cases |
* |
* @return array |
*/ |
public static function staticGetErrors( |
$purge = false, $level = false, $merge = false, |
$sortfunc = array('PEAR_ErrorStack', '_sortErrors') |
) { |
$ret = array(); |
if (!is_callable($sortfunc)) { |
$sortfunc = array('PEAR_ErrorStack', '_sortErrors'); |
} |
foreach ($GLOBALS['_PEAR_ERRORSTACK_SINGLETON'] as $package => $obj) { |
$test = $GLOBALS['_PEAR_ERRORSTACK_SINGLETON'][$package]->getErrors($purge, $level); |
if ($test) { |
if ($merge) { |
$ret = array_merge($ret, $test); |
} else { |
$ret[$package] = $test; |
} |
} |
} |
if ($merge) { |
usort($ret, $sortfunc); |
} |
return $ret; |
} |
/** |
* Error sorting function, sorts by time |
* @access private |
*/ |
public static function _sortErrors($a, $b) |
{ |
if ($a['time'] == $b['time']) { |
return 0; |
} |
if ($a['time'] < $b['time']) { |
return 1; |
} |
return -1; |
} |
/** |
* Standard file/line number/function/class context callback |
* |
* This function uses a backtrace generated from {@link debug_backtrace()} |
* and so will not work at all in PHP < 4.3.0. The frame should |
* reference the frame that contains the source of the error. |
* @return array|false either array('file' => file, 'line' => line, |
* 'function' => function name, 'class' => class name) or |
* if this doesn't work, then false |
* @param unused |
* @param integer backtrace frame. |
* @param array Results of debug_backtrace() |
*/ |
public static function getFileLine($code, $params, $backtrace = null) |
{ |
if ($backtrace === null) { |
return false; |
} |
$frame = 0; |
$functionframe = 1; |
if (!isset($backtrace[1])) { |
$functionframe = 0; |
} else { |
while (isset($backtrace[$functionframe]['function']) && |
$backtrace[$functionframe]['function'] == 'eval' && |
isset($backtrace[$functionframe + 1])) { |
$functionframe++; |
} |
} |
if (isset($backtrace[$frame])) { |
if (!isset($backtrace[$frame]['file'])) { |
$frame++; |
} |
$funcbacktrace = $backtrace[$functionframe]; |
$filebacktrace = $backtrace[$frame]; |
$ret = array('file' => $filebacktrace['file'], |
'line' => $filebacktrace['line']); |
// rearrange for eval'd code or create function errors |
if (strpos($filebacktrace['file'], '(') && |
preg_match(';^(.*?)\((\d+)\) : (.*?)\\z;', $filebacktrace['file'], |
$matches)) { |
$ret['file'] = $matches[1]; |
$ret['line'] = $matches[2] + 0; |
} |
if (isset($funcbacktrace['function']) && isset($backtrace[1])) { |
if ($funcbacktrace['function'] != 'eval') { |
if ($funcbacktrace['function'] == '__lambda_func') { |
$ret['function'] = 'create_function() code'; |
} else { |
$ret['function'] = $funcbacktrace['function']; |
} |
} |
} |
if (isset($funcbacktrace['class']) && isset($backtrace[1])) { |
$ret['class'] = $funcbacktrace['class']; |
} |
return $ret; |
} |
return false; |
} |
/** |
* Standard error message generation callback |
* |
* This method may also be called by a custom error message generator |
* to fill in template values from the params array, simply |
* set the third parameter to the error message template string to use |
* |
* The special variable %__msg% is reserved: use it only to specify |
* where a message passed in by the user should be placed in the template, |
* like so: |
* |
* Error message: %msg% - internal error |
* |
* If the message passed like so: |
* |
* <code> |
* $stack->push(ERROR_CODE, 'error', array(), 'server error 500'); |
* </code> |
* |
* The returned error message will be "Error message: server error 500 - |
* internal error" |
* @param PEAR_ErrorStack |
* @param array |
* @param string|false Pre-generated error message template |
* |
* @return string |
*/ |
public static function getErrorMessage(&$stack, $err, $template = false) |
{ |
if ($template) { |
$mainmsg = $template; |
} else { |
$mainmsg = $stack->getErrorMessageTemplate($err['code']); |
} |
$mainmsg = str_replace('%__msg%', $err['message'], $mainmsg); |
if (is_array($err['params']) && count($err['params'])) { |
foreach ($err['params'] as $name => $val) { |
if (is_array($val)) { |
// @ is needed in case $val is a multi-dimensional array |
$val = @implode(', ', $val); |
} |
if (is_object($val)) { |
if (method_exists($val, '__toString')) { |
$val = $val->__toString(); |
} else { |
PEAR_ErrorStack::staticPush('PEAR_ErrorStack', PEAR_ERRORSTACK_ERR_OBJTOSTRING, |
'warning', array('obj' => get_class($val)), |
'object %obj% passed into getErrorMessage, but has no __toString() method'); |
$val = 'Object'; |
} |
} |
$mainmsg = str_replace('%' . $name . '%', $val, $mainmsg); |
} |
} |
return $mainmsg; |
} |
/** |
* Standard Error Message Template generator from code |
* @return string |
*/ |
function getErrorMessageTemplate($code) |
{ |
if (!isset($this->_errorMsgs[$code])) { |
return '%__msg%'; |
} |
return $this->_errorMsgs[$code]; |
} |
/** |
* Set the Error Message Template array |
* |
* The array format must be: |
* <pre> |
* array(error code => 'message template',...) |
* </pre> |
* |
* Error message parameters passed into {@link push()} will be used as input |
* for the error message. If the template is 'message %foo% was %bar%', and the |
* parameters are array('foo' => 'one', 'bar' => 'six'), the error message returned will |
* be 'message one was six' |
* @return string |
*/ |
function setErrorMessageTemplate($template) |
{ |
$this->_errorMsgs = $template; |
} |
/** |
* emulate PEAR::raiseError() |
* |
* @return PEAR_Error |
*/ |
function raiseError() |
{ |
require_once 'PEAR.php'; |
$args = func_get_args(); |
return call_user_func_array(array('PEAR', 'raiseError'), $args); |
} |
} |
$stack = &PEAR_ErrorStack::singleton('PEAR_ErrorStack'); |
$stack->pushCallback(array('PEAR_ErrorStack', '_handleError')); |
?> |
/branches/v1.3-critias/bibliotheque/pear/PEAR/ChannelFile/Parser.php |
---|
New file |
0,0 → 1,67 |
<?php |
/** |
* PEAR_ChannelFile_Parser for parsing channel.xml |
* |
* PHP versions 4 and 5 |
* |
* @category pear |
* @package PEAR |
* @author Greg Beaver <cellog@php.net> |
* @copyright 1997-2009 The Authors |
* @license http://opensource.org/licenses/bsd-license.php New BSD License |
* @link http://pear.php.net/package/PEAR |
* @since File available since Release 1.4.0a1 |
*/ |
/** |
* base xml parser class |
*/ |
require_once 'PEAR/XMLParser.php'; |
require_once 'PEAR/ChannelFile.php'; |
/** |
* Parser for channel.xml |
* @category pear |
* @package PEAR |
* @author Greg Beaver <cellog@php.net> |
* @copyright 1997-2009 The Authors |
* @license http://opensource.org/licenses/bsd-license.php New BSD License |
* @version Release: 1.10.1 |
* @link http://pear.php.net/package/PEAR |
* @since Class available since Release 1.4.0a1 |
*/ |
class PEAR_ChannelFile_Parser extends PEAR_XMLParser |
{ |
var $_config; |
var $_logger; |
var $_registry; |
function setConfig(&$c) |
{ |
$this->_config = &$c; |
$this->_registry = &$c->getRegistry(); |
} |
function setLogger(&$l) |
{ |
$this->_logger = &$l; |
} |
function parse($data, $file) |
{ |
if (PEAR::isError($err = parent::parse($data, $file))) { |
return $err; |
} |
$ret = new PEAR_ChannelFile; |
$ret->setConfig($this->_config); |
if (isset($this->_logger)) { |
$ret->setLogger($this->_logger); |
} |
$ret->fromArray($this->_unserializedData); |
// make sure the filelist is in the easy to read format needed |
$ret->flattenFilelist(); |
$ret->setPackagefile($file, $archive); |
return $ret; |
} |
} |
/branches/v1.3-critias/bibliotheque/pear/PEAR/DependencyDB.php |
---|
New file |
0,0 → 1,764 |
<?php |
/** |
* PEAR_DependencyDB, advanced installed packages dependency database |
* |
* PHP versions 4 and 5 |
* |
* @category pear |
* @package PEAR |
* @author Tomas V. V. Cox <cox@idecnet.com> |
* @author Greg Beaver <cellog@php.net> |
* @copyright 1997-2009 The Authors |
* @license http://opensource.org/licenses/bsd-license.php New BSD License |
* @link http://pear.php.net/package/PEAR |
* @since File available since Release 1.4.0a1 |
*/ |
/** |
* Needed for error handling |
*/ |
require_once 'PEAR.php'; |
require_once 'PEAR/Config.php'; |
$GLOBALS['_PEAR_DEPENDENCYDB_INSTANCE'] = array(); |
/** |
* Track dependency relationships between installed packages |
* @category pear |
* @package PEAR |
* @author Greg Beaver <cellog@php.net> |
* @author Tomas V.V.Cox <cox@idec.net.com> |
* @copyright 1997-2009 The Authors |
* @license http://opensource.org/licenses/bsd-license.php New BSD License |
* @version Release: 1.10.1 |
* @link http://pear.php.net/package/PEAR |
* @since Class available since Release 1.4.0a1 |
*/ |
class PEAR_DependencyDB |
{ |
// {{{ properties |
/** |
* This is initialized by {@link setConfig()} |
* @var PEAR_Config |
* @access private |
*/ |
var $_config; |
/** |
* This is initialized by {@link setConfig()} |
* @var PEAR_Registry |
* @access private |
*/ |
var $_registry; |
/** |
* Filename of the dependency DB (usually .depdb) |
* @var string |
* @access private |
*/ |
var $_depdb = false; |
/** |
* File name of the lockfile (usually .depdblock) |
* @var string |
* @access private |
*/ |
var $_lockfile = false; |
/** |
* Open file resource for locking the lockfile |
* @var resource|false |
* @access private |
*/ |
var $_lockFp = false; |
/** |
* API version of this class, used to validate a file on-disk |
* @var string |
* @access private |
*/ |
var $_version = '1.0'; |
/** |
* Cached dependency database file |
* @var array|null |
* @access private |
*/ |
var $_cache; |
// }}} |
// {{{ & singleton() |
/** |
* Get a raw dependency database. Calls setConfig() and assertDepsDB() |
* @param PEAR_Config |
* @param string|false full path to the dependency database, or false to use default |
* @return PEAR_DependencyDB|PEAR_Error |
*/ |
public static function &singleton(&$config, $depdb = false) |
{ |
$phpdir = $config->get('php_dir', null, 'pear.php.net'); |
if (!isset($GLOBALS['_PEAR_DEPENDENCYDB_INSTANCE'][$phpdir])) { |
$a = new PEAR_DependencyDB; |
$GLOBALS['_PEAR_DEPENDENCYDB_INSTANCE'][$phpdir] = &$a; |
$a->setConfig($config, $depdb); |
$e = $a->assertDepsDB(); |
if (PEAR::isError($e)) { |
return $e; |
} |
} |
return $GLOBALS['_PEAR_DEPENDENCYDB_INSTANCE'][$phpdir]; |
} |
/** |
* Set up the registry/location of dependency DB |
* @param PEAR_Config|false |
* @param string|false full path to the dependency database, or false to use default |
*/ |
function setConfig(&$config, $depdb = false) |
{ |
if (!$config) { |
$this->_config = &PEAR_Config::singleton(); |
} else { |
$this->_config = &$config; |
} |
$this->_registry = &$this->_config->getRegistry(); |
if (!$depdb) { |
$dir = $this->_config->get('metadata_dir', null, 'pear.php.net'); |
if (!$dir) { |
$dir = $this->_config->get('php_dir', null, 'pear.php.net'); |
} |
$this->_depdb = $dir . DIRECTORY_SEPARATOR . '.depdb'; |
} else { |
$this->_depdb = $depdb; |
} |
$this->_lockfile = dirname($this->_depdb) . DIRECTORY_SEPARATOR . '.depdblock'; |
} |
// }}} |
function hasWriteAccess() |
{ |
if (!file_exists($this->_depdb)) { |
$dir = $this->_depdb; |
while ($dir && $dir != '.') { |
$dir = dirname($dir); // cd .. |
if ($dir != '.' && file_exists($dir)) { |
if (is_writeable($dir)) { |
return true; |
} |
return false; |
} |
} |
return false; |
} |
return is_writeable($this->_depdb); |
} |
// {{{ assertDepsDB() |
/** |
* Create the dependency database, if it doesn't exist. Error if the database is |
* newer than the code reading it. |
* @return void|PEAR_Error |
*/ |
function assertDepsDB() |
{ |
if (!is_file($this->_depdb)) { |
$this->rebuildDB(); |
return; |
} |
$depdb = $this->_getDepDB(); |
// Datatype format has been changed, rebuild the Deps DB |
if ($depdb['_version'] < $this->_version) { |
$this->rebuildDB(); |
} |
if ($depdb['_version']{0} > $this->_version{0}) { |
return PEAR::raiseError('Dependency database is version ' . |
$depdb['_version'] . ', and we are version ' . |
$this->_version . ', cannot continue'); |
} |
} |
/** |
* Get a list of installed packages that depend on this package |
* @param PEAR_PackageFile_v1|PEAR_PackageFile_v2|array |
* @return array|false |
*/ |
function getDependentPackages(&$pkg) |
{ |
$data = $this->_getDepDB(); |
if (is_object($pkg)) { |
$channel = strtolower($pkg->getChannel()); |
$package = strtolower($pkg->getPackage()); |
} else { |
$channel = strtolower($pkg['channel']); |
$package = strtolower($pkg['package']); |
} |
if (isset($data['packages'][$channel][$package])) { |
return $data['packages'][$channel][$package]; |
} |
return false; |
} |
/** |
* Get a list of the actual dependencies of installed packages that depend on |
* a package. |
* @param PEAR_PackageFile_v1|PEAR_PackageFile_v2|array |
* @return array|false |
*/ |
function getDependentPackageDependencies(&$pkg) |
{ |
$data = $this->_getDepDB(); |
if (is_object($pkg)) { |
$channel = strtolower($pkg->getChannel()); |
$package = strtolower($pkg->getPackage()); |
} else { |
$channel = strtolower($pkg['channel']); |
$package = strtolower($pkg['package']); |
} |
$depend = $this->getDependentPackages($pkg); |
if (!$depend) { |
return false; |
} |
$dependencies = array(); |
foreach ($depend as $info) { |
$temp = $this->getDependencies($info); |
foreach ($temp as $dep) { |
if ( |
isset($dep['dep'], $dep['dep']['channel'], $dep['dep']['name']) && |
strtolower($dep['dep']['channel']) == $channel && |
strtolower($dep['dep']['name']) == $package |
) { |
if (!isset($dependencies[$info['channel']])) { |
$dependencies[$info['channel']] = array(); |
} |
if (!isset($dependencies[$info['channel']][$info['package']])) { |
$dependencies[$info['channel']][$info['package']] = array(); |
} |
$dependencies[$info['channel']][$info['package']][] = $dep; |
} |
} |
} |
return $dependencies; |
} |
/** |
* Get a list of dependencies of this installed package |
* @param PEAR_PackageFile_v1|PEAR_PackageFile_v2|array |
* @return array|false |
*/ |
function getDependencies(&$pkg) |
{ |
if (is_object($pkg)) { |
$channel = strtolower($pkg->getChannel()); |
$package = strtolower($pkg->getPackage()); |
} else { |
$channel = strtolower($pkg['channel']); |
$package = strtolower($pkg['package']); |
} |
$data = $this->_getDepDB(); |
if (isset($data['dependencies'][$channel][$package])) { |
return $data['dependencies'][$channel][$package]; |
} |
return false; |
} |
/** |
* Determine whether $parent depends on $child, near or deep |
* @param array|PEAR_PackageFile_v2|PEAR_PackageFile_v2 |
* @param array|PEAR_PackageFile_v2|PEAR_PackageFile_v2 |
*/ |
function dependsOn($parent, $child) |
{ |
$c = array(); |
$this->_getDepDB(); |
return $this->_dependsOn($parent, $child, $c); |
} |
function _dependsOn($parent, $child, &$checked) |
{ |
if (is_object($parent)) { |
$channel = strtolower($parent->getChannel()); |
$package = strtolower($parent->getPackage()); |
} else { |
$channel = strtolower($parent['channel']); |
$package = strtolower($parent['package']); |
} |
if (is_object($child)) { |
$depchannel = strtolower($child->getChannel()); |
$deppackage = strtolower($child->getPackage()); |
} else { |
$depchannel = strtolower($child['channel']); |
$deppackage = strtolower($child['package']); |
} |
if (isset($checked[$channel][$package][$depchannel][$deppackage])) { |
return false; // avoid endless recursion |
} |
$checked[$channel][$package][$depchannel][$deppackage] = true; |
if (!isset($this->_cache['dependencies'][$channel][$package])) { |
return false; |
} |
foreach ($this->_cache['dependencies'][$channel][$package] as $info) { |
if (isset($info['dep']['uri'])) { |
if (is_object($child)) { |
if ($info['dep']['uri'] == $child->getURI()) { |
return true; |
} |
} elseif (isset($child['uri'])) { |
if ($info['dep']['uri'] == $child['uri']) { |
return true; |
} |
} |
return false; |
} |
if (strtolower($info['dep']['channel']) == $depchannel && |
strtolower($info['dep']['name']) == $deppackage) { |
return true; |
} |
} |
foreach ($this->_cache['dependencies'][$channel][$package] as $info) { |
if (isset($info['dep']['uri'])) { |
if ($this->_dependsOn(array( |
'uri' => $info['dep']['uri'], |
'package' => $info['dep']['name']), $child, $checked)) { |
return true; |
} |
} else { |
if ($this->_dependsOn(array( |
'channel' => $info['dep']['channel'], |
'package' => $info['dep']['name']), $child, $checked)) { |
return true; |
} |
} |
} |
return false; |
} |
/** |
* Register dependencies of a package that is being installed or upgraded |
* @param PEAR_PackageFile_v2|PEAR_PackageFile_v2 |
*/ |
function installPackage(&$package) |
{ |
$data = $this->_getDepDB(); |
unset($this->_cache); |
$this->_setPackageDeps($data, $package); |
$this->_writeDepDB($data); |
} |
/** |
* Remove dependencies of a package that is being uninstalled, or upgraded. |
* |
* Upgraded packages first uninstall, then install |
* @param PEAR_PackageFile_v1|PEAR_PackageFile_v2|array If an array, then it must have |
* indices 'channel' and 'package' |
*/ |
function uninstallPackage(&$pkg) |
{ |
$data = $this->_getDepDB(); |
unset($this->_cache); |
if (is_object($pkg)) { |
$channel = strtolower($pkg->getChannel()); |
$package = strtolower($pkg->getPackage()); |
} else { |
$channel = strtolower($pkg['channel']); |
$package = strtolower($pkg['package']); |
} |
if (!isset($data['dependencies'][$channel][$package])) { |
return true; |
} |
foreach ($data['dependencies'][$channel][$package] as $dep) { |
$found = false; |
$depchannel = isset($dep['dep']['uri']) ? '__uri' : strtolower($dep['dep']['channel']); |
$depname = strtolower($dep['dep']['name']); |
if (isset($data['packages'][$depchannel][$depname])) { |
foreach ($data['packages'][$depchannel][$depname] as $i => $info) { |
if ($info['channel'] == $channel && $info['package'] == $package) { |
$found = true; |
break; |
} |
} |
} |
if ($found) { |
unset($data['packages'][$depchannel][$depname][$i]); |
if (!count($data['packages'][$depchannel][$depname])) { |
unset($data['packages'][$depchannel][$depname]); |
if (!count($data['packages'][$depchannel])) { |
unset($data['packages'][$depchannel]); |
} |
} else { |
$data['packages'][$depchannel][$depname] = |
array_values($data['packages'][$depchannel][$depname]); |
} |
} |
} |
unset($data['dependencies'][$channel][$package]); |
if (!count($data['dependencies'][$channel])) { |
unset($data['dependencies'][$channel]); |
} |
if (!count($data['dependencies'])) { |
unset($data['dependencies']); |
} |
if (!count($data['packages'])) { |
unset($data['packages']); |
} |
$this->_writeDepDB($data); |
} |
/** |
* Rebuild the dependency DB by reading registry entries. |
* @return true|PEAR_Error |
*/ |
function rebuildDB() |
{ |
$depdb = array('_version' => $this->_version); |
if (!$this->hasWriteAccess()) { |
// allow startup for read-only with older Registry |
return $depdb; |
} |
$packages = $this->_registry->listAllPackages(); |
if (PEAR::isError($packages)) { |
return $packages; |
} |
foreach ($packages as $channel => $ps) { |
foreach ($ps as $package) { |
$package = $this->_registry->getPackage($package, $channel); |
if (PEAR::isError($package)) { |
return $package; |
} |
$this->_setPackageDeps($depdb, $package); |
} |
} |
$error = $this->_writeDepDB($depdb); |
if (PEAR::isError($error)) { |
return $error; |
} |
$this->_cache = $depdb; |
return true; |
} |
/** |
* Register usage of the dependency DB to prevent race conditions |
* @param int one of the LOCK_* constants |
* @return true|PEAR_Error |
* @access private |
*/ |
function _lock($mode = LOCK_EX) |
{ |
if (stristr(php_uname(), 'Windows 9')) { |
return true; |
} |
if ($mode != LOCK_UN && is_resource($this->_lockFp)) { |
// XXX does not check type of lock (LOCK_SH/LOCK_EX) |
return true; |
} |
$open_mode = 'w'; |
// XXX People reported problems with LOCK_SH and 'w' |
if ($mode === LOCK_SH) { |
if (!file_exists($this->_lockfile)) { |
touch($this->_lockfile); |
} elseif (!is_file($this->_lockfile)) { |
return PEAR::raiseError('could not create Dependency lock file, ' . |
'it exists and is not a regular file'); |
} |
$open_mode = 'r'; |
} |
if (!is_resource($this->_lockFp)) { |
$this->_lockFp = @fopen($this->_lockfile, $open_mode); |
} |
if (!is_resource($this->_lockFp)) { |
return PEAR::raiseError("could not create Dependency lock file" . |
(isset($php_errormsg) ? ": " . $php_errormsg : "")); |
} |
if (!(int)flock($this->_lockFp, $mode)) { |
switch ($mode) { |
case LOCK_SH: $str = 'shared'; break; |
case LOCK_EX: $str = 'exclusive'; break; |
case LOCK_UN: $str = 'unlock'; break; |
default: $str = 'unknown'; break; |
} |
return PEAR::raiseError("could not acquire $str lock ($this->_lockfile)"); |
} |
return true; |
} |
/** |
* Release usage of dependency DB |
* @return true|PEAR_Error |
* @access private |
*/ |
function _unlock() |
{ |
$ret = $this->_lock(LOCK_UN); |
if (is_resource($this->_lockFp)) { |
fclose($this->_lockFp); |
} |
$this->_lockFp = null; |
return $ret; |
} |
/** |
* Load the dependency database from disk, or return the cache |
* @return array|PEAR_Error |
*/ |
function _getDepDB() |
{ |
if (!$this->hasWriteAccess()) { |
return array('_version' => $this->_version); |
} |
if (isset($this->_cache)) { |
return $this->_cache; |
} |
if (!$fp = fopen($this->_depdb, 'r')) { |
$err = PEAR::raiseError("Could not open dependencies file `".$this->_depdb."'"); |
return $err; |
} |
clearstatcache(); |
fclose($fp); |
$data = unserialize(file_get_contents($this->_depdb)); |
$this->_cache = $data; |
return $data; |
} |
/** |
* Write out the dependency database to disk |
* @param array the database |
* @return true|PEAR_Error |
* @access private |
*/ |
function _writeDepDB(&$deps) |
{ |
if (PEAR::isError($e = $this->_lock(LOCK_EX))) { |
return $e; |
} |
if (!$fp = fopen($this->_depdb, 'wb')) { |
$this->_unlock(); |
return PEAR::raiseError("Could not open dependencies file `".$this->_depdb."' for writing"); |
} |
fwrite($fp, serialize($deps)); |
fclose($fp); |
$this->_unlock(); |
$this->_cache = $deps; |
return true; |
} |
/** |
* Register all dependencies from a package in the dependencies database, in essence |
* "installing" the package's dependency information |
* @param array the database |
* @param PEAR_PackageFile_v1|PEAR_PackageFile_v2 |
* @access private |
*/ |
function _setPackageDeps(&$data, &$pkg) |
{ |
$pkg->setConfig($this->_config); |
if ($pkg->getPackagexmlVersion() == '1.0') { |
$gen = &$pkg->getDefaultGenerator(); |
$deps = $gen->dependenciesToV2(); |
} else { |
$deps = $pkg->getDeps(true); |
} |
if (!$deps) { |
return; |
} |
if (!is_array($data)) { |
$data = array(); |
} |
if (!isset($data['dependencies'])) { |
$data['dependencies'] = array(); |
} |
$channel = strtolower($pkg->getChannel()); |
$package = strtolower($pkg->getPackage()); |
if (!isset($data['dependencies'][$channel])) { |
$data['dependencies'][$channel] = array(); |
} |
$data['dependencies'][$channel][$package] = array(); |
if (isset($deps['required']['package'])) { |
if (!isset($deps['required']['package'][0])) { |
$deps['required']['package'] = array($deps['required']['package']); |
} |
foreach ($deps['required']['package'] as $dep) { |
$this->_registerDep($data, $pkg, $dep, 'required'); |
} |
} |
if (isset($deps['optional']['package'])) { |
if (!isset($deps['optional']['package'][0])) { |
$deps['optional']['package'] = array($deps['optional']['package']); |
} |
foreach ($deps['optional']['package'] as $dep) { |
$this->_registerDep($data, $pkg, $dep, 'optional'); |
} |
} |
if (isset($deps['required']['subpackage'])) { |
if (!isset($deps['required']['subpackage'][0])) { |
$deps['required']['subpackage'] = array($deps['required']['subpackage']); |
} |
foreach ($deps['required']['subpackage'] as $dep) { |
$this->_registerDep($data, $pkg, $dep, 'required'); |
} |
} |
if (isset($deps['optional']['subpackage'])) { |
if (!isset($deps['optional']['subpackage'][0])) { |
$deps['optional']['subpackage'] = array($deps['optional']['subpackage']); |
} |
foreach ($deps['optional']['subpackage'] as $dep) { |
$this->_registerDep($data, $pkg, $dep, 'optional'); |
} |
} |
if (isset($deps['group'])) { |
if (!isset($deps['group'][0])) { |
$deps['group'] = array($deps['group']); |
} |
foreach ($deps['group'] as $group) { |
if (isset($group['package'])) { |
if (!isset($group['package'][0])) { |
$group['package'] = array($group['package']); |
} |
foreach ($group['package'] as $dep) { |
$this->_registerDep($data, $pkg, $dep, 'optional', |
$group['attribs']['name']); |
} |
} |
if (isset($group['subpackage'])) { |
if (!isset($group['subpackage'][0])) { |
$group['subpackage'] = array($group['subpackage']); |
} |
foreach ($group['subpackage'] as $dep) { |
$this->_registerDep($data, $pkg, $dep, 'optional', |
$group['attribs']['name']); |
} |
} |
} |
} |
if ($data['dependencies'][$channel][$package] == array()) { |
unset($data['dependencies'][$channel][$package]); |
if (!count($data['dependencies'][$channel])) { |
unset($data['dependencies'][$channel]); |
} |
} |
} |
/** |
* @param array the database |
* @param PEAR_PackageFile_v1|PEAR_PackageFile_v2 |
* @param array the specific dependency |
* @param required|optional whether this is a required or an optional dep |
* @param string|false dependency group this dependency is from, or false for ordinary dep |
*/ |
function _registerDep(&$data, &$pkg, $dep, $type, $group = false) |
{ |
$info = array( |
'dep' => $dep, |
'type' => $type, |
'group' => $group |
); |
$dep = array_map('strtolower', $dep); |
$depchannel = isset($dep['channel']) ? $dep['channel'] : '__uri'; |
if (!isset($data['dependencies'])) { |
$data['dependencies'] = array(); |
} |
$channel = strtolower($pkg->getChannel()); |
$package = strtolower($pkg->getPackage()); |
if (!isset($data['dependencies'][$channel])) { |
$data['dependencies'][$channel] = array(); |
} |
if (!isset($data['dependencies'][$channel][$package])) { |
$data['dependencies'][$channel][$package] = array(); |
} |
$data['dependencies'][$channel][$package][] = $info; |
if (isset($data['packages'][$depchannel][$dep['name']])) { |
$found = false; |
foreach ($data['packages'][$depchannel][$dep['name']] as $i => $p) { |
if ($p['channel'] == $channel && $p['package'] == $package) { |
$found = true; |
break; |
} |
} |
} else { |
if (!isset($data['packages'])) { |
$data['packages'] = array(); |
} |
if (!isset($data['packages'][$depchannel])) { |
$data['packages'][$depchannel] = array(); |
} |
if (!isset($data['packages'][$depchannel][$dep['name']])) { |
$data['packages'][$depchannel][$dep['name']] = array(); |
} |
$found = false; |
} |
if (!$found) { |
$data['packages'][$depchannel][$dep['name']][] = array( |
'channel' => $channel, |
'package' => $package |
); |
} |
} |
} |
/branches/v1.3-critias/bibliotheque/pear/PEAR/Builder.php |
---|
New file |
0,0 → 1,499 |
<?php |
/** |
* PEAR_Builder for building PHP extensions (PECL packages) |
* |
* PHP versions 4 and 5 |
* |
* @category pear |
* @package PEAR |
* @author Stig Bakken <ssb@php.net> |
* @author Greg Beaver <cellog@php.net> |
* @copyright 1997-2009 The Authors |
* @license http://opensource.org/licenses/bsd-license.php New BSD License |
* @link http://pear.php.net/package/PEAR |
* @since File available since Release 0.1 |
* |
* TODO: log output parameters in PECL command line |
* TODO: msdev path in configuration |
*/ |
/** |
* Needed for extending PEAR_Builder |
*/ |
require_once 'PEAR/Common.php'; |
require_once 'PEAR/PackageFile.php'; |
require_once 'System.php'; |
/** |
* Class to handle building (compiling) extensions. |
* |
* @category pear |
* @package PEAR |
* @author Stig Bakken <ssb@php.net> |
* @author Greg Beaver <cellog@php.net> |
* @copyright 1997-2009 The Authors |
* @license http://opensource.org/licenses/bsd-license.php New BSD License |
* @version Release: 1.10.1 |
* @link http://pear.php.net/package/PEAR |
* @since Class available since PHP 4.0.2 |
* @see http://pear.php.net/manual/en/core.ppm.pear-builder.php |
*/ |
class PEAR_Builder extends PEAR_Common |
{ |
var $php_api_version = 0; |
var $zend_module_api_no = 0; |
var $zend_extension_api_no = 0; |
var $extensions_built = array(); |
/** |
* @var string Used for reporting when it is not possible to pass function |
* via extra parameter, e.g. log, msdevCallback |
*/ |
var $current_callback = null; |
// used for msdev builds |
var $_lastline = null; |
var $_firstline = null; |
/** |
* PEAR_Builder constructor. |
* |
* @param object $ui user interface object (instance of PEAR_Frontend_*) |
* |
* @access public |
*/ |
function __construct(&$ui) |
{ |
parent::__construct(); |
$this->setFrontendObject($ui); |
} |
/** |
* Build an extension from source on windows. |
* requires msdev |
*/ |
function _build_win32($descfile, $callback = null) |
{ |
if (is_object($descfile)) { |
$pkg = $descfile; |
$descfile = $pkg->getPackageFile(); |
} else { |
$pf = new PEAR_PackageFile($this->config, $this->debug); |
$pkg = &$pf->fromPackageFile($descfile, PEAR_VALIDATE_NORMAL); |
if (PEAR::isError($pkg)) { |
return $pkg; |
} |
} |
$dir = dirname($descfile); |
$old_cwd = getcwd(); |
if (!file_exists($dir) || !is_dir($dir) || !chdir($dir)) { |
return $this->raiseError("could not chdir to $dir"); |
} |
// packages that were in a .tar have the packagefile in this directory |
$vdir = $pkg->getPackage() . '-' . $pkg->getVersion(); |
if (file_exists($dir) && is_dir($vdir)) { |
if (!chdir($vdir)) { |
return $this->raiseError("could not chdir to " . realpath($vdir)); |
} |
$dir = getcwd(); |
} |
$this->log(2, "building in $dir"); |
$dsp = $pkg->getPackage().'.dsp'; |
if (!file_exists("$dir/$dsp")) { |
return $this->raiseError("The DSP $dsp does not exist."); |
} |
// XXX TODO: make release build type configurable |
$command = 'msdev '.$dsp.' /MAKE "'.$pkg->getPackage(). ' - Release"'; |
$err = $this->_runCommand($command, array(&$this, 'msdevCallback')); |
if (PEAR::isError($err)) { |
return $err; |
} |
// figure out the build platform and type |
$platform = 'Win32'; |
$buildtype = 'Release'; |
if (preg_match('/.*?'.$pkg->getPackage().'\s-\s(\w+)\s(.*?)-+/i',$this->_firstline,$matches)) { |
$platform = $matches[1]; |
$buildtype = $matches[2]; |
} |
if (preg_match('/(.*)?\s-\s(\d+).*?(\d+)/', $this->_lastline, $matches)) { |
if ($matches[2]) { |
// there were errors in the build |
return $this->raiseError("There were errors during compilation."); |
} |
$out = $matches[1]; |
} else { |
return $this->raiseError("Did not understand the completion status returned from msdev.exe."); |
} |
// msdev doesn't tell us the output directory :/ |
// open the dsp, find /out and use that directory |
$dsptext = join(file($dsp),''); |
// this regex depends on the build platform and type having been |
// correctly identified above. |
$regex ='/.*?!IF\s+"\$\(CFG\)"\s+==\s+("'. |
$pkg->getPackage().'\s-\s'. |
$platform.'\s'. |
$buildtype.'").*?'. |
'\/out:"(.*?)"/is'; |
if ($dsptext && preg_match($regex, $dsptext, $matches)) { |
// what we get back is a relative path to the output file itself. |
$outfile = realpath($matches[2]); |
} else { |
return $this->raiseError("Could not retrieve output information from $dsp."); |
} |
// realpath returns false if the file doesn't exist |
if ($outfile && copy($outfile, "$dir/$out")) { |
$outfile = "$dir/$out"; |
} |
$built_files[] = array( |
'file' => "$outfile", |
'php_api' => $this->php_api_version, |
'zend_mod_api' => $this->zend_module_api_no, |
'zend_ext_api' => $this->zend_extension_api_no, |
); |
return $built_files; |
} |
// }}} |
// {{{ msdevCallback() |
function msdevCallback($what, $data) |
{ |
if (!$this->_firstline) |
$this->_firstline = $data; |
$this->_lastline = $data; |
call_user_func($this->current_callback, $what, $data); |
} |
/** |
* @param string |
* @param string |
* @param array |
* @access private |
*/ |
function _harvestInstDir($dest_prefix, $dirname, &$built_files) |
{ |
$d = opendir($dirname); |
if (!$d) |
return false; |
$ret = true; |
while (($ent = readdir($d)) !== false) { |
if ($ent{0} == '.') |
continue; |
$full = $dirname . DIRECTORY_SEPARATOR . $ent; |
if (is_dir($full)) { |
if (!$this->_harvestInstDir( |
$dest_prefix . DIRECTORY_SEPARATOR . $ent, |
$full, $built_files)) { |
$ret = false; |
break; |
} |
} else { |
$dest = $dest_prefix . DIRECTORY_SEPARATOR . $ent; |
$built_files[] = array( |
'file' => $full, |
'dest' => $dest, |
'php_api' => $this->php_api_version, |
'zend_mod_api' => $this->zend_module_api_no, |
'zend_ext_api' => $this->zend_extension_api_no, |
); |
} |
} |
closedir($d); |
return $ret; |
} |
/** |
* Build an extension from source. Runs "phpize" in the source |
* directory, but compiles in a temporary directory |
* (TMPDIR/pear-build-USER/PACKAGE-VERSION). |
* |
* @param string|PEAR_PackageFile_v* $descfile path to XML package description file, or |
* a PEAR_PackageFile object |
* |
* @param mixed $callback callback function used to report output, |
* see PEAR_Builder::_runCommand for details |
* |
* @return array an array of associative arrays with built files, |
* format: |
* array( array( 'file' => '/path/to/ext.so', |
* 'php_api' => YYYYMMDD, |
* 'zend_mod_api' => YYYYMMDD, |
* 'zend_ext_api' => YYYYMMDD ), |
* ... ) |
* |
* @access public |
* |
* @see PEAR_Builder::_runCommand |
*/ |
function build($descfile, $callback = null) |
{ |
if (preg_match('/(\\/|\\\\|^)([^\\/\\\\]+)?php([^\\/\\\\]+)?$/', |
$this->config->get('php_bin'), $matches)) { |
if (isset($matches[2]) && strlen($matches[2]) && |
trim($matches[2]) != trim($this->config->get('php_prefix'))) { |
$this->log(0, 'WARNING: php_bin ' . $this->config->get('php_bin') . |
' appears to have a prefix ' . $matches[2] . ', but' . |
' config variable php_prefix does not match'); |
} |
if (isset($matches[3]) && strlen($matches[3]) && |
trim($matches[3]) != trim($this->config->get('php_suffix'))) { |
$this->log(0, 'WARNING: php_bin ' . $this->config->get('php_bin') . |
' appears to have a suffix ' . $matches[3] . ', but' . |
' config variable php_suffix does not match'); |
} |
} |
$this->current_callback = $callback; |
if (PEAR_OS == "Windows") { |
return $this->_build_win32($descfile, $callback); |
} |
if (PEAR_OS != 'Unix') { |
return $this->raiseError("building extensions not supported on this platform"); |
} |
if (is_object($descfile)) { |
$pkg = $descfile; |
$descfile = $pkg->getPackageFile(); |
if (is_a($pkg, 'PEAR_PackageFile_v1')) { |
$dir = dirname($descfile); |
} else { |
$dir = $pkg->_config->get('temp_dir') . '/' . $pkg->getName(); |
// automatically delete at session end |
$this->addTempFile($dir); |
} |
} else { |
$pf = new PEAR_PackageFile($this->config); |
$pkg = &$pf->fromPackageFile($descfile, PEAR_VALIDATE_NORMAL); |
if (PEAR::isError($pkg)) { |
return $pkg; |
} |
$dir = dirname($descfile); |
} |
// Find config. outside of normal path - e.g. config.m4 |
foreach (array_keys($pkg->getInstallationFileList()) as $item) { |
if (stristr(basename($item), 'config.m4') && dirname($item) != '.') { |
$dir .= DIRECTORY_SEPARATOR . dirname($item); |
break; |
} |
} |
$old_cwd = getcwd(); |
if (!file_exists($dir) || !is_dir($dir) || !chdir($dir)) { |
return $this->raiseError("could not chdir to $dir"); |
} |
$vdir = $pkg->getPackage() . '-' . $pkg->getVersion(); |
if (is_dir($vdir)) { |
chdir($vdir); |
} |
$dir = getcwd(); |
$this->log(2, "building in $dir"); |
putenv('PATH=' . $this->config->get('bin_dir') . ':' . getenv('PATH')); |
$err = $this->_runCommand($this->config->get('php_prefix') |
. "phpize" . |
$this->config->get('php_suffix'), |
array(&$this, 'phpizeCallback')); |
if (PEAR::isError($err)) { |
return $err; |
} |
if (!$err) { |
return $this->raiseError("`phpize' failed"); |
} |
// {{{ start of interactive part |
$configure_command = "$dir/configure"; |
$phpConfigName = $this->config->get('php_prefix') |
. 'php-config' |
. $this->config->get('php_suffix'); |
$phpConfigPath = System::which($phpConfigName); |
if ($phpConfigPath !== false) { |
$configure_command .= ' --with-php-config=' |
. $phpConfigPath; |
} |
$configure_options = $pkg->getConfigureOptions(); |
if ($configure_options) { |
foreach ($configure_options as $o) { |
$default = array_key_exists('default', $o) ? $o['default'] : null; |
list($r) = $this->ui->userDialog('build', |
array($o['prompt']), |
array('text'), |
array($default)); |
if (substr($o['name'], 0, 5) == 'with-' && |
($r == 'yes' || $r == 'autodetect')) { |
$configure_command .= " --$o[name]"; |
} else { |
$configure_command .= " --$o[name]=".trim($r); |
} |
} |
} |
// }}} end of interactive part |
// FIXME make configurable |
if (!$user=getenv('USER')) { |
$user='defaultuser'; |
} |
$tmpdir = $this->config->get('temp_dir'); |
$build_basedir = System::mktemp(' -t "' . $tmpdir . '" -d "pear-build-' . $user . '"'); |
$build_dir = "$build_basedir/$vdir"; |
$inst_dir = "$build_basedir/install-$vdir"; |
$this->log(1, "building in $build_dir"); |
if (is_dir($build_dir)) { |
System::rm(array('-rf', $build_dir)); |
} |
if (!System::mkDir(array('-p', $build_dir))) { |
return $this->raiseError("could not create build dir: $build_dir"); |
} |
$this->addTempFile($build_dir); |
if (!System::mkDir(array('-p', $inst_dir))) { |
return $this->raiseError("could not create temporary install dir: $inst_dir"); |
} |
$this->addTempFile($inst_dir); |
$make_command = getenv('MAKE') ? getenv('MAKE') : 'make'; |
$to_run = array( |
$configure_command, |
$make_command, |
"$make_command INSTALL_ROOT=\"$inst_dir\" install", |
"find \"$inst_dir\" | xargs ls -dils" |
); |
if (!file_exists($build_dir) || !is_dir($build_dir) || !chdir($build_dir)) { |
return $this->raiseError("could not chdir to $build_dir"); |
} |
putenv('PHP_PEAR_VERSION=1.10.1'); |
foreach ($to_run as $cmd) { |
$err = $this->_runCommand($cmd, $callback); |
if (PEAR::isError($err)) { |
chdir($old_cwd); |
return $err; |
} |
if (!$err) { |
chdir($old_cwd); |
return $this->raiseError("`$cmd' failed"); |
} |
} |
if (!($dp = opendir("modules"))) { |
chdir($old_cwd); |
return $this->raiseError("no `modules' directory found"); |
} |
$built_files = array(); |
$prefix = exec($this->config->get('php_prefix') |
. "php-config" . |
$this->config->get('php_suffix') . " --prefix"); |
$this->_harvestInstDir($prefix, $inst_dir . DIRECTORY_SEPARATOR . $prefix, $built_files); |
chdir($old_cwd); |
return $built_files; |
} |
/** |
* Message callback function used when running the "phpize" |
* program. Extracts the API numbers used. Ignores other message |
* types than "cmdoutput". |
* |
* @param string $what the type of message |
* @param mixed $data the message |
* |
* @return void |
* |
* @access public |
*/ |
function phpizeCallback($what, $data) |
{ |
if ($what != 'cmdoutput') { |
return; |
} |
$this->log(1, rtrim($data)); |
if (preg_match('/You should update your .aclocal.m4/', $data)) { |
return; |
} |
$matches = array(); |
if (preg_match('/^\s+(\S[^:]+):\s+(\d{8})/', $data, $matches)) { |
$member = preg_replace('/[^a-z]/', '_', strtolower($matches[1])); |
$apino = (int)$matches[2]; |
if (isset($this->$member)) { |
$this->$member = $apino; |
//$msg = sprintf("%-22s : %d", $matches[1], $apino); |
//$this->log(1, $msg); |
} |
} |
} |
/** |
* Run an external command, using a message callback to report |
* output. The command will be run through popen and output is |
* reported for every line with a "cmdoutput" message with the |
* line string, including newlines, as payload. |
* |
* @param string $command the command to run |
* |
* @param mixed $callback (optional) function to use as message |
* callback |
* |
* @return bool whether the command was successful (exit code 0 |
* means success, any other means failure) |
* |
* @access private |
*/ |
function _runCommand($command, $callback = null) |
{ |
$this->log(1, "running: $command"); |
$pp = popen("$command 2>&1", "r"); |
if (!$pp) { |
return $this->raiseError("failed to run `$command'"); |
} |
if ($callback && $callback[0]->debug == 1) { |
$olddbg = $callback[0]->debug; |
$callback[0]->debug = 2; |
} |
while ($line = fgets($pp, 1024)) { |
if ($callback) { |
call_user_func($callback, 'cmdoutput', $line); |
} else { |
$this->log(2, rtrim($line)); |
} |
} |
if ($callback && isset($olddbg)) { |
$callback[0]->debug = $olddbg; |
} |
$exitcode = is_resource($pp) ? pclose($pp) : -1; |
return ($exitcode == 0); |
} |
function log($level, $msg, $append_crlf = true) |
{ |
if ($this->current_callback) { |
if ($this->debug >= $level) { |
call_user_func($this->current_callback, 'output', $msg); |
} |
return; |
} |
return parent::log($level, $msg, $append_crlf); |
} |
} |
/branches/v1.3-critias/bibliotheque/pear/PEAR/REST/10.php |
---|
New file |
0,0 → 1,870 |
<?php |
/** |
* PEAR_REST_10 |
* |
* PHP versions 4 and 5 |
* |
* @category pear |
* @package PEAR |
* @author Greg Beaver <cellog@php.net> |
* @copyright 1997-2009 The Authors |
* @license http://opensource.org/licenses/bsd-license.php New BSD License |
* @link http://pear.php.net/package/PEAR |
* @since File available since Release 1.4.0a12 |
*/ |
/** |
* For downloading REST xml/txt files |
*/ |
require_once 'PEAR/REST.php'; |
/** |
* Implement REST 1.0 |
* |
* @category pear |
* @package PEAR |
* @author Greg Beaver <cellog@php.net> |
* @copyright 1997-2009 The Authors |
* @license http://opensource.org/licenses/bsd-license.php New BSD License |
* @version Release: 1.10.1 |
* @link http://pear.php.net/package/PEAR |
* @since Class available since Release 1.4.0a12 |
*/ |
class PEAR_REST_10 |
{ |
/** |
* @var PEAR_REST |
*/ |
var $_rest; |
function __construct($config, $options = array()) |
{ |
$this->_rest = new PEAR_REST($config, $options); |
} |
/** |
* Retrieve information about a remote package to be downloaded from a REST server |
* |
* @param string $base The uri to prepend to all REST calls |
* @param array $packageinfo an array of format: |
* <pre> |
* array( |
* 'package' => 'packagename', |
* 'channel' => 'channelname', |
* ['state' => 'alpha' (or valid state),] |
* -or- |
* ['version' => '1.whatever'] |
* </pre> |
* @param string $prefstate Current preferred_state config variable value |
* @param bool $installed the installed version of this package to compare against |
* @return array|false|PEAR_Error see {@link _returnDownloadURL()} |
*/ |
function getDownloadURL($base, $packageinfo, $prefstate, $installed, $channel = false) |
{ |
$states = $this->betterStates($prefstate, true); |
if (!$states) { |
return PEAR::raiseError('"' . $prefstate . '" is not a valid state'); |
} |
$channel = $packageinfo['channel']; |
$package = $packageinfo['package']; |
$state = isset($packageinfo['state']) ? $packageinfo['state'] : null; |
$version = isset($packageinfo['version']) ? $packageinfo['version'] : null; |
$restFile = $base . 'r/' . strtolower($package) . '/allreleases.xml'; |
$info = $this->_rest->retrieveData($restFile, false, false, $channel); |
if (PEAR::isError($info)) { |
return PEAR::raiseError('No releases available for package "' . |
$channel . '/' . $package . '"'); |
} |
if (!isset($info['r'])) { |
return false; |
} |
$release = $found = false; |
if (!is_array($info['r']) || !isset($info['r'][0])) { |
$info['r'] = array($info['r']); |
} |
foreach ($info['r'] as $release) { |
if (!isset($this->_rest->_options['force']) && ($installed && |
version_compare($release['v'], $installed, '<'))) { |
continue; |
} |
if (isset($state)) { |
// try our preferred state first |
if ($release['s'] == $state) { |
$found = true; |
break; |
} |
// see if there is something newer and more stable |
// bug #7221 |
if (in_array($release['s'], $this->betterStates($state), true)) { |
$found = true; |
break; |
} |
} elseif (isset($version)) { |
if ($release['v'] == $version) { |
$found = true; |
break; |
} |
} else { |
if (in_array($release['s'], $states)) { |
$found = true; |
break; |
} |
} |
} |
return $this->_returnDownloadURL($base, $package, $release, $info, $found, false, $channel); |
} |
function getDepDownloadURL($base, $xsdversion, $dependency, $deppackage, |
$prefstate = 'stable', $installed = false, $channel = false) |
{ |
$states = $this->betterStates($prefstate, true); |
if (!$states) { |
return PEAR::raiseError('"' . $prefstate . '" is not a valid state'); |
} |
$channel = $dependency['channel']; |
$package = $dependency['name']; |
$state = isset($dependency['state']) ? $dependency['state'] : null; |
$version = isset($dependency['version']) ? $dependency['version'] : null; |
$restFile = $base . 'r/' . strtolower($package) . '/allreleases.xml'; |
$info = $this->_rest->retrieveData($restFile, false, false, $channel); |
if (PEAR::isError($info)) { |
return PEAR::raiseError('Package "' . $deppackage['channel'] . '/' . $deppackage['package'] |
. '" dependency "' . $channel . '/' . $package . '" has no releases'); |
} |
if (!is_array($info) || !isset($info['r'])) { |
return false; |
} |
$exclude = array(); |
$min = $max = $recommended = false; |
if ($xsdversion == '1.0') { |
switch ($dependency['rel']) { |
case 'ge' : |
$min = $dependency['version']; |
break; |
case 'gt' : |
$min = $dependency['version']; |
$exclude = array($dependency['version']); |
break; |
case 'eq' : |
$recommended = $dependency['version']; |
break; |
case 'lt' : |
$max = $dependency['version']; |
$exclude = array($dependency['version']); |
break; |
case 'le' : |
$max = $dependency['version']; |
break; |
case 'ne' : |
$exclude = array($dependency['version']); |
break; |
} |
} else { |
$min = isset($dependency['min']) ? $dependency['min'] : false; |
$max = isset($dependency['max']) ? $dependency['max'] : false; |
$recommended = isset($dependency['recommended']) ? |
$dependency['recommended'] : false; |
if (isset($dependency['exclude'])) { |
if (!isset($dependency['exclude'][0])) { |
$exclude = array($dependency['exclude']); |
} |
} |
} |
$release = $found = false; |
if (!is_array($info['r']) || !isset($info['r'][0])) { |
$info['r'] = array($info['r']); |
} |
foreach ($info['r'] as $release) { |
if (!isset($this->_rest->_options['force']) && ($installed && |
version_compare($release['v'], $installed, '<'))) { |
continue; |
} |
if (in_array($release['v'], $exclude)) { // skip excluded versions |
continue; |
} |
// allow newer releases to say "I'm OK with the dependent package" |
if ($xsdversion == '2.0' && isset($release['co'])) { |
if (!is_array($release['co']) || !isset($release['co'][0])) { |
$release['co'] = array($release['co']); |
} |
foreach ($release['co'] as $entry) { |
if (isset($entry['x']) && !is_array($entry['x'])) { |
$entry['x'] = array($entry['x']); |
} elseif (!isset($entry['x'])) { |
$entry['x'] = array(); |
} |
if ($entry['c'] == $deppackage['channel'] && |
strtolower($entry['p']) == strtolower($deppackage['package']) && |
version_compare($deppackage['version'], $entry['min'], '>=') && |
version_compare($deppackage['version'], $entry['max'], '<=') && |
!in_array($release['v'], $entry['x'])) { |
$recommended = $release['v']; |
break; |
} |
} |
} |
if ($recommended) { |
if ($release['v'] != $recommended) { // if we want a specific |
// version, then skip all others |
continue; |
} else { |
if (!in_array($release['s'], $states)) { |
// the stability is too low, but we must return the |
// recommended version if possible |
return $this->_returnDownloadURL($base, $package, $release, $info, true, false, $channel); |
} |
} |
} |
if ($min && version_compare($release['v'], $min, 'lt')) { // skip too old versions |
continue; |
} |
if ($max && version_compare($release['v'], $max, 'gt')) { // skip too new versions |
continue; |
} |
if ($installed && version_compare($release['v'], $installed, '<')) { |
continue; |
} |
if (in_array($release['s'], $states)) { // if in the preferred state... |
$found = true; // ... then use it |
break; |
} |
} |
return $this->_returnDownloadURL($base, $package, $release, $info, $found, false, $channel); |
} |
/** |
* Take raw data and return the array needed for processing a download URL |
* |
* @param string $base REST base uri |
* @param string $package Package name |
* @param array $release an array of format array('v' => version, 's' => state) |
* describing the release to download |
* @param array $info list of all releases as defined by allreleases.xml |
* @param bool|null $found determines whether the release was found or this is the next |
* best alternative. If null, then versions were skipped because |
* of PHP dependency |
* @return array|PEAR_Error |
* @access private |
*/ |
function _returnDownloadURL($base, $package, $release, $info, $found, $phpversion = false, $channel = false) |
{ |
if (!$found) { |
$release = $info['r'][0]; |
} |
$packageLower = strtolower($package); |
$pinfo = $this->_rest->retrieveCacheFirst($base . 'p/' . $packageLower . '/' . |
'info.xml', false, false, $channel); |
if (PEAR::isError($pinfo)) { |
return PEAR::raiseError('Package "' . $package . |
'" does not have REST info xml available'); |
} |
$releaseinfo = $this->_rest->retrieveCacheFirst($base . 'r/' . $packageLower . '/' . |
$release['v'] . '.xml', false, false, $channel); |
if (PEAR::isError($releaseinfo)) { |
return PEAR::raiseError('Package "' . $package . '" Version "' . $release['v'] . |
'" does not have REST xml available'); |
} |
$packagexml = $this->_rest->retrieveCacheFirst($base . 'r/' . $packageLower . '/' . |
'deps.' . $release['v'] . '.txt', false, true, $channel); |
if (PEAR::isError($packagexml)) { |
return PEAR::raiseError('Package "' . $package . '" Version "' . $release['v'] . |
'" does not have REST dependency information available'); |
} |
$packagexml = unserialize($packagexml); |
if (!$packagexml) { |
$packagexml = array(); |
} |
$allinfo = $this->_rest->retrieveData($base . 'r/' . $packageLower . |
'/allreleases.xml', false, false, $channel); |
if (PEAR::isError($allinfo)) { |
return $allinfo; |
} |
if (!is_array($allinfo['r']) || !isset($allinfo['r'][0])) { |
$allinfo['r'] = array($allinfo['r']); |
} |
$compatible = false; |
foreach ($allinfo['r'] as $release) { |
if ($release['v'] != $releaseinfo['v']) { |
continue; |
} |
if (!isset($release['co'])) { |
break; |
} |
$compatible = array(); |
if (!is_array($release['co']) || !isset($release['co'][0])) { |
$release['co'] = array($release['co']); |
} |
foreach ($release['co'] as $entry) { |
$comp = array(); |
$comp['name'] = $entry['p']; |
$comp['channel'] = $entry['c']; |
$comp['min'] = $entry['min']; |
$comp['max'] = $entry['max']; |
if (isset($entry['x']) && !is_array($entry['x'])) { |
$comp['exclude'] = $entry['x']; |
} |
$compatible[] = $comp; |
} |
if (count($compatible) == 1) { |
$compatible = $compatible[0]; |
} |
break; |
} |
$deprecated = false; |
if (isset($pinfo['dc']) && isset($pinfo['dp'])) { |
if (is_array($pinfo['dp'])) { |
$deprecated = array('channel' => (string) $pinfo['dc'], |
'package' => trim($pinfo['dp']['_content'])); |
} else { |
$deprecated = array('channel' => (string) $pinfo['dc'], |
'package' => trim($pinfo['dp'])); |
} |
} |
$return = array( |
'version' => $releaseinfo['v'], |
'info' => $packagexml, |
'package' => $releaseinfo['p']['_content'], |
'stability' => $releaseinfo['st'], |
'compatible' => $compatible, |
'deprecated' => $deprecated, |
); |
if ($found) { |
$return['url'] = $releaseinfo['g']; |
return $return; |
} |
$return['php'] = $phpversion; |
return $return; |
} |
function listPackages($base, $channel = false) |
{ |
$packagelist = $this->_rest->retrieveData($base . 'p/packages.xml', false, false, $channel); |
if (PEAR::isError($packagelist)) { |
return $packagelist; |
} |
if (!is_array($packagelist) || !isset($packagelist['p'])) { |
return array(); |
} |
if (!is_array($packagelist['p'])) { |
$packagelist['p'] = array($packagelist['p']); |
} |
return $packagelist['p']; |
} |
/** |
* List all categories of a REST server |
* |
* @param string $base base URL of the server |
* @return array of categorynames |
*/ |
function listCategories($base, $channel = false) |
{ |
$categories = array(); |
// c/categories.xml does not exist; |
// check for every package its category manually |
// This is SLOOOWWWW : /// |
$packagelist = $this->_rest->retrieveData($base . 'p/packages.xml', false, false, $channel); |
if (PEAR::isError($packagelist)) { |
return $packagelist; |
} |
if (!is_array($packagelist) || !isset($packagelist['p'])) { |
$ret = array(); |
return $ret; |
} |
if (!is_array($packagelist['p'])) { |
$packagelist['p'] = array($packagelist['p']); |
} |
PEAR::pushErrorHandling(PEAR_ERROR_RETURN); |
foreach ($packagelist['p'] as $package) { |
$inf = $this->_rest->retrieveData($base . 'p/' . strtolower($package) . '/info.xml', false, false, $channel); |
if (PEAR::isError($inf)) { |
PEAR::popErrorHandling(); |
return $inf; |
} |
$cat = $inf['ca']['_content']; |
if (!isset($categories[$cat])) { |
$categories[$cat] = $inf['ca']; |
} |
} |
return array_values($categories); |
} |
/** |
* List a category of a REST server |
* |
* @param string $base base URL of the server |
* @param string $category name of the category |
* @param boolean $info also download full package info |
* @return array of packagenames |
*/ |
function listCategory($base, $category, $info = false, $channel = false) |
{ |
// gives '404 Not Found' error when category doesn't exist |
$packagelist = $this->_rest->retrieveData($base.'c/'.urlencode($category).'/packages.xml', false, false, $channel); |
if (PEAR::isError($packagelist)) { |
return $packagelist; |
} |
if (!is_array($packagelist) || !isset($packagelist['p'])) { |
return array(); |
} |
if (!is_array($packagelist['p']) || |
!isset($packagelist['p'][0])) { // only 1 pkg |
$packagelist = array($packagelist['p']); |
} else { |
$packagelist = $packagelist['p']; |
} |
if ($info == true) { |
// get individual package info |
PEAR::pushErrorHandling(PEAR_ERROR_RETURN); |
foreach ($packagelist as $i => $packageitem) { |
$url = sprintf('%s'.'r/%s/latest.txt', |
$base, |
strtolower($packageitem['_content'])); |
$version = $this->_rest->retrieveData($url, false, false, $channel); |
if (PEAR::isError($version)) { |
break; // skipit |
} |
$url = sprintf('%s'.'r/%s/%s.xml', |
$base, |
strtolower($packageitem['_content']), |
$version); |
$info = $this->_rest->retrieveData($url, false, false, $channel); |
if (PEAR::isError($info)) { |
break; // skipit |
} |
$packagelist[$i]['info'] = $info; |
} |
PEAR::popErrorHandling(); |
} |
return $packagelist; |
} |
function listAll($base, $dostable, $basic = true, $searchpackage = false, $searchsummary = false, $channel = false) |
{ |
$packagelist = $this->_rest->retrieveData($base . 'p/packages.xml', false, false, $channel); |
if (PEAR::isError($packagelist)) { |
return $packagelist; |
} |
if ($this->_rest->config->get('verbose') > 0) { |
$ui = &PEAR_Frontend::singleton(); |
$ui->log('Retrieving data...0%', true); |
} |
$ret = array(); |
if (!is_array($packagelist) || !isset($packagelist['p'])) { |
return $ret; |
} |
if (!is_array($packagelist['p'])) { |
$packagelist['p'] = array($packagelist['p']); |
} |
// only search-packagename = quicksearch ! |
if ($searchpackage && (!$searchsummary || empty($searchpackage))) { |
$newpackagelist = array(); |
foreach ($packagelist['p'] as $package) { |
if (!empty($searchpackage) && stristr($package, $searchpackage) !== false) { |
$newpackagelist[] = $package; |
} |
} |
$packagelist['p'] = $newpackagelist; |
} |
PEAR::pushErrorHandling(PEAR_ERROR_RETURN); |
$next = .1; |
foreach ($packagelist['p'] as $progress => $package) { |
if ($this->_rest->config->get('verbose') > 0) { |
if ($progress / count($packagelist['p']) >= $next) { |
if ($next == .5) { |
$ui->log('50%', false); |
} else { |
$ui->log('.', false); |
} |
$next += .1; |
} |
} |
if ($basic) { // remote-list command |
if ($dostable) { |
$latest = $this->_rest->retrieveData($base . 'r/' . strtolower($package) . |
'/stable.txt', false, false, $channel); |
} else { |
$latest = $this->_rest->retrieveData($base . 'r/' . strtolower($package) . |
'/latest.txt', false, false, $channel); |
} |
if (PEAR::isError($latest)) { |
$latest = false; |
} |
$info = array('stable' => $latest); |
} else { // list-all command |
$inf = $this->_rest->retrieveData($base . 'p/' . strtolower($package) . '/info.xml', false, false, $channel); |
if (PEAR::isError($inf)) { |
PEAR::popErrorHandling(); |
return $inf; |
} |
if ($searchpackage) { |
$found = (!empty($searchpackage) && stristr($package, $searchpackage) !== false); |
if (!$found && !(isset($searchsummary) && !empty($searchsummary) |
&& (stristr($inf['s'], $searchsummary) !== false |
|| stristr($inf['d'], $searchsummary) !== false))) |
{ |
continue; |
}; |
} |
$releases = $this->_rest->retrieveData($base . 'r/' . strtolower($package) . |
'/allreleases.xml', false, false, $channel); |
if (PEAR::isError($releases)) { |
continue; |
} |
if (!isset($releases['r'][0])) { |
$releases['r'] = array($releases['r']); |
} |
unset($latest); |
unset($unstable); |
unset($stable); |
unset($state); |
foreach ($releases['r'] as $release) { |
if (!isset($latest)) { |
if ($dostable && $release['s'] == 'stable') { |
$latest = $release['v']; |
$state = 'stable'; |
} |
if (!$dostable) { |
$latest = $release['v']; |
$state = $release['s']; |
} |
} |
if (!isset($stable) && $release['s'] == 'stable') { |
$stable = $release['v']; |
if (!isset($unstable)) { |
$unstable = $stable; |
} |
} |
if (!isset($unstable) && $release['s'] != 'stable') { |
$latest = $unstable = $release['v']; |
$state = $release['s']; |
} |
if (isset($latest) && !isset($state)) { |
$state = $release['s']; |
} |
if (isset($latest) && isset($stable) && isset($unstable)) { |
break; |
} |
} |
$deps = array(); |
if (!isset($unstable)) { |
$unstable = false; |
$state = 'stable'; |
if (isset($stable)) { |
$latest = $unstable = $stable; |
} |
} else { |
$latest = $unstable; |
} |
if (!isset($latest)) { |
$latest = false; |
} |
if ($latest) { |
$d = $this->_rest->retrieveCacheFirst($base . 'r/' . strtolower($package) . '/deps.' . |
$latest . '.txt', false, false, $channel); |
if (!PEAR::isError($d)) { |
$d = unserialize($d); |
if ($d) { |
if (isset($d['required'])) { |
if (!class_exists('PEAR_PackageFile_v2')) { |
require_once 'PEAR/PackageFile/v2.php'; |
} |
if (!isset($pf)) { |
$pf = new PEAR_PackageFile_v2; |
} |
$pf->setDeps($d); |
$tdeps = $pf->getDeps(); |
} else { |
$tdeps = $d; |
} |
foreach ($tdeps as $dep) { |
if ($dep['type'] !== 'pkg') { |
continue; |
} |
$deps[] = $dep; |
} |
} |
} |
} |
if (!isset($stable)) { |
$stable = '-n/a-'; |
} |
if (!$searchpackage) { |
$info = array('stable' => $latest, 'summary' => $inf['s'], 'description' => |
$inf['d'], 'deps' => $deps, 'category' => $inf['ca']['_content'], |
'unstable' => $unstable, 'state' => $state); |
} else { |
$info = array('stable' => $stable, 'summary' => $inf['s'], 'description' => |
$inf['d'], 'deps' => $deps, 'category' => $inf['ca']['_content'], |
'unstable' => $unstable, 'state' => $state); |
} |
} |
$ret[$package] = $info; |
} |
PEAR::popErrorHandling(); |
return $ret; |
} |
function listLatestUpgrades($base, $pref_state, $installed, $channel, &$reg) |
{ |
$packagelist = $this->_rest->retrieveData($base . 'p/packages.xml', false, false, $channel); |
if (PEAR::isError($packagelist)) { |
return $packagelist; |
} |
$ret = array(); |
if (!is_array($packagelist) || !isset($packagelist['p'])) { |
return $ret; |
} |
if (!is_array($packagelist['p'])) { |
$packagelist['p'] = array($packagelist['p']); |
} |
foreach ($packagelist['p'] as $package) { |
if (!isset($installed[strtolower($package)])) { |
continue; |
} |
$inst_version = $reg->packageInfo($package, 'version', $channel); |
$inst_state = $reg->packageInfo($package, 'release_state', $channel); |
PEAR::pushErrorHandling(PEAR_ERROR_RETURN); |
$info = $this->_rest->retrieveData($base . 'r/' . strtolower($package) . |
'/allreleases.xml', false, false, $channel); |
PEAR::popErrorHandling(); |
if (PEAR::isError($info)) { |
continue; // no remote releases |
} |
if (!isset($info['r'])) { |
continue; |
} |
$release = $found = false; |
if (!is_array($info['r']) || !isset($info['r'][0])) { |
$info['r'] = array($info['r']); |
} |
// $info['r'] is sorted by version number |
usort($info['r'], array($this, '_sortReleasesByVersionNumber')); |
foreach ($info['r'] as $release) { |
if ($inst_version && version_compare($release['v'], $inst_version, '<=')) { |
// not newer than the one installed |
break; |
} |
// new version > installed version |
if (!$pref_state) { |
// every state is a good state |
$found = true; |
break; |
} else { |
$new_state = $release['s']; |
// if new state >= installed state: go |
if (in_array($new_state, $this->betterStates($inst_state, true))) { |
$found = true; |
break; |
} else { |
// only allow to lower the state of package, |
// if new state >= preferred state: go |
if (in_array($new_state, $this->betterStates($pref_state, true))) { |
$found = true; |
break; |
} |
} |
} |
} |
if (!$found) { |
continue; |
} |
$relinfo = $this->_rest->retrieveCacheFirst($base . 'r/' . strtolower($package) . '/' . |
$release['v'] . '.xml', false, false, $channel); |
if (PEAR::isError($relinfo)) { |
return $relinfo; |
} |
$ret[$package] = array( |
'version' => $release['v'], |
'state' => $release['s'], |
'filesize' => $relinfo['f'], |
); |
} |
return $ret; |
} |
function packageInfo($base, $package, $channel = false) |
{ |
PEAR::pushErrorHandling(PEAR_ERROR_RETURN); |
$pinfo = $this->_rest->retrieveData($base . 'p/' . strtolower($package) . '/info.xml', false, false, $channel); |
if (PEAR::isError($pinfo)) { |
PEAR::popErrorHandling(); |
return PEAR::raiseError('Unknown package: "' . $package . '" in channel "' . $channel . '"' . "\n". 'Debug: ' . |
$pinfo->getMessage()); |
} |
$releases = array(); |
$allreleases = $this->_rest->retrieveData($base . 'r/' . strtolower($package) . |
'/allreleases.xml', false, false, $channel); |
if (!PEAR::isError($allreleases)) { |
if (!class_exists('PEAR_PackageFile_v2')) { |
require_once 'PEAR/PackageFile/v2.php'; |
} |
if (!is_array($allreleases['r']) || !isset($allreleases['r'][0])) { |
$allreleases['r'] = array($allreleases['r']); |
} |
$pf = new PEAR_PackageFile_v2; |
foreach ($allreleases['r'] as $release) { |
$ds = $this->_rest->retrieveCacheFirst($base . 'r/' . strtolower($package) . '/deps.' . |
$release['v'] . '.txt', false, false, $channel); |
if (PEAR::isError($ds)) { |
continue; |
} |
if (!isset($latest)) { |
$latest = $release['v']; |
} |
$pf->setDeps(unserialize($ds)); |
$ds = $pf->getDeps(); |
$info = $this->_rest->retrieveCacheFirst($base . 'r/' . strtolower($package) |
. '/' . $release['v'] . '.xml', false, false, $channel); |
if (PEAR::isError($info)) { |
continue; |
} |
$releases[$release['v']] = array( |
'doneby' => $info['m'], |
'license' => $info['l'], |
'summary' => $info['s'], |
'description' => $info['d'], |
'releasedate' => $info['da'], |
'releasenotes' => $info['n'], |
'state' => $release['s'], |
'deps' => $ds ? $ds : array(), |
); |
} |
} else { |
$latest = ''; |
} |
PEAR::popErrorHandling(); |
if (isset($pinfo['dc']) && isset($pinfo['dp'])) { |
if (is_array($pinfo['dp'])) { |
$deprecated = array('channel' => (string) $pinfo['dc'], |
'package' => trim($pinfo['dp']['_content'])); |
} else { |
$deprecated = array('channel' => (string) $pinfo['dc'], |
'package' => trim($pinfo['dp'])); |
} |
} else { |
$deprecated = false; |
} |
if (!isset($latest)) { |
$latest = ''; |
} |
return array( |
'name' => $pinfo['n'], |
'channel' => $pinfo['c'], |
'category' => $pinfo['ca']['_content'], |
'stable' => $latest, |
'license' => $pinfo['l'], |
'summary' => $pinfo['s'], |
'description' => $pinfo['d'], |
'releases' => $releases, |
'deprecated' => $deprecated, |
); |
} |
/** |
* Return an array containing all of the states that are more stable than |
* or equal to the passed in state |
* |
* @param string Release state |
* @param boolean Determines whether to include $state in the list |
* @return false|array False if $state is not a valid release state |
*/ |
function betterStates($state, $include = false) |
{ |
static $states = array('snapshot', 'devel', 'alpha', 'beta', 'stable'); |
$i = array_search($state, $states); |
if ($i === false) { |
return false; |
} |
if ($include) { |
$i--; |
} |
return array_slice($states, $i + 1); |
} |
/** |
* Sort releases by version number |
* |
* @access private |
*/ |
function _sortReleasesByVersionNumber($a, $b) |
{ |
if (version_compare($a['v'], $b['v'], '=')) { |
return 0; |
} |
if (version_compare($a['v'], $b['v'], '>')) { |
return -1; |
} |
if (version_compare($a['v'], $b['v'], '<')) { |
return 1; |
} |
} |
} |
/branches/v1.3-critias/bibliotheque/pear/PEAR/REST/11.php |
---|
New file |
0,0 → 1,340 |
<?php |
/** |
* PEAR_REST_11 - implement faster list-all/remote-list command |
* |
* PHP versions 4 and 5 |
* |
* @category pear |
* @package PEAR |
* @author Greg Beaver <cellog@php.net> |
* @copyright 1997-2009 The Authors |
* @license http://opensource.org/licenses/bsd-license.php New BSD License |
* @link http://pear.php.net/package/PEAR |
* @since File available since Release 1.4.3 |
*/ |
/** |
* For downloading REST xml/txt files |
*/ |
require_once 'PEAR/REST.php'; |
/** |
* Implement REST 1.1 |
* |
* @category pear |
* @package PEAR |
* @author Greg Beaver <cellog@php.net> |
* @copyright 1997-2009 The Authors |
* @license http://opensource.org/licenses/bsd-license.php New BSD License |
* @version Release: 1.10.1 |
* @link http://pear.php.net/package/PEAR |
* @since Class available since Release 1.4.3 |
*/ |
class PEAR_REST_11 |
{ |
/** |
* @var PEAR_REST |
*/ |
var $_rest; |
function __construct($config, $options = array()) |
{ |
$this->_rest = new PEAR_REST($config, $options); |
} |
function listAll($base, $dostable, $basic = true, $searchpackage = false, $searchsummary = false, $channel = false) |
{ |
$categorylist = $this->_rest->retrieveData($base . 'c/categories.xml', false, false, $channel); |
if (PEAR::isError($categorylist)) { |
return $categorylist; |
} |
$ret = array(); |
if (!is_array($categorylist['c']) || !isset($categorylist['c'][0])) { |
$categorylist['c'] = array($categorylist['c']); |
} |
PEAR::pushErrorHandling(PEAR_ERROR_RETURN); |
foreach ($categorylist['c'] as $progress => $category) { |
$category = $category['_content']; |
$packagesinfo = $this->_rest->retrieveData($base . |
'c/' . urlencode($category) . '/packagesinfo.xml', false, false, $channel); |
if (PEAR::isError($packagesinfo)) { |
continue; |
} |
if (!is_array($packagesinfo) || !isset($packagesinfo['pi'])) { |
continue; |
} |
if (!is_array($packagesinfo['pi']) || !isset($packagesinfo['pi'][0])) { |
$packagesinfo['pi'] = array($packagesinfo['pi']); |
} |
foreach ($packagesinfo['pi'] as $packageinfo) { |
if (empty($packageinfo)) { |
continue; |
} |
$info = $packageinfo['p']; |
$package = $info['n']; |
$releases = isset($packageinfo['a']) ? $packageinfo['a'] : false; |
unset($latest); |
unset($unstable); |
unset($stable); |
unset($state); |
if ($releases) { |
if (!isset($releases['r'][0])) { |
$releases['r'] = array($releases['r']); |
} |
foreach ($releases['r'] as $release) { |
if (!isset($latest)) { |
if ($dostable && $release['s'] == 'stable') { |
$latest = $release['v']; |
$state = 'stable'; |
} |
if (!$dostable) { |
$latest = $release['v']; |
$state = $release['s']; |
} |
} |
if (!isset($stable) && $release['s'] == 'stable') { |
$stable = $release['v']; |
if (!isset($unstable)) { |
$unstable = $stable; |
} |
} |
if (!isset($unstable) && $release['s'] != 'stable') { |
$unstable = $release['v']; |
$state = $release['s']; |
} |
if (isset($latest) && !isset($state)) { |
$state = $release['s']; |
} |
if (isset($latest) && isset($stable) && isset($unstable)) { |
break; |
} |
} |
} |
if ($basic) { // remote-list command |
if (!isset($latest)) { |
$latest = false; |
} |
if ($dostable) { |
// $state is not set if there are no releases |
if (isset($state) && $state == 'stable') { |
$ret[$package] = array('stable' => $latest); |
} else { |
$ret[$package] = array('stable' => '-n/a-'); |
} |
} else { |
$ret[$package] = array('stable' => $latest); |
} |
continue; |
} |
// list-all command |
if (!isset($unstable)) { |
$unstable = false; |
$state = 'stable'; |
if (isset($stable)) { |
$latest = $unstable = $stable; |
} |
} else { |
$latest = $unstable; |
} |
if (!isset($latest)) { |
$latest = false; |
} |
$deps = array(); |
if ($latest && isset($packageinfo['deps'])) { |
if (!is_array($packageinfo['deps']) || |
!isset($packageinfo['deps'][0]) |
) { |
$packageinfo['deps'] = array($packageinfo['deps']); |
} |
$d = false; |
foreach ($packageinfo['deps'] as $dep) { |
if ($dep['v'] == $latest) { |
$d = unserialize($dep['d']); |
} |
} |
if ($d) { |
if (isset($d['required'])) { |
if (!class_exists('PEAR_PackageFile_v2')) { |
require_once 'PEAR/PackageFile/v2.php'; |
} |
if (!isset($pf)) { |
$pf = new PEAR_PackageFile_v2; |
} |
$pf->setDeps($d); |
$tdeps = $pf->getDeps(); |
} else { |
$tdeps = $d; |
} |
foreach ($tdeps as $dep) { |
if ($dep['type'] !== 'pkg') { |
continue; |
} |
$deps[] = $dep; |
} |
} |
} |
$info = array( |
'stable' => $latest, |
'summary' => $info['s'], |
'description' => $info['d'], |
'deps' => $deps, |
'category' => $info['ca']['_content'], |
'unstable' => $unstable, |
'state' => $state |
); |
$ret[$package] = $info; |
} |
} |
PEAR::popErrorHandling(); |
return $ret; |
} |
/** |
* List all categories of a REST server |
* |
* @param string $base base URL of the server |
* @return array of categorynames |
*/ |
function listCategories($base, $channel = false) |
{ |
$categorylist = $this->_rest->retrieveData($base . 'c/categories.xml', false, false, $channel); |
if (PEAR::isError($categorylist)) { |
return $categorylist; |
} |
if (!is_array($categorylist) || !isset($categorylist['c'])) { |
return array(); |
} |
if (isset($categorylist['c']['_content'])) { |
// only 1 category |
$categorylist['c'] = array($categorylist['c']); |
} |
return $categorylist['c']; |
} |
/** |
* List packages in a category of a REST server |
* |
* @param string $base base URL of the server |
* @param string $category name of the category |
* @param boolean $info also download full package info |
* @return array of packagenames |
*/ |
function listCategory($base, $category, $info = false, $channel = false) |
{ |
if ($info == false) { |
$url = '%s'.'c/%s/packages.xml'; |
} else { |
$url = '%s'.'c/%s/packagesinfo.xml'; |
} |
$url = sprintf($url, |
$base, |
urlencode($category)); |
// gives '404 Not Found' error when category doesn't exist |
$packagelist = $this->_rest->retrieveData($url, false, false, $channel); |
if (PEAR::isError($packagelist)) { |
return $packagelist; |
} |
if (!is_array($packagelist)) { |
return array(); |
} |
if ($info == false) { |
if (!isset($packagelist['p'])) { |
return array(); |
} |
if (!is_array($packagelist['p']) || |
!isset($packagelist['p'][0])) { // only 1 pkg |
$packagelist = array($packagelist['p']); |
} else { |
$packagelist = $packagelist['p']; |
} |
return $packagelist; |
} |
// info == true |
if (!isset($packagelist['pi'])) { |
return array(); |
} |
if (!is_array($packagelist['pi']) || |
!isset($packagelist['pi'][0])) { // only 1 pkg |
$packagelist_pre = array($packagelist['pi']); |
} else { |
$packagelist_pre = $packagelist['pi']; |
} |
$packagelist = array(); |
foreach ($packagelist_pre as $i => $item) { |
// compatibility with r/<latest.txt>.xml |
if (isset($item['a']['r'][0])) { |
// multiple releases |
$item['p']['v'] = $item['a']['r'][0]['v']; |
$item['p']['st'] = $item['a']['r'][0]['s']; |
} elseif (isset($item['a'])) { |
// first and only release |
$item['p']['v'] = $item['a']['r']['v']; |
$item['p']['st'] = $item['a']['r']['s']; |
} |
$packagelist[$i] = array('attribs' => $item['p']['r'], |
'_content' => $item['p']['n'], |
'info' => $item['p']); |
} |
return $packagelist; |
} |
/** |
* Return an array containing all of the states that are more stable than |
* or equal to the passed in state |
* |
* @param string Release state |
* @param boolean Determines whether to include $state in the list |
* @return false|array False if $state is not a valid release state |
*/ |
function betterStates($state, $include = false) |
{ |
static $states = array('snapshot', 'devel', 'alpha', 'beta', 'stable'); |
$i = array_search($state, $states); |
if ($i === false) { |
return false; |
} |
if ($include) { |
$i--; |
} |
return array_slice($states, $i + 1); |
} |
} |
?> |
/branches/v1.3-critias/bibliotheque/pear/PEAR/REST/13.php |
---|
New file |
0,0 → 1,396 |
<?php |
/** |
* PEAR_REST_13 |
* |
* PHP versions 4 and 5 |
* |
* @category pear |
* @package PEAR |
* @author Greg Beaver <cellog@php.net> |
* @copyright 1997-2009 The Authors |
* @license http://opensource.org/licenses/bsd-license.php New BSD License |
* @link http://pear.php.net/package/PEAR |
* @since File available since Release 1.4.0a12 |
*/ |
/** |
* For downloading REST xml/txt files |
*/ |
require_once 'PEAR/REST.php'; |
require_once 'PEAR/REST/10.php'; |
/** |
* Implement REST 1.3 |
* |
* @category pear |
* @package PEAR |
* @author Greg Beaver <cellog@php.net> |
* @copyright 1997-2009 The Authors |
* @license http://opensource.org/licenses/bsd-license.php New BSD License |
* @version Release: 1.10.1 |
* @link http://pear.php.net/package/PEAR |
* @since Class available since Release 1.4.0a12 |
*/ |
class PEAR_REST_13 extends PEAR_REST_10 |
{ |
/** |
* Retrieve information about a remote package to be downloaded from a REST server |
* |
* This is smart enough to resolve the minimum PHP version dependency prior to download |
* @param string $base The uri to prepend to all REST calls |
* @param array $packageinfo an array of format: |
* <pre> |
* array( |
* 'package' => 'packagename', |
* 'channel' => 'channelname', |
* ['state' => 'alpha' (or valid state),] |
* -or- |
* ['version' => '1.whatever'] |
* </pre> |
* @param string $prefstate Current preferred_state config variable value |
* @param bool $installed the installed version of this package to compare against |
* @return array|false|PEAR_Error see {@link _returnDownloadURL()} |
*/ |
function getDownloadURL($base, $packageinfo, $prefstate, $installed, $channel = false) |
{ |
$states = $this->betterStates($prefstate, true); |
if (!$states) { |
return PEAR::raiseError('"' . $prefstate . '" is not a valid state'); |
} |
$channel = $packageinfo['channel']; |
$package = $packageinfo['package']; |
$state = isset($packageinfo['state']) ? $packageinfo['state'] : null; |
$version = isset($packageinfo['version']) ? $packageinfo['version'] : null; |
$restFile = $base . 'r/' . strtolower($package) . '/allreleases2.xml'; |
$info = $this->_rest->retrieveData($restFile, false, false, $channel); |
if (PEAR::isError($info)) { |
return PEAR::raiseError('No releases available for package "' . |
$channel . '/' . $package . '"'); |
} |
if (!isset($info['r'])) { |
return false; |
} |
$release = $found = false; |
if (!is_array($info['r']) || !isset($info['r'][0])) { |
$info['r'] = array($info['r']); |
} |
$skippedphp = false; |
foreach ($info['r'] as $release) { |
if (!isset($this->_rest->_options['force']) && ($installed && |
version_compare($release['v'], $installed, '<'))) { |
continue; |
} |
if (isset($state)) { |
// try our preferred state first |
if ($release['s'] == $state) { |
if (!isset($version) && version_compare($release['m'], phpversion(), '>')) { |
// skip releases that require a PHP version newer than our PHP version |
$skippedphp = $release; |
continue; |
} |
$found = true; |
break; |
} |
// see if there is something newer and more stable |
// bug #7221 |
if (in_array($release['s'], $this->betterStates($state), true)) { |
if (!isset($version) && version_compare($release['m'], phpversion(), '>')) { |
// skip releases that require a PHP version newer than our PHP version |
$skippedphp = $release; |
continue; |
} |
$found = true; |
break; |
} |
} elseif (isset($version)) { |
if ($release['v'] == $version) { |
if (!isset($this->_rest->_options['force']) && |
!isset($version) && |
version_compare($release['m'], phpversion(), '>')) { |
// skip releases that require a PHP version newer than our PHP version |
$skippedphp = $release; |
continue; |
} |
$found = true; |
break; |
} |
} else { |
if (in_array($release['s'], $states)) { |
if (version_compare($release['m'], phpversion(), '>')) { |
// skip releases that require a PHP version newer than our PHP version |
$skippedphp = $release; |
continue; |
} |
$found = true; |
break; |
} |
} |
} |
if (!$found && $skippedphp) { |
$found = null; |
} |
return $this->_returnDownloadURL($base, $package, $release, $info, $found, $skippedphp, $channel); |
} |
function getDepDownloadURL($base, $xsdversion, $dependency, $deppackage, |
$prefstate = 'stable', $installed = false, $channel = false) |
{ |
$states = $this->betterStates($prefstate, true); |
if (!$states) { |
return PEAR::raiseError('"' . $prefstate . '" is not a valid state'); |
} |
$channel = $dependency['channel']; |
$package = $dependency['name']; |
$state = isset($dependency['state']) ? $dependency['state'] : null; |
$version = isset($dependency['version']) ? $dependency['version'] : null; |
$restFile = $base . 'r/' . strtolower($package) .'/allreleases2.xml'; |
$info = $this->_rest->retrieveData($restFile, false, false, $channel); |
if (PEAR::isError($info)) { |
return PEAR::raiseError('Package "' . $deppackage['channel'] . '/' . $deppackage['package'] |
. '" dependency "' . $channel . '/' . $package . '" has no releases'); |
} |
if (!is_array($info) || !isset($info['r'])) { |
return false; |
} |
$exclude = array(); |
$min = $max = $recommended = false; |
if ($xsdversion == '1.0') { |
$pinfo['package'] = $dependency['name']; |
$pinfo['channel'] = 'pear.php.net'; // this is always true - don't change this |
switch ($dependency['rel']) { |
case 'ge' : |
$min = $dependency['version']; |
break; |
case 'gt' : |
$min = $dependency['version']; |
$exclude = array($dependency['version']); |
break; |
case 'eq' : |
$recommended = $dependency['version']; |
break; |
case 'lt' : |
$max = $dependency['version']; |
$exclude = array($dependency['version']); |
break; |
case 'le' : |
$max = $dependency['version']; |
break; |
case 'ne' : |
$exclude = array($dependency['version']); |
break; |
} |
} else { |
$pinfo['package'] = $dependency['name']; |
$min = isset($dependency['min']) ? $dependency['min'] : false; |
$max = isset($dependency['max']) ? $dependency['max'] : false; |
$recommended = isset($dependency['recommended']) ? |
$dependency['recommended'] : false; |
if (isset($dependency['exclude'])) { |
if (!isset($dependency['exclude'][0])) { |
$exclude = array($dependency['exclude']); |
} |
} |
} |
$skippedphp = $found = $release = false; |
if (!is_array($info['r']) || !isset($info['r'][0])) { |
$info['r'] = array($info['r']); |
} |
foreach ($info['r'] as $release) { |
if (!isset($this->_rest->_options['force']) && ($installed && |
version_compare($release['v'], $installed, '<'))) { |
continue; |
} |
if (in_array($release['v'], $exclude)) { // skip excluded versions |
continue; |
} |
// allow newer releases to say "I'm OK with the dependent package" |
if ($xsdversion == '2.0' && isset($release['co'])) { |
if (!is_array($release['co']) || !isset($release['co'][0])) { |
$release['co'] = array($release['co']); |
} |
foreach ($release['co'] as $entry) { |
if (isset($entry['x']) && !is_array($entry['x'])) { |
$entry['x'] = array($entry['x']); |
} elseif (!isset($entry['x'])) { |
$entry['x'] = array(); |
} |
if ($entry['c'] == $deppackage['channel'] && |
strtolower($entry['p']) == strtolower($deppackage['package']) && |
version_compare($deppackage['version'], $entry['min'], '>=') && |
version_compare($deppackage['version'], $entry['max'], '<=') && |
!in_array($release['v'], $entry['x'])) { |
if (version_compare($release['m'], phpversion(), '>')) { |
// skip dependency releases that require a PHP version |
// newer than our PHP version |
$skippedphp = $release; |
continue; |
} |
$recommended = $release['v']; |
break; |
} |
} |
} |
if ($recommended) { |
if ($release['v'] != $recommended) { // if we want a specific |
// version, then skip all others |
continue; |
} |
if (!in_array($release['s'], $states)) { |
// the stability is too low, but we must return the |
// recommended version if possible |
return $this->_returnDownloadURL($base, $package, $release, $info, true, false, $channel); |
} |
} |
if ($min && version_compare($release['v'], $min, 'lt')) { // skip too old versions |
continue; |
} |
if ($max && version_compare($release['v'], $max, 'gt')) { // skip too new versions |
continue; |
} |
if ($installed && version_compare($release['v'], $installed, '<')) { |
continue; |
} |
if (in_array($release['s'], $states)) { // if in the preferred state... |
if (version_compare($release['m'], phpversion(), '>')) { |
// skip dependency releases that require a PHP version |
// newer than our PHP version |
$skippedphp = $release; |
continue; |
} |
$found = true; // ... then use it |
break; |
} |
} |
if (!$found && $skippedphp) { |
$found = null; |
} |
return $this->_returnDownloadURL($base, $package, $release, $info, $found, $skippedphp, $channel); |
} |
/** |
* List package upgrades but take the PHP version into account. |
*/ |
function listLatestUpgrades($base, $pref_state, $installed, $channel, &$reg) |
{ |
$packagelist = $this->_rest->retrieveData($base . 'p/packages.xml', false, false, $channel); |
if (PEAR::isError($packagelist)) { |
return $packagelist; |
} |
$ret = array(); |
if (!is_array($packagelist) || !isset($packagelist['p'])) { |
return $ret; |
} |
if (!is_array($packagelist['p'])) { |
$packagelist['p'] = array($packagelist['p']); |
} |
foreach ($packagelist['p'] as $package) { |
if (!isset($installed[strtolower($package)])) { |
continue; |
} |
$inst_version = $reg->packageInfo($package, 'version', $channel); |
$inst_state = $reg->packageInfo($package, 'release_state', $channel); |
PEAR::pushErrorHandling(PEAR_ERROR_RETURN); |
$info = $this->_rest->retrieveData($base . 'r/' . strtolower($package) . |
'/allreleases2.xml', false, false, $channel); |
PEAR::popErrorHandling(); |
if (PEAR::isError($info)) { |
continue; // no remote releases |
} |
if (!isset($info['r'])) { |
continue; |
} |
$release = $found = false; |
if (!is_array($info['r']) || !isset($info['r'][0])) { |
$info['r'] = array($info['r']); |
} |
// $info['r'] is sorted by version number |
usort($info['r'], array($this, '_sortReleasesByVersionNumber')); |
foreach ($info['r'] as $release) { |
if ($inst_version && version_compare($release['v'], $inst_version, '<=')) { |
// not newer than the one installed |
break; |
} |
if (version_compare($release['m'], phpversion(), '>')) { |
// skip dependency releases that require a PHP version |
// newer than our PHP version |
continue; |
} |
// new version > installed version |
if (!$pref_state) { |
// every state is a good state |
$found = true; |
break; |
} else { |
$new_state = $release['s']; |
// if new state >= installed state: go |
if (in_array($new_state, $this->betterStates($inst_state, true))) { |
$found = true; |
break; |
} else { |
// only allow to lower the state of package, |
// if new state >= preferred state: go |
if (in_array($new_state, $this->betterStates($pref_state, true))) { |
$found = true; |
break; |
} |
} |
} |
} |
if (!$found) { |
continue; |
} |
$relinfo = $this->_rest->retrieveCacheFirst($base . 'r/' . strtolower($package) . '/' . |
$release['v'] . '.xml', false, false, $channel); |
if (PEAR::isError($relinfo)) { |
return $relinfo; |
} |
$ret[$package] = array( |
'version' => $release['v'], |
'state' => $release['s'], |
'filesize' => $relinfo['f'], |
); |
} |
return $ret; |
} |
} |
/branches/v1.3-critias/bibliotheque/pear/PEAR/Command/Test.xml |
---|
New file |
0,0 → 1,54 |
<commands version="1.0"> |
<run-tests> |
<summary>Run Regression Tests</summary> |
<function>doRunTests</function> |
<shortcut>rt</shortcut> |
<options> |
<recur> |
<shortopt>r</shortopt> |
<doc>Run tests in child directories, recursively. 4 dirs deep maximum</doc> |
</recur> |
<ini> |
<shortopt>i</shortopt> |
<doc>actual string of settings to pass to php in format " -d setting=blah"</doc> |
<arg>SETTINGS</arg> |
</ini> |
<realtimelog> |
<shortopt>l</shortopt> |
<doc>Log test runs/results as they are run</doc> |
</realtimelog> |
<quiet> |
<shortopt>q</shortopt> |
<doc>Only display detail for failed tests</doc> |
</quiet> |
<simple> |
<shortopt>s</shortopt> |
<doc>Display simple output for all tests</doc> |
</simple> |
<package> |
<shortopt>p</shortopt> |
<doc>Treat parameters as installed packages from which to run tests</doc> |
</package> |
<phpunit> |
<shortopt>u</shortopt> |
<doc>Search parameters for AllTests.php, and use that to run phpunit-based tests |
If none is found, all .phpt tests will be tried instead.</doc> |
</phpunit> |
<tapoutput> |
<shortopt>t</shortopt> |
<doc>Output run-tests.log in TAP-compliant format</doc> |
</tapoutput> |
<cgi> |
<shortopt>c</shortopt> |
<doc>CGI php executable (needed for tests with POST/GET section)</doc> |
<arg>PHPCGI</arg> |
</cgi> |
<coverage> |
<shortopt>x</shortopt> |
<doc>Generate a code coverage report (requires Xdebug 2.0.0+)</doc> |
</coverage> |
</options> |
<doc>[testfile|dir ...] |
Run regression tests with PHP's regression testing script (run-tests.php).</doc> |
</run-tests> |
</commands> |
/branches/v1.3-critias/bibliotheque/pear/PEAR/Command/Common.php |
---|
New file |
0,0 → 1,272 |
<?php |
/** |
* PEAR_Command_Common base class |
* |
* PHP versions 4 and 5 |
* |
* @category pear |
* @package PEAR |
* @author Stig Bakken <ssb@php.net> |
* @author Greg Beaver <cellog@php.net> |
* @copyright 1997-2009 The Authors |
* @license http://opensource.org/licenses/bsd-license.php New BSD License |
* @link http://pear.php.net/package/PEAR |
* @since File available since Release 0.1 |
*/ |
/** |
* base class |
*/ |
require_once 'PEAR.php'; |
/** |
* PEAR commands base class |
* |
* @category pear |
* @package PEAR |
* @author Stig Bakken <ssb@php.net> |
* @author Greg Beaver <cellog@php.net> |
* @copyright 1997-2009 The Authors |
* @license http://opensource.org/licenses/bsd-license.php New BSD License |
* @version Release: 1.10.1 |
* @link http://pear.php.net/package/PEAR |
* @since Class available since Release 0.1 |
*/ |
class PEAR_Command_Common extends PEAR |
{ |
/** |
* PEAR_Config object used to pass user system and configuration |
* on when executing commands |
* |
* @var PEAR_Config |
*/ |
var $config; |
/** |
* @var PEAR_Registry |
* @access protected |
*/ |
var $_registry; |
/** |
* User Interface object, for all interaction with the user. |
* @var object |
*/ |
var $ui; |
var $_deps_rel_trans = array( |
'lt' => '<', |
'le' => '<=', |
'eq' => '=', |
'ne' => '!=', |
'gt' => '>', |
'ge' => '>=', |
'has' => '==' |
); |
var $_deps_type_trans = array( |
'pkg' => 'package', |
'ext' => 'extension', |
'php' => 'PHP', |
'prog' => 'external program', |
'ldlib' => 'external library for linking', |
'rtlib' => 'external runtime library', |
'os' => 'operating system', |
'websrv' => 'web server', |
'sapi' => 'SAPI backend' |
); |
/** |
* PEAR_Command_Common constructor. |
* |
* @access public |
*/ |
function __construct(&$ui, &$config) |
{ |
parent::__construct(); |
$this->config = &$config; |
$this->ui = &$ui; |
} |
/** |
* Return a list of all the commands defined by this class. |
* @return array list of commands |
* @access public |
*/ |
function getCommands() |
{ |
$ret = array(); |
foreach (array_keys($this->commands) as $command) { |
$ret[$command] = $this->commands[$command]['summary']; |
} |
return $ret; |
} |
/** |
* Return a list of all the command shortcuts defined by this class. |
* @return array shortcut => command |
* @access public |
*/ |
function getShortcuts() |
{ |
$ret = array(); |
foreach (array_keys($this->commands) as $command) { |
if (isset($this->commands[$command]['shortcut'])) { |
$ret[$this->commands[$command]['shortcut']] = $command; |
} |
} |
return $ret; |
} |
function getOptions($command) |
{ |
$shortcuts = $this->getShortcuts(); |
if (isset($shortcuts[$command])) { |
$command = $shortcuts[$command]; |
} |
if (isset($this->commands[$command]) && |
isset($this->commands[$command]['options'])) { |
return $this->commands[$command]['options']; |
} |
return null; |
} |
function getGetoptArgs($command, &$short_args, &$long_args) |
{ |
$short_args = ''; |
$long_args = array(); |
if (empty($this->commands[$command]) || empty($this->commands[$command]['options'])) { |
return; |
} |
reset($this->commands[$command]['options']); |
while (list($option, $info) = each($this->commands[$command]['options'])) { |
$larg = $sarg = ''; |
if (isset($info['arg'])) { |
if ($info['arg']{0} == '(') { |
$larg = '=='; |
$sarg = '::'; |
$arg = substr($info['arg'], 1, -1); |
} else { |
$larg = '='; |
$sarg = ':'; |
$arg = $info['arg']; |
} |
} |
if (isset($info['shortopt'])) { |
$short_args .= $info['shortopt'] . $sarg; |
} |
$long_args[] = $option . $larg; |
} |
} |
/** |
* Returns the help message for the given command |
* |
* @param string $command The command |
* @return mixed A fail string if the command does not have help or |
* a two elements array containing [0]=>help string, |
* [1]=> help string for the accepted cmd args |
*/ |
function getHelp($command) |
{ |
$config = &PEAR_Config::singleton(); |
if (!isset($this->commands[$command])) { |
return "No such command \"$command\""; |
} |
$help = null; |
if (isset($this->commands[$command]['doc'])) { |
$help = $this->commands[$command]['doc']; |
} |
if (empty($help)) { |
// XXX (cox) Fallback to summary if there is no doc (show both?) |
if (!isset($this->commands[$command]['summary'])) { |
return "No help for command \"$command\""; |
} |
$help = $this->commands[$command]['summary']; |
} |
if (preg_match_all('/{config\s+([^\}]+)}/e', $help, $matches)) { |
foreach($matches[0] as $k => $v) { |
$help = preg_replace("/$v/", $config->get($matches[1][$k]), $help); |
} |
} |
return array($help, $this->getHelpArgs($command)); |
} |
/** |
* Returns the help for the accepted arguments of a command |
* |
* @param string $command |
* @return string The help string |
*/ |
function getHelpArgs($command) |
{ |
if (isset($this->commands[$command]['options']) && |
count($this->commands[$command]['options'])) |
{ |
$help = "Options:\n"; |
foreach ($this->commands[$command]['options'] as $k => $v) { |
if (isset($v['arg'])) { |
if ($v['arg'][0] == '(') { |
$arg = substr($v['arg'], 1, -1); |
$sapp = " [$arg]"; |
$lapp = "[=$arg]"; |
} else { |
$sapp = " $v[arg]"; |
$lapp = "=$v[arg]"; |
} |
} else { |
$sapp = $lapp = ""; |
} |
if (isset($v['shortopt'])) { |
$s = $v['shortopt']; |
$help .= " -$s$sapp, --$k$lapp\n"; |
} else { |
$help .= " --$k$lapp\n"; |
} |
$p = " "; |
$doc = rtrim(str_replace("\n", "\n$p", $v['doc'])); |
$help .= " $doc\n"; |
} |
return $help; |
} |
return null; |
} |
function run($command, $options, $params) |
{ |
if (empty($this->commands[$command]['function'])) { |
// look for shortcuts |
foreach (array_keys($this->commands) as $cmd) { |
if (isset($this->commands[$cmd]['shortcut']) && $this->commands[$cmd]['shortcut'] == $command) { |
if (empty($this->commands[$cmd]['function'])) { |
return $this->raiseError("unknown command `$command'"); |
} else { |
$func = $this->commands[$cmd]['function']; |
} |
$command = $cmd; |
//$command = $this->commands[$cmd]['function']; |
break; |
} |
} |
} else { |
$func = $this->commands[$command]['function']; |
} |
return $this->$func($command, $options, $params); |
} |
} |
/branches/v1.3-critias/bibliotheque/pear/PEAR/Command/Remote.php |
---|
New file |
0,0 → 1,809 |
<?php |
/** |
* PEAR_Command_Remote (remote-info, list-upgrades, remote-list, search, list-all, download, |
* clear-cache commands) |
* |
* PHP versions 4 and 5 |
* |
* @category pear |
* @package PEAR |
* @author Stig Bakken <ssb@php.net> |
* @author Greg Beaver <cellog@php.net> |
* @copyright 1997-2009 The Authors |
* @license http://opensource.org/licenses/bsd-license.php New BSD License |
* @link http://pear.php.net/package/PEAR |
* @since File available since Release 0.1 |
*/ |
/** |
* base class |
*/ |
require_once 'PEAR/Command/Common.php'; |
require_once 'PEAR/REST.php'; |
/** |
* PEAR commands for remote server querying |
* |
* @category pear |
* @package PEAR |
* @author Stig Bakken <ssb@php.net> |
* @author Greg Beaver <cellog@php.net> |
* @copyright 1997-2009 The Authors |
* @license http://opensource.org/licenses/bsd-license.php New BSD License |
* @version Release: 1.10.1 |
* @link http://pear.php.net/package/PEAR |
* @since Class available since Release 0.1 |
*/ |
class PEAR_Command_Remote extends PEAR_Command_Common |
{ |
var $commands = array( |
'remote-info' => array( |
'summary' => 'Information About Remote Packages', |
'function' => 'doRemoteInfo', |
'shortcut' => 'ri', |
'options' => array(), |
'doc' => '<package> |
Get details on a package from the server.', |
), |
'list-upgrades' => array( |
'summary' => 'List Available Upgrades', |
'function' => 'doListUpgrades', |
'shortcut' => 'lu', |
'options' => array( |
'channelinfo' => array( |
'shortopt' => 'i', |
'doc' => 'output fully channel-aware data, even on failure', |
), |
), |
'doc' => '[preferred_state] |
List releases on the server of packages you have installed where |
a newer version is available with the same release state (stable etc.) |
or the state passed as the second parameter.' |
), |
'remote-list' => array( |
'summary' => 'List Remote Packages', |
'function' => 'doRemoteList', |
'shortcut' => 'rl', |
'options' => array( |
'channel' => |
array( |
'shortopt' => 'c', |
'doc' => 'specify a channel other than the default channel', |
'arg' => 'CHAN', |
) |
), |
'doc' => ' |
Lists the packages available on the configured server along with the |
latest stable release of each package.', |
), |
'search' => array( |
'summary' => 'Search remote package database', |
'function' => 'doSearch', |
'shortcut' => 'sp', |
'options' => array( |
'channel' => |
array( |
'shortopt' => 'c', |
'doc' => 'specify a channel other than the default channel', |
'arg' => 'CHAN', |
), |
'allchannels' => array( |
'shortopt' => 'a', |
'doc' => 'search packages from all known channels', |
), |
'channelinfo' => array( |
'shortopt' => 'i', |
'doc' => 'output fully channel-aware data, even on failure', |
), |
), |
'doc' => '[packagename] [packageinfo] |
Lists all packages which match the search parameters. The first |
parameter is a fragment of a packagename. The default channel |
will be used unless explicitly overridden. The second parameter |
will be used to match any portion of the summary/description', |
), |
'list-all' => array( |
'summary' => 'List All Packages', |
'function' => 'doListAll', |
'shortcut' => 'la', |
'options' => array( |
'channel' => |
array( |
'shortopt' => 'c', |
'doc' => 'specify a channel other than the default channel', |
'arg' => 'CHAN', |
), |
'channelinfo' => array( |
'shortopt' => 'i', |
'doc' => 'output fully channel-aware data, even on failure', |
), |
), |
'doc' => ' |
Lists the packages available on the configured server along with the |
latest stable release of each package.', |
), |
'download' => array( |
'summary' => 'Download Package', |
'function' => 'doDownload', |
'shortcut' => 'd', |
'options' => array( |
'nocompress' => array( |
'shortopt' => 'Z', |
'doc' => 'download an uncompressed (.tar) file', |
), |
), |
'doc' => '<package>... |
Download package tarballs. The files will be named as suggested by the |
server, for example if you download the DB package and the latest stable |
version of DB is 1.6.5, the downloaded file will be DB-1.6.5.tgz.', |
), |
'clear-cache' => array( |
'summary' => 'Clear Web Services Cache', |
'function' => 'doClearCache', |
'shortcut' => 'cc', |
'options' => array(), |
'doc' => ' |
Clear the REST cache. See also the cache_ttl configuration |
parameter. |
', |
), |
); |
/** |
* PEAR_Command_Remote constructor. |
* |
* @access public |
*/ |
function __construct(&$ui, &$config) |
{ |
parent::__construct($ui, $config); |
} |
function _checkChannelForStatus($channel, $chan) |
{ |
if (PEAR::isError($chan)) { |
$this->raiseError($chan); |
} |
if (!is_a($chan, 'PEAR_ChannelFile')) { |
return $this->raiseError('Internal corruption error: invalid channel "' . |
$channel . '"'); |
} |
$rest = new PEAR_REST($this->config); |
PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN); |
$mirror = $this->config->get('preferred_mirror', null, |
$channel); |
$a = $rest->downloadHttp('http://' . $channel . |
'/channel.xml', $chan->lastModified()); |
PEAR::staticPopErrorHandling(); |
if (!PEAR::isError($a) && $a) { |
$this->ui->outputData('WARNING: channel "' . $channel . '" has ' . |
'updated its protocols, use "' . PEAR_RUNTYPE . ' channel-update ' . $channel . |
'" to update'); |
} |
} |
function doRemoteInfo($command, $options, $params) |
{ |
if (sizeof($params) != 1) { |
return $this->raiseError("$command expects one param: the remote package name"); |
} |
$savechannel = $channel = $this->config->get('default_channel'); |
$reg = &$this->config->getRegistry(); |
$package = $params[0]; |
$parsed = $reg->parsePackageName($package, $channel); |
if (PEAR::isError($parsed)) { |
return $this->raiseError('Invalid package name "' . $package . '"'); |
} |
$channel = $parsed['channel']; |
$this->config->set('default_channel', $channel); |
$chan = $reg->getChannel($channel); |
if (PEAR::isError($e = $this->_checkChannelForStatus($channel, $chan))) { |
return $e; |
} |
$mirror = $this->config->get('preferred_mirror'); |
if ($chan->supportsREST($mirror) && $base = $chan->getBaseURL('REST1.0', $mirror)) { |
$rest = &$this->config->getREST('1.0', array()); |
$info = $rest->packageInfo($base, $parsed['package'], $channel); |
} |
if (!isset($info)) { |
return $this->raiseError('No supported protocol was found'); |
} |
if (PEAR::isError($info)) { |
$this->config->set('default_channel', $savechannel); |
return $this->raiseError($info); |
} |
if (!isset($info['name'])) { |
return $this->raiseError('No remote package "' . $package . '" was found'); |
} |
$installed = $reg->packageInfo($info['name'], null, $channel); |
$info['installed'] = $installed['version'] ? $installed['version'] : '- no -'; |
if (is_array($info['installed'])) { |
$info['installed'] = $info['installed']['release']; |
} |
$this->ui->outputData($info, $command); |
$this->config->set('default_channel', $savechannel); |
return true; |
} |
function doRemoteList($command, $options, $params) |
{ |
$savechannel = $channel = $this->config->get('default_channel'); |
$reg = &$this->config->getRegistry(); |
if (isset($options['channel'])) { |
$channel = $options['channel']; |
if (!$reg->channelExists($channel)) { |
return $this->raiseError('Channel "' . $channel . '" does not exist'); |
} |
$this->config->set('default_channel', $channel); |
} |
$chan = $reg->getChannel($channel); |
if (PEAR::isError($e = $this->_checkChannelForStatus($channel, $chan))) { |
return $e; |
} |
$list_options = false; |
if ($this->config->get('preferred_state') == 'stable') { |
$list_options = true; |
} |
$available = array(); |
if ($chan->supportsREST($this->config->get('preferred_mirror')) && |
$base = $chan->getBaseURL('REST1.1', $this->config->get('preferred_mirror')) |
) { |
// use faster list-all if available |
$rest = &$this->config->getREST('1.1', array()); |
$available = $rest->listAll($base, $list_options, true, false, false, $chan->getName()); |
} elseif ($chan->supportsREST($this->config->get('preferred_mirror')) && |
$base = $chan->getBaseURL('REST1.0', $this->config->get('preferred_mirror'))) { |
$rest = &$this->config->getREST('1.0', array()); |
$available = $rest->listAll($base, $list_options, true, false, false, $chan->getName()); |
} |
if (PEAR::isError($available)) { |
$this->config->set('default_channel', $savechannel); |
return $this->raiseError($available); |
} |
$i = $j = 0; |
$data = array( |
'caption' => 'Channel ' . $channel . ' Available packages:', |
'border' => true, |
'headline' => array('Package', 'Version'), |
'channel' => $channel |
); |
if (count($available) == 0) { |
$data = '(no packages available yet)'; |
} else { |
foreach ($available as $name => $info) { |
$version = (isset($info['stable']) && $info['stable']) ? $info['stable'] : '-n/a-'; |
$data['data'][] = array($name, $version); |
} |
} |
$this->ui->outputData($data, $command); |
$this->config->set('default_channel', $savechannel); |
return true; |
} |
function doListAll($command, $options, $params) |
{ |
$savechannel = $channel = $this->config->get('default_channel'); |
$reg = &$this->config->getRegistry(); |
if (isset($options['channel'])) { |
$channel = $options['channel']; |
if (!$reg->channelExists($channel)) { |
return $this->raiseError("Channel \"$channel\" does not exist"); |
} |
$this->config->set('default_channel', $channel); |
} |
$list_options = false; |
if ($this->config->get('preferred_state') == 'stable') { |
$list_options = true; |
} |
$chan = $reg->getChannel($channel); |
if (PEAR::isError($e = $this->_checkChannelForStatus($channel, $chan))) { |
return $e; |
} |
if ($chan->supportsREST($this->config->get('preferred_mirror')) && |
$base = $chan->getBaseURL('REST1.1', $this->config->get('preferred_mirror'))) { |
// use faster list-all if available |
$rest = &$this->config->getREST('1.1', array()); |
$available = $rest->listAll($base, $list_options, false, false, false, $chan->getName()); |
} elseif ($chan->supportsREST($this->config->get('preferred_mirror')) && |
$base = $chan->getBaseURL('REST1.0', $this->config->get('preferred_mirror'))) { |
$rest = &$this->config->getREST('1.0', array()); |
$available = $rest->listAll($base, $list_options, false, false, false, $chan->getName()); |
} |
if (PEAR::isError($available)) { |
$this->config->set('default_channel', $savechannel); |
return $this->raiseError('The package list could not be fetched from the remote server. Please try again. (Debug info: "' . $available->getMessage() . '")'); |
} |
$data = array( |
'caption' => 'All packages [Channel ' . $channel . ']:', |
'border' => true, |
'headline' => array('Package', 'Latest', 'Local'), |
'channel' => $channel, |
); |
if (isset($options['channelinfo'])) { |
// add full channelinfo |
$data['caption'] = 'Channel ' . $channel . ' All packages:'; |
$data['headline'] = array('Channel', 'Package', 'Latest', 'Local', |
'Description', 'Dependencies'); |
} |
$local_pkgs = $reg->listPackages($channel); |
foreach ($available as $name => $info) { |
$installed = $reg->packageInfo($name, null, $channel); |
if (is_array($installed['version'])) { |
$installed['version'] = $installed['version']['release']; |
} |
$desc = $info['summary']; |
if (isset($params[$name])) { |
$desc .= "\n\n".$info['description']; |
} |
if (isset($options['mode'])) |
{ |
if ($options['mode'] == 'installed' && !isset($installed['version'])) { |
continue; |
} |
if ($options['mode'] == 'notinstalled' && isset($installed['version'])) { |
continue; |
} |
if ($options['mode'] == 'upgrades' |
&& (!isset($installed['version']) || version_compare($installed['version'], |
$info['stable'], '>='))) { |
continue; |
} |
} |
$pos = array_search(strtolower($name), $local_pkgs); |
if ($pos !== false) { |
unset($local_pkgs[$pos]); |
} |
if (isset($info['stable']) && !$info['stable']) { |
$info['stable'] = null; |
} |
if (isset($options['channelinfo'])) { |
// add full channelinfo |
if ($info['stable'] === $info['unstable']) { |
$state = $info['state']; |
} else { |
$state = 'stable'; |
} |
$latest = $info['stable'].' ('.$state.')'; |
$local = ''; |
if (isset($installed['version'])) { |
$inst_state = $reg->packageInfo($name, 'release_state', $channel); |
$local = $installed['version'].' ('.$inst_state.')'; |
} |
$packageinfo = array( |
$channel, |
$name, |
$latest, |
$local, |
isset($desc) ? $desc : null, |
isset($info['deps']) ? $info['deps'] : null, |
); |
} else { |
$packageinfo = array( |
$reg->channelAlias($channel) . '/' . $name, |
isset($info['stable']) ? $info['stable'] : null, |
isset($installed['version']) ? $installed['version'] : null, |
isset($desc) ? $desc : null, |
isset($info['deps']) ? $info['deps'] : null, |
); |
} |
$data['data'][$info['category']][] = $packageinfo; |
} |
if (isset($options['mode']) && in_array($options['mode'], array('notinstalled', 'upgrades'))) { |
$this->config->set('default_channel', $savechannel); |
$this->ui->outputData($data, $command); |
return true; |
} |
foreach ($local_pkgs as $name) { |
$info = &$reg->getPackage($name, $channel); |
$data['data']['Local'][] = array( |
$reg->channelAlias($channel) . '/' . $info->getPackage(), |
'', |
$info->getVersion(), |
$info->getSummary(), |
$info->getDeps() |
); |
} |
$this->config->set('default_channel', $savechannel); |
$this->ui->outputData($data, $command); |
return true; |
} |
function doSearch($command, $options, $params) |
{ |
if ((!isset($params[0]) || empty($params[0])) |
&& (!isset($params[1]) || empty($params[1]))) |
{ |
return $this->raiseError('no valid search string supplied'); |
} |
$channelinfo = isset($options['channelinfo']); |
$reg = &$this->config->getRegistry(); |
if (isset($options['allchannels'])) { |
// search all channels |
unset($options['allchannels']); |
$channels = $reg->getChannels(); |
$errors = array(); |
PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN); |
foreach ($channels as $channel) { |
if ($channel->getName() != '__uri') { |
$options['channel'] = $channel->getName(); |
$ret = $this->doSearch($command, $options, $params); |
if (PEAR::isError($ret)) { |
$errors[] = $ret; |
} |
} |
} |
PEAR::staticPopErrorHandling(); |
if (count($errors) !== 0) { |
// for now, only give first error |
return PEAR::raiseError($errors[0]); |
} |
return true; |
} |
$savechannel = $channel = $this->config->get('default_channel'); |
$package = strtolower($params[0]); |
$summary = isset($params[1]) ? $params[1] : false; |
if (isset($options['channel'])) { |
$reg = &$this->config->getRegistry(); |
$channel = $options['channel']; |
if (!$reg->channelExists($channel)) { |
return $this->raiseError('Channel "' . $channel . '" does not exist'); |
} |
$this->config->set('default_channel', $channel); |
} |
$chan = $reg->getChannel($channel); |
if (PEAR::isError($e = $this->_checkChannelForStatus($channel, $chan))) { |
return $e; |
} |
if ($chan->supportsREST($this->config->get('preferred_mirror')) && |
$base = $chan->getBaseURL('REST1.0', $this->config->get('preferred_mirror'))) { |
$rest = &$this->config->getREST('1.0', array()); |
$available = $rest->listAll($base, false, false, $package, $summary, $chan->getName()); |
} |
if (PEAR::isError($available)) { |
$this->config->set('default_channel', $savechannel); |
return $this->raiseError($available); |
} |
if (!$available && !$channelinfo) { |
// clean exit when not found, no error ! |
$data = 'no packages found that match pattern "' . $package . '", for channel '.$channel.'.'; |
$this->ui->outputData($data); |
$this->config->set('default_channel', $channel); |
return true; |
} |
if ($channelinfo) { |
$data = array( |
'caption' => 'Matched packages, channel ' . $channel . ':', |
'border' => true, |
'headline' => array('Channel', 'Package', 'Stable/(Latest)', 'Local'), |
'channel' => $channel |
); |
} else { |
$data = array( |
'caption' => 'Matched packages, channel ' . $channel . ':', |
'border' => true, |
'headline' => array('Package', 'Stable/(Latest)', 'Local'), |
'channel' => $channel |
); |
} |
if (!$available && $channelinfo) { |
unset($data['headline']); |
$data['data'] = 'No packages found that match pattern "' . $package . '".'; |
$available = array(); |
} |
foreach ($available as $name => $info) { |
$installed = $reg->packageInfo($name, null, $channel); |
$desc = $info['summary']; |
if (isset($params[$name])) |
$desc .= "\n\n".$info['description']; |
if (!isset($info['stable']) || !$info['stable']) { |
$version_remote = 'none'; |
} else { |
if ($info['unstable']) { |
$version_remote = $info['unstable']; |
} else { |
$version_remote = $info['stable']; |
} |
$version_remote .= ' ('.$info['state'].')'; |
} |
$version = is_array($installed['version']) ? $installed['version']['release'] : |
$installed['version']; |
if ($channelinfo) { |
$packageinfo = array( |
$channel, |
$name, |
$version_remote, |
$version, |
$desc, |
); |
} else { |
$packageinfo = array( |
$name, |
$version_remote, |
$version, |
$desc, |
); |
} |
$data['data'][$info['category']][] = $packageinfo; |
} |
$this->ui->outputData($data, $command); |
$this->config->set('default_channel', $channel); |
return true; |
} |
function &getDownloader($options) |
{ |
if (!class_exists('PEAR_Downloader')) { |
require_once 'PEAR/Downloader.php'; |
} |
$a = new PEAR_Downloader($this->ui, $options, $this->config); |
return $a; |
} |
function doDownload($command, $options, $params) |
{ |
// make certain that dependencies are ignored |
$options['downloadonly'] = 1; |
// eliminate error messages for preferred_state-related errors |
/* TODO: Should be an option, but until now download does respect |
prefered state */ |
/* $options['ignorepreferred_state'] = 1; */ |
// eliminate error messages for preferred_state-related errors |
$downloader = &$this->getDownloader($options); |
PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN); |
$e = $downloader->setDownloadDir(getcwd()); |
PEAR::staticPopErrorHandling(); |
if (PEAR::isError($e)) { |
return $this->raiseError('Current directory is not writeable, cannot download'); |
} |
$errors = array(); |
$downloaded = array(); |
$err = $downloader->download($params); |
if (PEAR::isError($err)) { |
return $err; |
} |
$errors = $downloader->getErrorMsgs(); |
if (count($errors)) { |
foreach ($errors as $error) { |
if ($error !== null) { |
$this->ui->outputData($error); |
} |
} |
return $this->raiseError("$command failed"); |
} |
$downloaded = $downloader->getDownloadedPackages(); |
foreach ($downloaded as $pkg) { |
$this->ui->outputData("File $pkg[file] downloaded", $command); |
} |
return true; |
} |
function downloadCallback($msg, $params = null) |
{ |
if ($msg == 'done') { |
$this->bytes_downloaded = $params; |
} |
} |
function doListUpgrades($command, $options, $params) |
{ |
require_once 'PEAR/Common.php'; |
if (isset($params[0]) && !is_array(PEAR_Common::betterStates($params[0]))) { |
return $this->raiseError($params[0] . ' is not a valid state (stable/beta/alpha/devel/etc.) try "pear help list-upgrades"'); |
} |
$savechannel = $channel = $this->config->get('default_channel'); |
$reg = &$this->config->getRegistry(); |
foreach ($reg->listChannels() as $channel) { |
$inst = array_flip($reg->listPackages($channel)); |
if (!count($inst)) { |
continue; |
} |
if ($channel == '__uri') { |
continue; |
} |
$this->config->set('default_channel', $channel); |
$state = empty($params[0]) ? $this->config->get('preferred_state') : $params[0]; |
$caption = $channel . ' Available Upgrades'; |
$chan = $reg->getChannel($channel); |
if (PEAR::isError($e = $this->_checkChannelForStatus($channel, $chan))) { |
return $e; |
} |
$latest = array(); |
$base2 = false; |
$preferred_mirror = $this->config->get('preferred_mirror'); |
if ($chan->supportsREST($preferred_mirror) && |
( |
($base2 = $chan->getBaseURL('REST1.3', $preferred_mirror)) |
|| ($base = $chan->getBaseURL('REST1.0', $preferred_mirror)) |
) |
) { |
if ($base2) { |
$rest = &$this->config->getREST('1.3', array()); |
$base = $base2; |
} else { |
$rest = &$this->config->getREST('1.0', array()); |
} |
if (empty($state) || $state == 'any') { |
$state = false; |
} else { |
$caption .= ' (' . implode(', ', PEAR_Common::betterStates($state, true)) . ')'; |
} |
PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN); |
$latest = $rest->listLatestUpgrades($base, $state, $inst, $channel, $reg); |
PEAR::staticPopErrorHandling(); |
} |
if (PEAR::isError($latest)) { |
$this->ui->outputData($latest->getMessage()); |
continue; |
} |
$caption .= ':'; |
if (PEAR::isError($latest)) { |
$this->config->set('default_channel', $savechannel); |
return $latest; |
} |
$data = array( |
'caption' => $caption, |
'border' => 1, |
'headline' => array('Channel', 'Package', 'Local', 'Remote', 'Size'), |
'channel' => $channel |
); |
foreach ((array)$latest as $pkg => $info) { |
$package = strtolower($pkg); |
if (!isset($inst[$package])) { |
// skip packages we don't have installed |
continue; |
} |
extract($info); |
$inst_version = $reg->packageInfo($package, 'version', $channel); |
$inst_state = $reg->packageInfo($package, 'release_state', $channel); |
if (version_compare("$version", "$inst_version", "le")) { |
// installed version is up-to-date |
continue; |
} |
if ($filesize >= 20480) { |
$filesize += 1024 - ($filesize % 1024); |
$fs = sprintf("%dkB", $filesize / 1024); |
} elseif ($filesize > 0) { |
$filesize += 103 - ($filesize % 103); |
$fs = sprintf("%.1fkB", $filesize / 1024.0); |
} else { |
$fs = " -"; // XXX center instead |
} |
$data['data'][] = array($channel, $pkg, "$inst_version ($inst_state)", "$version ($state)", $fs); |
} |
if (isset($options['channelinfo'])) { |
if (empty($data['data'])) { |
unset($data['headline']); |
if (count($inst) == 0) { |
$data['data'] = '(no packages installed)'; |
} else { |
$data['data'] = '(no upgrades available)'; |
} |
} |
$this->ui->outputData($data, $command); |
} else { |
if (empty($data['data'])) { |
$this->ui->outputData('Channel ' . $channel . ': No upgrades available'); |
} else { |
$this->ui->outputData($data, $command); |
} |
} |
} |
$this->config->set('default_channel', $savechannel); |
return true; |
} |
function doClearCache($command, $options, $params) |
{ |
$cache_dir = $this->config->get('cache_dir'); |
$verbose = $this->config->get('verbose'); |
$output = ''; |
if (!file_exists($cache_dir) || !is_dir($cache_dir)) { |
return $this->raiseError("$cache_dir does not exist or is not a directory"); |
} |
if (!($dp = @opendir($cache_dir))) { |
return $this->raiseError("opendir($cache_dir) failed: $php_errormsg"); |
} |
if ($verbose >= 1) { |
$output .= "reading directory $cache_dir\n"; |
} |
$num = 0; |
while ($ent = readdir($dp)) { |
if (preg_match('/rest.cache(file|id)\\z/', $ent)) { |
$path = $cache_dir . DIRECTORY_SEPARATOR . $ent; |
if (file_exists($path)) { |
$ok = @unlink($path); |
} else { |
$ok = false; |
$php_errormsg = ''; |
} |
if ($ok) { |
if ($verbose >= 2) { |
$output .= "deleted $path\n"; |
} |
$num++; |
} elseif ($verbose >= 1) { |
$output .= "failed to delete $path $php_errormsg\n"; |
} |
} |
} |
closedir($dp); |
if ($verbose >= 1) { |
$output .= "$num cache entries cleared\n"; |
} |
$this->ui->outputData(rtrim($output), $command); |
return $num; |
} |
} |
/branches/v1.3-critias/bibliotheque/pear/PEAR/Command/Channels.php |
---|
New file |
0,0 → 1,882 |
<?php |
// /* vim: set expandtab tabstop=4 shiftwidth=4: */ |
/** |
* PEAR_Command_Channels (list-channels, update-channels, channel-delete, channel-add, |
* channel-update, channel-info, channel-alias, channel-discover commands) |
* |
* PHP versions 4 and 5 |
* |
* @category pear |
* @package PEAR |
* @author Stig Bakken <ssb@php.net> |
* @author Greg Beaver <cellog@php.net> |
* @copyright 1997-2009 The Authors |
* @license http://opensource.org/licenses/bsd-license.php New BSD License |
* @link http://pear.php.net/package/PEAR |
* @since File available since Release 1.4.0a1 |
*/ |
/** |
* base class |
*/ |
require_once 'PEAR/Command/Common.php'; |
define('PEAR_COMMAND_CHANNELS_CHANNEL_EXISTS', -500); |
/** |
* PEAR commands for managing channels. |
* |
* @category pear |
* @package PEAR |
* @author Greg Beaver <cellog@php.net> |
* @copyright 1997-2009 The Authors |
* @license http://opensource.org/licenses/bsd-license.php New BSD License |
* @version Release: 1.10.1 |
* @link http://pear.php.net/package/PEAR |
* @since Class available since Release 1.4.0a1 |
*/ |
class PEAR_Command_Channels extends PEAR_Command_Common |
{ |
var $commands = array( |
'list-channels' => array( |
'summary' => 'List Available Channels', |
'function' => 'doList', |
'shortcut' => 'lc', |
'options' => array(), |
'doc' => ' |
List all available channels for installation. |
', |
), |
'update-channels' => array( |
'summary' => 'Update the Channel List', |
'function' => 'doUpdateAll', |
'shortcut' => 'uc', |
'options' => array(), |
'doc' => ' |
List all installed packages in all channels. |
' |
), |
'channel-delete' => array( |
'summary' => 'Remove a Channel From the List', |
'function' => 'doDelete', |
'shortcut' => 'cde', |
'options' => array(), |
'doc' => '<channel name> |
Delete a channel from the registry. You may not |
remove any channel that has installed packages. |
' |
), |
'channel-add' => array( |
'summary' => 'Add a Channel', |
'function' => 'doAdd', |
'shortcut' => 'ca', |
'options' => array(), |
'doc' => '<channel.xml> |
Add a private channel to the channel list. Note that all |
public channels should be synced using "update-channels". |
Parameter may be either a local file or remote URL to a |
channel.xml. |
' |
), |
'channel-update' => array( |
'summary' => 'Update an Existing Channel', |
'function' => 'doUpdate', |
'shortcut' => 'cu', |
'options' => array( |
'force' => array( |
'shortopt' => 'f', |
'doc' => 'will force download of new channel.xml if an existing channel name is used', |
), |
'channel' => array( |
'shortopt' => 'c', |
'arg' => 'CHANNEL', |
'doc' => 'will force download of new channel.xml if an existing channel name is used', |
), |
), |
'doc' => '[<channel.xml>|<channel name>] |
Update a channel in the channel list directly. Note that all |
public channels can be synced using "update-channels". |
Parameter may be a local or remote channel.xml, or the name of |
an existing channel. |
' |
), |
'channel-info' => array( |
'summary' => 'Retrieve Information on a Channel', |
'function' => 'doInfo', |
'shortcut' => 'ci', |
'options' => array(), |
'doc' => '<package> |
List the files in an installed package. |
' |
), |
'channel-alias' => array( |
'summary' => 'Specify an alias to a channel name', |
'function' => 'doAlias', |
'shortcut' => 'cha', |
'options' => array(), |
'doc' => '<channel> <alias> |
Specify a specific alias to use for a channel name. |
The alias may not be an existing channel name or |
alias. |
' |
), |
'channel-discover' => array( |
'summary' => 'Initialize a Channel from its server', |
'function' => 'doDiscover', |
'shortcut' => 'di', |
'options' => array(), |
'doc' => '[<channel.xml>|<channel name>] |
Initialize a channel from its server and create a local channel.xml. |
If <channel name> is in the format "<username>:<password>@<channel>" then |
<username> and <password> will be set as the login username/password for |
<channel>. Use caution when passing the username/password in this way, as |
it may allow other users on your computer to briefly view your username/ |
password via the system\'s process list. |
' |
), |
'channel-login' => array( |
'summary' => 'Connects and authenticates to remote channel server', |
'shortcut' => 'cli', |
'function' => 'doLogin', |
'options' => array(), |
'doc' => '<channel name> |
Log in to a remote channel server. If <channel name> is not supplied, |
the default channel is used. To use remote functions in the installer |
that require any kind of privileges, you need to log in first. The |
username and password you enter here will be stored in your per-user |
PEAR configuration (~/.pearrc on Unix-like systems). After logging |
in, your username and password will be sent along in subsequent |
operations on the remote server.', |
), |
'channel-logout' => array( |
'summary' => 'Logs out from the remote channel server', |
'shortcut' => 'clo', |
'function' => 'doLogout', |
'options' => array(), |
'doc' => '<channel name> |
Logs out from a remote channel server. If <channel name> is not supplied, |
the default channel is used. This command does not actually connect to the |
remote server, it only deletes the stored username and password from your user |
configuration.', |
), |
); |
/** |
* PEAR_Command_Registry constructor. |
* |
* @access public |
*/ |
function __construct(&$ui, &$config) |
{ |
parent::__construct($ui, $config); |
} |
function _sortChannels($a, $b) |
{ |
return strnatcasecmp($a->getName(), $b->getName()); |
} |
function doList($command, $options, $params) |
{ |
$reg = &$this->config->getRegistry(); |
$registered = $reg->getChannels(); |
usort($registered, array(&$this, '_sortchannels')); |
$i = $j = 0; |
$data = array( |
'caption' => 'Registered Channels:', |
'border' => true, |
'headline' => array('Channel', 'Alias', 'Summary') |
); |
foreach ($registered as $channel) { |
$data['data'][] = array($channel->getName(), |
$channel->getAlias(), |
$channel->getSummary()); |
} |
if (count($registered) === 0) { |
$data = '(no registered channels)'; |
} |
$this->ui->outputData($data, $command); |
return true; |
} |
function doUpdateAll($command, $options, $params) |
{ |
$reg = &$this->config->getRegistry(); |
$channels = $reg->getChannels(); |
$success = true; |
foreach ($channels as $channel) { |
if ($channel->getName() != '__uri') { |
PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN); |
$err = $this->doUpdate('channel-update', |
$options, |
array($channel->getName())); |
if (PEAR::isError($err)) { |
$this->ui->outputData($err->getMessage(), $command); |
$success = false; |
} else { |
$success &= $err; |
} |
} |
} |
return $success; |
} |
function doInfo($command, $options, $params) |
{ |
if (count($params) !== 1) { |
return $this->raiseError("No channel specified"); |
} |
$reg = &$this->config->getRegistry(); |
$channel = strtolower($params[0]); |
if ($reg->channelExists($channel)) { |
$chan = $reg->getChannel($channel); |
if (PEAR::isError($chan)) { |
return $this->raiseError($chan); |
} |
} else { |
if (strpos($channel, '://')) { |
$downloader = &$this->getDownloader(); |
$tmpdir = $this->config->get('temp_dir'); |
PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN); |
$loc = $downloader->downloadHttp($channel, $this->ui, $tmpdir); |
PEAR::staticPopErrorHandling(); |
if (PEAR::isError($loc)) { |
return $this->raiseError('Cannot open "' . $channel . |
'" (' . $loc->getMessage() . ')'); |
} else { |
$contents = implode('', file($loc)); |
} |
} else { |
if (!file_exists($params[0])) { |
return $this->raiseError('Unknown channel "' . $channel . '"'); |
} |
$fp = fopen($params[0], 'r'); |
if (!$fp) { |
return $this->raiseError('Cannot open "' . $params[0] . '"'); |
} |
$contents = ''; |
while (!feof($fp)) { |
$contents .= fread($fp, 1024); |
} |
fclose($fp); |
} |
if (!class_exists('PEAR_ChannelFile')) { |
require_once 'PEAR/ChannelFile.php'; |
} |
$chan = new PEAR_ChannelFile; |
$chan->fromXmlString($contents); |
$chan->validate(); |
if ($errs = $chan->getErrors(true)) { |
foreach ($errs as $err) { |
$this->ui->outputData($err['level'] . ': ' . $err['message']); |
} |
return $this->raiseError('Channel file "' . $params[0] . '" is not valid'); |
} |
} |
if (!$chan) { |
return $this->raiseError('Serious error: Channel "' . $params[0] . |
'" has a corrupted registry entry'); |
} |
$channel = $chan->getName(); |
$caption = 'Channel ' . $channel . ' Information:'; |
$data1 = array( |
'caption' => $caption, |
'border' => true); |
$data1['data']['server'] = array('Name and Server', $chan->getName()); |
if ($chan->getAlias() != $chan->getName()) { |
$data1['data']['alias'] = array('Alias', $chan->getAlias()); |
} |
$data1['data']['summary'] = array('Summary', $chan->getSummary()); |
$validate = $chan->getValidationPackage(); |
$data1['data']['vpackage'] = array('Validation Package Name', $validate['_content']); |
$data1['data']['vpackageversion'] = |
array('Validation Package Version', $validate['attribs']['version']); |
$d = array(); |
$d['main'] = $data1; |
$data['data'] = array(); |
$data['caption'] = 'Server Capabilities'; |
$data['headline'] = array('Type', 'Version/REST type', 'Function Name/REST base'); |
if ($chan->supportsREST()) { |
if ($chan->supportsREST()) { |
$funcs = $chan->getFunctions('rest'); |
if (!isset($funcs[0])) { |
$funcs = array($funcs); |
} |
foreach ($funcs as $protocol) { |
$data['data'][] = array('rest', $protocol['attribs']['type'], |
$protocol['_content']); |
} |
} |
} else { |
$data['data'][] = array('No supported protocols'); |
} |
$d['protocols'] = $data; |
$data['data'] = array(); |
$mirrors = $chan->getMirrors(); |
if ($mirrors) { |
$data['caption'] = 'Channel ' . $channel . ' Mirrors:'; |
unset($data['headline']); |
foreach ($mirrors as $mirror) { |
$data['data'][] = array($mirror['attribs']['host']); |
$d['mirrors'] = $data; |
} |
foreach ($mirrors as $i => $mirror) { |
$data['data'] = array(); |
$data['caption'] = 'Mirror ' . $mirror['attribs']['host'] . ' Capabilities'; |
$data['headline'] = array('Type', 'Version/REST type', 'Function Name/REST base'); |
if ($chan->supportsREST($mirror['attribs']['host'])) { |
if ($chan->supportsREST($mirror['attribs']['host'])) { |
$funcs = $chan->getFunctions('rest', $mirror['attribs']['host']); |
if (!isset($funcs[0])) { |
$funcs = array($funcs); |
} |
foreach ($funcs as $protocol) { |
$data['data'][] = array('rest', $protocol['attribs']['type'], |
$protocol['_content']); |
} |
} |
} else { |
$data['data'][] = array('No supported protocols'); |
} |
$d['mirrorprotocols' . $i] = $data; |
} |
} |
$this->ui->outputData($d, 'channel-info'); |
} |
// }}} |
function doDelete($command, $options, $params) |
{ |
if (count($params) !== 1) { |
return $this->raiseError('channel-delete: no channel specified'); |
} |
$reg = &$this->config->getRegistry(); |
if (!$reg->channelExists($params[0])) { |
return $this->raiseError('channel-delete: channel "' . $params[0] . '" does not exist'); |
} |
$channel = $reg->channelName($params[0]); |
if ($channel == 'pear.php.net') { |
return $this->raiseError('Cannot delete the pear.php.net channel'); |
} |
if ($channel == 'pecl.php.net') { |
return $this->raiseError('Cannot delete the pecl.php.net channel'); |
} |
if ($channel == 'doc.php.net') { |
return $this->raiseError('Cannot delete the doc.php.net channel'); |
} |
if ($channel == '__uri') { |
return $this->raiseError('Cannot delete the __uri pseudo-channel'); |
} |
if (PEAR::isError($err = $reg->listPackages($channel))) { |
return $err; |
} |
if (count($err)) { |
return $this->raiseError('Channel "' . $channel . |
'" has installed packages, cannot delete'); |
} |
if (!$reg->deleteChannel($channel)) { |
return $this->raiseError('Channel "' . $channel . '" deletion failed'); |
} else { |
$this->config->deleteChannel($channel); |
$this->ui->outputData('Channel "' . $channel . '" deleted', $command); |
} |
} |
function doAdd($command, $options, $params) |
{ |
if (count($params) !== 1) { |
return $this->raiseError('channel-add: no channel file specified'); |
} |
if (strpos($params[0], '://')) { |
$downloader = &$this->getDownloader(); |
$tmpdir = $this->config->get('temp_dir'); |
if (!file_exists($tmpdir)) { |
require_once 'System.php'; |
PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN); |
$err = System::mkdir(array('-p', $tmpdir)); |
PEAR::staticPopErrorHandling(); |
if (PEAR::isError($err)) { |
return $this->raiseError('channel-add: temp_dir does not exist: "' . |
$tmpdir . |
'" - You can change this location with "pear config-set temp_dir"'); |
} |
} |
if (!is_writable($tmpdir)) { |
return $this->raiseError('channel-add: temp_dir is not writable: "' . |
$tmpdir . |
'" - You can change this location with "pear config-set temp_dir"'); |
} |
PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN); |
$loc = $downloader->downloadHttp($params[0], $this->ui, $tmpdir, null, false); |
PEAR::staticPopErrorHandling(); |
if (PEAR::isError($loc)) { |
return $this->raiseError('channel-add: Cannot open "' . $params[0] . |
'" (' . $loc->getMessage() . ')'); |
} |
list($loc, $lastmodified) = $loc; |
$contents = implode('', file($loc)); |
} else { |
$lastmodified = $fp = false; |
if (file_exists($params[0])) { |
$fp = fopen($params[0], 'r'); |
} |
if (!$fp) { |
return $this->raiseError('channel-add: cannot open "' . $params[0] . '"'); |
} |
$contents = ''; |
while (!feof($fp)) { |
$contents .= fread($fp, 1024); |
} |
fclose($fp); |
} |
if (!class_exists('PEAR_ChannelFile')) { |
require_once 'PEAR/ChannelFile.php'; |
} |
$channel = new PEAR_ChannelFile; |
PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN); |
$result = $channel->fromXmlString($contents); |
PEAR::staticPopErrorHandling(); |
if (!$result) { |
$exit = false; |
if (count($errors = $channel->getErrors(true))) { |
foreach ($errors as $error) { |
$this->ui->outputData(ucfirst($error['level'] . ': ' . $error['message'])); |
if (!$exit) { |
$exit = $error['level'] == 'error' ? true : false; |
} |
} |
if ($exit) { |
return $this->raiseError('channel-add: invalid channel.xml file'); |
} |
} |
} |
$reg = &$this->config->getRegistry(); |
if ($reg->channelExists($channel->getName())) { |
return $this->raiseError('channel-add: Channel "' . $channel->getName() . |
'" exists, use channel-update to update entry', PEAR_COMMAND_CHANNELS_CHANNEL_EXISTS); |
} |
$ret = $reg->addChannel($channel, $lastmodified); |
if (PEAR::isError($ret)) { |
return $ret; |
} |
if (!$ret) { |
return $this->raiseError('channel-add: adding Channel "' . $channel->getName() . |
'" to registry failed'); |
} |
$this->config->setChannels($reg->listChannels()); |
$this->config->writeConfigFile(); |
$this->ui->outputData('Adding Channel "' . $channel->getName() . '" succeeded', $command); |
} |
function doUpdate($command, $options, $params) |
{ |
if (count($params) !== 1) { |
return $this->raiseError("No channel file specified"); |
} |
$tmpdir = $this->config->get('temp_dir'); |
if (!file_exists($tmpdir)) { |
require_once 'System.php'; |
PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN); |
$err = System::mkdir(array('-p', $tmpdir)); |
PEAR::staticPopErrorHandling(); |
if (PEAR::isError($err)) { |
return $this->raiseError('channel-add: temp_dir does not exist: "' . |
$tmpdir . |
'" - You can change this location with "pear config-set temp_dir"'); |
} |
} |
if (!is_writable($tmpdir)) { |
return $this->raiseError('channel-add: temp_dir is not writable: "' . |
$tmpdir . |
'" - You can change this location with "pear config-set temp_dir"'); |
} |
$reg = &$this->config->getRegistry(); |
$lastmodified = false; |
if ((!file_exists($params[0]) || is_dir($params[0])) |
&& $reg->channelExists(strtolower($params[0]))) { |
$c = $reg->getChannel(strtolower($params[0])); |
if (PEAR::isError($c)) { |
return $this->raiseError($c); |
} |
$this->ui->outputData("Updating channel \"$params[0]\"", $command); |
$dl = &$this->getDownloader(array()); |
// if force is specified, use a timestamp of "1" to force retrieval |
$lastmodified = isset($options['force']) ? false : $c->lastModified(); |
PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN); |
$contents = $dl->downloadHttp('http://' . $c->getName() . '/channel.xml', |
$this->ui, $tmpdir, null, $lastmodified); |
PEAR::staticPopErrorHandling(); |
if (PEAR::isError($contents)) { |
// Attempt to fall back to https |
$this->ui->outputData("Channel \"$params[0]\" is not responding over http://, failed with message: " . $contents->getMessage()); |
$this->ui->outputData("Trying channel \"$params[0]\" over https:// instead"); |
PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN); |
$contents = $dl->downloadHttp('https://' . $c->getName() . '/channel.xml', |
$this->ui, $tmpdir, null, $lastmodified); |
PEAR::staticPopErrorHandling(); |
if (PEAR::isError($contents)) { |
return $this->raiseError('Cannot retrieve channel.xml for channel "' . |
$c->getName() . '" (' . $contents->getMessage() . ')'); |
} |
} |
list($contents, $lastmodified) = $contents; |
if (!$contents) { |
$this->ui->outputData("Channel \"$params[0]\" is up to date"); |
return; |
} |
$contents = implode('', file($contents)); |
if (!class_exists('PEAR_ChannelFile')) { |
require_once 'PEAR/ChannelFile.php'; |
} |
$channel = new PEAR_ChannelFile; |
$channel->fromXmlString($contents); |
if (!$channel->getErrors()) { |
// security check: is the downloaded file for the channel we got it from? |
if (strtolower($channel->getName()) != strtolower($c->getName())) { |
if (!isset($options['force'])) { |
return $this->raiseError('ERROR: downloaded channel definition file' . |
' for channel "' . $channel->getName() . '" from channel "' . |
strtolower($c->getName()) . '"'); |
} |
$this->ui->log(0, 'WARNING: downloaded channel definition file' . |
' for channel "' . $channel->getName() . '" from channel "' . |
strtolower($c->getName()) . '"'); |
} |
} |
} else { |
if (strpos($params[0], '://')) { |
$dl = &$this->getDownloader(); |
PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN); |
$loc = $dl->downloadHttp($params[0], |
$this->ui, $tmpdir, null, $lastmodified); |
PEAR::staticPopErrorHandling(); |
if (PEAR::isError($loc)) { |
return $this->raiseError("Cannot open " . $params[0] . |
' (' . $loc->getMessage() . ')'); |
} |
list($loc, $lastmodified) = $loc; |
$contents = implode('', file($loc)); |
} else { |
$fp = false; |
if (file_exists($params[0])) { |
$fp = fopen($params[0], 'r'); |
} |
if (!$fp) { |
return $this->raiseError("Cannot open " . $params[0]); |
} |
$contents = ''; |
while (!feof($fp)) { |
$contents .= fread($fp, 1024); |
} |
fclose($fp); |
} |
if (!class_exists('PEAR_ChannelFile')) { |
require_once 'PEAR/ChannelFile.php'; |
} |
$channel = new PEAR_ChannelFile; |
$channel->fromXmlString($contents); |
} |
$exit = false; |
if (count($errors = $channel->getErrors(true))) { |
foreach ($errors as $error) { |
$this->ui->outputData(ucfirst($error['level'] . ': ' . $error['message'])); |
if (!$exit) { |
$exit = $error['level'] == 'error' ? true : false; |
} |
} |
if ($exit) { |
return $this->raiseError('Invalid channel.xml file'); |
} |
} |
if (!$reg->channelExists($channel->getName())) { |
return $this->raiseError('Error: Channel "' . $channel->getName() . |
'" does not exist, use channel-add to add an entry'); |
} |
$ret = $reg->updateChannel($channel, $lastmodified); |
if (PEAR::isError($ret)) { |
return $ret; |
} |
if (!$ret) { |
return $this->raiseError('Updating Channel "' . $channel->getName() . |
'" in registry failed'); |
} |
$this->config->setChannels($reg->listChannels()); |
$this->config->writeConfigFile(); |
$this->ui->outputData('Update of Channel "' . $channel->getName() . '" succeeded'); |
} |
function &getDownloader() |
{ |
if (!class_exists('PEAR_Downloader')) { |
require_once 'PEAR/Downloader.php'; |
} |
$a = new PEAR_Downloader($this->ui, array(), $this->config); |
return $a; |
} |
function doAlias($command, $options, $params) |
{ |
if (count($params) === 1) { |
return $this->raiseError('No channel alias specified'); |
} |
if (count($params) !== 2 || (!empty($params[1]) && $params[1]{0} == '-')) { |
return $this->raiseError( |
'Invalid format, correct is: channel-alias channel alias'); |
} |
$reg = &$this->config->getRegistry(); |
if (!$reg->channelExists($params[0], true)) { |
$extra = ''; |
if ($reg->isAlias($params[0])) { |
$extra = ' (use "channel-alias ' . $reg->channelName($params[0]) . ' ' . |
strtolower($params[1]) . '")'; |
} |
return $this->raiseError('"' . $params[0] . '" is not a valid channel' . $extra); |
} |
if ($reg->isAlias($params[1])) { |
return $this->raiseError('Channel "' . $reg->channelName($params[1]) . '" is ' . |
'already aliased to "' . strtolower($params[1]) . '", cannot re-alias'); |
} |
$chan = $reg->getChannel($params[0]); |
if (PEAR::isError($chan)) { |
return $this->raiseError('Corrupt registry? Error retrieving channel "' . $params[0] . |
'" information (' . $chan->getMessage() . ')'); |
} |
// make it a local alias |
if (!$chan->setAlias(strtolower($params[1]), true)) { |
return $this->raiseError('Alias "' . strtolower($params[1]) . |
'" is not a valid channel alias'); |
} |
$reg->updateChannel($chan); |
$this->ui->outputData('Channel "' . $chan->getName() . '" aliased successfully to "' . |
strtolower($params[1]) . '"'); |
} |
/** |
* The channel-discover command |
* |
* @param string $command command name |
* @param array $options option_name => value |
* @param array $params list of additional parameters. |
* $params[0] should contain a string with either: |
* - <channel name> or |
* - <username>:<password>@<channel name> |
* @return null|PEAR_Error |
*/ |
function doDiscover($command, $options, $params) |
{ |
if (count($params) !== 1) { |
return $this->raiseError("No channel server specified"); |
} |
// Look for the possible input format "<username>:<password>@<channel>" |
if (preg_match('/^(.+):(.+)@(.+)\\z/', $params[0], $matches)) { |
$username = $matches[1]; |
$password = $matches[2]; |
$channel = $matches[3]; |
} else { |
$channel = $params[0]; |
} |
$reg = &$this->config->getRegistry(); |
if ($reg->channelExists($channel)) { |
if (!$reg->isAlias($channel)) { |
return $this->raiseError("Channel \"$channel\" is already initialized", PEAR_COMMAND_CHANNELS_CHANNEL_EXISTS); |
} |
return $this->raiseError("A channel alias named \"$channel\" " . |
'already exists, aliasing channel "' . $reg->channelName($channel) |
. '"'); |
} |
$this->pushErrorHandling(PEAR_ERROR_RETURN); |
$err = $this->doAdd($command, $options, array('http://' . $channel . '/channel.xml')); |
$this->popErrorHandling(); |
if (PEAR::isError($err)) { |
if ($err->getCode() === PEAR_COMMAND_CHANNELS_CHANNEL_EXISTS) { |
return $this->raiseError("Discovery of channel \"$channel\" failed (" . |
$err->getMessage() . ')'); |
} |
// Attempt fetch via https |
$this->ui->outputData("Discovering channel $channel over http:// failed with message: " . $err->getMessage()); |
$this->ui->outputData("Trying to discover channel $channel over https:// instead"); |
$this->pushErrorHandling(PEAR_ERROR_RETURN); |
$err = $this->doAdd($command, $options, array('https://' . $channel . '/channel.xml')); |
$this->popErrorHandling(); |
if (PEAR::isError($err)) { |
return $this->raiseError("Discovery of channel \"$channel\" failed (" . |
$err->getMessage() . ')'); |
} |
} |
// Store username/password if they were given |
// Arguably we should do a logintest on the channel here, but since |
// that's awkward on a REST-based channel (even "pear login" doesn't |
// do it for those), and XML-RPC is deprecated, it's fairly pointless. |
if (isset($username)) { |
$this->config->set('username', $username, 'user', $channel); |
$this->config->set('password', $password, 'user', $channel); |
$this->config->store(); |
$this->ui->outputData("Stored login for channel \"$channel\" using username \"$username\"", $command); |
} |
$this->ui->outputData("Discovery of channel \"$channel\" succeeded", $command); |
} |
/** |
* Execute the 'login' command. |
* |
* @param string $command command name |
* @param array $options option_name => value |
* @param array $params list of additional parameters |
* |
* @return bool TRUE on success or |
* a PEAR error on failure |
* |
* @access public |
*/ |
function doLogin($command, $options, $params) |
{ |
$reg = &$this->config->getRegistry(); |
// If a parameter is supplied, use that as the channel to log in to |
$channel = isset($params[0]) ? $params[0] : $this->config->get('default_channel'); |
$chan = $reg->getChannel($channel); |
if (PEAR::isError($chan)) { |
return $this->raiseError($chan); |
} |
$server = $this->config->get('preferred_mirror', null, $channel); |
$username = $this->config->get('username', null, $channel); |
if (empty($username)) { |
$username = isset($_ENV['USER']) ? $_ENV['USER'] : null; |
} |
$this->ui->outputData("Logging in to $server.", $command); |
list($username, $password) = $this->ui->userDialog( |
$command, |
array('Username', 'Password'), |
array('text', 'password'), |
array($username, '') |
); |
$username = trim($username); |
$password = trim($password); |
$ourfile = $this->config->getConfFile('user'); |
if (!$ourfile) { |
$ourfile = $this->config->getConfFile('system'); |
} |
$this->config->set('username', $username, 'user', $channel); |
$this->config->set('password', $password, 'user', $channel); |
if ($chan->supportsREST()) { |
$ok = true; |
} |
if ($ok !== true) { |
return $this->raiseError('Login failed!'); |
} |
$this->ui->outputData("Logged in.", $command); |
// avoid changing any temporary settings changed with -d |
$ourconfig = new PEAR_Config($ourfile, $ourfile); |
$ourconfig->set('username', $username, 'user', $channel); |
$ourconfig->set('password', $password, 'user', $channel); |
$ourconfig->store(); |
return true; |
} |
/** |
* Execute the 'logout' command. |
* |
* @param string $command command name |
* @param array $options option_name => value |
* @param array $params list of additional parameters |
* |
* @return bool TRUE on success or |
* a PEAR error on failure |
* |
* @access public |
*/ |
function doLogout($command, $options, $params) |
{ |
$reg = &$this->config->getRegistry(); |
// If a parameter is supplied, use that as the channel to log in to |
$channel = isset($params[0]) ? $params[0] : $this->config->get('default_channel'); |
$chan = $reg->getChannel($channel); |
if (PEAR::isError($chan)) { |
return $this->raiseError($chan); |
} |
$server = $this->config->get('preferred_mirror', null, $channel); |
$this->ui->outputData("Logging out from $server.", $command); |
$this->config->remove('username', 'user', $channel); |
$this->config->remove('password', 'user', $channel); |
$this->config->store(); |
return true; |
} |
} |
/branches/v1.3-critias/bibliotheque/pear/PEAR/Command/Package.php |
---|
New file |
0,0 → 1,1123 |
<?php |
/** |
* PEAR_Command_Package (package, package-validate, cvsdiff, cvstag, package-dependencies, |
* sign, makerpm, convert commands) |
* |
* PHP versions 4 and 5 |
* |
* @category pear |
* @package PEAR |
* @author Stig Bakken <ssb@php.net> |
* @author Martin Jansen <mj@php.net> |
* @author Greg Beaver <cellog@php.net> |
* @copyright 1997-2009 The Authors |
* @license http://opensource.org/licenses/bsd-license.php New BSD License |
* @link http://pear.php.net/package/PEAR |
* @since File available since Release 0.1 |
*/ |
/** |
* base class |
*/ |
require_once 'PEAR/Command/Common.php'; |
/** |
* PEAR commands for login/logout |
* |
* @category pear |
* @package PEAR |
* @author Stig Bakken <ssb@php.net> |
* @author Martin Jansen <mj@php.net> |
* @author Greg Beaver <cellog@php.net> |
* @copyright 1997-2009 The Authors |
* @license http://opensource.org/licenses/bsd-license.php New BSD License |
* @version Release: @package_version@ |
* @link http://pear.php.net/package/PEAR |
* @since Class available since Release 0.1 |
*/ |
class PEAR_Command_Package extends PEAR_Command_Common |
{ |
var $commands = array( |
'package' => array( |
'summary' => 'Build Package', |
'function' => 'doPackage', |
'shortcut' => 'p', |
'options' => array( |
'nocompress' => array( |
'shortopt' => 'Z', |
'doc' => 'Do not gzip the package file' |
), |
'showname' => array( |
'shortopt' => 'n', |
'doc' => 'Print the name of the packaged file.', |
), |
), |
'doc' => '[descfile] [descfile2] |
Creates a PEAR package from its description file (usually called |
package.xml). If a second packagefile is passed in, then |
the packager will check to make sure that one is a package.xml |
version 1.0, and the other is a package.xml version 2.0. The |
package.xml version 1.0 will be saved as "package.xml" in the archive, |
and the other as "package2.xml" in the archive" |
' |
), |
'package-validate' => array( |
'summary' => 'Validate Package Consistency', |
'function' => 'doPackageValidate', |
'shortcut' => 'pv', |
'options' => array(), |
'doc' => ' |
', |
), |
'cvsdiff' => array( |
'summary' => 'Run a "cvs diff" for all files in a package', |
'function' => 'doCvsDiff', |
'shortcut' => 'cd', |
'options' => array( |
'quiet' => array( |
'shortopt' => 'q', |
'doc' => 'Be quiet', |
), |
'reallyquiet' => array( |
'shortopt' => 'Q', |
'doc' => 'Be really quiet', |
), |
'date' => array( |
'shortopt' => 'D', |
'doc' => 'Diff against revision of DATE', |
'arg' => 'DATE', |
), |
'release' => array( |
'shortopt' => 'R', |
'doc' => 'Diff against tag for package release REL', |
'arg' => 'REL', |
), |
'revision' => array( |
'shortopt' => 'r', |
'doc' => 'Diff against revision REV', |
'arg' => 'REV', |
), |
'context' => array( |
'shortopt' => 'c', |
'doc' => 'Generate context diff', |
), |
'unified' => array( |
'shortopt' => 'u', |
'doc' => 'Generate unified diff', |
), |
'ignore-case' => array( |
'shortopt' => 'i', |
'doc' => 'Ignore case, consider upper- and lower-case letters equivalent', |
), |
'ignore-whitespace' => array( |
'shortopt' => 'b', |
'doc' => 'Ignore changes in amount of white space', |
), |
'ignore-blank-lines' => array( |
'shortopt' => 'B', |
'doc' => 'Ignore changes that insert or delete blank lines', |
), |
'brief' => array( |
'doc' => 'Report only whether the files differ, no details', |
), |
'dry-run' => array( |
'shortopt' => 'n', |
'doc' => 'Don\'t do anything, just pretend', |
), |
), |
'doc' => '<package.xml> |
Compares all the files in a package. Without any options, this |
command will compare the current code with the last checked-in code. |
Using the -r or -R option you may compare the current code with that |
of a specific release. |
', |
), |
'svntag' => array( |
'summary' => 'Set SVN Release Tag', |
'function' => 'doSvnTag', |
'shortcut' => 'sv', |
'options' => array( |
'quiet' => array( |
'shortopt' => 'q', |
'doc' => 'Be quiet', |
), |
'slide' => array( |
'shortopt' => 'F', |
'doc' => 'Move (slide) tag if it exists', |
), |
'delete' => array( |
'shortopt' => 'd', |
'doc' => 'Remove tag', |
), |
'dry-run' => array( |
'shortopt' => 'n', |
'doc' => 'Don\'t do anything, just pretend', |
), |
), |
'doc' => '<package.xml> [files...] |
Sets a SVN tag on all files in a package. Use this command after you have |
packaged a distribution tarball with the "package" command to tag what |
revisions of what files were in that release. If need to fix something |
after running svntag once, but before the tarball is released to the public, |
use the "slide" option to move the release tag. |
to include files (such as a second package.xml, or tests not included in the |
release), pass them as additional parameters. |
', |
), |
'cvstag' => array( |
'summary' => 'Set CVS Release Tag', |
'function' => 'doCvsTag', |
'shortcut' => 'ct', |
'options' => array( |
'quiet' => array( |
'shortopt' => 'q', |
'doc' => 'Be quiet', |
), |
'reallyquiet' => array( |
'shortopt' => 'Q', |
'doc' => 'Be really quiet', |
), |
'slide' => array( |
'shortopt' => 'F', |
'doc' => 'Move (slide) tag if it exists', |
), |
'delete' => array( |
'shortopt' => 'd', |
'doc' => 'Remove tag', |
), |
'dry-run' => array( |
'shortopt' => 'n', |
'doc' => 'Don\'t do anything, just pretend', |
), |
), |
'doc' => '<package.xml> [files...] |
Sets a CVS tag on all files in a package. Use this command after you have |
packaged a distribution tarball with the "package" command to tag what |
revisions of what files were in that release. If need to fix something |
after running cvstag once, but before the tarball is released to the public, |
use the "slide" option to move the release tag. |
to include files (such as a second package.xml, or tests not included in the |
release), pass them as additional parameters. |
', |
), |
'package-dependencies' => array( |
'summary' => 'Show package dependencies', |
'function' => 'doPackageDependencies', |
'shortcut' => 'pd', |
'options' => array(), |
'doc' => '<package-file> or <package.xml> or <install-package-name> |
List all dependencies the package has. |
Can take a tgz / tar file, package.xml or a package name of an installed package.' |
), |
'sign' => array( |
'summary' => 'Sign a package distribution file', |
'function' => 'doSign', |
'shortcut' => 'si', |
'options' => array( |
'verbose' => array( |
'shortopt' => 'v', |
'doc' => 'Display GnuPG output', |
), |
), |
'doc' => '<package-file> |
Signs a package distribution (.tar or .tgz) file with GnuPG.', |
), |
'makerpm' => array( |
'summary' => 'Builds an RPM spec file from a PEAR package', |
'function' => 'doMakeRPM', |
'shortcut' => 'rpm', |
'options' => array( |
'spec-template' => array( |
'shortopt' => 't', |
'arg' => 'FILE', |
'doc' => 'Use FILE as RPM spec file template' |
), |
'rpm-pkgname' => array( |
'shortopt' => 'p', |
'arg' => 'FORMAT', |
'doc' => 'Use FORMAT as format string for RPM package name, %s is replaced |
by the PEAR package name, defaults to "PEAR::%s".', |
), |
), |
'doc' => '<package-file> |
Creates an RPM .spec file for wrapping a PEAR package inside an RPM |
package. Intended to be used from the SPECS directory, with the PEAR |
package tarball in the SOURCES directory: |
$ pear makerpm ../SOURCES/Net_Socket-1.0.tgz |
Wrote RPM spec file PEAR::Net_Geo-1.0.spec |
$ rpm -bb PEAR::Net_Socket-1.0.spec |
... |
Wrote: /usr/src/redhat/RPMS/i386/PEAR::Net_Socket-1.0-1.i386.rpm |
', |
), |
'convert' => array( |
'summary' => 'Convert a package.xml 1.0 to package.xml 2.0 format', |
'function' => 'doConvert', |
'shortcut' => 'c2', |
'options' => array( |
'flat' => array( |
'shortopt' => 'f', |
'doc' => 'do not beautify the filelist.', |
), |
), |
'doc' => '[descfile] [descfile2] |
Converts a package.xml in 1.0 format into a package.xml |
in 2.0 format. The new file will be named package2.xml by default, |
and package.xml will be used as the old file by default. |
This is not the most intelligent conversion, and should only be |
used for automated conversion or learning the format. |
' |
), |
); |
var $output; |
/** |
* PEAR_Command_Package constructor. |
* |
* @access public |
*/ |
function __construct(&$ui, &$config) |
{ |
parent::__construct($ui, $config); |
} |
function _displayValidationResults($err, $warn, $strict = false) |
{ |
foreach ($err as $e) { |
$this->output .= "Error: $e\n"; |
} |
foreach ($warn as $w) { |
$this->output .= "Warning: $w\n"; |
} |
$this->output .= sprintf('Validation: %d error(s), %d warning(s)'."\n", |
sizeof($err), sizeof($warn)); |
if ($strict && count($err) > 0) { |
$this->output .= "Fix these errors and try again."; |
return false; |
} |
return true; |
} |
function &getPackager() |
{ |
if (!class_exists('PEAR_Packager')) { |
require_once 'PEAR/Packager.php'; |
} |
$a = new PEAR_Packager; |
return $a; |
} |
function &getPackageFile($config, $debug = false) |
{ |
if (!class_exists('PEAR_Common')) { |
require_once 'PEAR/Common.php'; |
} |
if (!class_exists('PEAR_PackageFile')) { |
require_once 'PEAR/PackageFile.php'; |
} |
$a = new PEAR_PackageFile($config, $debug); |
$common = new PEAR_Common; |
$common->ui = $this->ui; |
$a->setLogger($common); |
return $a; |
} |
function doPackage($command, $options, $params) |
{ |
$this->output = ''; |
$pkginfofile = isset($params[0]) ? $params[0] : 'package.xml'; |
$pkg2 = isset($params[1]) ? $params[1] : null; |
if (!$pkg2 && !isset($params[0]) && file_exists('package2.xml')) { |
$pkg2 = 'package2.xml'; |
} |
$packager = &$this->getPackager(); |
$compress = empty($options['nocompress']) ? true : false; |
$result = $packager->package($pkginfofile, $compress, $pkg2); |
if (PEAR::isError($result)) { |
return $this->raiseError($result); |
} |
// Don't want output, only the package file name just created |
if (isset($options['showname'])) { |
$this->output = $result; |
} |
if ($this->output) { |
$this->ui->outputData($this->output, $command); |
} |
return true; |
} |
function doPackageValidate($command, $options, $params) |
{ |
$this->output = ''; |
if (count($params) < 1) { |
$params[0] = 'package.xml'; |
} |
$obj = &$this->getPackageFile($this->config, $this->_debug); |
$obj->rawReturn(); |
PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN); |
$info = $obj->fromTgzFile($params[0], PEAR_VALIDATE_NORMAL); |
if (PEAR::isError($info)) { |
$info = $obj->fromPackageFile($params[0], PEAR_VALIDATE_NORMAL); |
} else { |
$archive = $info->getArchiveFile(); |
$tar = new Archive_Tar($archive); |
$tar->extract(dirname($info->getPackageFile())); |
$info->setPackageFile(dirname($info->getPackageFile()) . DIRECTORY_SEPARATOR . |
$info->getPackage() . '-' . $info->getVersion() . DIRECTORY_SEPARATOR . |
basename($info->getPackageFile())); |
} |
PEAR::staticPopErrorHandling(); |
if (PEAR::isError($info)) { |
return $this->raiseError($info); |
} |
$valid = false; |
if ($info->getPackagexmlVersion() == '2.0') { |
if ($valid = $info->validate(PEAR_VALIDATE_NORMAL)) { |
$info->flattenFileList(); |
$valid = $info->validate(PEAR_VALIDATE_PACKAGING); |
} |
} else { |
$valid = $info->validate(PEAR_VALIDATE_PACKAGING); |
} |
$err = $warn = array(); |
if ($errors = $info->getValidationWarnings()) { |
foreach ($errors as $error) { |
if ($error['level'] == 'warning') { |
$warn[] = $error['message']; |
} else { |
$err[] = $error['message']; |
} |
} |
} |
$this->_displayValidationResults($err, $warn); |
$this->ui->outputData($this->output, $command); |
return true; |
} |
function doSvnTag($command, $options, $params) |
{ |
$this->output = ''; |
$_cmd = $command; |
if (count($params) < 1) { |
$help = $this->getHelp($command); |
return $this->raiseError("$command: missing parameter: $help[0]"); |
} |
$packageFile = realpath($params[0]); |
$dir = dirname($packageFile); |
$dir = substr($dir, strrpos($dir, DIRECTORY_SEPARATOR) + 1); |
$obj = &$this->getPackageFile($this->config, $this->_debug); |
$info = $obj->fromAnyFile($packageFile, PEAR_VALIDATE_NORMAL); |
if (PEAR::isError($info)) { |
return $this->raiseError($info); |
} |
$err = $warn = array(); |
if (!$info->validate()) { |
foreach ($info->getValidationWarnings() as $error) { |
if ($error['level'] == 'warning') { |
$warn[] = $error['message']; |
} else { |
$err[] = $error['message']; |
} |
} |
} |
if (!$this->_displayValidationResults($err, $warn, true)) { |
$this->ui->outputData($this->output, $command); |
return $this->raiseError('SVN tag failed'); |
} |
$version = $info->getVersion(); |
$package = $info->getName(); |
$svntag = "$package-$version"; |
if (isset($options['delete'])) { |
return $this->_svnRemoveTag($version, $package, $svntag, $packageFile, $options); |
} |
$path = $this->_svnFindPath($packageFile); |
// Check if there are any modified files |
$fp = popen('svn st --xml ' . dirname($packageFile), "r"); |
$out = ''; |
while ($line = fgets($fp, 1024)) { |
$out .= rtrim($line)."\n"; |
} |
pclose($fp); |
if (!isset($options['quiet']) && strpos($out, 'item="modified"')) { |
$params = array(array( |
'name' => 'modified', |
'type' => 'yesno', |
'default' => 'no', |
'prompt' => 'You have files in your SVN checkout (' . $path['from'] . ') that have been modified but not committed, do you still want to tag ' . $version . '?', |
)); |
$answers = $this->ui->confirmDialog($params); |
if (!in_array($answers['modified'], array('y', 'yes', 'on', '1'))) { |
return true; |
} |
} |
if (isset($options['slide'])) { |
$this->_svnRemoveTag($version, $package, $svntag, $packageFile, $options); |
} |
// Check if tag already exists |
$releaseTag = $path['local']['base'] . 'tags' . DIRECTORY_SEPARATOR . $svntag; |
$existsCommand = 'svn ls ' . $path['base'] . 'tags/'; |
$fp = popen($existsCommand, "r"); |
$out = ''; |
while ($line = fgets($fp, 1024)) { |
$out .= rtrim($line)."\n"; |
} |
pclose($fp); |
if (in_array($svntag . DIRECTORY_SEPARATOR, explode("\n", $out))) { |
$this->ui->outputData($this->output, $command); |
return $this->raiseError('SVN tag ' . $svntag . ' for ' . $package . ' already exists.'); |
} elseif (file_exists($path['local']['base'] . 'tags') === false) { |
return $this->raiseError('Can not locate the tags directory at ' . $path['local']['base'] . 'tags'); |
} elseif (is_writeable($path['local']['base'] . 'tags') === false) { |
return $this->raiseError('Can not write to the tag directory at ' . $path['local']['base'] . 'tags'); |
} else { |
$makeCommand = 'svn mkdir ' . $releaseTag; |
$this->output .= "+ $makeCommand\n"; |
if (empty($options['dry-run'])) { |
// We need to create the tag dir. |
$fp = popen($makeCommand, "r"); |
$out = ''; |
while ($line = fgets($fp, 1024)) { |
$out .= rtrim($line)."\n"; |
} |
pclose($fp); |
$this->output .= "$out\n"; |
} |
} |
$command = 'svn'; |
if (isset($options['quiet'])) { |
$command .= ' -q'; |
} |
$command .= ' copy --parents '; |
$dir = dirname($packageFile); |
$dir = substr($dir, strrpos($dir, DIRECTORY_SEPARATOR) + 1); |
$files = array_keys($info->getFilelist()); |
if (!in_array(basename($packageFile), $files)) { |
$files[] = basename($packageFile); |
} |
array_shift($params); |
if (count($params)) { |
// add in additional files to be tagged (package files and such) |
$files = array_merge($files, $params); |
} |
$commands = array(); |
foreach ($files as $file) { |
if (!file_exists($file)) { |
$file = $dir . DIRECTORY_SEPARATOR . $file; |
} |
$commands[] = $command . ' ' . escapeshellarg($file) . ' ' . |
escapeshellarg($releaseTag . DIRECTORY_SEPARATOR . $file); |
} |
$this->output .= implode("\n", $commands) . "\n"; |
if (empty($options['dry-run'])) { |
foreach ($commands as $command) { |
$fp = popen($command, "r"); |
while ($line = fgets($fp, 1024)) { |
$this->output .= rtrim($line)."\n"; |
} |
pclose($fp); |
} |
} |
$command = 'svn ci -m "Tagging the ' . $version . ' release" ' . $releaseTag . "\n"; |
$this->output .= "+ $command\n"; |
if (empty($options['dry-run'])) { |
$fp = popen($command, "r"); |
while ($line = fgets($fp, 1024)) { |
$this->output .= rtrim($line)."\n"; |
} |
pclose($fp); |
} |
$this->ui->outputData($this->output, $_cmd); |
return true; |
} |
function _svnFindPath($file) |
{ |
$xml = ''; |
$command = "svn info --xml $file"; |
$fp = popen($command, "r"); |
while ($line = fgets($fp, 1024)) { |
$xml .= rtrim($line)."\n"; |
} |
pclose($fp); |
$url_tag = strpos($xml, '<url>'); |
$url = substr($xml, $url_tag + 5, strpos($xml, '</url>', $url_tag + 5) - ($url_tag + 5)); |
$path = array(); |
$path['from'] = substr($url, 0, strrpos($url, '/')); |
$path['base'] = substr($path['from'], 0, strrpos($path['from'], '/') + 1); |
// Figure out the local paths - see http://pear.php.net/bugs/17463 |
$pos = strpos($file, DIRECTORY_SEPARATOR . 'trunk' . DIRECTORY_SEPARATOR); |
if ($pos === false) { |
$pos = strpos($file, DIRECTORY_SEPARATOR . 'branches' . DIRECTORY_SEPARATOR); |
} |
$path['local']['base'] = substr($file, 0, $pos + 1); |
return $path; |
} |
function _svnRemoveTag($version, $package, $tag, $packageFile, $options) |
{ |
$command = 'svn'; |
if (isset($options['quiet'])) { |
$command .= ' -q'; |
} |
$command .= ' remove'; |
$command .= ' -m "Removing tag for the ' . $version . ' release."'; |
$path = $this->_svnFindPath($packageFile); |
$command .= ' ' . $path['base'] . 'tags/' . $tag; |
if ($this->config->get('verbose') > 1) { |
$this->output .= "+ $command\n"; |
} |
$this->output .= "+ $command\n"; |
if (empty($options['dry-run'])) { |
$fp = popen($command, "r"); |
while ($line = fgets($fp, 1024)) { |
$this->output .= rtrim($line)."\n"; |
} |
pclose($fp); |
} |
$this->ui->outputData($this->output, $command); |
return true; |
} |
function doCvsTag($command, $options, $params) |
{ |
$this->output = ''; |
$_cmd = $command; |
if (count($params) < 1) { |
$help = $this->getHelp($command); |
return $this->raiseError("$command: missing parameter: $help[0]"); |
} |
$packageFile = realpath($params[0]); |
$obj = &$this->getPackageFile($this->config, $this->_debug); |
$info = $obj->fromAnyFile($packageFile, PEAR_VALIDATE_NORMAL); |
if (PEAR::isError($info)) { |
return $this->raiseError($info); |
} |
$err = $warn = array(); |
if (!$info->validate()) { |
foreach ($info->getValidationWarnings() as $error) { |
if ($error['level'] == 'warning') { |
$warn[] = $error['message']; |
} else { |
$err[] = $error['message']; |
} |
} |
} |
if (!$this->_displayValidationResults($err, $warn, true)) { |
$this->ui->outputData($this->output, $command); |
return $this->raiseError('CVS tag failed'); |
} |
$version = $info->getVersion(); |
$cvsversion = preg_replace('/[^a-z0-9]/i', '_', $version); |
$cvstag = "RELEASE_$cvsversion"; |
$files = array_keys($info->getFilelist()); |
$command = 'cvs'; |
if (isset($options['quiet'])) { |
$command .= ' -q'; |
} |
if (isset($options['reallyquiet'])) { |
$command .= ' -Q'; |
} |
$command .= ' tag'; |
if (isset($options['slide'])) { |
$command .= ' -F'; |
} |
if (isset($options['delete'])) { |
$command .= ' -d'; |
} |
$command .= ' ' . $cvstag . ' ' . escapeshellarg($params[0]); |
array_shift($params); |
if (count($params)) { |
// add in additional files to be tagged |
$files = array_merge($files, $params); |
} |
$dir = dirname($packageFile); |
$dir = substr($dir, strrpos($dir, '/') + 1); |
foreach ($files as $file) { |
if (!file_exists($file)) { |
$file = $dir . DIRECTORY_SEPARATOR . $file; |
} |
$command .= ' ' . escapeshellarg($file); |
} |
if ($this->config->get('verbose') > 1) { |
$this->output .= "+ $command\n"; |
} |
$this->output .= "+ $command\n"; |
if (empty($options['dry-run'])) { |
$fp = popen($command, "r"); |
while ($line = fgets($fp, 1024)) { |
$this->output .= rtrim($line)."\n"; |
} |
pclose($fp); |
} |
$this->ui->outputData($this->output, $_cmd); |
return true; |
} |
function doCvsDiff($command, $options, $params) |
{ |
$this->output = ''; |
if (sizeof($params) < 1) { |
$help = $this->getHelp($command); |
return $this->raiseError("$command: missing parameter: $help[0]"); |
} |
$file = realpath($params[0]); |
$obj = &$this->getPackageFile($this->config, $this->_debug); |
$info = $obj->fromAnyFile($file, PEAR_VALIDATE_NORMAL); |
if (PEAR::isError($info)) { |
return $this->raiseError($info); |
} |
$err = $warn = array(); |
if (!$info->validate()) { |
foreach ($info->getValidationWarnings() as $error) { |
if ($error['level'] == 'warning') { |
$warn[] = $error['message']; |
} else { |
$err[] = $error['message']; |
} |
} |
} |
if (!$this->_displayValidationResults($err, $warn, true)) { |
$this->ui->outputData($this->output, $command); |
return $this->raiseError('CVS diff failed'); |
} |
$info1 = $info->getFilelist(); |
$files = $info1; |
$cmd = "cvs"; |
if (isset($options['quiet'])) { |
$cmd .= ' -q'; |
unset($options['quiet']); |
} |
if (isset($options['reallyquiet'])) { |
$cmd .= ' -Q'; |
unset($options['reallyquiet']); |
} |
if (isset($options['release'])) { |
$cvsversion = preg_replace('/[^a-z0-9]/i', '_', $options['release']); |
$cvstag = "RELEASE_$cvsversion"; |
$options['revision'] = $cvstag; |
unset($options['release']); |
} |
$execute = true; |
if (isset($options['dry-run'])) { |
$execute = false; |
unset($options['dry-run']); |
} |
$cmd .= ' diff'; |
// the rest of the options are passed right on to "cvs diff" |
foreach ($options as $option => $optarg) { |
$arg = $short = false; |
if (isset($this->commands[$command]['options'][$option])) { |
$arg = $this->commands[$command]['options'][$option]['arg']; |
$short = $this->commands[$command]['options'][$option]['shortopt']; |
} |
$cmd .= $short ? " -$short" : " --$option"; |
if ($arg && $optarg) { |
$cmd .= ($short ? '' : '=') . escapeshellarg($optarg); |
} |
} |
foreach ($files as $file) { |
$cmd .= ' ' . escapeshellarg($file['name']); |
} |
if ($this->config->get('verbose') > 1) { |
$this->output .= "+ $cmd\n"; |
} |
if ($execute) { |
$fp = popen($cmd, "r"); |
while ($line = fgets($fp, 1024)) { |
$this->output .= rtrim($line)."\n"; |
} |
pclose($fp); |
} |
$this->ui->outputData($this->output, $command); |
return true; |
} |
function doPackageDependencies($command, $options, $params) |
{ |
// $params[0] -> the PEAR package to list its information |
if (count($params) !== 1) { |
return $this->raiseError("bad parameter(s), try \"help $command\""); |
} |
$obj = &$this->getPackageFile($this->config, $this->_debug); |
if (is_file($params[0]) || strpos($params[0], '.xml') > 0) { |
$info = $obj->fromAnyFile($params[0], PEAR_VALIDATE_NORMAL); |
} else { |
$reg = $this->config->getRegistry(); |
$info = $obj->fromArray($reg->packageInfo($params[0])); |
} |
if (PEAR::isError($info)) { |
return $this->raiseError($info); |
} |
$deps = $info->getDeps(); |
if (is_array($deps)) { |
if ($info->getPackagexmlVersion() == '1.0') { |
$data = array( |
'caption' => 'Dependencies for pear/' . $info->getPackage(), |
'border' => true, |
'headline' => array("Required?", "Type", "Name", "Relation", "Version"), |
); |
foreach ($deps as $d) { |
if (isset($d['optional'])) { |
if ($d['optional'] == 'yes') { |
$req = 'No'; |
} else { |
$req = 'Yes'; |
} |
} else { |
$req = 'Yes'; |
} |
if (isset($this->_deps_rel_trans[$d['rel']])) { |
$rel = $this->_deps_rel_trans[$d['rel']]; |
} else { |
$rel = $d['rel']; |
} |
if (isset($this->_deps_type_trans[$d['type']])) { |
$type = ucfirst($this->_deps_type_trans[$d['type']]); |
} else { |
$type = $d['type']; |
} |
if (isset($d['name'])) { |
$name = $d['name']; |
} else { |
$name = ''; |
} |
if (isset($d['version'])) { |
$version = $d['version']; |
} else { |
$version = ''; |
} |
$data['data'][] = array($req, $type, $name, $rel, $version); |
} |
} else { // package.xml 2.0 dependencies display |
require_once 'PEAR/Dependency2.php'; |
$deps = $info->getDependencies(); |
$reg = &$this->config->getRegistry(); |
if (is_array($deps)) { |
$d = new PEAR_Dependency2($this->config, array(), ''); |
$data = array( |
'caption' => 'Dependencies for ' . $info->getPackage(), |
'border' => true, |
'headline' => array("Required?", "Type", "Name", 'Versioning', 'Group'), |
); |
foreach ($deps as $type => $subd) { |
$req = ($type == 'required') ? 'Yes' : 'No'; |
if ($type == 'group' && isset($subd['attribs']['name'])) { |
$group = $subd['attribs']['name']; |
} else { |
$group = ''; |
} |
if (!isset($subd[0])) { |
$subd = array($subd); |
} |
foreach ($subd as $groupa) { |
foreach ($groupa as $deptype => $depinfo) { |
if ($deptype == 'attribs') { |
continue; |
} |
if ($deptype == 'pearinstaller') { |
$deptype = 'pear Installer'; |
} |
if (!isset($depinfo[0])) { |
$depinfo = array($depinfo); |
} |
foreach ($depinfo as $inf) { |
$name = ''; |
if (isset($inf['channel'])) { |
$alias = $reg->channelAlias($inf['channel']); |
if (!$alias) { |
$alias = '(channel?) ' .$inf['channel']; |
} |
$name = $alias . '/'; |
} |
if (isset($inf['name'])) { |
$name .= $inf['name']; |
} elseif (isset($inf['pattern'])) { |
$name .= $inf['pattern']; |
} else { |
$name .= ''; |
} |
if (isset($inf['uri'])) { |
$name .= ' [' . $inf['uri'] . ']'; |
} |
if (isset($inf['conflicts'])) { |
$ver = 'conflicts'; |
} else { |
$ver = $d->_getExtraString($inf); |
} |
$data['data'][] = array($req, ucfirst($deptype), $name, |
$ver, $group); |
} |
} |
} |
} |
} |
} |
$this->ui->outputData($data, $command); |
return true; |
} |
// Fallback |
$this->ui->outputData("This package does not have any dependencies.", $command); |
} |
function doSign($command, $options, $params) |
{ |
// should move most of this code into PEAR_Packager |
// so it'll be easy to implement "pear package --sign" |
if (count($params) !== 1) { |
return $this->raiseError("bad parameter(s), try \"help $command\""); |
} |
require_once 'System.php'; |
require_once 'Archive/Tar.php'; |
if (!file_exists($params[0])) { |
return $this->raiseError("file does not exist: $params[0]"); |
} |
$obj = $this->getPackageFile($this->config, $this->_debug); |
$info = $obj->fromTgzFile($params[0], PEAR_VALIDATE_NORMAL); |
if (PEAR::isError($info)) { |
return $this->raiseError($info); |
} |
$tar = new Archive_Tar($params[0]); |
$tmpdir = $this->config->get('temp_dir'); |
$tmpdir = System::mktemp(' -t "' . $tmpdir . '" -d pearsign'); |
if (!$tar->extractList('package2.xml package.xml package.sig', $tmpdir)) { |
return $this->raiseError("failed to extract tar file"); |
} |
if (file_exists("$tmpdir/package.sig")) { |
return $this->raiseError("package already signed"); |
} |
$packagexml = 'package.xml'; |
if (file_exists("$tmpdir/package2.xml")) { |
$packagexml = 'package2.xml'; |
} |
if (file_exists("$tmpdir/package.sig")) { |
unlink("$tmpdir/package.sig"); |
} |
if (!file_exists("$tmpdir/$packagexml")) { |
return $this->raiseError("Extracted file $tmpdir/$packagexml not found."); |
} |
$input = $this->ui->userDialog($command, |
array('GnuPG Passphrase'), |
array('password')); |
if (!isset($input[0])) { |
//use empty passphrase |
$input[0] = ''; |
} |
$devnull = (isset($options['verbose'])) ? '' : ' 2>/dev/null'; |
$gpg = popen("gpg --batch --passphrase-fd 0 --armor --detach-sign --output $tmpdir/package.sig $tmpdir/$packagexml" . $devnull, "w"); |
if (!$gpg) { |
return $this->raiseError("gpg command failed"); |
} |
fwrite($gpg, "$input[0]\n"); |
if (pclose($gpg) || !file_exists("$tmpdir/package.sig")) { |
return $this->raiseError("gpg sign failed"); |
} |
if (!$tar->addModify("$tmpdir/package.sig", '', $tmpdir)) { |
return $this->raiseError('failed adding signature to file'); |
} |
$this->ui->outputData("Package signed.", $command); |
return true; |
} |
/** |
* For unit testing purposes |
*/ |
function &getInstaller(&$ui) |
{ |
if (!class_exists('PEAR_Installer')) { |
require_once 'PEAR/Installer.php'; |
} |
$a = new PEAR_Installer($ui); |
return $a; |
} |
/** |
* For unit testing purposes |
*/ |
function &getCommandPackaging(&$ui, &$config) |
{ |
if (!class_exists('PEAR_Command_Packaging')) { |
if ($fp = @fopen('PEAR/Command/Packaging.php', 'r', true)) { |
fclose($fp); |
include_once 'PEAR/Command/Packaging.php'; |
} |
} |
if (class_exists('PEAR_Command_Packaging')) { |
$a = new PEAR_Command_Packaging($ui, $config); |
} else { |
$a = null; |
} |
return $a; |
} |
function doMakeRPM($command, $options, $params) |
{ |
// Check to see if PEAR_Command_Packaging is installed, and |
// transparently switch to use the "make-rpm-spec" command from it |
// instead, if it does. Otherwise, continue to use the old version |
// of "makerpm" supplied with this package (PEAR). |
$packaging_cmd = $this->getCommandPackaging($this->ui, $this->config); |
if ($packaging_cmd !== null) { |
$this->ui->outputData('PEAR_Command_Packaging is installed; using '. |
'newer "make-rpm-spec" command instead'); |
return $packaging_cmd->run('make-rpm-spec', $options, $params); |
} |
$this->ui->outputData('WARNING: "pear makerpm" is no longer available; an '. |
'improved version is available via "pear make-rpm-spec", which '. |
'is available by installing PEAR_Command_Packaging'); |
return true; |
} |
function doConvert($command, $options, $params) |
{ |
$packagexml = isset($params[0]) ? $params[0] : 'package.xml'; |
$newpackagexml = isset($params[1]) ? $params[1] : dirname($packagexml) . |
DIRECTORY_SEPARATOR . 'package2.xml'; |
$pkg = &$this->getPackageFile($this->config, $this->_debug); |
PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN); |
$pf = $pkg->fromPackageFile($packagexml, PEAR_VALIDATE_NORMAL); |
PEAR::staticPopErrorHandling(); |
if (PEAR::isError($pf)) { |
if (is_array($pf->getUserInfo())) { |
foreach ($pf->getUserInfo() as $warning) { |
$this->ui->outputData($warning['message']); |
} |
} |
return $this->raiseError($pf); |
} |
if (is_a($pf, 'PEAR_PackageFile_v2')) { |
$this->ui->outputData($packagexml . ' is already a package.xml version 2.0'); |
return true; |
} |
$gen = &$pf->getDefaultGenerator(); |
$newpf = &$gen->toV2(); |
$newpf->setPackagefile($newpackagexml); |
$gen = &$newpf->getDefaultGenerator(); |
PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN); |
$state = (isset($options['flat']) ? PEAR_VALIDATE_PACKAGING : PEAR_VALIDATE_NORMAL); |
$saved = $gen->toPackageFile(dirname($newpackagexml), $state, basename($newpackagexml)); |
PEAR::staticPopErrorHandling(); |
if (PEAR::isError($saved)) { |
if (is_array($saved->getUserInfo())) { |
foreach ($saved->getUserInfo() as $warning) { |
$this->ui->outputData($warning['message']); |
} |
} |
$this->ui->outputData($saved->getMessage()); |
return true; |
} |
$this->ui->outputData('Wrote new version 2.0 package.xml to "' . $saved . '"'); |
return true; |
} |
} |
/branches/v1.3-critias/bibliotheque/pear/PEAR/Command/Build.php |
---|
New file |
0,0 → 1,84 |
<?php |
/** |
* PEAR_Command_Auth (build command) |
* |
* PHP versions 4 and 5 |
* |
* @category pear |
* @package PEAR |
* @author Stig Bakken <ssb@php.net> |
* @author Tomas V.V.Cox <cox@idecnet.com> |
* @author Greg Beaver <cellog@php.net> |
* @copyright 1997-2009 The Authors |
* @license http://opensource.org/licenses/bsd-license.php New BSD License |
* @link http://pear.php.net/package/PEAR |
* @since File available since Release 0.1 |
*/ |
/** |
* base class |
*/ |
require_once 'PEAR/Command/Common.php'; |
/** |
* PEAR commands for building extensions. |
* |
* @category pear |
* @package PEAR |
* @author Stig Bakken <ssb@php.net> |
* @author Tomas V.V.Cox <cox@idecnet.com> |
* @author Greg Beaver <cellog@php.net> |
* @copyright 1997-2009 The Authors |
* @license http://opensource.org/licenses/bsd-license.php New BSD License |
* @version Release: 1.10.1 |
* @link http://pear.php.net/package/PEAR |
* @since Class available since Release 0.1 |
*/ |
class PEAR_Command_Build extends PEAR_Command_Common |
{ |
var $commands = array( |
'build' => array( |
'summary' => 'Build an Extension From C Source', |
'function' => 'doBuild', |
'shortcut' => 'b', |
'options' => array(), |
'doc' => '[package.xml] |
Builds one or more extensions contained in a package.' |
), |
); |
/** |
* PEAR_Command_Build constructor. |
* |
* @access public |
*/ |
function __construct(&$ui, &$config) |
{ |
parent::__construct($ui, $config); |
} |
function doBuild($command, $options, $params) |
{ |
require_once 'PEAR/Builder.php'; |
if (sizeof($params) < 1) { |
$params[0] = 'package.xml'; |
} |
$builder = new PEAR_Builder($this->ui); |
$this->debug = $this->config->get('verbose'); |
$err = $builder->build($params[0], array(&$this, 'buildCallback')); |
if (PEAR::isError($err)) { |
return $err; |
} |
return true; |
} |
function buildCallback($what, $data) |
{ |
if (($what == 'cmdoutput' && $this->debug > 1) || |
($what == 'output' && $this->debug > 0)) { |
$this->ui->outputData(rtrim($data), 'build'); |
} |
} |
} |
/branches/v1.3-critias/bibliotheque/pear/PEAR/Command/Auth.php |
---|
New file |
0,0 → 1,80 |
<?php |
/** |
* PEAR_Command_Auth (login, logout commands) |
* |
* PHP versions 4 and 5 |
* |
* @category pear |
* @package PEAR |
* @author Stig Bakken <ssb@php.net> |
* @author Greg Beaver <cellog@php.net> |
* @copyright 1997-2009 The Authors |
* @license http://opensource.org/licenses/bsd-license.php New BSD License |
* @link http://pear.php.net/package/PEAR |
* @since File available since Release 0.1 |
* @deprecated since 1.8.0alpha1 |
*/ |
/** |
* base class |
*/ |
require_once 'PEAR/Command/Channels.php'; |
/** |
* PEAR commands for login/logout |
* |
* @category pear |
* @package PEAR |
* @author Stig Bakken <ssb@php.net> |
* @author Greg Beaver <cellog@php.net> |
* @copyright 1997-2009 The Authors |
* @license http://opensource.org/licenses/bsd-license.php New BSD License |
* @version Release: 1.10.1 |
* @link http://pear.php.net/package/PEAR |
* @since Class available since Release 0.1 |
* @deprecated since 1.8.0alpha1 |
*/ |
class PEAR_Command_Auth extends PEAR_Command_Channels |
{ |
var $commands = array( |
'login' => array( |
'summary' => 'Connects and authenticates to remote server [Deprecated in favor of channel-login]', |
'shortcut' => 'li', |
'function' => 'doLogin', |
'options' => array(), |
'doc' => '<channel name> |
WARNING: This function is deprecated in favor of using channel-login |
Log in to a remote channel server. If <channel name> is not supplied, |
the default channel is used. To use remote functions in the installer |
that require any kind of privileges, you need to log in first. The |
username and password you enter here will be stored in your per-user |
PEAR configuration (~/.pearrc on Unix-like systems). After logging |
in, your username and password will be sent along in subsequent |
operations on the remote server.', |
), |
'logout' => array( |
'summary' => 'Logs out from the remote server [Deprecated in favor of channel-logout]', |
'shortcut' => 'lo', |
'function' => 'doLogout', |
'options' => array(), |
'doc' => ' |
WARNING: This function is deprecated in favor of using channel-logout |
Logs out from the remote server. This command does not actually |
connect to the remote server, it only deletes the stored username and |
password from your user configuration.', |
) |
); |
/** |
* PEAR_Command_Auth constructor. |
* |
* @access public |
*/ |
function __construct(&$ui, &$config) |
{ |
parent::__construct($ui, $config); |
} |
} |
/branches/v1.3-critias/bibliotheque/pear/PEAR/Command/Remote.xml |
---|
New file |
0,0 → 1,109 |
<commands version="1.0"> |
<remote-info> |
<summary>Information About Remote Packages</summary> |
<function>doRemoteInfo</function> |
<shortcut>ri</shortcut> |
<options /> |
<doc><package> |
Get details on a package from the server.</doc> |
</remote-info> |
<list-upgrades> |
<summary>List Available Upgrades</summary> |
<function>doListUpgrades</function> |
<shortcut>lu</shortcut> |
<options> |
<channelinfo> |
<shortopt>i</shortopt> |
<doc>output fully channel-aware data, even on failure</doc> |
</channelinfo> |
</options> |
<doc>[preferred_state] |
List releases on the server of packages you have installed where |
a newer version is available with the same release state (stable etc.) |
or the state passed as the second parameter.</doc> |
</list-upgrades> |
<remote-list> |
<summary>List Remote Packages</summary> |
<function>doRemoteList</function> |
<shortcut>rl</shortcut> |
<options> |
<channel> |
<shortopt>c</shortopt> |
<doc>specify a channel other than the default channel</doc> |
<arg>CHAN</arg> |
</channel> |
</options> |
<doc> |
Lists the packages available on the configured server along with the |
latest stable release of each package.</doc> |
</remote-list> |
<search> |
<summary>Search remote package database</summary> |
<function>doSearch</function> |
<shortcut>sp</shortcut> |
<options> |
<channel> |
<shortopt>c</shortopt> |
<doc>specify a channel other than the default channel</doc> |
<arg>CHAN</arg> |
</channel> |
<allchannels> |
<shortopt>a</shortopt> |
<doc>search packages from all known channels</doc> |
</allchannels> |
<channelinfo> |
<shortopt>i</shortopt> |
<doc>output fully channel-aware data, even on failure</doc> |
</channelinfo> |
</options> |
<doc>[packagename] [packageinfo] |
Lists all packages which match the search parameters. The first |
parameter is a fragment of a packagename. The default channel |
will be used unless explicitly overridden. The second parameter |
will be used to match any portion of the summary/description</doc> |
</search> |
<list-all> |
<summary>List All Packages</summary> |
<function>doListAll</function> |
<shortcut>la</shortcut> |
<options> |
<channel> |
<shortopt>c</shortopt> |
<doc>specify a channel other than the default channel</doc> |
<arg>CHAN</arg> |
</channel> |
<channelinfo> |
<shortopt>i</shortopt> |
<doc>output fully channel-aware data, even on failure</doc> |
</channelinfo> |
</options> |
<doc> |
Lists the packages available on the configured server along with the |
latest stable release of each package.</doc> |
</list-all> |
<download> |
<summary>Download Package</summary> |
<function>doDownload</function> |
<shortcut>d</shortcut> |
<options> |
<nocompress> |
<shortopt>Z</shortopt> |
<doc>download an uncompressed (.tar) file</doc> |
</nocompress> |
</options> |
<doc><package>... |
Download package tarballs. The files will be named as suggested by the |
server, for example if you download the DB package and the latest stable |
version of DB is 1.6.5, the downloaded file will be DB-1.6.5.tgz.</doc> |
</download> |
<clear-cache> |
<summary>Clear Web Services Cache</summary> |
<function>doClearCache</function> |
<shortcut>cc</shortcut> |
<options /> |
<doc> |
Clear the XML-RPC/REST cache. See also the cache_ttl configuration |
parameter. |
</doc> |
</clear-cache> |
</commands> |
/branches/v1.3-critias/bibliotheque/pear/PEAR/Command/Channels.xml |
---|
New file |
0,0 → 1,123 |
<commands version="1.0"> |
<list-channels> |
<summary>List Available Channels</summary> |
<function>doList</function> |
<shortcut>lc</shortcut> |
<options /> |
<doc> |
List all available channels for installation. |
</doc> |
</list-channels> |
<update-channels> |
<summary>Update the Channel List</summary> |
<function>doUpdateAll</function> |
<shortcut>uc</shortcut> |
<options /> |
<doc> |
List all installed packages in all channels. |
</doc> |
</update-channels> |
<channel-delete> |
<summary>Remove a Channel From the List</summary> |
<function>doDelete</function> |
<shortcut>cde</shortcut> |
<options /> |
<doc><channel name> |
Delete a channel from the registry. You may not |
remove any channel that has installed packages. |
</doc> |
</channel-delete> |
<channel-add> |
<summary>Add a Channel</summary> |
<function>doAdd</function> |
<shortcut>ca</shortcut> |
<options /> |
<doc><channel.xml> |
Add a private channel to the channel list. Note that all |
public channels should be synced using "update-channels". |
Parameter may be either a local file or remote URL to a |
channel.xml. |
</doc> |
</channel-add> |
<channel-update> |
<summary>Update an Existing Channel</summary> |
<function>doUpdate</function> |
<shortcut>cu</shortcut> |
<options> |
<force> |
<shortopt>f</shortopt> |
<doc>will force download of new channel.xml if an existing channel name is used</doc> |
</force> |
<channel> |
<shortopt>c</shortopt> |
<doc>will force download of new channel.xml if an existing channel name is used</doc> |
<arg>CHANNEL</arg> |
</channel> |
</options> |
<doc>[<channel.xml>|<channel name>] |
Update a channel in the channel list directly. Note that all |
public channels can be synced using "update-channels". |
Parameter may be a local or remote channel.xml, or the name of |
an existing channel. |
</doc> |
</channel-update> |
<channel-info> |
<summary>Retrieve Information on a Channel</summary> |
<function>doInfo</function> |
<shortcut>ci</shortcut> |
<options /> |
<doc><package> |
List the files in an installed package. |
</doc> |
</channel-info> |
<channel-alias> |
<summary>Specify an alias to a channel name</summary> |
<function>doAlias</function> |
<shortcut>cha</shortcut> |
<options /> |
<doc><channel> <alias> |
Specify a specific alias to use for a channel name. |
The alias may not be an existing channel name or |
alias. |
</doc> |
</channel-alias> |
<channel-discover> |
<summary>Initialize a Channel from its server</summary> |
<function>doDiscover</function> |
<shortcut>di</shortcut> |
<options /> |
<doc>[<channel.xml>|<channel name>] |
Initialize a channel from its server and create a local channel.xml. |
If <channel name> is in the format "<username>:<password>@<channel>" then |
<username> and <password> will be set as the login username/password for |
<channel>. Use caution when passing the username/password in this way, as |
it may allow other users on your computer to briefly view your username/ |
password via the system's process list. |
</doc> |
</channel-discover> |
<channel-login> |
<summary>Connects and authenticates to remote channel server</summary> |
<function>doLogin</function> |
<shortcut>cli</shortcut> |
<options /> |
<doc><channel name> |
Log in to a remote channel server. If <channel name> is not supplied, |
the default channel is used. To use remote functions in the installer |
that require any kind of privileges, you need to log in first. The |
username and password you enter here will be stored in your per-user |
PEAR configuration (~/.pearrc on Unix-like systems). After logging |
in, your username and password will be sent along in subsequent |
operations on the remote server.</doc> |
</channel-login> |
<channel-logout> |
<summary>Logs out from the remote channel server</summary> |
<function>doLogout</function> |
<shortcut>clo</shortcut> |
<options /> |
<doc><channel name> |
Logs out from a remote channel server. If <channel name> is not supplied, |
the default channel is used. This command does not actually connect to the |
remote server, it only deletes the stored username and password from your user |
configuration.</doc> |
</channel-logout> |
</commands> |
/branches/v1.3-critias/bibliotheque/pear/PEAR/Command/Package.xml |
---|
New file |
0,0 → 1,237 |
<commands version="1.0"> |
<package> |
<summary>Build Package</summary> |
<function>doPackage</function> |
<shortcut>p</shortcut> |
<options> |
<nocompress> |
<shortopt>Z</shortopt> |
<doc>Do not gzip the package file</doc> |
</nocompress> |
<showname> |
<shortopt>n</shortopt> |
<doc>Print the name of the packaged file.</doc> |
</showname> |
</options> |
<doc>[descfile] [descfile2] |
Creates a PEAR package from its description file (usually called |
package.xml). If a second packagefile is passed in, then |
the packager will check to make sure that one is a package.xml |
version 1.0, and the other is a package.xml version 2.0. The |
package.xml version 1.0 will be saved as "package.xml" in the archive, |
and the other as "package2.xml" in the archive" |
</doc> |
</package> |
<package-validate> |
<summary>Validate Package Consistency</summary> |
<function>doPackageValidate</function> |
<shortcut>pv</shortcut> |
<options /> |
<doc> |
</doc> |
</package-validate> |
<cvsdiff> |
<summary>Run a "cvs diff" for all files in a package</summary> |
<function>doCvsDiff</function> |
<shortcut>cd</shortcut> |
<options> |
<quiet> |
<shortopt>q</shortopt> |
<doc>Be quiet</doc> |
</quiet> |
<reallyquiet> |
<shortopt>Q</shortopt> |
<doc>Be really quiet</doc> |
</reallyquiet> |
<date> |
<shortopt>D</shortopt> |
<doc>Diff against revision of DATE</doc> |
<arg>DATE</arg> |
</date> |
<release> |
<shortopt>R</shortopt> |
<doc>Diff against tag for package release REL</doc> |
<arg>REL</arg> |
</release> |
<revision> |
<shortopt>r</shortopt> |
<doc>Diff against revision REV</doc> |
<arg>REV</arg> |
</revision> |
<context> |
<shortopt>c</shortopt> |
<doc>Generate context diff</doc> |
</context> |
<unified> |
<shortopt>u</shortopt> |
<doc>Generate unified diff</doc> |
</unified> |
<ignore-case> |
<shortopt>i</shortopt> |
<doc>Ignore case, consider upper- and lower-case letters equivalent</doc> |
</ignore-case> |
<ignore-whitespace> |
<shortopt>b</shortopt> |
<doc>Ignore changes in amount of white space</doc> |
</ignore-whitespace> |
<ignore-blank-lines> |
<shortopt>B</shortopt> |
<doc>Ignore changes that insert or delete blank lines</doc> |
</ignore-blank-lines> |
<brief> |
<shortopt></shortopt> |
<doc>Report only whether the files differ, no details</doc> |
</brief> |
<dry-run> |
<shortopt>n</shortopt> |
<doc>Don't do anything, just pretend</doc> |
</dry-run> |
</options> |
<doc><package.xml> |
Compares all the files in a package. Without any options, this |
command will compare the current code with the last checked-in code. |
Using the -r or -R option you may compare the current code with that |
of a specific release. |
</doc> |
</cvsdiff> |
<svntag> |
<summary>Set SVN Release Tag</summary> |
<function>doSvnTag</function> |
<shortcut>sv</shortcut> |
<options> |
<quiet> |
<shortopt>q</shortopt> |
<doc>Be quiet</doc> |
</quiet> |
<slide> |
<shortopt>F</shortopt> |
<doc>Move (slide) tag if it exists</doc> |
</slide> |
<delete> |
<shortopt>d</shortopt> |
<doc>Remove tag</doc> |
</delete> |
<dry-run> |
<shortopt>n</shortopt> |
<doc>Don't do anything, just pretend</doc> |
</dry-run> |
</options> |
<doc><package.xml> [files...] |
Sets a SVN tag on all files in a package. Use this command after you have |
packaged a distribution tarball with the "package" command to tag what |
revisions of what files were in that release. If need to fix something |
after running svntag once, but before the tarball is released to the public, |
use the "slide" option to move the release tag. |
to include files (such as a second package.xml, or tests not included in the |
release), pass them as additional parameters. |
</doc> |
</svntag> |
<cvstag> |
<summary>Set CVS Release Tag</summary> |
<function>doCvsTag</function> |
<shortcut>ct</shortcut> |
<options> |
<quiet> |
<shortopt>q</shortopt> |
<doc>Be quiet</doc> |
</quiet> |
<reallyquiet> |
<shortopt>Q</shortopt> |
<doc>Be really quiet</doc> |
</reallyquiet> |
<slide> |
<shortopt>F</shortopt> |
<doc>Move (slide) tag if it exists</doc> |
</slide> |
<delete> |
<shortopt>d</shortopt> |
<doc>Remove tag</doc> |
</delete> |
<dry-run> |
<shortopt>n</shortopt> |
<doc>Don't do anything, just pretend</doc> |
</dry-run> |
</options> |
<doc><package.xml> [files...] |
Sets a CVS tag on all files in a package. Use this command after you have |
packaged a distribution tarball with the "package" command to tag what |
revisions of what files were in that release. If need to fix something |
after running cvstag once, but before the tarball is released to the public, |
use the "slide" option to move the release tag. |
to include files (such as a second package.xml, or tests not included in the |
release), pass them as additional parameters. |
</doc> |
</cvstag> |
<package-dependencies> |
<summary>Show package dependencies</summary> |
<function>doPackageDependencies</function> |
<shortcut>pd</shortcut> |
<options /> |
<doc><package-file> or <package.xml> or <install-package-name> |
List all dependencies the package has. |
Can take a tgz / tar file, package.xml or a package name of an installed package.</doc> |
</package-dependencies> |
<sign> |
<summary>Sign a package distribution file</summary> |
<function>doSign</function> |
<shortcut>si</shortcut> |
<options> |
<verbose> |
<shortopt>v</shortopt> |
<doc>Display GnuPG output</doc> |
</verbose> |
</options> |
<doc><package-file> |
Signs a package distribution (.tar or .tgz) file with GnuPG.</doc> |
</sign> |
<makerpm> |
<summary>Builds an RPM spec file from a PEAR package</summary> |
<function>doMakeRPM</function> |
<shortcut>rpm</shortcut> |
<options> |
<spec-template> |
<shortopt>t</shortopt> |
<doc>Use FILE as RPM spec file template</doc> |
<arg>FILE</arg> |
</spec-template> |
<rpm-pkgname> |
<shortopt>p</shortopt> |
<doc>Use FORMAT as format string for RPM package name, %s is replaced |
by the PEAR package name, defaults to "PEAR::%s".</doc> |
<arg>FORMAT</arg> |
</rpm-pkgname> |
</options> |
<doc><package-file> |
Creates an RPM .spec file for wrapping a PEAR package inside an RPM |
package. Intended to be used from the SPECS directory, with the PEAR |
package tarball in the SOURCES directory: |
$ pear makerpm ../SOURCES/Net_Socket-1.0.tgz |
Wrote RPM spec file PEAR::Net_Geo-1.0.spec |
$ rpm -bb PEAR::Net_Socket-1.0.spec |
... |
Wrote: /usr/src/redhat/RPMS/i386/PEAR::Net_Socket-1.0-1.i386.rpm |
</doc> |
</makerpm> |
<convert> |
<summary>Convert a package.xml 1.0 to package.xml 2.0 format</summary> |
<function>doConvert</function> |
<shortcut>c2</shortcut> |
<options> |
<flat> |
<shortopt>f</shortopt> |
<doc>do not beautify the filelist.</doc> |
</flat> |
</options> |
<doc>[descfile] [descfile2] |
Converts a package.xml in 1.0 format into a package.xml |
in 2.0 format. The new file will be named package2.xml by default, |
and package.xml will be used as the old file by default. |
This is not the most intelligent conversion, and should only be |
used for automated conversion or learning the format. |
</doc> |
</convert> |
</commands> |
/branches/v1.3-critias/bibliotheque/pear/PEAR/Command/Config.php |
---|
New file |
0,0 → 1,414 |
<?php |
/** |
* PEAR_Command_Config (config-show, config-get, config-set, config-help, config-create commands) |
* |
* PHP versions 4 and 5 |
* |
* @category pear |
* @package PEAR |
* @author Stig Bakken <ssb@php.net> |
* @author Greg Beaver <cellog@php.net> |
* @copyright 1997-2009 The Authors |
* @license http://opensource.org/licenses/bsd-license.php New BSD License |
* @link http://pear.php.net/package/PEAR |
* @since File available since Release 0.1 |
*/ |
/** |
* base class |
*/ |
require_once 'PEAR/Command/Common.php'; |
/** |
* PEAR commands for managing configuration data. |
* |
* @category pear |
* @package PEAR |
* @author Stig Bakken <ssb@php.net> |
* @author Greg Beaver <cellog@php.net> |
* @copyright 1997-2009 The Authors |
* @license http://opensource.org/licenses/bsd-license.php New BSD License |
* @version Release: 1.10.1 |
* @link http://pear.php.net/package/PEAR |
* @since Class available since Release 0.1 |
*/ |
class PEAR_Command_Config extends PEAR_Command_Common |
{ |
var $commands = array( |
'config-show' => array( |
'summary' => 'Show All Settings', |
'function' => 'doConfigShow', |
'shortcut' => 'csh', |
'options' => array( |
'channel' => array( |
'shortopt' => 'c', |
'doc' => 'show configuration variables for another channel', |
'arg' => 'CHAN', |
), |
), |
'doc' => '[layer] |
Displays all configuration values. An optional argument |
may be used to tell which configuration layer to display. Valid |
configuration layers are "user", "system" and "default". To display |
configurations for different channels, set the default_channel |
configuration variable and run config-show again. |
', |
), |
'config-get' => array( |
'summary' => 'Show One Setting', |
'function' => 'doConfigGet', |
'shortcut' => 'cg', |
'options' => array( |
'channel' => array( |
'shortopt' => 'c', |
'doc' => 'show configuration variables for another channel', |
'arg' => 'CHAN', |
), |
), |
'doc' => '<parameter> [layer] |
Displays the value of one configuration parameter. The |
first argument is the name of the parameter, an optional second argument |
may be used to tell which configuration layer to look in. Valid configuration |
layers are "user", "system" and "default". If no layer is specified, a value |
will be picked from the first layer that defines the parameter, in the order |
just specified. The configuration value will be retrieved for the channel |
specified by the default_channel configuration variable. |
', |
), |
'config-set' => array( |
'summary' => 'Change Setting', |
'function' => 'doConfigSet', |
'shortcut' => 'cs', |
'options' => array( |
'channel' => array( |
'shortopt' => 'c', |
'doc' => 'show configuration variables for another channel', |
'arg' => 'CHAN', |
), |
), |
'doc' => '<parameter> <value> [layer] |
Sets the value of one configuration parameter. The first argument is |
the name of the parameter, the second argument is the new value. Some |
parameters are subject to validation, and the command will fail with |
an error message if the new value does not make sense. An optional |
third argument may be used to specify in which layer to set the |
configuration parameter. The default layer is "user". The |
configuration value will be set for the current channel, which |
is controlled by the default_channel configuration variable. |
', |
), |
'config-help' => array( |
'summary' => 'Show Information About Setting', |
'function' => 'doConfigHelp', |
'shortcut' => 'ch', |
'options' => array(), |
'doc' => '[parameter] |
Displays help for a configuration parameter. Without arguments it |
displays help for all configuration parameters. |
', |
), |
'config-create' => array( |
'summary' => 'Create a Default configuration file', |
'function' => 'doConfigCreate', |
'shortcut' => 'coc', |
'options' => array( |
'windows' => array( |
'shortopt' => 'w', |
'doc' => 'create a config file for a windows install', |
), |
), |
'doc' => '<root path> <filename> |
Create a default configuration file with all directory configuration |
variables set to subdirectories of <root path>, and save it as <filename>. |
This is useful especially for creating a configuration file for a remote |
PEAR installation (using the --remoteconfig option of install, upgrade, |
and uninstall). |
', |
), |
); |
/** |
* PEAR_Command_Config constructor. |
* |
* @access public |
*/ |
function __construct(&$ui, &$config) |
{ |
parent::__construct($ui, $config); |
} |
function doConfigShow($command, $options, $params) |
{ |
$layer = null; |
if (is_array($params)) { |
$layer = isset($params[0]) ? $params[0] : null; |
} |
// $params[0] -> the layer |
if ($error = $this->_checkLayer($layer)) { |
return $this->raiseError("config-show:$error"); |
} |
$keys = $this->config->getKeys(); |
sort($keys); |
$channel = isset($options['channel']) ? $options['channel'] : |
$this->config->get('default_channel'); |
$reg = &$this->config->getRegistry(); |
if (!$reg->channelExists($channel)) { |
return $this->raiseError('Channel "' . $channel . '" does not exist'); |
} |
$channel = $reg->channelName($channel); |
$data = array('caption' => 'Configuration (channel ' . $channel . '):'); |
foreach ($keys as $key) { |
$type = $this->config->getType($key); |
$value = $this->config->get($key, $layer, $channel); |
if ($type == 'password' && $value) { |
$value = '********'; |
} |
if ($value === false) { |
$value = 'false'; |
} elseif ($value === true) { |
$value = 'true'; |
} |
$data['data'][$this->config->getGroup($key)][] = array($this->config->getPrompt($key) , $key, $value); |
} |
foreach ($this->config->getLayers() as $layer) { |
$data['data']['Config Files'][] = array(ucfirst($layer) . ' Configuration File', 'Filename' , $this->config->getConfFile($layer)); |
} |
$this->ui->outputData($data, $command); |
return true; |
} |
function doConfigGet($command, $options, $params) |
{ |
$args_cnt = is_array($params) ? count($params) : 0; |
switch ($args_cnt) { |
case 1: |
$config_key = $params[0]; |
$layer = null; |
break; |
case 2: |
$config_key = $params[0]; |
$layer = $params[1]; |
if ($error = $this->_checkLayer($layer)) { |
return $this->raiseError("config-get:$error"); |
} |
break; |
case 0: |
default: |
return $this->raiseError("config-get expects 1 or 2 parameters"); |
} |
$reg = &$this->config->getRegistry(); |
$channel = isset($options['channel']) ? $options['channel'] : $this->config->get('default_channel'); |
if (!$reg->channelExists($channel)) { |
return $this->raiseError('Channel "' . $channel . '" does not exist'); |
} |
$channel = $reg->channelName($channel); |
$this->ui->outputData($this->config->get($config_key, $layer, $channel), $command); |
return true; |
} |
function doConfigSet($command, $options, $params) |
{ |
// $param[0] -> a parameter to set |
// $param[1] -> the value for the parameter |
// $param[2] -> the layer |
$failmsg = ''; |
if (count($params) < 2 || count($params) > 3) { |
$failmsg .= "config-set expects 2 or 3 parameters"; |
return PEAR::raiseError($failmsg); |
} |
if (isset($params[2]) && ($error = $this->_checkLayer($params[2]))) { |
$failmsg .= $error; |
return PEAR::raiseError("config-set:$failmsg"); |
} |
$channel = isset($options['channel']) ? $options['channel'] : $this->config->get('default_channel'); |
$reg = &$this->config->getRegistry(); |
if (!$reg->channelExists($channel)) { |
return $this->raiseError('Channel "' . $channel . '" does not exist'); |
} |
$channel = $reg->channelName($channel); |
if ($params[0] == 'default_channel' && !$reg->channelExists($params[1])) { |
return $this->raiseError('Channel "' . $params[1] . '" does not exist'); |
} |
if ($params[0] == 'preferred_mirror' |
&& ( |
!$reg->mirrorExists($channel, $params[1]) && |
(!$reg->channelExists($params[1]) || $channel != $params[1]) |
) |
) { |
$msg = 'Channel Mirror "' . $params[1] . '" does not exist'; |
$msg .= ' in your registry for channel "' . $channel . '".'; |
$msg .= "\n" . 'Attempt to run "pear channel-update ' . $channel .'"'; |
$msg .= ' if you believe this mirror should exist as you may'; |
$msg .= ' have outdated channel information.'; |
return $this->raiseError($msg); |
} |
if (count($params) == 2) { |
array_push($params, 'user'); |
$layer = 'user'; |
} else { |
$layer = $params[2]; |
} |
array_push($params, $channel); |
if (!call_user_func_array(array(&$this->config, 'set'), $params)) { |
array_pop($params); |
$failmsg = "config-set (" . implode(", ", $params) . ") failed, channel $channel"; |
} else { |
$this->config->store($layer); |
} |
if ($failmsg) { |
return $this->raiseError($failmsg); |
} |
$this->ui->outputData('config-set succeeded', $command); |
return true; |
} |
function doConfigHelp($command, $options, $params) |
{ |
if (empty($params)) { |
$params = $this->config->getKeys(); |
} |
$data['caption'] = "Config help" . ((count($params) == 1) ? " for $params[0]" : ''); |
$data['headline'] = array('Name', 'Type', 'Description'); |
$data['border'] = true; |
foreach ($params as $name) { |
$type = $this->config->getType($name); |
$docs = $this->config->getDocs($name); |
if ($type == 'set') { |
$docs = rtrim($docs) . "\nValid set: " . |
implode(' ', $this->config->getSetValues($name)); |
} |
$data['data'][] = array($name, $type, $docs); |
} |
$this->ui->outputData($data, $command); |
} |
function doConfigCreate($command, $options, $params) |
{ |
if (count($params) != 2) { |
return PEAR::raiseError('config-create: must have 2 parameters, root path and ' . |
'filename to save as'); |
} |
$root = $params[0]; |
// Clean up the DIRECTORY_SEPARATOR mess |
$ds2 = DIRECTORY_SEPARATOR . DIRECTORY_SEPARATOR; |
$root = preg_replace(array('!\\\\+!', '!/+!', "!$ds2+!"), |
array('/', '/', '/'), |
$root); |
if ($root{0} != '/') { |
if (!isset($options['windows'])) { |
return PEAR::raiseError('Root directory must be an absolute path beginning ' . |
'with "/", was: "' . $root . '"'); |
} |
if (!preg_match('/^[A-Za-z]:/', $root)) { |
return PEAR::raiseError('Root directory must be an absolute path beginning ' . |
'with "\\" or "C:\\", was: "' . $root . '"'); |
} |
} |
$windows = isset($options['windows']); |
if ($windows) { |
$root = str_replace('/', '\\', $root); |
} |
if (!file_exists($params[1]) && !@touch($params[1])) { |
return PEAR::raiseError('Could not create "' . $params[1] . '"'); |
} |
$params[1] = realpath($params[1]); |
$config = new PEAR_Config($params[1], '#no#system#config#', false, false); |
if ($root{strlen($root) - 1} == '/') { |
$root = substr($root, 0, strlen($root) - 1); |
} |
$config->noRegistry(); |
$config->set('php_dir', $windows ? "$root\\pear\\php" : "$root/pear/php", 'user'); |
$config->set('data_dir', $windows ? "$root\\pear\\data" : "$root/pear/data"); |
$config->set('www_dir', $windows ? "$root\\pear\\www" : "$root/pear/www"); |
$config->set('cfg_dir', $windows ? "$root\\pear\\cfg" : "$root/pear/cfg"); |
$config->set('ext_dir', $windows ? "$root\\pear\\ext" : "$root/pear/ext"); |
$config->set('doc_dir', $windows ? "$root\\pear\\docs" : "$root/pear/docs"); |
$config->set('test_dir', $windows ? "$root\\pear\\tests" : "$root/pear/tests"); |
$config->set('cache_dir', $windows ? "$root\\pear\\cache" : "$root/pear/cache"); |
$config->set('download_dir', $windows ? "$root\\pear\\download" : "$root/pear/download"); |
$config->set('temp_dir', $windows ? "$root\\pear\\temp" : "$root/pear/temp"); |
$config->set('bin_dir', $windows ? "$root\\pear" : "$root/pear"); |
$config->set('man_dir', $windows ? "$root\\pear\\man" : "$root/pear/man"); |
$config->writeConfigFile(); |
$this->_showConfig($config); |
$this->ui->outputData('Successfully created default configuration file "' . $params[1] . '"', |
$command); |
} |
function _showConfig(&$config) |
{ |
$params = array('user'); |
$keys = $config->getKeys(); |
sort($keys); |
$channel = 'pear.php.net'; |
$data = array('caption' => 'Configuration (channel ' . $channel . '):'); |
foreach ($keys as $key) { |
$type = $config->getType($key); |
$value = $config->get($key, 'user', $channel); |
if ($type == 'password' && $value) { |
$value = '********'; |
} |
if ($value === false) { |
$value = 'false'; |
} elseif ($value === true) { |
$value = 'true'; |
} |
$data['data'][$config->getGroup($key)][] = |
array($config->getPrompt($key) , $key, $value); |
} |
foreach ($config->getLayers() as $layer) { |
$data['data']['Config Files'][] = |
array(ucfirst($layer) . ' Configuration File', 'Filename' , |
$config->getConfFile($layer)); |
} |
$this->ui->outputData($data, 'config-show'); |
return true; |
} |
/** |
* Checks if a layer is defined or not |
* |
* @param string $layer The layer to search for |
* @return mixed False on no error or the error message |
*/ |
function _checkLayer($layer = null) |
{ |
if (!empty($layer) && $layer != 'default') { |
$layers = $this->config->getLayers(); |
if (!in_array($layer, $layers)) { |
return " only the layers: \"" . implode('" or "', $layers) . "\" are supported"; |
} |
} |
return false; |
} |
} |
/branches/v1.3-critias/bibliotheque/pear/PEAR/Command/Install.php |
---|
New file |
0,0 → 1,1269 |
<?php |
/** |
* PEAR_Command_Install (install, upgrade, upgrade-all, uninstall, bundle, run-scripts commands) |
* |
* PHP versions 4 and 5 |
* |
* @category pear |
* @package PEAR |
* @author Stig Bakken <ssb@php.net> |
* @author Greg Beaver <cellog@php.net> |
* @copyright 1997-2009 The Authors |
* @license http://opensource.org/licenses/bsd-license.php New BSD License |
* @link http://pear.php.net/package/PEAR |
* @since File available since Release 0.1 |
*/ |
/** |
* base class |
*/ |
require_once 'PEAR/Command/Common.php'; |
/** |
* PEAR commands for installation or deinstallation/upgrading of |
* packages. |
* |
* @category pear |
* @package PEAR |
* @author Stig Bakken <ssb@php.net> |
* @author Greg Beaver <cellog@php.net> |
* @copyright 1997-2009 The Authors |
* @license http://opensource.org/licenses/bsd-license.php New BSD License |
* @version Release: 1.10.1 |
* @link http://pear.php.net/package/PEAR |
* @since Class available since Release 0.1 |
*/ |
class PEAR_Command_Install extends PEAR_Command_Common |
{ |
// {{{ properties |
var $commands = array( |
'install' => array( |
'summary' => 'Install Package', |
'function' => 'doInstall', |
'shortcut' => 'i', |
'options' => array( |
'force' => array( |
'shortopt' => 'f', |
'doc' => 'will overwrite newer installed packages', |
), |
'loose' => array( |
'shortopt' => 'l', |
'doc' => 'do not check for recommended dependency version', |
), |
'nodeps' => array( |
'shortopt' => 'n', |
'doc' => 'ignore dependencies, install anyway', |
), |
'register-only' => array( |
'shortopt' => 'r', |
'doc' => 'do not install files, only register the package as installed', |
), |
'soft' => array( |
'shortopt' => 's', |
'doc' => 'soft install, fail silently, or upgrade if already installed', |
), |
'nobuild' => array( |
'shortopt' => 'B', |
'doc' => 'don\'t build C extensions', |
), |
'nocompress' => array( |
'shortopt' => 'Z', |
'doc' => 'request uncompressed files when downloading', |
), |
'installroot' => array( |
'shortopt' => 'R', |
'arg' => 'DIR', |
'doc' => 'root directory used when installing files (ala PHP\'s INSTALL_ROOT), use packagingroot for RPM', |
), |
'packagingroot' => array( |
'shortopt' => 'P', |
'arg' => 'DIR', |
'doc' => 'root directory used when packaging files, like RPM packaging', |
), |
'ignore-errors' => array( |
'doc' => 'force install even if there were errors', |
), |
'alldeps' => array( |
'shortopt' => 'a', |
'doc' => 'install all required and optional dependencies', |
), |
'onlyreqdeps' => array( |
'shortopt' => 'o', |
'doc' => 'install all required dependencies', |
), |
'offline' => array( |
'shortopt' => 'O', |
'doc' => 'do not attempt to download any urls or contact channels', |
), |
'pretend' => array( |
'shortopt' => 'p', |
'doc' => 'Only list the packages that would be downloaded', |
), |
), |
'doc' => '[channel/]<package> ... |
Installs one or more PEAR packages. You can specify a package to |
install in four ways: |
"Package-1.0.tgz" : installs from a local file |
"http://example.com/Package-1.0.tgz" : installs from |
anywhere on the net. |
"package.xml" : installs the package described in |
package.xml. Useful for testing, or for wrapping a PEAR package in |
another package manager such as RPM. |
"Package[-version/state][.tar]" : queries your default channel\'s server |
({config master_server}) and downloads the newest package with |
the preferred quality/state ({config preferred_state}). |
To retrieve Package version 1.1, use "Package-1.1," to retrieve |
Package state beta, use "Package-beta." To retrieve an uncompressed |
file, append .tar (make sure there is no file by the same name first) |
To download a package from another channel, prefix with the channel name like |
"channel/Package" |
More than one package may be specified at once. It is ok to mix these |
four ways of specifying packages. |
'), |
'upgrade' => array( |
'summary' => 'Upgrade Package', |
'function' => 'doInstall', |
'shortcut' => 'up', |
'options' => array( |
'channel' => array( |
'shortopt' => 'c', |
'doc' => 'upgrade packages from a specific channel', |
'arg' => 'CHAN', |
), |
'force' => array( |
'shortopt' => 'f', |
'doc' => 'overwrite newer installed packages', |
), |
'loose' => array( |
'shortopt' => 'l', |
'doc' => 'do not check for recommended dependency version', |
), |
'nodeps' => array( |
'shortopt' => 'n', |
'doc' => 'ignore dependencies, upgrade anyway', |
), |
'register-only' => array( |
'shortopt' => 'r', |
'doc' => 'do not install files, only register the package as upgraded', |
), |
'nobuild' => array( |
'shortopt' => 'B', |
'doc' => 'don\'t build C extensions', |
), |
'nocompress' => array( |
'shortopt' => 'Z', |
'doc' => 'request uncompressed files when downloading', |
), |
'installroot' => array( |
'shortopt' => 'R', |
'arg' => 'DIR', |
'doc' => 'root directory used when installing files (ala PHP\'s INSTALL_ROOT)', |
), |
'ignore-errors' => array( |
'doc' => 'force install even if there were errors', |
), |
'alldeps' => array( |
'shortopt' => 'a', |
'doc' => 'install all required and optional dependencies', |
), |
'onlyreqdeps' => array( |
'shortopt' => 'o', |
'doc' => 'install all required dependencies', |
), |
'offline' => array( |
'shortopt' => 'O', |
'doc' => 'do not attempt to download any urls or contact channels', |
), |
'pretend' => array( |
'shortopt' => 'p', |
'doc' => 'Only list the packages that would be downloaded', |
), |
), |
'doc' => '<package> ... |
Upgrades one or more PEAR packages. See documentation for the |
"install" command for ways to specify a package. |
When upgrading, your package will be updated if the provided new |
package has a higher version number (use the -f option if you need to |
upgrade anyway). |
More than one package may be specified at once. |
'), |
'upgrade-all' => array( |
'summary' => 'Upgrade All Packages [Deprecated in favor of calling upgrade with no parameters]', |
'function' => 'doUpgradeAll', |
'shortcut' => 'ua', |
'options' => array( |
'channel' => array( |
'shortopt' => 'c', |
'doc' => 'upgrade packages from a specific channel', |
'arg' => 'CHAN', |
), |
'nodeps' => array( |
'shortopt' => 'n', |
'doc' => 'ignore dependencies, upgrade anyway', |
), |
'register-only' => array( |
'shortopt' => 'r', |
'doc' => 'do not install files, only register the package as upgraded', |
), |
'nobuild' => array( |
'shortopt' => 'B', |
'doc' => 'don\'t build C extensions', |
), |
'nocompress' => array( |
'shortopt' => 'Z', |
'doc' => 'request uncompressed files when downloading', |
), |
'installroot' => array( |
'shortopt' => 'R', |
'arg' => 'DIR', |
'doc' => 'root directory used when installing files (ala PHP\'s INSTALL_ROOT), use packagingroot for RPM', |
), |
'ignore-errors' => array( |
'doc' => 'force install even if there were errors', |
), |
'loose' => array( |
'doc' => 'do not check for recommended dependency version', |
), |
), |
'doc' => ' |
WARNING: This function is deprecated in favor of using the upgrade command with no params |
Upgrades all packages that have a newer release available. Upgrades are |
done only if there is a release available of the state specified in |
"preferred_state" (currently {config preferred_state}), or a state considered |
more stable. |
'), |
'uninstall' => array( |
'summary' => 'Un-install Package', |
'function' => 'doUninstall', |
'shortcut' => 'un', |
'options' => array( |
'nodeps' => array( |
'shortopt' => 'n', |
'doc' => 'ignore dependencies, uninstall anyway', |
), |
'register-only' => array( |
'shortopt' => 'r', |
'doc' => 'do not remove files, only register the packages as not installed', |
), |
'installroot' => array( |
'shortopt' => 'R', |
'arg' => 'DIR', |
'doc' => 'root directory used when installing files (ala PHP\'s INSTALL_ROOT)', |
), |
'ignore-errors' => array( |
'doc' => 'force install even if there were errors', |
), |
'offline' => array( |
'shortopt' => 'O', |
'doc' => 'do not attempt to uninstall remotely', |
), |
), |
'doc' => '[channel/]<package> ... |
Uninstalls one or more PEAR packages. More than one package may be |
specified at once. Prefix with channel name to uninstall from a |
channel not in your default channel ({config default_channel}) |
'), |
'bundle' => array( |
'summary' => 'Unpacks a Pecl Package', |
'function' => 'doBundle', |
'shortcut' => 'bun', |
'options' => array( |
'destination' => array( |
'shortopt' => 'd', |
'arg' => 'DIR', |
'doc' => 'Optional destination directory for unpacking (defaults to current path or "ext" if exists)', |
), |
'force' => array( |
'shortopt' => 'f', |
'doc' => 'Force the unpacking even if there were errors in the package', |
), |
), |
'doc' => '<package> |
Unpacks a Pecl Package into the selected location. It will download the |
package if needed. |
'), |
'run-scripts' => array( |
'summary' => 'Run Post-Install Scripts bundled with a package', |
'function' => 'doRunScripts', |
'shortcut' => 'rs', |
'options' => array( |
), |
'doc' => '<package> |
Run post-installation scripts in package <package>, if any exist. |
'), |
); |
// }}} |
// {{{ constructor |
/** |
* PEAR_Command_Install constructor. |
* |
* @access public |
*/ |
function __construct(&$ui, &$config) |
{ |
parent::__construct($ui, $config); |
} |
// }}} |
/** |
* For unit testing purposes |
*/ |
function &getDownloader(&$ui, $options, &$config) |
{ |
if (!class_exists('PEAR_Downloader')) { |
require_once 'PEAR/Downloader.php'; |
} |
$a = new PEAR_Downloader($ui, $options, $config); |
return $a; |
} |
/** |
* For unit testing purposes |
*/ |
function &getInstaller(&$ui) |
{ |
if (!class_exists('PEAR_Installer')) { |
require_once 'PEAR/Installer.php'; |
} |
$a = new PEAR_Installer($ui); |
return $a; |
} |
function enableExtension($binaries, $type) |
{ |
if (!($phpini = $this->config->get('php_ini', null, 'pear.php.net'))) { |
return PEAR::raiseError('configuration option "php_ini" is not set to php.ini location'); |
} |
$ini = $this->_parseIni($phpini); |
if (PEAR::isError($ini)) { |
return $ini; |
} |
$line = 0; |
if ($type == 'extsrc' || $type == 'extbin') { |
$search = 'extensions'; |
$enable = 'extension'; |
} else { |
$search = 'zend_extensions'; |
ob_start(); |
phpinfo(INFO_GENERAL); |
$info = ob_get_contents(); |
ob_end_clean(); |
$debug = function_exists('leak') ? '_debug' : ''; |
$ts = preg_match('/Thread Safety.+enabled/', $info) ? '_ts' : ''; |
$enable = 'zend_extension' . $debug . $ts; |
} |
foreach ($ini[$search] as $line => $extension) { |
if (in_array($extension, $binaries, true) || in_array( |
$ini['extension_dir'] . DIRECTORY_SEPARATOR . $extension, $binaries, true)) { |
// already enabled - assume if one is, all are |
return true; |
} |
} |
if ($line) { |
$newini = array_slice($ini['all'], 0, $line); |
} else { |
$newini = array(); |
} |
foreach ($binaries as $binary) { |
if ($ini['extension_dir']) { |
$binary = basename($binary); |
} |
$newini[] = $enable . '="' . $binary . '"' . (OS_UNIX ? "\n" : "\r\n"); |
} |
$newini = array_merge($newini, array_slice($ini['all'], $line)); |
$fp = @fopen($phpini, 'wb'); |
if (!$fp) { |
return PEAR::raiseError('cannot open php.ini "' . $phpini . '" for writing'); |
} |
foreach ($newini as $line) { |
fwrite($fp, $line); |
} |
fclose($fp); |
return true; |
} |
function disableExtension($binaries, $type) |
{ |
if (!($phpini = $this->config->get('php_ini', null, 'pear.php.net'))) { |
return PEAR::raiseError('configuration option "php_ini" is not set to php.ini location'); |
} |
$ini = $this->_parseIni($phpini); |
if (PEAR::isError($ini)) { |
return $ini; |
} |
$line = 0; |
if ($type == 'extsrc' || $type == 'extbin') { |
$search = 'extensions'; |
$enable = 'extension'; |
} else { |
$search = 'zend_extensions'; |
ob_start(); |
phpinfo(INFO_GENERAL); |
$info = ob_get_contents(); |
ob_end_clean(); |
$debug = function_exists('leak') ? '_debug' : ''; |
$ts = preg_match('/Thread Safety.+enabled/', $info) ? '_ts' : ''; |
$enable = 'zend_extension' . $debug . $ts; |
} |
$found = false; |
foreach ($ini[$search] as $line => $extension) { |
if (in_array($extension, $binaries, true) || in_array( |
$ini['extension_dir'] . DIRECTORY_SEPARATOR . $extension, $binaries, true)) { |
$found = true; |
break; |
} |
} |
if (!$found) { |
// not enabled |
return true; |
} |
$fp = @fopen($phpini, 'wb'); |
if (!$fp) { |
return PEAR::raiseError('cannot open php.ini "' . $phpini . '" for writing'); |
} |
if ($line) { |
$newini = array_slice($ini['all'], 0, $line); |
// delete the enable line |
$newini = array_merge($newini, array_slice($ini['all'], $line + 1)); |
} else { |
$newini = array_slice($ini['all'], 1); |
} |
foreach ($newini as $line) { |
fwrite($fp, $line); |
} |
fclose($fp); |
return true; |
} |
function _parseIni($filename) |
{ |
if (!file_exists($filename)) { |
return PEAR::raiseError('php.ini "' . $filename . '" does not exist'); |
} |
if (filesize($filename) > 300000) { |
return PEAR::raiseError('php.ini "' . $filename . '" is too large, aborting'); |
} |
ob_start(); |
phpinfo(INFO_GENERAL); |
$info = ob_get_contents(); |
ob_end_clean(); |
$debug = function_exists('leak') ? '_debug' : ''; |
$ts = preg_match('/Thread Safety.+enabled/', $info) ? '_ts' : ''; |
$zend_extension_line = 'zend_extension' . $debug . $ts; |
$all = @file($filename); |
if ($all === false) { |
return PEAR::raiseError('php.ini "' . $filename .'" could not be read'); |
} |
$zend_extensions = $extensions = array(); |
// assume this is right, but pull from the php.ini if it is found |
$extension_dir = ini_get('extension_dir'); |
foreach ($all as $linenum => $line) { |
$line = trim($line); |
if (!$line) { |
continue; |
} |
if ($line[0] == ';') { |
continue; |
} |
if (strtolower(substr($line, 0, 13)) == 'extension_dir') { |
$line = trim(substr($line, 13)); |
if ($line[0] == '=') { |
$x = trim(substr($line, 1)); |
$x = explode(';', $x); |
$extension_dir = str_replace('"', '', array_shift($x)); |
continue; |
} |
} |
if (strtolower(substr($line, 0, 9)) == 'extension') { |
$line = trim(substr($line, 9)); |
if ($line[0] == '=') { |
$x = trim(substr($line, 1)); |
$x = explode(';', $x); |
$extensions[$linenum] = str_replace('"', '', array_shift($x)); |
continue; |
} |
} |
if (strtolower(substr($line, 0, strlen($zend_extension_line))) == |
$zend_extension_line) { |
$line = trim(substr($line, strlen($zend_extension_line))); |
if ($line[0] == '=') { |
$x = trim(substr($line, 1)); |
$x = explode(';', $x); |
$zend_extensions[$linenum] = str_replace('"', '', array_shift($x)); |
continue; |
} |
} |
} |
return array( |
'extensions' => $extensions, |
'zend_extensions' => $zend_extensions, |
'extension_dir' => $extension_dir, |
'all' => $all, |
); |
} |
// {{{ doInstall() |
function doInstall($command, $options, $params) |
{ |
if (!class_exists('PEAR_PackageFile')) { |
require_once 'PEAR/PackageFile.php'; |
} |
if (isset($options['installroot']) && isset($options['packagingroot'])) { |
return $this->raiseError('ERROR: cannot use both --installroot and --packagingroot'); |
} |
$reg = &$this->config->getRegistry(); |
$channel = isset($options['channel']) ? $options['channel'] : $this->config->get('default_channel'); |
if (!$reg->channelExists($channel)) { |
return $this->raiseError('Channel "' . $channel . '" does not exist'); |
} |
if (empty($this->installer)) { |
$this->installer = &$this->getInstaller($this->ui); |
} |
if ($command == 'upgrade' || $command == 'upgrade-all') { |
// If people run the upgrade command but pass nothing, emulate a upgrade-all |
if ($command == 'upgrade' && empty($params)) { |
return $this->doUpgradeAll($command, $options, $params); |
} |
$options['upgrade'] = true; |
} else { |
$packages = $params; |
} |
$instreg = &$reg; // instreg used to check if package is installed |
if (isset($options['packagingroot']) && !isset($options['upgrade'])) { |
$packrootphp_dir = $this->installer->_prependPath( |
$this->config->get('php_dir', null, 'pear.php.net'), |
$options['packagingroot']); |
$metadata_dir = $this->config->get('metadata_dir', null, 'pear.php.net'); |
if ($metadata_dir) { |
$metadata_dir = $this->installer->_prependPath( |
$metadata_dir, |
$options['packagingroot']); |
} |
$instreg = new PEAR_Registry($packrootphp_dir, false, false, $metadata_dir); // other instreg! |
if ($this->config->get('verbose') > 2) { |
$this->ui->outputData('using package root: ' . $options['packagingroot']); |
} |
} |
$abstractpackages = $otherpackages = array(); |
// parse params |
PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN); |
foreach ($params as $param) { |
if (strpos($param, 'http://') === 0) { |
$otherpackages[] = $param; |
continue; |
} |
if (strpos($param, 'channel://') === false && @file_exists($param)) { |
if (isset($options['force'])) { |
$otherpackages[] = $param; |
continue; |
} |
$pkg = new PEAR_PackageFile($this->config); |
$pf = $pkg->fromAnyFile($param, PEAR_VALIDATE_DOWNLOADING); |
if (PEAR::isError($pf)) { |
$otherpackages[] = $param; |
continue; |
} |
$exists = $reg->packageExists($pf->getPackage(), $pf->getChannel()); |
$pversion = $reg->packageInfo($pf->getPackage(), 'version', $pf->getChannel()); |
$version_compare = version_compare($pf->getVersion(), $pversion, '<='); |
if ($exists && $version_compare) { |
if ($this->config->get('verbose')) { |
$this->ui->outputData('Ignoring installed package ' . |
$reg->parsedPackageNameToString( |
array('package' => $pf->getPackage(), |
'channel' => $pf->getChannel()), true)); |
} |
continue; |
} |
$otherpackages[] = $param; |
continue; |
} |
$e = $reg->parsePackageName($param, $channel); |
if (PEAR::isError($e)) { |
$otherpackages[] = $param; |
} else { |
$abstractpackages[] = $e; |
} |
} |
PEAR::staticPopErrorHandling(); |
// if there are any local package .tgz or remote static url, we can't |
// filter. The filter only works for abstract packages |
if (count($abstractpackages) && !isset($options['force'])) { |
// when not being forced, only do necessary upgrades/installs |
if (isset($options['upgrade'])) { |
$abstractpackages = $this->_filterUptodatePackages($abstractpackages, $command); |
} else { |
$count = count($abstractpackages); |
foreach ($abstractpackages as $i => $package) { |
if (isset($package['group'])) { |
// do not filter out install groups |
continue; |
} |
if ($instreg->packageExists($package['package'], $package['channel'])) { |
if ($count > 1) { |
if ($this->config->get('verbose')) { |
$this->ui->outputData('Ignoring installed package ' . |
$reg->parsedPackageNameToString($package, true)); |
} |
unset($abstractpackages[$i]); |
} elseif ($count === 1) { |
// Lets try to upgrade it since it's already installed |
$options['upgrade'] = true; |
} |
} |
} |
} |
$abstractpackages = |
array_map(array($reg, 'parsedPackageNameToString'), $abstractpackages); |
} elseif (count($abstractpackages)) { |
$abstractpackages = |
array_map(array($reg, 'parsedPackageNameToString'), $abstractpackages); |
} |
$packages = array_merge($abstractpackages, $otherpackages); |
if (!count($packages)) { |
$c = ''; |
if (isset($options['channel'])){ |
$c .= ' in channel "' . $options['channel'] . '"'; |
} |
$this->ui->outputData('Nothing to ' . $command . $c); |
return true; |
} |
$this->downloader = &$this->getDownloader($this->ui, $options, $this->config); |
$errors = $downloaded = $binaries = array(); |
$downloaded = &$this->downloader->download($packages); |
if (PEAR::isError($downloaded)) { |
return $this->raiseError($downloaded); |
} |
$errors = $this->downloader->getErrorMsgs(); |
if (count($errors)) { |
$err = array(); |
$err['data'] = array(); |
foreach ($errors as $error) { |
if ($error !== null) { |
$err['data'][] = array($error); |
} |
} |
if (!empty($err['data'])) { |
$err['headline'] = 'Install Errors'; |
$this->ui->outputData($err); |
} |
if (!count($downloaded)) { |
return $this->raiseError("$command failed"); |
} |
} |
$data = array( |
'headline' => 'Packages that would be Installed' |
); |
if (isset($options['pretend'])) { |
foreach ($downloaded as $package) { |
$data['data'][] = array($reg->parsedPackageNameToString($package->getParsedPackage())); |
} |
$this->ui->outputData($data, 'pretend'); |
return true; |
} |
$this->installer->setOptions($options); |
$this->installer->sortPackagesForInstall($downloaded); |
if (PEAR::isError($err = $this->installer->setDownloadedPackages($downloaded))) { |
$this->raiseError($err->getMessage()); |
return true; |
} |
$binaries = $extrainfo = array(); |
foreach ($downloaded as $param) { |
PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN); |
$info = $this->installer->install($param, $options); |
PEAR::staticPopErrorHandling(); |
if (PEAR::isError($info)) { |
$oldinfo = $info; |
$pkg = &$param->getPackageFile(); |
if ($info->getCode() != PEAR_INSTALLER_NOBINARY) { |
if (!($info = $pkg->installBinary($this->installer))) { |
$this->ui->outputData('ERROR: ' .$oldinfo->getMessage()); |
continue; |
} |
// we just installed a different package than requested, |
// let's change the param and info so that the rest of this works |
$param = $info[0]; |
$info = $info[1]; |
} |
} |
if (!is_array($info)) { |
return $this->raiseError("$command failed"); |
} |
if ($param->getPackageType() == 'extsrc' || |
$param->getPackageType() == 'extbin' || |
$param->getPackageType() == 'zendextsrc' || |
$param->getPackageType() == 'zendextbin' |
) { |
$pkg = &$param->getPackageFile(); |
if ($instbin = $pkg->getInstalledBinary()) { |
$instpkg = &$instreg->getPackage($instbin, $pkg->getChannel()); |
} else { |
$instpkg = &$instreg->getPackage($pkg->getPackage(), $pkg->getChannel()); |
} |
foreach ($instpkg->getFilelist() as $name => $atts) { |
$pinfo = pathinfo($atts['installed_as']); |
if (!isset($pinfo['extension']) || |
in_array($pinfo['extension'], array('c', 'h')) |
) { |
continue; // make sure we don't match php_blah.h |
} |
if ((strpos($pinfo['basename'], 'php_') === 0 && |
$pinfo['extension'] == 'dll') || |
// most unices |
$pinfo['extension'] == 'so' || |
// hp-ux |
$pinfo['extension'] == 'sl') { |
$binaries[] = array($atts['installed_as'], $pinfo); |
break; |
} |
} |
if (count($binaries)) { |
foreach ($binaries as $pinfo) { |
PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN); |
$ret = $this->enableExtension(array($pinfo[0]), $param->getPackageType()); |
PEAR::staticPopErrorHandling(); |
if (PEAR::isError($ret)) { |
$extrainfo[] = $ret->getMessage(); |
if ($param->getPackageType() == 'extsrc' || |
$param->getPackageType() == 'extbin') { |
$exttype = 'extension'; |
$extpath = $pinfo[1]['basename']; |
} else { |
$exttype = 'zend_extension'; |
$extpath = $atts['installed_as']; |
} |
$extrainfo[] = 'You should add "' . $exttype . '=' . |
$extpath . '" to php.ini'; |
} else { |
$extrainfo[] = 'Extension ' . $instpkg->getProvidesExtension() . |
' enabled in php.ini'; |
} |
} |
} |
} |
if ($this->config->get('verbose') > 0) { |
$chan = $param->getChannel(); |
$label = $reg->parsedPackageNameToString( |
array( |
'channel' => $chan, |
'package' => $param->getPackage(), |
'version' => $param->getVersion(), |
)); |
$out = array('data' => "$command ok: $label"); |
if (isset($info['release_warnings'])) { |
$out['release_warnings'] = $info['release_warnings']; |
} |
$this->ui->outputData($out, $command); |
if (!isset($options['register-only']) && !isset($options['offline'])) { |
if ($this->config->isDefinedLayer('ftp')) { |
PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN); |
$info = $this->installer->ftpInstall($param); |
PEAR::staticPopErrorHandling(); |
if (PEAR::isError($info)) { |
$this->ui->outputData($info->getMessage()); |
$this->ui->outputData("remote install failed: $label"); |
} else { |
$this->ui->outputData("remote install ok: $label"); |
} |
} |
} |
} |
$deps = $param->getDeps(); |
if ($deps) { |
if (isset($deps['group'])) { |
$groups = $deps['group']; |
if (!isset($groups[0])) { |
$groups = array($groups); |
} |
foreach ($groups as $group) { |
if ($group['attribs']['name'] == 'default') { |
// default group is always installed, unless the user |
// explicitly chooses to install another group |
continue; |
} |
$extrainfo[] = $param->getPackage() . ': Optional feature ' . |
$group['attribs']['name'] . ' available (' . |
$group['attribs']['hint'] . ')'; |
} |
$extrainfo[] = $param->getPackage() . |
': To install optional features use "pear install ' . |
$reg->parsedPackageNameToString( |
array('package' => $param->getPackage(), |
'channel' => $param->getChannel()), true) . |
'#featurename"'; |
} |
} |
$pkg = &$instreg->getPackage($param->getPackage(), $param->getChannel()); |
// $pkg may be NULL if install is a 'fake' install via --packagingroot |
if (is_object($pkg)) { |
$pkg->setConfig($this->config); |
if ($list = $pkg->listPostinstallScripts()) { |
$pn = $reg->parsedPackageNameToString(array('channel' => |
$param->getChannel(), 'package' => $param->getPackage()), true); |
$extrainfo[] = $pn . ' has post-install scripts:'; |
foreach ($list as $file) { |
$extrainfo[] = $file; |
} |
$extrainfo[] = $param->getPackage() . |
': Use "pear run-scripts ' . $pn . '" to finish setup.'; |
$extrainfo[] = 'DO NOT RUN SCRIPTS FROM UNTRUSTED SOURCES'; |
} |
} |
} |
if (count($extrainfo)) { |
foreach ($extrainfo as $info) { |
$this->ui->outputData($info); |
} |
} |
return true; |
} |
// }}} |
// {{{ doUpgradeAll() |
function doUpgradeAll($command, $options, $params) |
{ |
$reg = &$this->config->getRegistry(); |
$upgrade = array(); |
if (isset($options['channel'])) { |
$channels = array($options['channel']); |
} else { |
$channels = $reg->listChannels(); |
} |
foreach ($channels as $channel) { |
if ($channel == '__uri') { |
continue; |
} |
// parse name with channel |
foreach ($reg->listPackages($channel) as $name) { |
$upgrade[] = $reg->parsedPackageNameToString(array( |
'channel' => $channel, |
'package' => $name |
)); |
} |
} |
$err = $this->doInstall($command, $options, $upgrade); |
if (PEAR::isError($err)) { |
$this->ui->outputData($err->getMessage(), $command); |
} |
} |
// }}} |
// {{{ doUninstall() |
function doUninstall($command, $options, $params) |
{ |
if (count($params) < 1) { |
return $this->raiseError("Please supply the package(s) you want to uninstall"); |
} |
if (empty($this->installer)) { |
$this->installer = &$this->getInstaller($this->ui); |
} |
if (isset($options['remoteconfig'])) { |
$e = $this->config->readFTPConfigFile($options['remoteconfig']); |
if (!PEAR::isError($e)) { |
$this->installer->setConfig($this->config); |
} |
} |
$reg = &$this->config->getRegistry(); |
$newparams = array(); |
$binaries = array(); |
$badparams = array(); |
foreach ($params as $pkg) { |
$channel = $this->config->get('default_channel'); |
PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN); |
$parsed = $reg->parsePackageName($pkg, $channel); |
PEAR::staticPopErrorHandling(); |
if (!$parsed || PEAR::isError($parsed)) { |
$badparams[] = $pkg; |
continue; |
} |
$package = $parsed['package']; |
$channel = $parsed['channel']; |
$info = &$reg->getPackage($package, $channel); |
if ($info === null && |
($channel == 'pear.php.net' || $channel == 'pecl.php.net')) { |
// make sure this isn't a package that has flipped from pear to pecl but |
// used a package.xml 1.0 |
$testc = ($channel == 'pear.php.net') ? 'pecl.php.net' : 'pear.php.net'; |
$info = &$reg->getPackage($package, $testc); |
if ($info !== null) { |
$channel = $testc; |
} |
} |
if ($info === null) { |
$badparams[] = $pkg; |
} else { |
$newparams[] = &$info; |
// check for binary packages (this is an alias for those packages if so) |
if ($installedbinary = $info->getInstalledBinary()) { |
$this->ui->log('adding binary package ' . |
$reg->parsedPackageNameToString(array('channel' => $channel, |
'package' => $installedbinary), true)); |
$newparams[] = &$reg->getPackage($installedbinary, $channel); |
} |
// add the contents of a dependency group to the list of installed packages |
if (isset($parsed['group'])) { |
$group = $info->getDependencyGroup($parsed['group']); |
if ($group) { |
$installed = $reg->getInstalledGroup($group); |
if ($installed) { |
foreach ($installed as $i => $p) { |
$newparams[] = &$installed[$i]; |
} |
} |
} |
} |
} |
} |
$err = $this->installer->sortPackagesForUninstall($newparams); |
if (PEAR::isError($err)) { |
$this->ui->outputData($err->getMessage(), $command); |
return true; |
} |
$params = $newparams; |
// twist this to use it to check on whether dependent packages are also being uninstalled |
// for circular dependencies like subpackages |
$this->installer->setUninstallPackages($newparams); |
$params = array_merge($params, $badparams); |
$binaries = array(); |
foreach ($params as $pkg) { |
$this->installer->pushErrorHandling(PEAR_ERROR_RETURN); |
if ($err = $this->installer->uninstall($pkg, $options)) { |
$this->installer->popErrorHandling(); |
if (PEAR::isError($err)) { |
$this->ui->outputData($err->getMessage(), $command); |
continue; |
} |
if ($pkg->getPackageType() == 'extsrc' || |
$pkg->getPackageType() == 'extbin' || |
$pkg->getPackageType() == 'zendextsrc' || |
$pkg->getPackageType() == 'zendextbin') { |
if ($instbin = $pkg->getInstalledBinary()) { |
continue; // this will be uninstalled later |
} |
foreach ($pkg->getFilelist() as $name => $atts) { |
$pinfo = pathinfo($atts['installed_as']); |
if (!isset($pinfo['extension']) || |
in_array($pinfo['extension'], array('c', 'h'))) { |
continue; // make sure we don't match php_blah.h |
} |
if ((strpos($pinfo['basename'], 'php_') === 0 && |
$pinfo['extension'] == 'dll') || |
// most unices |
$pinfo['extension'] == 'so' || |
// hp-ux |
$pinfo['extension'] == 'sl') { |
$binaries[] = array($atts['installed_as'], $pinfo); |
break; |
} |
} |
if (count($binaries)) { |
foreach ($binaries as $pinfo) { |
PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN); |
$ret = $this->disableExtension(array($pinfo[0]), $pkg->getPackageType()); |
PEAR::staticPopErrorHandling(); |
if (PEAR::isError($ret)) { |
$extrainfo[] = $ret->getMessage(); |
if ($pkg->getPackageType() == 'extsrc' || |
$pkg->getPackageType() == 'extbin') { |
$exttype = 'extension'; |
} else { |
ob_start(); |
phpinfo(INFO_GENERAL); |
$info = ob_get_contents(); |
ob_end_clean(); |
$debug = function_exists('leak') ? '_debug' : ''; |
$ts = preg_match('/Thread Safety.+enabled/', $info) ? '_ts' : ''; |
$exttype = 'zend_extension' . $debug . $ts; |
} |
$this->ui->outputData('Unable to remove "' . $exttype . '=' . |
$pinfo[1]['basename'] . '" from php.ini', $command); |
} else { |
$this->ui->outputData('Extension ' . $pkg->getProvidesExtension() . |
' disabled in php.ini', $command); |
} |
} |
} |
} |
$savepkg = $pkg; |
if ($this->config->get('verbose') > 0) { |
if (is_object($pkg)) { |
$pkg = $reg->parsedPackageNameToString($pkg); |
} |
$this->ui->outputData("uninstall ok: $pkg", $command); |
} |
if (!isset($options['offline']) && is_object($savepkg) && |
defined('PEAR_REMOTEINSTALL_OK')) { |
if ($this->config->isDefinedLayer('ftp')) { |
$this->installer->pushErrorHandling(PEAR_ERROR_RETURN); |
$info = $this->installer->ftpUninstall($savepkg); |
$this->installer->popErrorHandling(); |
if (PEAR::isError($info)) { |
$this->ui->outputData($info->getMessage()); |
$this->ui->outputData("remote uninstall failed: $pkg"); |
} else { |
$this->ui->outputData("remote uninstall ok: $pkg"); |
} |
} |
} |
} else { |
$this->installer->popErrorHandling(); |
if (!is_object($pkg)) { |
return $this->raiseError("uninstall failed: $pkg"); |
} |
$pkg = $reg->parsedPackageNameToString($pkg); |
} |
} |
return true; |
} |
// }}} |
// }}} |
// {{{ doBundle() |
/* |
(cox) It just downloads and untars the package, does not do |
any check that the PEAR_Installer::_installFile() does. |
*/ |
function doBundle($command, $options, $params) |
{ |
$opts = array( |
'force' => true, |
'nodeps' => true, |
'soft' => true, |
'downloadonly' => true |
); |
$downloader = &$this->getDownloader($this->ui, $opts, $this->config); |
$reg = &$this->config->getRegistry(); |
if (count($params) < 1) { |
return $this->raiseError("Please supply the package you want to bundle"); |
} |
if (isset($options['destination'])) { |
if (!is_dir($options['destination'])) { |
System::mkdir('-p ' . $options['destination']); |
} |
$dest = realpath($options['destination']); |
} else { |
$pwd = getcwd(); |
$dir = $pwd . DIRECTORY_SEPARATOR . 'ext'; |
$dest = is_dir($dir) ? $dir : $pwd; |
} |
PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN); |
$err = $downloader->setDownloadDir($dest); |
PEAR::staticPopErrorHandling(); |
if (PEAR::isError($err)) { |
return PEAR::raiseError('download directory "' . $dest . |
'" is not writeable.'); |
} |
$result = &$downloader->download(array($params[0])); |
if (PEAR::isError($result)) { |
return $result; |
} |
if (!isset($result[0])) { |
return $this->raiseError('unable to unpack ' . $params[0]); |
} |
$pkgfile = &$result[0]->getPackageFile(); |
$pkgname = $pkgfile->getName(); |
$pkgversion = $pkgfile->getVersion(); |
// Unpacking ------------------------------------------------- |
$dest .= DIRECTORY_SEPARATOR . $pkgname; |
$orig = $pkgname . '-' . $pkgversion; |
$tar = new Archive_Tar($pkgfile->getArchiveFile()); |
if (!$tar->extractModify($dest, $orig)) { |
return $this->raiseError('unable to unpack ' . $pkgfile->getArchiveFile()); |
} |
$this->ui->outputData("Package ready at '$dest'"); |
// }}} |
} |
// }}} |
function doRunScripts($command, $options, $params) |
{ |
if (!isset($params[0])) { |
return $this->raiseError('run-scripts expects 1 parameter: a package name'); |
} |
$reg = &$this->config->getRegistry(); |
PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN); |
$parsed = $reg->parsePackageName($params[0], $this->config->get('default_channel')); |
PEAR::staticPopErrorHandling(); |
if (PEAR::isError($parsed)) { |
return $this->raiseError($parsed); |
} |
$package = &$reg->getPackage($parsed['package'], $parsed['channel']); |
if (!is_object($package)) { |
return $this->raiseError('Could not retrieve package "' . $params[0] . '" from registry'); |
} |
$package->setConfig($this->config); |
$package->runPostinstallScripts(); |
$this->ui->outputData('Install scripts complete', $command); |
return true; |
} |
/** |
* Given a list of packages, filter out those ones that are already up to date |
* |
* @param $packages: packages, in parsed array format ! |
* @return list of packages that can be upgraded |
*/ |
function _filterUptodatePackages($packages, $command) |
{ |
$reg = &$this->config->getRegistry(); |
$latestReleases = array(); |
$ret = array(); |
foreach ($packages as $package) { |
if (isset($package['group'])) { |
$ret[] = $package; |
continue; |
} |
$channel = $package['channel']; |
$name = $package['package']; |
if (!$reg->packageExists($name, $channel)) { |
$ret[] = $package; |
continue; |
} |
if (!isset($latestReleases[$channel])) { |
// fill in cache for this channel |
$chan = $reg->getChannel($channel); |
if (PEAR::isError($chan)) { |
return $this->raiseError($chan); |
} |
$base2 = false; |
$preferred_mirror = $this->config->get('preferred_mirror', null, $channel); |
if ($chan->supportsREST($preferred_mirror) && |
( |
//($base2 = $chan->getBaseURL('REST1.4', $preferred_mirror)) || |
($base = $chan->getBaseURL('REST1.0', $preferred_mirror)) |
) |
) { |
$dorest = true; |
} |
PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN); |
if (!isset($package['state'])) { |
$state = $this->config->get('preferred_state', null, $channel); |
} else { |
$state = $package['state']; |
} |
if ($dorest) { |
if ($base2) { |
$rest = &$this->config->getREST('1.4', array()); |
$base = $base2; |
} else { |
$rest = &$this->config->getREST('1.0', array()); |
} |
$installed = array_flip($reg->listPackages($channel)); |
$latest = $rest->listLatestUpgrades($base, $state, $installed, $channel, $reg); |
} |
PEAR::staticPopErrorHandling(); |
if (PEAR::isError($latest)) { |
$this->ui->outputData('Error getting channel info from ' . $channel . |
': ' . $latest->getMessage()); |
continue; |
} |
$latestReleases[$channel] = array_change_key_case($latest); |
} |
// check package for latest release |
$name_lower = strtolower($name); |
if (isset($latestReleases[$channel][$name_lower])) { |
// if not set, up to date |
$inst_version = $reg->packageInfo($name, 'version', $channel); |
$channel_version = $latestReleases[$channel][$name_lower]['version']; |
if (version_compare($channel_version, $inst_version, 'le')) { |
// installed version is up-to-date |
continue; |
} |
// maintain BC |
if ($command == 'upgrade-all') { |
$this->ui->outputData(array('data' => 'Will upgrade ' . |
$reg->parsedPackageNameToString($package)), $command); |
} |
$ret[] = $package; |
} |
} |
return $ret; |
} |
} |
/branches/v1.3-critias/bibliotheque/pear/PEAR/Command/Pickle.php |
---|
New file |
0,0 → 1,420 |
<?php |
/** |
* PEAR_Command_Pickle (pickle command) |
* |
* PHP versions 4 and 5 |
* |
* @category pear |
* @package PEAR |
* @author Greg Beaver <cellog@php.net> |
* @copyright 2005-2009 The Authors |
* @license http://opensource.org/licenses/bsd-license.php New BSD License |
* @link http://pear.php.net/package/PEAR |
* @since File available since Release 1.4.1 |
*/ |
/** |
* base class |
*/ |
require_once 'PEAR/Command/Common.php'; |
/** |
* PEAR commands for login/logout |
* |
* @category pear |
* @package PEAR |
* @author Greg Beaver <cellog@php.net> |
* @copyright 2005-2009 The Authors |
* @license http://opensource.org/licenses/bsd-license.php New BSD License |
* @version Release: 1.10.1 |
* @link http://pear.php.net/package/PEAR |
* @since Class available since Release 1.4.1 |
*/ |
class PEAR_Command_Pickle extends PEAR_Command_Common |
{ |
var $commands = array( |
'pickle' => array( |
'summary' => 'Build PECL Package', |
'function' => 'doPackage', |
'shortcut' => 'pi', |
'options' => array( |
'nocompress' => array( |
'shortopt' => 'Z', |
'doc' => 'Do not gzip the package file' |
), |
'showname' => array( |
'shortopt' => 'n', |
'doc' => 'Print the name of the packaged file.', |
), |
), |
'doc' => '[descfile] |
Creates a PECL package from its package2.xml file. |
An automatic conversion will be made to a package.xml 1.0 and written out to |
disk in the current directory as "package.xml". Note that |
only simple package.xml 2.0 will be converted. package.xml 2.0 with: |
- dependency types other than required/optional PECL package/ext/php/pearinstaller |
- more than one extsrcrelease or zendextsrcrelease |
- zendextbinrelease, extbinrelease, phprelease, or bundle release type |
- dependency groups |
- ignore tags in release filelist |
- tasks other than replace |
- custom roles |
will cause pickle to fail, and output an error message. If your package2.xml |
uses any of these features, you are best off using PEAR_PackageFileManager to |
generate both package.xml. |
' |
), |
); |
/** |
* PEAR_Command_Package constructor. |
* |
* @access public |
*/ |
function __construct(&$ui, &$config) |
{ |
parent::__construct($ui, $config); |
} |
/** |
* For unit-testing ease |
* |
* @return PEAR_Packager |
*/ |
function &getPackager() |
{ |
if (!class_exists('PEAR_Packager')) { |
require_once 'PEAR/Packager.php'; |
} |
$a = new PEAR_Packager; |
return $a; |
} |
/** |
* For unit-testing ease |
* |
* @param PEAR_Config $config |
* @param bool $debug |
* @param string|null $tmpdir |
* @return PEAR_PackageFile |
*/ |
function &getPackageFile($config, $debug = false) |
{ |
if (!class_exists('PEAR_Common')) { |
require_once 'PEAR/Common.php'; |
} |
if (!class_exists('PEAR_PackageFile')) { |
require_once 'PEAR/PackageFile.php'; |
} |
$a = new PEAR_PackageFile($config, $debug); |
$common = new PEAR_Common; |
$common->ui = $this->ui; |
$a->setLogger($common); |
return $a; |
} |
function doPackage($command, $options, $params) |
{ |
$this->output = ''; |
$pkginfofile = isset($params[0]) ? $params[0] : 'package2.xml'; |
$packager = &$this->getPackager(); |
if (PEAR::isError($err = $this->_convertPackage($pkginfofile))) { |
return $err; |
} |
$compress = empty($options['nocompress']) ? true : false; |
$result = $packager->package($pkginfofile, $compress, 'package.xml'); |
if (PEAR::isError($result)) { |
return $this->raiseError($result); |
} |
// Don't want output, only the package file name just created |
if (isset($options['showname'])) { |
$this->ui->outputData($result, $command); |
} |
return true; |
} |
function _convertPackage($packagexml) |
{ |
$pkg = &$this->getPackageFile($this->config); |
$pf2 = &$pkg->fromPackageFile($packagexml, PEAR_VALIDATE_NORMAL); |
if (!is_a($pf2, 'PEAR_PackageFile_v2')) { |
return $this->raiseError('Cannot process "' . |
$packagexml . '", is not a package.xml 2.0'); |
} |
require_once 'PEAR/PackageFile/v1.php'; |
$pf = new PEAR_PackageFile_v1; |
$pf->setConfig($this->config); |
if ($pf2->getPackageType() != 'extsrc' && $pf2->getPackageType() != 'zendextsrc') { |
return $this->raiseError('Cannot safely convert "' . $packagexml . |
'", is not an extension source package. Using a PEAR_PackageFileManager-based ' . |
'script is an option'); |
} |
if (is_array($pf2->getUsesRole())) { |
return $this->raiseError('Cannot safely convert "' . $packagexml . |
'", contains custom roles. Using a PEAR_PackageFileManager-based script or ' . |
'the convert command is an option'); |
} |
if (is_array($pf2->getUsesTask())) { |
return $this->raiseError('Cannot safely convert "' . $packagexml . |
'", contains custom tasks. Using a PEAR_PackageFileManager-based script or ' . |
'the convert command is an option'); |
} |
$deps = $pf2->getDependencies(); |
if (isset($deps['group'])) { |
return $this->raiseError('Cannot safely convert "' . $packagexml . |
'", contains dependency groups. Using a PEAR_PackageFileManager-based script ' . |
'or the convert command is an option'); |
} |
if (isset($deps['required']['subpackage']) || |
isset($deps['optional']['subpackage'])) { |
return $this->raiseError('Cannot safely convert "' . $packagexml . |
'", contains subpackage dependencies. Using a PEAR_PackageFileManager-based '. |
'script is an option'); |
} |
if (isset($deps['required']['os'])) { |
return $this->raiseError('Cannot safely convert "' . $packagexml . |
'", contains os dependencies. Using a PEAR_PackageFileManager-based '. |
'script is an option'); |
} |
if (isset($deps['required']['arch'])) { |
return $this->raiseError('Cannot safely convert "' . $packagexml . |
'", contains arch dependencies. Using a PEAR_PackageFileManager-based '. |
'script is an option'); |
} |
$pf->setPackage($pf2->getPackage()); |
$pf->setSummary($pf2->getSummary()); |
$pf->setDescription($pf2->getDescription()); |
foreach ($pf2->getMaintainers() as $maintainer) { |
$pf->addMaintainer($maintainer['role'], $maintainer['handle'], |
$maintainer['name'], $maintainer['email']); |
} |
$pf->setVersion($pf2->getVersion()); |
$pf->setDate($pf2->getDate()); |
$pf->setLicense($pf2->getLicense()); |
$pf->setState($pf2->getState()); |
$pf->setNotes($pf2->getNotes()); |
$pf->addPhpDep($deps['required']['php']['min'], 'ge'); |
if (isset($deps['required']['php']['max'])) { |
$pf->addPhpDep($deps['required']['php']['max'], 'le'); |
} |
if (isset($deps['required']['package'])) { |
if (!isset($deps['required']['package'][0])) { |
$deps['required']['package'] = array($deps['required']['package']); |
} |
foreach ($deps['required']['package'] as $dep) { |
if (!isset($dep['channel'])) { |
return $this->raiseError('Cannot safely convert "' . $packagexml . '"' . |
' contains uri-based dependency on a package. Using a ' . |
'PEAR_PackageFileManager-based script is an option'); |
} |
if ($dep['channel'] != 'pear.php.net' |
&& $dep['channel'] != 'pecl.php.net' |
&& $dep['channel'] != 'doc.php.net') { |
return $this->raiseError('Cannot safely convert "' . $packagexml . '"' . |
' contains dependency on a non-standard channel package. Using a ' . |
'PEAR_PackageFileManager-based script is an option'); |
} |
if (isset($dep['conflicts'])) { |
return $this->raiseError('Cannot safely convert "' . $packagexml . '"' . |
' contains conflicts dependency. Using a ' . |
'PEAR_PackageFileManager-based script is an option'); |
} |
if (isset($dep['exclude'])) { |
$this->ui->outputData('WARNING: exclude tags are ignored in conversion'); |
} |
if (isset($dep['min'])) { |
$pf->addPackageDep($dep['name'], $dep['min'], 'ge'); |
} |
if (isset($dep['max'])) { |
$pf->addPackageDep($dep['name'], $dep['max'], 'le'); |
} |
} |
} |
if (isset($deps['required']['extension'])) { |
if (!isset($deps['required']['extension'][0])) { |
$deps['required']['extension'] = array($deps['required']['extension']); |
} |
foreach ($deps['required']['extension'] as $dep) { |
if (isset($dep['conflicts'])) { |
return $this->raiseError('Cannot safely convert "' . $packagexml . '"' . |
' contains conflicts dependency. Using a ' . |
'PEAR_PackageFileManager-based script is an option'); |
} |
if (isset($dep['exclude'])) { |
$this->ui->outputData('WARNING: exclude tags are ignored in conversion'); |
} |
if (isset($dep['min'])) { |
$pf->addExtensionDep($dep['name'], $dep['min'], 'ge'); |
} |
if (isset($dep['max'])) { |
$pf->addExtensionDep($dep['name'], $dep['max'], 'le'); |
} |
} |
} |
if (isset($deps['optional']['package'])) { |
if (!isset($deps['optional']['package'][0])) { |
$deps['optional']['package'] = array($deps['optional']['package']); |
} |
foreach ($deps['optional']['package'] as $dep) { |
if (!isset($dep['channel'])) { |
return $this->raiseError('Cannot safely convert "' . $packagexml . '"' . |
' contains uri-based dependency on a package. Using a ' . |
'PEAR_PackageFileManager-based script is an option'); |
} |
if ($dep['channel'] != 'pear.php.net' |
&& $dep['channel'] != 'pecl.php.net' |
&& $dep['channel'] != 'doc.php.net') { |
return $this->raiseError('Cannot safely convert "' . $packagexml . '"' . |
' contains dependency on a non-standard channel package. Using a ' . |
'PEAR_PackageFileManager-based script is an option'); |
} |
if (isset($dep['exclude'])) { |
$this->ui->outputData('WARNING: exclude tags are ignored in conversion'); |
} |
if (isset($dep['min'])) { |
$pf->addPackageDep($dep['name'], $dep['min'], 'ge', 'yes'); |
} |
if (isset($dep['max'])) { |
$pf->addPackageDep($dep['name'], $dep['max'], 'le', 'yes'); |
} |
} |
} |
if (isset($deps['optional']['extension'])) { |
if (!isset($deps['optional']['extension'][0])) { |
$deps['optional']['extension'] = array($deps['optional']['extension']); |
} |
foreach ($deps['optional']['extension'] as $dep) { |
if (isset($dep['exclude'])) { |
$this->ui->outputData('WARNING: exclude tags are ignored in conversion'); |
} |
if (isset($dep['min'])) { |
$pf->addExtensionDep($dep['name'], $dep['min'], 'ge', 'yes'); |
} |
if (isset($dep['max'])) { |
$pf->addExtensionDep($dep['name'], $dep['max'], 'le', 'yes'); |
} |
} |
} |
$contents = $pf2->getContents(); |
$release = $pf2->getReleases(); |
if (isset($releases[0])) { |
return $this->raiseError('Cannot safely process "' . $packagexml . '" contains ' |
. 'multiple extsrcrelease/zendextsrcrelease tags. Using a PEAR_PackageFileManager-based script ' . |
'or the convert command is an option'); |
} |
if ($configoptions = $pf2->getConfigureOptions()) { |
foreach ($configoptions as $option) { |
$default = isset($option['default']) ? $option['default'] : false; |
$pf->addConfigureOption($option['name'], $option['prompt'], $default); |
} |
} |
if (isset($release['filelist']['ignore'])) { |
return $this->raiseError('Cannot safely process "' . $packagexml . '" contains ' |
. 'ignore tags. Using a PEAR_PackageFileManager-based script or the convert' . |
' command is an option'); |
} |
if (isset($release['filelist']['install']) && |
!isset($release['filelist']['install'][0])) { |
$release['filelist']['install'] = array($release['filelist']['install']); |
} |
if (isset($contents['dir']['attribs']['baseinstalldir'])) { |
$baseinstalldir = $contents['dir']['attribs']['baseinstalldir']; |
} else { |
$baseinstalldir = false; |
} |
if (!isset($contents['dir']['file'][0])) { |
$contents['dir']['file'] = array($contents['dir']['file']); |
} |
foreach ($contents['dir']['file'] as $file) { |
if ($baseinstalldir && !isset($file['attribs']['baseinstalldir'])) { |
$file['attribs']['baseinstalldir'] = $baseinstalldir; |
} |
$processFile = $file; |
unset($processFile['attribs']); |
if (count($processFile)) { |
foreach ($processFile as $name => $task) { |
if ($name != $pf2->getTasksNs() . ':replace') { |
return $this->raiseError('Cannot safely process "' . $packagexml . |
'" contains tasks other than replace. Using a ' . |
'PEAR_PackageFileManager-based script is an option.'); |
} |
$file['attribs']['replace'][] = $task; |
} |
} |
if (!in_array($file['attribs']['role'], PEAR_Common::getFileRoles())) { |
return $this->raiseError('Cannot safely convert "' . $packagexml . |
'", contains custom roles. Using a PEAR_PackageFileManager-based script ' . |
'or the convert command is an option'); |
} |
if (isset($release['filelist']['install'])) { |
foreach ($release['filelist']['install'] as $installas) { |
if ($installas['attribs']['name'] == $file['attribs']['name']) { |
$file['attribs']['install-as'] = $installas['attribs']['as']; |
} |
} |
} |
$pf->addFile('/', $file['attribs']['name'], $file['attribs']); |
} |
if ($pf2->getChangeLog()) { |
$this->ui->outputData('WARNING: changelog is not translated to package.xml ' . |
'1.0, use PEAR_PackageFileManager-based script if you need changelog-' . |
'translation for package.xml 1.0'); |
} |
$gen = &$pf->getDefaultGenerator(); |
$gen->toPackageFile('.'); |
} |
} |
/branches/v1.3-critias/bibliotheque/pear/PEAR/Command/Registry.php |
---|
New file |
0,0 → 1,1144 |
<?php |
/** |
* PEAR_Command_Registry (list, list-files, shell-test, info commands) |
* |
* PHP versions 4 and 5 |
* |
* @category pear |
* @package PEAR |
* @author Stig Bakken <ssb@php.net> |
* @author Greg Beaver <cellog@php.net> |
* @copyright 1997-2009 The Authors |
* @license http://opensource.org/licenses/bsd-license.php New BSD License |
* @link http://pear.php.net/package/PEAR |
* @since File available since Release 0.1 |
*/ |
/** |
* base class |
*/ |
require_once 'PEAR/Command/Common.php'; |
/** |
* PEAR commands for registry manipulation |
* |
* @category pear |
* @package PEAR |
* @author Stig Bakken <ssb@php.net> |
* @author Greg Beaver <cellog@php.net> |
* @copyright 1997-2009 The Authors |
* @license http://opensource.org/licenses/bsd-license.php New BSD License |
* @version Release: 1.10.1 |
* @link http://pear.php.net/package/PEAR |
* @since Class available since Release 0.1 |
*/ |
class PEAR_Command_Registry extends PEAR_Command_Common |
{ |
var $commands = array( |
'list' => array( |
'summary' => 'List Installed Packages In The Default Channel', |
'function' => 'doList', |
'shortcut' => 'l', |
'options' => array( |
'channel' => array( |
'shortopt' => 'c', |
'doc' => 'list installed packages from this channel', |
'arg' => 'CHAN', |
), |
'allchannels' => array( |
'shortopt' => 'a', |
'doc' => 'list installed packages from all channels', |
), |
'channelinfo' => array( |
'shortopt' => 'i', |
'doc' => 'output fully channel-aware data, even on failure', |
), |
), |
'doc' => '<package> |
If invoked without parameters, this command lists the PEAR packages |
installed in your php_dir ({config php_dir}). With a parameter, it |
lists the files in a package. |
', |
), |
'list-files' => array( |
'summary' => 'List Files In Installed Package', |
'function' => 'doFileList', |
'shortcut' => 'fl', |
'options' => array(), |
'doc' => '<package> |
List the files in an installed package. |
' |
), |
'shell-test' => array( |
'summary' => 'Shell Script Test', |
'function' => 'doShellTest', |
'shortcut' => 'st', |
'options' => array(), |
'doc' => '<package> [[relation] version] |
Tests if a package is installed in the system. Will exit(1) if it is not. |
<relation> The version comparison operator. One of: |
<, lt, <=, le, >, gt, >=, ge, ==, =, eq, !=, <>, ne |
<version> The version to compare with |
'), |
'info' => array( |
'summary' => 'Display information about a package', |
'function' => 'doInfo', |
'shortcut' => 'in', |
'options' => array(), |
'doc' => '<package> |
Displays information about a package. The package argument may be a |
local package file, an URL to a package file, or the name of an |
installed package.' |
) |
); |
/** |
* PEAR_Command_Registry constructor. |
* |
* @access public |
*/ |
function __construct(&$ui, &$config) |
{ |
parent::__construct($ui, $config); |
} |
function _sortinfo($a, $b) |
{ |
$apackage = isset($a['package']) ? $a['package'] : $a['name']; |
$bpackage = isset($b['package']) ? $b['package'] : $b['name']; |
return strcmp($apackage, $bpackage); |
} |
function doList($command, $options, $params) |
{ |
$reg = &$this->config->getRegistry(); |
$channelinfo = isset($options['channelinfo']); |
if (isset($options['allchannels']) && !$channelinfo) { |
return $this->doListAll($command, array(), $params); |
} |
if (isset($options['allchannels']) && $channelinfo) { |
// allchannels with $channelinfo |
unset($options['allchannels']); |
$channels = $reg->getChannels(); |
$errors = array(); |
PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN); |
foreach ($channels as $channel) { |
$options['channel'] = $channel->getName(); |
$ret = $this->doList($command, $options, $params); |
if (PEAR::isError($ret)) { |
$errors[] = $ret; |
} |
} |
PEAR::staticPopErrorHandling(); |
if (count($errors)) { |
// for now, only give first error |
return PEAR::raiseError($errors[0]); |
} |
return true; |
} |
if (count($params) === 1) { |
return $this->doFileList($command, $options, $params); |
} |
if (isset($options['channel'])) { |
if (!$reg->channelExists($options['channel'])) { |
return $this->raiseError('Channel "' . $options['channel'] .'" does not exist'); |
} |
$channel = $reg->channelName($options['channel']); |
} else { |
$channel = $this->config->get('default_channel'); |
} |
$installed = $reg->packageInfo(null, null, $channel); |
usort($installed, array(&$this, '_sortinfo')); |
$data = array( |
'caption' => 'Installed packages, channel ' . |
$channel . ':', |
'border' => true, |
'headline' => array('Package', 'Version', 'State'), |
'channel' => $channel, |
); |
if ($channelinfo) { |
$data['headline'] = array('Channel', 'Package', 'Version', 'State'); |
} |
if (count($installed) && !isset($data['data'])) { |
$data['data'] = array(); |
} |
foreach ($installed as $package) { |
$pobj = $reg->getPackage(isset($package['package']) ? |
$package['package'] : $package['name'], $channel); |
if ($channelinfo) { |
$packageinfo = array($pobj->getChannel(), $pobj->getPackage(), $pobj->getVersion(), |
$pobj->getState() ? $pobj->getState() : null); |
} else { |
$packageinfo = array($pobj->getPackage(), $pobj->getVersion(), |
$pobj->getState() ? $pobj->getState() : null); |
} |
$data['data'][] = $packageinfo; |
} |
if (count($installed) === 0) { |
if (!$channelinfo) { |
$data = '(no packages installed from channel ' . $channel . ')'; |
} else { |
$data = array( |
'caption' => 'Installed packages, channel ' . |
$channel . ':', |
'border' => true, |
'channel' => $channel, |
'data' => array(array('(no packages installed)')), |
); |
} |
} |
$this->ui->outputData($data, $command); |
return true; |
} |
function doListAll($command, $options, $params) |
{ |
// This duplicate code is deprecated over |
// list --channelinfo, which gives identical |
// output for list and list --allchannels. |
$reg = &$this->config->getRegistry(); |
$installed = $reg->packageInfo(null, null, null); |
foreach ($installed as $channel => $packages) { |
usort($packages, array($this, '_sortinfo')); |
$data = array( |
'caption' => 'Installed packages, channel ' . $channel . ':', |
'border' => true, |
'headline' => array('Package', 'Version', 'State'), |
'channel' => $channel |
); |
foreach ($packages as $package) { |
$p = isset($package['package']) ? $package['package'] : $package['name']; |
$pobj = $reg->getPackage($p, $channel); |
$data['data'][] = array($pobj->getPackage(), $pobj->getVersion(), |
$pobj->getState() ? $pobj->getState() : null); |
} |
// Adds a blank line after each section |
$data['data'][] = array(); |
if (count($packages) === 0) { |
$data = array( |
'caption' => 'Installed packages, channel ' . $channel . ':', |
'border' => true, |
'data' => array(array('(no packages installed)'), array()), |
'channel' => $channel |
); |
} |
$this->ui->outputData($data, $command); |
} |
return true; |
} |
function doFileList($command, $options, $params) |
{ |
if (count($params) !== 1) { |
return $this->raiseError('list-files expects 1 parameter'); |
} |
$reg = &$this->config->getRegistry(); |
$fp = false; |
if (!is_dir($params[0]) && (file_exists($params[0]) || $fp = @fopen($params[0], 'r'))) { |
if ($fp) { |
fclose($fp); |
} |
if (!class_exists('PEAR_PackageFile')) { |
require_once 'PEAR/PackageFile.php'; |
} |
$pkg = new PEAR_PackageFile($this->config, $this->_debug); |
PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN); |
$info = &$pkg->fromAnyFile($params[0], PEAR_VALIDATE_NORMAL); |
PEAR::staticPopErrorHandling(); |
$headings = array('Package File', 'Install Path'); |
$installed = false; |
} else { |
PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN); |
$parsed = $reg->parsePackageName($params[0], $this->config->get('default_channel')); |
PEAR::staticPopErrorHandling(); |
if (PEAR::isError($parsed)) { |
return $this->raiseError($parsed); |
} |
$info = &$reg->getPackage($parsed['package'], $parsed['channel']); |
$headings = array('Type', 'Install Path'); |
$installed = true; |
} |
if (PEAR::isError($info)) { |
return $this->raiseError($info); |
} |
if ($info === null) { |
return $this->raiseError("`$params[0]' not installed"); |
} |
$list = ($info->getPackagexmlVersion() == '1.0' || $installed) ? |
$info->getFilelist() : $info->getContents(); |
if ($installed) { |
$caption = 'Installed Files For ' . $params[0]; |
} else { |
$caption = 'Contents of ' . basename($params[0]); |
} |
$data = array( |
'caption' => $caption, |
'border' => true, |
'headline' => $headings); |
if ($info->getPackagexmlVersion() == '1.0' || $installed) { |
foreach ($list as $file => $att) { |
if ($installed) { |
if (empty($att['installed_as'])) { |
continue; |
} |
$data['data'][] = array($att['role'], $att['installed_as']); |
} else { |
if (isset($att['baseinstalldir']) && !in_array($att['role'], |
array('test', 'data', 'doc'))) { |
$dest = $att['baseinstalldir'] . DIRECTORY_SEPARATOR . |
$file; |
} else { |
$dest = $file; |
} |
switch ($att['role']) { |
case 'test': |
case 'data': |
case 'doc': |
$role = $att['role']; |
if ($role == 'test') { |
$role .= 's'; |
} |
$dest = $this->config->get($role . '_dir') . DIRECTORY_SEPARATOR . |
$info->getPackage() . DIRECTORY_SEPARATOR . $dest; |
break; |
case 'php': |
default: |
$dest = $this->config->get('php_dir') . DIRECTORY_SEPARATOR . |
$dest; |
} |
$ds2 = DIRECTORY_SEPARATOR . DIRECTORY_SEPARATOR; |
$dest = preg_replace(array('!\\\\+!', '!/!', "!$ds2+!"), |
array(DIRECTORY_SEPARATOR, |
DIRECTORY_SEPARATOR, |
DIRECTORY_SEPARATOR), |
$dest); |
$file = preg_replace('!/+!', '/', $file); |
$data['data'][] = array($file, $dest); |
} |
} |
} else { // package.xml 2.0, not installed |
if (!isset($list['dir']['file'][0])) { |
$list['dir']['file'] = array($list['dir']['file']); |
} |
foreach ($list['dir']['file'] as $att) { |
$att = $att['attribs']; |
$file = $att['name']; |
$role = &PEAR_Installer_Role::factory($info, $att['role'], $this->config); |
$role->setup($this, $info, $att, $file); |
if (!$role->isInstallable()) { |
$dest = '(not installable)'; |
} else { |
$dest = $role->processInstallation($info, $att, $file, ''); |
if (PEAR::isError($dest)) { |
$dest = '(Unknown role "' . $att['role'] . ')'; |
} else { |
list(,, $dest) = $dest; |
} |
} |
$data['data'][] = array($file, $dest); |
} |
} |
$this->ui->outputData($data, $command); |
return true; |
} |
function doShellTest($command, $options, $params) |
{ |
if (count($params) < 1) { |
return PEAR::raiseError('ERROR, usage: pear shell-test packagename [[relation] version]'); |
} |
PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN); |
$reg = &$this->config->getRegistry(); |
$info = $reg->parsePackageName($params[0], $this->config->get('default_channel')); |
if (PEAR::isError($info)) { |
exit(1); // invalid package name |
} |
$package = $info['package']; |
$channel = $info['channel']; |
// "pear shell-test Foo" |
if (!$reg->packageExists($package, $channel)) { |
if ($channel == 'pecl.php.net') { |
if ($reg->packageExists($package, 'pear.php.net')) { |
$channel = 'pear.php.net'; // magically change channels for extensions |
} |
} |
} |
if (count($params) === 1) { |
if (!$reg->packageExists($package, $channel)) { |
exit(1); |
} |
// "pear shell-test Foo 1.0" |
} elseif (count($params) === 2) { |
$v = $reg->packageInfo($package, 'version', $channel); |
if (!$v || !version_compare("$v", "{$params[1]}", "ge")) { |
exit(1); |
} |
// "pear shell-test Foo ge 1.0" |
} elseif (count($params) === 3) { |
$v = $reg->packageInfo($package, 'version', $channel); |
if (!$v || !version_compare("$v", "{$params[2]}", $params[1])) { |
exit(1); |
} |
} else { |
PEAR::staticPopErrorHandling(); |
$this->raiseError("$command: expects 1 to 3 parameters"); |
exit(1); |
} |
} |
function doInfo($command, $options, $params) |
{ |
if (count($params) !== 1) { |
return $this->raiseError('pear info expects 1 parameter'); |
} |
$info = $fp = false; |
$reg = &$this->config->getRegistry(); |
if (is_file($params[0]) && !is_dir($params[0]) && |
(file_exists($params[0]) || $fp = @fopen($params[0], 'r')) |
) { |
if ($fp) { |
fclose($fp); |
} |
if (!class_exists('PEAR_PackageFile')) { |
require_once 'PEAR/PackageFile.php'; |
} |
$pkg = new PEAR_PackageFile($this->config, $this->_debug); |
PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN); |
$obj = &$pkg->fromAnyFile($params[0], PEAR_VALIDATE_NORMAL); |
PEAR::staticPopErrorHandling(); |
if (PEAR::isError($obj)) { |
$uinfo = $obj->getUserInfo(); |
if (is_array($uinfo)) { |
foreach ($uinfo as $message) { |
if (is_array($message)) { |
$message = $message['message']; |
} |
$this->ui->outputData($message); |
} |
} |
return $this->raiseError($obj); |
} |
if ($obj->getPackagexmlVersion() != '1.0') { |
return $this->_doInfo2($command, $options, $params, $obj, false); |
} |
$info = $obj->toArray(); |
} else { |
$parsed = $reg->parsePackageName($params[0], $this->config->get('default_channel')); |
if (PEAR::isError($parsed)) { |
return $this->raiseError($parsed); |
} |
$package = $parsed['package']; |
$channel = $parsed['channel']; |
$info = $reg->packageInfo($package, null, $channel); |
if (isset($info['old'])) { |
$obj = $reg->getPackage($package, $channel); |
return $this->_doInfo2($command, $options, $params, $obj, true); |
} |
} |
if (PEAR::isError($info)) { |
return $info; |
} |
if (empty($info)) { |
$this->raiseError("No information found for `$params[0]'"); |
return; |
} |
unset($info['filelist']); |
unset($info['dirtree']); |
unset($info['changelog']); |
if (isset($info['xsdversion'])) { |
$info['package.xml version'] = $info['xsdversion']; |
unset($info['xsdversion']); |
} |
if (isset($info['packagerversion'])) { |
$info['packaged with PEAR version'] = $info['packagerversion']; |
unset($info['packagerversion']); |
} |
$keys = array_keys($info); |
$longtext = array('description', 'summary'); |
foreach ($keys as $key) { |
if (is_array($info[$key])) { |
switch ($key) { |
case 'maintainers': { |
$i = 0; |
$mstr = ''; |
foreach ($info[$key] as $m) { |
if ($i++ > 0) { |
$mstr .= "\n"; |
} |
$mstr .= $m['name'] . " <"; |
if (isset($m['email'])) { |
$mstr .= $m['email']; |
} else { |
$mstr .= $m['handle'] . '@php.net'; |
} |
$mstr .= "> ($m[role])"; |
} |
$info[$key] = $mstr; |
break; |
} |
case 'release_deps': { |
$i = 0; |
$dstr = ''; |
foreach ($info[$key] as $d) { |
if (isset($this->_deps_rel_trans[$d['rel']])) { |
$rel = $this->_deps_rel_trans[$d['rel']]; |
} else { |
$rel = $d['rel']; |
} |
if (isset($this->_deps_type_trans[$d['type']])) { |
$type = ucfirst($this->_deps_type_trans[$d['type']]); |
} else { |
$type = $d['type']; |
} |
if (isset($d['name'])) { |
$name = $d['name'] . ' '; |
} else { |
$name = ''; |
} |
if (isset($d['version'])) { |
$version = $d['version'] . ' '; |
} else { |
$version = ''; |
} |
if (isset($d['optional']) && $d['optional'] == 'yes') { |
$optional = ' (optional)'; |
} else { |
$optional = ''; |
} |
$dstr .= "$type $name$rel $version$optional\n"; |
} |
$info[$key] = $dstr; |
break; |
} |
case 'provides' : { |
$debug = $this->config->get('verbose'); |
if ($debug < 2) { |
$pstr = 'Classes: '; |
} else { |
$pstr = ''; |
} |
$i = 0; |
foreach ($info[$key] as $p) { |
if ($debug < 2 && $p['type'] != "class") { |
continue; |
} |
// Only print classes when verbosity mode is < 2 |
if ($debug < 2) { |
if ($i++ > 0) { |
$pstr .= ", "; |
} |
$pstr .= $p['name']; |
} else { |
if ($i++ > 0) { |
$pstr .= "\n"; |
} |
$pstr .= ucfirst($p['type']) . " " . $p['name']; |
if (isset($p['explicit']) && $p['explicit'] == 1) { |
$pstr .= " (explicit)"; |
} |
} |
} |
$info[$key] = $pstr; |
break; |
} |
case 'configure_options' : { |
foreach ($info[$key] as $i => $p) { |
$info[$key][$i] = array_map(null, array_keys($p), array_values($p)); |
$info[$key][$i] = array_map(create_function('$a', |
'return join(" = ",$a);'), $info[$key][$i]); |
$info[$key][$i] = implode(', ', $info[$key][$i]); |
} |
$info[$key] = implode("\n", $info[$key]); |
break; |
} |
default: { |
$info[$key] = implode(", ", $info[$key]); |
break; |
} |
} |
} |
if ($key == '_lastmodified') { |
$hdate = date('Y-m-d', $info[$key]); |
unset($info[$key]); |
$info['Last Modified'] = $hdate; |
} elseif ($key == '_lastversion') { |
$info['Previous Installed Version'] = $info[$key] ? $info[$key] : '- None -'; |
unset($info[$key]); |
} else { |
$info[$key] = trim($info[$key]); |
if (in_array($key, $longtext)) { |
$info[$key] = preg_replace('/ +/', ' ', $info[$key]); |
} |
} |
} |
$caption = 'About ' . $info['package'] . '-' . $info['version']; |
$data = array( |
'caption' => $caption, |
'border' => true); |
foreach ($info as $key => $value) { |
$key = ucwords(trim(str_replace('_', ' ', $key))); |
$data['data'][] = array($key, $value); |
} |
$data['raw'] = $info; |
$this->ui->outputData($data, 'package-info'); |
} |
/** |
* @access private |
*/ |
function _doInfo2($command, $options, $params, &$obj, $installed) |
{ |
$reg = &$this->config->getRegistry(); |
$caption = 'About ' . $obj->getChannel() . '/' .$obj->getPackage() . '-' . |
$obj->getVersion(); |
$data = array( |
'caption' => $caption, |
'border' => true); |
switch ($obj->getPackageType()) { |
case 'php' : |
$release = 'PEAR-style PHP-based Package'; |
break; |
case 'extsrc' : |
$release = 'PECL-style PHP extension (source code)'; |
break; |
case 'zendextsrc' : |
$release = 'PECL-style Zend extension (source code)'; |
break; |
case 'extbin' : |
$release = 'PECL-style PHP extension (binary)'; |
break; |
case 'zendextbin' : |
$release = 'PECL-style Zend extension (binary)'; |
break; |
case 'bundle' : |
$release = 'Package bundle (collection of packages)'; |
break; |
} |
$extends = $obj->getExtends(); |
$extends = $extends ? |
$obj->getPackage() . ' (extends ' . $extends . ')' : $obj->getPackage(); |
if ($src = $obj->getSourcePackage()) { |
$extends .= ' (source package ' . $src['channel'] . '/' . $src['package'] . ')'; |
} |
$info = array( |
'Release Type' => $release, |
'Name' => $extends, |
'Channel' => $obj->getChannel(), |
'Summary' => preg_replace('/ +/', ' ', $obj->getSummary()), |
'Description' => preg_replace('/ +/', ' ', $obj->getDescription()), |
); |
$info['Maintainers'] = ''; |
foreach (array('lead', 'developer', 'contributor', 'helper') as $role) { |
$leads = $obj->{"get{$role}s"}(); |
if (!$leads) { |
continue; |
} |
if (isset($leads['active'])) { |
$leads = array($leads); |
} |
foreach ($leads as $lead) { |
if (!empty($info['Maintainers'])) { |
$info['Maintainers'] .= "\n"; |
} |
$active = $lead['active'] == 'no' ? ', inactive' : ''; |
$info['Maintainers'] .= $lead['name'] . ' <'; |
$info['Maintainers'] .= $lead['email'] . "> ($role$active)"; |
} |
} |
$info['Release Date'] = $obj->getDate(); |
if ($time = $obj->getTime()) { |
$info['Release Date'] .= ' ' . $time; |
} |
$info['Release Version'] = $obj->getVersion() . ' (' . $obj->getState() . ')'; |
$info['API Version'] = $obj->getVersion('api') . ' (' . $obj->getState('api') . ')'; |
$info['License'] = $obj->getLicense(); |
$uri = $obj->getLicenseLocation(); |
if ($uri) { |
if (isset($uri['uri'])) { |
$info['License'] .= ' (' . $uri['uri'] . ')'; |
} else { |
$extra = $obj->getInstalledLocation($info['filesource']); |
if ($extra) { |
$info['License'] .= ' (' . $uri['filesource'] . ')'; |
} |
} |
} |
$info['Release Notes'] = $obj->getNotes(); |
if ($compat = $obj->getCompatible()) { |
if (!isset($compat[0])) { |
$compat = array($compat); |
} |
$info['Compatible with'] = ''; |
foreach ($compat as $package) { |
$info['Compatible with'] .= $package['channel'] . '/' . $package['name'] . |
"\nVersions >= " . $package['min'] . ', <= ' . $package['max']; |
if (isset($package['exclude'])) { |
if (is_array($package['exclude'])) { |
$package['exclude'] = implode(', ', $package['exclude']); |
} |
if (!isset($info['Not Compatible with'])) { |
$info['Not Compatible with'] = ''; |
} else { |
$info['Not Compatible with'] .= "\n"; |
} |
$info['Not Compatible with'] .= $package['channel'] . '/' . |
$package['name'] . "\nVersions " . $package['exclude']; |
} |
} |
} |
$usesrole = $obj->getUsesrole(); |
if ($usesrole) { |
if (!isset($usesrole[0])) { |
$usesrole = array($usesrole); |
} |
foreach ($usesrole as $roledata) { |
if (isset($info['Uses Custom Roles'])) { |
$info['Uses Custom Roles'] .= "\n"; |
} else { |
$info['Uses Custom Roles'] = ''; |
} |
if (isset($roledata['package'])) { |
$rolepackage = $reg->parsedPackageNameToString($roledata, true); |
} else { |
$rolepackage = $roledata['uri']; |
} |
$info['Uses Custom Roles'] .= $roledata['role'] . ' (' . $rolepackage . ')'; |
} |
} |
$usestask = $obj->getUsestask(); |
if ($usestask) { |
if (!isset($usestask[0])) { |
$usestask = array($usestask); |
} |
foreach ($usestask as $taskdata) { |
if (isset($info['Uses Custom Tasks'])) { |
$info['Uses Custom Tasks'] .= "\n"; |
} else { |
$info['Uses Custom Tasks'] = ''; |
} |
if (isset($taskdata['package'])) { |
$taskpackage = $reg->parsedPackageNameToString($taskdata, true); |
} else { |
$taskpackage = $taskdata['uri']; |
} |
$info['Uses Custom Tasks'] .= $taskdata['task'] . ' (' . $taskpackage . ')'; |
} |
} |
$deps = $obj->getDependencies(); |
$info['Required Dependencies'] = 'PHP version ' . $deps['required']['php']['min']; |
if (isset($deps['required']['php']['max'])) { |
$info['Required Dependencies'] .= '-' . $deps['required']['php']['max'] . "\n"; |
} else { |
$info['Required Dependencies'] .= "\n"; |
} |
if (isset($deps['required']['php']['exclude'])) { |
if (!isset($info['Not Compatible with'])) { |
$info['Not Compatible with'] = ''; |
} else { |
$info['Not Compatible with'] .= "\n"; |
} |
if (is_array($deps['required']['php']['exclude'])) { |
$deps['required']['php']['exclude'] = |
implode(', ', $deps['required']['php']['exclude']); |
} |
$info['Not Compatible with'] .= "PHP versions\n " . |
$deps['required']['php']['exclude']; |
} |
$info['Required Dependencies'] .= 'PEAR installer version'; |
if (isset($deps['required']['pearinstaller']['max'])) { |
$info['Required Dependencies'] .= 's ' . |
$deps['required']['pearinstaller']['min'] . '-' . |
$deps['required']['pearinstaller']['max']; |
} else { |
$info['Required Dependencies'] .= ' ' . |
$deps['required']['pearinstaller']['min'] . ' or newer'; |
} |
if (isset($deps['required']['pearinstaller']['exclude'])) { |
if (!isset($info['Not Compatible with'])) { |
$info['Not Compatible with'] = ''; |
} else { |
$info['Not Compatible with'] .= "\n"; |
} |
if (is_array($deps['required']['pearinstaller']['exclude'])) { |
$deps['required']['pearinstaller']['exclude'] = |
implode(', ', $deps['required']['pearinstaller']['exclude']); |
} |
$info['Not Compatible with'] .= "PEAR installer\n Versions " . |
$deps['required']['pearinstaller']['exclude']; |
} |
foreach (array('Package', 'Extension') as $type) { |
$index = strtolower($type); |
if (isset($deps['required'][$index])) { |
if (isset($deps['required'][$index]['name'])) { |
$deps['required'][$index] = array($deps['required'][$index]); |
} |
foreach ($deps['required'][$index] as $package) { |
if (isset($package['conflicts'])) { |
$infoindex = 'Not Compatible with'; |
if (!isset($info['Not Compatible with'])) { |
$info['Not Compatible with'] = ''; |
} else { |
$info['Not Compatible with'] .= "\n"; |
} |
} else { |
$infoindex = 'Required Dependencies'; |
$info[$infoindex] .= "\n"; |
} |
if ($index == 'extension') { |
$name = $package['name']; |
} else { |
if (isset($package['channel'])) { |
$name = $package['channel'] . '/' . $package['name']; |
} else { |
$name = '__uri/' . $package['name'] . ' (static URI)'; |
} |
} |
$info[$infoindex] .= "$type $name"; |
if (isset($package['uri'])) { |
$info[$infoindex] .= "\n Download URI: $package[uri]"; |
continue; |
} |
if (isset($package['max']) && isset($package['min'])) { |
$info[$infoindex] .= " \n Versions " . |
$package['min'] . '-' . $package['max']; |
} elseif (isset($package['min'])) { |
$info[$infoindex] .= " \n Version " . |
$package['min'] . ' or newer'; |
} elseif (isset($package['max'])) { |
$info[$infoindex] .= " \n Version " . |
$package['max'] . ' or older'; |
} |
if (isset($package['recommended'])) { |
$info[$infoindex] .= "\n Recommended version: $package[recommended]"; |
} |
if (isset($package['exclude'])) { |
if (!isset($info['Not Compatible with'])) { |
$info['Not Compatible with'] = ''; |
} else { |
$info['Not Compatible with'] .= "\n"; |
} |
if (is_array($package['exclude'])) { |
$package['exclude'] = implode(', ', $package['exclude']); |
} |
$package['package'] = $package['name']; // for parsedPackageNameToString |
if (isset($package['conflicts'])) { |
$info['Not Compatible with'] .= '=> except '; |
} |
$info['Not Compatible with'] .= 'Package ' . |
$reg->parsedPackageNameToString($package, true); |
$info['Not Compatible with'] .= "\n Versions " . $package['exclude']; |
} |
} |
} |
} |
if (isset($deps['required']['os'])) { |
if (isset($deps['required']['os']['name'])) { |
$dep['required']['os']['name'] = array($dep['required']['os']['name']); |
} |
foreach ($dep['required']['os'] as $os) { |
if (isset($os['conflicts']) && $os['conflicts'] == 'yes') { |
if (!isset($info['Not Compatible with'])) { |
$info['Not Compatible with'] = ''; |
} else { |
$info['Not Compatible with'] .= "\n"; |
} |
$info['Not Compatible with'] .= "$os[name] Operating System"; |
} else { |
$info['Required Dependencies'] .= "\n"; |
$info['Required Dependencies'] .= "$os[name] Operating System"; |
} |
} |
} |
if (isset($deps['required']['arch'])) { |
if (isset($deps['required']['arch']['pattern'])) { |
$dep['required']['arch']['pattern'] = array($dep['required']['os']['pattern']); |
} |
foreach ($dep['required']['arch'] as $os) { |
if (isset($os['conflicts']) && $os['conflicts'] == 'yes') { |
if (!isset($info['Not Compatible with'])) { |
$info['Not Compatible with'] = ''; |
} else { |
$info['Not Compatible with'] .= "\n"; |
} |
$info['Not Compatible with'] .= "OS/Arch matching pattern '/$os[pattern]/'"; |
} else { |
$info['Required Dependencies'] .= "\n"; |
$info['Required Dependencies'] .= "OS/Arch matching pattern '/$os[pattern]/'"; |
} |
} |
} |
if (isset($deps['optional'])) { |
foreach (array('Package', 'Extension') as $type) { |
$index = strtolower($type); |
if (isset($deps['optional'][$index])) { |
if (isset($deps['optional'][$index]['name'])) { |
$deps['optional'][$index] = array($deps['optional'][$index]); |
} |
foreach ($deps['optional'][$index] as $package) { |
if (isset($package['conflicts']) && $package['conflicts'] == 'yes') { |
$infoindex = 'Not Compatible with'; |
if (!isset($info['Not Compatible with'])) { |
$info['Not Compatible with'] = ''; |
} else { |
$info['Not Compatible with'] .= "\n"; |
} |
} else { |
$infoindex = 'Optional Dependencies'; |
if (!isset($info['Optional Dependencies'])) { |
$info['Optional Dependencies'] = ''; |
} else { |
$info['Optional Dependencies'] .= "\n"; |
} |
} |
if ($index == 'extension') { |
$name = $package['name']; |
} else { |
if (isset($package['channel'])) { |
$name = $package['channel'] . '/' . $package['name']; |
} else { |
$name = '__uri/' . $package['name'] . ' (static URI)'; |
} |
} |
$info[$infoindex] .= "$type $name"; |
if (isset($package['uri'])) { |
$info[$infoindex] .= "\n Download URI: $package[uri]"; |
continue; |
} |
if ($infoindex == 'Not Compatible with') { |
// conflicts is only used to say that all versions conflict |
continue; |
} |
if (isset($package['max']) && isset($package['min'])) { |
$info[$infoindex] .= " \n Versions " . |
$package['min'] . '-' . $package['max']; |
} elseif (isset($package['min'])) { |
$info[$infoindex] .= " \n Version " . |
$package['min'] . ' or newer'; |
} elseif (isset($package['max'])) { |
$info[$infoindex] .= " \n Version " . |
$package['min'] . ' or older'; |
} |
if (isset($package['recommended'])) { |
$info[$infoindex] .= "\n Recommended version: $package[recommended]"; |
} |
if (isset($package['exclude'])) { |
if (!isset($info['Not Compatible with'])) { |
$info['Not Compatible with'] = ''; |
} else { |
$info['Not Compatible with'] .= "\n"; |
} |
if (is_array($package['exclude'])) { |
$package['exclude'] = implode(', ', $package['exclude']); |
} |
$info['Not Compatible with'] .= "Package $package\n Versions " . |
$package['exclude']; |
} |
} |
} |
} |
} |
if (isset($deps['group'])) { |
if (!isset($deps['group'][0])) { |
$deps['group'] = array($deps['group']); |
} |
foreach ($deps['group'] as $group) { |
$info['Dependency Group ' . $group['attribs']['name']] = $group['attribs']['hint']; |
$groupindex = $group['attribs']['name'] . ' Contents'; |
$info[$groupindex] = ''; |
foreach (array('Package', 'Extension') as $type) { |
$index = strtolower($type); |
if (isset($group[$index])) { |
if (isset($group[$index]['name'])) { |
$group[$index] = array($group[$index]); |
} |
foreach ($group[$index] as $package) { |
if (!empty($info[$groupindex])) { |
$info[$groupindex] .= "\n"; |
} |
if ($index == 'extension') { |
$name = $package['name']; |
} else { |
if (isset($package['channel'])) { |
$name = $package['channel'] . '/' . $package['name']; |
} else { |
$name = '__uri/' . $package['name'] . ' (static URI)'; |
} |
} |
if (isset($package['uri'])) { |
if (isset($package['conflicts']) && $package['conflicts'] == 'yes') { |
$info[$groupindex] .= "Not Compatible with $type $name"; |
} else { |
$info[$groupindex] .= "$type $name"; |
} |
$info[$groupindex] .= "\n Download URI: $package[uri]"; |
continue; |
} |
if (isset($package['conflicts']) && $package['conflicts'] == 'yes') { |
$info[$groupindex] .= "Not Compatible with $type $name"; |
continue; |
} |
$info[$groupindex] .= "$type $name"; |
if (isset($package['max']) && isset($package['min'])) { |
$info[$groupindex] .= " \n Versions " . |
$package['min'] . '-' . $package['max']; |
} elseif (isset($package['min'])) { |
$info[$groupindex] .= " \n Version " . |
$package['min'] . ' or newer'; |
} elseif (isset($package['max'])) { |
$info[$groupindex] .= " \n Version " . |
$package['min'] . ' or older'; |
} |
if (isset($package['recommended'])) { |
$info[$groupindex] .= "\n Recommended version: $package[recommended]"; |
} |
if (isset($package['exclude'])) { |
if (!isset($info['Not Compatible with'])) { |
$info['Not Compatible with'] = ''; |
} else { |
$info[$groupindex] .= "Not Compatible with\n"; |
} |
if (is_array($package['exclude'])) { |
$package['exclude'] = implode(', ', $package['exclude']); |
} |
$info[$groupindex] .= " Package $package\n Versions " . |
$package['exclude']; |
} |
} |
} |
} |
} |
} |
if ($obj->getPackageType() == 'bundle') { |
$info['Bundled Packages'] = ''; |
foreach ($obj->getBundledPackages() as $package) { |
if (!empty($info['Bundled Packages'])) { |
$info['Bundled Packages'] .= "\n"; |
} |
if (isset($package['uri'])) { |
$info['Bundled Packages'] .= '__uri/' . $package['name']; |
$info['Bundled Packages'] .= "\n (URI: $package[uri]"; |
} else { |
$info['Bundled Packages'] .= $package['channel'] . '/' . $package['name']; |
} |
} |
} |
$info['package.xml version'] = '2.0'; |
if ($installed) { |
if ($obj->getLastModified()) { |
$info['Last Modified'] = date('Y-m-d H:i', $obj->getLastModified()); |
} |
$v = $obj->getLastInstalledVersion(); |
$info['Previous Installed Version'] = $v ? $v : '- None -'; |
} |
foreach ($info as $key => $value) { |
$data['data'][] = array($key, $value); |
} |
$data['raw'] = $obj->getArray(); // no validation needed |
$this->ui->outputData($data, 'package-info'); |
} |
} |
/branches/v1.3-critias/bibliotheque/pear/PEAR/Command/Build.xml |
---|
New file |
0,0 → 1,10 |
<commands version="1.0"> |
<build> |
<summary>Build an Extension From C Source</summary> |
<function>doBuild</function> |
<shortcut>b</shortcut> |
<options /> |
<doc>[package.xml] |
Builds one or more extensions contained in a package.</doc> |
</build> |
</commands> |
/branches/v1.3-critias/bibliotheque/pear/PEAR/Command/Mirror.php |
---|
New file |
0,0 → 1,138 |
<?php |
/** |
* PEAR_Command_Mirror (download-all command) |
* |
* PHP versions 4 and 5 |
* |
* @category pear |
* @package PEAR |
* @author Alexander Merz <alexmerz@php.net> |
* @copyright 1997-2009 The Authors |
* @license http://opensource.org/licenses/bsd-license.php New BSD License |
* @link http://pear.php.net/package/PEAR |
* @since File available since Release 1.2.0 |
*/ |
/** |
* base class |
*/ |
require_once 'PEAR/Command/Common.php'; |
/** |
* PEAR commands for providing file mirrors |
* |
* @category pear |
* @package PEAR |
* @author Alexander Merz <alexmerz@php.net> |
* @copyright 1997-2009 The Authors |
* @license http://opensource.org/licenses/bsd-license.php New BSD License |
* @version Release: 1.10.1 |
* @link http://pear.php.net/package/PEAR |
* @since Class available since Release 1.2.0 |
*/ |
class PEAR_Command_Mirror extends PEAR_Command_Common |
{ |
var $commands = array( |
'download-all' => array( |
'summary' => 'Downloads each available package from the default channel', |
'function' => 'doDownloadAll', |
'shortcut' => 'da', |
'options' => array( |
'channel' => |
array( |
'shortopt' => 'c', |
'doc' => 'specify a channel other than the default channel', |
'arg' => 'CHAN', |
), |
), |
'doc' => ' |
Requests a list of available packages from the default channel ({config default_channel}) |
and downloads them to current working directory. Note: only |
packages within preferred_state ({config preferred_state}) will be downloaded' |
), |
); |
/** |
* PEAR_Command_Mirror constructor. |
* |
* @access public |
* @param object PEAR_Frontend a reference to an frontend |
* @param object PEAR_Config a reference to the configuration data |
*/ |
function __construct(&$ui, &$config) |
{ |
parent::__construct($ui, $config); |
} |
/** |
* For unit-testing |
*/ |
function &factory($a) |
{ |
$a = &PEAR_Command::factory($a, $this->config); |
return $a; |
} |
/** |
* retrieves a list of avaible Packages from master server |
* and downloads them |
* |
* @access public |
* @param string $command the command |
* @param array $options the command options before the command |
* @param array $params the stuff after the command name |
* @return bool true if successful |
* @throw PEAR_Error |
*/ |
function doDownloadAll($command, $options, $params) |
{ |
$savechannel = $this->config->get('default_channel'); |
$reg = &$this->config->getRegistry(); |
$channel = isset($options['channel']) ? $options['channel'] : |
$this->config->get('default_channel'); |
if (!$reg->channelExists($channel)) { |
$this->config->set('default_channel', $savechannel); |
return $this->raiseError('Channel "' . $channel . '" does not exist'); |
} |
$this->config->set('default_channel', $channel); |
$this->ui->outputData('Using Channel ' . $this->config->get('default_channel')); |
$chan = $reg->getChannel($channel); |
if (PEAR::isError($chan)) { |
return $this->raiseError($chan); |
} |
if ($chan->supportsREST($this->config->get('preferred_mirror')) && |
$base = $chan->getBaseURL('REST1.0', $this->config->get('preferred_mirror'))) { |
$rest = &$this->config->getREST('1.0', array()); |
$remoteInfo = array_flip($rest->listPackages($base, $channel)); |
} |
if (PEAR::isError($remoteInfo)) { |
return $remoteInfo; |
} |
$cmd = &$this->factory("download"); |
if (PEAR::isError($cmd)) { |
return $cmd; |
} |
$this->ui->outputData('Using Preferred State of ' . |
$this->config->get('preferred_state')); |
$this->ui->outputData('Gathering release information, please wait...'); |
/** |
* Error handling not necessary, because already done by |
* the download command |
*/ |
PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN); |
$err = $cmd->run('download', array('downloadonly' => true), array_keys($remoteInfo)); |
PEAR::staticPopErrorHandling(); |
$this->config->set('default_channel', $savechannel); |
if (PEAR::isError($err)) { |
$this->ui->outputData($err->getMessage()); |
} |
return true; |
} |
} |
/branches/v1.3-critias/bibliotheque/pear/PEAR/Command/Auth.xml |
---|
New file |
0,0 → 1,30 |
<commands version="1.0"> |
<login> |
<summary>Connects and authenticates to remote server [Deprecated in favor of channel-login]</summary> |
<function>doLogin</function> |
<shortcut>li</shortcut> |
<options /> |
<doc><channel name> |
WARNING: This function is deprecated in favor of using channel-login |
Log in to a remote channel server. If <channel name> is not supplied, |
the default channel is used. To use remote functions in the installer |
that require any kind of privileges, you need to log in first. The |
username and password you enter here will be stored in your per-user |
PEAR configuration (~/.pearrc on Unix-like systems). After logging |
in, your username and password will be sent along in subsequent |
operations on the remote server.</doc> |
</login> |
<logout> |
<summary>Logs out from the remote server [Deprecated in favor of channel-logout]</summary> |
<function>doLogout</function> |
<shortcut>lo</shortcut> |
<options /> |
<doc> |
WARNING: This function is deprecated in favor of using channel-logout |
Logs out from the remote server. This command does not actually |
connect to the remote server, it only deletes the stored username and |
password from your user configuration.</doc> |
</logout> |
</commands> |
/branches/v1.3-critias/bibliotheque/pear/PEAR/Command/Config.xml |
---|
New file |
0,0 → 1,92 |
<commands version="1.0"> |
<config-show> |
<summary>Show All Settings</summary> |
<function>doConfigShow</function> |
<shortcut>csh</shortcut> |
<options> |
<channel> |
<shortopt>c</shortopt> |
<doc>show configuration variables for another channel</doc> |
<arg>CHAN</arg> |
</channel> |
</options> |
<doc>[layer] |
Displays all configuration values. An optional argument |
may be used to tell which configuration layer to display. Valid |
configuration layers are "user", "system" and "default". To display |
configurations for different channels, set the default_channel |
configuration variable and run config-show again. |
</doc> |
</config-show> |
<config-get> |
<summary>Show One Setting</summary> |
<function>doConfigGet</function> |
<shortcut>cg</shortcut> |
<options> |
<channel> |
<shortopt>c</shortopt> |
<doc>show configuration variables for another channel</doc> |
<arg>CHAN</arg> |
</channel> |
</options> |
<doc><parameter> [layer] |
Displays the value of one configuration parameter. The |
first argument is the name of the parameter, an optional second argument |
may be used to tell which configuration layer to look in. Valid configuration |
layers are "user", "system" and "default". If no layer is specified, a value |
will be picked from the first layer that defines the parameter, in the order |
just specified. The configuration value will be retrieved for the channel |
specified by the default_channel configuration variable. |
</doc> |
</config-get> |
<config-set> |
<summary>Change Setting</summary> |
<function>doConfigSet</function> |
<shortcut>cs</shortcut> |
<options> |
<channel> |
<shortopt>c</shortopt> |
<doc>show configuration variables for another channel</doc> |
<arg>CHAN</arg> |
</channel> |
</options> |
<doc><parameter> <value> [layer] |
Sets the value of one configuration parameter. The first argument is |
the name of the parameter, the second argument is the new value. Some |
parameters are subject to validation, and the command will fail with |
an error message if the new value does not make sense. An optional |
third argument may be used to specify in which layer to set the |
configuration parameter. The default layer is "user". The |
configuration value will be set for the current channel, which |
is controlled by the default_channel configuration variable. |
</doc> |
</config-set> |
<config-help> |
<summary>Show Information About Setting</summary> |
<function>doConfigHelp</function> |
<shortcut>ch</shortcut> |
<options /> |
<doc>[parameter] |
Displays help for a configuration parameter. Without arguments it |
displays help for all configuration parameters. |
</doc> |
</config-help> |
<config-create> |
<summary>Create a Default configuration file</summary> |
<function>doConfigCreate</function> |
<shortcut>coc</shortcut> |
<options> |
<windows> |
<shortopt>w</shortopt> |
<doc>create a config file for a windows install</doc> |
</windows> |
</options> |
<doc><root path> <filename> |
Create a default configuration file with all directory configuration |
variables set to subdirectories of <root path>, and save it as <filename>. |
This is useful especially for creating a configuration file for a remote |
PEAR installation (using the --remoteconfig option of install, upgrade, |
and uninstall). |
</doc> |
</config-create> |
</commands> |
/branches/v1.3-critias/bibliotheque/pear/PEAR/Command/Install.xml |
---|
New file |
0,0 → 1,276 |
<commands version="1.0"> |
<install> |
<summary>Install Package</summary> |
<function>doInstall</function> |
<shortcut>i</shortcut> |
<options> |
<force> |
<shortopt>f</shortopt> |
<doc>will overwrite newer installed packages</doc> |
</force> |
<loose> |
<shortopt>l</shortopt> |
<doc>do not check for recommended dependency version</doc> |
</loose> |
<nodeps> |
<shortopt>n</shortopt> |
<doc>ignore dependencies, install anyway</doc> |
</nodeps> |
<register-only> |
<shortopt>r</shortopt> |
<doc>do not install files, only register the package as installed</doc> |
</register-only> |
<soft> |
<shortopt>s</shortopt> |
<doc>soft install, fail silently, or upgrade if already installed</doc> |
</soft> |
<nobuild> |
<shortopt>B</shortopt> |
<doc>don't build C extensions</doc> |
</nobuild> |
<nocompress> |
<shortopt>Z</shortopt> |
<doc>request uncompressed files when downloading</doc> |
</nocompress> |
<installroot> |
<shortopt>R</shortopt> |
<doc>root directory used when installing files (ala PHP's INSTALL_ROOT), use packagingroot for RPM</doc> |
<arg>DIR</arg> |
</installroot> |
<packagingroot> |
<shortopt>P</shortopt> |
<doc>root directory used when packaging files, like RPM packaging</doc> |
<arg>DIR</arg> |
</packagingroot> |
<ignore-errors> |
<shortopt></shortopt> |
<doc>force install even if there were errors</doc> |
</ignore-errors> |
<alldeps> |
<shortopt>a</shortopt> |
<doc>install all required and optional dependencies</doc> |
</alldeps> |
<onlyreqdeps> |
<shortopt>o</shortopt> |
<doc>install all required dependencies</doc> |
</onlyreqdeps> |
<offline> |
<shortopt>O</shortopt> |
<doc>do not attempt to download any urls or contact channels</doc> |
</offline> |
<pretend> |
<shortopt>p</shortopt> |
<doc>Only list the packages that would be downloaded</doc> |
</pretend> |
</options> |
<doc>[channel/]<package> ... |
Installs one or more PEAR packages. You can specify a package to |
install in four ways: |
"Package-1.0.tgz" : installs from a local file |
"http://example.com/Package-1.0.tgz" : installs from |
anywhere on the net. |
"package.xml" : installs the package described in |
package.xml. Useful for testing, or for wrapping a PEAR package in |
another package manager such as RPM. |
"Package[-version/state][.tar]" : queries your default channel's server |
({config master_server}) and downloads the newest package with |
the preferred quality/state ({config preferred_state}). |
To retrieve Package version 1.1, use "Package-1.1," to retrieve |
Package state beta, use "Package-beta." To retrieve an uncompressed |
file, append .tar (make sure there is no file by the same name first) |
To download a package from another channel, prefix with the channel name like |
"channel/Package" |
More than one package may be specified at once. It is ok to mix these |
four ways of specifying packages. |
</doc> |
</install> |
<upgrade> |
<summary>Upgrade Package</summary> |
<function>doInstall</function> |
<shortcut>up</shortcut> |
<options> |
<channel> |
<shortopt>c</shortopt> |
<doc>upgrade packages from a specific channel</doc> |
<arg>CHAN</arg> |
</channel> |
<force> |
<shortopt>f</shortopt> |
<doc>overwrite newer installed packages</doc> |
</force> |
<loose> |
<shortopt>l</shortopt> |
<doc>do not check for recommended dependency version</doc> |
</loose> |
<nodeps> |
<shortopt>n</shortopt> |
<doc>ignore dependencies, upgrade anyway</doc> |
</nodeps> |
<register-only> |
<shortopt>r</shortopt> |
<doc>do not install files, only register the package as upgraded</doc> |
</register-only> |
<nobuild> |
<shortopt>B</shortopt> |
<doc>don't build C extensions</doc> |
</nobuild> |
<nocompress> |
<shortopt>Z</shortopt> |
<doc>request uncompressed files when downloading</doc> |
</nocompress> |
<installroot> |
<shortopt>R</shortopt> |
<doc>root directory used when installing files (ala PHP's INSTALL_ROOT)</doc> |
<arg>DIR</arg> |
</installroot> |
<ignore-errors> |
<shortopt></shortopt> |
<doc>force install even if there were errors</doc> |
</ignore-errors> |
<alldeps> |
<shortopt>a</shortopt> |
<doc>install all required and optional dependencies</doc> |
</alldeps> |
<onlyreqdeps> |
<shortopt>o</shortopt> |
<doc>install all required dependencies</doc> |
</onlyreqdeps> |
<offline> |
<shortopt>O</shortopt> |
<doc>do not attempt to download any urls or contact channels</doc> |
</offline> |
<pretend> |
<shortopt>p</shortopt> |
<doc>Only list the packages that would be downloaded</doc> |
</pretend> |
</options> |
<doc><package> ... |
Upgrades one or more PEAR packages. See documentation for the |
"install" command for ways to specify a package. |
When upgrading, your package will be updated if the provided new |
package has a higher version number (use the -f option if you need to |
upgrade anyway). |
More than one package may be specified at once. |
</doc> |
</upgrade> |
<upgrade-all> |
<summary>Upgrade All Packages [Deprecated in favor of calling upgrade with no parameters]</summary> |
<function>doUpgradeAll</function> |
<shortcut>ua</shortcut> |
<options> |
<channel> |
<shortopt>c</shortopt> |
<doc>upgrade packages from a specific channel</doc> |
<arg>CHAN</arg> |
</channel> |
<nodeps> |
<shortopt>n</shortopt> |
<doc>ignore dependencies, upgrade anyway</doc> |
</nodeps> |
<register-only> |
<shortopt>r</shortopt> |
<doc>do not install files, only register the package as upgraded</doc> |
</register-only> |
<nobuild> |
<shortopt>B</shortopt> |
<doc>don't build C extensions</doc> |
</nobuild> |
<nocompress> |
<shortopt>Z</shortopt> |
<doc>request uncompressed files when downloading</doc> |
</nocompress> |
<installroot> |
<shortopt>R</shortopt> |
<doc>root directory used when installing files (ala PHP's INSTALL_ROOT), use packagingroot for RPM</doc> |
<arg>DIR</arg> |
</installroot> |
<ignore-errors> |
<shortopt></shortopt> |
<doc>force install even if there were errors</doc> |
</ignore-errors> |
<loose> |
<shortopt></shortopt> |
<doc>do not check for recommended dependency version</doc> |
</loose> |
</options> |
<doc> |
WARNING: This function is deprecated in favor of using the upgrade command with no params |
Upgrades all packages that have a newer release available. Upgrades are |
done only if there is a release available of the state specified in |
"preferred_state" (currently {config preferred_state}), or a state considered |
more stable. |
</doc> |
</upgrade-all> |
<uninstall> |
<summary>Un-install Package</summary> |
<function>doUninstall</function> |
<shortcut>un</shortcut> |
<options> |
<nodeps> |
<shortopt>n</shortopt> |
<doc>ignore dependencies, uninstall anyway</doc> |
</nodeps> |
<register-only> |
<shortopt>r</shortopt> |
<doc>do not remove files, only register the packages as not installed</doc> |
</register-only> |
<installroot> |
<shortopt>R</shortopt> |
<doc>root directory used when installing files (ala PHP's INSTALL_ROOT)</doc> |
<arg>DIR</arg> |
</installroot> |
<ignore-errors> |
<shortopt></shortopt> |
<doc>force install even if there were errors</doc> |
</ignore-errors> |
<offline> |
<shortopt>O</shortopt> |
<doc>do not attempt to uninstall remotely</doc> |
</offline> |
</options> |
<doc>[channel/]<package> ... |
Uninstalls one or more PEAR packages. More than one package may be |
specified at once. Prefix with channel name to uninstall from a |
channel not in your default channel ({config default_channel}) |
</doc> |
</uninstall> |
<bundle> |
<summary>Unpacks a Pecl Package</summary> |
<function>doBundle</function> |
<shortcut>bun</shortcut> |
<options> |
<destination> |
<shortopt>d</shortopt> |
<doc>Optional destination directory for unpacking (defaults to current path or "ext" if exists)</doc> |
<arg>DIR</arg> |
</destination> |
<force> |
<shortopt>f</shortopt> |
<doc>Force the unpacking even if there were errors in the package</doc> |
</force> |
</options> |
<doc><package> |
Unpacks a Pecl Package into the selected location. It will download the |
package if needed. |
</doc> |
</bundle> |
<run-scripts> |
<summary>Run Post-Install Scripts bundled with a package</summary> |
<function>doRunScripts</function> |
<shortcut>rs</shortcut> |
<options /> |
<doc><package> |
Run post-installation scripts in package <package>, if any exist. |
</doc> |
</run-scripts> |
</commands> |
/branches/v1.3-critias/bibliotheque/pear/PEAR/Command/Test.php |
---|
New file |
0,0 → 1,343 |
<?php |
/** |
* PEAR_Command_Test (run-tests) |
* |
* PHP versions 4 and 5 |
* |
* @category pear |
* @package PEAR |
* @author Stig Bakken <ssb@php.net> |
* @author Martin Jansen <mj@php.net> |
* @author Greg Beaver <cellog@php.net> |
* @copyright 1997-2009 The Authors |
* @license http://opensource.org/licenses/bsd-license.php New BSD License |
* @link http://pear.php.net/package/PEAR |
* @since File available since Release 0.1 |
*/ |
/** |
* base class |
*/ |
require_once 'PEAR/Command/Common.php'; |
/** |
* PEAR commands for login/logout |
* |
* @category pear |
* @package PEAR |
* @author Stig Bakken <ssb@php.net> |
* @author Martin Jansen <mj@php.net> |
* @author Greg Beaver <cellog@php.net> |
* @copyright 1997-2009 The Authors |
* @license http://opensource.org/licenses/bsd-license.php New BSD License |
* @version Release: 1.10.1 |
* @link http://pear.php.net/package/PEAR |
* @since Class available since Release 0.1 |
*/ |
class PEAR_Command_Test extends PEAR_Command_Common |
{ |
var $commands = array( |
'run-tests' => array( |
'summary' => 'Run Regression Tests', |
'function' => 'doRunTests', |
'shortcut' => 'rt', |
'options' => array( |
'recur' => array( |
'shortopt' => 'r', |
'doc' => 'Run tests in child directories, recursively. 4 dirs deep maximum', |
), |
'ini' => array( |
'shortopt' => 'i', |
'doc' => 'actual string of settings to pass to php in format " -d setting=blah"', |
'arg' => 'SETTINGS' |
), |
'realtimelog' => array( |
'shortopt' => 'l', |
'doc' => 'Log test runs/results as they are run', |
), |
'quiet' => array( |
'shortopt' => 'q', |
'doc' => 'Only display detail for failed tests', |
), |
'simple' => array( |
'shortopt' => 's', |
'doc' => 'Display simple output for all tests', |
), |
'package' => array( |
'shortopt' => 'p', |
'doc' => 'Treat parameters as installed packages from which to run tests', |
), |
'phpunit' => array( |
'shortopt' => 'u', |
'doc' => 'Search parameters for AllTests.php, and use that to run phpunit-based tests |
If none is found, all .phpt tests will be tried instead.', |
), |
'tapoutput' => array( |
'shortopt' => 't', |
'doc' => 'Output run-tests.log in TAP-compliant format', |
), |
'cgi' => array( |
'shortopt' => 'c', |
'doc' => 'CGI php executable (needed for tests with POST/GET section)', |
'arg' => 'PHPCGI', |
), |
'coverage' => array( |
'shortopt' => 'x', |
'doc' => 'Generate a code coverage report (requires Xdebug 2.0.0+)', |
), |
'showdiff' => array( |
'shortopt' => 'd', |
'doc' => 'Output diff on test failure', |
), |
), |
'doc' => '[testfile|dir ...] |
Run regression tests with PHP\'s regression testing script (run-tests.php).', |
), |
); |
var $output; |
/** |
* PEAR_Command_Test constructor. |
* |
* @access public |
*/ |
function __construct(&$ui, &$config) |
{ |
parent::__construct($ui, $config); |
} |
function doRunTests($command, $options, $params) |
{ |
if (isset($options['phpunit']) && isset($options['tapoutput'])) { |
return $this->raiseError('ERROR: cannot use both --phpunit and --tapoutput at the same time'); |
} |
require_once 'PEAR/Common.php'; |
require_once 'System.php'; |
$log = new PEAR_Common; |
$log->ui = &$this->ui; // slightly hacky, but it will work |
$tests = array(); |
$depth = isset($options['recur']) ? 14 : 1; |
if (!count($params)) { |
$params[] = '.'; |
} |
if (isset($options['package'])) { |
$oldparams = $params; |
$params = array(); |
$reg = &$this->config->getRegistry(); |
foreach ($oldparams as $param) { |
$pname = $reg->parsePackageName($param, $this->config->get('default_channel')); |
if (PEAR::isError($pname)) { |
return $this->raiseError($pname); |
} |
$package = &$reg->getPackage($pname['package'], $pname['channel']); |
if (!$package) { |
return PEAR::raiseError('Unknown package "' . |
$reg->parsedPackageNameToString($pname) . '"'); |
} |
$filelist = $package->getFilelist(); |
foreach ($filelist as $name => $atts) { |
if (isset($atts['role']) && $atts['role'] != 'test') { |
continue; |
} |
if (isset($options['phpunit']) && preg_match('/AllTests\.php\\z/i', $name)) { |
$params[] = $atts['installed_as']; |
continue; |
} elseif (!preg_match('/\.phpt\\z/', $name)) { |
continue; |
} |
$params[] = $atts['installed_as']; |
} |
} |
} |
foreach ($params as $p) { |
if (is_dir($p)) { |
if (isset($options['phpunit'])) { |
$dir = System::find(array($p, '-type', 'f', |
'-maxdepth', $depth, |
'-name', 'AllTests.php')); |
if (count($dir)) { |
foreach ($dir as $p) { |
$p = realpath($p); |
if (!count($tests) || |
(count($tests) && strlen($p) < strlen($tests[0]))) { |
// this is in a higher-level directory, use this one instead. |
$tests = array($p); |
} |
} |
} |
continue; |
} |
$args = array($p, '-type', 'f', '-name', '*.phpt'); |
} else { |
if (isset($options['phpunit'])) { |
if (preg_match('/AllTests\.php\\z/i', $p)) { |
$p = realpath($p); |
if (!count($tests) || |
(count($tests) && strlen($p) < strlen($tests[0]))) { |
// this is in a higher-level directory, use this one instead. |
$tests = array($p); |
} |
} |
continue; |
} |
if (file_exists($p) && preg_match('/\.phpt$/', $p)) { |
$tests[] = $p; |
continue; |
} |
if (!preg_match('/\.phpt\\z/', $p)) { |
$p .= '.phpt'; |
} |
$args = array(dirname($p), '-type', 'f', '-name', $p); |
} |
if (!isset($options['recur'])) { |
$args[] = '-maxdepth'; |
$args[] = 1; |
} |
$dir = System::find($args); |
$tests = array_merge($tests, $dir); |
} |
$ini_settings = ''; |
if (isset($options['ini'])) { |
$ini_settings .= $options['ini']; |
} |
if (isset($_ENV['TEST_PHP_INCLUDE_PATH'])) { |
$ini_settings .= " -d include_path={$_ENV['TEST_PHP_INCLUDE_PATH']}"; |
} |
if ($ini_settings) { |
$this->ui->outputData('Using INI settings: "' . $ini_settings . '"'); |
} |
$skipped = $passed = $failed = array(); |
$tests_count = count($tests); |
$this->ui->outputData('Running ' . $tests_count . ' tests', $command); |
$start = time(); |
if (isset($options['realtimelog']) && file_exists('run-tests.log')) { |
unlink('run-tests.log'); |
} |
if (isset($options['tapoutput'])) { |
$tap = '1..' . $tests_count . "\n"; |
} |
require_once 'PEAR/RunTest.php'; |
$run = new PEAR_RunTest($log, $options); |
$run->tests_count = $tests_count; |
if (isset($options['coverage']) && extension_loaded('xdebug')){ |
$run->xdebug_loaded = true; |
} else { |
$run->xdebug_loaded = false; |
} |
$j = $i = 1; |
foreach ($tests as $t) { |
if (isset($options['realtimelog'])) { |
$fp = @fopen('run-tests.log', 'a'); |
if ($fp) { |
fwrite($fp, "Running test [$i / $tests_count] $t..."); |
fclose($fp); |
} |
} |
PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN); |
if (isset($options['phpunit'])) { |
$result = $run->runPHPUnit($t, $ini_settings); |
} else { |
$result = $run->run($t, $ini_settings, $j); |
} |
PEAR::staticPopErrorHandling(); |
if (PEAR::isError($result)) { |
$this->ui->log($result->getMessage()); |
continue; |
} |
if (isset($options['tapoutput'])) { |
$tap .= $result[0] . ' ' . $i . $result[1] . "\n"; |
continue; |
} |
if (isset($options['realtimelog'])) { |
$fp = @fopen('run-tests.log', 'a'); |
if ($fp) { |
fwrite($fp, "$result\n"); |
fclose($fp); |
} |
} |
if ($result == 'FAILED') { |
$failed[] = $t; |
} |
if ($result == 'PASSED') { |
$passed[] = $t; |
} |
if ($result == 'SKIPPED') { |
$skipped[] = $t; |
} |
$j++; |
} |
$total = date('i:s', time() - $start); |
if (isset($options['tapoutput'])) { |
$fp = @fopen('run-tests.log', 'w'); |
if ($fp) { |
fwrite($fp, $tap, strlen($tap)); |
fclose($fp); |
$this->ui->outputData('wrote TAP-format log to "' .realpath('run-tests.log') . |
'"', $command); |
} |
} else { |
if (count($failed)) { |
$output = "TOTAL TIME: $total\n"; |
$output .= count($passed) . " PASSED TESTS\n"; |
$output .= count($skipped) . " SKIPPED TESTS\n"; |
$output .= count($failed) . " FAILED TESTS:\n"; |
foreach ($failed as $failure) { |
$output .= $failure . "\n"; |
} |
$mode = isset($options['realtimelog']) ? 'a' : 'w'; |
$fp = @fopen('run-tests.log', $mode); |
if ($fp) { |
fwrite($fp, $output, strlen($output)); |
fclose($fp); |
$this->ui->outputData('wrote log to "' . realpath('run-tests.log') . '"', $command); |
} |
} elseif (file_exists('run-tests.log') && !is_dir('run-tests.log')) { |
@unlink('run-tests.log'); |
} |
} |
$this->ui->outputData('TOTAL TIME: ' . $total); |
$this->ui->outputData(count($passed) . ' PASSED TESTS', $command); |
$this->ui->outputData(count($skipped) . ' SKIPPED TESTS', $command); |
if (count($failed)) { |
$this->ui->outputData(count($failed) . ' FAILED TESTS:', $command); |
foreach ($failed as $failure) { |
$this->ui->outputData($failure, $command); |
} |
} |
if (count($failed) == 0) { |
return true; |
} |
return $this->raiseError('Some tests failed'); |
} |
} |
/branches/v1.3-critias/bibliotheque/pear/PEAR/Command/Pickle.xml |
---|
New file |
0,0 → 1,36 |
<commands version="1.0"> |
<pickle> |
<summary>Build PECL Package</summary> |
<function>doPackage</function> |
<shortcut>pi</shortcut> |
<options> |
<nocompress> |
<shortopt>Z</shortopt> |
<doc>Do not gzip the package file</doc> |
</nocompress> |
<showname> |
<shortopt>n</shortopt> |
<doc>Print the name of the packaged file.</doc> |
</showname> |
</options> |
<doc>[descfile] |
Creates a PECL package from its package2.xml file. |
An automatic conversion will be made to a package.xml 1.0 and written out to |
disk in the current directory as "package.xml". Note that |
only simple package.xml 2.0 will be converted. package.xml 2.0 with: |
- dependency types other than required/optional PECL package/ext/php/pearinstaller |
- more than one extsrcrelease or zendextsrcrelease |
- zendextbinrelease, extbinrelease, phprelease, or bundle release type |
- dependency groups |
- ignore tags in release filelist |
- tasks other than replace |
- custom roles |
will cause pickle to fail, and output an error message. If your package2.xml |
uses any of these features, you are best off using PEAR_PackageFileManager to |
generate both package.xml. |
</doc> |
</pickle> |
</commands> |
/branches/v1.3-critias/bibliotheque/pear/PEAR/Command/Registry.xml |
---|
New file |
0,0 → 1,58 |
<commands version="1.0"> |
<list> |
<summary>List Installed Packages In The Default Channel</summary> |
<function>doList</function> |
<shortcut>l</shortcut> |
<options> |
<channel> |
<shortopt>c</shortopt> |
<doc>list installed packages from this channel</doc> |
<arg>CHAN</arg> |
</channel> |
<allchannels> |
<shortopt>a</shortopt> |
<doc>list installed packages from all channels</doc> |
</allchannels> |
<channelinfo> |
<shortopt>i</shortopt> |
<doc>output fully channel-aware data, even on failure</doc> |
</channelinfo> |
</options> |
<doc><package> |
If invoked without parameters, this command lists the PEAR packages |
installed in your php_dir ({config php_dir}). With a parameter, it |
lists the files in a package. |
</doc> |
</list> |
<list-files> |
<summary>List Files In Installed Package</summary> |
<function>doFileList</function> |
<shortcut>fl</shortcut> |
<options /> |
<doc><package> |
List the files in an installed package. |
</doc> |
</list-files> |
<shell-test> |
<summary>Shell Script Test</summary> |
<function>doShellTest</function> |
<shortcut>st</shortcut> |
<options /> |
<doc><package> [[relation] version] |
Tests if a package is installed in the system. Will exit(1) if it is not. |
<relation> The version comparison operator. One of: |
<, lt, <=, le, >, gt, >=, ge, ==, =, eq, !=, <>, ne |
<version> The version to compare with |
</doc> |
</shell-test> |
<info> |
<summary>Display information about a package</summary> |
<function>doInfo</function> |
<shortcut>in</shortcut> |
<options /> |
<doc><package> |
Displays information about a package. The package argument may be a |
local package file, an URL to a package file, or the name of an |
installed package.</doc> |
</info> |
</commands> |
/branches/v1.3-critias/bibliotheque/pear/PEAR/Command/Mirror.xml |
---|
New file |
0,0 → 1,18 |
<commands version="1.0"> |
<download-all> |
<summary>Downloads each available package from the default channel</summary> |
<function>doDownloadAll</function> |
<shortcut>da</shortcut> |
<options> |
<channel> |
<shortopt>c</shortopt> |
<doc>specify a channel other than the default channel</doc> |
<arg>CHAN</arg> |
</channel> |
</options> |
<doc> |
Requests a list of available packages from the default channel ({config default_channel}) |
and downloads them to current working directory. Note: only |
packages within preferred_state ({config preferred_state}) will be downloaded</doc> |
</download-all> |
</commands> |
/branches/v1.3-critias/bibliotheque/pear/PEAR/Common.php |
---|
New file |
0,0 → 1,838 |
<?php |
/** |
* PEAR_Common, the base class for the PEAR Installer |
* |
* PHP versions 4 and 5 |
* |
* @category pear |
* @package PEAR |
* @author Stig Bakken <ssb@php.net> |
* @author Tomas V. V. Cox <cox@idecnet.com> |
* @author Greg Beaver <cellog@php.net> |
* @copyright 1997-2009 The Authors |
* @license http://opensource.org/licenses/bsd-license.php New BSD License |
* @link http://pear.php.net/package/PEAR |
* @since File available since Release 0.1.0 |
* @deprecated File deprecated since Release 1.4.0a1 |
*/ |
/** |
* Include error handling |
*/ |
require_once 'PEAR.php'; |
/** |
* PEAR_Common error when an invalid PHP file is passed to PEAR_Common::analyzeSourceCode() |
*/ |
define('PEAR_COMMON_ERROR_INVALIDPHP', 1); |
define('_PEAR_COMMON_PACKAGE_NAME_PREG', '[A-Za-z][a-zA-Z0-9_]+'); |
define('PEAR_COMMON_PACKAGE_NAME_PREG', '/^' . _PEAR_COMMON_PACKAGE_NAME_PREG . '\\z/'); |
// this should allow: 1, 1.0, 1.0RC1, 1.0dev, 1.0dev123234234234, 1.0a1, 1.0b1, 1.0pl1 |
define('_PEAR_COMMON_PACKAGE_VERSION_PREG', '\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?'); |
define('PEAR_COMMON_PACKAGE_VERSION_PREG', '/^' . _PEAR_COMMON_PACKAGE_VERSION_PREG . '\\z/i'); |
// XXX far from perfect :-) |
define('_PEAR_COMMON_PACKAGE_DOWNLOAD_PREG', '(' . _PEAR_COMMON_PACKAGE_NAME_PREG . |
')(-([.0-9a-zA-Z]+))?'); |
define('PEAR_COMMON_PACKAGE_DOWNLOAD_PREG', '/^' . _PEAR_COMMON_PACKAGE_DOWNLOAD_PREG . |
'\\z/'); |
define('_PEAR_CHANNELS_NAME_PREG', '[A-Za-z][a-zA-Z0-9\.]+'); |
define('PEAR_CHANNELS_NAME_PREG', '/^' . _PEAR_CHANNELS_NAME_PREG . '\\z/'); |
// this should allow any dns or IP address, plus a path - NO UNDERSCORES ALLOWED |
define('_PEAR_CHANNELS_SERVER_PREG', '[a-zA-Z0-9\-]+(?:\.[a-zA-Z0-9\-]+)*(\/[a-zA-Z0-9\-]+)*'); |
define('PEAR_CHANNELS_SERVER_PREG', '/^' . _PEAR_CHANNELS_SERVER_PREG . '\\z/i'); |
define('_PEAR_CHANNELS_PACKAGE_PREG', '(' ._PEAR_CHANNELS_SERVER_PREG . ')\/(' |
. _PEAR_COMMON_PACKAGE_NAME_PREG . ')'); |
define('PEAR_CHANNELS_PACKAGE_PREG', '/^' . _PEAR_CHANNELS_PACKAGE_PREG . '\\z/i'); |
define('_PEAR_COMMON_CHANNEL_DOWNLOAD_PREG', '(' . _PEAR_CHANNELS_NAME_PREG . ')::(' |
. _PEAR_COMMON_PACKAGE_NAME_PREG . ')(-([.0-9a-zA-Z]+))?'); |
define('PEAR_COMMON_CHANNEL_DOWNLOAD_PREG', '/^' . _PEAR_COMMON_CHANNEL_DOWNLOAD_PREG . '\\z/'); |
/** |
* List of temporary files and directories registered by |
* PEAR_Common::addTempFile(). |
* @var array |
*/ |
$GLOBALS['_PEAR_Common_tempfiles'] = array(); |
/** |
* Valid maintainer roles |
* @var array |
*/ |
$GLOBALS['_PEAR_Common_maintainer_roles'] = array('lead','developer','contributor','helper'); |
/** |
* Valid release states |
* @var array |
*/ |
$GLOBALS['_PEAR_Common_release_states'] = array('alpha','beta','stable','snapshot','devel'); |
/** |
* Valid dependency types |
* @var array |
*/ |
$GLOBALS['_PEAR_Common_dependency_types'] = array('pkg','ext','php','prog','ldlib','rtlib','os','websrv','sapi'); |
/** |
* Valid dependency relations |
* @var array |
*/ |
$GLOBALS['_PEAR_Common_dependency_relations'] = array('has','eq','lt','le','gt','ge','not', 'ne'); |
/** |
* Valid file roles |
* @var array |
*/ |
$GLOBALS['_PEAR_Common_file_roles'] = array('php','ext','test','doc','data','src','script'); |
/** |
* Valid replacement types |
* @var array |
*/ |
$GLOBALS['_PEAR_Common_replacement_types'] = array('php-const', 'pear-config', 'package-info'); |
/** |
* Valid "provide" types |
* @var array |
*/ |
$GLOBALS['_PEAR_Common_provide_types'] = array('ext', 'prog', 'class', 'function', 'feature', 'api'); |
/** |
* Valid "provide" types |
* @var array |
*/ |
$GLOBALS['_PEAR_Common_script_phases'] = array('pre-install', 'post-install', 'pre-uninstall', 'post-uninstall', 'pre-build', 'post-build', 'pre-configure', 'post-configure', 'pre-setup', 'post-setup'); |
/** |
* Class providing common functionality for PEAR administration classes. |
* @category pear |
* @package PEAR |
* @author Stig Bakken <ssb@php.net> |
* @author Tomas V. V. Cox <cox@idecnet.com> |
* @author Greg Beaver <cellog@php.net> |
* @copyright 1997-2009 The Authors |
* @license http://opensource.org/licenses/bsd-license.php New BSD License |
* @version Release: 1.10.1 |
* @link http://pear.php.net/package/PEAR |
* @since Class available since Release 1.4.0a1 |
* @deprecated This class will disappear, and its components will be spread |
* into smaller classes, like the AT&T breakup, as of Release 1.4.0a1 |
*/ |
class PEAR_Common extends PEAR |
{ |
/** |
* User Interface object (PEAR_Frontend_* class). If null, |
* the log() method uses print. |
* @var object |
*/ |
var $ui = null; |
/** |
* Configuration object (PEAR_Config). |
* @var PEAR_Config |
*/ |
var $config = null; |
/** stack of elements, gives some sort of XML context */ |
var $element_stack = array(); |
/** name of currently parsed XML element */ |
var $current_element; |
/** array of attributes of the currently parsed XML element */ |
var $current_attributes = array(); |
/** assoc with information about a package */ |
var $pkginfo = array(); |
var $current_path = null; |
/** |
* Flag variable used to mark a valid package file |
* @var boolean |
* @access private |
*/ |
var $_validPackageFile; |
/** |
* PEAR_Common constructor |
* |
* @access public |
*/ |
function __construct() |
{ |
parent::__construct(); |
$this->config = &PEAR_Config::singleton(); |
$this->debug = $this->config->get('verbose'); |
} |
/** |
* PEAR_Common destructor |
* |
* @access private |
*/ |
function _PEAR_Common() |
{ |
// doesn't work due to bug #14744 |
//$tempfiles = $this->_tempfiles; |
$tempfiles =& $GLOBALS['_PEAR_Common_tempfiles']; |
while ($file = array_shift($tempfiles)) { |
if (@is_dir($file)) { |
if (!class_exists('System')) { |
require_once 'System.php'; |
} |
System::rm(array('-rf', $file)); |
} elseif (file_exists($file)) { |
unlink($file); |
} |
} |
} |
/** |
* Register a temporary file or directory. When the destructor is |
* executed, all registered temporary files and directories are |
* removed. |
* |
* @param string $file name of file or directory |
* |
* @return void |
* |
* @access public |
*/ |
function addTempFile($file) |
{ |
if (!class_exists('PEAR_Frontend')) { |
require_once 'PEAR/Frontend.php'; |
} |
PEAR_Frontend::addTempFile($file); |
} |
/** |
* Wrapper to System::mkDir(), creates a directory as well as |
* any necessary parent directories. |
* |
* @param string $dir directory name |
* |
* @return bool TRUE on success, or a PEAR error |
* |
* @access public |
*/ |
function mkDirHier($dir) |
{ |
// Only used in Installer - move it there ? |
$this->log(2, "+ create dir $dir"); |
if (!class_exists('System')) { |
require_once 'System.php'; |
} |
return System::mkDir(array('-p', $dir)); |
} |
/** |
* Logging method. |
* |
* @param int $level log level (0 is quiet, higher is noisier) |
* @param string $msg message to write to the log |
* |
* @return void |
*/ |
public function log($level, $msg, $append_crlf = true) |
{ |
if ($this->debug >= $level) { |
if (!class_exists('PEAR_Frontend')) { |
require_once 'PEAR/Frontend.php'; |
} |
$ui = &PEAR_Frontend::singleton(); |
if (is_a($ui, 'PEAR_Frontend')) { |
$ui->log($msg, $append_crlf); |
} else { |
print "$msg\n"; |
} |
} |
} |
/** |
* Create and register a temporary directory. |
* |
* @param string $tmpdir (optional) Directory to use as tmpdir. |
* Will use system defaults (for example |
* /tmp or c:\windows\temp) if not specified |
* |
* @return string name of created directory |
* |
* @access public |
*/ |
function mkTempDir($tmpdir = '') |
{ |
$topt = $tmpdir ? array('-t', $tmpdir) : array(); |
$topt = array_merge($topt, array('-d', 'pear')); |
if (!class_exists('System')) { |
require_once 'System.php'; |
} |
if (!$tmpdir = System::mktemp($topt)) { |
return false; |
} |
$this->addTempFile($tmpdir); |
return $tmpdir; |
} |
/** |
* Set object that represents the frontend to be used. |
* |
* @param object Reference of the frontend object |
* @return void |
* @access public |
*/ |
function setFrontendObject(&$ui) |
{ |
$this->ui = &$ui; |
} |
/** |
* Return an array containing all of the states that are more stable than |
* or equal to the passed in state |
* |
* @param string Release state |
* @param boolean Determines whether to include $state in the list |
* @return false|array False if $state is not a valid release state |
*/ |
function betterStates($state, $include = false) |
{ |
static $states = array('snapshot', 'devel', 'alpha', 'beta', 'stable'); |
$i = array_search($state, $states); |
if ($i === false) { |
return false; |
} |
if ($include) { |
$i--; |
} |
return array_slice($states, $i + 1); |
} |
/** |
* Get the valid roles for a PEAR package maintainer |
* |
* @return array |
*/ |
public static function getUserRoles() |
{ |
return $GLOBALS['_PEAR_Common_maintainer_roles']; |
} |
/** |
* Get the valid package release states of packages |
* |
* @return array |
*/ |
public static function getReleaseStates() |
{ |
return $GLOBALS['_PEAR_Common_release_states']; |
} |
/** |
* Get the implemented dependency types (php, ext, pkg etc.) |
* |
* @return array |
*/ |
public static function getDependencyTypes() |
{ |
return $GLOBALS['_PEAR_Common_dependency_types']; |
} |
/** |
* Get the implemented dependency relations (has, lt, ge etc.) |
* |
* @return array |
*/ |
public static function getDependencyRelations() |
{ |
return $GLOBALS['_PEAR_Common_dependency_relations']; |
} |
/** |
* Get the implemented file roles |
* |
* @return array |
*/ |
public static function getFileRoles() |
{ |
return $GLOBALS['_PEAR_Common_file_roles']; |
} |
/** |
* Get the implemented file replacement types in |
* |
* @return array |
*/ |
public static function getReplacementTypes() |
{ |
return $GLOBALS['_PEAR_Common_replacement_types']; |
} |
/** |
* Get the implemented file replacement types in |
* |
* @return array |
*/ |
public static function getProvideTypes() |
{ |
return $GLOBALS['_PEAR_Common_provide_types']; |
} |
/** |
* Get the implemented file replacement types in |
* |
* @return array |
*/ |
public static function getScriptPhases() |
{ |
return $GLOBALS['_PEAR_Common_script_phases']; |
} |
/** |
* Test whether a string contains a valid package name. |
* |
* @param string $name the package name to test |
* |
* @return bool |
* |
* @access public |
*/ |
function validPackageName($name) |
{ |
return (bool)preg_match(PEAR_COMMON_PACKAGE_NAME_PREG, $name); |
} |
/** |
* Test whether a string contains a valid package version. |
* |
* @param string $ver the package version to test |
* |
* @return bool |
* |
* @access public |
*/ |
function validPackageVersion($ver) |
{ |
return (bool)preg_match(PEAR_COMMON_PACKAGE_VERSION_PREG, $ver); |
} |
/** |
* @param string $path relative or absolute include path |
* @return boolean |
*/ |
public static function isIncludeable($path) |
{ |
if (file_exists($path) && is_readable($path)) { |
return true; |
} |
$ipath = explode(PATH_SEPARATOR, ini_get('include_path')); |
foreach ($ipath as $include) { |
$test = realpath($include . DIRECTORY_SEPARATOR . $path); |
if (file_exists($test) && is_readable($test)) { |
return true; |
} |
} |
return false; |
} |
function _postProcessChecks($pf) |
{ |
if (!PEAR::isError($pf)) { |
return $this->_postProcessValidPackagexml($pf); |
} |
$errs = $pf->getUserinfo(); |
if (is_array($errs)) { |
foreach ($errs as $error) { |
$e = $this->raiseError($error['message'], $error['code'], null, null, $error); |
} |
} |
return $pf; |
} |
/** |
* Returns information about a package file. Expects the name of |
* a gzipped tar file as input. |
* |
* @param string $file name of .tgz file |
* |
* @return array array with package information |
* |
* @access public |
* @deprecated use PEAR_PackageFile->fromTgzFile() instead |
* |
*/ |
function infoFromTgzFile($file) |
{ |
$packagefile = new PEAR_PackageFile($this->config); |
$pf = &$packagefile->fromTgzFile($file, PEAR_VALIDATE_NORMAL); |
return $this->_postProcessChecks($pf); |
} |
/** |
* Returns information about a package file. Expects the name of |
* a package xml file as input. |
* |
* @param string $descfile name of package xml file |
* |
* @return array array with package information |
* |
* @access public |
* @deprecated use PEAR_PackageFile->fromPackageFile() instead |
* |
*/ |
function infoFromDescriptionFile($descfile) |
{ |
$packagefile = new PEAR_PackageFile($this->config); |
$pf = &$packagefile->fromPackageFile($descfile, PEAR_VALIDATE_NORMAL); |
return $this->_postProcessChecks($pf); |
} |
/** |
* Returns information about a package file. Expects the contents |
* of a package xml file as input. |
* |
* @param string $data contents of package.xml file |
* |
* @return array array with package information |
* |
* @access public |
* @deprecated use PEAR_PackageFile->fromXmlstring() instead |
* |
*/ |
function infoFromString($data) |
{ |
$packagefile = new PEAR_PackageFile($this->config); |
$pf = &$packagefile->fromXmlString($data, PEAR_VALIDATE_NORMAL, false); |
return $this->_postProcessChecks($pf); |
} |
/** |
* @param PEAR_PackageFile_v1|PEAR_PackageFile_v2 |
* @return array |
*/ |
function _postProcessValidPackagexml(&$pf) |
{ |
if (!is_a($pf, 'PEAR_PackageFile_v2')) { |
$this->pkginfo = $pf->toArray(); |
return $this->pkginfo; |
} |
// sort of make this into a package.xml 1.0-style array |
// changelog is not converted to old format. |
$arr = $pf->toArray(true); |
$arr = array_merge($arr, $arr['old']); |
unset($arr['old'], $arr['xsdversion'], $arr['contents'], $arr['compatible'], |
$arr['channel'], $arr['uri'], $arr['dependencies'], $arr['phprelease'], |
$arr['extsrcrelease'], $arr['zendextsrcrelease'], $arr['extbinrelease'], |
$arr['zendextbinrelease'], $arr['bundle'], $arr['lead'], $arr['developer'], |
$arr['helper'], $arr['contributor']); |
$arr['filelist'] = $pf->getFilelist(); |
$this->pkginfo = $arr; |
return $arr; |
} |
/** |
* Returns package information from different sources |
* |
* This method is able to extract information about a package |
* from a .tgz archive or from a XML package definition file. |
* |
* @access public |
* @param string Filename of the source ('package.xml', '<package>.tgz') |
* @return string |
* @deprecated use PEAR_PackageFile->fromAnyFile() instead |
*/ |
function infoFromAny($info) |
{ |
if (is_string($info) && file_exists($info)) { |
$packagefile = new PEAR_PackageFile($this->config); |
$pf = &$packagefile->fromAnyFile($info, PEAR_VALIDATE_NORMAL); |
if (PEAR::isError($pf)) { |
$errs = $pf->getUserinfo(); |
if (is_array($errs)) { |
foreach ($errs as $error) { |
$e = $this->raiseError($error['message'], $error['code'], null, null, $error); |
} |
} |
return $pf; |
} |
return $this->_postProcessValidPackagexml($pf); |
} |
return $info; |
} |
/** |
* Return an XML document based on the package info (as returned |
* by the PEAR_Common::infoFrom* methods). |
* |
* @param array $pkginfo package info |
* |
* @return string XML data |
* |
* @access public |
* @deprecated use a PEAR_PackageFile_v* object's generator instead |
*/ |
function xmlFromInfo($pkginfo) |
{ |
$config = &PEAR_Config::singleton(); |
$packagefile = new PEAR_PackageFile($config); |
$pf = &$packagefile->fromArray($pkginfo); |
$gen = &$pf->getDefaultGenerator(); |
return $gen->toXml(PEAR_VALIDATE_PACKAGING); |
} |
/** |
* Validate XML package definition file. |
* |
* @param string $info Filename of the package archive or of the |
* package definition file |
* @param array $errors Array that will contain the errors |
* @param array $warnings Array that will contain the warnings |
* @param string $dir_prefix (optional) directory where source files |
* may be found, or empty if they are not available |
* @access public |
* @return boolean |
* @deprecated use the validation of PEAR_PackageFile objects |
*/ |
function validatePackageInfo($info, &$errors, &$warnings, $dir_prefix = '') |
{ |
$config = &PEAR_Config::singleton(); |
$packagefile = new PEAR_PackageFile($config); |
PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN); |
if (strpos($info, '<?xml') !== false) { |
$pf = &$packagefile->fromXmlString($info, PEAR_VALIDATE_NORMAL, ''); |
} else { |
$pf = &$packagefile->fromAnyFile($info, PEAR_VALIDATE_NORMAL); |
} |
PEAR::staticPopErrorHandling(); |
if (PEAR::isError($pf)) { |
$errs = $pf->getUserinfo(); |
if (is_array($errs)) { |
foreach ($errs as $error) { |
if ($error['level'] == 'error') { |
$errors[] = $error['message']; |
} else { |
$warnings[] = $error['message']; |
} |
} |
} |
return false; |
} |
return true; |
} |
/** |
* Build a "provides" array from data returned by |
* analyzeSourceCode(). The format of the built array is like |
* this: |
* |
* array( |
* 'class;MyClass' => 'array('type' => 'class', 'name' => 'MyClass'), |
* ... |
* ) |
* |
* |
* @param array $srcinfo array with information about a source file |
* as returned by the analyzeSourceCode() method. |
* |
* @return void |
* |
* @access public |
* |
*/ |
function buildProvidesArray($srcinfo) |
{ |
$file = basename($srcinfo['source_file']); |
$pn = ''; |
if (isset($this->_packageName)) { |
$pn = $this->_packageName; |
} |
$pnl = strlen($pn); |
foreach ($srcinfo['declared_classes'] as $class) { |
$key = "class;$class"; |
if (isset($this->pkginfo['provides'][$key])) { |
continue; |
} |
$this->pkginfo['provides'][$key] = |
array('file'=> $file, 'type' => 'class', 'name' => $class); |
if (isset($srcinfo['inheritance'][$class])) { |
$this->pkginfo['provides'][$key]['extends'] = |
$srcinfo['inheritance'][$class]; |
} |
} |
foreach ($srcinfo['declared_methods'] as $class => $methods) { |
foreach ($methods as $method) { |
$function = "$class::$method"; |
$key = "function;$function"; |
if ($method{0} == '_' || !strcasecmp($method, $class) || |
isset($this->pkginfo['provides'][$key])) { |
continue; |
} |
$this->pkginfo['provides'][$key] = |
array('file'=> $file, 'type' => 'function', 'name' => $function); |
} |
} |
foreach ($srcinfo['declared_functions'] as $function) { |
$key = "function;$function"; |
if ($function{0} == '_' || isset($this->pkginfo['provides'][$key])) { |
continue; |
} |
if (!strstr($function, '::') && strncasecmp($function, $pn, $pnl)) { |
$warnings[] = "in1 " . $file . ": function \"$function\" not prefixed with package name \"$pn\""; |
} |
$this->pkginfo['provides'][$key] = |
array('file'=> $file, 'type' => 'function', 'name' => $function); |
} |
} |
/** |
* Analyze the source code of the given PHP file |
* |
* @param string Filename of the PHP file |
* @return mixed |
* @access public |
*/ |
function analyzeSourceCode($file) |
{ |
if (!class_exists('PEAR_PackageFile_v2_Validator')) { |
require_once 'PEAR/PackageFile/v2/Validator.php'; |
} |
$a = new PEAR_PackageFile_v2_Validator; |
return $a->analyzeSourceCode($file); |
} |
function detectDependencies($any, $status_callback = null) |
{ |
if (!function_exists("token_get_all")) { |
return false; |
} |
if (PEAR::isError($info = $this->infoFromAny($any))) { |
return $this->raiseError($info); |
} |
if (!is_array($info)) { |
return false; |
} |
$deps = array(); |
$used_c = $decl_c = $decl_f = $decl_m = array(); |
foreach ($info['filelist'] as $file => $fa) { |
$tmp = $this->analyzeSourceCode($file); |
$used_c = @array_merge($used_c, $tmp['used_classes']); |
$decl_c = @array_merge($decl_c, $tmp['declared_classes']); |
$decl_f = @array_merge($decl_f, $tmp['declared_functions']); |
$decl_m = @array_merge($decl_m, $tmp['declared_methods']); |
$inheri = @array_merge($inheri, $tmp['inheritance']); |
} |
$used_c = array_unique($used_c); |
$decl_c = array_unique($decl_c); |
$undecl_c = array_diff($used_c, $decl_c); |
return array('used_classes' => $used_c, |
'declared_classes' => $decl_c, |
'declared_methods' => $decl_m, |
'declared_functions' => $decl_f, |
'undeclared_classes' => $undecl_c, |
'inheritance' => $inheri, |
); |
} |
/** |
* Download a file through HTTP. Considers suggested file name in |
* Content-disposition: header and can run a callback function for |
* different events. The callback will be called with two |
* parameters: the callback type, and parameters. The implemented |
* callback types are: |
* |
* 'setup' called at the very beginning, parameter is a UI object |
* that should be used for all output |
* 'message' the parameter is a string with an informational message |
* 'saveas' may be used to save with a different file name, the |
* parameter is the filename that is about to be used. |
* If a 'saveas' callback returns a non-empty string, |
* that file name will be used as the filename instead. |
* Note that $save_dir will not be affected by this, only |
* the basename of the file. |
* 'start' download is starting, parameter is number of bytes |
* that are expected, or -1 if unknown |
* 'bytesread' parameter is the number of bytes read so far |
* 'done' download is complete, parameter is the total number |
* of bytes read |
* 'connfailed' if the TCP connection fails, this callback is called |
* with array(host,port,errno,errmsg) |
* 'writefailed' if writing to disk fails, this callback is called |
* with array(destfile,errmsg) |
* |
* If an HTTP proxy has been configured (http_proxy PEAR_Config |
* setting), the proxy will be used. |
* |
* @param string $url the URL to download |
* @param object $ui PEAR_Frontend_* instance |
* @param object $config PEAR_Config instance |
* @param string $save_dir (optional) directory to save file in |
* @param mixed $callback (optional) function/method to call for status |
* updates |
* @param false|string|array $lastmodified header values to check against |
* for caching |
* use false to return the header |
* values from this download |
* @param false|array $accept Accept headers to send |
* @param false|string $channel Channel to use for retrieving |
* authentication |
* |
* @return mixed Returns the full path of the downloaded file or a PEAR |
* error on failure. If the error is caused by |
* socket-related errors, the error object will |
* have the fsockopen error code available through |
* getCode(). If caching is requested, then return the header |
* values. |
* If $lastmodified was given and the there are no changes, |
* boolean false is returned. |
* |
* @access public |
*/ |
function downloadHttp( |
$url, &$ui, $save_dir = '.', $callback = null, $lastmodified = null, |
$accept = false, $channel = false |
) { |
if (!class_exists('PEAR_Downloader')) { |
require_once 'PEAR/Downloader.php'; |
} |
return PEAR_Downloader::_downloadHttp( |
$this, $url, $ui, $save_dir, $callback, $lastmodified, |
$accept, $channel |
); |
} |
} |
require_once 'PEAR/Config.php'; |
require_once 'PEAR/PackageFile.php'; |
/branches/v1.3-critias/bibliotheque/pear/PEAR/Validate.php |
---|
New file |
0,0 → 1,625 |
<?php |
/** |
* PEAR_Validate |
* |
* PHP versions 4 and 5 |
* |
* @category pear |
* @package PEAR |
* @author Greg Beaver <cellog@php.net> |
* @copyright 1997-2009 The Authors |
* @license http://opensource.org/licenses/bsd-license.php New BSD License |
* @link http://pear.php.net/package/PEAR |
* @since File available since Release 1.4.0a1 |
*/ |
/**#@+ |
* Constants for install stage |
*/ |
define('PEAR_VALIDATE_INSTALLING', 1); |
define('PEAR_VALIDATE_UNINSTALLING', 2); // this is not bit-mapped like the others |
define('PEAR_VALIDATE_NORMAL', 3); |
define('PEAR_VALIDATE_DOWNLOADING', 4); // this is not bit-mapped like the others |
define('PEAR_VALIDATE_PACKAGING', 7); |
/**#@-*/ |
require_once 'PEAR/Common.php'; |
require_once 'PEAR/Validator/PECL.php'; |
/** |
* Validation class for package.xml - channel-level advanced validation |
* @category pear |
* @package PEAR |
* @author Greg Beaver <cellog@php.net> |
* @copyright 1997-2009 The Authors |
* @license http://opensource.org/licenses/bsd-license.php New BSD License |
* @version Release: 1.10.1 |
* @link http://pear.php.net/package/PEAR |
* @since Class available since Release 1.4.0a1 |
*/ |
class PEAR_Validate |
{ |
var $packageregex = _PEAR_COMMON_PACKAGE_NAME_PREG; |
/** |
* @var PEAR_PackageFile_v1|PEAR_PackageFile_v2 |
*/ |
var $_packagexml; |
/** |
* @var int one of the PEAR_VALIDATE_* constants |
*/ |
var $_state = PEAR_VALIDATE_NORMAL; |
/** |
* Format: ('error' => array('field' => name, 'reason' => reason), 'warning' => same) |
* @var array |
* @access private |
*/ |
var $_failures = array('error' => array(), 'warning' => array()); |
/** |
* Override this method to handle validation of normal package names |
* @param string |
* @return bool |
* @access protected |
*/ |
function _validPackageName($name) |
{ |
return (bool) preg_match('/^' . $this->packageregex . '\\z/', $name); |
} |
/** |
* @param string package name to validate |
* @param string name of channel-specific validation package |
* @final |
*/ |
function validPackageName($name, $validatepackagename = false) |
{ |
if ($validatepackagename) { |
if (strtolower($name) == strtolower($validatepackagename)) { |
return (bool) preg_match('/^[a-zA-Z0-9_]+(?:\.[a-zA-Z0-9_]+)*\\z/', $name); |
} |
} |
return $this->_validPackageName($name); |
} |
/** |
* This validates a bundle name, and bundle names must conform |
* to the PEAR naming convention, so the method is final and static. |
* @param string |
* @final |
*/ |
public static function validGroupName($name) |
{ |
return (bool) preg_match('/^' . _PEAR_COMMON_PACKAGE_NAME_PREG . '\\z/', $name); |
} |
/** |
* Determine whether $state represents a valid stability level |
* @param string |
* @return bool |
* @final |
*/ |
public static function validState($state) |
{ |
return in_array($state, array('snapshot', 'devel', 'alpha', 'beta', 'stable')); |
} |
/** |
* Get a list of valid stability levels |
* @return array |
* @final |
*/ |
public static function getValidStates() |
{ |
return array('snapshot', 'devel', 'alpha', 'beta', 'stable'); |
} |
/** |
* Determine whether a version is a properly formatted version number that can be used |
* by version_compare |
* @param string |
* @return bool |
* @final |
*/ |
public static function validVersion($ver) |
{ |
return (bool) preg_match(PEAR_COMMON_PACKAGE_VERSION_PREG, $ver); |
} |
/** |
* @param PEAR_PackageFile_v1|PEAR_PackageFile_v2 |
*/ |
function setPackageFile(&$pf) |
{ |
$this->_packagexml = &$pf; |
} |
/** |
* @access private |
*/ |
function _addFailure($field, $reason) |
{ |
$this->_failures['errors'][] = array('field' => $field, 'reason' => $reason); |
} |
/** |
* @access private |
*/ |
function _addWarning($field, $reason) |
{ |
$this->_failures['warnings'][] = array('field' => $field, 'reason' => $reason); |
} |
function getFailures() |
{ |
$failures = $this->_failures; |
$this->_failures = array('warnings' => array(), 'errors' => array()); |
return $failures; |
} |
/** |
* @param int one of the PEAR_VALIDATE_* constants |
*/ |
function validate($state = null) |
{ |
if (!isset($this->_packagexml)) { |
return false; |
} |
if ($state !== null) { |
$this->_state = $state; |
} |
$this->_failures = array('warnings' => array(), 'errors' => array()); |
$this->validatePackageName(); |
$this->validateVersion(); |
$this->validateMaintainers(); |
$this->validateDate(); |
$this->validateSummary(); |
$this->validateDescription(); |
$this->validateLicense(); |
$this->validateNotes(); |
if ($this->_packagexml->getPackagexmlVersion() == '1.0') { |
$this->validateState(); |
$this->validateFilelist(); |
} elseif ($this->_packagexml->getPackagexmlVersion() == '2.0' || |
$this->_packagexml->getPackagexmlVersion() == '2.1') { |
$this->validateTime(); |
$this->validateStability(); |
$this->validateDeps(); |
$this->validateMainFilelist(); |
$this->validateReleaseFilelist(); |
//$this->validateGlobalTasks(); |
$this->validateChangelog(); |
} |
return !((bool) count($this->_failures['errors'])); |
} |
/** |
* @access protected |
*/ |
function validatePackageName() |
{ |
if ($this->_state == PEAR_VALIDATE_PACKAGING || |
$this->_state == PEAR_VALIDATE_NORMAL) { |
if (($this->_packagexml->getPackagexmlVersion() == '2.0' || |
$this->_packagexml->getPackagexmlVersion() == '2.1') && |
$this->_packagexml->getExtends()) { |
$version = $this->_packagexml->getVersion() . ''; |
$name = $this->_packagexml->getPackage(); |
$a = explode('.', $version); |
$test = array_shift($a); |
if ($test == '0') { |
return true; |
} |
$vlen = strlen($test); |
$majver = substr($name, strlen($name) - $vlen); |
while ($majver && !is_numeric($majver{0})) { |
$majver = substr($majver, 1); |
} |
if ($majver != $test) { |
$this->_addWarning('package', "package $name extends package " . |
$this->_packagexml->getExtends() . ' and so the name should ' . |
'have a postfix equal to the major version like "' . |
$this->_packagexml->getExtends() . $test . '"'); |
return true; |
} elseif (substr($name, 0, strlen($name) - $vlen) != |
$this->_packagexml->getExtends()) { |
$this->_addWarning('package', "package $name extends package " . |
$this->_packagexml->getExtends() . ' and so the name must ' . |
'be an extension like "' . $this->_packagexml->getExtends() . |
$test . '"'); |
return true; |
} |
} |
} |
if (!$this->validPackageName($this->_packagexml->getPackage())) { |
$this->_addFailure('name', 'package name "' . |
$this->_packagexml->getPackage() . '" is invalid'); |
return false; |
} |
} |
/** |
* @access protected |
*/ |
function validateVersion() |
{ |
if ($this->_state != PEAR_VALIDATE_PACKAGING) { |
if (!$this->validVersion($this->_packagexml->getVersion())) { |
$this->_addFailure('version', |
'Invalid version number "' . $this->_packagexml->getVersion() . '"'); |
} |
return false; |
} |
$version = $this->_packagexml->getVersion(); |
$versioncomponents = explode('.', $version); |
if (count($versioncomponents) != 3) { |
$this->_addWarning('version', |
'A version number should have 3 decimals (x.y.z)'); |
return true; |
} |
$name = $this->_packagexml->getPackage(); |
// version must be based upon state |
switch ($this->_packagexml->getState()) { |
case 'snapshot' : |
return true; |
case 'devel' : |
if ($versioncomponents[0] . 'a' == '0a') { |
return true; |
} |
if ($versioncomponents[0] == 0) { |
$versioncomponents[0] = '0'; |
$this->_addWarning('version', |
'version "' . $version . '" should be "' . |
implode('.' ,$versioncomponents) . '"'); |
} else { |
$this->_addWarning('version', |
'packages with devel stability must be < version 1.0.0'); |
} |
return true; |
break; |
case 'alpha' : |
case 'beta' : |
// check for a package that extends a package, |
// like Foo and Foo2 |
if ($this->_state == PEAR_VALIDATE_PACKAGING) { |
if (substr($versioncomponents[2], 1, 2) == 'rc') { |
$this->_addFailure('version', 'Release Candidate versions ' . |
'must have capital RC, not lower-case rc'); |
return false; |
} |
} |
if (!$this->_packagexml->getExtends()) { |
if ($versioncomponents[0] == '1') { |
if ($versioncomponents[2]{0} == '0') { |
if ($versioncomponents[2] == '0') { |
// version 1.*.0000 |
$this->_addWarning('version', |
'version 1.' . $versioncomponents[1] . |
'.0 probably should not be alpha or beta'); |
return true; |
} elseif (strlen($versioncomponents[2]) > 1) { |
// version 1.*.0RC1 or 1.*.0beta24 etc. |
return true; |
} else { |
// version 1.*.0 |
$this->_addWarning('version', |
'version 1.' . $versioncomponents[1] . |
'.0 probably should not be alpha or beta'); |
return true; |
} |
} else { |
$this->_addWarning('version', |
'bugfix versions (1.3.x where x > 0) probably should ' . |
'not be alpha or beta'); |
return true; |
} |
} elseif ($versioncomponents[0] != '0') { |
$this->_addWarning('version', |
'major versions greater than 1 are not allowed for packages ' . |
'without an <extends> tag or an identical postfix (foo2 v2.0.0)'); |
return true; |
} |
if ($versioncomponents[0] . 'a' == '0a') { |
return true; |
} |
if ($versioncomponents[0] == 0) { |
$versioncomponents[0] = '0'; |
$this->_addWarning('version', |
'version "' . $version . '" should be "' . |
implode('.' ,$versioncomponents) . '"'); |
} |
} else { |
$vlen = strlen($versioncomponents[0] . ''); |
$majver = substr($name, strlen($name) - $vlen); |
while ($majver && !is_numeric($majver{0})) { |
$majver = substr($majver, 1); |
} |
if (($versioncomponents[0] != 0) && $majver != $versioncomponents[0]) { |
$this->_addWarning('version', 'first version number "' . |
$versioncomponents[0] . '" must match the postfix of ' . |
'package name "' . $name . '" (' . |
$majver . ')'); |
return true; |
} |
if ($versioncomponents[0] == $majver) { |
if ($versioncomponents[2]{0} == '0') { |
if ($versioncomponents[2] == '0') { |
// version 2.*.0000 |
$this->_addWarning('version', |
"version $majver." . $versioncomponents[1] . |
'.0 probably should not be alpha or beta'); |
return false; |
} elseif (strlen($versioncomponents[2]) > 1) { |
// version 2.*.0RC1 or 2.*.0beta24 etc. |
return true; |
} else { |
// version 2.*.0 |
$this->_addWarning('version', |
"version $majver." . $versioncomponents[1] . |
'.0 cannot be alpha or beta'); |
return true; |
} |
} else { |
$this->_addWarning('version', |
"bugfix versions ($majver.x.y where y > 0) should " . |
'not be alpha or beta'); |
return true; |
} |
} elseif ($versioncomponents[0] != '0') { |
$this->_addWarning('version', |
"only versions 0.x.y and $majver.x.y are allowed for alpha/beta releases"); |
return true; |
} |
if ($versioncomponents[0] . 'a' == '0a') { |
return true; |
} |
if ($versioncomponents[0] == 0) { |
$versioncomponents[0] = '0'; |
$this->_addWarning('version', |
'version "' . $version . '" should be "' . |
implode('.' ,$versioncomponents) . '"'); |
} |
} |
return true; |
break; |
case 'stable' : |
if ($versioncomponents[0] == '0') { |
$this->_addWarning('version', 'versions less than 1.0.0 cannot ' . |
'be stable'); |
return true; |
} |
if (!is_numeric($versioncomponents[2])) { |
if (preg_match('/\d+(rc|a|alpha|b|beta)\d*/i', |
$versioncomponents[2])) { |
$this->_addWarning('version', 'version "' . $version . '" or any ' . |
'RC/beta/alpha version cannot be stable'); |
return true; |
} |
} |
// check for a package that extends a package, |
// like Foo and Foo2 |
if ($this->_packagexml->getExtends()) { |
$vlen = strlen($versioncomponents[0] . ''); |
$majver = substr($name, strlen($name) - $vlen); |
while ($majver && !is_numeric($majver{0})) { |
$majver = substr($majver, 1); |
} |
if (($versioncomponents[0] != 0) && $majver != $versioncomponents[0]) { |
$this->_addWarning('version', 'first version number "' . |
$versioncomponents[0] . '" must match the postfix of ' . |
'package name "' . $name . '" (' . |
$majver . ')'); |
return true; |
} |
} elseif ($versioncomponents[0] > 1) { |
$this->_addWarning('version', 'major version x in x.y.z may not be greater than ' . |
'1 for any package that does not have an <extends> tag'); |
} |
return true; |
break; |
default : |
return false; |
break; |
} |
} |
/** |
* @access protected |
*/ |
function validateMaintainers() |
{ |
// maintainers can only be truly validated server-side for most channels |
// but allow this customization for those who wish it |
return true; |
} |
/** |
* @access protected |
*/ |
function validateDate() |
{ |
if ($this->_state == PEAR_VALIDATE_NORMAL || |
$this->_state == PEAR_VALIDATE_PACKAGING) { |
if (!preg_match('/(\d\d\d\d)\-(\d\d)\-(\d\d)/', |
$this->_packagexml->getDate(), $res) || |
count($res) < 4 |
|| !checkdate($res[2], $res[3], $res[1]) |
) { |
$this->_addFailure('date', 'invalid release date "' . |
$this->_packagexml->getDate() . '"'); |
return false; |
} |
if ($this->_state == PEAR_VALIDATE_PACKAGING && |
$this->_packagexml->getDate() != date('Y-m-d')) { |
$this->_addWarning('date', 'Release Date "' . |
$this->_packagexml->getDate() . '" is not today'); |
} |
} |
return true; |
} |
/** |
* @access protected |
*/ |
function validateTime() |
{ |
if (!$this->_packagexml->getTime()) { |
// default of no time value set |
return true; |
} |
// packager automatically sets time, so only validate if pear validate is called |
if ($this->_state = PEAR_VALIDATE_NORMAL) { |
if (!preg_match('/\d\d:\d\d:\d\d/', |
$this->_packagexml->getTime())) { |
$this->_addFailure('time', 'invalid release time "' . |
$this->_packagexml->getTime() . '"'); |
return false; |
} |
$result = preg_match('|\d{2}\:\d{2}\:\d{2}|', $this->_packagexml->getTime(), $matches); |
if ($result === false || empty($matches)) { |
$this->_addFailure('time', 'invalid release time "' . |
$this->_packagexml->getTime() . '"'); |
return false; |
} |
} |
return true; |
} |
/** |
* @access protected |
*/ |
function validateState() |
{ |
// this is the closest to "final" php4 can get |
if (!PEAR_Validate::validState($this->_packagexml->getState())) { |
if (strtolower($this->_packagexml->getState() == 'rc')) { |
$this->_addFailure('state', 'RC is not a state, it is a version ' . |
'postfix, use ' . $this->_packagexml->getVersion() . 'RC1, state beta'); |
} |
$this->_addFailure('state', 'invalid release state "' . |
$this->_packagexml->getState() . '", must be one of: ' . |
implode(', ', PEAR_Validate::getValidStates())); |
return false; |
} |
return true; |
} |
/** |
* @access protected |
*/ |
function validateStability() |
{ |
$ret = true; |
$packagestability = $this->_packagexml->getState(); |
$apistability = $this->_packagexml->getState('api'); |
if (!PEAR_Validate::validState($packagestability)) { |
$this->_addFailure('state', 'invalid release stability "' . |
$this->_packagexml->getState() . '", must be one of: ' . |
implode(', ', PEAR_Validate::getValidStates())); |
$ret = false; |
} |
$apistates = PEAR_Validate::getValidStates(); |
array_shift($apistates); // snapshot is not allowed |
if (!in_array($apistability, $apistates)) { |
$this->_addFailure('state', 'invalid API stability "' . |
$this->_packagexml->getState('api') . '", must be one of: ' . |
implode(', ', $apistates)); |
$ret = false; |
} |
return $ret; |
} |
/** |
* @access protected |
*/ |
function validateSummary() |
{ |
return true; |
} |
/** |
* @access protected |
*/ |
function validateDescription() |
{ |
return true; |
} |
/** |
* @access protected |
*/ |
function validateLicense() |
{ |
return true; |
} |
/** |
* @access protected |
*/ |
function validateNotes() |
{ |
return true; |
} |
/** |
* for package.xml 2.0 only - channels can't use package.xml 1.0 |
* @access protected |
*/ |
function validateDependencies() |
{ |
return true; |
} |
/** |
* for package.xml 1.0 only |
* @access private |
*/ |
function _validateFilelist() |
{ |
return true; // placeholder for now |
} |
/** |
* for package.xml 2.0 only |
* @access protected |
*/ |
function validateMainFilelist() |
{ |
return true; // placeholder for now |
} |
/** |
* for package.xml 2.0 only |
* @access protected |
*/ |
function validateReleaseFilelist() |
{ |
return true; // placeholder for now |
} |
/** |
* @access protected |
*/ |
function validateChangelog() |
{ |
return true; |
} |
/** |
* @access protected |
*/ |
function validateFilelist() |
{ |
return true; |
} |
/** |
* @access protected |
*/ |
function validateDeps() |
{ |
return true; |
} |
} |
/branches/v1.3-critias/bibliotheque/pear/PEAR/Frontend/CLI.php |
---|
New file |
0,0 → 1,750 |
<?php |
/** |
* PEAR_Frontend_CLI |
* |
* PHP versions 4 and 5 |
* |
* @category pear |
* @package PEAR |
* @author Stig Bakken <ssb@php.net> |
* @author Greg Beaver <cellog@php.net> |
* @copyright 1997-2009 The Authors |
* @license http://opensource.org/licenses/bsd-license.php New BSD License |
* @link http://pear.php.net/package/PEAR |
* @since File available since Release 0.1 |
*/ |
/** |
* base class |
*/ |
require_once 'PEAR/Frontend.php'; |
/** |
* Command-line Frontend for the PEAR Installer |
* @category pear |
* @package PEAR |
* @author Stig Bakken <ssb@php.net> |
* @author Greg Beaver <cellog@php.net> |
* @copyright 1997-2009 The Authors |
* @license http://opensource.org/licenses/bsd-license.php New BSD License |
* @version Release: 1.10.1 |
* @link http://pear.php.net/package/PEAR |
* @since Class available since Release 0.1 |
*/ |
class PEAR_Frontend_CLI extends PEAR_Frontend |
{ |
/** |
* What type of user interface this frontend is for. |
* @var string |
* @access public |
*/ |
var $type = 'CLI'; |
var $lp = ''; // line prefix |
var $params = array(); |
var $term = array( |
'bold' => '', |
'normal' => '', |
); |
function __construct() |
{ |
parent::__construct(); |
$term = getenv('TERM'); //(cox) $_ENV is empty for me in 4.1.1 |
if (function_exists('posix_isatty') && !posix_isatty(1)) { |
// output is being redirected to a file or through a pipe |
} elseif ($term) { |
if (preg_match('/^(xterm|vt220|linux)/', $term)) { |
$this->term['bold'] = sprintf("%c%c%c%c", 27, 91, 49, 109); |
$this->term['normal'] = sprintf("%c%c%c", 27, 91, 109); |
} elseif (preg_match('/^vt100/', $term)) { |
$this->term['bold'] = sprintf("%c%c%c%c%c%c", 27, 91, 49, 109, 0, 0); |
$this->term['normal'] = sprintf("%c%c%c%c%c", 27, 91, 109, 0, 0); |
} |
} elseif (OS_WINDOWS) { |
// XXX add ANSI codes here |
} |
} |
/** |
* @param object PEAR_Error object |
*/ |
function displayError($e) |
{ |
return $this->_displayLine($e->getMessage()); |
} |
/** |
* @param object PEAR_Error object |
*/ |
function displayFatalError($eobj) |
{ |
$this->displayError($eobj); |
if (class_exists('PEAR_Config')) { |
$config = &PEAR_Config::singleton(); |
if ($config->get('verbose') > 5) { |
if (function_exists('debug_print_backtrace')) { |
debug_print_backtrace(); |
exit(1); |
} |
$raised = false; |
foreach (debug_backtrace() as $i => $frame) { |
if (!$raised) { |
if (isset($frame['class']) |
&& strtolower($frame['class']) == 'pear' |
&& strtolower($frame['function']) == 'raiseerror' |
) { |
$raised = true; |
} else { |
continue; |
} |
} |
$frame['class'] = !isset($frame['class']) ? '' : $frame['class']; |
$frame['type'] = !isset($frame['type']) ? '' : $frame['type']; |
$frame['function'] = !isset($frame['function']) ? '' : $frame['function']; |
$frame['line'] = !isset($frame['line']) ? '' : $frame['line']; |
$this->_displayLine("#$i: $frame[class]$frame[type]$frame[function] $frame[line]"); |
} |
} |
} |
exit(1); |
} |
/** |
* Instruct the runInstallScript method to skip a paramgroup that matches the |
* id value passed in. |
* |
* This method is useful for dynamically configuring which sections of a post-install script |
* will be run based on the user's setup, which is very useful for making flexible |
* post-install scripts without losing the cross-Frontend ability to retrieve user input |
* @param string |
*/ |
function skipParamgroup($id) |
{ |
$this->_skipSections[$id] = true; |
} |
function runPostinstallScripts(&$scripts) |
{ |
foreach ($scripts as $i => $script) { |
$this->runInstallScript($scripts[$i]->_params, $scripts[$i]->_obj); |
} |
} |
/** |
* @param array $xml contents of postinstallscript tag |
* @param object $script post-installation script |
* @param string install|upgrade |
*/ |
function runInstallScript($xml, &$script) |
{ |
$this->_skipSections = array(); |
if (!is_array($xml) || !isset($xml['paramgroup'])) { |
$script->run(array(), '_default'); |
return; |
} |
$completedPhases = array(); |
if (!isset($xml['paramgroup'][0])) { |
$xml['paramgroup'] = array($xml['paramgroup']); |
} |
foreach ($xml['paramgroup'] as $group) { |
if (isset($this->_skipSections[$group['id']])) { |
// the post-install script chose to skip this section dynamically |
continue; |
} |
if (isset($group['name'])) { |
$paramname = explode('::', $group['name']); |
if ($lastgroup['id'] != $paramname[0]) { |
continue; |
} |
$group['name'] = $paramname[1]; |
if (!isset($answers)) { |
return; |
} |
if (isset($answers[$group['name']])) { |
switch ($group['conditiontype']) { |
case '=' : |
if ($answers[$group['name']] != $group['value']) { |
continue 2; |
} |
break; |
case '!=' : |
if ($answers[$group['name']] == $group['value']) { |
continue 2; |
} |
break; |
case 'preg_match' : |
if (!@preg_match('/' . $group['value'] . '/', |
$answers[$group['name']])) { |
continue 2; |
} |
break; |
default : |
return; |
} |
} |
} |
$lastgroup = $group; |
if (isset($group['instructions'])) { |
$this->_display($group['instructions']); |
} |
if (!isset($group['param'][0])) { |
$group['param'] = array($group['param']); |
} |
if (isset($group['param'])) { |
if (method_exists($script, 'postProcessPrompts')) { |
$prompts = $script->postProcessPrompts($group['param'], $group['id']); |
if (!is_array($prompts) || count($prompts) != count($group['param'])) { |
$this->outputData('postinstall', 'Error: post-install script did not ' . |
'return proper post-processed prompts'); |
$prompts = $group['param']; |
} else { |
foreach ($prompts as $i => $var) { |
if (!is_array($var) || !isset($var['prompt']) || |
!isset($var['name']) || |
($var['name'] != $group['param'][$i]['name']) || |
($var['type'] != $group['param'][$i]['type']) |
) { |
$this->outputData('postinstall', 'Error: post-install script ' . |
'modified the variables or prompts, severe security risk. ' . |
'Will instead use the defaults from the package.xml'); |
$prompts = $group['param']; |
} |
} |
} |
$answers = $this->confirmDialog($prompts); |
} else { |
$answers = $this->confirmDialog($group['param']); |
} |
} |
if ((isset($answers) && $answers) || !isset($group['param'])) { |
if (!isset($answers)) { |
$answers = array(); |
} |
array_unshift($completedPhases, $group['id']); |
if (!$script->run($answers, $group['id'])) { |
$script->run($completedPhases, '_undoOnError'); |
return; |
} |
} else { |
$script->run($completedPhases, '_undoOnError'); |
return; |
} |
} |
} |
/** |
* Ask for user input, confirm the answers and continue until the user is satisfied |
* @param array an array of arrays, format array('name' => 'paramname', 'prompt' => |
* 'text to display', 'type' => 'string'[, default => 'default value']) |
* @return array |
*/ |
function confirmDialog($params) |
{ |
$answers = $prompts = $types = array(); |
foreach ($params as $param) { |
$prompts[$param['name']] = $param['prompt']; |
$types[$param['name']] = $param['type']; |
$answers[$param['name']] = isset($param['default']) ? $param['default'] : ''; |
} |
$tried = false; |
do { |
if ($tried) { |
$i = 1; |
foreach ($answers as $var => $value) { |
if (!strlen($value)) { |
echo $this->bold("* Enter an answer for #" . $i . ": ({$prompts[$var]})\n"); |
} |
$i++; |
} |
} |
$answers = $this->userDialog('', $prompts, $types, $answers); |
$tried = true; |
} while (is_array($answers) && count(array_filter($answers)) != count($prompts)); |
return $answers; |
} |
function userDialog($command, $prompts, $types = array(), $defaults = array(), $screensize = 20) |
{ |
if (!is_array($prompts)) { |
return array(); |
} |
$testprompts = array_keys($prompts); |
$result = $defaults; |
reset($prompts); |
if (count($prompts) === 1) { |
foreach ($prompts as $key => $prompt) { |
$type = $types[$key]; |
$default = @$defaults[$key]; |
print "$prompt "; |
if ($default) { |
print "[$default] "; |
} |
print ": "; |
$line = fgets(STDIN, 2048); |
$result[$key] = ($default && trim($line) == '') ? $default : trim($line); |
} |
return $result; |
} |
$first_run = true; |
while (true) { |
$descLength = max(array_map('strlen', $prompts)); |
$descFormat = "%-{$descLength}s"; |
$last = count($prompts); |
$i = 0; |
foreach ($prompts as $n => $var) { |
$res = isset($result[$n]) ? $result[$n] : null; |
printf("%2d. $descFormat : %s\n", ++$i, $prompts[$n], $res); |
} |
print "\n1-$last, 'all', 'abort', or Enter to continue: "; |
$tmp = trim(fgets(STDIN, 1024)); |
if (empty($tmp)) { |
break; |
} |
if ($tmp == 'abort') { |
return false; |
} |
if (isset($testprompts[(int)$tmp - 1])) { |
$var = $testprompts[(int)$tmp - 1]; |
$desc = $prompts[$var]; |
$current = @$result[$var]; |
print "$desc [$current] : "; |
$tmp = trim(fgets(STDIN, 1024)); |
if ($tmp !== '') { |
$result[$var] = $tmp; |
} |
} elseif ($tmp == 'all') { |
foreach ($prompts as $var => $desc) { |
$current = $result[$var]; |
print "$desc [$current] : "; |
$tmp = trim(fgets(STDIN, 1024)); |
if (trim($tmp) !== '') { |
$result[$var] = trim($tmp); |
} |
} |
} |
$first_run = false; |
} |
return $result; |
} |
function userConfirm($prompt, $default = 'yes') |
{ |
trigger_error("PEAR_Frontend_CLI::userConfirm not yet converted", E_USER_ERROR); |
static $positives = array('y', 'yes', 'on', '1'); |
static $negatives = array('n', 'no', 'off', '0'); |
print "$this->lp$prompt [$default] : "; |
$fp = fopen("php://stdin", "r"); |
$line = fgets($fp, 2048); |
fclose($fp); |
$answer = strtolower(trim($line)); |
if (empty($answer)) { |
$answer = $default; |
} |
if (in_array($answer, $positives)) { |
return true; |
} |
if (in_array($answer, $negatives)) { |
return false; |
} |
if (in_array($default, $positives)) { |
return true; |
} |
return false; |
} |
function outputData($data, $command = '_default') |
{ |
switch ($command) { |
case 'channel-info': |
foreach ($data as $type => $section) { |
if ($type == 'main') { |
$section['data'] = array_values($section['data']); |
} |
$this->outputData($section); |
} |
break; |
case 'install': |
case 'upgrade': |
case 'upgrade-all': |
if (is_array($data) && isset($data['release_warnings'])) { |
$this->_displayLine(''); |
$this->_startTable(array( |
'border' => false, |
'caption' => 'Release Warnings' |
)); |
$this->_tableRow(array($data['release_warnings']), null, array(1 => array('wrap' => 55))); |
$this->_endTable(); |
$this->_displayLine(''); |
} |
$this->_displayLine(is_array($data) ? $data['data'] : $data); |
break; |
case 'search': |
$this->_startTable($data); |
if (isset($data['headline']) && is_array($data['headline'])) { |
$this->_tableRow($data['headline'], array('bold' => true), array(1 => array('wrap' => 55))); |
} |
$packages = array(); |
foreach($data['data'] as $category) { |
foreach($category as $name => $pkg) { |
$packages[$pkg[0]] = $pkg; |
} |
} |
$p = array_keys($packages); |
natcasesort($p); |
foreach ($p as $name) { |
$this->_tableRow($packages[$name], null, array(1 => array('wrap' => 55))); |
} |
$this->_endTable(); |
break; |
case 'list-all': |
if (!isset($data['data'])) { |
$this->_displayLine('No packages in channel'); |
break; |
} |
$this->_startTable($data); |
if (isset($data['headline']) && is_array($data['headline'])) { |
$this->_tableRow($data['headline'], array('bold' => true), array(1 => array('wrap' => 55))); |
} |
$packages = array(); |
foreach($data['data'] as $category) { |
foreach($category as $name => $pkg) { |
$packages[$pkg[0]] = $pkg; |
} |
} |
$p = array_keys($packages); |
natcasesort($p); |
foreach ($p as $name) { |
$pkg = $packages[$name]; |
unset($pkg[4], $pkg[5]); |
$this->_tableRow($pkg, null, array(1 => array('wrap' => 55))); |
} |
$this->_endTable(); |
break; |
case 'config-show': |
$data['border'] = false; |
$opts = array( |
0 => array('wrap' => 30), |
1 => array('wrap' => 20), |
2 => array('wrap' => 35) |
); |
$this->_startTable($data); |
if (isset($data['headline']) && is_array($data['headline'])) { |
$this->_tableRow($data['headline'], array('bold' => true), $opts); |
} |
foreach ($data['data'] as $group) { |
foreach ($group as $value) { |
if ($value[2] == '') { |
$value[2] = "<not set>"; |
} |
$this->_tableRow($value, null, $opts); |
} |
} |
$this->_endTable(); |
break; |
case 'remote-info': |
$d = $data; |
$data = array( |
'caption' => 'Package details:', |
'border' => false, |
'data' => array( |
array("Latest", $data['stable']), |
array("Installed", $data['installed']), |
array("Package", $data['name']), |
array("License", $data['license']), |
array("Category", $data['category']), |
array("Summary", $data['summary']), |
array("Description", $data['description']), |
), |
); |
if (isset($d['deprecated']) && $d['deprecated']) { |
$conf = &PEAR_Config::singleton(); |
$reg = $conf->getRegistry(); |
$name = $reg->parsedPackageNameToString($d['deprecated'], true); |
$data['data'][] = array('Deprecated! use', $name); |
} |
default: { |
if (is_array($data)) { |
$this->_startTable($data); |
$count = count($data['data'][0]); |
if ($count == 2) { |
$opts = array(0 => array('wrap' => 25), |
1 => array('wrap' => 48) |
); |
} elseif ($count == 3) { |
$opts = array(0 => array('wrap' => 30), |
1 => array('wrap' => 20), |
2 => array('wrap' => 35) |
); |
} else { |
$opts = null; |
} |
if (isset($data['headline']) && is_array($data['headline'])) { |
$this->_tableRow($data['headline'], |
array('bold' => true), |
$opts); |
} |
if (is_array($data['data'])) { |
foreach($data['data'] as $row) { |
$this->_tableRow($row, null, $opts); |
} |
} else { |
$this->_tableRow(array($data['data']), null, $opts); |
} |
$this->_endTable(); |
} else { |
$this->_displayLine($data); |
} |
} |
} |
} |
function log($text, $append_crlf = true) |
{ |
if ($append_crlf) { |
return $this->_displayLine($text); |
} |
return $this->_display($text); |
} |
function bold($text) |
{ |
if (empty($this->term['bold'])) { |
return strtoupper($text); |
} |
return $this->term['bold'] . $text . $this->term['normal']; |
} |
function _displayHeading($title) |
{ |
print $this->lp.$this->bold($title)."\n"; |
print $this->lp.str_repeat("=", strlen($title))."\n"; |
} |
function _startTable($params = array()) |
{ |
$params['table_data'] = array(); |
$params['widest'] = array(); // indexed by column |
$params['highest'] = array(); // indexed by row |
$params['ncols'] = 0; |
$this->params = $params; |
} |
function _tableRow($columns, $rowparams = array(), $colparams = array()) |
{ |
$highest = 1; |
for ($i = 0; $i < count($columns); $i++) { |
$col = &$columns[$i]; |
if (isset($colparams[$i]) && !empty($colparams[$i]['wrap'])) { |
$col = wordwrap($col, $colparams[$i]['wrap']); |
} |
if (strpos($col, "\n") !== false) { |
$multiline = explode("\n", $col); |
$w = 0; |
foreach ($multiline as $n => $line) { |
$len = strlen($line); |
if ($len > $w) { |
$w = $len; |
} |
} |
$lines = count($multiline); |
} else { |
$w = strlen($col); |
} |
if (isset($this->params['widest'][$i])) { |
if ($w > $this->params['widest'][$i]) { |
$this->params['widest'][$i] = $w; |
} |
} else { |
$this->params['widest'][$i] = $w; |
} |
$tmp = count_chars($columns[$i], 1); |
// handle unix, mac and windows formats |
$lines = (isset($tmp[10]) ? $tmp[10] : (isset($tmp[13]) ? $tmp[13] : 0)) + 1; |
if ($lines > $highest) { |
$highest = $lines; |
} |
} |
if (count($columns) > $this->params['ncols']) { |
$this->params['ncols'] = count($columns); |
} |
$new_row = array( |
'data' => $columns, |
'height' => $highest, |
'rowparams' => $rowparams, |
'colparams' => $colparams, |
); |
$this->params['table_data'][] = $new_row; |
} |
function _endTable() |
{ |
extract($this->params); |
if (!empty($caption)) { |
$this->_displayHeading($caption); |
} |
if (count($table_data) === 0) { |
return; |
} |
if (!isset($width)) { |
$width = $widest; |
} else { |
for ($i = 0; $i < $ncols; $i++) { |
if (!isset($width[$i])) { |
$width[$i] = $widest[$i]; |
} |
} |
} |
$border = false; |
if (empty($border)) { |
$cellstart = ''; |
$cellend = ' '; |
$rowend = ''; |
$padrowend = false; |
$borderline = ''; |
} else { |
$cellstart = '| '; |
$cellend = ' '; |
$rowend = '|'; |
$padrowend = true; |
$borderline = '+'; |
foreach ($width as $w) { |
$borderline .= str_repeat('-', $w + strlen($cellstart) + strlen($cellend) - 1); |
$borderline .= '+'; |
} |
} |
if ($borderline) { |
$this->_displayLine($borderline); |
} |
for ($i = 0; $i < count($table_data); $i++) { |
extract($table_data[$i]); |
if (!is_array($rowparams)) { |
$rowparams = array(); |
} |
if (!is_array($colparams)) { |
$colparams = array(); |
} |
$rowlines = array(); |
if ($height > 1) { |
for ($c = 0; $c < count($data); $c++) { |
$rowlines[$c] = preg_split('/(\r?\n|\r)/', $data[$c]); |
if (count($rowlines[$c]) < $height) { |
$rowlines[$c] = array_pad($rowlines[$c], $height, ''); |
} |
} |
} else { |
for ($c = 0; $c < count($data); $c++) { |
$rowlines[$c] = array($data[$c]); |
} |
} |
for ($r = 0; $r < $height; $r++) { |
$rowtext = ''; |
for ($c = 0; $c < count($data); $c++) { |
if (isset($colparams[$c])) { |
$attribs = array_merge($rowparams, $colparams); |
} else { |
$attribs = $rowparams; |
} |
$w = isset($width[$c]) ? $width[$c] : 0; |
//$cell = $data[$c]; |
$cell = $rowlines[$c][$r]; |
$l = strlen($cell); |
if ($l > $w) { |
$cell = substr($cell, 0, $w); |
} |
if (isset($attribs['bold'])) { |
$cell = $this->bold($cell); |
} |
if ($l < $w) { |
// not using str_pad here because we may |
// add bold escape characters to $cell |
$cell .= str_repeat(' ', $w - $l); |
} |
$rowtext .= $cellstart . $cell . $cellend; |
} |
if (!$border) { |
$rowtext = rtrim($rowtext); |
} |
$rowtext .= $rowend; |
$this->_displayLine($rowtext); |
} |
} |
if ($borderline) { |
$this->_displayLine($borderline); |
} |
} |
function _displayLine($text) |
{ |
print "$this->lp$text\n"; |
} |
function _display($text) |
{ |
print $text; |
} |
} |
/branches/v1.3-critias/bibliotheque/pear/PEAR/PackageFile.php |
---|
New file |
0,0 → 1,491 |
<?php |
/** |
* PEAR_PackageFile, package.xml parsing utility class |
* |
* PHP versions 4 and 5 |
* |
* @category pear |
* @package PEAR |
* @author Greg Beaver <cellog@php.net> |
* @copyright 1997-2009 The Authors |
* @license http://opensource.org/licenses/bsd-license.php New BSD License |
* @link http://pear.php.net/package/PEAR |
* @since File available since Release 1.4.0a1 |
*/ |
/** |
* needed for PEAR_VALIDATE_* constants |
*/ |
require_once 'PEAR/Validate.php'; |
/** |
* Error code if the package.xml <package> tag does not contain a valid version |
*/ |
define('PEAR_PACKAGEFILE_ERROR_NO_PACKAGEVERSION', 1); |
/** |
* Error code if the package.xml <package> tag version is not supported (version 1.0 and 1.1 are the only supported versions, |
* currently |
*/ |
define('PEAR_PACKAGEFILE_ERROR_INVALID_PACKAGEVERSION', 2); |
/** |
* Abstraction for the package.xml package description file |
* |
* @category pear |
* @package PEAR |
* @author Greg Beaver <cellog@php.net> |
* @copyright 1997-2009 The Authors |
* @license http://opensource.org/licenses/bsd-license.php New BSD License |
* @version Release: 1.10.1 |
* @link http://pear.php.net/package/PEAR |
* @since Class available since Release 1.4.0a1 |
*/ |
class PEAR_PackageFile |
{ |
/** |
* @var PEAR_Config |
*/ |
var $_config; |
var $_debug; |
var $_logger = false; |
/** |
* @var boolean |
*/ |
var $_rawReturn = false; |
/** |
* helper for extracting Archive_Tar errors |
* @var array |
* @access private |
*/ |
var $_extractErrors = array(); |
/** |
* |
* @param PEAR_Config $config |
* @param ? $debug |
* @param string @tmpdir Optional temporary directory for uncompressing |
* files |
*/ |
function __construct(&$config, $debug = false) |
{ |
$this->_config = $config; |
$this->_debug = $debug; |
} |
/** |
* Turn off validation - return a parsed package.xml without checking it |
* |
* This is used by the package-validate command |
*/ |
function rawReturn() |
{ |
$this->_rawReturn = true; |
} |
function setLogger(&$l) |
{ |
$this->_logger = &$l; |
} |
/** |
* Create a PEAR_PackageFile_Parser_v* of a given version. |
* @param int $version |
* @return PEAR_PackageFile_Parser_v1|PEAR_PackageFile_Parser_v1 |
*/ |
function &parserFactory($version) |
{ |
if (!in_array($version{0}, array('1', '2'))) { |
$a = false; |
return $a; |
} |
include_once 'PEAR/PackageFile/Parser/v' . $version{0} . '.php'; |
$version = $version{0}; |
$class = "PEAR_PackageFile_Parser_v$version"; |
$a = new $class; |
return $a; |
} |
/** |
* For simpler unit-testing |
* @return string |
*/ |
function getClassPrefix() |
{ |
return 'PEAR_PackageFile_v'; |
} |
/** |
* Create a PEAR_PackageFile_v* of a given version. |
* @param int $version |
* @return PEAR_PackageFile_v1|PEAR_PackageFile_v1 |
*/ |
function &factory($version) |
{ |
if (!in_array($version{0}, array('1', '2'))) { |
$a = false; |
return $a; |
} |
include_once 'PEAR/PackageFile/v' . $version{0} . '.php'; |
$version = $version{0}; |
$class = $this->getClassPrefix() . $version; |
$a = new $class; |
return $a; |
} |
/** |
* Create a PEAR_PackageFile_v* from its toArray() method |
* |
* WARNING: no validation is performed, the array is assumed to be valid, |
* always parse from xml if you want validation. |
* @param array $arr |
* @return PEAR_PackageFileManager_v1|PEAR_PackageFileManager_v2 |
* @uses factory() to construct the returned object. |
*/ |
function &fromArray($arr) |
{ |
if (isset($arr['xsdversion'])) { |
$obj = &$this->factory($arr['xsdversion']); |
if ($this->_logger) { |
$obj->setLogger($this->_logger); |
} |
$obj->setConfig($this->_config); |
$obj->fromArray($arr); |
return $obj; |
} |
if (isset($arr['package']['attribs']['version'])) { |
$obj = &$this->factory($arr['package']['attribs']['version']); |
} else { |
$obj = &$this->factory('1.0'); |
} |
if ($this->_logger) { |
$obj->setLogger($this->_logger); |
} |
$obj->setConfig($this->_config); |
$obj->fromArray($arr); |
return $obj; |
} |
/** |
* Create a PEAR_PackageFile_v* from an XML string. |
* @access public |
* @param string $data contents of package.xml file |
* @param int $state package state (one of PEAR_VALIDATE_* constants) |
* @param string $file full path to the package.xml file (and the files |
* it references) |
* @param string $archive optional name of the archive that the XML was |
* extracted from, if any |
* @return PEAR_PackageFile_v1|PEAR_PackageFile_v2 |
* @uses parserFactory() to construct a parser to load the package. |
*/ |
function &fromXmlString($data, $state, $file, $archive = false) |
{ |
if (preg_match('/<package[^>]+version=[\'"]([0-9]+\.[0-9]+)[\'"]/', $data, $packageversion)) { |
if (!in_array($packageversion[1], array('1.0', '2.0', '2.1'))) { |
return PEAR::raiseError('package.xml version "' . $packageversion[1] . |
'" is not supported, only 1.0, 2.0, and 2.1 are supported.'); |
} |
$object = &$this->parserFactory($packageversion[1]); |
if ($this->_logger) { |
$object->setLogger($this->_logger); |
} |
$object->setConfig($this->_config); |
$pf = $object->parse($data, $file, $archive); |
if (PEAR::isError($pf)) { |
return $pf; |
} |
if ($this->_rawReturn) { |
return $pf; |
} |
if (!$pf->validate($state)) {; |
if ($this->_config->get('verbose') > 0 |
&& $this->_logger && $pf->getValidationWarnings(false) |
) { |
foreach ($pf->getValidationWarnings(false) as $warning) { |
$this->_logger->log(0, 'ERROR: ' . $warning['message']); |
} |
} |
$a = PEAR::raiseError('Parsing of package.xml from file "' . $file . '" failed', |
2, null, null, $pf->getValidationWarnings()); |
return $a; |
} |
if ($this->_logger && $pf->getValidationWarnings(false)) { |
foreach ($pf->getValidationWarnings() as $warning) { |
$this->_logger->log(0, 'WARNING: ' . $warning['message']); |
} |
} |
if (method_exists($pf, 'flattenFilelist')) { |
$pf->flattenFilelist(); // for v2 |
} |
return $pf; |
} elseif (preg_match('/<package[^>]+version=[\'"]([^"\']+)[\'"]/', $data, $packageversion)) { |
$a = PEAR::raiseError('package.xml file "' . $file . |
'" has unsupported package.xml <package> version "' . $packageversion[1] . '"'); |
return $a; |
} else { |
if (!class_exists('PEAR_ErrorStack')) { |
require_once 'PEAR/ErrorStack.php'; |
} |
PEAR_ErrorStack::staticPush('PEAR_PackageFile', |
PEAR_PACKAGEFILE_ERROR_NO_PACKAGEVERSION, |
'warning', array('xml' => $data), 'package.xml "' . $file . |
'" has no package.xml <package> version'); |
$object = &$this->parserFactory('1.0'); |
$object->setConfig($this->_config); |
$pf = $object->parse($data, $file, $archive); |
if (PEAR::isError($pf)) { |
return $pf; |
} |
if ($this->_rawReturn) { |
return $pf; |
} |
if (!$pf->validate($state)) { |
$a = PEAR::raiseError('Parsing of package.xml from file "' . $file . '" failed', |
2, null, null, $pf->getValidationWarnings()); |
return $a; |
} |
if ($this->_logger && $pf->getValidationWarnings(false)) { |
foreach ($pf->getValidationWarnings() as $warning) { |
$this->_logger->log(0, 'WARNING: ' . $warning['message']); |
} |
} |
if (method_exists($pf, 'flattenFilelist')) { |
$pf->flattenFilelist(); // for v2 |
} |
return $pf; |
} |
} |
/** |
* Register a temporary file or directory. When the destructor is |
* executed, all registered temporary files and directories are |
* removed. |
* |
* @param string $file name of file or directory |
* @return void |
*/ |
function addTempFile($file) |
{ |
$GLOBALS['_PEAR_Common_tempfiles'][] = $file; |
} |
/** |
* Create a PEAR_PackageFile_v* from a compresed Tar or Tgz file. |
* @access public |
* @param string contents of package.xml file |
* @param int package state (one of PEAR_VALIDATE_* constants) |
* @return PEAR_PackageFile_v1|PEAR_PackageFile_v2 |
* @using Archive_Tar to extract the files |
* @using fromPackageFile() to load the package after the package.xml |
* file is extracted. |
*/ |
function &fromTgzFile($file, $state) |
{ |
if (!class_exists('Archive_Tar')) { |
require_once 'Archive/Tar.php'; |
} |
$tar = new Archive_Tar($file); |
if ($this->_debug <= 1) { |
$tar->pushErrorHandling(PEAR_ERROR_RETURN); |
} |
$content = $tar->listContent(); |
if ($this->_debug <= 1) { |
$tar->popErrorHandling(); |
} |
if (!is_array($content)) { |
if (is_string($file) && strlen($file < 255) && |
(!file_exists($file) || !@is_file($file))) { |
$ret = PEAR::raiseError("could not open file \"$file\""); |
return $ret; |
} |
$file = realpath($file); |
$ret = PEAR::raiseError("Could not get contents of package \"$file\"". |
'. Invalid tgz file.'); |
return $ret; |
} |
if (!count($content) && !@is_file($file)) { |
$ret = PEAR::raiseError("could not open file \"$file\""); |
return $ret; |
} |
$xml = null; |
$origfile = $file; |
foreach ($content as $file) { |
$name = $file['filename']; |
if ($name == 'package2.xml') { // allow a .tgz to distribute both versions |
$xml = $name; |
break; |
} |
if ($name == 'package.xml') { |
$xml = $name; |
break; |
} elseif (preg_match('/package.xml$/', $name, $match)) { |
$xml = $name; |
break; |
} |
} |
$tmpdir = System::mktemp('-t "' . $this->_config->get('temp_dir') . '" -d pear'); |
if ($tmpdir === false) { |
$ret = PEAR::raiseError("there was a problem with getting the configured temp directory"); |
return $ret; |
} |
PEAR_PackageFile::addTempFile($tmpdir); |
$this->_extractErrors(); |
PEAR::staticPushErrorHandling(PEAR_ERROR_CALLBACK, array($this, '_extractErrors')); |
if (!$xml || !$tar->extractList(array($xml), $tmpdir)) { |
$extra = implode("\n", $this->_extractErrors()); |
if ($extra) { |
$extra = ' ' . $extra; |
} |
PEAR::staticPopErrorHandling(); |
$ret = PEAR::raiseError('could not extract the package.xml file from "' . |
$origfile . '"' . $extra); |
return $ret; |
} |
PEAR::staticPopErrorHandling(); |
$ret = &PEAR_PackageFile::fromPackageFile("$tmpdir/$xml", $state, $origfile); |
return $ret; |
} |
/** |
* helper callback for extracting Archive_Tar errors |
* |
* @param PEAR_Error|null $err |
* @return array |
* @access private |
*/ |
function _extractErrors($err = null) |
{ |
static $errors = array(); |
if ($err === null) { |
$e = $errors; |
$errors = array(); |
return $e; |
} |
$errors[] = $err->getMessage(); |
} |
/** |
* Create a PEAR_PackageFile_v* from a package.xml file. |
* |
* @access public |
* @param string $descfile name of package xml file |
* @param int $state package state (one of PEAR_VALIDATE_* constants) |
* @param string|false $archive name of the archive this package.xml came |
* from, if any |
* @return PEAR_PackageFile_v1|PEAR_PackageFile_v2 |
* @uses PEAR_PackageFile::fromXmlString to create the oject after the |
* XML is loaded from the package.xml file. |
*/ |
function &fromPackageFile($descfile, $state, $archive = false) |
{ |
$fp = false; |
if (is_string($descfile) && strlen($descfile) < 255 && |
( |
!file_exists($descfile) || !is_file($descfile) || !is_readable($descfile) |
|| (!$fp = @fopen($descfile, 'r')) |
) |
) { |
$a = PEAR::raiseError("Unable to open $descfile"); |
return $a; |
} |
// read the whole thing so we only get one cdata callback |
// for each block of cdata |
fclose($fp); |
$data = file_get_contents($descfile); |
$ret = &PEAR_PackageFile::fromXmlString($data, $state, $descfile, $archive); |
return $ret; |
} |
/** |
* Create a PEAR_PackageFile_v* from a .tgz archive or package.xml file. |
* |
* This method is able to extract information about a package from a .tgz |
* archive or from a XML package definition file. |
* |
* @access public |
* @param string $info file name |
* @param int $state package state (one of PEAR_VALIDATE_* constants) |
* @return PEAR_PackageFile_v1|PEAR_PackageFile_v2 |
* @uses fromPackageFile() if the file appears to be XML |
* @uses fromTgzFile() to load all non-XML files |
*/ |
function &fromAnyFile($info, $state) |
{ |
if (is_dir($info)) { |
$dir_name = realpath($info); |
if (file_exists($dir_name . '/package.xml')) { |
$info = PEAR_PackageFile::fromPackageFile($dir_name . '/package.xml', $state); |
} elseif (file_exists($dir_name . '/package2.xml')) { |
$info = PEAR_PackageFile::fromPackageFile($dir_name . '/package2.xml', $state); |
} else { |
$info = PEAR::raiseError("No package definition found in '$info' directory"); |
} |
return $info; |
} |
$fp = false; |
if (is_string($info) && strlen($info) < 255 && |
(file_exists($info) || ($fp = @fopen($info, 'r'))) |
) { |
if ($fp) { |
fclose($fp); |
} |
$tmp = substr($info, -4); |
if ($tmp == '.xml') { |
$info = &PEAR_PackageFile::fromPackageFile($info, $state); |
} elseif ($tmp == '.tar' || $tmp == '.tgz') { |
$info = &PEAR_PackageFile::fromTgzFile($info, $state); |
} else { |
$fp = fopen($info, 'r'); |
$test = fread($fp, 5); |
fclose($fp); |
if ($test == '<?xml') { |
$info = &PEAR_PackageFile::fromPackageFile($info, $state); |
} else { |
$info = &PEAR_PackageFile::fromTgzFile($info, $state); |
} |
} |
return $info; |
} |
$info = PEAR::raiseError("Cannot open '$info' for parsing"); |
return $info; |
} |
} |
/branches/v1.3-critias/bibliotheque/pear/PEAR/Installer.php |
---|
New file |
0,0 → 1,1794 |
<?php |
/** |
* PEAR_Installer |
* |
* PHP versions 4 and 5 |
* |
* @category pear |
* @package PEAR |
* @author Stig Bakken <ssb@php.net> |
* @author Tomas V.V. Cox <cox@idecnet.com> |
* @author Martin Jansen <mj@php.net> |
* @author Greg Beaver <cellog@php.net> |
* @copyright 1997-2009 The Authors |
* @license http://opensource.org/licenses/bsd-license.php New BSD License |
* @link http://pear.php.net/package/PEAR |
* @since File available since Release 0.1 |
*/ |
/** |
* Used for installation groups in package.xml 2.0 and platform exceptions |
*/ |
require_once 'OS/Guess.php'; |
require_once 'PEAR/Downloader.php'; |
define('PEAR_INSTALLER_NOBINARY', -240); |
/** |
* Administration class used to install PEAR packages and maintain the |
* installed package database. |
* |
* @category pear |
* @package PEAR |
* @author Stig Bakken <ssb@php.net> |
* @author Tomas V.V. Cox <cox@idecnet.com> |
* @author Martin Jansen <mj@php.net> |
* @author Greg Beaver <cellog@php.net> |
* @copyright 1997-2009 The Authors |
* @license http://opensource.org/licenses/bsd-license.php New BSD License |
* @version Release: 1.10.1 |
* @link http://pear.php.net/package/PEAR |
* @since Class available since Release 0.1 |
*/ |
class PEAR_Installer extends PEAR_Downloader |
{ |
// {{{ properties |
/** name of the package directory, for example Foo-1.0 |
* @var string |
*/ |
var $pkgdir; |
/** directory where PHP code files go |
* @var string |
*/ |
var $phpdir; |
/** directory where PHP extension files go |
* @var string |
*/ |
var $extdir; |
/** directory where documentation goes |
* @var string |
*/ |
var $docdir; |
/** installation root directory (ala PHP's INSTALL_ROOT or |
* automake's DESTDIR |
* @var string |
*/ |
var $installroot = ''; |
/** debug level |
* @var int |
*/ |
var $debug = 1; |
/** temporary directory |
* @var string |
*/ |
var $tmpdir; |
/** |
* PEAR_Registry object used by the installer |
* @var PEAR_Registry |
*/ |
var $registry; |
/** |
* array of PEAR_Downloader_Packages |
* @var array |
*/ |
var $_downloadedPackages; |
/** List of file transactions queued for an install/upgrade/uninstall. |
* |
* Format: |
* array( |
* 0 => array("rename => array("from-file", "to-file")), |
* 1 => array("delete" => array("file-to-delete")), |
* ... |
* ) |
* |
* @var array |
*/ |
var $file_operations = array(); |
// }}} |
// {{{ constructor |
/** |
* PEAR_Installer constructor. |
* |
* @param object $ui user interface object (instance of PEAR_Frontend_*) |
* |
* @access public |
*/ |
function __construct(&$ui) |
{ |
parent::__construct($ui, array(), null); |
$this->setFrontendObject($ui); |
$this->debug = $this->config->get('verbose'); |
} |
function setOptions($options) |
{ |
$this->_options = $options; |
} |
function setConfig(&$config) |
{ |
$this->config = &$config; |
$this->_registry = &$config->getRegistry(); |
} |
// }}} |
function _removeBackups($files) |
{ |
foreach ($files as $path) { |
$this->addFileOperation('removebackup', array($path)); |
} |
} |
// {{{ _deletePackageFiles() |
/** |
* Delete a package's installed files, does not remove empty directories. |
* |
* @param string package name |
* @param string channel name |
* @param bool if true, then files are backed up first |
* @return bool TRUE on success, or a PEAR error on failure |
* @access protected |
*/ |
function _deletePackageFiles($package, $channel = false, $backup = false) |
{ |
if (!$channel) { |
$channel = 'pear.php.net'; |
} |
if (!strlen($package)) { |
return $this->raiseError("No package to uninstall given"); |
} |
if (strtolower($package) == 'pear' && $channel == 'pear.php.net') { |
// to avoid race conditions, include all possible needed files |
require_once 'PEAR/Task/Common.php'; |
require_once 'PEAR/Task/Replace.php'; |
require_once 'PEAR/Task/Unixeol.php'; |
require_once 'PEAR/Task/Windowseol.php'; |
require_once 'PEAR/PackageFile/v1.php'; |
require_once 'PEAR/PackageFile/v2.php'; |
require_once 'PEAR/PackageFile/Generator/v1.php'; |
require_once 'PEAR/PackageFile/Generator/v2.php'; |
} |
$filelist = $this->_registry->packageInfo($package, 'filelist', $channel); |
if ($filelist == null) { |
return $this->raiseError("$channel/$package not installed"); |
} |
$ret = array(); |
foreach ($filelist as $file => $props) { |
if (empty($props['installed_as'])) { |
continue; |
} |
$path = $props['installed_as']; |
if ($backup) { |
$this->addFileOperation('backup', array($path)); |
$ret[] = $path; |
} |
$this->addFileOperation('delete', array($path)); |
} |
if ($backup) { |
return $ret; |
} |
return true; |
} |
// }}} |
// {{{ _installFile() |
/** |
* @param string filename |
* @param array attributes from <file> tag in package.xml |
* @param string path to install the file in |
* @param array options from command-line |
* @access private |
*/ |
function _installFile($file, $atts, $tmp_path, $options) |
{ |
// {{{ return if this file is meant for another platform |
static $os; |
if (!isset($this->_registry)) { |
$this->_registry = &$this->config->getRegistry(); |
} |
if (isset($atts['platform'])) { |
if (empty($os)) { |
$os = new OS_Guess(); |
} |
if (strlen($atts['platform']) && $atts['platform']{0} == '!') { |
$negate = true; |
$platform = substr($atts['platform'], 1); |
} else { |
$negate = false; |
$platform = $atts['platform']; |
} |
if ((bool) $os->matchSignature($platform) === $negate) { |
$this->log(3, "skipped $file (meant for $atts[platform], we are ".$os->getSignature().")"); |
return PEAR_INSTALLER_SKIPPED; |
} |
} |
// }}} |
$channel = $this->pkginfo->getChannel(); |
// {{{ assemble the destination paths |
switch ($atts['role']) { |
case 'src': |
case 'extsrc': |
$this->source_files++; |
return; |
case 'doc': |
case 'data': |
case 'test': |
$dest_dir = $this->config->get($atts['role'] . '_dir', null, $channel) . |
DIRECTORY_SEPARATOR . $this->pkginfo->getPackage(); |
unset($atts['baseinstalldir']); |
break; |
case 'ext': |
case 'php': |
$dest_dir = $this->config->get($atts['role'] . '_dir', null, $channel); |
break; |
case 'script': |
$dest_dir = $this->config->get('bin_dir', null, $channel); |
break; |
default: |
return $this->raiseError("Invalid role `$atts[role]' for file $file"); |
} |
$save_destdir = $dest_dir; |
if (!empty($atts['baseinstalldir'])) { |
$dest_dir .= DIRECTORY_SEPARATOR . $atts['baseinstalldir']; |
} |
if (dirname($file) != '.' && empty($atts['install-as'])) { |
$dest_dir .= DIRECTORY_SEPARATOR . dirname($file); |
} |
if (empty($atts['install-as'])) { |
$dest_file = $dest_dir . DIRECTORY_SEPARATOR . basename($file); |
} else { |
$dest_file = $dest_dir . DIRECTORY_SEPARATOR . $atts['install-as']; |
} |
$orig_file = $tmp_path . DIRECTORY_SEPARATOR . $file; |
// Clean up the DIRECTORY_SEPARATOR mess |
$ds2 = DIRECTORY_SEPARATOR . DIRECTORY_SEPARATOR; |
list($dest_file, $orig_file) = preg_replace(array('!\\\\+!', '!/!', "!$ds2+!"), |
array(DIRECTORY_SEPARATOR, |
DIRECTORY_SEPARATOR, |
DIRECTORY_SEPARATOR), |
array($dest_file, $orig_file)); |
$final_dest_file = $installed_as = $dest_file; |
if (isset($this->_options['packagingroot'])) { |
$installedas_dest_dir = dirname($final_dest_file); |
$installedas_dest_file = $dest_dir . DIRECTORY_SEPARATOR . '.tmp' . basename($final_dest_file); |
$final_dest_file = $this->_prependPath($final_dest_file, $this->_options['packagingroot']); |
} else { |
$installedas_dest_dir = dirname($final_dest_file); |
$installedas_dest_file = $installedas_dest_dir . DIRECTORY_SEPARATOR . '.tmp' . basename($final_dest_file); |
} |
$dest_dir = dirname($final_dest_file); |
$dest_file = $dest_dir . DIRECTORY_SEPARATOR . '.tmp' . basename($final_dest_file); |
if (preg_match('~/\.\.(/|\\z)|^\.\./~', str_replace('\\', '/', $dest_file))) { |
return $this->raiseError("SECURITY ERROR: file $file (installed to $dest_file) contains parent directory reference ..", PEAR_INSTALLER_FAILED); |
} |
// }}} |
if (empty($this->_options['register-only']) && |
(!file_exists($dest_dir) || !is_dir($dest_dir))) { |
if (!$this->mkDirHier($dest_dir)) { |
return $this->raiseError("failed to mkdir $dest_dir", |
PEAR_INSTALLER_FAILED); |
} |
$this->log(3, "+ mkdir $dest_dir"); |
} |
// pretty much nothing happens if we are only registering the install |
if (empty($this->_options['register-only'])) { |
if (empty($atts['replacements'])) { |
if (!file_exists($orig_file)) { |
return $this->raiseError("file $orig_file does not exist", |
PEAR_INSTALLER_FAILED); |
} |
if (!@copy($orig_file, $dest_file)) { |
return $this->raiseError("failed to write $dest_file: $php_errormsg", |
PEAR_INSTALLER_FAILED); |
} |
$this->log(3, "+ cp $orig_file $dest_file"); |
if (isset($atts['md5sum'])) { |
$md5sum = md5_file($dest_file); |
} |
} else { |
// {{{ file with replacements |
if (!file_exists($orig_file)) { |
return $this->raiseError("file does not exist", |
PEAR_INSTALLER_FAILED); |
} |
$contents = file_get_contents($orig_file); |
if ($contents === false) { |
$contents = ''; |
} |
if (isset($atts['md5sum'])) { |
$md5sum = md5($contents); |
} |
$subst_from = $subst_to = array(); |
foreach ($atts['replacements'] as $a) { |
$to = ''; |
if ($a['type'] == 'php-const') { |
if (preg_match('/^[a-z0-9_]+\\z/i', $a['to'])) { |
eval("\$to = $a[to];"); |
} else { |
if (!isset($options['soft'])) { |
$this->log(0, "invalid php-const replacement: $a[to]"); |
} |
continue; |
} |
} elseif ($a['type'] == 'pear-config') { |
if ($a['to'] == 'master_server') { |
$chan = $this->_registry->getChannel($channel); |
if (!PEAR::isError($chan)) { |
$to = $chan->getServer(); |
} else { |
$to = $this->config->get($a['to'], null, $channel); |
} |
} else { |
$to = $this->config->get($a['to'], null, $channel); |
} |
if (is_null($to)) { |
if (!isset($options['soft'])) { |
$this->log(0, "invalid pear-config replacement: $a[to]"); |
} |
continue; |
} |
} elseif ($a['type'] == 'package-info') { |
if ($t = $this->pkginfo->packageInfo($a['to'])) { |
$to = $t; |
} else { |
if (!isset($options['soft'])) { |
$this->log(0, "invalid package-info replacement: $a[to]"); |
} |
continue; |
} |
} |
if (!is_null($to)) { |
$subst_from[] = $a['from']; |
$subst_to[] = $to; |
} |
} |
$this->log(3, "doing ".sizeof($subst_from)." substitution(s) for $final_dest_file"); |
if (sizeof($subst_from)) { |
$contents = str_replace($subst_from, $subst_to, $contents); |
} |
$wp = @fopen($dest_file, "wb"); |
if (!is_resource($wp)) { |
return $this->raiseError("failed to create $dest_file: $php_errormsg", |
PEAR_INSTALLER_FAILED); |
} |
if (@fwrite($wp, $contents) === false) { |
return $this->raiseError("failed writing to $dest_file: $php_errormsg", |
PEAR_INSTALLER_FAILED); |
} |
fclose($wp); |
// }}} |
} |
// {{{ check the md5 |
if (isset($md5sum)) { |
if (strtolower($md5sum) === strtolower($atts['md5sum'])) { |
$this->log(2, "md5sum ok: $final_dest_file"); |
} else { |
if (empty($options['force'])) { |
// delete the file |
if (file_exists($dest_file)) { |
unlink($dest_file); |
} |
if (!isset($options['ignore-errors'])) { |
return $this->raiseError("bad md5sum for file $final_dest_file", |
PEAR_INSTALLER_FAILED); |
} |
if (!isset($options['soft'])) { |
$this->log(0, "warning : bad md5sum for file $final_dest_file"); |
} |
} else { |
if (!isset($options['soft'])) { |
$this->log(0, "warning : bad md5sum for file $final_dest_file"); |
} |
} |
} |
} |
// }}} |
// {{{ set file permissions |
if (!OS_WINDOWS) { |
if ($atts['role'] == 'script') { |
$mode = 0777 & ~(int)octdec($this->config->get('umask')); |
$this->log(3, "+ chmod +x $dest_file"); |
} else { |
$mode = 0666 & ~(int)octdec($this->config->get('umask')); |
} |
if ($atts['role'] != 'src') { |
$this->addFileOperation("chmod", array($mode, $dest_file)); |
if (!@chmod($dest_file, $mode)) { |
if (!isset($options['soft'])) { |
$this->log(0, "failed to change mode of $dest_file: $php_errormsg"); |
} |
} |
} |
} |
// }}} |
if ($atts['role'] == 'src') { |
rename($dest_file, $final_dest_file); |
$this->log(2, "renamed source file $dest_file to $final_dest_file"); |
} else { |
$this->addFileOperation("rename", array($dest_file, $final_dest_file, |
$atts['role'] == 'ext')); |
} |
} |
// Store the full path where the file was installed for easy unistall |
if ($atts['role'] != 'script') { |
$loc = $this->config->get($atts['role'] . '_dir'); |
} else { |
$loc = $this->config->get('bin_dir'); |
} |
if ($atts['role'] != 'src') { |
$this->addFileOperation("installed_as", array($file, $installed_as, |
$loc, |
dirname(substr($installedas_dest_file, strlen($loc))))); |
} |
//$this->log(2, "installed: $dest_file"); |
return PEAR_INSTALLER_OK; |
} |
// }}} |
// {{{ _installFile2() |
/** |
* @param PEAR_PackageFile_v1|PEAR_PackageFile_v2 |
* @param string filename |
* @param array attributes from <file> tag in package.xml |
* @param string path to install the file in |
* @param array options from command-line |
* @access private |
*/ |
function _installFile2(&$pkg, $file, &$real_atts, $tmp_path, $options) |
{ |
$atts = $real_atts; |
if (!isset($this->_registry)) { |
$this->_registry = &$this->config->getRegistry(); |
} |
$channel = $pkg->getChannel(); |
// {{{ assemble the destination paths |
if (!in_array($atts['attribs']['role'], |
PEAR_Installer_Role::getValidRoles($pkg->getPackageType()))) { |
return $this->raiseError('Invalid role `' . $atts['attribs']['role'] . |
"' for file $file"); |
} |
$role = &PEAR_Installer_Role::factory($pkg, $atts['attribs']['role'], $this->config); |
$err = $role->setup($this, $pkg, $atts['attribs'], $file); |
if (PEAR::isError($err)) { |
return $err; |
} |
if (!$role->isInstallable()) { |
return; |
} |
$info = $role->processInstallation($pkg, $atts['attribs'], $file, $tmp_path); |
if (PEAR::isError($info)) { |
return $info; |
} |
list($save_destdir, $dest_dir, $dest_file, $orig_file) = $info; |
if (preg_match('~/\.\.(/|\\z)|^\.\./~', str_replace('\\', '/', $dest_file))) { |
return $this->raiseError("SECURITY ERROR: file $file (installed to $dest_file) contains parent directory reference ..", PEAR_INSTALLER_FAILED); |
} |
$final_dest_file = $installed_as = $dest_file; |
if (isset($this->_options['packagingroot'])) { |
$final_dest_file = $this->_prependPath($final_dest_file, |
$this->_options['packagingroot']); |
} |
$dest_dir = dirname($final_dest_file); |
$dest_file = $dest_dir . DIRECTORY_SEPARATOR . '.tmp' . basename($final_dest_file); |
// }}} |
if (empty($this->_options['register-only'])) { |
if (!file_exists($dest_dir) || !is_dir($dest_dir)) { |
if (!$this->mkDirHier($dest_dir)) { |
return $this->raiseError("failed to mkdir $dest_dir", |
PEAR_INSTALLER_FAILED); |
} |
$this->log(3, "+ mkdir $dest_dir"); |
} |
} |
$attribs = $atts['attribs']; |
unset($atts['attribs']); |
// pretty much nothing happens if we are only registering the install |
if (empty($this->_options['register-only'])) { |
if (!count($atts)) { // no tasks |
if (!file_exists($orig_file)) { |
return $this->raiseError("file $orig_file does not exist", |
PEAR_INSTALLER_FAILED); |
} |
if (!@copy($orig_file, $dest_file)) { |
return $this->raiseError("failed to write $dest_file: $php_errormsg", |
PEAR_INSTALLER_FAILED); |
} |
$this->log(3, "+ cp $orig_file $dest_file"); |
if (isset($attribs['md5sum'])) { |
$md5sum = md5_file($dest_file); |
} |
} else { // file with tasks |
if (!file_exists($orig_file)) { |
return $this->raiseError("file $orig_file does not exist", |
PEAR_INSTALLER_FAILED); |
} |
$contents = file_get_contents($orig_file); |
if ($contents === false) { |
$contents = ''; |
} |
if (isset($attribs['md5sum'])) { |
$md5sum = md5($contents); |
} |
foreach ($atts as $tag => $raw) { |
$tag = str_replace(array($pkg->getTasksNs() . ':', '-'), array('', '_'), $tag); |
$task = "PEAR_Task_$tag"; |
$task = new $task($this->config, $this, PEAR_TASK_INSTALL); |
if (!$task->isScript()) { // scripts are only handled after installation |
$task->init($raw, $attribs, $pkg->getLastInstalledVersion()); |
$res = $task->startSession($pkg, $contents, $final_dest_file); |
if ($res === false) { |
continue; // skip this file |
} |
if (PEAR::isError($res)) { |
return $res; |
} |
$contents = $res; // save changes |
} |
$wp = @fopen($dest_file, "wb"); |
if (!is_resource($wp)) { |
return $this->raiseError("failed to create $dest_file: $php_errormsg", |
PEAR_INSTALLER_FAILED); |
} |
if (fwrite($wp, $contents) === false) { |
return $this->raiseError("failed writing to $dest_file: $php_errormsg", |
PEAR_INSTALLER_FAILED); |
} |
fclose($wp); |
} |
} |
// {{{ check the md5 |
if (isset($md5sum)) { |
// Make sure the original md5 sum matches with expected |
if (strtolower($md5sum) === strtolower($attribs['md5sum'])) { |
$this->log(2, "md5sum ok: $final_dest_file"); |
if (isset($contents)) { |
// set md5 sum based on $content in case any tasks were run. |
$real_atts['attribs']['md5sum'] = md5($contents); |
} |
} else { |
if (empty($options['force'])) { |
// delete the file |
if (file_exists($dest_file)) { |
unlink($dest_file); |
} |
if (!isset($options['ignore-errors'])) { |
return $this->raiseError("bad md5sum for file $final_dest_file", |
PEAR_INSTALLER_FAILED); |
} |
if (!isset($options['soft'])) { |
$this->log(0, "warning : bad md5sum for file $final_dest_file"); |
} |
} else { |
if (!isset($options['soft'])) { |
$this->log(0, "warning : bad md5sum for file $final_dest_file"); |
} |
} |
} |
} else { |
$real_atts['attribs']['md5sum'] = md5_file($dest_file); |
} |
// }}} |
// {{{ set file permissions |
if (!OS_WINDOWS) { |
if ($role->isExecutable()) { |
$mode = 0777 & ~(int)octdec($this->config->get('umask')); |
$this->log(3, "+ chmod +x $dest_file"); |
} else { |
$mode = 0666 & ~(int)octdec($this->config->get('umask')); |
} |
if ($attribs['role'] != 'src') { |
$this->addFileOperation("chmod", array($mode, $dest_file)); |
if (!@chmod($dest_file, $mode)) { |
if (!isset($options['soft'])) { |
$this->log(0, "failed to change mode of $dest_file: $php_errormsg"); |
} |
} |
} |
} |
// }}} |
if ($attribs['role'] == 'src') { |
rename($dest_file, $final_dest_file); |
$this->log(2, "renamed source file $dest_file to $final_dest_file"); |
} else { |
$this->addFileOperation("rename", array($dest_file, $final_dest_file, $role->isExtension())); |
} |
} |
// Store the full path where the file was installed for easy uninstall |
if ($attribs['role'] != 'src') { |
$loc = $this->config->get($role->getLocationConfig(), null, $channel); |
$this->addFileOperation('installed_as', array($file, $installed_as, |
$loc, |
dirname(substr($installed_as, strlen($loc))))); |
} |
//$this->log(2, "installed: $dest_file"); |
return PEAR_INSTALLER_OK; |
} |
// }}} |
// {{{ addFileOperation() |
/** |
* Add a file operation to the current file transaction. |
* |
* @see startFileTransaction() |
* @param string $type This can be one of: |
* - rename: rename a file ($data has 3 values) |
* - backup: backup an existing file ($data has 1 value) |
* - removebackup: clean up backups created during install ($data has 1 value) |
* - chmod: change permissions on a file ($data has 2 values) |
* - delete: delete a file ($data has 1 value) |
* - rmdir: delete a directory if empty ($data has 1 value) |
* - installed_as: mark a file as installed ($data has 4 values). |
* @param array $data For all file operations, this array must contain the |
* full path to the file or directory that is being operated on. For |
* the rename command, the first parameter must be the file to rename, |
* the second its new name, the third whether this is a PHP extension. |
* |
* The installed_as operation contains 4 elements in this order: |
* 1. Filename as listed in the filelist element from package.xml |
* 2. Full path to the installed file |
* 3. Full path from the php_dir configuration variable used in this |
* installation |
* 4. Relative path from the php_dir that this file is installed in |
*/ |
function addFileOperation($type, $data) |
{ |
if (!is_array($data)) { |
return $this->raiseError('Internal Error: $data in addFileOperation' |
. ' must be an array, was ' . gettype($data)); |
} |
if ($type == 'chmod') { |
$octmode = decoct($data[0]); |
$this->log(3, "adding to transaction: $type $octmode $data[1]"); |
} else { |
$this->log(3, "adding to transaction: $type " . implode(" ", $data)); |
} |
$this->file_operations[] = array($type, $data); |
} |
// }}} |
// {{{ startFileTransaction() |
function startFileTransaction($rollback_in_case = false) |
{ |
if (count($this->file_operations) && $rollback_in_case) { |
$this->rollbackFileTransaction(); |
} |
$this->file_operations = array(); |
} |
// }}} |
// {{{ commitFileTransaction() |
function commitFileTransaction() |
{ |
// {{{ first, check permissions and such manually |
$errors = array(); |
foreach ($this->file_operations as $key => $tr) { |
list($type, $data) = $tr; |
switch ($type) { |
case 'rename': |
if (!file_exists($data[0])) { |
$errors[] = "cannot rename file $data[0], doesn't exist"; |
} |
// check that dest dir. is writable |
if (!is_writable(dirname($data[1]))) { |
$errors[] = "permission denied ($type): $data[1]"; |
} |
break; |
case 'chmod': |
// check that file is writable |
if (!is_writable($data[1])) { |
$errors[] = "permission denied ($type): $data[1] " . decoct($data[0]); |
} |
break; |
case 'delete': |
if (!file_exists($data[0])) { |
$this->log(2, "warning: file $data[0] doesn't exist, can't be deleted"); |
} |
// check that directory is writable |
if (file_exists($data[0])) { |
if (!is_writable(dirname($data[0]))) { |
$errors[] = "permission denied ($type): $data[0]"; |
} else { |
// make sure the file to be deleted can be opened for writing |
$fp = false; |
if (!is_dir($data[0]) && |
(!is_writable($data[0]) || !($fp = @fopen($data[0], 'a')))) { |
$errors[] = "permission denied ($type): $data[0]"; |
} elseif ($fp) { |
fclose($fp); |
} |
} |
/* Verify we are not deleting a file owned by another package |
* This can happen when a file moves from package A to B in |
* an upgrade ala http://pear.php.net/17986 |
*/ |
$info = array( |
'package' => strtolower($this->pkginfo->getName()), |
'channel' => strtolower($this->pkginfo->getChannel()), |
); |
$result = $this->_registry->checkFileMap($data[0], $info, '1.1'); |
if (is_array($result)) { |
$res = array_diff($result, $info); |
if (!empty($res)) { |
$new = $this->_registry->getPackage($result[1], $result[0]); |
$this->file_operations[$key] = false; |
$pkginfoName = $this->pkginfo->getName(); |
$newChannel = $new->getChannel(); |
$newPackage = $new->getName(); |
$this->log(3, "file $data[0] was scheduled for removal from $pkginfoName but is owned by $newChannel/$newPackage, removal has been cancelled."); |
} |
} |
} |
break; |
} |
} |
// }}} |
$n = count($this->file_operations); |
$this->log(2, "about to commit $n file operations for " . $this->pkginfo->getName()); |
$m = count($errors); |
if ($m > 0) { |
foreach ($errors as $error) { |
if (!isset($this->_options['soft'])) { |
$this->log(1, $error); |
} |
} |
if (!isset($this->_options['ignore-errors'])) { |
return false; |
} |
} |
$this->_dirtree = array(); |
// {{{ really commit the transaction |
foreach ($this->file_operations as $i => $tr) { |
if (!$tr) { |
// support removal of non-existing backups |
continue; |
} |
list($type, $data) = $tr; |
switch ($type) { |
case 'backup': |
if (!file_exists($data[0])) { |
$this->file_operations[$i] = false; |
break; |
} |
if (!@copy($data[0], $data[0] . '.bak')) { |
$this->log(1, 'Could not copy ' . $data[0] . ' to ' . $data[0] . |
'.bak ' . $php_errormsg); |
return false; |
} |
$this->log(3, "+ backup $data[0] to $data[0].bak"); |
break; |
case 'removebackup': |
if (file_exists($data[0] . '.bak') && is_writable($data[0] . '.bak')) { |
unlink($data[0] . '.bak'); |
$this->log(3, "+ rm backup of $data[0] ($data[0].bak)"); |
} |
break; |
case 'rename': |
$test = file_exists($data[1]) ? @unlink($data[1]) : null; |
if (!$test && file_exists($data[1])) { |
if ($data[2]) { |
$extra = ', this extension must be installed manually. Rename to "' . |
basename($data[1]) . '"'; |
} else { |
$extra = ''; |
} |
if (!isset($this->_options['soft'])) { |
$this->log(1, 'Could not delete ' . $data[1] . ', cannot rename ' . |
$data[0] . $extra); |
} |
if (!isset($this->_options['ignore-errors'])) { |
return false; |
} |
} |
// permissions issues with rename - copy() is far superior |
$perms = @fileperms($data[0]); |
if (!@copy($data[0], $data[1])) { |
$this->log(1, 'Could not rename ' . $data[0] . ' to ' . $data[1] . |
' ' . $php_errormsg); |
return false; |
} |
// copy over permissions, otherwise they are lost |
@chmod($data[1], $perms); |
@unlink($data[0]); |
$this->log(3, "+ mv $data[0] $data[1]"); |
break; |
case 'chmod': |
if (!@chmod($data[1], $data[0])) { |
$this->log(1, 'Could not chmod ' . $data[1] . ' to ' . |
decoct($data[0]) . ' ' . $php_errormsg); |
return false; |
} |
$octmode = decoct($data[0]); |
$this->log(3, "+ chmod $octmode $data[1]"); |
break; |
case 'delete': |
if (file_exists($data[0])) { |
if (!@unlink($data[0])) { |
$this->log(1, 'Could not delete ' . $data[0] . ' ' . |
$php_errormsg); |
return false; |
} |
$this->log(3, "+ rm $data[0]"); |
} |
break; |
case 'rmdir': |
if (file_exists($data[0])) { |
do { |
$testme = opendir($data[0]); |
while (false !== ($entry = readdir($testme))) { |
if ($entry == '.' || $entry == '..') { |
continue; |
} |
closedir($testme); |
break 2; // this directory is not empty and can't be |
// deleted |
} |
closedir($testme); |
if (!@rmdir($data[0])) { |
$this->log(1, 'Could not rmdir ' . $data[0] . ' ' . |
$php_errormsg); |
return false; |
} |
$this->log(3, "+ rmdir $data[0]"); |
} while (false); |
} |
break; |
case 'installed_as': |
$this->pkginfo->setInstalledAs($data[0], $data[1]); |
if (!isset($this->_dirtree[dirname($data[1])])) { |
$this->_dirtree[dirname($data[1])] = true; |
$this->pkginfo->setDirtree(dirname($data[1])); |
while(!empty($data[3]) && dirname($data[3]) != $data[3] && |
$data[3] != '/' && $data[3] != '\\') { |
$this->pkginfo->setDirtree($pp = |
$this->_prependPath($data[3], $data[2])); |
$this->_dirtree[$pp] = true; |
$data[3] = dirname($data[3]); |
} |
} |
break; |
} |
} |
// }}} |
$this->log(2, "successfully committed $n file operations"); |
$this->file_operations = array(); |
return true; |
} |
// }}} |
// {{{ rollbackFileTransaction() |
function rollbackFileTransaction() |
{ |
$n = count($this->file_operations); |
$this->log(2, "rolling back $n file operations"); |
foreach ($this->file_operations as $tr) { |
list($type, $data) = $tr; |
switch ($type) { |
case 'backup': |
if (file_exists($data[0] . '.bak')) { |
if (file_exists($data[0] && is_writable($data[0]))) { |
unlink($data[0]); |
} |
@copy($data[0] . '.bak', $data[0]); |
$this->log(3, "+ restore $data[0] from $data[0].bak"); |
} |
break; |
case 'removebackup': |
if (file_exists($data[0] . '.bak') && is_writable($data[0] . '.bak')) { |
unlink($data[0] . '.bak'); |
$this->log(3, "+ rm backup of $data[0] ($data[0].bak)"); |
} |
break; |
case 'rename': |
@unlink($data[0]); |
$this->log(3, "+ rm $data[0]"); |
break; |
case 'mkdir': |
@rmdir($data[0]); |
$this->log(3, "+ rmdir $data[0]"); |
break; |
case 'chmod': |
break; |
case 'delete': |
break; |
case 'installed_as': |
$this->pkginfo->setInstalledAs($data[0], false); |
break; |
} |
} |
$this->pkginfo->resetDirtree(); |
$this->file_operations = array(); |
} |
// }}} |
// {{{ mkDirHier($dir) |
function mkDirHier($dir) |
{ |
$this->addFileOperation('mkdir', array($dir)); |
return parent::mkDirHier($dir); |
} |
// }}} |
// {{{ _parsePackageXml() |
function _parsePackageXml(&$descfile) |
{ |
// Parse xml file ----------------------------------------------- |
$pkg = new PEAR_PackageFile($this->config, $this->debug); |
PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN); |
$p = &$pkg->fromAnyFile($descfile, PEAR_VALIDATE_INSTALLING); |
PEAR::staticPopErrorHandling(); |
if (PEAR::isError($p)) { |
if (is_array($p->getUserInfo())) { |
foreach ($p->getUserInfo() as $err) { |
$loglevel = $err['level'] == 'error' ? 0 : 1; |
if (!isset($this->_options['soft'])) { |
$this->log($loglevel, ucfirst($err['level']) . ': ' . $err['message']); |
} |
} |
} |
return $this->raiseError('Installation failed: invalid package file'); |
} |
$descfile = $p->getPackageFile(); |
return $p; |
} |
// }}} |
/** |
* Set the list of PEAR_Downloader_Package objects to allow more sane |
* dependency validation |
* @param array |
*/ |
function setDownloadedPackages(&$pkgs) |
{ |
PEAR::pushErrorHandling(PEAR_ERROR_RETURN); |
$err = $this->analyzeDependencies($pkgs); |
PEAR::popErrorHandling(); |
if (PEAR::isError($err)) { |
return $err; |
} |
$this->_downloadedPackages = &$pkgs; |
} |
/** |
* Set the list of PEAR_Downloader_Package objects to allow more sane |
* dependency validation |
* @param array |
*/ |
function setUninstallPackages(&$pkgs) |
{ |
$this->_downloadedPackages = &$pkgs; |
} |
function getInstallPackages() |
{ |
return $this->_downloadedPackages; |
} |
// {{{ install() |
/** |
* Installs the files within the package file specified. |
* |
* @param string|PEAR_Downloader_Package $pkgfile path to the package file, |
* or a pre-initialized packagefile object |
* @param array $options |
* recognized options: |
* - installroot : optional prefix directory for installation |
* - force : force installation |
* - register-only : update registry but don't install files |
* - upgrade : upgrade existing install |
* - soft : fail silently |
* - nodeps : ignore dependency conflicts/missing dependencies |
* - alldeps : install all dependencies |
* - onlyreqdeps : install only required dependencies |
* |
* @return array|PEAR_Error package info if successful |
*/ |
function install($pkgfile, $options = array()) |
{ |
$this->_options = $options; |
$this->_registry = &$this->config->getRegistry(); |
if (is_object($pkgfile)) { |
$dlpkg = &$pkgfile; |
$pkg = $pkgfile->getPackageFile(); |
$pkgfile = $pkg->getArchiveFile(); |
$descfile = $pkg->getPackageFile(); |
} else { |
$descfile = $pkgfile; |
$pkg = $this->_parsePackageXml($descfile); |
if (PEAR::isError($pkg)) { |
return $pkg; |
} |
} |
$tmpdir = dirname($descfile); |
if (realpath($descfile) != realpath($pkgfile)) { |
// Use the temp_dir since $descfile can contain the download dir path |
$tmpdir = $this->config->get('temp_dir', null, 'pear.php.net'); |
$tmpdir = System::mktemp('-d -t "' . $tmpdir . '"'); |
$tar = new Archive_Tar($pkgfile); |
if (!$tar->extract($tmpdir)) { |
return $this->raiseError("unable to unpack $pkgfile"); |
} |
} |
$pkgname = $pkg->getName(); |
$channel = $pkg->getChannel(); |
if (isset($options['installroot'])) { |
$this->config->setInstallRoot($options['installroot']); |
$this->_registry = &$this->config->getRegistry(); |
$installregistry = &$this->_registry; |
$this->installroot = ''; // all done automagically now |
$php_dir = $this->config->get('php_dir', null, $channel); |
} else { |
$this->config->setInstallRoot(false); |
$this->_registry = &$this->config->getRegistry(); |
if (isset($this->_options['packagingroot'])) { |
$regdir = $this->_prependPath( |
$this->config->get('php_dir', null, 'pear.php.net'), |
$this->_options['packagingroot']); |
$metadata_dir = $this->config->get('metadata_dir', null, 'pear.php.net'); |
if ($metadata_dir) { |
$metadata_dir = $this->_prependPath( |
$metadata_dir, |
$this->_options['packagingroot']); |
} |
$packrootphp_dir = $this->_prependPath( |
$this->config->get('php_dir', null, $channel), |
$this->_options['packagingroot']); |
$installregistry = new PEAR_Registry($regdir, false, false, $metadata_dir); |
if (!$installregistry->channelExists($channel, true)) { |
// we need to fake a channel-discover of this channel |
$chanobj = $this->_registry->getChannel($channel, true); |
$installregistry->addChannel($chanobj); |
} |
$php_dir = $packrootphp_dir; |
} else { |
$installregistry = &$this->_registry; |
$php_dir = $this->config->get('php_dir', null, $channel); |
} |
$this->installroot = ''; |
} |
// {{{ checks to do when not in "force" mode |
if (empty($options['force']) && |
(file_exists($this->config->get('php_dir')) && |
is_dir($this->config->get('php_dir')))) { |
$testp = $channel == 'pear.php.net' ? $pkgname : array($channel, $pkgname); |
$instfilelist = $pkg->getInstallationFileList(true); |
if (PEAR::isError($instfilelist)) { |
return $instfilelist; |
} |
// ensure we have the most accurate registry |
$installregistry->flushFileMap(); |
$test = $installregistry->checkFileMap($instfilelist, $testp, '1.1'); |
if (PEAR::isError($test)) { |
return $test; |
} |
if (sizeof($test)) { |
$pkgs = $this->getInstallPackages(); |
$found = false; |
foreach ($pkgs as $param) { |
if ($pkg->isSubpackageOf($param)) { |
$found = true; |
break; |
} |
} |
if ($found) { |
// subpackages can conflict with earlier versions of parent packages |
$parentreg = $installregistry->packageInfo($param->getPackage(), null, $param->getChannel()); |
$tmp = $test; |
foreach ($tmp as $file => $info) { |
if (is_array($info)) { |
if (strtolower($info[1]) == strtolower($param->getPackage()) && |
strtolower($info[0]) == strtolower($param->getChannel()) |
) { |
if (isset($parentreg['filelist'][$file])) { |
unset($parentreg['filelist'][$file]); |
} else{ |
$pos = strpos($file, '/'); |
$basedir = substr($file, 0, $pos); |
$file2 = substr($file, $pos + 1); |
if (isset($parentreg['filelist'][$file2]['baseinstalldir']) |
&& $parentreg['filelist'][$file2]['baseinstalldir'] === $basedir |
) { |
unset($parentreg['filelist'][$file2]); |
} |
} |
unset($test[$file]); |
} |
} else { |
if (strtolower($param->getChannel()) != 'pear.php.net') { |
continue; |
} |
if (strtolower($info) == strtolower($param->getPackage())) { |
if (isset($parentreg['filelist'][$file])) { |
unset($parentreg['filelist'][$file]); |
} else{ |
$pos = strpos($file, '/'); |
$basedir = substr($file, 0, $pos); |
$file2 = substr($file, $pos + 1); |
if (isset($parentreg['filelist'][$file2]['baseinstalldir']) |
&& $parentreg['filelist'][$file2]['baseinstalldir'] === $basedir |
) { |
unset($parentreg['filelist'][$file2]); |
} |
} |
unset($test[$file]); |
} |
} |
} |
$pfk = new PEAR_PackageFile($this->config); |
$parentpkg = &$pfk->fromArray($parentreg); |
$installregistry->updatePackage2($parentpkg); |
} |
if ($param->getChannel() == 'pecl.php.net' && isset($options['upgrade'])) { |
$tmp = $test; |
foreach ($tmp as $file => $info) { |
if (is_string($info)) { |
// pear.php.net packages are always stored as strings |
if (strtolower($info) == strtolower($param->getPackage())) { |
// upgrading existing package |
unset($test[$file]); |
} |
} |
} |
} |
if (count($test)) { |
$msg = "$channel/$pkgname: conflicting files found:\n"; |
$longest = max(array_map("strlen", array_keys($test))); |
$fmt = "%${longest}s (%s)\n"; |
foreach ($test as $file => $info) { |
if (!is_array($info)) { |
$info = array('pear.php.net', $info); |
} |
$info = $info[0] . '/' . $info[1]; |
$msg .= sprintf($fmt, $file, $info); |
} |
if (!isset($options['ignore-errors'])) { |
return $this->raiseError($msg); |
} |
if (!isset($options['soft'])) { |
$this->log(0, "WARNING: $msg"); |
} |
} |
} |
} |
// }}} |
$this->startFileTransaction(); |
$usechannel = $channel; |
if ($channel == 'pecl.php.net') { |
$test = $installregistry->packageExists($pkgname, $channel); |
if (!$test) { |
$test = $installregistry->packageExists($pkgname, 'pear.php.net'); |
$usechannel = 'pear.php.net'; |
} |
} else { |
$test = $installregistry->packageExists($pkgname, $channel); |
} |
if (empty($options['upgrade']) && empty($options['soft'])) { |
// checks to do only when installing new packages |
if (empty($options['force']) && $test) { |
return $this->raiseError("$channel/$pkgname is already installed"); |
} |
} else { |
// Upgrade |
if ($test) { |
$v1 = $installregistry->packageInfo($pkgname, 'version', $usechannel); |
$v2 = $pkg->getVersion(); |
$cmp = version_compare("$v1", "$v2", 'gt'); |
if (empty($options['force']) && !version_compare("$v2", "$v1", 'gt')) { |
return $this->raiseError("upgrade to a newer version ($v2 is not newer than $v1)"); |
} |
} |
} |
// Do cleanups for upgrade and install, remove old release's files first |
if ($test && empty($options['register-only'])) { |
// when upgrading, remove old release's files first: |
if (PEAR::isError($err = $this->_deletePackageFiles($pkgname, $usechannel, |
true))) { |
if (!isset($options['ignore-errors'])) { |
return $this->raiseError($err); |
} |
if (!isset($options['soft'])) { |
$this->log(0, 'WARNING: ' . $err->getMessage()); |
} |
} else { |
$backedup = $err; |
} |
} |
// {{{ Copy files to dest dir --------------------------------------- |
// info from the package it self we want to access from _installFile |
$this->pkginfo = &$pkg; |
// used to determine whether we should build any C code |
$this->source_files = 0; |
$savechannel = $this->config->get('default_channel'); |
if (empty($options['register-only']) && !is_dir($php_dir)) { |
if (PEAR::isError(System::mkdir(array('-p'), $php_dir))) { |
return $this->raiseError("no installation destination directory '$php_dir'\n"); |
} |
} |
if (substr($pkgfile, -4) != '.xml') { |
$tmpdir .= DIRECTORY_SEPARATOR . $pkgname . '-' . $pkg->getVersion(); |
} |
$this->configSet('default_channel', $channel); |
// {{{ install files |
$ver = $pkg->getPackagexmlVersion(); |
if (version_compare($ver, '2.0', '>=')) { |
$filelist = $pkg->getInstallationFilelist(); |
} else { |
$filelist = $pkg->getFileList(); |
} |
if (PEAR::isError($filelist)) { |
return $filelist; |
} |
$p = &$installregistry->getPackage($pkgname, $channel); |
$dirtree = (empty($options['register-only']) && $p) ? $p->getDirTree() : false; |
$pkg->resetFilelist(); |
$pkg->setLastInstalledVersion($installregistry->packageInfo($pkg->getPackage(), |
'version', $pkg->getChannel())); |
foreach ($filelist as $file => $atts) { |
$this->expectError(PEAR_INSTALLER_FAILED); |
if ($pkg->getPackagexmlVersion() == '1.0') { |
$res = $this->_installFile($file, $atts, $tmpdir, $options); |
} else { |
$res = $this->_installFile2($pkg, $file, $atts, $tmpdir, $options); |
} |
$this->popExpect(); |
if (PEAR::isError($res)) { |
if (empty($options['ignore-errors'])) { |
$this->rollbackFileTransaction(); |
if ($res->getMessage() == "file does not exist") { |
$this->raiseError("file $file in package.xml does not exist"); |
} |
return $this->raiseError($res); |
} |
if (!isset($options['soft'])) { |
$this->log(0, "Warning: " . $res->getMessage()); |
} |
} |
$real = isset($atts['attribs']) ? $atts['attribs'] : $atts; |
if ($res == PEAR_INSTALLER_OK && $real['role'] != 'src') { |
// Register files that were installed |
$pkg->installedFile($file, $atts); |
} |
} |
// }}} |
// {{{ compile and install source files |
if ($this->source_files > 0 && empty($options['nobuild'])) { |
if (PEAR::isError($err = |
$this->_compileSourceFiles($savechannel, $pkg))) { |
return $err; |
} |
} |
// }}} |
if (isset($backedup)) { |
$this->_removeBackups($backedup); |
} |
if (!$this->commitFileTransaction()) { |
$this->rollbackFileTransaction(); |
$this->configSet('default_channel', $savechannel); |
return $this->raiseError("commit failed", PEAR_INSTALLER_FAILED); |
} |
// }}} |
$ret = false; |
$installphase = 'install'; |
$oldversion = false; |
// {{{ Register that the package is installed ----------------------- |
if (empty($options['upgrade'])) { |
// if 'force' is used, replace the info in registry |
$usechannel = $channel; |
if ($channel == 'pecl.php.net') { |
$test = $installregistry->packageExists($pkgname, $channel); |
if (!$test) { |
$test = $installregistry->packageExists($pkgname, 'pear.php.net'); |
$usechannel = 'pear.php.net'; |
} |
} else { |
$test = $installregistry->packageExists($pkgname, $channel); |
} |
if (!empty($options['force']) && $test) { |
$oldversion = $installregistry->packageInfo($pkgname, 'version', $usechannel); |
$installregistry->deletePackage($pkgname, $usechannel); |
} |
$ret = $installregistry->addPackage2($pkg); |
} else { |
if ($dirtree) { |
$this->startFileTransaction(); |
// attempt to delete empty directories |
uksort($dirtree, array($this, '_sortDirs')); |
foreach($dirtree as $dir => $notused) { |
$this->addFileOperation('rmdir', array($dir)); |
} |
$this->commitFileTransaction(); |
} |
$usechannel = $channel; |
if ($channel == 'pecl.php.net') { |
$test = $installregistry->packageExists($pkgname, $channel); |
if (!$test) { |
$test = $installregistry->packageExists($pkgname, 'pear.php.net'); |
$usechannel = 'pear.php.net'; |
} |
} else { |
$test = $installregistry->packageExists($pkgname, $channel); |
} |
// new: upgrade installs a package if it isn't installed |
if (!$test) { |
$ret = $installregistry->addPackage2($pkg); |
} else { |
if ($usechannel != $channel) { |
$installregistry->deletePackage($pkgname, $usechannel); |
$ret = $installregistry->addPackage2($pkg); |
} else { |
$ret = $installregistry->updatePackage2($pkg); |
} |
$installphase = 'upgrade'; |
} |
} |
if (!$ret) { |
$this->configSet('default_channel', $savechannel); |
return $this->raiseError("Adding package $channel/$pkgname to registry failed"); |
} |
// }}} |
$this->configSet('default_channel', $savechannel); |
if (class_exists('PEAR_Task_Common')) { // this is auto-included if any tasks exist |
if (PEAR_Task_Common::hasPostinstallTasks()) { |
PEAR_Task_Common::runPostinstallTasks($installphase); |
} |
} |
return $pkg->toArray(true); |
} |
// }}} |
// {{{ _compileSourceFiles() |
/** |
* @param string |
* @param PEAR_PackageFile_v1|PEAR_PackageFile_v2 |
*/ |
function _compileSourceFiles($savechannel, &$filelist) |
{ |
require_once 'PEAR/Builder.php'; |
$this->log(1, "$this->source_files source files, building"); |
$bob = new PEAR_Builder($this->ui); |
$bob->debug = $this->debug; |
$built = $bob->build($filelist, array(&$this, '_buildCallback')); |
if (PEAR::isError($built)) { |
$this->rollbackFileTransaction(); |
$this->configSet('default_channel', $savechannel); |
return $built; |
} |
$this->log(1, "\nBuild process completed successfully"); |
foreach ($built as $ext) { |
$bn = basename($ext['file']); |
list($_ext_name, $_ext_suff) = explode('.', $bn); |
if ($_ext_suff == '.so' || $_ext_suff == '.dll') { |
if (extension_loaded($_ext_name)) { |
$this->raiseError("Extension '$_ext_name' already loaded. " . |
'Please unload it in your php.ini file ' . |
'prior to install or upgrade'); |
} |
$role = 'ext'; |
} else { |
$role = 'src'; |
} |
$dest = $ext['dest']; |
$packagingroot = ''; |
if (isset($this->_options['packagingroot'])) { |
$packagingroot = $this->_options['packagingroot']; |
} |
$copyto = $this->_prependPath($dest, $packagingroot); |
$extra = $copyto != $dest ? " as '$copyto'" : ''; |
$this->log(1, "Installing '$dest'$extra"); |
$copydir = dirname($copyto); |
// pretty much nothing happens if we are only registering the install |
if (empty($this->_options['register-only'])) { |
if (!file_exists($copydir) || !is_dir($copydir)) { |
if (!$this->mkDirHier($copydir)) { |
return $this->raiseError("failed to mkdir $copydir", |
PEAR_INSTALLER_FAILED); |
} |
$this->log(3, "+ mkdir $copydir"); |
} |
if (!@copy($ext['file'], $copyto)) { |
return $this->raiseError("failed to write $copyto ($php_errormsg)", PEAR_INSTALLER_FAILED); |
} |
$this->log(3, "+ cp $ext[file] $copyto"); |
$this->addFileOperation('rename', array($ext['file'], $copyto)); |
if (!OS_WINDOWS) { |
$mode = 0666 & ~(int)octdec($this->config->get('umask')); |
$this->addFileOperation('chmod', array($mode, $copyto)); |
if (!@chmod($copyto, $mode)) { |
$this->log(0, "failed to change mode of $copyto ($php_errormsg)"); |
} |
} |
} |
$data = array( |
'role' => $role, |
'name' => $bn, |
'installed_as' => $dest, |
'php_api' => $ext['php_api'], |
'zend_mod_api' => $ext['zend_mod_api'], |
'zend_ext_api' => $ext['zend_ext_api'], |
); |
if ($filelist->getPackageXmlVersion() == '1.0') { |
$filelist->installedFile($bn, $data); |
} else { |
$filelist->installedFile($bn, array('attribs' => $data)); |
} |
} |
} |
// }}} |
function &getUninstallPackages() |
{ |
return $this->_downloadedPackages; |
} |
// {{{ uninstall() |
/** |
* Uninstall a package |
* |
* This method removes all files installed by the application, and then |
* removes any empty directories. |
* @param string package name |
* @param array Command-line options. Possibilities include: |
* |
* - installroot: base installation dir, if not the default |
* - register-only : update registry but don't remove files |
* - nodeps: do not process dependencies of other packages to ensure |
* uninstallation does not break things |
*/ |
function uninstall($package, $options = array()) |
{ |
$installRoot = isset($options['installroot']) ? $options['installroot'] : ''; |
$this->config->setInstallRoot($installRoot); |
$this->installroot = ''; |
$this->_registry = &$this->config->getRegistry(); |
if (is_object($package)) { |
$channel = $package->getChannel(); |
$pkg = $package; |
$package = $pkg->getPackage(); |
} else { |
$pkg = false; |
$info = $this->_registry->parsePackageName($package, |
$this->config->get('default_channel')); |
$channel = $info['channel']; |
$package = $info['package']; |
} |
$savechannel = $this->config->get('default_channel'); |
$this->configSet('default_channel', $channel); |
if (!is_object($pkg)) { |
$pkg = $this->_registry->getPackage($package, $channel); |
} |
if (!$pkg) { |
$this->configSet('default_channel', $savechannel); |
return $this->raiseError($this->_registry->parsedPackageNameToString( |
array( |
'channel' => $channel, |
'package' => $package |
), true) . ' not installed'); |
} |
if ($pkg->getInstalledBinary()) { |
// this is just an alias for a binary package |
return $this->_registry->deletePackage($package, $channel); |
} |
$filelist = $pkg->getFilelist(); |
PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN); |
if (!class_exists('PEAR_Dependency2')) { |
require_once 'PEAR/Dependency2.php'; |
} |
$depchecker = new PEAR_Dependency2($this->config, $options, |
array('channel' => $channel, 'package' => $package), |
PEAR_VALIDATE_UNINSTALLING); |
$e = $depchecker->validatePackageUninstall($this); |
PEAR::staticPopErrorHandling(); |
if (PEAR::isError($e)) { |
if (!isset($options['ignore-errors'])) { |
return $this->raiseError($e); |
} |
if (!isset($options['soft'])) { |
$this->log(0, 'WARNING: ' . $e->getMessage()); |
} |
} elseif (is_array($e)) { |
if (!isset($options['soft'])) { |
$this->log(0, $e[0]); |
} |
} |
$this->pkginfo = &$pkg; |
// pretty much nothing happens if we are only registering the uninstall |
if (empty($options['register-only'])) { |
// {{{ Delete the files |
$this->startFileTransaction(); |
PEAR::pushErrorHandling(PEAR_ERROR_RETURN); |
if (PEAR::isError($err = $this->_deletePackageFiles($package, $channel))) { |
PEAR::popErrorHandling(); |
$this->rollbackFileTransaction(); |
$this->configSet('default_channel', $savechannel); |
if (!isset($options['ignore-errors'])) { |
return $this->raiseError($err); |
} |
if (!isset($options['soft'])) { |
$this->log(0, 'WARNING: ' . $err->getMessage()); |
} |
} else { |
PEAR::popErrorHandling(); |
} |
if (!$this->commitFileTransaction()) { |
$this->rollbackFileTransaction(); |
if (!isset($options['ignore-errors'])) { |
return $this->raiseError("uninstall failed"); |
} |
if (!isset($options['soft'])) { |
$this->log(0, 'WARNING: uninstall failed'); |
} |
} else { |
$this->startFileTransaction(); |
$dirtree = $pkg->getDirTree(); |
if ($dirtree === false) { |
$this->configSet('default_channel', $savechannel); |
return $this->_registry->deletePackage($package, $channel); |
} |
// attempt to delete empty directories |
uksort($dirtree, array($this, '_sortDirs')); |
foreach($dirtree as $dir => $notused) { |
$this->addFileOperation('rmdir', array($dir)); |
} |
if (!$this->commitFileTransaction()) { |
$this->rollbackFileTransaction(); |
if (!isset($options['ignore-errors'])) { |
return $this->raiseError("uninstall failed"); |
} |
if (!isset($options['soft'])) { |
$this->log(0, 'WARNING: uninstall failed'); |
} |
} |
} |
// }}} |
} |
$this->configSet('default_channel', $savechannel); |
// Register that the package is no longer installed |
return $this->_registry->deletePackage($package, $channel); |
} |
/** |
* Sort a list of arrays of array(downloaded packagefilename) by dependency. |
* |
* It also removes duplicate dependencies |
* @param array an array of PEAR_PackageFile_v[1/2] objects |
* @return array|PEAR_Error array of array(packagefilename, package.xml contents) |
*/ |
function sortPackagesForUninstall(&$packages) |
{ |
$this->_dependencyDB = &PEAR_DependencyDB::singleton($this->config); |
if (PEAR::isError($this->_dependencyDB)) { |
return $this->_dependencyDB; |
} |
usort($packages, array(&$this, '_sortUninstall')); |
} |
function _sortUninstall($a, $b) |
{ |
if (!$a->getDeps() && !$b->getDeps()) { |
return 0; // neither package has dependencies, order is insignificant |
} |
if ($a->getDeps() && !$b->getDeps()) { |
return -1; // $a must be installed after $b because $a has dependencies |
} |
if (!$a->getDeps() && $b->getDeps()) { |
return 1; // $b must be installed after $a because $b has dependencies |
} |
// both packages have dependencies |
if ($this->_dependencyDB->dependsOn($a, $b)) { |
return -1; |
} |
if ($this->_dependencyDB->dependsOn($b, $a)) { |
return 1; |
} |
return 0; |
} |
// }}} |
// {{{ _sortDirs() |
function _sortDirs($a, $b) |
{ |
if (strnatcmp($a, $b) == -1) return 1; |
if (strnatcmp($a, $b) == 1) return -1; |
return 0; |
} |
// }}} |
// {{{ _buildCallback() |
function _buildCallback($what, $data) |
{ |
if (($what == 'cmdoutput' && $this->debug > 1) || |
($what == 'output' && $this->debug > 0)) { |
$this->ui->outputData(rtrim($data), 'build'); |
} |
} |
// }}} |
} |
/branches/v1.3-critias/bibliotheque/pear/PEAR/Downloader.php |
---|
New file |
0,0 → 1,1788 |
<?php |
/** |
* PEAR_Downloader, the PEAR Installer's download utility class |
* |
* PHP versions 4 and 5 |
* |
* @category pear |
* @package PEAR |
* @author Greg Beaver <cellog@php.net> |
* @author Stig Bakken <ssb@php.net> |
* @author Tomas V. V. Cox <cox@idecnet.com> |
* @author Martin Jansen <mj@php.net> |
* @copyright 1997-2009 The Authors |
* @license http://opensource.org/licenses/bsd-license.php New BSD License |
* @link http://pear.php.net/package/PEAR |
* @since File available since Release 1.3.0 |
*/ |
/** |
* Needed for constants, extending |
*/ |
require_once 'PEAR/Common.php'; |
define('PEAR_INSTALLER_OK', 1); |
define('PEAR_INSTALLER_FAILED', 0); |
define('PEAR_INSTALLER_SKIPPED', -1); |
define('PEAR_INSTALLER_ERROR_NO_PREF_STATE', 2); |
/** |
* Administration class used to download anything from the internet (PEAR Packages, |
* static URLs, xml files) |
* |
* @category pear |
* @package PEAR |
* @author Greg Beaver <cellog@php.net> |
* @author Stig Bakken <ssb@php.net> |
* @author Tomas V. V. Cox <cox@idecnet.com> |
* @author Martin Jansen <mj@php.net> |
* @copyright 1997-2009 The Authors |
* @license http://opensource.org/licenses/bsd-license.php New BSD License |
* @version Release: 1.10.1 |
* @link http://pear.php.net/package/PEAR |
* @since Class available since Release 1.3.0 |
*/ |
class PEAR_Downloader extends PEAR_Common |
{ |
/** |
* @var PEAR_Registry |
* @access private |
*/ |
var $_registry; |
/** |
* Preferred Installation State (snapshot, devel, alpha, beta, stable) |
* @var string|null |
* @access private |
*/ |
var $_preferredState; |
/** |
* Options from command-line passed to Install. |
* |
* Recognized options:<br /> |
* - onlyreqdeps : install all required dependencies as well |
* - alldeps : install all dependencies, including optional |
* - installroot : base relative path to install files in |
* - force : force a download even if warnings would prevent it |
* - nocompress : download uncompressed tarballs |
* @see PEAR_Command_Install |
* @access private |
* @var array |
*/ |
var $_options; |
/** |
* Downloaded Packages after a call to download(). |
* |
* Format of each entry: |
* |
* <code> |
* array('pkg' => 'package_name', 'file' => '/path/to/local/file', |
* 'info' => array() // parsed package.xml |
* ); |
* </code> |
* @access private |
* @var array |
*/ |
var $_downloadedPackages = array(); |
/** |
* Packages slated for download. |
* |
* This is used to prevent downloading a package more than once should it be a dependency |
* for two packages to be installed. |
* Format of each entry: |
* |
* <pre> |
* array('package_name1' => parsed package.xml, 'package_name2' => parsed package.xml, |
* ); |
* </pre> |
* @access private |
* @var array |
*/ |
var $_toDownload = array(); |
/** |
* Array of every package installed, with names lower-cased. |
* |
* Format: |
* <code> |
* array('package1' => 0, 'package2' => 1, ); |
* </code> |
* @var array |
*/ |
var $_installed = array(); |
/** |
* @var array |
* @access private |
*/ |
var $_errorStack = array(); |
/** |
* @var boolean |
* @access private |
*/ |
var $_internalDownload = false; |
/** |
* Temporary variable used in sorting packages by dependency in {@link sortPkgDeps()} |
* @var array |
* @access private |
*/ |
var $_packageSortTree; |
/** |
* Temporary directory, or configuration value where downloads will occur |
* @var string |
*/ |
var $_downloadDir; |
/** |
* List of methods that can be called both statically and non-statically. |
* @var array |
*/ |
protected static $bivalentMethods = array( |
'setErrorHandling' => true, |
'raiseError' => true, |
'throwError' => true, |
'pushErrorHandling' => true, |
'popErrorHandling' => true, |
'downloadHttp' => true, |
); |
/** |
* @param PEAR_Frontend_* |
* @param array |
* @param PEAR_Config |
*/ |
function __construct($ui = null, $options = array(), $config = null) |
{ |
parent::__construct(); |
$this->_options = $options; |
if ($config !== null) { |
$this->config = &$config; |
$this->_preferredState = $this->config->get('preferred_state'); |
} |
$this->ui = &$ui; |
if (!$this->_preferredState) { |
// don't inadvertantly use a non-set preferred_state |
$this->_preferredState = null; |
} |
if ($config !== null) { |
if (isset($this->_options['installroot'])) { |
$this->config->setInstallRoot($this->_options['installroot']); |
} |
$this->_registry = &$config->getRegistry(); |
} |
if (isset($this->_options['alldeps']) || isset($this->_options['onlyreqdeps'])) { |
$this->_installed = $this->_registry->listAllPackages(); |
foreach ($this->_installed as $key => $unused) { |
if (!count($unused)) { |
continue; |
} |
$strtolower = create_function('$a','return strtolower($a);'); |
array_walk($this->_installed[$key], $strtolower); |
} |
} |
} |
/** |
* Attempt to discover a channel's remote capabilities from |
* its server name |
* @param string |
* @return boolean |
*/ |
function discover($channel) |
{ |
$this->log(1, 'Attempting to discover channel "' . $channel . '"...'); |
PEAR::pushErrorHandling(PEAR_ERROR_RETURN); |
$callback = $this->ui ? array(&$this, '_downloadCallback') : null; |
if (!class_exists('System')) { |
require_once 'System.php'; |
} |
$tmpdir = $this->config->get('temp_dir'); |
$tmp = System::mktemp('-d -t "' . $tmpdir . '"'); |
$a = $this->downloadHttp('http://' . $channel . '/channel.xml', $this->ui, $tmp, $callback, false); |
PEAR::popErrorHandling(); |
if (PEAR::isError($a)) { |
// Attempt to fallback to https automatically. |
PEAR::pushErrorHandling(PEAR_ERROR_RETURN); |
$this->log(1, 'Attempting fallback to https instead of http on channel "' . $channel . '"...'); |
$a = $this->downloadHttp('https://' . $channel . '/channel.xml', $this->ui, $tmp, $callback, false); |
PEAR::popErrorHandling(); |
if (PEAR::isError($a)) { |
return false; |
} |
} |
list($a, $lastmodified) = $a; |
if (!class_exists('PEAR_ChannelFile')) { |
require_once 'PEAR/ChannelFile.php'; |
} |
$b = new PEAR_ChannelFile; |
if ($b->fromXmlFile($a)) { |
unlink($a); |
if ($this->config->get('auto_discover')) { |
$this->_registry->addChannel($b, $lastmodified); |
$alias = $b->getName(); |
if ($b->getName() == $this->_registry->channelName($b->getAlias())) { |
$alias = $b->getAlias(); |
} |
$this->log(1, 'Auto-discovered channel "' . $channel . |
'", alias "' . $alias . '", adding to registry'); |
} |
return true; |
} |
unlink($a); |
return false; |
} |
/** |
* For simpler unit-testing |
* @param PEAR_Downloader |
* @return PEAR_Downloader_Package |
*/ |
function newDownloaderPackage(&$t) |
{ |
if (!class_exists('PEAR_Downloader_Package')) { |
require_once 'PEAR/Downloader/Package.php'; |
} |
$a = new PEAR_Downloader_Package($t); |
return $a; |
} |
/** |
* For simpler unit-testing |
* @param PEAR_Config |
* @param array |
* @param array |
* @param int |
*/ |
function &getDependency2Object(&$c, $i, $p, $s) |
{ |
if (!class_exists('PEAR_Dependency2')) { |
require_once 'PEAR/Dependency2.php'; |
} |
$z = new PEAR_Dependency2($c, $i, $p, $s); |
return $z; |
} |
function &download($params) |
{ |
if (!count($params)) { |
$a = array(); |
return $a; |
} |
if (!isset($this->_registry)) { |
$this->_registry = &$this->config->getRegistry(); |
} |
$channelschecked = array(); |
// convert all parameters into PEAR_Downloader_Package objects |
foreach ($params as $i => $param) { |
$params[$i] = $this->newDownloaderPackage($this); |
PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN); |
$err = $params[$i]->initialize($param); |
PEAR::staticPopErrorHandling(); |
if (!$err) { |
// skip parameters that were missed by preferred_state |
continue; |
} |
if (PEAR::isError($err)) { |
if (!isset($this->_options['soft']) && $err->getMessage() !== '') { |
$this->log(0, $err->getMessage()); |
} |
$params[$i] = false; |
if (is_object($param)) { |
$param = $param->getChannel() . '/' . $param->getPackage(); |
} |
if (!isset($this->_options['soft'])) { |
$this->log(2, 'Package "' . $param . '" is not valid'); |
} |
// Message logged above in a specific verbose mode, passing null to not show up on CLI |
$this->pushError(null, PEAR_INSTALLER_SKIPPED); |
} else { |
do { |
if ($params[$i] && $params[$i]->getType() == 'local') { |
// bug #7090 skip channel.xml check for local packages |
break; |
} |
if ($params[$i] && !isset($channelschecked[$params[$i]->getChannel()]) && |
!isset($this->_options['offline']) |
) { |
$channelschecked[$params[$i]->getChannel()] = true; |
PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN); |
if (!class_exists('System')) { |
require_once 'System.php'; |
} |
$curchannel = $this->_registry->getChannel($params[$i]->getChannel()); |
if (PEAR::isError($curchannel)) { |
PEAR::staticPopErrorHandling(); |
return $this->raiseError($curchannel); |
} |
if (PEAR::isError($dir = $this->getDownloadDir())) { |
PEAR::staticPopErrorHandling(); |
break; |
} |
$mirror = $this->config->get('preferred_mirror', null, $params[$i]->getChannel()); |
$url = 'http://' . $mirror . '/channel.xml'; |
$a = $this->downloadHttp($url, $this->ui, $dir, null, $curchannel->lastModified()); |
PEAR::staticPopErrorHandling(); |
if ($a === false) { |
//channel.xml not modified |
break; |
} else if (PEAR::isError($a)) { |
// Attempt fallback to https automatically |
PEAR::pushErrorHandling(PEAR_ERROR_RETURN); |
$a = $this->downloadHttp('https://' . $mirror . |
'/channel.xml', $this->ui, $dir, null, $curchannel->lastModified()); |
PEAR::staticPopErrorHandling(); |
if (PEAR::isError($a) || !$a) { |
break; |
} |
} |
$this->log(0, 'WARNING: channel "' . $params[$i]->getChannel() . '" has ' . |
'updated its protocols, use "' . PEAR_RUNTYPE . ' channel-update ' . $params[$i]->getChannel() . |
'" to update'); |
} |
} while (false); |
if ($params[$i] && !isset($this->_options['downloadonly'])) { |
if (isset($this->_options['packagingroot'])) { |
$checkdir = $this->_prependPath( |
$this->config->get('php_dir', null, $params[$i]->getChannel()), |
$this->_options['packagingroot']); |
} else { |
$checkdir = $this->config->get('php_dir', |
null, $params[$i]->getChannel()); |
} |
while ($checkdir && $checkdir != '/' && !file_exists($checkdir)) { |
$checkdir = dirname($checkdir); |
} |
if ($checkdir == '.') { |
$checkdir = '/'; |
} |
if (!is_writeable($checkdir)) { |
return PEAR::raiseError('Cannot install, php_dir for channel "' . |
$params[$i]->getChannel() . '" is not writeable by the current user'); |
} |
} |
} |
} |
unset($channelschecked); |
PEAR_Downloader_Package::removeDuplicates($params); |
if (!count($params)) { |
$a = array(); |
return $a; |
} |
if (!isset($this->_options['nodeps']) && !isset($this->_options['offline'])) { |
$reverify = true; |
while ($reverify) { |
$reverify = false; |
foreach ($params as $i => $param) { |
//PHP Bug 40768 / PEAR Bug #10944 |
//Nested foreaches fail in PHP 5.2.1 |
key($params); |
$ret = $params[$i]->detectDependencies($params); |
if (PEAR::isError($ret)) { |
$reverify = true; |
$params[$i] = false; |
PEAR_Downloader_Package::removeDuplicates($params); |
if (!isset($this->_options['soft'])) { |
$this->log(0, $ret->getMessage()); |
} |
continue 2; |
} |
} |
} |
} |
if (isset($this->_options['offline'])) { |
$this->log(3, 'Skipping dependency download check, --offline specified'); |
} |
if (!count($params)) { |
$a = array(); |
return $a; |
} |
while (PEAR_Downloader_Package::mergeDependencies($params)); |
PEAR_Downloader_Package::removeDuplicates($params, true); |
$errorparams = array(); |
if (PEAR_Downloader_Package::detectStupidDuplicates($params, $errorparams)) { |
if (count($errorparams)) { |
foreach ($errorparams as $param) { |
$name = $this->_registry->parsedPackageNameToString($param->getParsedPackage()); |
$this->pushError('Duplicate package ' . $name . ' found', PEAR_INSTALLER_FAILED); |
} |
$a = array(); |
return $a; |
} |
} |
PEAR_Downloader_Package::removeInstalled($params); |
if (!count($params)) { |
$this->pushError('No valid packages found', PEAR_INSTALLER_FAILED); |
$a = array(); |
return $a; |
} |
PEAR::pushErrorHandling(PEAR_ERROR_RETURN); |
$err = $this->analyzeDependencies($params); |
PEAR::popErrorHandling(); |
if (!count($params)) { |
$this->pushError('No valid packages found', PEAR_INSTALLER_FAILED); |
$a = array(); |
return $a; |
} |
$ret = array(); |
$newparams = array(); |
if (isset($this->_options['pretend'])) { |
return $params; |
} |
$somefailed = false; |
foreach ($params as $i => $package) { |
PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN); |
$pf = &$params[$i]->download(); |
PEAR::staticPopErrorHandling(); |
if (PEAR::isError($pf)) { |
if (!isset($this->_options['soft'])) { |
$this->log(1, $pf->getMessage()); |
$this->log(0, 'Error: cannot download "' . |
$this->_registry->parsedPackageNameToString($package->getParsedPackage(), |
true) . |
'"'); |
} |
$somefailed = true; |
continue; |
} |
$newparams[] = &$params[$i]; |
$ret[] = array( |
'file' => $pf->getArchiveFile(), |
'info' => &$pf, |
'pkg' => $pf->getPackage() |
); |
} |
if ($somefailed) { |
// remove params that did not download successfully |
PEAR::pushErrorHandling(PEAR_ERROR_RETURN); |
$err = $this->analyzeDependencies($newparams, true); |
PEAR::popErrorHandling(); |
if (!count($newparams)) { |
$this->pushError('Download failed', PEAR_INSTALLER_FAILED); |
$a = array(); |
return $a; |
} |
} |
$this->_downloadedPackages = $ret; |
return $newparams; |
} |
/** |
* @param array all packages to be installed |
*/ |
function analyzeDependencies(&$params, $force = false) |
{ |
if (isset($this->_options['downloadonly'])) { |
return; |
} |
PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN); |
$redo = true; |
$reset = $hasfailed = $failed = false; |
while ($redo) { |
$redo = false; |
foreach ($params as $i => $param) { |
$deps = $param->getDeps(); |
if (!$deps) { |
$depchecker = &$this->getDependency2Object($this->config, $this->getOptions(), |
$param->getParsedPackage(), PEAR_VALIDATE_DOWNLOADING); |
$send = $param->getPackageFile(); |
$installcheck = $depchecker->validatePackage($send, $this, $params); |
if (PEAR::isError($installcheck)) { |
if (!isset($this->_options['soft'])) { |
$this->log(0, $installcheck->getMessage()); |
} |
$hasfailed = true; |
$params[$i] = false; |
$reset = true; |
$redo = true; |
$failed = false; |
PEAR_Downloader_Package::removeDuplicates($params); |
continue 2; |
} |
continue; |
} |
if (!$reset && $param->alreadyValidated() && !$force) { |
continue; |
} |
if (count($deps)) { |
$depchecker = &$this->getDependency2Object($this->config, $this->getOptions(), |
$param->getParsedPackage(), PEAR_VALIDATE_DOWNLOADING); |
$send = $param->getPackageFile(); |
if ($send === null) { |
$send = $param->getDownloadURL(); |
} |
$installcheck = $depchecker->validatePackage($send, $this, $params); |
if (PEAR::isError($installcheck)) { |
if (!isset($this->_options['soft'])) { |
$this->log(0, $installcheck->getMessage()); |
} |
$hasfailed = true; |
$params[$i] = false; |
$reset = true; |
$redo = true; |
$failed = false; |
PEAR_Downloader_Package::removeDuplicates($params); |
continue 2; |
} |
$failed = false; |
if (isset($deps['required']) && is_array($deps['required'])) { |
foreach ($deps['required'] as $type => $dep) { |
// note: Dependency2 will never return a PEAR_Error if ignore-errors |
// is specified, so soft is needed to turn off logging |
if (!isset($dep[0])) { |
if (PEAR::isError($e = $depchecker->{"validate{$type}Dependency"}($dep, |
true, $params))) { |
$failed = true; |
if (!isset($this->_options['soft'])) { |
$this->log(0, $e->getMessage()); |
} |
} elseif (is_array($e) && !$param->alreadyValidated()) { |
if (!isset($this->_options['soft'])) { |
$this->log(0, $e[0]); |
} |
} |
} else { |
foreach ($dep as $d) { |
if (PEAR::isError($e = |
$depchecker->{"validate{$type}Dependency"}($d, |
true, $params))) { |
$failed = true; |
if (!isset($this->_options['soft'])) { |
$this->log(0, $e->getMessage()); |
} |
} elseif (is_array($e) && !$param->alreadyValidated()) { |
if (!isset($this->_options['soft'])) { |
$this->log(0, $e[0]); |
} |
} |
} |
} |
} |
if (isset($deps['optional']) && is_array($deps['optional'])) { |
foreach ($deps['optional'] as $type => $dep) { |
if (!isset($dep[0])) { |
if (PEAR::isError($e = |
$depchecker->{"validate{$type}Dependency"}($dep, |
false, $params))) { |
$failed = true; |
if (!isset($this->_options['soft'])) { |
$this->log(0, $e->getMessage()); |
} |
} elseif (is_array($e) && !$param->alreadyValidated()) { |
if (!isset($this->_options['soft'])) { |
$this->log(0, $e[0]); |
} |
} |
} else { |
foreach ($dep as $d) { |
if (PEAR::isError($e = |
$depchecker->{"validate{$type}Dependency"}($d, |
false, $params))) { |
$failed = true; |
if (!isset($this->_options['soft'])) { |
$this->log(0, $e->getMessage()); |
} |
} elseif (is_array($e) && !$param->alreadyValidated()) { |
if (!isset($this->_options['soft'])) { |
$this->log(0, $e[0]); |
} |
} |
} |
} |
} |
} |
$groupname = $param->getGroup(); |
if (isset($deps['group']) && $groupname) { |
if (!isset($deps['group'][0])) { |
$deps['group'] = array($deps['group']); |
} |
$found = false; |
foreach ($deps['group'] as $group) { |
if ($group['attribs']['name'] == $groupname) { |
$found = true; |
break; |
} |
} |
if ($found) { |
unset($group['attribs']); |
foreach ($group as $type => $dep) { |
if (!isset($dep[0])) { |
if (PEAR::isError($e = |
$depchecker->{"validate{$type}Dependency"}($dep, |
false, $params))) { |
$failed = true; |
if (!isset($this->_options['soft'])) { |
$this->log(0, $e->getMessage()); |
} |
} elseif (is_array($e) && !$param->alreadyValidated()) { |
if (!isset($this->_options['soft'])) { |
$this->log(0, $e[0]); |
} |
} |
} else { |
foreach ($dep as $d) { |
if (PEAR::isError($e = |
$depchecker->{"validate{$type}Dependency"}($d, |
false, $params))) { |
$failed = true; |
if (!isset($this->_options['soft'])) { |
$this->log(0, $e->getMessage()); |
} |
} elseif (is_array($e) && !$param->alreadyValidated()) { |
if (!isset($this->_options['soft'])) { |
$this->log(0, $e[0]); |
} |
} |
} |
} |
} |
} |
} |
} else { |
foreach ($deps as $dep) { |
if (PEAR::isError($e = $depchecker->validateDependency1($dep, $params))) { |
$failed = true; |
if (!isset($this->_options['soft'])) { |
$this->log(0, $e->getMessage()); |
} |
} elseif (is_array($e) && !$param->alreadyValidated()) { |
if (!isset($this->_options['soft'])) { |
$this->log(0, $e[0]); |
} |
} |
} |
} |
$params[$i]->setValidated(); |
} |
if ($failed) { |
$hasfailed = true; |
$params[$i] = false; |
$reset = true; |
$redo = true; |
$failed = false; |
PEAR_Downloader_Package::removeDuplicates($params); |
continue 2; |
} |
} |
} |
PEAR::staticPopErrorHandling(); |
if ($hasfailed && (isset($this->_options['ignore-errors']) || |
isset($this->_options['nodeps']))) { |
// this is probably not needed, but just in case |
if (!isset($this->_options['soft'])) { |
$this->log(0, 'WARNING: dependencies failed'); |
} |
} |
} |
/** |
* Retrieve the directory that downloads will happen in |
* @access private |
* @return string |
*/ |
function getDownloadDir() |
{ |
if (isset($this->_downloadDir)) { |
return $this->_downloadDir; |
} |
$downloaddir = $this->config->get('download_dir'); |
if (empty($downloaddir) || (is_dir($downloaddir) && !is_writable($downloaddir))) { |
if (is_dir($downloaddir) && !is_writable($downloaddir)) { |
$this->log(0, 'WARNING: configuration download directory "' . $downloaddir . |
'" is not writeable. Change download_dir config variable to ' . |
'a writeable dir to avoid this warning'); |
} |
if (!class_exists('System')) { |
require_once 'System.php'; |
} |
if (PEAR::isError($downloaddir = System::mktemp('-d'))) { |
return $downloaddir; |
} |
$this->log(3, '+ tmp dir created at ' . $downloaddir); |
} |
if (!is_writable($downloaddir)) { |
if (PEAR::isError(System::mkdir(array('-p', $downloaddir))) || |
!is_writable($downloaddir)) { |
return PEAR::raiseError('download directory "' . $downloaddir . |
'" is not writeable. Change download_dir config variable to ' . |
'a writeable dir'); |
} |
} |
return $this->_downloadDir = $downloaddir; |
} |
function setDownloadDir($dir) |
{ |
if (!@is_writable($dir)) { |
if (PEAR::isError(System::mkdir(array('-p', $dir)))) { |
return PEAR::raiseError('download directory "' . $dir . |
'" is not writeable. Change download_dir config variable to ' . |
'a writeable dir'); |
} |
} |
$this->_downloadDir = $dir; |
} |
function configSet($key, $value, $layer = 'user', $channel = false) |
{ |
$this->config->set($key, $value, $layer, $channel); |
$this->_preferredState = $this->config->get('preferred_state', null, $channel); |
if (!$this->_preferredState) { |
// don't inadvertantly use a non-set preferred_state |
$this->_preferredState = null; |
} |
} |
function setOptions($options) |
{ |
$this->_options = $options; |
} |
function getOptions() |
{ |
return $this->_options; |
} |
/** |
* @param array output of {@link parsePackageName()} |
* @access private |
*/ |
function _getPackageDownloadUrl($parr) |
{ |
$curchannel = $this->config->get('default_channel'); |
$this->configSet('default_channel', $parr['channel']); |
// getDownloadURL returns an array. On error, it only contains information |
// on the latest release as array(version, info). On success it contains |
// array(version, info, download url string) |
$state = isset($parr['state']) ? $parr['state'] : $this->config->get('preferred_state'); |
if (!$this->_registry->channelExists($parr['channel'])) { |
do { |
if ($this->config->get('auto_discover') && $this->discover($parr['channel'])) { |
break; |
} |
$this->configSet('default_channel', $curchannel); |
return PEAR::raiseError('Unknown remote channel: ' . $parr['channel']); |
} while (false); |
} |
$chan = $this->_registry->getChannel($parr['channel']); |
if (PEAR::isError($chan)) { |
return $chan; |
} |
PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN); |
$version = $this->_registry->packageInfo($parr['package'], 'version', $parr['channel']); |
$stability = $this->_registry->packageInfo($parr['package'], 'stability', $parr['channel']); |
// package is installed - use the installed release stability level |
if (!isset($parr['state']) && $stability !== null) { |
$state = $stability['release']; |
} |
PEAR::staticPopErrorHandling(); |
$base2 = false; |
$preferred_mirror = $this->config->get('preferred_mirror'); |
if (!$chan->supportsREST($preferred_mirror) || |
( |
!($base2 = $chan->getBaseURL('REST1.3', $preferred_mirror)) |
&& |
!($base = $chan->getBaseURL('REST1.0', $preferred_mirror)) |
) |
) { |
return $this->raiseError($parr['channel'] . ' is using a unsupported protocol - This should never happen.'); |
} |
if ($base2) { |
$rest = &$this->config->getREST('1.3', $this->_options); |
$base = $base2; |
} else { |
$rest = &$this->config->getREST('1.0', $this->_options); |
} |
$downloadVersion = false; |
if (!isset($parr['version']) && !isset($parr['state']) && $version |
&& !PEAR::isError($version) |
&& !isset($this->_options['downloadonly']) |
) { |
$downloadVersion = $version; |
} |
$url = $rest->getDownloadURL($base, $parr, $state, $downloadVersion, $chan->getName()); |
if (PEAR::isError($url)) { |
$this->configSet('default_channel', $curchannel); |
return $url; |
} |
if ($parr['channel'] != $curchannel) { |
$this->configSet('default_channel', $curchannel); |
} |
if (!is_array($url)) { |
return $url; |
} |
$url['raw'] = false; // no checking is necessary for REST |
if (!is_array($url['info'])) { |
return PEAR::raiseError('Invalid remote dependencies retrieved from REST - ' . |
'this should never happen'); |
} |
if (!isset($this->_options['force']) && |
!isset($this->_options['downloadonly']) && |
$version && |
!PEAR::isError($version) && |
!isset($parr['group']) |
) { |
if (version_compare($version, $url['version'], '=')) { |
return PEAR::raiseError($this->_registry->parsedPackageNameToString( |
$parr, true) . ' is already installed and is the same as the ' . |
'released version ' . $url['version'], -976); |
} |
if (version_compare($version, $url['version'], '>')) { |
return PEAR::raiseError($this->_registry->parsedPackageNameToString( |
$parr, true) . ' is already installed and is newer than detected ' . |
'released version ' . $url['version'], -976); |
} |
} |
if (isset($url['info']['required']) || $url['compatible']) { |
require_once 'PEAR/PackageFile/v2.php'; |
$pf = new PEAR_PackageFile_v2; |
$pf->setRawChannel($parr['channel']); |
if ($url['compatible']) { |
$pf->setRawCompatible($url['compatible']); |
} |
} else { |
require_once 'PEAR/PackageFile/v1.php'; |
$pf = new PEAR_PackageFile_v1; |
} |
$pf->setRawPackage($url['package']); |
$pf->setDeps($url['info']); |
if ($url['compatible']) { |
$pf->setCompatible($url['compatible']); |
} |
$pf->setRawState($url['stability']); |
$url['info'] = &$pf; |
if (!extension_loaded("zlib") || isset($this->_options['nocompress'])) { |
$ext = '.tar'; |
} else { |
$ext = '.tgz'; |
} |
if (is_array($url) && isset($url['url'])) { |
$url['url'] .= $ext; |
} |
return $url; |
} |
/** |
* @param array dependency array |
* @access private |
*/ |
function _getDepPackageDownloadUrl($dep, $parr) |
{ |
$xsdversion = isset($dep['rel']) ? '1.0' : '2.0'; |
$curchannel = $this->config->get('default_channel'); |
if (isset($dep['uri'])) { |
$xsdversion = '2.0'; |
$chan = $this->_registry->getChannel('__uri'); |
if (PEAR::isError($chan)) { |
return $chan; |
} |
$version = $this->_registry->packageInfo($dep['name'], 'version', '__uri'); |
$this->configSet('default_channel', '__uri'); |
} else { |
if (isset($dep['channel'])) { |
$remotechannel = $dep['channel']; |
} else { |
$remotechannel = 'pear.php.net'; |
} |
if (!$this->_registry->channelExists($remotechannel)) { |
do { |
if ($this->config->get('auto_discover')) { |
if ($this->discover($remotechannel)) { |
break; |
} |
} |
return PEAR::raiseError('Unknown remote channel: ' . $remotechannel); |
} while (false); |
} |
$chan = $this->_registry->getChannel($remotechannel); |
if (PEAR::isError($chan)) { |
return $chan; |
} |
$version = $this->_registry->packageInfo($dep['name'], 'version', $remotechannel); |
$this->configSet('default_channel', $remotechannel); |
} |
$state = isset($parr['state']) ? $parr['state'] : $this->config->get('preferred_state'); |
if (isset($parr['state']) && isset($parr['version'])) { |
unset($parr['state']); |
} |
if (isset($dep['uri'])) { |
$info = $this->newDownloaderPackage($this); |
PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN); |
$err = $info->initialize($dep); |
PEAR::staticPopErrorHandling(); |
if (!$err) { |
// skip parameters that were missed by preferred_state |
return PEAR::raiseError('Cannot initialize dependency'); |
} |
if (PEAR::isError($err)) { |
if (!isset($this->_options['soft'])) { |
$this->log(0, $err->getMessage()); |
} |
if (is_object($info)) { |
$param = $info->getChannel() . '/' . $info->getPackage(); |
} |
return PEAR::raiseError('Package "' . $param . '" is not valid'); |
} |
return $info; |
} elseif ($chan->supportsREST($this->config->get('preferred_mirror')) |
&& |
( |
($base2 = $chan->getBaseURL('REST1.3', $this->config->get('preferred_mirror'))) |
|| |
($base = $chan->getBaseURL('REST1.0', $this->config->get('preferred_mirror'))) |
) |
) { |
if ($base2) { |
$base = $base2; |
$rest = &$this->config->getREST('1.3', $this->_options); |
} else { |
$rest = &$this->config->getREST('1.0', $this->_options); |
} |
$url = $rest->getDepDownloadURL($base, $xsdversion, $dep, $parr, |
$state, $version, $chan->getName()); |
if (PEAR::isError($url)) { |
return $url; |
} |
if ($parr['channel'] != $curchannel) { |
$this->configSet('default_channel', $curchannel); |
} |
if (!is_array($url)) { |
return $url; |
} |
$url['raw'] = false; // no checking is necessary for REST |
if (!is_array($url['info'])) { |
return PEAR::raiseError('Invalid remote dependencies retrieved from REST - ' . |
'this should never happen'); |
} |
if (isset($url['info']['required'])) { |
if (!class_exists('PEAR_PackageFile_v2')) { |
require_once 'PEAR/PackageFile/v2.php'; |
} |
$pf = new PEAR_PackageFile_v2; |
$pf->setRawChannel($remotechannel); |
} else { |
if (!class_exists('PEAR_PackageFile_v1')) { |
require_once 'PEAR/PackageFile/v1.php'; |
} |
$pf = new PEAR_PackageFile_v1; |
} |
$pf->setRawPackage($url['package']); |
$pf->setDeps($url['info']); |
if ($url['compatible']) { |
$pf->setCompatible($url['compatible']); |
} |
$pf->setRawState($url['stability']); |
$url['info'] = &$pf; |
if (!extension_loaded("zlib") || isset($this->_options['nocompress'])) { |
$ext = '.tar'; |
} else { |
$ext = '.tgz'; |
} |
if (is_array($url) && isset($url['url'])) { |
$url['url'] .= $ext; |
} |
return $url; |
} |
return $this->raiseError($parr['channel'] . ' is using a unsupported protocol - This should never happen.'); |
} |
/** |
* @deprecated in favor of _getPackageDownloadUrl |
*/ |
function getPackageDownloadUrl($package, $version = null, $channel = false) |
{ |
if ($version) { |
$package .= "-$version"; |
} |
if ($this === null || $this->_registry === null) { |
$package = "http://pear.php.net/get/$package"; |
} else { |
$chan = $this->_registry->getChannel($channel); |
if (PEAR::isError($chan)) { |
return ''; |
} |
$package = "http://" . $chan->getServer() . "/get/$package"; |
} |
if (!extension_loaded("zlib")) { |
$package .= '?uncompress=yes'; |
} |
return $package; |
} |
/** |
* Retrieve a list of downloaded packages after a call to {@link download()}. |
* |
* Also resets the list of downloaded packages. |
* @return array |
*/ |
function getDownloadedPackages() |
{ |
$ret = $this->_downloadedPackages; |
$this->_downloadedPackages = array(); |
$this->_toDownload = array(); |
return $ret; |
} |
function _downloadCallback($msg, $params = null) |
{ |
switch ($msg) { |
case 'saveas': |
$this->log(1, "downloading $params ..."); |
break; |
case 'done': |
$this->log(1, '...done: ' . number_format($params, 0, '', ',') . ' bytes'); |
break; |
case 'bytesread': |
static $bytes; |
if (empty($bytes)) { |
$bytes = 0; |
} |
if (!($bytes % 10240)) { |
$this->log(1, '.', false); |
} |
$bytes += $params; |
break; |
case 'start': |
if($params[1] == -1) { |
$length = "Unknown size"; |
} else { |
$length = number_format($params[1], 0, '', ',')." bytes"; |
} |
$this->log(1, "Starting to download {$params[0]} ($length)"); |
break; |
} |
if (method_exists($this->ui, '_downloadCallback')) |
$this->ui->_downloadCallback($msg, $params); |
} |
function _prependPath($path, $prepend) |
{ |
if (strlen($prepend) > 0) { |
if (OS_WINDOWS && preg_match('/^[a-z]:/i', $path)) { |
if (preg_match('/^[a-z]:/i', $prepend)) { |
$prepend = substr($prepend, 2); |
} elseif ($prepend{0} != '\\') { |
$prepend = "\\$prepend"; |
} |
$path = substr($path, 0, 2) . $prepend . substr($path, 2); |
} else { |
$path = $prepend . $path; |
} |
} |
return $path; |
} |
/** |
* @param string |
* @param integer |
*/ |
function pushError($errmsg, $code = -1) |
{ |
array_push($this->_errorStack, array($errmsg, $code)); |
} |
function getErrorMsgs() |
{ |
$msgs = array(); |
$errs = $this->_errorStack; |
foreach ($errs as $err) { |
$msgs[] = $err[0]; |
} |
$this->_errorStack = array(); |
return $msgs; |
} |
/** |
* for BC |
* |
* @deprecated |
*/ |
function sortPkgDeps(&$packages, $uninstall = false) |
{ |
$uninstall ? |
$this->sortPackagesForUninstall($packages) : |
$this->sortPackagesForInstall($packages); |
} |
/** |
* Sort a list of arrays of array(downloaded packagefilename) by dependency. |
* |
* This uses the topological sort method from graph theory, and the |
* Structures_Graph package to properly sort dependencies for installation. |
* @param array an array of downloaded PEAR_Downloader_Packages |
* @return array array of array(packagefilename, package.xml contents) |
*/ |
function sortPackagesForInstall(&$packages) |
{ |
require_once 'Structures/Graph.php'; |
require_once 'Structures/Graph/Node.php'; |
require_once 'Structures/Graph/Manipulator/TopologicalSorter.php'; |
$depgraph = new Structures_Graph(true); |
$nodes = array(); |
$reg = &$this->config->getRegistry(); |
foreach ($packages as $i => $package) { |
$pname = $reg->parsedPackageNameToString( |
array( |
'channel' => $package->getChannel(), |
'package' => strtolower($package->getPackage()), |
)); |
$nodes[$pname] = new Structures_Graph_Node; |
$nodes[$pname]->setData($packages[$i]); |
$depgraph->addNode($nodes[$pname]); |
} |
$deplinks = array(); |
foreach ($nodes as $package => $node) { |
$pf = &$node->getData(); |
$pdeps = $pf->getDeps(true); |
if (!$pdeps) { |
continue; |
} |
if ($pf->getPackagexmlVersion() == '1.0') { |
foreach ($pdeps as $dep) { |
if ($dep['type'] != 'pkg' || |
(isset($dep['optional']) && $dep['optional'] == 'yes')) { |
continue; |
} |
$dname = $reg->parsedPackageNameToString( |
array( |
'channel' => 'pear.php.net', |
'package' => strtolower($dep['name']), |
)); |
if (isset($nodes[$dname])) { |
if (!isset($deplinks[$dname])) { |
$deplinks[$dname] = array(); |
} |
$deplinks[$dname][$package] = 1; |
// dependency is in installed packages |
continue; |
} |
$dname = $reg->parsedPackageNameToString( |
array( |
'channel' => 'pecl.php.net', |
'package' => strtolower($dep['name']), |
)); |
if (isset($nodes[$dname])) { |
if (!isset($deplinks[$dname])) { |
$deplinks[$dname] = array(); |
} |
$deplinks[$dname][$package] = 1; |
// dependency is in installed packages |
continue; |
} |
} |
} else { |
// the only ordering we care about is: |
// 1) subpackages must be installed before packages that depend on them |
// 2) required deps must be installed before packages that depend on them |
if (isset($pdeps['required']['subpackage'])) { |
$t = $pdeps['required']['subpackage']; |
if (!isset($t[0])) { |
$t = array($t); |
} |
$this->_setupGraph($t, $reg, $deplinks, $nodes, $package); |
} |
if (isset($pdeps['group'])) { |
if (!isset($pdeps['group'][0])) { |
$pdeps['group'] = array($pdeps['group']); |
} |
foreach ($pdeps['group'] as $group) { |
if (isset($group['subpackage'])) { |
$t = $group['subpackage']; |
if (!isset($t[0])) { |
$t = array($t); |
} |
$this->_setupGraph($t, $reg, $deplinks, $nodes, $package); |
} |
} |
} |
if (isset($pdeps['optional']['subpackage'])) { |
$t = $pdeps['optional']['subpackage']; |
if (!isset($t[0])) { |
$t = array($t); |
} |
$this->_setupGraph($t, $reg, $deplinks, $nodes, $package); |
} |
if (isset($pdeps['required']['package'])) { |
$t = $pdeps['required']['package']; |
if (!isset($t[0])) { |
$t = array($t); |
} |
$this->_setupGraph($t, $reg, $deplinks, $nodes, $package); |
} |
if (isset($pdeps['group'])) { |
if (!isset($pdeps['group'][0])) { |
$pdeps['group'] = array($pdeps['group']); |
} |
foreach ($pdeps['group'] as $group) { |
if (isset($group['package'])) { |
$t = $group['package']; |
if (!isset($t[0])) { |
$t = array($t); |
} |
$this->_setupGraph($t, $reg, $deplinks, $nodes, $package); |
} |
} |
} |
} |
} |
$this->_detectDepCycle($deplinks); |
foreach ($deplinks as $dependent => $parents) { |
foreach ($parents as $parent => $unused) { |
$nodes[$dependent]->connectTo($nodes[$parent]); |
} |
} |
$installOrder = Structures_Graph_Manipulator_TopologicalSorter::sort($depgraph); |
$ret = array(); |
for ($i = 0, $count = count($installOrder); $i < $count; $i++) { |
foreach ($installOrder[$i] as $index => $sortedpackage) { |
$data = &$installOrder[$i][$index]->getData(); |
$ret[] = &$nodes[$reg->parsedPackageNameToString( |
array( |
'channel' => $data->getChannel(), |
'package' => strtolower($data->getPackage()), |
))]->getData(); |
} |
} |
$packages = $ret; |
return; |
} |
/** |
* Detect recursive links between dependencies and break the cycles |
* |
* @param array |
* @access private |
*/ |
function _detectDepCycle(&$deplinks) |
{ |
do { |
$keepgoing = false; |
foreach ($deplinks as $dep => $parents) { |
foreach ($parents as $parent => $unused) { |
// reset the parent cycle detector |
$this->_testCycle(null, null, null); |
if ($this->_testCycle($dep, $deplinks, $parent)) { |
$keepgoing = true; |
unset($deplinks[$dep][$parent]); |
if (count($deplinks[$dep]) == 0) { |
unset($deplinks[$dep]); |
} |
continue 3; |
} |
} |
} |
} while ($keepgoing); |
} |
function _testCycle($test, $deplinks, $dep) |
{ |
static $visited = array(); |
if ($test === null) { |
$visited = array(); |
return; |
} |
// this happens when a parent has a dep cycle on another dependency |
// but the child is not part of the cycle |
if (isset($visited[$dep])) { |
return false; |
} |
$visited[$dep] = 1; |
if ($test == $dep) { |
return true; |
} |
if (isset($deplinks[$dep])) { |
if (in_array($test, array_keys($deplinks[$dep]), true)) { |
return true; |
} |
foreach ($deplinks[$dep] as $parent => $unused) { |
if ($this->_testCycle($test, $deplinks, $parent)) { |
return true; |
} |
} |
} |
return false; |
} |
/** |
* Set up the dependency for installation parsing |
* |
* @param array $t dependency information |
* @param PEAR_Registry $reg |
* @param array $deplinks list of dependency links already established |
* @param array $nodes all existing package nodes |
* @param string $package parent package name |
* @access private |
*/ |
function _setupGraph($t, $reg, &$deplinks, &$nodes, $package) |
{ |
foreach ($t as $dep) { |
$depchannel = !isset($dep['channel']) ? '__uri': $dep['channel']; |
$dname = $reg->parsedPackageNameToString( |
array( |
'channel' => $depchannel, |
'package' => strtolower($dep['name']), |
)); |
if (isset($nodes[$dname])) { |
if (!isset($deplinks[$dname])) { |
$deplinks[$dname] = array(); |
} |
$deplinks[$dname][$package] = 1; |
} |
} |
} |
function _dependsOn($a, $b) |
{ |
return $this->_checkDepTree(strtolower($a->getChannel()), strtolower($a->getPackage()), $b); |
} |
function _checkDepTree($channel, $package, $b, $checked = array()) |
{ |
$checked[$channel][$package] = true; |
if (!isset($this->_depTree[$channel][$package])) { |
return false; |
} |
if (isset($this->_depTree[$channel][$package][strtolower($b->getChannel())] |
[strtolower($b->getPackage())])) { |
return true; |
} |
foreach ($this->_depTree[$channel][$package] as $ch => $packages) { |
foreach ($packages as $pa => $true) { |
if ($this->_checkDepTree($ch, $pa, $b, $checked)) { |
return true; |
} |
} |
} |
return false; |
} |
function _sortInstall($a, $b) |
{ |
if (!$a->getDeps() && !$b->getDeps()) { |
return 0; // neither package has dependencies, order is insignificant |
} |
if ($a->getDeps() && !$b->getDeps()) { |
return 1; // $a must be installed after $b because $a has dependencies |
} |
if (!$a->getDeps() && $b->getDeps()) { |
return -1; // $b must be installed after $a because $b has dependencies |
} |
// both packages have dependencies |
if ($this->_dependsOn($a, $b)) { |
return 1; |
} |
if ($this->_dependsOn($b, $a)) { |
return -1; |
} |
return 0; |
} |
/** |
* Download a file through HTTP. Considers suggested file name in |
* Content-disposition: header and can run a callback function for |
* different events. The callback will be called with two |
* parameters: the callback type, and parameters. The implemented |
* callback types are: |
* |
* 'setup' called at the very beginning, parameter is a UI object |
* that should be used for all output |
* 'message' the parameter is a string with an informational message |
* 'saveas' may be used to save with a different file name, the |
* parameter is the filename that is about to be used. |
* If a 'saveas' callback returns a non-empty string, |
* that file name will be used as the filename instead. |
* Note that $save_dir will not be affected by this, only |
* the basename of the file. |
* 'start' download is starting, parameter is number of bytes |
* that are expected, or -1 if unknown |
* 'bytesread' parameter is the number of bytes read so far |
* 'done' download is complete, parameter is the total number |
* of bytes read |
* 'connfailed' if the TCP/SSL connection fails, this callback is called |
* with array(host,port,errno,errmsg) |
* 'writefailed' if writing to disk fails, this callback is called |
* with array(destfile,errmsg) |
* |
* If an HTTP proxy has been configured (http_proxy PEAR_Config |
* setting), the proxy will be used. |
* |
* @param string $url the URL to download |
* @param object $ui PEAR_Frontend_* instance |
* @param object $config PEAR_Config instance |
* @param string $save_dir directory to save file in |
* @param mixed $callback function/method to call for status |
* updates |
* @param false|string|array $lastmodified header values to check against for caching |
* use false to return the header values from this download |
* @param false|array $accept Accept headers to send |
* @param false|string $channel Channel to use for retrieving authentication |
* @return mixed Returns the full path of the downloaded file or a PEAR |
* error on failure. If the error is caused by |
* socket-related errors, the error object will |
* have the fsockopen error code available through |
* getCode(). If caching is requested, then return the header |
* values. |
* If $lastmodified was given and the there are no changes, |
* boolean false is returned. |
* |
* @access public |
*/ |
public static function _downloadHttp( |
$object, $url, &$ui, $save_dir = '.', $callback = null, $lastmodified = null, |
$accept = false, $channel = false |
) { |
static $redirect = 0; |
// always reset , so we are clean case of error |
$wasredirect = $redirect; |
$redirect = 0; |
if ($callback) { |
call_user_func($callback, 'setup', array(&$ui)); |
} |
$info = parse_url($url); |
if (!isset($info['scheme']) || !in_array($info['scheme'], array('http', 'https'))) { |
return PEAR::raiseError('Cannot download non-http URL "' . $url . '"'); |
} |
if (!isset($info['host'])) { |
return PEAR::raiseError('Cannot download from non-URL "' . $url . '"'); |
} |
$host = isset($info['host']) ? $info['host'] : null; |
$port = isset($info['port']) ? $info['port'] : null; |
$path = isset($info['path']) ? $info['path'] : null; |
if ($object !== null) { |
$config = $object->config; |
} else { |
$config = &PEAR_Config::singleton(); |
} |
$proxy_host = $proxy_port = $proxy_user = $proxy_pass = ''; |
if ($config->get('http_proxy') && |
$proxy = parse_url($config->get('http_proxy'))) { |
$proxy_host = isset($proxy['host']) ? $proxy['host'] : null; |
if (isset($proxy['scheme']) && $proxy['scheme'] == 'https') { |
$proxy_host = 'ssl://' . $proxy_host; |
} |
$proxy_port = isset($proxy['port']) ? $proxy['port'] : 8080; |
$proxy_user = isset($proxy['user']) ? urldecode($proxy['user']) : null; |
$proxy_pass = isset($proxy['pass']) ? urldecode($proxy['pass']) : null; |
if ($callback) { |
call_user_func($callback, 'message', "Using HTTP proxy $host:$port"); |
} |
} |
if (empty($port)) { |
$port = (isset($info['scheme']) && $info['scheme'] == 'https') ? 443 : 80; |
} |
$scheme = (isset($info['scheme']) && $info['scheme'] == 'https') ? 'https' : 'http'; |
if ($proxy_host != '') { |
$fp = @fsockopen($proxy_host, $proxy_port, $errno, $errstr); |
if (!$fp) { |
if ($callback) { |
call_user_func($callback, 'connfailed', array($proxy_host, $proxy_port, |
$errno, $errstr)); |
} |
return PEAR::raiseError("Connection to `$proxy_host:$proxy_port' failed: $errstr", $errno); |
} |
if ($lastmodified === false || $lastmodified) { |
$request = "GET $url HTTP/1.1\r\n"; |
$request .= "Host: $host\r\n"; |
} else { |
$request = "GET $url HTTP/1.0\r\n"; |
$request .= "Host: $host\r\n"; |
} |
} else { |
$network_host = $host; |
if (isset($info['scheme']) && $info['scheme'] == 'https') { |
$network_host = 'ssl://' . $host; |
} |
$fp = @fsockopen($network_host, $port, $errno, $errstr); |
if (!$fp) { |
if ($callback) { |
call_user_func($callback, 'connfailed', array($host, $port, |
$errno, $errstr)); |
} |
return PEAR::raiseError("Connection to `$host:$port' failed: $errstr", $errno); |
} |
if ($lastmodified === false || $lastmodified) { |
$request = "GET $path HTTP/1.1\r\n"; |
$request .= "Host: $host\r\n"; |
} else { |
$request = "GET $path HTTP/1.0\r\n"; |
$request .= "Host: $host\r\n"; |
} |
} |
$ifmodifiedsince = ''; |
if (is_array($lastmodified)) { |
if (isset($lastmodified['Last-Modified'])) { |
$ifmodifiedsince = 'If-Modified-Since: ' . $lastmodified['Last-Modified'] . "\r\n"; |
} |
if (isset($lastmodified['ETag'])) { |
$ifmodifiedsince .= "If-None-Match: $lastmodified[ETag]\r\n"; |
} |
} else { |
$ifmodifiedsince = ($lastmodified ? "If-Modified-Since: $lastmodified\r\n" : ''); |
} |
$request .= $ifmodifiedsince . |
"User-Agent: PEAR/1.10.1/PHP/" . PHP_VERSION . "\r\n"; |
if ($object !== null) { // only pass in authentication for non-static calls |
$username = $config->get('username', null, $channel); |
$password = $config->get('password', null, $channel); |
if ($username && $password) { |
$tmp = base64_encode("$username:$password"); |
$request .= "Authorization: Basic $tmp\r\n"; |
} |
} |
if ($proxy_host != '' && $proxy_user != '') { |
$request .= 'Proxy-Authorization: Basic ' . |
base64_encode($proxy_user . ':' . $proxy_pass) . "\r\n"; |
} |
if ($accept) { |
$request .= 'Accept: ' . implode(', ', $accept) . "\r\n"; |
} |
$request .= "Connection: close\r\n"; |
$request .= "\r\n"; |
fwrite($fp, $request); |
$headers = array(); |
$reply = 0; |
while (trim($line = fgets($fp, 1024))) { |
if (preg_match('/^([^:]+):\s+(.*)\s*\\z/', $line, $matches)) { |
$headers[strtolower($matches[1])] = trim($matches[2]); |
} elseif (preg_match('|^HTTP/1.[01] ([0-9]{3}) |', $line, $matches)) { |
$reply = (int)$matches[1]; |
if ($reply == 304 && ($lastmodified || ($lastmodified === false))) { |
return false; |
} |
if (!in_array($reply, array(200, 301, 302, 303, 305, 307))) { |
return PEAR::raiseError("File $scheme://$host:$port$path not valid (received: $line)"); |
} |
} |
} |
if ($reply != 200) { |
if (!isset($headers['location'])) { |
return PEAR::raiseError("File $scheme://$host:$port$path not valid (redirected but no location)"); |
} |
if ($wasredirect > 4) { |
return PEAR::raiseError("File $scheme://$host:$port$path not valid (redirection looped more than 5 times)"); |
} |
$redirect = $wasredirect + 1; |
return static::_downloadHttp($object, $headers['location'], |
$ui, $save_dir, $callback, $lastmodified, $accept); |
} |
if (isset($headers['content-disposition']) && |
preg_match('/\sfilename=\"([^;]*\S)\"\s*(;|\\z)/', $headers['content-disposition'], $matches)) { |
$save_as = basename($matches[1]); |
} else { |
$save_as = basename($url); |
} |
if ($callback) { |
$tmp = call_user_func($callback, 'saveas', $save_as); |
if ($tmp) { |
$save_as = $tmp; |
} |
} |
$dest_file = $save_dir . DIRECTORY_SEPARATOR . $save_as; |
if (is_link($dest_file)) { |
return PEAR::raiseError('SECURITY ERROR: Will not write to ' . $dest_file . ' as it is symlinked to ' . readlink($dest_file) . ' - Possible symlink attack'); |
} |
if (!$wp = @fopen($dest_file, 'wb')) { |
fclose($fp); |
if ($callback) { |
call_user_func($callback, 'writefailed', array($dest_file, $php_errormsg)); |
} |
return PEAR::raiseError("could not open $dest_file for writing"); |
} |
$length = isset($headers['content-length']) ? $headers['content-length'] : -1; |
$bytes = 0; |
if ($callback) { |
call_user_func($callback, 'start', array(basename($dest_file), $length)); |
} |
while ($data = fread($fp, 1024)) { |
$bytes += strlen($data); |
if ($callback) { |
call_user_func($callback, 'bytesread', $bytes); |
} |
if (!@fwrite($wp, $data)) { |
fclose($fp); |
if ($callback) { |
call_user_func($callback, 'writefailed', array($dest_file, $php_errormsg)); |
} |
return PEAR::raiseError("$dest_file: write failed ($php_errormsg)"); |
} |
} |
fclose($fp); |
fclose($wp); |
if ($callback) { |
call_user_func($callback, 'done', $bytes); |
} |
if ($lastmodified === false || $lastmodified) { |
if (isset($headers['etag'])) { |
$lastmodified = array('ETag' => $headers['etag']); |
} |
if (isset($headers['last-modified'])) { |
if (is_array($lastmodified)) { |
$lastmodified['Last-Modified'] = $headers['last-modified']; |
} else { |
$lastmodified = $headers['last-modified']; |
} |
} |
return array($dest_file, $lastmodified, $headers); |
} |
return $dest_file; |
} |
} |
/branches/v1.3-critias/bibliotheque/pear/PEAR/Exception.php |
---|
New file |
0,0 → 1,388 |
<?php |
/* vim: set expandtab tabstop=4 shiftwidth=4 foldmethod=marker: */ |
/** |
* PEAR_Exception |
* |
* PHP versions 4 and 5 |
* |
* @category pear |
* @package PEAR |
* @author Tomas V. V. Cox <cox@idecnet.com> |
* @author Hans Lellelid <hans@velum.net> |
* @author Bertrand Mansion <bmansion@mamasam.com> |
* @author Greg Beaver <cellog@php.net> |
* @copyright 1997-2009 The Authors |
* @license http://opensource.org/licenses/bsd-license.php New BSD License |
* @link http://pear.php.net/package/PEAR |
* @since File available since Release 1.3.3 |
*/ |
/** |
* Base PEAR_Exception Class |
* |
* 1) Features: |
* |
* - Nestable exceptions (throw new PEAR_Exception($msg, $prev_exception)) |
* - Definable triggers, shot when exceptions occur |
* - Pretty and informative error messages |
* - Added more context info available (like class, method or cause) |
* - cause can be a PEAR_Exception or an array of mixed |
* PEAR_Exceptions/PEAR_ErrorStack warnings |
* - callbacks for specific exception classes and their children |
* |
* 2) Ideas: |
* |
* - Maybe a way to define a 'template' for the output |
* |
* 3) Inherited properties from PHP Exception Class: |
* |
* protected $message |
* protected $code |
* protected $line |
* protected $file |
* private $trace |
* |
* 4) Inherited methods from PHP Exception Class: |
* |
* __clone |
* __construct |
* getMessage |
* getCode |
* getFile |
* getLine |
* getTraceSafe |
* getTraceSafeAsString |
* __toString |
* |
* 5) Usage example |
* |
* <code> |
* require_once 'PEAR/Exception.php'; |
* |
* class Test { |
* function foo() { |
* throw new PEAR_Exception('Error Message', ERROR_CODE); |
* } |
* } |
* |
* function myLogger($pear_exception) { |
* echo $pear_exception->getMessage(); |
* } |
* // each time a exception is thrown the 'myLogger' will be called |
* // (its use is completely optional) |
* PEAR_Exception::addObserver('myLogger'); |
* $test = new Test; |
* try { |
* $test->foo(); |
* } catch (PEAR_Exception $e) { |
* print $e; |
* } |
* </code> |
* |
* @category pear |
* @package PEAR |
* @author Tomas V.V.Cox <cox@idecnet.com> |
* @author Hans Lellelid <hans@velum.net> |
* @author Bertrand Mansion <bmansion@mamasam.com> |
* @author Greg Beaver <cellog@php.net> |
* @copyright 1997-2009 The Authors |
* @license http://opensource.org/licenses/bsd-license.php New BSD License |
* @version Release: 1.10.1 |
* @link http://pear.php.net/package/PEAR |
* @since Class available since Release 1.3.3 |
* |
*/ |
class PEAR_Exception extends Exception |
{ |
const OBSERVER_PRINT = -2; |
const OBSERVER_TRIGGER = -4; |
const OBSERVER_DIE = -8; |
protected $cause; |
private static $_observers = array(); |
private static $_uniqueid = 0; |
private $_trace; |
/** |
* Supported signatures: |
* - PEAR_Exception(string $message); |
* - PEAR_Exception(string $message, int $code); |
* - PEAR_Exception(string $message, Exception $cause); |
* - PEAR_Exception(string $message, Exception $cause, int $code); |
* - PEAR_Exception(string $message, PEAR_Error $cause); |
* - PEAR_Exception(string $message, PEAR_Error $cause, int $code); |
* - PEAR_Exception(string $message, array $causes); |
* - PEAR_Exception(string $message, array $causes, int $code); |
* @param string exception message |
* @param int|Exception|PEAR_Error|array|null exception cause |
* @param int|null exception code or null |
*/ |
public function __construct($message, $p2 = null, $p3 = null) |
{ |
if (is_int($p2)) { |
$code = $p2; |
$this->cause = null; |
} elseif (is_object($p2) || is_array($p2)) { |
// using is_object allows both Exception and PEAR_Error |
if (is_object($p2) && !($p2 instanceof Exception)) { |
if (!class_exists('PEAR_Error') || !($p2 instanceof PEAR_Error)) { |
throw new PEAR_Exception('exception cause must be Exception, ' . |
'array, or PEAR_Error'); |
} |
} |
$code = $p3; |
if (is_array($p2) && isset($p2['message'])) { |
// fix potential problem of passing in a single warning |
$p2 = array($p2); |
} |
$this->cause = $p2; |
} else { |
$code = null; |
$this->cause = null; |
} |
parent::__construct($message, $code); |
$this->signal(); |
} |
/** |
* @param mixed $callback - A valid php callback, see php func is_callable() |
* - A PEAR_Exception::OBSERVER_* constant |
* - An array(const PEAR_Exception::OBSERVER_*, |
* mixed $options) |
* @param string $label The name of the observer. Use this if you want |
* to remove it later with removeObserver() |
*/ |
public static function addObserver($callback, $label = 'default') |
{ |
self::$_observers[$label] = $callback; |
} |
public static function removeObserver($label = 'default') |
{ |
unset(self::$_observers[$label]); |
} |
/** |
* @return int unique identifier for an observer |
*/ |
public static function getUniqueId() |
{ |
return self::$_uniqueid++; |
} |
private function signal() |
{ |
foreach (self::$_observers as $func) { |
if (is_callable($func)) { |
call_user_func($func, $this); |
continue; |
} |
settype($func, 'array'); |
switch ($func[0]) { |
case self::OBSERVER_PRINT : |
$f = (isset($func[1])) ? $func[1] : '%s'; |
printf($f, $this->getMessage()); |
break; |
case self::OBSERVER_TRIGGER : |
$f = (isset($func[1])) ? $func[1] : E_USER_NOTICE; |
trigger_error($this->getMessage(), $f); |
break; |
case self::OBSERVER_DIE : |
$f = (isset($func[1])) ? $func[1] : '%s'; |
die(printf($f, $this->getMessage())); |
break; |
default: |
trigger_error('invalid observer type', E_USER_WARNING); |
} |
} |
} |
/** |
* Return specific error information that can be used for more detailed |
* error messages or translation. |
* |
* This method may be overridden in child exception classes in order |
* to add functionality not present in PEAR_Exception and is a placeholder |
* to define API |
* |
* The returned array must be an associative array of parameter => value like so: |
* <pre> |
* array('name' => $name, 'context' => array(...)) |
* </pre> |
* @return array |
*/ |
public function getErrorData() |
{ |
return array(); |
} |
/** |
* Returns the exception that caused this exception to be thrown |
* @access public |
* @return Exception|array The context of the exception |
*/ |
public function getCause() |
{ |
return $this->cause; |
} |
/** |
* Function must be public to call on caused exceptions |
* @param array |
*/ |
public function getCauseMessage(&$causes) |
{ |
$trace = $this->getTraceSafe(); |
$cause = array('class' => get_class($this), |
'message' => $this->message, |
'file' => 'unknown', |
'line' => 'unknown'); |
if (isset($trace[0])) { |
if (isset($trace[0]['file'])) { |
$cause['file'] = $trace[0]['file']; |
$cause['line'] = $trace[0]['line']; |
} |
} |
$causes[] = $cause; |
if ($this->cause instanceof PEAR_Exception) { |
$this->cause->getCauseMessage($causes); |
} elseif ($this->cause instanceof Exception) { |
$causes[] = array('class' => get_class($this->cause), |
'message' => $this->cause->getMessage(), |
'file' => $this->cause->getFile(), |
'line' => $this->cause->getLine()); |
} elseif (class_exists('PEAR_Error') && $this->cause instanceof PEAR_Error) { |
$causes[] = array('class' => get_class($this->cause), |
'message' => $this->cause->getMessage(), |
'file' => 'unknown', |
'line' => 'unknown'); |
} elseif (is_array($this->cause)) { |
foreach ($this->cause as $cause) { |
if ($cause instanceof PEAR_Exception) { |
$cause->getCauseMessage($causes); |
} elseif ($cause instanceof Exception) { |
$causes[] = array('class' => get_class($cause), |
'message' => $cause->getMessage(), |
'file' => $cause->getFile(), |
'line' => $cause->getLine()); |
} elseif (class_exists('PEAR_Error') && $cause instanceof PEAR_Error) { |
$causes[] = array('class' => get_class($cause), |
'message' => $cause->getMessage(), |
'file' => 'unknown', |
'line' => 'unknown'); |
} elseif (is_array($cause) && isset($cause['message'])) { |
// PEAR_ErrorStack warning |
$causes[] = array( |
'class' => $cause['package'], |
'message' => $cause['message'], |
'file' => isset($cause['context']['file']) ? |
$cause['context']['file'] : |
'unknown', |
'line' => isset($cause['context']['line']) ? |
$cause['context']['line'] : |
'unknown', |
); |
} |
} |
} |
} |
public function getTraceSafe() |
{ |
if (!isset($this->_trace)) { |
$this->_trace = $this->getTrace(); |
if (empty($this->_trace)) { |
$backtrace = debug_backtrace(); |
$this->_trace = array($backtrace[count($backtrace)-1]); |
} |
} |
return $this->_trace; |
} |
public function getErrorClass() |
{ |
$trace = $this->getTraceSafe(); |
return $trace[0]['class']; |
} |
public function getErrorMethod() |
{ |
$trace = $this->getTraceSafe(); |
return $trace[0]['function']; |
} |
public function __toString() |
{ |
if (isset($_SERVER['REQUEST_URI'])) { |
return $this->toHtml(); |
} |
return $this->toText(); |
} |
public function toHtml() |
{ |
$trace = $this->getTraceSafe(); |
$causes = array(); |
$this->getCauseMessage($causes); |
$html = '<table style="border: 1px" cellspacing="0">' . "\n"; |
foreach ($causes as $i => $cause) { |
$html .= '<tr><td colspan="3" style="background: #ff9999">' |
. str_repeat('-', $i) . ' <b>' . $cause['class'] . '</b>: ' |
. htmlspecialchars($cause['message']) . ' in <b>' . $cause['file'] . '</b> ' |
. 'on line <b>' . $cause['line'] . '</b>' |
. "</td></tr>\n"; |
} |
$html .= '<tr><td colspan="3" style="background-color: #aaaaaa; text-align: center; font-weight: bold;">Exception trace</td></tr>' . "\n" |
. '<tr><td style="text-align: center; background: #cccccc; width:20px; font-weight: bold;">#</td>' |
. '<td style="text-align: center; background: #cccccc; font-weight: bold;">Function</td>' |
. '<td style="text-align: center; background: #cccccc; font-weight: bold;">Location</td></tr>' . "\n"; |
foreach ($trace as $k => $v) { |
$html .= '<tr><td style="text-align: center;">' . $k . '</td>' |
. '<td>'; |
if (!empty($v['class'])) { |
$html .= $v['class'] . $v['type']; |
} |
$html .= $v['function']; |
$args = array(); |
if (!empty($v['args'])) { |
foreach ($v['args'] as $arg) { |
if (is_null($arg)) $args[] = 'null'; |
elseif (is_array($arg)) $args[] = 'Array'; |
elseif (is_object($arg)) $args[] = 'Object('.get_class($arg).')'; |
elseif (is_bool($arg)) $args[] = $arg ? 'true' : 'false'; |
elseif (is_int($arg) || is_double($arg)) $args[] = $arg; |
else { |
$arg = (string)$arg; |
$str = htmlspecialchars(substr($arg, 0, 16)); |
if (strlen($arg) > 16) $str .= '…'; |
$args[] = "'" . $str . "'"; |
} |
} |
} |
$html .= '(' . implode(', ',$args) . ')' |
. '</td>' |
. '<td>' . (isset($v['file']) ? $v['file'] : 'unknown') |
. ':' . (isset($v['line']) ? $v['line'] : 'unknown') |
. '</td></tr>' . "\n"; |
} |
$html .= '<tr><td style="text-align: center;">' . ($k+1) . '</td>' |
. '<td>{main}</td>' |
. '<td> </td></tr>' . "\n" |
. '</table>'; |
return $html; |
} |
public function toText() |
{ |
$causes = array(); |
$this->getCauseMessage($causes); |
$causeMsg = ''; |
foreach ($causes as $i => $cause) { |
$causeMsg .= str_repeat(' ', $i) . $cause['class'] . ': ' |
. $cause['message'] . ' in ' . $cause['file'] |
. ' on line ' . $cause['line'] . "\n"; |
} |
return $causeMsg . $this->getTraceAsString(); |
} |
} |
/branches/v1.3-critias/bibliotheque/pear/PEAR/Validator/PECL.php |
---|
New file |
0,0 → 1,62 |
<?php |
/** |
* Channel Validator for the pecl.php.net channel |
* |
* PHP 4 and PHP 5 |
* |
* @category pear |
* @package PEAR |
* @author Greg Beaver <cellog@php.net> |
* @copyright 1997-2006 The PHP Group |
* @license http://opensource.org/licenses/bsd-license.php New BSD License |
* @link http://pear.php.net/package/PEAR |
* @since File available since Release 1.4.0a5 |
*/ |
/** |
* This is the parent class for all validators |
*/ |
require_once 'PEAR/Validate.php'; |
/** |
* Channel Validator for the pecl.php.net channel |
* @category pear |
* @package PEAR |
* @author Greg Beaver <cellog@php.net> |
* @copyright 1997-2009 The Authors |
* @license http://opensource.org/licenses/bsd-license.php New BSD License |
* @version Release: 1.10.1 |
* @link http://pear.php.net/package/PEAR |
* @since Class available since Release 1.4.0a5 |
*/ |
class PEAR_Validator_PECL extends PEAR_Validate |
{ |
function validateVersion() |
{ |
if ($this->_state == PEAR_VALIDATE_PACKAGING) { |
$version = $this->_packagexml->getVersion(); |
$versioncomponents = explode('.', $version); |
$last = array_pop($versioncomponents); |
if (substr($last, 1, 2) == 'rc') { |
$this->_addFailure('version', 'Release Candidate versions must have ' . |
'upper-case RC, not lower-case rc'); |
return false; |
} |
} |
return true; |
} |
function validatePackageName() |
{ |
$ret = parent::validatePackageName(); |
if ($this->_packagexml->getPackageType() == 'extsrc' || |
$this->_packagexml->getPackageType() == 'zendextsrc') { |
if (strtolower($this->_packagexml->getPackage()) != |
strtolower($this->_packagexml->getProvidesExtension())) { |
$this->_addWarning('providesextension', 'package name "' . |
$this->_packagexml->getPackage() . '" is different from extension name "' . |
$this->_packagexml->getProvidesExtension() . '"'); |
} |
} |
return $ret; |
} |
} |
?> |
/branches/v1.3-critias/bibliotheque/pear/PEAR/Autoloader.php |
---|
New file |
0,0 → 1,217 |
<?php |
/** |
* Class auto-loader |
* |
* PHP versions 4 |
* |
* @category pear |
* @package PEAR |
* @author Stig Bakken <ssb@php.net> |
* @copyright 1997-2009 The Authors |
* @license http://opensource.org/licenses/bsd-license.php New BSD License |
* @link http://pear.php.net/manual/en/core.ppm.php#core.ppm.pear-autoloader |
* @since File available since Release 0.1 |
* @deprecated File deprecated in Release 1.4.0a1 |
*/ |
// /* vim: set expandtab tabstop=4 shiftwidth=4: */ |
if (!extension_loaded("overload")) { |
// die hard without ext/overload |
die("Rebuild PHP with the `overload' extension to use PEAR_Autoloader"); |
} |
/** |
* Include for PEAR_Error and PEAR classes |
*/ |
require_once "PEAR.php"; |
/** |
* This class is for objects where you want to separate the code for |
* some methods into separate classes. This is useful if you have a |
* class with not-frequently-used methods that contain lots of code |
* that you would like to avoid always parsing. |
* |
* The PEAR_Autoloader class provides autoloading and aggregation. |
* The autoloading lets you set up in which classes the separated |
* methods are found. Aggregation is the technique used to import new |
* methods, an instance of each class providing separated methods is |
* stored and called every time the aggregated method is called. |
* |
* @category pear |
* @package PEAR |
* @author Stig Bakken <ssb@php.net> |
* @copyright 1997-2009 The Authors |
* @license http://opensource.org/licenses/bsd-license.php New BSD License |
* @version Release: 1.10.1 |
* @link http://pear.php.net/manual/en/core.ppm.php#core.ppm.pear-autoloader |
* @since File available since Release 0.1 |
* @deprecated File deprecated in Release 1.4.0a1 |
*/ |
class PEAR_Autoloader extends PEAR |
{ |
// {{{ properties |
/** |
* Map of methods and classes where they are defined |
* |
* @var array |
* |
* @access private |
*/ |
var $_autoload_map = array(); |
/** |
* Map of methods and aggregate objects |
* |
* @var array |
* |
* @access private |
*/ |
var $_method_map = array(); |
// }}} |
// {{{ addAutoload() |
/** |
* Add one or more autoload entries. |
* |
* @param string $method which method to autoload |
* |
* @param string $classname (optional) which class to find the method in. |
* If the $method parameter is an array, this |
* parameter may be omitted (and will be ignored |
* if not), and the $method parameter will be |
* treated as an associative array with method |
* names as keys and class names as values. |
* |
* @return void |
* |
* @access public |
*/ |
function addAutoload($method, $classname = null) |
{ |
if (is_array($method)) { |
array_walk($method, create_function('$a,&$b', '$b = strtolower($b);')); |
$this->_autoload_map = array_merge($this->_autoload_map, $method); |
} else { |
$this->_autoload_map[strtolower($method)] = $classname; |
} |
} |
// }}} |
// {{{ removeAutoload() |
/** |
* Remove an autoload entry. |
* |
* @param string $method which method to remove the autoload entry for |
* |
* @return bool TRUE if an entry was removed, FALSE if not |
* |
* @access public |
*/ |
function removeAutoload($method) |
{ |
$method = strtolower($method); |
$ok = isset($this->_autoload_map[$method]); |
unset($this->_autoload_map[$method]); |
return $ok; |
} |
// }}} |
// {{{ addAggregateObject() |
/** |
* Add an aggregate object to this object. If the specified class |
* is not defined, loading it will be attempted following PEAR's |
* file naming scheme. All the methods in the class will be |
* aggregated, except private ones (name starting with an |
* underscore) and constructors. |
* |
* @param string $classname what class to instantiate for the object. |
* |
* @return void |
* |
* @access public |
*/ |
function addAggregateObject($classname) |
{ |
$classname = strtolower($classname); |
if (!class_exists($classname)) { |
$include_file = preg_replace('/[^a-z0-9]/i', '_', $classname); |
include_once $include_file; |
} |
$obj = new $classname; |
$methods = get_class_methods($classname); |
foreach ($methods as $method) { |
// don't import priviate methods and constructors |
if ($method{0} != '_' && $method != $classname) { |
$this->_method_map[$method] = $obj; |
} |
} |
} |
// }}} |
// {{{ removeAggregateObject() |
/** |
* Remove an aggregate object. |
* |
* @param string $classname the class of the object to remove |
* |
* @return bool TRUE if an object was removed, FALSE if not |
* |
* @access public |
*/ |
function removeAggregateObject($classname) |
{ |
$ok = false; |
$classname = strtolower($classname); |
reset($this->_method_map); |
while (list($method, $obj) = each($this->_method_map)) { |
if (is_a($obj, $classname)) { |
unset($this->_method_map[$method]); |
$ok = true; |
} |
} |
return $ok; |
} |
// }}} |
// {{{ __call() |
/** |
* Overloaded object call handler, called each time an |
* undefined/aggregated method is invoked. This method repeats |
* the call in the right aggregate object and passes on the return |
* value. |
* |
* @param string $method which method that was called |
* |
* @param string $args An array of the parameters passed in the |
* original call |
* |
* @return mixed The return value from the aggregated method, or a PEAR |
* error if the called method was unknown. |
*/ |
function __call($method, $args, &$retval) |
{ |
$method = strtolower($method); |
if (empty($this->_method_map[$method]) && isset($this->_autoload_map[$method])) { |
$this->addAggregateObject($this->_autoload_map[$method]); |
} |
if (isset($this->_method_map[$method])) { |
$retval = call_user_func_array(array($this->_method_map[$method], $method), $args); |
return true; |
} |
return false; |
} |
// }}} |
} |
overload("PEAR_Autoloader"); |
?> |
/branches/v1.3-critias/bibliotheque/pear/PEAR/Dependency2.php |
---|
New file |
0,0 → 1,1357 |
<?php |
/** |
* PEAR_Dependency2, advanced dependency validation |
* |
* PHP versions 4 and 5 |
* |
* @category pear |
* @package PEAR |
* @author Greg Beaver <cellog@php.net> |
* @copyright 1997-2009 The Authors |
* @license http://opensource.org/licenses/bsd-license.php New BSD License |
* @link http://pear.php.net/package/PEAR |
* @since File available since Release 1.4.0a1 |
*/ |
/** |
* Required for the PEAR_VALIDATE_* constants |
*/ |
require_once 'PEAR/Validate.php'; |
/** |
* Dependency check for PEAR packages |
* |
* This class handles both version 1.0 and 2.0 dependencies |
* WARNING: *any* changes to this class must be duplicated in the |
* test_PEAR_Dependency2 class found in tests/PEAR_Dependency2/setup.php.inc, |
* or unit tests will not actually validate the changes |
* @category pear |
* @package PEAR |
* @author Greg Beaver <cellog@php.net> |
* @copyright 1997-2009 The Authors |
* @license http://opensource.org/licenses/bsd-license.php New BSD License |
* @version Release: 1.10.1 |
* @link http://pear.php.net/package/PEAR |
* @since Class available since Release 1.4.0a1 |
*/ |
class PEAR_Dependency2 |
{ |
/** |
* One of the PEAR_VALIDATE_* states |
* @see PEAR_VALIDATE_NORMAL |
* @var integer |
*/ |
var $_state; |
/** |
* Command-line options to install/upgrade/uninstall commands |
* @param array |
*/ |
var $_options; |
/** |
* @var OS_Guess |
*/ |
var $_os; |
/** |
* @var PEAR_Registry |
*/ |
var $_registry; |
/** |
* @var PEAR_Config |
*/ |
var $_config; |
/** |
* @var PEAR_DependencyDB |
*/ |
var $_dependencydb; |
/** |
* Output of PEAR_Registry::parsedPackageName() |
* @var array |
*/ |
var $_currentPackage; |
/** |
* @param PEAR_Config |
* @param array installation options |
* @param array format of PEAR_Registry::parsedPackageName() |
* @param int installation state (one of PEAR_VALIDATE_*) |
*/ |
function __construct(&$config, $installoptions, $package, |
$state = PEAR_VALIDATE_INSTALLING) |
{ |
$this->_config = &$config; |
if (!class_exists('PEAR_DependencyDB')) { |
require_once 'PEAR/DependencyDB.php'; |
} |
if (isset($installoptions['packagingroot'])) { |
// make sure depdb is in the right location |
$config->setInstallRoot($installoptions['packagingroot']); |
} |
$this->_registry = &$config->getRegistry(); |
$this->_dependencydb = &PEAR_DependencyDB::singleton($config); |
if (isset($installoptions['packagingroot'])) { |
$config->setInstallRoot(false); |
} |
$this->_options = $installoptions; |
$this->_state = $state; |
if (!class_exists('OS_Guess')) { |
require_once 'OS/Guess.php'; |
} |
$this->_os = new OS_Guess; |
$this->_currentPackage = $package; |
} |
function _getExtraString($dep) |
{ |
$extra = ' ('; |
if (isset($dep['uri'])) { |
return ''; |
} |
if (isset($dep['recommended'])) { |
$extra .= 'recommended version ' . $dep['recommended']; |
} else { |
if (isset($dep['min'])) { |
$extra .= 'version >= ' . $dep['min']; |
} |
if (isset($dep['max'])) { |
if ($extra != ' (') { |
$extra .= ', '; |
} |
$extra .= 'version <= ' . $dep['max']; |
} |
if (isset($dep['exclude'])) { |
if (!is_array($dep['exclude'])) { |
$dep['exclude'] = array($dep['exclude']); |
} |
if ($extra != ' (') { |
$extra .= ', '; |
} |
$extra .= 'excluded versions: '; |
foreach ($dep['exclude'] as $i => $exclude) { |
if ($i) { |
$extra .= ', '; |
} |
$extra .= $exclude; |
} |
} |
} |
$extra .= ')'; |
if ($extra == ' ()') { |
$extra = ''; |
} |
return $extra; |
} |
/** |
* This makes unit-testing a heck of a lot easier |
*/ |
function getPHP_OS() |
{ |
return PHP_OS; |
} |
/** |
* This makes unit-testing a heck of a lot easier |
*/ |
function getsysname() |
{ |
return $this->_os->getSysname(); |
} |
/** |
* Specify a dependency on an OS. Use arch for detailed os/processor information |
* |
* There are two generic OS dependencies that will be the most common, unix and windows. |
* Other options are linux, freebsd, darwin (OS X), sunos, irix, hpux, aix |
*/ |
function validateOsDependency($dep) |
{ |
if ($this->_state != PEAR_VALIDATE_INSTALLING && $this->_state != PEAR_VALIDATE_DOWNLOADING) { |
return true; |
} |
if ($dep['name'] == '*') { |
return true; |
} |
$not = isset($dep['conflicts']) ? true : false; |
switch (strtolower($dep['name'])) { |
case 'windows' : |
if ($not) { |
if (strtolower(substr($this->getPHP_OS(), 0, 3)) == 'win') { |
if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) { |
return $this->raiseError("Cannot install %s on Windows"); |
} |
return $this->warning("warning: Cannot install %s on Windows"); |
} |
} else { |
if (strtolower(substr($this->getPHP_OS(), 0, 3)) != 'win') { |
if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) { |
return $this->raiseError("Can only install %s on Windows"); |
} |
return $this->warning("warning: Can only install %s on Windows"); |
} |
} |
break; |
case 'unix' : |
$unices = array('linux', 'freebsd', 'darwin', 'sunos', 'irix', 'hpux', 'aix'); |
if ($not) { |
if (in_array($this->getSysname(), $unices)) { |
if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) { |
return $this->raiseError("Cannot install %s on any Unix system"); |
} |
return $this->warning( "warning: Cannot install %s on any Unix system"); |
} |
} else { |
if (!in_array($this->getSysname(), $unices)) { |
if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) { |
return $this->raiseError("Can only install %s on a Unix system"); |
} |
return $this->warning("warning: Can only install %s on a Unix system"); |
} |
} |
break; |
default : |
if ($not) { |
if (strtolower($dep['name']) == strtolower($this->getSysname())) { |
if (!isset($this->_options['nodeps']) && |
!isset($this->_options['force'])) { |
return $this->raiseError('Cannot install %s on ' . $dep['name'] . |
' operating system'); |
} |
return $this->warning('warning: Cannot install %s on ' . |
$dep['name'] . ' operating system'); |
} |
} else { |
if (strtolower($dep['name']) != strtolower($this->getSysname())) { |
if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) { |
return $this->raiseError('Cannot install %s on ' . |
$this->getSysname() . |
' operating system, can only install on ' . $dep['name']); |
} |
return $this->warning('warning: Cannot install %s on ' . |
$this->getSysname() . |
' operating system, can only install on ' . $dep['name']); |
} |
} |
} |
return true; |
} |
/** |
* This makes unit-testing a heck of a lot easier |
*/ |
function matchSignature($pattern) |
{ |
return $this->_os->matchSignature($pattern); |
} |
/** |
* Specify a complex dependency on an OS/processor/kernel version, |
* Use OS for simple operating system dependency. |
* |
* This is the only dependency that accepts an eregable pattern. The pattern |
* will be matched against the php_uname() output parsed by OS_Guess |
*/ |
function validateArchDependency($dep) |
{ |
if ($this->_state != PEAR_VALIDATE_INSTALLING) { |
return true; |
} |
$not = isset($dep['conflicts']) ? true : false; |
if (!$this->matchSignature($dep['pattern'])) { |
if (!$not) { |
if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) { |
return $this->raiseError('%s Architecture dependency failed, does not ' . |
'match "' . $dep['pattern'] . '"'); |
} |
return $this->warning('warning: %s Architecture dependency failed, does ' . |
'not match "' . $dep['pattern'] . '"'); |
} |
return true; |
} |
if ($not) { |
if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) { |
return $this->raiseError('%s Architecture dependency failed, required "' . |
$dep['pattern'] . '"'); |
} |
return $this->warning('warning: %s Architecture dependency failed, ' . |
'required "' . $dep['pattern'] . '"'); |
} |
return true; |
} |
/** |
* This makes unit-testing a heck of a lot easier |
*/ |
function extension_loaded($name) |
{ |
return extension_loaded($name); |
} |
/** |
* This makes unit-testing a heck of a lot easier |
*/ |
function phpversion($name = null) |
{ |
if ($name !== null) { |
return phpversion($name); |
} |
return phpversion(); |
} |
function validateExtensionDependency($dep, $required = true) |
{ |
if ($this->_state != PEAR_VALIDATE_INSTALLING && |
$this->_state != PEAR_VALIDATE_DOWNLOADING) { |
return true; |
} |
$loaded = $this->extension_loaded($dep['name']); |
$extra = $this->_getExtraString($dep); |
if (isset($dep['exclude'])) { |
if (!is_array($dep['exclude'])) { |
$dep['exclude'] = array($dep['exclude']); |
} |
} |
if (!isset($dep['min']) && !isset($dep['max']) && |
!isset($dep['recommended']) && !isset($dep['exclude']) |
) { |
if ($loaded) { |
if (isset($dep['conflicts'])) { |
if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) { |
return $this->raiseError('%s conflicts with PHP extension "' . |
$dep['name'] . '"' . $extra); |
} |
return $this->warning('warning: %s conflicts with PHP extension "' . |
$dep['name'] . '"' . $extra); |
} |
return true; |
} |
if (isset($dep['conflicts'])) { |
return true; |
} |
if ($required) { |
if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) { |
return $this->raiseError('%s requires PHP extension "' . |
$dep['name'] . '"' . $extra); |
} |
return $this->warning('warning: %s requires PHP extension "' . |
$dep['name'] . '"' . $extra); |
} |
return $this->warning('%s can optionally use PHP extension "' . |
$dep['name'] . '"' . $extra); |
} |
if (!$loaded) { |
if (isset($dep['conflicts'])) { |
return true; |
} |
if (!$required) { |
return $this->warning('%s can optionally use PHP extension "' . |
$dep['name'] . '"' . $extra); |
} |
if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) { |
return $this->raiseError('%s requires PHP extension "' . $dep['name'] . |
'"' . $extra); |
} |
return $this->warning('warning: %s requires PHP extension "' . $dep['name'] . |
'"' . $extra); |
} |
$version = (string) $this->phpversion($dep['name']); |
if (empty($version)) { |
$version = '0'; |
} |
$fail = false; |
if (isset($dep['min']) && !version_compare($version, $dep['min'], '>=')) { |
$fail = true; |
} |
if (isset($dep['max']) && !version_compare($version, $dep['max'], '<=')) { |
$fail = true; |
} |
if ($fail && !isset($dep['conflicts'])) { |
if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) { |
return $this->raiseError('%s requires PHP extension "' . $dep['name'] . |
'"' . $extra . ', installed version is ' . $version); |
} |
return $this->warning('warning: %s requires PHP extension "' . $dep['name'] . |
'"' . $extra . ', installed version is ' . $version); |
} elseif ((isset($dep['min']) || isset($dep['max'])) && !$fail && isset($dep['conflicts'])) { |
if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) { |
return $this->raiseError('%s conflicts with PHP extension "' . |
$dep['name'] . '"' . $extra . ', installed version is ' . $version); |
} |
return $this->warning('warning: %s conflicts with PHP extension "' . |
$dep['name'] . '"' . $extra . ', installed version is ' . $version); |
} |
if (isset($dep['exclude'])) { |
foreach ($dep['exclude'] as $exclude) { |
if (version_compare($version, $exclude, '==')) { |
if (isset($dep['conflicts'])) { |
continue; |
} |
if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) { |
return $this->raiseError('%s is not compatible with PHP extension "' . |
$dep['name'] . '" version ' . |
$exclude); |
} |
return $this->warning('warning: %s is not compatible with PHP extension "' . |
$dep['name'] . '" version ' . |
$exclude); |
} elseif (version_compare($version, $exclude, '!=') && isset($dep['conflicts'])) { |
if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) { |
return $this->raiseError('%s conflicts with PHP extension "' . |
$dep['name'] . '"' . $extra . ', installed version is ' . $version); |
} |
return $this->warning('warning: %s conflicts with PHP extension "' . |
$dep['name'] . '"' . $extra . ', installed version is ' . $version); |
} |
} |
} |
if (isset($dep['recommended'])) { |
if (version_compare($version, $dep['recommended'], '==')) { |
return true; |
} |
if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) { |
return $this->raiseError('%s dependency: PHP extension ' . $dep['name'] . |
' version "' . $version . '"' . |
' is not the recommended version "' . $dep['recommended'] . |
'", but may be compatible, use --force to install'); |
} |
return $this->warning('warning: %s dependency: PHP extension ' . |
$dep['name'] . ' version "' . $version . '"' . |
' is not the recommended version "' . $dep['recommended'].'"'); |
} |
return true; |
} |
function validatePhpDependency($dep) |
{ |
if ($this->_state != PEAR_VALIDATE_INSTALLING && |
$this->_state != PEAR_VALIDATE_DOWNLOADING) { |
return true; |
} |
$version = $this->phpversion(); |
$extra = $this->_getExtraString($dep); |
if (isset($dep['exclude'])) { |
if (!is_array($dep['exclude'])) { |
$dep['exclude'] = array($dep['exclude']); |
} |
} |
if (isset($dep['min'])) { |
if (!version_compare($version, $dep['min'], '>=')) { |
if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) { |
return $this->raiseError('%s requires PHP' . |
$extra . ', installed version is ' . $version); |
} |
return $this->warning('warning: %s requires PHP' . |
$extra . ', installed version is ' . $version); |
} |
} |
if (isset($dep['max'])) { |
if (!version_compare($version, $dep['max'], '<=')) { |
if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) { |
return $this->raiseError('%s requires PHP' . |
$extra . ', installed version is ' . $version); |
} |
return $this->warning('warning: %s requires PHP' . |
$extra . ', installed version is ' . $version); |
} |
} |
if (isset($dep['exclude'])) { |
foreach ($dep['exclude'] as $exclude) { |
if (version_compare($version, $exclude, '==')) { |
if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) { |
return $this->raiseError('%s is not compatible with PHP version ' . |
$exclude); |
} |
return $this->warning( |
'warning: %s is not compatible with PHP version ' . |
$exclude); |
} |
} |
} |
return true; |
} |
/** |
* This makes unit-testing a heck of a lot easier |
*/ |
function getPEARVersion() |
{ |
return '1.10.1'; |
} |
function validatePearinstallerDependency($dep) |
{ |
$pearversion = $this->getPEARVersion(); |
$extra = $this->_getExtraString($dep); |
if (isset($dep['exclude'])) { |
if (!is_array($dep['exclude'])) { |
$dep['exclude'] = array($dep['exclude']); |
} |
} |
if (version_compare($pearversion, $dep['min'], '<')) { |
if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) { |
return $this->raiseError('%s requires PEAR Installer' . $extra . |
', installed version is ' . $pearversion); |
} |
return $this->warning('warning: %s requires PEAR Installer' . $extra . |
', installed version is ' . $pearversion); |
} |
if (isset($dep['max'])) { |
if (version_compare($pearversion, $dep['max'], '>')) { |
if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) { |
return $this->raiseError('%s requires PEAR Installer' . $extra . |
', installed version is ' . $pearversion); |
} |
return $this->warning('warning: %s requires PEAR Installer' . $extra . |
', installed version is ' . $pearversion); |
} |
} |
if (isset($dep['exclude'])) { |
if (!isset($dep['exclude'][0])) { |
$dep['exclude'] = array($dep['exclude']); |
} |
foreach ($dep['exclude'] as $exclude) { |
if (version_compare($exclude, $pearversion, '==')) { |
if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) { |
return $this->raiseError('%s is not compatible with PEAR Installer ' . |
'version ' . $exclude); |
} |
return $this->warning('warning: %s is not compatible with PEAR ' . |
'Installer version ' . $exclude); |
} |
} |
} |
return true; |
} |
function validateSubpackageDependency($dep, $required, $params) |
{ |
return $this->validatePackageDependency($dep, $required, $params); |
} |
/** |
* @param array dependency information (2.0 format) |
* @param boolean whether this is a required dependency |
* @param array a list of downloaded packages to be installed, if any |
* @param boolean if true, then deps on pear.php.net that fail will also check |
* against pecl.php.net packages to accommodate extensions that have |
* moved to pecl.php.net from pear.php.net |
*/ |
function validatePackageDependency($dep, $required, $params, $depv1 = false) |
{ |
if ($this->_state != PEAR_VALIDATE_INSTALLING && |
$this->_state != PEAR_VALIDATE_DOWNLOADING) { |
return true; |
} |
if (isset($dep['providesextension'])) { |
if ($this->extension_loaded($dep['providesextension'])) { |
$save = $dep; |
$subdep = $dep; |
$subdep['name'] = $subdep['providesextension']; |
PEAR::pushErrorHandling(PEAR_ERROR_RETURN); |
$ret = $this->validateExtensionDependency($subdep, $required); |
PEAR::popErrorHandling(); |
if (!PEAR::isError($ret)) { |
return true; |
} |
} |
} |
if ($this->_state == PEAR_VALIDATE_INSTALLING) { |
return $this->_validatePackageInstall($dep, $required, $depv1); |
} |
if ($this->_state == PEAR_VALIDATE_DOWNLOADING) { |
return $this->_validatePackageDownload($dep, $required, $params, $depv1); |
} |
} |
function _validatePackageDownload($dep, $required, $params, $depv1 = false) |
{ |
$dep['package'] = $dep['name']; |
if (isset($dep['uri'])) { |
$dep['channel'] = '__uri'; |
} |
$depname = $this->_registry->parsedPackageNameToString($dep, true); |
$found = false; |
foreach ($params as $param) { |
if ($param->isEqual( |
array('package' => $dep['name'], |
'channel' => $dep['channel']))) { |
$found = true; |
break; |
} |
if ($depv1 && $dep['channel'] == 'pear.php.net') { |
if ($param->isEqual( |
array('package' => $dep['name'], |
'channel' => 'pecl.php.net'))) { |
$found = true; |
break; |
} |
} |
} |
if (!$found && isset($dep['providesextension'])) { |
foreach ($params as $param) { |
if ($param->isExtension($dep['providesextension'])) { |
$found = true; |
break; |
} |
} |
} |
if ($found) { |
$version = $param->getVersion(); |
$installed = false; |
$downloaded = true; |
} else { |
if ($this->_registry->packageExists($dep['name'], $dep['channel'])) { |
$installed = true; |
$downloaded = false; |
$version = $this->_registry->packageinfo($dep['name'], 'version', |
$dep['channel']); |
} else { |
if ($dep['channel'] == 'pecl.php.net' && $this->_registry->packageExists($dep['name'], |
'pear.php.net')) { |
$installed = true; |
$downloaded = false; |
$version = $this->_registry->packageinfo($dep['name'], 'version', |
'pear.php.net'); |
} else { |
$version = 'not installed or downloaded'; |
$installed = false; |
$downloaded = false; |
} |
} |
} |
$extra = $this->_getExtraString($dep); |
if (isset($dep['exclude']) && !is_array($dep['exclude'])) { |
$dep['exclude'] = array($dep['exclude']); |
} |
if (!isset($dep['min']) && !isset($dep['max']) && |
!isset($dep['recommended']) && !isset($dep['exclude']) |
) { |
if ($installed || $downloaded) { |
$installed = $installed ? 'installed' : 'downloaded'; |
if (isset($dep['conflicts'])) { |
$rest = ''; |
if ($version) { |
$rest = ", $installed version is " . $version; |
} |
if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) { |
return $this->raiseError('%s conflicts with package "' . $depname . '"' . $extra . $rest); |
} |
return $this->warning('warning: %s conflicts with package "' . $depname . '"' . $extra . $rest); |
} |
return true; |
} |
if (isset($dep['conflicts'])) { |
return true; |
} |
if ($required) { |
if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) { |
return $this->raiseError('%s requires package "' . $depname . '"' . $extra); |
} |
return $this->warning('warning: %s requires package "' . $depname . '"' . $extra); |
} |
return $this->warning('%s can optionally use package "' . $depname . '"' . $extra); |
} |
if (!$installed && !$downloaded) { |
if (isset($dep['conflicts'])) { |
return true; |
} |
if ($required) { |
if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) { |
return $this->raiseError('%s requires package "' . $depname . '"' . $extra); |
} |
return $this->warning('warning: %s requires package "' . $depname . '"' . $extra); |
} |
return $this->warning('%s can optionally use package "' . $depname . '"' . $extra); |
} |
$fail = false; |
if (isset($dep['min']) && version_compare($version, $dep['min'], '<')) { |
$fail = true; |
} |
if (isset($dep['max']) && version_compare($version, $dep['max'], '>')) { |
$fail = true; |
} |
if ($fail && !isset($dep['conflicts'])) { |
$installed = $installed ? 'installed' : 'downloaded'; |
$dep['package'] = $dep['name']; |
$dep = $this->_registry->parsedPackageNameToString($dep, true); |
if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) { |
return $this->raiseError('%s requires package "' . $depname . '"' . |
$extra . ", $installed version is " . $version); |
} |
return $this->warning('warning: %s requires package "' . $depname . '"' . |
$extra . ", $installed version is " . $version); |
} elseif ((isset($dep['min']) || isset($dep['max'])) && !$fail && |
isset($dep['conflicts']) && !isset($dep['exclude'])) { |
$installed = $installed ? 'installed' : 'downloaded'; |
if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) { |
return $this->raiseError('%s conflicts with package "' . $depname . '"' . $extra . |
", $installed version is " . $version); |
} |
return $this->warning('warning: %s conflicts with package "' . $depname . '"' . |
$extra . ", $installed version is " . $version); |
} |
if (isset($dep['exclude'])) { |
$installed = $installed ? 'installed' : 'downloaded'; |
foreach ($dep['exclude'] as $exclude) { |
if (version_compare($version, $exclude, '==') && !isset($dep['conflicts'])) { |
if (!isset($this->_options['nodeps']) && |
!isset($this->_options['force']) |
) { |
return $this->raiseError('%s is not compatible with ' . |
$installed . ' package "' . |
$depname . '" version ' . |
$exclude); |
} |
return $this->warning('warning: %s is not compatible with ' . |
$installed . ' package "' . |
$depname . '" version ' . |
$exclude); |
} elseif (version_compare($version, $exclude, '!=') && isset($dep['conflicts'])) { |
$installed = $installed ? 'installed' : 'downloaded'; |
if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) { |
return $this->raiseError('%s conflicts with package "' . $depname . '"' . |
$extra . ", $installed version is " . $version); |
} |
return $this->warning('warning: %s conflicts with package "' . $depname . '"' . |
$extra . ", $installed version is " . $version); |
} |
} |
} |
if (isset($dep['recommended'])) { |
$installed = $installed ? 'installed' : 'downloaded'; |
if (version_compare($version, $dep['recommended'], '==')) { |
return true; |
} |
if (!$found && $installed) { |
$param = $this->_registry->getPackage($dep['name'], $dep['channel']); |
} |
if ($param) { |
$found = false; |
foreach ($params as $parent) { |
if ($parent->isEqual($this->_currentPackage)) { |
$found = true; |
break; |
} |
} |
if ($found) { |
if ($param->isCompatible($parent)) { |
return true; |
} |
} else { // this is for validPackage() calls |
$parent = $this->_registry->getPackage($this->_currentPackage['package'], |
$this->_currentPackage['channel']); |
if ($parent !== null && $param->isCompatible($parent)) { |
return true; |
} |
} |
} |
if (!isset($this->_options['nodeps']) && !isset($this->_options['force']) && |
!isset($this->_options['loose']) |
) { |
return $this->raiseError('%s dependency package "' . $depname . |
'" ' . $installed . ' version ' . $version . |
' is not the recommended version ' . $dep['recommended'] . |
', but may be compatible, use --force to install'); |
} |
return $this->warning('warning: %s dependency package "' . $depname . |
'" ' . $installed . ' version ' . $version . |
' is not the recommended version ' . $dep['recommended']); |
} |
return true; |
} |
function _validatePackageInstall($dep, $required, $depv1 = false) |
{ |
return $this->_validatePackageDownload($dep, $required, array(), $depv1); |
} |
/** |
* Verify that uninstalling packages passed in to command line is OK. |
* |
* @param PEAR_Installer $dl |
* @return PEAR_Error|true |
*/ |
function validatePackageUninstall(&$dl) |
{ |
if (PEAR::isError($this->_dependencydb)) { |
return $this->_dependencydb; |
} |
$params = array(); |
// construct an array of "downloaded" packages to fool the package dependency checker |
// into using these to validate uninstalls of circular dependencies |
$downloaded = &$dl->getUninstallPackages(); |
foreach ($downloaded as $i => $pf) { |
if (!class_exists('PEAR_Downloader_Package')) { |
require_once 'PEAR/Downloader/Package.php'; |
} |
$dp = new PEAR_Downloader_Package($dl); |
$dp->setPackageFile($downloaded[$i]); |
$params[$i] = $dp; |
} |
// check cache |
$memyselfandI = strtolower($this->_currentPackage['channel']) . '/' . |
strtolower($this->_currentPackage['package']); |
if (isset($dl->___uninstall_package_cache)) { |
$badpackages = $dl->___uninstall_package_cache; |
if (isset($badpackages[$memyselfandI]['warnings'])) { |
foreach ($badpackages[$memyselfandI]['warnings'] as $warning) { |
$dl->log(0, $warning[0]); |
} |
} |
if (isset($badpackages[$memyselfandI]['errors'])) { |
foreach ($badpackages[$memyselfandI]['errors'] as $error) { |
if (is_array($error)) { |
$dl->log(0, $error[0]); |
} else { |
$dl->log(0, $error->getMessage()); |
} |
} |
if (isset($this->_options['nodeps']) || isset($this->_options['force'])) { |
return $this->warning( |
'warning: %s should not be uninstalled, other installed packages depend ' . |
'on this package'); |
} |
return $this->raiseError( |
'%s cannot be uninstalled, other installed packages depend on this package'); |
} |
return true; |
} |
// first, list the immediate parents of each package to be uninstalled |
$perpackagelist = array(); |
$allparents = array(); |
foreach ($params as $i => $param) { |
$a = array( |
'channel' => strtolower($param->getChannel()), |
'package' => strtolower($param->getPackage()) |
); |
$deps = $this->_dependencydb->getDependentPackages($a); |
if ($deps) { |
foreach ($deps as $d) { |
$pardeps = $this->_dependencydb->getDependencies($d); |
foreach ($pardeps as $dep) { |
if (strtolower($dep['dep']['channel']) == $a['channel'] && |
strtolower($dep['dep']['name']) == $a['package']) { |
if (!isset($perpackagelist[$a['channel'] . '/' . $a['package']])) { |
$perpackagelist[$a['channel'] . '/' . $a['package']] = array(); |
} |
$perpackagelist[$a['channel'] . '/' . $a['package']][] |
= array($d['channel'] . '/' . $d['package'], $dep); |
if (!isset($allparents[$d['channel'] . '/' . $d['package']])) { |
$allparents[$d['channel'] . '/' . $d['package']] = array(); |
} |
if (!isset($allparents[$d['channel'] . '/' . $d['package']][$a['channel'] . '/' . $a['package']])) { |
$allparents[$d['channel'] . '/' . $d['package']][$a['channel'] . '/' . $a['package']] = array(); |
} |
$allparents[$d['channel'] . '/' . $d['package']] |
[$a['channel'] . '/' . $a['package']][] |
= array($d, $dep); |
} |
} |
} |
} |
} |
// next, remove any packages from the parents list that are not installed |
$remove = array(); |
foreach ($allparents as $parent => $d1) { |
foreach ($d1 as $d) { |
if ($this->_registry->packageExists($d[0][0]['package'], $d[0][0]['channel'])) { |
continue; |
} |
$remove[$parent] = true; |
} |
} |
// next remove any packages from the parents list that are not passed in for |
// uninstallation |
foreach ($allparents as $parent => $d1) { |
foreach ($d1 as $d) { |
foreach ($params as $param) { |
if (strtolower($param->getChannel()) == $d[0][0]['channel'] && |
strtolower($param->getPackage()) == $d[0][0]['package']) { |
// found it |
continue 3; |
} |
} |
$remove[$parent] = true; |
} |
} |
// remove all packages whose dependencies fail |
// save which ones failed for error reporting |
$badchildren = array(); |
do { |
$fail = false; |
foreach ($remove as $package => $unused) { |
if (!isset($allparents[$package])) { |
continue; |
} |
foreach ($allparents[$package] as $kid => $d1) { |
foreach ($d1 as $depinfo) { |
if ($depinfo[1]['type'] != 'optional') { |
if (isset($badchildren[$kid])) { |
continue; |
} |
$badchildren[$kid] = true; |
$remove[$kid] = true; |
$fail = true; |
continue 2; |
} |
} |
} |
if ($fail) { |
// start over, we removed some children |
continue 2; |
} |
} |
} while ($fail); |
// next, construct the list of packages that can't be uninstalled |
$badpackages = array(); |
$save = $this->_currentPackage; |
foreach ($perpackagelist as $package => $packagedeps) { |
foreach ($packagedeps as $parent) { |
if (!isset($remove[$parent[0]])) { |
continue; |
} |
$packagename = $this->_registry->parsePackageName($parent[0]); |
$packagename['channel'] = $this->_registry->channelAlias($packagename['channel']); |
$pa = $this->_registry->getPackage($packagename['package'], $packagename['channel']); |
$packagename['package'] = $pa->getPackage(); |
$this->_currentPackage = $packagename; |
// parent is not present in uninstall list, make sure we can actually |
// uninstall it (parent dep is optional) |
$parentname['channel'] = $this->_registry->channelAlias($parent[1]['dep']['channel']); |
$pa = $this->_registry->getPackage($parent[1]['dep']['name'], $parent[1]['dep']['channel']); |
$parentname['package'] = $pa->getPackage(); |
$parent[1]['dep']['package'] = $parentname['package']; |
$parent[1]['dep']['channel'] = $parentname['channel']; |
if ($parent[1]['type'] == 'optional') { |
$test = $this->_validatePackageUninstall($parent[1]['dep'], false, $dl); |
if ($test !== true) { |
$badpackages[$package]['warnings'][] = $test; |
} |
} else { |
$test = $this->_validatePackageUninstall($parent[1]['dep'], true, $dl); |
if ($test !== true) { |
$badpackages[$package]['errors'][] = $test; |
} |
} |
} |
} |
$this->_currentPackage = $save; |
$dl->___uninstall_package_cache = $badpackages; |
if (isset($badpackages[$memyselfandI])) { |
if (isset($badpackages[$memyselfandI]['warnings'])) { |
foreach ($badpackages[$memyselfandI]['warnings'] as $warning) { |
$dl->log(0, $warning[0]); |
} |
} |
if (isset($badpackages[$memyselfandI]['errors'])) { |
foreach ($badpackages[$memyselfandI]['errors'] as $error) { |
if (is_array($error)) { |
$dl->log(0, $error[0]); |
} else { |
$dl->log(0, $error->getMessage()); |
} |
} |
if (isset($this->_options['nodeps']) || isset($this->_options['force'])) { |
return $this->warning( |
'warning: %s should not be uninstalled, other installed packages depend ' . |
'on this package'); |
} |
return $this->raiseError( |
'%s cannot be uninstalled, other installed packages depend on this package'); |
} |
} |
return true; |
} |
function _validatePackageUninstall($dep, $required, $dl) |
{ |
$depname = $this->_registry->parsedPackageNameToString($dep, true); |
$version = $this->_registry->packageinfo($dep['package'], 'version', $dep['channel']); |
if (!$version) { |
return true; |
} |
$extra = $this->_getExtraString($dep); |
if (isset($dep['exclude']) && !is_array($dep['exclude'])) { |
$dep['exclude'] = array($dep['exclude']); |
} |
if (isset($dep['conflicts'])) { |
return true; // uninstall OK - these packages conflict (probably installed with --force) |
} |
if (!isset($dep['min']) && !isset($dep['max'])) { |
if (!$required) { |
return $this->warning('"' . $depname . '" can be optionally used by ' . |
'installed package %s' . $extra); |
} |
if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) { |
return $this->raiseError('"' . $depname . '" is required by ' . |
'installed package %s' . $extra); |
} |
return $this->warning('warning: "' . $depname . '" is required by ' . |
'installed package %s' . $extra); |
} |
$fail = false; |
if (isset($dep['min']) && version_compare($version, $dep['min'], '>=')) { |
$fail = true; |
} |
if (isset($dep['max']) && version_compare($version, $dep['max'], '<=')) { |
$fail = true; |
} |
// we re-use this variable, preserve the original value |
$saverequired = $required; |
if (!$required) { |
return $this->warning($depname . $extra . ' can be optionally used by installed package' . |
' "%s"'); |
} |
if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) { |
return $this->raiseError($depname . $extra . ' is required by installed package' . |
' "%s"'); |
} |
return $this->raiseError('warning: ' . $depname . $extra . |
' is required by installed package "%s"'); |
} |
/** |
* validate a downloaded package against installed packages |
* |
* As of PEAR 1.4.3, this will only validate |
* |
* @param array|PEAR_Downloader_Package|PEAR_PackageFile_v1|PEAR_PackageFile_v2 |
* $pkg package identifier (either |
* array('package' => blah, 'channel' => blah) or an array with |
* index 'info' referencing an object) |
* @param PEAR_Downloader $dl |
* @param array $params full list of packages to install |
* @return true|PEAR_Error |
*/ |
function validatePackage($pkg, &$dl, $params = array()) |
{ |
if (is_array($pkg) && isset($pkg['info'])) { |
$deps = $this->_dependencydb->getDependentPackageDependencies($pkg['info']); |
} else { |
$deps = $this->_dependencydb->getDependentPackageDependencies($pkg); |
} |
$fail = false; |
if ($deps) { |
if (!class_exists('PEAR_Downloader_Package')) { |
require_once 'PEAR/Downloader/Package.php'; |
} |
$dp = new PEAR_Downloader_Package($dl); |
if (is_object($pkg)) { |
$dp->setPackageFile($pkg); |
} else { |
$dp->setDownloadURL($pkg); |
} |
PEAR::pushErrorHandling(PEAR_ERROR_RETURN); |
foreach ($deps as $channel => $info) { |
foreach ($info as $package => $ds) { |
foreach ($params as $packd) { |
if (strtolower($packd->getPackage()) == strtolower($package) && |
$packd->getChannel() == $channel) { |
$dl->log(3, 'skipping installed package check of "' . |
$this->_registry->parsedPackageNameToString( |
array('channel' => $channel, 'package' => $package), |
true) . |
'", version "' . $packd->getVersion() . '" will be ' . |
'downloaded and installed'); |
continue 2; // jump to next package |
} |
} |
foreach ($ds as $d) { |
$checker = new PEAR_Dependency2($this->_config, $this->_options, |
array('channel' => $channel, 'package' => $package), $this->_state); |
$dep = $d['dep']; |
$required = $d['type'] == 'required'; |
$ret = $checker->_validatePackageDownload($dep, $required, array(&$dp)); |
if (is_array($ret)) { |
$dl->log(0, $ret[0]); |
} elseif (PEAR::isError($ret)) { |
$dl->log(0, $ret->getMessage()); |
$fail = true; |
} |
} |
} |
} |
PEAR::popErrorHandling(); |
} |
if ($fail) { |
return $this->raiseError( |
'%s cannot be installed, conflicts with installed packages'); |
} |
return true; |
} |
/** |
* validate a package.xml 1.0 dependency |
*/ |
function validateDependency1($dep, $params = array()) |
{ |
if (!isset($dep['optional'])) { |
$dep['optional'] = 'no'; |
} |
list($newdep, $type) = $this->normalizeDep($dep); |
if (!$newdep) { |
return $this->raiseError("Invalid Dependency"); |
} |
if (method_exists($this, "validate{$type}Dependency")) { |
return $this->{"validate{$type}Dependency"}($newdep, $dep['optional'] == 'no', |
$params, true); |
} |
} |
/** |
* Convert a 1.0 dep into a 2.0 dep |
*/ |
function normalizeDep($dep) |
{ |
$types = array( |
'pkg' => 'Package', |
'ext' => 'Extension', |
'os' => 'Os', |
'php' => 'Php' |
); |
if (!isset($types[$dep['type']])) { |
return array(false, false); |
} |
$type = $types[$dep['type']]; |
$newdep = array(); |
switch ($type) { |
case 'Package' : |
$newdep['channel'] = 'pear.php.net'; |
case 'Extension' : |
case 'Os' : |
$newdep['name'] = $dep['name']; |
break; |
} |
$dep['rel'] = PEAR_Dependency2::signOperator($dep['rel']); |
switch ($dep['rel']) { |
case 'has' : |
return array($newdep, $type); |
break; |
case 'not' : |
$newdep['conflicts'] = true; |
break; |
case '>=' : |
case '>' : |
$newdep['min'] = $dep['version']; |
if ($dep['rel'] == '>') { |
$newdep['exclude'] = $dep['version']; |
} |
break; |
case '<=' : |
case '<' : |
$newdep['max'] = $dep['version']; |
if ($dep['rel'] == '<') { |
$newdep['exclude'] = $dep['version']; |
} |
break; |
case 'ne' : |
case '!=' : |
$newdep['min'] = '0'; |
$newdep['max'] = '100000'; |
$newdep['exclude'] = $dep['version']; |
break; |
case '==' : |
$newdep['min'] = $dep['version']; |
$newdep['max'] = $dep['version']; |
break; |
} |
if ($type == 'Php') { |
if (!isset($newdep['min'])) { |
$newdep['min'] = '4.4.0'; |
} |
if (!isset($newdep['max'])) { |
$newdep['max'] = '6.0.0'; |
} |
} |
return array($newdep, $type); |
} |
/** |
* Converts text comparing operators to them sign equivalents |
* |
* Example: 'ge' to '>=' |
* |
* @access public |
* @param string Operator |
* @return string Sign equivalent |
*/ |
function signOperator($operator) |
{ |
switch($operator) { |
case 'lt': return '<'; |
case 'le': return '<='; |
case 'gt': return '>'; |
case 'ge': return '>='; |
case 'eq': return '=='; |
case 'ne': return '!='; |
default: |
return $operator; |
} |
} |
function raiseError($msg) |
{ |
if (isset($this->_options['ignore-errors'])) { |
return $this->warning($msg); |
} |
return PEAR::raiseError(sprintf($msg, $this->_registry->parsedPackageNameToString( |
$this->_currentPackage, true))); |
} |
function warning($msg) |
{ |
return array(sprintf($msg, $this->_registry->parsedPackageNameToString( |
$this->_currentPackage, true))); |
} |
} |
/branches/v1.3-critias/bibliotheque/pear/scripts/pecl.bat |
---|
New file |
0,0 → 1,115 |
@ECHO OFF |
REM ---------------------------------------------------------------------- |
REM PHP version 5 |
REM ---------------------------------------------------------------------- |
REM Copyright (c) 1997-2004 The PHP Group |
REM ---------------------------------------------------------------------- |
REM This source file is subject to version 3.0 of the PHP license, |
REM that is bundled with this package in the file LICENSE, and is |
REM available at through the world-wide-web at |
REM http://www.php.net/license/3_0.txt. |
REM If you did not receive a copy of the PHP license and are unable to |
REM obtain it through the world-wide-web, please send a note to |
REM license@php.net so we can mail you a copy immediately. |
REM ---------------------------------------------------------------------- |
REM Authors: Alexander Merz (alexmerz@php.net) |
REM ---------------------------------------------------------------------- |
REM |
REM Last updated 02/08/2004 ($Id$ is not replaced if the file is binary) |
REM change this lines to match the paths of your system |
REM ------------------- |
REM Test to see if this is a raw pear.bat (uninstalled version) |
SET TMPTMPTMPTMPT=@includ |
SET PMTPMTPMT=%TMPTMPTMPTMPT%e_path@ |
FOR %%x IN ("@include_path@") DO (if %%x=="%PMTPMTPMT%" GOTO :NOTINSTALLED) |
REM Check PEAR global ENV, set them if they do not exist |
IF "%PHP_PEAR_INSTALL_DIR%"=="" SET "PHP_PEAR_INSTALL_DIR=@include_path@" |
IF "%PHP_PEAR_BIN_DIR%"=="" SET "PHP_PEAR_BIN_DIR=@bin_dir@" |
IF "%PHP_PEAR_PHP_BIN%"=="" SET "PHP_PEAR_PHP_BIN=@php_bin@" |
GOTO :INSTALLED |
:NOTINSTALLED |
ECHO WARNING: This is a raw, uninstalled pear.bat |
REM Check to see if we can grab the directory of this file (Windows NT+) |
IF %~n0 == pear ( |
FOR %%x IN (cli\php.exe php.exe) DO (if "%%~$PATH:x" NEQ "" ( |
SET "PHP_PEAR_PHP_BIN=%%~$PATH:x" |
echo Using PHP Executable "%PHP_PEAR_PHP_BIN%" |
"%PHP_PEAR_PHP_BIN%" -v |
GOTO :NEXTTEST |
)) |
GOTO :FAILAUTODETECT |
:NEXTTEST |
IF "%PHP_PEAR_PHP_BIN%" NEQ "" ( |
REM We can use this PHP to run a temporary php file to get the dirname of pear |
echo ^<?php $s=getcwd^(^);chdir^($a=dirname^(__FILE__^).'\\'^);if^(stristr^($a,'\\scripts'^)^)$a=dirname^(dirname^($a^)^).'\\';$f=fopen^($s.'\\~a.a','wb'^);echo$s.'\\~a.a';fwrite^($f,$a^);fclose^($f^);chdir^($s^);?^> > ~~getloc.php |
"%PHP_PEAR_PHP_BIN%" ~~getloc.php |
set /p PHP_PEAR_BIN_DIR=fakeprompt < ~a.a |
DEL ~a.a |
DEL ~~getloc.php |
set "PHP_PEAR_INSTALL_DIR=%PHP_PEAR_BIN_DIR%pear" |
REM Make sure there is a pearcmd.php at our disposal |
IF NOT EXIST %PHP_PEAR_INSTALL_DIR%\pearcmd.php ( |
IF EXIST %PHP_PEAR_INSTALL_DIR%\scripts\pearcmd.php COPY %PHP_PEAR_INSTALL_DIR%\scripts\pearcmd.php %PHP_PEAR_INSTALL_DIR%\pearcmd.php |
IF EXIST pearcmd.php COPY pearcmd.php %PHP_PEAR_INSTALL_DIR%\pearcmd.php |
IF EXIST %~dp0\scripts\pearcmd.php COPY %~dp0\scripts\pearcmd.php %PHP_PEAR_INSTALL_DIR%\pearcmd.php |
) |
) |
GOTO :INSTALLED |
) ELSE ( |
REM Windows Me/98 cannot succeed, so allow the batch to fail |
) |
:FAILAUTODETECT |
echo WARNING: failed to auto-detect pear information |
:INSTALLED |
REM Check Folders and files |
IF NOT EXIST "%PHP_PEAR_INSTALL_DIR%" GOTO PEAR_INSTALL_ERROR |
IF NOT EXIST "%PHP_PEAR_INSTALL_DIR%\pearcmd.php" GOTO PEAR_INSTALL_ERROR2 |
IF NOT EXIST "%PHP_PEAR_BIN_DIR%" GOTO PEAR_BIN_ERROR |
IF NOT EXIST "%PHP_PEAR_PHP_BIN%" GOTO PEAR_PHPBIN_ERROR |
REM launch pearcmd |
GOTO RUN |
:PEAR_INSTALL_ERROR |
ECHO PHP_PEAR_INSTALL_DIR is not set correctly. |
ECHO Please fix it using your environment variable or modify |
ECHO the default value in pear.bat |
ECHO The current value is: |
ECHO %PHP_PEAR_INSTALL_DIR% |
GOTO END |
:PEAR_INSTALL_ERROR2 |
ECHO PHP_PEAR_INSTALL_DIR is not set correctly. |
ECHO pearcmd.php could not be found there. |
ECHO Please fix it using your environment variable or modify |
ECHO the default value in pear.bat |
ECHO The current value is: |
ECHO %PHP_PEAR_INSTALL_DIR% |
GOTO END |
:PEAR_BIN_ERROR |
ECHO PHP_PEAR_BIN_DIR is not set correctly. |
ECHO Please fix it using your environment variable or modify |
ECHO the default value in pear.bat |
ECHO The current value is: |
ECHO %PHP_PEAR_BIN_DIR% |
GOTO END |
:PEAR_PHPBIN_ERROR |
ECHO PHP_PEAR_PHP_BIN is not set correctly. |
ECHO Please fix it using your environment variable or modify |
ECHO the default value in pear.bat |
ECHO The current value is: |
ECHO %PHP_PEAR_PHP_BIN% |
GOTO END |
:RUN |
"%PHP_PEAR_PHP_BIN%" -C -n -d date.timezone=UTC -d output_buffering=1 -d safe_mode=0 -d "include_path='%PHP_PEAR_INSTALL_DIR%'" -d register_argc_argv="On" -d variables_order=EGPCS -f "%PHP_PEAR_INSTALL_DIR%\peclcmd.php" -- %1 %2 %3 %4 %5 %6 %7 %8 %9 |
:END |
@ECHO ON |
/branches/v1.3-critias/bibliotheque/pear/scripts/peardev.bat |
---|
New file |
0,0 → 1,115 |
@ECHO OFF |
REM ---------------------------------------------------------------------- |
REM PHP version 5 |
REM ---------------------------------------------------------------------- |
REM Copyright (c) 1997-2004 The PHP Group |
REM ---------------------------------------------------------------------- |
REM This source file is subject to version 3.0 of the PHP license, |
REM that is bundled with this package in the file LICENSE, and is |
REM available at through the world-wide-web at |
REM http://www.php.net/license/3_0.txt. |
REM If you did not receive a copy of the PHP license and are unable to |
REM obtain it through the world-wide-web, please send a note to |
REM license@php.net so we can mail you a copy immediately. |
REM ---------------------------------------------------------------------- |
REM Authors: Alexander Merz (alexmerz@php.net) |
REM ---------------------------------------------------------------------- |
REM |
REM $Id: peardev.bat,v 1.6 2007-09-03 03:00:17 cellog Exp $ |
REM change this lines to match the paths of your system |
REM ------------------- |
REM Test to see if this is a raw pear.bat (uninstalled version) |
SET TMPTMPTMPTMPT=@includ |
SET PMTPMTPMT=%TMPTMPTMPTMPT%e_path@ |
FOR %%x IN ("@include_path@") DO (if %%x=="%PMTPMTPMT%" GOTO :NOTINSTALLED) |
REM Check PEAR global ENV, set them if they do not exist |
IF "%PHP_PEAR_INSTALL_DIR%"=="" SET "PHP_PEAR_INSTALL_DIR=@include_path@" |
IF "%PHP_PEAR_BIN_DIR%"=="" SET "PHP_PEAR_BIN_DIR=@bin_dir@" |
IF "%PHP_PEAR_PHP_BIN%"=="" SET "PHP_PEAR_PHP_BIN=@php_bin@" |
GOTO :INSTALLED |
:NOTINSTALLED |
ECHO WARNING: This is a raw, uninstalled pear.bat |
REM Check to see if we can grab the directory of this file (Windows NT+) |
IF %~n0 == pear ( |
FOR %%x IN (cli\php.exe php.exe) DO (if "%%~$PATH:x" NEQ "" ( |
SET "PHP_PEAR_PHP_BIN=%%~$PATH:x" |
echo Using PHP Executable "%PHP_PEAR_PHP_BIN%" |
"%PHP_PEAR_PHP_BIN%" -v |
GOTO :NEXTTEST |
)) |
GOTO :FAILAUTODETECT |
:NEXTTEST |
IF "%PHP_PEAR_PHP_BIN%" NEQ "" ( |
REM We can use this PHP to run a temporary php file to get the dirname of pear |
echo ^<?php $s=getcwd^(^);chdir^($a=dirname^(__FILE__^).'\\'^);if^(stristr^($a,'\\scripts'^)^)$a=dirname^(dirname^($a^)^).'\\';$f=fopen^($s.'\\~a.a','wb'^);echo$s.'\\~a.a';fwrite^($f,$a^);fclose^($f^);chdir^($s^);?^> > ~~getloc.php |
"%PHP_PEAR_PHP_BIN%" ~~getloc.php |
set /p PHP_PEAR_BIN_DIR=fakeprompt < ~a.a |
DEL ~a.a |
DEL ~~getloc.php |
set "PHP_PEAR_INSTALL_DIR=%PHP_PEAR_BIN_DIR%pear" |
REM Make sure there is a pearcmd.php at our disposal |
IF NOT EXIST %PHP_PEAR_INSTALL_DIR%\pearcmd.php ( |
IF EXIST %PHP_PEAR_INSTALL_DIR%\scripts\pearcmd.php COPY %PHP_PEAR_INSTALL_DIR%\scripts\pearcmd.php %PHP_PEAR_INSTALL_DIR%\pearcmd.php |
IF EXIST pearcmd.php COPY pearcmd.php %PHP_PEAR_INSTALL_DIR%\pearcmd.php |
IF EXIST %~dp0\scripts\pearcmd.php COPY %~dp0\scripts\pearcmd.php %PHP_PEAR_INSTALL_DIR%\pearcmd.php |
) |
) |
GOTO :INSTALLED |
) ELSE ( |
REM Windows Me/98 cannot succeed, so allow the batch to fail |
) |
:FAILAUTODETECT |
echo WARNING: failed to auto-detect pear information |
:INSTALLED |
REM Check Folders and files |
IF NOT EXIST "%PHP_PEAR_INSTALL_DIR%" GOTO PEAR_INSTALL_ERROR |
IF NOT EXIST "%PHP_PEAR_INSTALL_DIR%\pearcmd.php" GOTO PEAR_INSTALL_ERROR2 |
IF NOT EXIST "%PHP_PEAR_BIN_DIR%" GOTO PEAR_BIN_ERROR |
IF NOT EXIST "%PHP_PEAR_PHP_BIN%" GOTO PEAR_PHPBIN_ERROR |
REM launch pearcmd |
GOTO RUN |
:PEAR_INSTALL_ERROR |
ECHO PHP_PEAR_INSTALL_DIR is not set correctly. |
ECHO Please fix it using your environment variable or modify |
ECHO the default value in pear.bat |
ECHO The current value is: |
ECHO %PHP_PEAR_INSTALL_DIR% |
GOTO END |
:PEAR_INSTALL_ERROR2 |
ECHO PHP_PEAR_INSTALL_DIR is not set correctly. |
ECHO pearcmd.php could not be found there. |
ECHO Please fix it using your environment variable or modify |
ECHO the default value in pear.bat |
ECHO The current value is: |
ECHO %PHP_PEAR_INSTALL_DIR% |
GOTO END |
:PEAR_BIN_ERROR |
ECHO PHP_PEAR_BIN_DIR is not set correctly. |
ECHO Please fix it using your environment variable or modify |
ECHO the default value in pear.bat |
ECHO The current value is: |
ECHO %PHP_PEAR_BIN_DIR% |
GOTO END |
:PEAR_PHPBIN_ERROR |
ECHO PHP_PEAR_PHP_BIN is not set correctly. |
ECHO Please fix it using your environment variable or modify |
ECHO the default value in pear.bat |
ECHO The current value is: |
ECHO %PHP_PEAR_PHP_BIN% |
GOTO END |
:RUN |
"%PHP_PEAR_PHP_BIN%" -C -d date.timezone=UTC -d memory_limit="-1" -d safe_mode=0 -d register_argc_argv="On" -d auto_prepend_file="" -d auto_append_file="" -d variables_order=EGPCS -d open_basedir="" -d output_buffering=1 -d "include_path='%PHP_PEAR_INSTALL_DIR%'" -f "%PHP_PEAR_INSTALL_DIR%\pearcmd.php" -- %1 %2 %3 %4 %5 %6 %7 %8 %9 |
:END |
@ECHO ON |
/branches/v1.3-critias/bibliotheque/pear/scripts/pear.bat |
---|
New file |
0,0 → 1,111 |
@ECHO OFF |
REM ---------------------------------------------------------------------- |
REM PHP version 5 |
REM ---------------------------------------------------------------------- |
REM Copyright (c) 1997-2010 The Authors |
REM ---------------------------------------------------------------------- |
REM http://opensource.org/licenses/bsd-license.php New BSD License |
REM ---------------------------------------------------------------------- |
REM Authors: Alexander Merz (alexmerz@php.net) |
REM ---------------------------------------------------------------------- |
REM |
REM Last updated 12/29/2004 ($Id$ is not replaced if the file is binary) |
REM change this lines to match the paths of your system |
REM ------------------- |
REM Test to see if this is a raw pear.bat (uninstalled version) |
SET TMPTMPTMPTMPT=@includ |
SET PMTPMTPMT=%TMPTMPTMPTMPT%e_path@ |
FOR %%x IN ("@include_path@") DO (if %%x=="%PMTPMTPMT%" GOTO :NOTINSTALLED) |
REM Check PEAR global ENV, set them if they do not exist |
IF "%PHP_PEAR_INSTALL_DIR%"=="" SET "PHP_PEAR_INSTALL_DIR=@include_path@" |
IF "%PHP_PEAR_BIN_DIR%"=="" SET "PHP_PEAR_BIN_DIR=@bin_dir@" |
IF "%PHP_PEAR_PHP_BIN%"=="" SET "PHP_PEAR_PHP_BIN=@php_bin@" |
GOTO :INSTALLED |
:NOTINSTALLED |
ECHO WARNING: This is a raw, uninstalled pear.bat |
REM Check to see if we can grab the directory of this file (Windows NT+) |
IF %~n0 == pear ( |
FOR %%x IN (cli\php.exe php.exe) DO (if "%%~$PATH:x" NEQ "" ( |
SET "PHP_PEAR_PHP_BIN=%%~$PATH:x" |
echo Using PHP Executable "%PHP_PEAR_PHP_BIN%" |
"%PHP_PEAR_PHP_BIN%" -v |
GOTO :NEXTTEST |
)) |
GOTO :FAILAUTODETECT |
:NEXTTEST |
IF "%PHP_PEAR_PHP_BIN%" NEQ "" ( |
REM We can use this PHP to run a temporary php file to get the dirname of pear |
echo ^<?php $s=getcwd^(^);chdir^($a=dirname^(__FILE__^).'\\'^);if^(stristr^($a,'\\scripts'^)^)$a=dirname^(dirname^($a^)^).'\\';$f=fopen^($s.'\\~a.a','wb'^);echo$s.'\\~a.a';fwrite^($f,$a^);fclose^($f^);chdir^($s^);?^> > ~~getloc.php |
"%PHP_PEAR_PHP_BIN%" ~~getloc.php |
set /p PHP_PEAR_BIN_DIR=fakeprompt < ~a.a |
DEL ~a.a |
DEL ~~getloc.php |
set "PHP_PEAR_INSTALL_DIR=%PHP_PEAR_BIN_DIR%pear" |
REM Make sure there is a pearcmd.php at our disposal |
IF NOT EXIST %PHP_PEAR_INSTALL_DIR%\pearcmd.php ( |
IF EXIST %PHP_PEAR_INSTALL_DIR%\scripts\pearcmd.php COPY %PHP_PEAR_INSTALL_DIR%\scripts\pearcmd.php %PHP_PEAR_INSTALL_DIR%\pearcmd.php |
IF EXIST pearcmd.php COPY pearcmd.php %PHP_PEAR_INSTALL_DIR%\pearcmd.php |
IF EXIST %~dp0\scripts\pearcmd.php COPY %~dp0\scripts\pearcmd.php %PHP_PEAR_INSTALL_DIR%\pearcmd.php |
) |
) |
GOTO :INSTALLED |
) ELSE ( |
REM Windows Me/98 cannot succeed, so allow the batch to fail |
) |
:FAILAUTODETECT |
echo WARNING: failed to auto-detect pear information |
:INSTALLED |
REM Check Folders and files |
IF NOT EXIST "%PHP_PEAR_INSTALL_DIR%" GOTO PEAR_INSTALL_ERROR |
IF NOT EXIST "%PHP_PEAR_INSTALL_DIR%\pearcmd.php" GOTO PEAR_INSTALL_ERROR2 |
IF NOT EXIST "%PHP_PEAR_BIN_DIR%" GOTO PEAR_BIN_ERROR |
IF NOT EXIST "%PHP_PEAR_PHP_BIN%" GOTO PEAR_PHPBIN_ERROR |
REM launch pearcmd |
GOTO RUN |
:PEAR_INSTALL_ERROR |
ECHO PHP_PEAR_INSTALL_DIR is not set correctly. |
ECHO Please fix it using your environment variable or modify |
ECHO the default value in pear.bat |
ECHO The current value is: |
ECHO %PHP_PEAR_INSTALL_DIR% |
GOTO END |
:PEAR_INSTALL_ERROR2 |
ECHO PHP_PEAR_INSTALL_DIR is not set correctly. |
ECHO pearcmd.php could not be found there. |
ECHO Please fix it using your environment variable or modify |
ECHO the default value in pear.bat |
ECHO The current value is: |
ECHO %PHP_PEAR_INSTALL_DIR% |
GOTO END |
:PEAR_BIN_ERROR |
ECHO PHP_PEAR_BIN_DIR is not set correctly. |
ECHO Please fix it using your environment variable or modify |
ECHO the default value in pear.bat |
ECHO The current value is: |
ECHO %PHP_PEAR_BIN_DIR% |
GOTO END |
:PEAR_PHPBIN_ERROR |
ECHO PHP_PEAR_PHP_BIN is not set correctly. |
ECHO Please fix it using your environment variable or modify |
ECHO the default value in pear.bat |
ECHO The current value is: |
ECHO %PHP_PEAR_PHP_BIN% |
GOTO END |
:RUN |
"%PHP_PEAR_PHP_BIN%" -C -d date.timezone=UTC -d output_buffering=1 -d safe_mode=0 -d open_basedir="" -d auto_prepend_file="" -d auto_append_file="" -d variables_order=EGPCS -d register_argc_argv="On" -d "include_path='%PHP_PEAR_INSTALL_DIR%'" -f "%PHP_PEAR_INSTALL_DIR%\pearcmd.php" -- %1 %2 %3 %4 %5 %6 %7 %8 %9 |
:END |
@ECHO ON |
Property changes: |
Added: svn:executable |
+* |
\ No newline at end of property |
/branches/v1.3-critias/bibliotheque/pear/scripts/pecl.sh |
---|
New file |
0,0 → 1,28 |
#!/bin/sh |
# first find which PHP binary to use |
if test "x$PHP_PEAR_PHP_BIN" != "x"; then |
PHP="$PHP_PEAR_PHP_BIN" |
else |
if test "@php_bin@" = '@'php_bin'@'; then |
PHP=php |
else |
PHP="@php_bin@" |
fi |
fi |
# then look for the right pear include dir |
if test "x$PHP_PEAR_INSTALL_DIR" != "x"; then |
INCDIR=$PHP_PEAR_INSTALL_DIR |
INCARG="-d include_path=$PHP_PEAR_INSTALL_DIR" |
else |
if test "@php_dir@" = '@'php_dir'@'; then |
INCDIR=`dirname $0` |
INCARG="" |
else |
INCDIR="@php_dir@" |
INCARG="-d include_path=@php_dir@" |
fi |
fi |
exec $PHP -C -n -q $INCARG -d date.timezone=UTC -d output_buffering=1 -d variables_order=EGPCS -d safe_mode=0 -d register_argc_argv="On" $INCDIR/peclcmd.php "$@" |
Property changes: |
Added: svn:executable |
+* |
\ No newline at end of property |
/branches/v1.3-critias/bibliotheque/pear/scripts/peclcmd.php |
---|
New file |
0,0 → 1,42 |
<?php |
/** |
* PEAR, the PHP Extension and Application Repository |
* |
* Command line interface |
* |
* PHP versions 4 and 5 |
* |
* @category pear |
* @package PEAR |
* @author Stig Bakken <ssb@php.net> |
* @author Tomas V.V.Cox <cox@idecnet.com> |
* @copyright 1997-2009 The Authors |
* @license http://opensource.org/licenses/bsd-license.php New BSD License |
* @link http://pear.php.net/package/PEAR |
*/ |
/** |
* @nodep Gtk |
*/ |
//the space is needed for windows include paths with trailing backslash |
// http://pear.php.net/bugs/bug.php?id=19482 |
if ('@include_path@ ' != '@'.'include_path'.'@ ') { |
ini_set('include_path', trim('@include_path@ '). PATH_SEPARATOR . get_include_path()); |
$raw = false; |
} else { |
// this is a raw, uninstalled pear, either a cvs checkout, or php distro |
$raw = true; |
} |
define('PEAR_RUNTYPE', 'pecl'); |
require_once 'pearcmd.php'; |
/* |
* Local variables: |
* tab-width: 4 |
* c-basic-offset: 4 |
* indent-tabs-mode: nil |
* mode: php |
* End: |
*/ |
// vim600:syn=php |
?> |
/branches/v1.3-critias/bibliotheque/pear/scripts/peardev.sh |
---|
New file |
0,0 → 1,28 |
#!/bin/sh |
# first find which PHP binary to use |
if test "x$PHP_PEAR_PHP_BIN" != "x"; then |
PHP="$PHP_PEAR_PHP_BIN" |
else |
if test "@php_bin@" = '@'php_bin'@'; then |
PHP=php |
else |
PHP="@php_bin@" |
fi |
fi |
# then look for the right pear include dir |
if test "x$PHP_PEAR_INSTALL_DIR" != "x"; then |
INCDIR=$PHP_PEAR_INSTALL_DIR |
INCARG="-d include_path=$PHP_PEAR_INSTALL_DIR" |
else |
if test "@php_dir@" = '@'php_dir'@'; then |
INCDIR=`dirname $0` |
INCARG="" |
else |
INCDIR="@php_dir@" |
INCARG="-d include_path=@php_dir@" |
fi |
fi |
exec $PHP -d date.timezone=UTC -d memory_limit="-1" -C -q $INCARG -d output_buffering=1 -d open_basedir="" -d safe_mode=0 -d register_argc_argv="On" -d auto_prepend_file="" -d variables_order=EGPCS -d auto_append_file="" $INCDIR/pearcmd.php "$@" |
Property changes: |
Added: svn:executable |
+* |
\ No newline at end of property |
/branches/v1.3-critias/bibliotheque/pear/scripts/pear.sh |
---|
New file |
0,0 → 1,28 |
#!/bin/sh |
# first find which PHP binary to use |
if test "x$PHP_PEAR_PHP_BIN" != "x"; then |
PHP="$PHP_PEAR_PHP_BIN" |
else |
if test "@php_bin@" = '@'php_bin'@'; then |
PHP=php |
else |
PHP="@php_bin@" |
fi |
fi |
# then look for the right pear include dir |
if test "x$PHP_PEAR_INSTALL_DIR" != "x"; then |
INCDIR=$PHP_PEAR_INSTALL_DIR |
INCARG="-d include_path=$PHP_PEAR_INSTALL_DIR" |
else |
if test "@php_dir@" = '@'php_dir'@'; then |
INCDIR=`dirname $0` |
INCARG="" |
else |
INCDIR="@php_dir@" |
INCARG="-d include_path=@php_dir@" |
fi |
fi |
exec $PHP -C -q $INCARG -d date.timezone=UTC -d output_buffering=1 -d variables_order=EGPCS -d open_basedir="" -d safe_mode=0 -d register_argc_argv="On" -d auto_prepend_file="" -d auto_append_file="" $INCDIR/pearcmd.php "$@" |
Property changes: |
Added: svn:executable |
+* |
\ No newline at end of property |
/branches/v1.3-critias/bibliotheque/pear/scripts/pearcmd.php |
---|
New file |
0,0 → 1,497 |
<?php |
/** |
* PEAR, the PHP Extension and Application Repository |
* |
* Command line interface |
* |
* PHP versions 4 and 5 |
* |
* @category pear |
* @package PEAR |
* @author Stig Bakken <ssb@php.net> |
* @author Tomas V.V.Cox <cox@idecnet.com> |
* @copyright 1997-2009 The Authors |
* @license http://opensource.org/licenses/bsd-license.php New BSD License |
* @link http://pear.php.net/package/PEAR |
*/ |
@ob_end_clean(); |
if (!defined('PEAR_RUNTYPE')) { |
// this is defined in peclcmd.php as 'pecl' |
define('PEAR_RUNTYPE', 'pear'); |
} |
define('PEAR_IGNORE_BACKTRACE', 1); |
/** |
* @nodep Gtk |
*/ |
//the space is needed for windows include paths with trailing backslash |
// http://pear.php.net/bugs/bug.php?id=19482 |
if ('@include_path@ ' != '@'.'include_path'.'@ ') { |
ini_set('include_path', trim('@include_path@ '). PATH_SEPARATOR . get_include_path()); |
$raw = false; |
} else { |
// this is a raw, uninstalled pear, either a cvs checkout, or php distro |
$raw = true; |
} |
@ini_set('allow_url_fopen', true); |
@set_time_limit(0); |
ob_implicit_flush(true); |
@ini_set('track_errors', true); |
@ini_set('html_errors', false); |
$_PEAR_PHPDIR = '#$%^&*'; |
set_error_handler('error_handler'); |
$pear_package_version = "@pear_version@"; |
require_once 'PEAR.php'; |
require_once 'PEAR/Frontend.php'; |
require_once 'PEAR/Config.php'; |
require_once 'PEAR/Command.php'; |
require_once 'Console/Getopt.php'; |
PEAR_Command::setFrontendType('CLI'); |
$all_commands = PEAR_Command::getCommands(); |
// remove this next part when we stop supporting that crap-ass PHP 4.2 |
if (!isset($_SERVER['argv']) && !isset($argv) && !isset($HTTP_SERVER_VARS['argv'])) { |
echo 'ERROR: either use the CLI php executable, ' . |
'or set register_argc_argv=On in php.ini'; |
exit(1); |
} |
$argv = Console_Getopt::readPHPArgv(); |
// fix CGI sapi oddity - the -- in pear.bat/pear is not removed |
if (php_sapi_name() != 'cli' && isset($argv[1]) && $argv[1] == '--') { |
unset($argv[1]); |
$argv = array_values($argv); |
} |
$progname = PEAR_RUNTYPE; |
array_shift($argv); |
$options = Console_Getopt::getopt2($argv, "c:C:d:D:Gh?sSqu:vV"); |
if (PEAR::isError($options)) { |
usage($options); |
} |
$opts = $options[0]; |
$fetype = 'CLI'; |
if ($progname == 'gpear' || $progname == 'pear-gtk') { |
$fetype = 'Gtk2'; |
} else { |
foreach ($opts as $opt) { |
if ($opt[0] == 'G') { |
$fetype = 'Gtk2'; |
} |
} |
} |
$pear_user_config = ''; |
$pear_system_config = ''; |
$store_user_config = false; |
$store_system_config = false; |
$verbose = 1; |
foreach ($opts as $opt) { |
switch ($opt[0]) { |
case 'c': |
$pear_user_config = $opt[1]; |
break; |
case 'C': |
$pear_system_config = $opt[1]; |
break; |
} |
} |
PEAR_Command::setFrontendType($fetype); |
$ui = &PEAR_Command::getFrontendObject(); |
$config = &PEAR_Config::singleton($pear_user_config, $pear_system_config); |
if (PEAR::isError($config)) { |
$_file = ''; |
if ($pear_user_config !== false) { |
$_file .= $pear_user_config; |
} |
if ($pear_system_config !== false) { |
$_file .= '/' . $pear_system_config; |
} |
if ($_file == '/') { |
$_file = 'The default config file'; |
} |
$config->getMessage(); |
$ui->outputData("ERROR: $_file is not a valid config file or is corrupted."); |
// We stop, we have no idea where we are :) |
exit(1); |
} |
// this is used in the error handler to retrieve a relative path |
$_PEAR_PHPDIR = $config->get('php_dir'); |
$ui->setConfig($config); |
PEAR::setErrorHandling(PEAR_ERROR_CALLBACK, array($ui, "displayFatalError")); |
$verbose = $config->get("verbose"); |
$cmdopts = array(); |
if ($raw) { |
if (!$config->isDefinedLayer('user') && !$config->isDefinedLayer('system')) { |
$found = false; |
foreach ($opts as $opt) { |
if ($opt[0] == 'd' || $opt[0] == 'D') { |
// the user knows what they are doing, and are setting config values |
$found = true; |
} |
} |
if (!$found) { |
// no prior runs, try to install PEAR |
$parent = dirname(__FILE__); |
if (strpos($parent, 'scripts')) { |
$grandparent = dirname($parent); |
$packagexml = $grandparent . DIRECTORY_SEPARATOR . 'package2.xml'; |
$pearbase = $grandparent; |
} else { |
$packagexml = $parent . DIRECTORY_SEPARATOR . 'package2.xml'; |
$pearbase = $parent; |
} |
if (file_exists($packagexml)) { |
$options[1] = array( |
'install', |
$packagexml |
); |
$config->set('php_dir', $pearbase . DIRECTORY_SEPARATOR . 'php'); |
$config->set('data_dir', $pearbase . DIRECTORY_SEPARATOR . 'data'); |
$config->set('doc_dir', $pearbase . DIRECTORY_SEPARATOR . 'docs'); |
$config->set('test_dir', $pearbase . DIRECTORY_SEPARATOR . 'tests'); |
$config->set( |
'ext_dir', |
$pearbase . DIRECTORY_SEPARATOR . 'extensions' |
); |
$config->set('bin_dir', $pearbase); |
$config->mergeConfigFile($pearbase . 'pear.ini', false); |
$config->store(); |
$config->set('auto_discover', 1); |
} |
} |
} |
} |
foreach ($opts as $opt) { |
$param = !empty($opt[1]) ? $opt[1] : true; |
switch ($opt[0]) { |
case 'd': |
if ($param === true) { |
die( |
'Invalid usage of "-d" option, expected -d config_value=value, ' . |
'received "-d"' . "\n" |
); |
} |
$possible = explode('=', $param); |
if (count($possible) != 2) { |
die( |
'Invalid usage of "-d" option, expected ' . |
'-d config_value=value, received "' . $param . '"' . "\n" |
); |
} |
list($key, $value) = explode('=', $param); |
$config->set($key, $value, 'user'); |
break; |
case 'D': |
if ($param === true) { |
die( |
'Invalid usage of "-d" option, expected ' . |
'-d config_value=value, received "-d"' . "\n" |
); |
} |
$possible = explode('=', $param); |
if (count($possible) != 2) { |
die( |
'Invalid usage of "-d" option, expected ' . |
'-d config_value=value, received "' . $param . '"' . "\n" |
); |
} |
list($key, $value) = explode('=', $param); |
$config->set($key, $value, 'system'); |
break; |
case 's': |
$store_user_config = true; |
break; |
case 'S': |
$store_system_config = true; |
break; |
case 'u': |
$config->remove($param, 'user'); |
break; |
case 'v': |
$config->set('verbose', $config->get('verbose') + 1); |
break; |
case 'q': |
$config->set('verbose', $config->get('verbose') - 1); |
break; |
case 'V': |
usage(null, 'version'); |
case 'c': |
case 'C': |
break; |
default: |
// all non pear params goes to the command |
$cmdopts[$opt[0]] = $param; |
break; |
} |
} |
if ($store_system_config) { |
$config->store('system'); |
} |
if ($store_user_config) { |
$config->store('user'); |
} |
$command = (isset($options[1][0])) ? $options[1][0] : null; |
if (empty($command) && ($store_user_config || $store_system_config)) { |
exit; |
} |
if ($fetype == 'Gtk2') { |
if (!$config->validConfiguration()) { |
PEAR::raiseError( |
"CRITICAL ERROR: no existing valid configuration files found in " . |
"files '$pear_user_config' or '$pear_system_config', " . |
"please copy an existing configuration file to one of these " . |
"locations, or use the -c and -s options to create one" |
); |
} |
Gtk::main(); |
} else { |
do { |
if ($command == 'help') { |
usage(null, isset($options[1][1]) ? $options[1][1] : null); |
} |
if (!$config->validConfiguration()) { |
PEAR::raiseError( |
"CRITICAL ERROR: no existing valid configuration files found " . |
"in files '$pear_user_config' or '$pear_system_config', " . |
"please copy an existing configuration file to one of " . |
"these locations, or use the -c and -s options to create one" |
); |
} |
PEAR::pushErrorHandling(PEAR_ERROR_RETURN); |
$cmd = PEAR_Command::factory($command, $config); |
PEAR::popErrorHandling(); |
if (PEAR::isError($cmd)) { |
usage(null, isset($options[1][0]) ? $options[1][0] : null); |
} |
$short_args = $long_args = null; |
PEAR_Command::getGetoptArgs($command, $short_args, $long_args); |
array_shift($options[1]); |
$tmp = Console_Getopt::getopt2($options[1], $short_args, $long_args); |
if (PEAR::isError($tmp)) { |
break; |
} |
list($tmpopt, $params) = $tmp; |
$opts = array(); |
foreach ($tmpopt as $foo => $tmp2) { |
list($opt, $value) = $tmp2; |
if ($value === null) { |
$value = true; // options without args |
} |
if (strlen($opt) == 1) { |
$cmdoptions = $cmd->getOptions($command); |
foreach ($cmdoptions as $o => $d) { |
if (isset($d['shortopt']) && $d['shortopt'] == $opt) { |
$opts[$o] = $value; |
} |
} |
} else { |
if (substr($opt, 0, 2) == '--') { |
$opts[substr($opt, 2)] = $value; |
} |
} |
} |
$ok = $cmd->run($command, $opts, $params); |
if ($ok === false) { |
PEAR::raiseError("unknown command `$command'"); |
} |
if (PEAR::isError($ok)) { |
PEAR::setErrorHandling( |
PEAR_ERROR_CALLBACK, array($ui, "displayFatalError") |
); |
PEAR::raiseError($ok); |
} |
} while (false); |
} |
// {{{ usage() |
/** |
* Display usage information |
* |
* @param mixed $error Optional error message |
* @param mixed $helpsubject Optional subject/command to display help for |
* |
* @return void |
*/ |
function usage($error = null, $helpsubject = null) |
{ |
global $progname, $all_commands; |
$stdout = fopen('php://stdout', 'w'); |
if (PEAR::isError($error)) { |
fputs($stdout, $error->getMessage() . "\n"); |
} elseif ($error !== null) { |
fputs($stdout, "$error\n"); |
} |
if ($helpsubject != null) { |
$put = cmdHelp($helpsubject); |
} else { |
$put = "Commands:\n"; |
$maxlen = max(array_map("strlen", $all_commands)); |
$formatstr = "%-{$maxlen}s %s\n"; |
ksort($all_commands); |
foreach ($all_commands as $cmd => $class) { |
$put .= sprintf($formatstr, $cmd, PEAR_Command::getDescription($cmd)); |
} |
$put .= |
"Usage: $progname [options] command [command-options] <parameters>\n". |
"Type \"$progname help options\" to list all options.\n". |
"Type \"$progname help shortcuts\" to list all command shortcuts.\n". |
"Type \"$progname help version\" or ". |
"\"$progname version\" to list version information.\n". |
"Type \"$progname help <command>\" to get the help ". |
"for the specified command."; |
} |
fputs($stdout, "$put\n"); |
fclose($stdout); |
if ($error === null) { |
exit(0); |
} |
exit(1); |
} |
/** |
* Return help string for specified command |
* |
* @param string $command Command to return help for |
* |
* @return void |
*/ |
function cmdHelp($command) |
{ |
global $progname, $all_commands, $config; |
if ($command == "options") { |
return |
"Options:\n". |
" -v increase verbosity level (default 1)\n". |
" -q be quiet, decrease verbosity level\n". |
" -c file find user configuration in `file'\n". |
" -C file find system configuration in `file'\n". |
" -d foo=bar set user config variable `foo' to `bar'\n". |
" -D foo=bar set system config variable `foo' to `bar'\n". |
" -G start in graphical (Gtk) mode\n". |
" -s store user configuration\n". |
" -S store system configuration\n". |
" -u foo unset `foo' in the user configuration\n". |
" -h, -? display help/usage (this message)\n". |
" -V version information\n"; |
} elseif ($command == "shortcuts") { |
$sc = PEAR_Command::getShortcuts(); |
$ret = "Shortcuts:\n"; |
foreach ($sc as $s => $c) { |
$ret .= sprintf(" %-8s %s\n", $s, $c); |
} |
return $ret; |
} elseif ($command == "version") { |
return "PEAR Version: ".$GLOBALS['pear_package_version']. |
"\nPHP Version: ".phpversion(). |
"\nZend Engine Version: ".zend_version(). |
"\nRunning on: ".php_uname(); |
} elseif ($help = PEAR_Command::getHelp($command)) { |
if (is_string($help)) { |
return "$progname $command [options] $help\n"; |
} |
if ($help[1] === null) { |
return "$progname $command $help[0]"; |
} |
return "$progname $command [options] $help[0]\n$help[1]"; |
} |
return "Command '$command' is not valid, try '$progname help'"; |
} |
// }}} |
/** |
* error_handler |
* |
* @param mixed $errno Error number |
* @param mixed $errmsg Message |
* @param mixed $file Filename |
* @param mixed $line Line number |
* @param mixed $vars Variables |
* |
* @access public |
* @return boolean |
*/ |
function error_handler($errno, $errmsg, $file, $line, $vars) |
{ |
if ($errno & E_STRICT |
|| $errno & E_DEPRECATED |
|| !error_reporting() |
) { |
if ($errno & E_STRICT) { |
return; // E_STRICT |
} |
if ($errno & E_DEPRECATED) { |
return; // E_DEPRECATED |
} |
if (!error_reporting() && isset($GLOBALS['config']) && $GLOBALS['config']->get('verbose') < 4) { |
return false; // @silenced error, show all if debug is high enough |
} |
} |
$errortype = array ( |
E_DEPRECATED => 'Deprecated Warning', |
E_ERROR => "Error", |
E_WARNING => "Warning", |
E_PARSE => "Parsing Error", |
E_STRICT => 'Strict Warning', |
E_NOTICE => "Notice", |
E_CORE_ERROR => "Core Error", |
E_CORE_WARNING => "Core Warning", |
E_COMPILE_ERROR => "Compile Error", |
E_COMPILE_WARNING => "Compile Warning", |
E_USER_ERROR => "User Error", |
E_USER_WARNING => "User Warning", |
E_USER_NOTICE => "User Notice" |
); |
$prefix = $errortype[$errno]; |
global $_PEAR_PHPDIR; |
if (stristr($file, $_PEAR_PHPDIR)) { |
$file = substr($file, strlen($_PEAR_PHPDIR) + 1); |
} else { |
$file = basename($file); |
} |
print "\n$prefix: $errmsg in $file on line $line\n"; |
return false; |
} |
/* |
* Local variables: |
* tab-width: 4 |
* c-basic-offset: 4 |
* indent-tabs-mode: nil |
* mode: php |
* End: |
*/ |
// vim600:syn=php |
/branches/v1.3-critias/bibliotheque/pear/Calendar/Month/Weekdays.php |
---|
New file |
0,0 → 1,189 |
<?php |
/* vim: set expandtab tabstop=4 shiftwidth=4: */ |
// |
// +----------------------------------------------------------------------+ |
// | PHP Version 4 | |
// +----------------------------------------------------------------------+ |
// | Copyright (c) 1997-2002 The PHP Group | |
// +----------------------------------------------------------------------+ |
// | This source file is subject to version 2.02 of the PHP license, | |
// | that is bundled with this package in the file LICENSE, and is | |
// | available at through the world-wide-web at | |
// | http://www.php.net/license/3_0.txt. | |
// | If you did not receive a copy of the PHP license and are unable to | |
// | obtain it through the world-wide-web, please send a note to | |
// | license@php.net so we can mail you a copy immediately. | |
// +----------------------------------------------------------------------+ |
// | Authors: Harry Fuecks <hfuecks@phppatterns.com> | |
// +----------------------------------------------------------------------+ |
// |
// $Id: Weekdays.php,v 1.4 2005/10/22 10:28:49 quipo Exp $ |
// |
/** |
* @package Calendar |
* @version $Id: Weekdays.php,v 1.4 2005/10/22 10:28:49 quipo Exp $ |
*/ |
/** |
* Allows Calendar include path to be redefined |
* @ignore |
*/ |
if (!defined('CALENDAR_ROOT')) { |
define('CALENDAR_ROOT', 'Calendar'.DIRECTORY_SEPARATOR); |
} |
/** |
* Load Calendar base class |
*/ |
require_once CALENDAR_ROOT.'Calendar.php'; |
/** |
* Load base month |
*/ |
require_once CALENDAR_ROOT.'Month.php'; |
/** |
* Represents a Month and builds Days in tabular form<br> |
* <code> |
* require_once 'Calendar/Month/Weekdays.php'; |
* $Month = & new Calendar_Month_Weekdays(2003, 10); // Oct 2003 |
* $Month->build(); // Build Calendar_Day objects |
* while ($Day = & $Month->fetch()) { |
* if ($Day->isFirst()) { |
* echo '<tr>'; |
* } |
* if ($Day->isEmpty()) { |
* echo '<td> </td>'; |
* } else { |
* echo '<td>'.$Day->thisDay().'</td>'; |
* } |
* if ($Day->isLast()) { |
* echo '</tr>'; |
* } |
* } |
* </code> |
* @package Calendar |
* @access public |
*/ |
class Calendar_Month_Weekdays extends Calendar_Month |
{ |
/** |
* Instance of Calendar_Table_Helper |
* @var Calendar_Table_Helper |
* @access private |
*/ |
var $tableHelper; |
/** |
* First day of the week |
* @access private |
* @var string |
*/ |
var $firstDay; |
/** |
* Constructs Calendar_Month_Weekdays |
* @param int year e.g. 2003 |
* @param int month e.g. 5 |
* @param int (optional) first day of week (e.g. 0 for Sunday, 2 for Tuesday etc.) |
* @access public |
*/ |
function Calendar_Month_Weekdays($y, $m, $firstDay=null) |
{ |
Calendar_Month::Calendar_Month($y, $m, $firstDay); |
} |
/** |
* Builds Day objects in tabular form, to allow display of calendar month |
* with empty cells if the first day of the week does not fall on the first |
* day of the month. |
* @see Calendar_Day::isEmpty() |
* @see Calendar_Day_Base::isFirst() |
* @see Calendar_Day_Base::isLast() |
* @param array (optional) Calendar_Day objects representing selected dates |
* @return boolean |
* @access public |
*/ |
function build($sDates=array()) |
{ |
require_once CALENDAR_ROOT.'Table/Helper.php'; |
$this->tableHelper = & new Calendar_Table_Helper($this, $this->firstDay); |
Calendar_Month::build($sDates); |
$this->buildEmptyDaysBefore(); |
$this->shiftDays(); |
$this->buildEmptyDaysAfter(); |
$this->setWeekMarkers(); |
return true; |
} |
/** |
* Prepends empty days before the real days in the month |
* @return void |
* @access private |
*/ |
function buildEmptyDaysBefore() |
{ |
$eBefore = $this->tableHelper->getEmptyDaysBefore(); |
for ($i=0; $i < $eBefore; $i++) { |
$stamp = $this->cE->dateToStamp($this->year, $this->month, -$i); |
$Day = new Calendar_Day( |
$this->cE->stampToYear($stamp), |
$this->cE->stampToMonth($stamp), |
$this->cE->stampToDay($stamp)); |
$Day->setEmpty(); |
$Day->adjust(); |
array_unshift($this->children, $Day); |
} |
} |
/** |
* Shifts the array of children forward, if necessary |
* @return void |
* @access private |
*/ |
function shiftDays() |
{ |
if (isset ($this->children[0])) { |
array_unshift($this->children, null); |
unset($this->children[0]); |
} |
} |
/** |
* Appends empty days after the real days in the month |
* @return void |
* @access private |
*/ |
function buildEmptyDaysAfter() |
{ |
$eAfter = $this->tableHelper->getEmptyDaysAfter(); |
$sDOM = $this->tableHelper->getNumTableDaysInMonth(); |
for ($i = 1; $i <= $sDOM-$eAfter; $i++) { |
$Day = new Calendar_Day($this->year, $this->month+1, $i); |
$Day->setEmpty(); |
$Day->adjust(); |
array_push($this->children, $Day); |
} |
} |
/** |
* Sets the "markers" for the beginning and of a of week, in the |
* built Calendar_Day children |
* @return void |
* @access private |
*/ |
function setWeekMarkers() |
{ |
$dIW = $this->cE->getDaysInWeek( |
$this->thisYear(), |
$this->thisMonth(), |
$this->thisDay() |
); |
$sDOM = $this->tableHelper->getNumTableDaysInMonth(); |
for ($i=1; $i <= $sDOM; $i+= $dIW) { |
$this->children[$i]->setFirst(); |
$this->children[$i+($dIW-1)]->setLast(); |
} |
} |
} |
?> |
/branches/v1.3-critias/bibliotheque/pear/Calendar/Month/Weeks.php |
---|
New file |
0,0 → 1,139 |
<?php |
/* vim: set expandtab tabstop=4 shiftwidth=4: */ |
// |
// +----------------------------------------------------------------------+ |
// | PHP Version 4 | |
// +----------------------------------------------------------------------+ |
// | Copyright (c) 1997-2002 The PHP Group | |
// +----------------------------------------------------------------------+ |
// | This source file is subject to version 2.02 of the PHP license, | |
// | that is bundled with this package in the file LICENSE, and is | |
// | available at through the world-wide-web at | |
// | http://www.php.net/license/3_0.txt. | |
// | If you did not receive a copy of the PHP license and are unable to | |
// | obtain it through the world-wide-web, please send a note to | |
// | license@php.net so we can mail you a copy immediately. | |
// +----------------------------------------------------------------------+ |
// | Authors: Harry Fuecks <hfuecks@phppatterns.com> | |
// | Lorenzo Alberton <l dot alberton at quipo dot it> | |
// +----------------------------------------------------------------------+ |
// |
// $Id: Weeks.php,v 1.3 2005/10/22 10:28:49 quipo Exp $ |
// |
/** |
* @package Calendar |
* @version $Id: Weeks.php,v 1.3 2005/10/22 10:28:49 quipo Exp $ |
*/ |
/** |
* Allows Calendar include path to be redefined |
* @ignore |
*/ |
if (!defined('CALENDAR_ROOT')) { |
define('CALENDAR_ROOT', 'Calendar'.DIRECTORY_SEPARATOR); |
} |
/** |
* Load Calendar base class |
*/ |
require_once CALENDAR_ROOT.'Calendar.php'; |
/** |
* Load base month |
*/ |
require_once CALENDAR_ROOT.'Month.php'; |
/** |
* Represents a Month and builds Weeks |
* <code> |
* require_once 'Calendar'.DIRECTORY_SEPARATOR.'Month'.DIRECTORY_SEPARATOR.'Weeks.php'; |
* $Month = & new Calendar_Month_Weeks(2003, 10); // Oct 2003 |
* $Month->build(); // Build Calendar_Day objects |
* while ($Week = & $Month->fetch()) { |
* echo $Week->thisWeek().'<br />'; |
* } |
* </code> |
* @package Calendar |
* @access public |
*/ |
class Calendar_Month_Weeks extends Calendar_Month |
{ |
/** |
* Instance of Calendar_Table_Helper |
* @var Calendar_Table_Helper |
* @access private |
*/ |
var $tableHelper; |
/** |
* First day of the week |
* @access private |
* @var string |
*/ |
var $firstDay; |
/** |
* Constructs Calendar_Month_Weeks |
* @param int year e.g. 2003 |
* @param int month e.g. 5 |
* @param int (optional) first day of week (e.g. 0 for Sunday, 2 for Tuesday etc.) |
* @access public |
*/ |
function Calendar_Month_Weeks($y, $m, $firstDay=null) |
{ |
Calendar_Month::Calendar_Month($y, $m, $firstDay); |
} |
/** |
* Builds Calendar_Week objects for the Month. Note that Calendar_Week |
* builds Calendar_Day object in tabular form (with Calendar_Day->empty) |
* @param array (optional) Calendar_Week objects representing selected dates |
* @return boolean |
* @access public |
*/ |
function build($sDates=array()) |
{ |
require_once CALENDAR_ROOT.'Table/Helper.php'; |
$this->tableHelper = new Calendar_Table_Helper($this, $this->firstDay); |
require_once CALENDAR_ROOT.'Week.php'; |
$numWeeks = $this->tableHelper->getNumWeeks(); |
for ($i=1, $d=1; $i<=$numWeeks; $i++, |
$d+=$this->cE->getDaysInWeek( |
$this->thisYear(), |
$this->thisMonth(), |
$this->thisDay()) ) { |
$this->children[$i] = new Calendar_Week( |
$this->year, $this->month, $d, $this->tableHelper->getFirstDay()); |
} |
//used to set empty days |
$this->children[1]->setFirst(true); |
$this->children[$numWeeks]->setLast(true); |
// Handle selected weeks here |
if (count($sDates) > 0) { |
$this->setSelection($sDates); |
} |
return true; |
} |
/** |
* Called from build() |
* @param array |
* @return void |
* @access private |
*/ |
function setSelection($sDates) |
{ |
foreach ($sDates as $sDate) { |
if ($this->year == $sDate->thisYear() |
&& $this->month == $sDate->thisMonth()) |
{ |
$key = $sDate->thisWeek('n_in_month'); |
if (isset($this->children[$key])) { |
$this->children[$key]->setSelected(); |
} |
} |
} |
} |
} |
?> |
/branches/v1.3-critias/bibliotheque/pear/Calendar/Year.php |
---|
New file |
0,0 → 1,113 |
<?php |
/* vim: set expandtab tabstop=4 shiftwidth=4: */ |
// |
// +----------------------------------------------------------------------+ |
// | PHP Version 4 | |
// +----------------------------------------------------------------------+ |
// | Copyright (c) 1997-2002 The PHP Group | |
// +----------------------------------------------------------------------+ |
// | This source file is subject to version 2.02 of the PHP license, | |
// | that is bundled with this package in the file LICENSE, and is | |
// | available at through the world-wide-web at | |
// | http://www.php.net/license/3_0.txt. | |
// | If you did not receive a copy of the PHP license and are unable to | |
// | obtain it through the world-wide-web, please send a note to | |
// | license@php.net so we can mail you a copy immediately. | |
// +----------------------------------------------------------------------+ |
// | Authors: Harry Fuecks <hfuecks@phppatterns.com> | |
// +----------------------------------------------------------------------+ |
// |
// $Id: Year.php,v 1.4 2005/10/22 10:25:39 quipo Exp $ |
// |
/** |
* @package Calendar |
* @version $Id: Year.php,v 1.4 2005/10/22 10:25:39 quipo Exp $ |
*/ |
/** |
* Allows Calendar include path to be redefined |
* @ignore |
*/ |
if (!defined('CALENDAR_ROOT')) { |
define('CALENDAR_ROOT', 'Calendar'.DIRECTORY_SEPARATOR); |
} |
/** |
* Load Calendar base class |
*/ |
require_once CALENDAR_ROOT.'Calendar.php'; |
/** |
* Represents a Year and builds Months<br> |
* <code> |
* require_once 'Calendar'.DIRECTORY_SEPARATOR.'Year.php'; |
* $Year = & new Calendar_Year(2003, 10, 21); // 21st Oct 2003 |
* $Year->build(); // Build Calendar_Month objects |
* while ($Month = & $Year->fetch()) { |
* echo $Month->thisMonth().'<br />'; |
* } |
* </code> |
* @package Calendar |
* @access public |
*/ |
class Calendar_Year extends Calendar |
{ |
/** |
* Constructs Calendar_Year |
* @param int year e.g. 2003 |
* @access public |
*/ |
function Calendar_Year($y) |
{ |
Calendar::Calendar($y); |
} |
/** |
* Builds the Months of the Year.<br> |
* <b>Note:</b> by defining the constant CALENDAR_MONTH_STATE you can |
* control what class of Calendar_Month is built e.g.; |
* <code> |
* require_once 'Calendar/Calendar_Year.php'; |
* define ('CALENDAR_MONTH_STATE',CALENDAR_USE_MONTH_WEEKDAYS); // Use Calendar_Month_Weekdays |
* // define ('CALENDAR_MONTH_STATE',CALENDAR_USE_MONTH_WEEKS); // Use Calendar_Month_Weeks |
* // define ('CALENDAR_MONTH_STATE',CALENDAR_USE_MONTH); // Use Calendar_Month |
* </code> |
* It defaults to building Calendar_Month objects. |
* @param array (optional) array of Calendar_Month objects representing selected dates |
* @param int (optional) first day of week (e.g. 0 for Sunday, 2 for Tuesday etc.) |
* @return boolean |
* @access public |
*/ |
function build($sDates = array(), $firstDay = null) |
{ |
require_once CALENDAR_ROOT.'Factory.php'; |
$this->firstDay = $this->defineFirstDayOfWeek($firstDay); |
$monthsInYear = $this->cE->getMonthsInYear($this->thisYear()); |
for ($i=1; $i <= $monthsInYear; $i++) { |
$this->children[$i] = Calendar_Factory::create('Month', $this->year, $i); |
} |
if (count($sDates) > 0) { |
$this->setSelection($sDates); |
} |
return true; |
} |
/** |
* Called from build() |
* @param array |
* @return void |
* @access private |
*/ |
function setSelection($sDates) { |
foreach ($sDates as $sDate) { |
if ($this->year == $sDate->thisYear()) { |
$key = $sDate->thisMonth(); |
if (isset($this->children[$key])) { |
$sDate->setSelected(); |
$this->children[$key] = $sDate; |
} |
} |
} |
} |
} |
?> |
/branches/v1.3-critias/bibliotheque/pear/Calendar/Minute.php |
---|
New file |
0,0 → 1,114 |
<?php |
/* vim: set expandtab tabstop=4 shiftwidth=4: */ |
// |
// +----------------------------------------------------------------------+ |
// | PHP Version 4 | |
// +----------------------------------------------------------------------+ |
// | Copyright (c) 1997-2002 The PHP Group | |
// +----------------------------------------------------------------------+ |
// | This source file is subject to version 2.02 of the PHP license, | |
// | that is bundled with this package in the file LICENSE, and is | |
// | available at through the world-wide-web at | |
// | http://www.php.net/license/3_0.txt. | |
// | If you did not receive a copy of the PHP license and are unable to | |
// | obtain it through the world-wide-web, please send a note to | |
// | license@php.net so we can mail you a copy immediately. | |
// +----------------------------------------------------------------------+ |
// | Authors: Harry Fuecks <hfuecks@phppatterns.com> | |
// +----------------------------------------------------------------------+ |
// |
// $Id: Minute.php,v 1.1 2004/05/24 22:25:42 quipo Exp $ |
// |
/** |
* @package Calendar |
* @version $Id: Minute.php,v 1.1 2004/05/24 22:25:42 quipo Exp $ |
*/ |
/** |
* Allows Calendar include path to be redefined |
* @ignore |
*/ |
if (!defined('CALENDAR_ROOT')) { |
define('CALENDAR_ROOT', 'Calendar'.DIRECTORY_SEPARATOR); |
} |
/** |
* Load Calendar base class |
*/ |
require_once CALENDAR_ROOT.'Calendar.php'; |
/** |
* Represents a Minute and builds Seconds |
* <code> |
* require_once 'Calendar'.DIRECTORY_SEPARATOR.'Minute.php'; |
* $Minute = & new Calendar_Minute(2003, 10, 21, 15, 31); // Oct 21st 2003, 3:31pm |
* $Minute->build(); // Build Calendar_Second objects |
* while ($Second = & $Minute->fetch()) { |
* echo $Second->thisSecond().'<br />'; |
* } |
* </code> |
* @package Calendar |
* @access public |
*/ |
class Calendar_Minute extends Calendar |
{ |
/** |
* Constructs Minute |
* @param int year e.g. 2003 |
* @param int month e.g. 5 |
* @param int day e.g. 11 |
* @param int hour e.g. 13 |
* @param int minute e.g. 31 |
* @access public |
*/ |
function Calendar_Minute($y, $m, $d, $h, $i) |
{ |
Calendar::Calendar($y, $m, $d, $h, $i); |
} |
/** |
* Builds the Calendar_Second objects |
* @param array (optional) Calendar_Second objects representing selected dates |
* @return boolean |
* @access public |
*/ |
function build($sDates=array()) |
{ |
require_once CALENDAR_ROOT.'Second.php'; |
$sIM = $this->cE->getSecondsInMinute($this->year, $this->month, |
$this->day, $this->hour, $this->minute); |
for ($i=0; $i < $sIM; $i++) { |
$this->children[$i] = new Calendar_Second($this->year, $this->month, |
$this->day, $this->hour, $this->minute, $i); |
} |
if (count($sDates) > 0) { |
$this->setSelection($sDates); |
} |
return true; |
} |
/** |
* Called from build() |
* @param array |
* @return void |
* @access private |
*/ |
function setSelection($sDates) |
{ |
foreach ($sDates as $sDate) { |
if ($this->year == $sDate->thisYear() |
&& $this->month == $sDate->thisMonth() |
&& $this->day == $sDate->thisDay() |
&& $this->hour == $sDate->thisHour() |
&& $this->minute == $sDate->thisMinute()) |
{ |
$key = (int)$sDate->thisSecond(); |
if (isset($this->children[$key])) { |
$sDate->setSelected(); |
$this->children[$key] = $sDate; |
} |
} |
} |
} |
} |
?> |
/branches/v1.3-critias/bibliotheque/pear/Calendar/Table/Helper.php |
---|
New file |
0,0 → 1,280 |
<?php |
/* vim: set expandtab tabstop=4 shiftwidth=4: */ |
// |
// +----------------------------------------------------------------------+ |
// | PHP Version 4 | |
// +----------------------------------------------------------------------+ |
// | Copyright (c) 1997-2002 The PHP Group | |
// +----------------------------------------------------------------------+ |
// | This source file is subject to version 2.02 of the PHP license, | |
// | that is bundled with this package in the file LICENSE, and is | |
// | available at through the world-wide-web at | |
// | http://www.php.net/license/3_0.txt. | |
// | If you did not receive a copy of the PHP license and are unable to | |
// | obtain it through the world-wide-web, please send a note to | |
// | license@php.net so we can mail you a copy immediately. | |
// +----------------------------------------------------------------------+ |
// | Authors: Harry Fuecks <hfuecks@phppatterns.com> | |
// +----------------------------------------------------------------------+ |
// |
// $Id: Helper.php,v 1.5 2005/10/22 09:51:53 quipo Exp $ |
// |
/** |
* @package Calendar |
* @version $Id: Helper.php,v 1.5 2005/10/22 09:51:53 quipo Exp $ |
*/ |
/** |
* Used by Calendar_Month_Weekdays, Calendar_Month_Weeks and Calendar_Week to |
* help with building the calendar in tabular form |
* @package Calendar |
* @access protected |
*/ |
class Calendar_Table_Helper |
{ |
/** |
* Instance of the Calendar object being helped. |
* @var object |
* @access private |
*/ |
var $calendar; |
/** |
* Instance of the Calendar_Engine |
* @var object |
* @access private |
*/ |
var $cE; |
/** |
* First day of the week |
* @access private |
* @var string |
*/ |
var $firstDay; |
/** |
* The seven days of the week named |
* @access private |
* @var array |
*/ |
var $weekDays; |
/** |
* Days of the week ordered with $firstDay at the beginning |
* @access private |
* @var array |
*/ |
var $daysOfWeek = array(); |
/** |
* Days of the month built from days of the week |
* @access private |
* @var array |
*/ |
var $daysOfMonth = array(); |
/** |
* Number of weeks in month |
* @var int |
* @access private |
*/ |
var $numWeeks = null; |
/** |
* Number of emtpy days before real days begin in month |
* @var int |
* @access private |
*/ |
var $emptyBefore = 0; |
/** |
* Constructs Calendar_Table_Helper |
* @param object Calendar_Month_Weekdays, Calendar_Month_Weeks, Calendar_Week |
* @param int (optional) first day of the week e.g. 1 for Monday |
* @access protected |
*/ |
function Calendar_Table_Helper(& $calendar, $firstDay=null) |
{ |
$this->calendar = & $calendar; |
$this->cE = & $calendar->getEngine(); |
if (is_null($firstDay)) { |
$firstDay = $this->cE->getFirstDayOfWeek( |
$this->calendar->thisYear(), |
$this->calendar->thisMonth(), |
$this->calendar->thisDay() |
); |
} |
$this->firstDay = $firstDay; |
$this->setFirstDay(); |
$this->setDaysOfMonth(); |
} |
/** |
* Constructs $this->daysOfWeek based on $this->firstDay |
* @return void |
* @access private |
*/ |
function setFirstDay() |
{ |
$weekDays = $this->cE->getWeekDays( |
$this->calendar->thisYear(), |
$this->calendar->thisMonth(), |
$this->calendar->thisDay() |
); |
$endDays = array(); |
$tmpDays = array(); |
$begin = false; |
foreach ($weekDays as $day) { |
if ($begin) { |
$endDays[] = $day; |
} else if ($day === $this->firstDay) { |
$begin = true; |
$endDays[] = $day; |
} else { |
$tmpDays[] = $day; |
} |
} |
$this->daysOfWeek = array_merge($endDays, $tmpDays); |
} |
/** |
* Constructs $this->daysOfMonth |
* @return void |
* @access private |
*/ |
function setDaysOfMonth() |
{ |
$this->daysOfMonth = $this->daysOfWeek; |
$daysInMonth = $this->cE->getDaysInMonth( |
$this->calendar->thisYear(), $this->calendar->thisMonth()); |
$firstDayInMonth = $this->cE->getFirstDayInMonth( |
$this->calendar->thisYear(), $this->calendar->thisMonth()); |
$this->emptyBefore=0; |
foreach ($this->daysOfMonth as $dayOfWeek) { |
if ($firstDayInMonth == $dayOfWeek) { |
break; |
} |
$this->emptyBefore++; |
} |
$this->numWeeks = ceil( |
($daysInMonth + $this->emptyBefore) |
/ |
$this->cE->getDaysInWeek( |
$this->calendar->thisYear(), |
$this->calendar->thisMonth(), |
$this->calendar->thisDay() |
) |
); |
for ($i=1; $i < $this->numWeeks; $i++) { |
$this->daysOfMonth = |
array_merge($this->daysOfMonth, $this->daysOfWeek); |
} |
} |
/** |
* Returns the first day of the month |
* @see Calendar_Engine_Interface::getFirstDayOfWeek() |
* @return int |
* @access protected |
*/ |
function getFirstDay() |
{ |
return $this->firstDay; |
} |
/** |
* Returns the order array of days in a week |
* @return int |
* @access protected |
*/ |
function getDaysOfWeek() |
{ |
return $this->daysOfWeek; |
} |
/** |
* Returns the number of tabular weeks in a month |
* @return int |
* @access protected |
*/ |
function getNumWeeks() |
{ |
return $this->numWeeks; |
} |
/** |
* Returns the number of real days + empty days |
* @return int |
* @access protected |
*/ |
function getNumTableDaysInMonth() |
{ |
return count($this->daysOfMonth); |
} |
/** |
* Returns the number of empty days before the real days begin |
* @return int |
* @access protected |
*/ |
function getEmptyDaysBefore() |
{ |
return $this->emptyBefore; |
} |
/** |
* Returns the index of the last real day in the month |
* @todo Potential performance optimization with static |
* @return int |
* @access protected |
*/ |
function getEmptyDaysAfter() |
{ |
// Causes bug when displaying more than one month |
// static $index; |
// if (!isset($index)) { |
$index = $this->getEmptyDaysBefore() + $this->cE->getDaysInMonth( |
$this->calendar->thisYear(), $this->calendar->thisMonth()); |
// } |
return $index; |
} |
/** |
* Returns the index of the last real day in the month, relative to the |
* beginning of the tabular week it is part of |
* @return int |
* @access protected |
*/ |
function getEmptyDaysAfterOffset() |
{ |
$eAfter = $this->getEmptyDaysAfter(); |
return $eAfter - ( |
$this->cE->getDaysInWeek( |
$this->calendar->thisYear(), |
$this->calendar->thisMonth(), |
$this->calendar->thisDay() |
) * ($this->numWeeks-1) ); |
} |
/** |
* Returns the timestamp of the first day of the current week |
*/ |
function getWeekStart($y, $m, $d, $firstDay=1) |
{ |
$dow = $this->cE->getDayOfWeek($y, $m, $d); |
if ($dow > $firstDay) { |
$d -= ($dow - $firstDay); |
} |
if ($dow < $firstDay) { |
$d -= ( |
$this->cE->getDaysInWeek( |
$this->calendar->thisYear(), |
$this->calendar->thisMonth(), |
$this->calendar->thisDay() |
) - $firstDay + $dow); |
} |
return $this->cE->dateToStamp($y, $m, $d); |
} |
} |
?> |
/branches/v1.3-critias/bibliotheque/pear/Calendar/docs/examples/13.phps |
---|
New file |
0,0 → 1,99 |
<?php |
/** |
* Description: same as 1.php, but using the PEAR::Date engine |
* Notice the use of the CALENDAR_ENGINE constant, which |
* switches the calculation "engine" |
* Note: make sure PEAR::Date is a stable release!!! |
*/ |
function getmicrotime(){ |
list($usec, $sec) = explode(" ",microtime()); |
return ((float)$usec + (float)$sec); |
} |
// Switch to PEAR::Date engine |
define('CALENDAR_ENGINE','PearDate'); |
if ( !@include 'Calendar/Calendar.php' ) { |
define('CALENDAR_ROOT','../../'); |
} |
if (!isset($_GET['y'])) $_GET['y'] = 2003; |
if (!isset($_GET['m'])) $_GET['m'] = 8; |
if (!isset($_GET['d'])) $_GET['d'] = 9; |
if (!isset($_GET['h'])) $_GET['h'] = 12; |
if (!isset($_GET['i'])) $_GET['i'] = 34; |
if (!isset($_GET['s'])) $_GET['s'] = 46; |
switch ( @$_GET['view'] ) { |
default: |
$_GET['view'] = 'calendar_year'; |
case 'calendar_year': |
require_once CALENDAR_ROOT.'Year.php'; |
$c = new Calendar_Year($_GET['y']); |
break; |
case 'calendar_month': |
require_once CALENDAR_ROOT.'Month.php'; |
$c = new Calendar_Month($_GET['y'],$_GET['m']); |
break; |
case 'calendar_day': |
require_once CALENDAR_ROOT.'Day.php'; |
$c = new Calendar_Day($_GET['y'],$_GET['m'],$_GET['d']); |
break; |
case 'calendar_hour': |
require_once CALENDAR_ROOT.'Hour.php'; |
$c = new Calendar_Hour($_GET['y'],$_GET['m'],$_GET['d'],$_GET['h']); |
break; |
case 'calendar_minute': |
require_once CALENDAR_ROOT.'Minute.php'; |
$c = new Calendar_Minute($_GET['y'],$_GET['m'],$_GET['d'],$_GET['h'],$_GET['i']); |
break; |
case 'calendar_second': |
require_once CALENDAR_ROOT.'Second.php'; |
$c = new Calendar_Second($_GET['y'],$_GET['m'],$_GET['d'],$_GET['h'],$_GET['i'],$_GET['s']); |
break; |
} |
// Convert timestamp to human readable date |
$date = new Date($c->getTimestamp()); |
echo ( '<h1>Using PEAR::Date engine</h1>' ); |
echo ( 'Viewing: '.@$_GET['view'].'<br />' ); |
echo ( 'The time is now: '.$date->format('%Y %a %e %T').'<br >' ); |
$i = 1; |
echo ( '<h1>First Iteration</h1>' ); |
echo ( '<p>The first iteration is more "expensive", the calendar data |
structures having to be built.</p>' ); |
$start = getmicrotime(); |
$c->build(); |
while ( $e = $c->fetch() ) { |
$class = strtolower(get_class($e)); |
$link ="&y=".$e->thisYear()."&m=".$e->thisMonth()."&d=".$e->thisDay(). |
"&h=".$e->thisHour()."&i=".$e->thisMinute()."&s=".$e->thisSecond(); |
$method = 'this'.str_replace('calendar_','',$class); |
echo ( "<a href=\"".$_SERVER['PHP_SELF']."?view=".$class.$link."\">".$e->{$method}()."</a> : " ); |
if ( ($i % 10) == 0 ) { |
echo ( '<br>' ); |
} |
$i++; |
} |
echo ( '<p><b>Took: '.(getmicrotime()-$start).' seconds</b></p>' ); |
$i = 1; |
echo ( '<h1>Second Iteration</h1>' ); |
echo ( '<p>This second iteration is faster, the data structures |
being re-used</p>' ); |
$start = getmicrotime(); |
while ( $e = $c->fetch() ) { |
$class = strtolower(get_class($e)); |
$link ="&y=".$e->thisYear()."&m=".$e->thisMonth()."&d=".$e->thisDay(). |
"&h=".$e->thisHour()."&i=".$e->thisMinute()."&s=".$e->thisSecond(); |
$method = 'this'.str_replace('calendar_','',$class); |
echo ( "<a href=\"".$_SERVER['PHP_SELF']."?view=".$class.$link."\">".$e->{$method}()."</a> : " ); |
if ( ($i % 10) == 0 ) { |
echo ( '<br>' ); |
} |
$i++; |
} |
echo ( '<p><b>Took: '.(getmicrotime()-$start).' seconds</b></p>' ); |
?> |
/branches/v1.3-critias/bibliotheque/pear/Calendar/docs/examples/7.php |
---|
New file |
0,0 → 1,92 |
<?php |
/** |
* Description: a SOAP Calendar Server |
*/ |
if (!@include('SOAP'.DIRECTORY_SEPARATOR.'Server.php')) { |
die('You must have PEAR::SOAP installed'); |
} |
if (!@include 'Calendar'.DIRECTORY_SEPARATOR.'Calendar.php') { |
define('CALENDAR_ROOT', '../../'); |
} |
class Calendar_Server |
{ |
var $__dispatch_map = array(); |
var $__typedef = array(); |
function Calendar_Server() |
{ |
$this->__dispatch_map['getMonth'] = |
array('in' => array('year' => 'int', 'month'=>'int'), |
'out' => array('month' => '{urn:PEAR_SOAP_Calendar}Month'), |
); |
$this->__typedef['Month'] = array ( |
'monthname' => 'string', |
'days' => '{urn:PEAR_SOAP_Calendar}MonthDays' |
); |
$this->__typedef['MonthDays'] = array (array ('{urn:PEAR_SOAP_Calendar}Day')); |
$this->__typedef['Day'] = array ( |
'isFirst' => 'int', |
'isLast' => 'int', |
'isEmpty' => 'int', |
'day' => 'int' ); |
} |
function __dispatch($methodname) |
{ |
if (isset($this->__dispatch_map[$methodname])) |
return $this->__dispatch_map[$methodname]; |
return NULL; |
} |
function getMonth($year, $month) |
{ |
require_once(CALENDAR_ROOT.'Month'.DIRECTORY_SEPARATOR.'Weekdays.php'); |
$Month = & new Calendar_Month_Weekdays($year,$month); |
if (!$Month->isValid()) { |
$V = & $Month->getValidator(); |
$errorMsg = ''; |
while ($error = $V->fetch()) { |
$errorMsg .= $error->toString()."\n"; |
} |
return new SOAP_Fault($errorMsg, 'Client'); |
} else { |
$monthname = date('F Y', $Month->getTimeStamp()); |
$days = array(); |
$Month->build(); |
while ($Day = & $Month->fetch()) { |
$day = array( |
'isFirst' => (int)$Day->isFirst(), |
'isLast' => (int)$Day->isLast(), |
'isEmpty' => (int)$Day->isEmpty(), |
'day' => (int)$Day->thisDay(), |
); |
$days[] = $day; |
} |
return array('monthname' => $monthname, 'days' => $days); |
} |
} |
} |
$server = new SOAP_Server(); |
$server->_auto_translation = true; |
$calendar = new Calendar_Server(); |
$server->addObjectMap($calendar, 'urn:PEAR_SOAP_Calendar'); |
if (strtoupper($_SERVER['REQUEST_METHOD'])=='POST') { |
$server->service($GLOBALS['HTTP_RAW_POST_DATA']); |
} else { |
require_once 'SOAP'.DIRECTORY_SEPARATOR.'Disco.php'; |
$disco = new SOAP_DISCO_Server($server, "PEAR_SOAP_Calendar"); |
if (isset($_SERVER['QUERY_STRING']) && |
strcasecmp($_SERVER['QUERY_STRING'], 'wsdl')==0) { |
header("Content-type: text/xml"); |
echo $disco->getWSDL(); |
} else { |
echo 'This is a PEAR::SOAP Calendar Server. For client try <a href="8.php">here</a><br />'; |
echo 'For WSDL try <a href="?wsdl">here</a>'; |
} |
exit; |
} |
?> |
/branches/v1.3-critias/bibliotheque/pear/Calendar/docs/examples/23.phps |
---|
New file |
0,0 → 1,66 |
<?php |
/** |
* Description: demonstrates using the Textual util |
*/ |
if (!@include 'Calendar'.DIRECTORY_SEPARATOR.'Calendar.php') { |
define('CALENDAR_ROOT', '../../'); |
} |
require_once CALENDAR_ROOT.'Day.php'; |
require_once CALENDAR_ROOT.'Month'.DIRECTORY_SEPARATOR.'Weekdays.php'; |
require_once CALENDAR_ROOT.'Util'.DIRECTORY_SEPARATOR.'Textual.php'; |
// Could change language like this |
// setlocale (LC_TIME, "de_DE"); // Unix based (probably) |
// setlocale (LC_TIME, "ge"); // Windows |
echo "<hr>Calling: Calendar_Util_Textual::monthNames('long');<pre>"; |
print_r(Calendar_Util_Textual::monthNames('long')); |
echo '</pre>'; |
echo "<hr>Calling: Calendar_Util_Textual::weekdayNames('two');<pre>"; |
print_r(Calendar_Util_Textual::weekdayNames('two')); |
echo '</pre>'; |
echo "<hr>Creating: new Calendar_Day(date('Y'), date('n'), date('d'));<br />"; |
$Calendar = new Calendar_Day(date('Y'), date('n'), date('d')); |
echo '<hr>Previous month is: '.Calendar_Util_Textual::prevMonthName($Calendar,'two').'<br />'; |
echo 'This month is: '.Calendar_Util_Textual::thisMonthName($Calendar,'short').'<br />'; |
echo 'Next month is: '.Calendar_Util_Textual::nextMonthName($Calendar).'<br /><hr />'; |
echo 'Previous day is: '.Calendar_Util_Textual::prevDayName($Calendar).'<br />'; |
echo 'This day is: '.Calendar_Util_Textual::thisDayName($Calendar,'short').'<br />'; |
echo 'Next day is: '.Calendar_Util_Textual::nextDayName($Calendar,'one').'<br /><hr />'; |
echo "Creating: new Calendar_Month_Weekdays(date('Y'), date('n'), 6); - Saturday is first day of week<br />"; |
$Calendar = new Calendar_Month_Weekdays(date('Y'), date('n'), 6); |
?> |
<p>Rendering calendar....</p> |
<table> |
<caption><?php echo Calendar_Util_Textual::thisMonthName($Calendar).' '.$Calendar->thisYear(); ?></caption> |
<tr> |
<?php |
$dayheaders = Calendar_Util_Textual::orderedWeekdays($Calendar,'short'); |
foreach ($dayheaders as $dayheader) { |
echo '<th>'.$dayheader.'</th>'; |
} |
?> |
</tr> |
<?php |
$Calendar->build(); |
while ($Day = $Calendar->fetch()) { |
if ($Day->isFirst()) { |
echo "<tr>\n"; |
} |
if ($Day->isEmpty()) { |
echo '<td> </td>'; |
} else { |
echo '<td>'.$Day->thisDay().'</td>'; |
} |
if ($Day->isLast()) { |
echo "</tr>\n"; |
} |
} |
?> |
</table> |
/branches/v1.3-critias/bibliotheque/pear/Calendar/docs/examples/8.php |
---|
New file |
0,0 → 1,70 |
<?php |
/** |
* Description: client for the SOAP Calendar Server |
*/ |
if ( version_compare(phpversion(), "5.0.0", ">") ) { |
die('PHP 5 has problems with PEAR::SOAP Client (8.0RC3) |
- remove @ before include below to see why'); |
} |
if (!@include('SOAP'.DIRECTORY_SEPARATOR.'Client.php')) { |
die('You must have PEAR::SOAP installed'); |
} |
// Just to save manaul modification... |
$basePath = explode('/', $_SERVER['SCRIPT_NAME']); |
array_pop($basePath); |
$basePath = implode('/', $basePath); |
$url = 'http://'.$_SERVER['SERVER_NAME'].$basePath.'/7.php?wsdl'; |
if (!isset($_GET['y'])) $_GET['y'] = date('Y'); |
if (!isset($_GET['m'])) $_GET['m'] = date('n'); |
$wsdl = new SOAP_WSDL ($url); |
echo ( '<pre>'.$wsdl->generateProxyCode().'</pre>' ); |
$calendarClient = $wsdl->getProxy(); |
$month = $calendarClient->getMonth((int)$_GET['y'],(int)$_GET['m']); |
if ( PEAR::isError($month) ) { |
die ( $month->toString() ); |
} |
?> |
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> |
<html> |
<head> |
<title> Calendar over the Wire </title> |
</head> |
<body> |
<h1>Calendar Over the Wire (featuring PEAR::SOAP)</h1> |
<table> |
<caption><b><?php echo ( $month->monthname );?></b></caption> |
<tr> |
<th>M</th><th>T</th><th>W</th><th>T</th><th>F</th><th>S</th><th>S</th> |
</tr> |
<?php |
foreach ( $month->days as $day ) { |
if ( $day->isFirst === 1 ) |
echo ( "<tr>\n" ); |
if ( $day->isEmpty === 1 ) { |
echo ( "<td></td>" ); |
} else { |
echo ( "<td>".$day->day."</td>" ); |
} |
if ( $day->isLast === 1 ) |
echo ( "</tr>\n" ); |
} |
?> |
<tr> |
</table> |
<p>Enter Year and Month to View:</p> |
<form action="<?php echo ( $_SERVER['PHP_SELF'] ); ?>" method="get"> |
Year: <input type="text" size="4" name="y" value="<?php echo ( $_GET['y'] ); ?>"> |
Month: <input type="text" size="2" name="m" value="<?php echo ( $_GET['m'] ); ?>"> |
<input type="submit" value="Fetch Calendar"> |
</form> |
</body> |
</html> |
/branches/v1.3-critias/bibliotheque/pear/Calendar/docs/examples/15.phps |
---|
New file |
0,0 → 1,58 |
<?php |
/** |
* Shows more on how a week can be used |
*/ |
function getmicrotime() { |
list($usec, $sec) = explode(" ", microtime()); |
return ((float)$usec + (float)$sec); |
} |
$start = getmicrotime(); |
if (!@include 'Calendar/Calendar.php') { |
define('CALENDAR_ROOT', '../../'); |
} |
require_once CALENDAR_ROOT.'Week.php'; |
if (!isset($_GET['y'])) $_GET['y'] = date('Y'); |
if (!isset($_GET['m'])) $_GET['m'] = date('m'); |
if (!isset($_GET['d'])) $_GET['d'] = 1; |
// Build the month |
$Week = new Calendar_Week($_GET['y'], $_GET['m'], $_GET['d']); |
/* |
$Validator = $Week->getValidator(); |
if (!$Validator->isValidWeek()) { |
die ('Please enter a valid week!'); |
} |
*/ |
?> |
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> |
<html> |
<head> |
<title> Paging Weeks </title> |
</head> |
<body> |
<h1>Paging Weeks</h1> |
<h2>Week: <?php echo $Week->thisWeek().' '.date('F Y',$Week->thisMonth(true)); ?></h2> |
<?php |
$Week->build(); |
while ($Day = $Week->fetch()) { |
echo '<p>'.date('jS F',$Day->thisDay(true))."</p>\n"; |
} |
$days = $Week->fetchAll(); |
$prevWeek = $Week->prevWeek('array'); |
$prevWeekLink = $_SERVER['PHP_SELF']. |
'?y='.$prevWeek['year']. |
'&m='.$prevWeek['month']. |
'&d='.$prevWeek['day']; |
$nextWeek = $Week->nextWeek('array'); |
$nextWeekLink = $_SERVER['PHP_SELF']. |
'?y='.$nextWeek['year']. |
'&m='.$nextWeek['month']. |
'&d='.$nextWeek['day']; |
?> |
<p><a href="<?php echo $prevWeekLink; ?>"><<</a> | <a href="<?php echo $nextWeekLink; ?>">>></a></p> |
</body> |
</html> |
/branches/v1.3-critias/bibliotheque/pear/Calendar/docs/examples/9.php |
---|
New file |
0,0 → 1,16 |
<?php |
/** |
* Description: simple example on i18N |
*/ |
if ( !@include 'Calendar/Calendar.php' ) { |
define('CALENDAR_ROOT','../../'); |
} |
require_once CALENDAR_ROOT.'Day.php'; |
$Day = & new Calendar_Day(2003,10,23); |
setlocale (LC_TIME, "de_DE"); // Unix based (probably) |
// setlocale (LC_TIME, "ge"); // Windows |
echo ( strftime('%A %d %B %Y',$Day->getTimeStamp())); |
?> |
/branches/v1.3-critias/bibliotheque/pear/Calendar/docs/examples/17.phps |
---|
New file |
0,0 → 1,71 |
<?php |
/** |
* Description: demonstrates using the Textual decorator |
*/ |
if (!@include 'Calendar'.DIRECTORY_SEPARATOR.'Calendar.php') { |
define('CALENDAR_ROOT', '../../'); |
} |
require_once CALENDAR_ROOT.'Day.php'; |
require_once CALENDAR_ROOT.'Month'.DIRECTORY_SEPARATOR.'Weekdays.php'; |
require_once CALENDAR_ROOT.'Decorator'.DIRECTORY_SEPARATOR.'Textual.php'; |
// Could change language like this |
// setlocale (LC_TIME, "de_DE"); // Unix based (probably) |
// setlocale (LC_TIME, "ge"); // Windows |
echo "<hr>Calling: Calendar_Decorator_Textual::monthNames('long');<pre>"; |
print_r(Calendar_Decorator_Textual::monthNames('long')); |
echo '</pre>'; |
echo "<hr>Calling: Calendar_Decorator_Textual::weekdayNames('two');<pre>"; |
print_r(Calendar_Decorator_Textual::weekdayNames('two')); |
echo '</pre>'; |
echo "<hr>Creating: new Calendar_Day(date('Y'), date('n'), date('d'));<br />"; |
$Calendar = new Calendar_Day(date('Y'), date('n'), date('d')); |
// Decorate |
$Textual = & new Calendar_Decorator_Textual($Calendar); |
echo '<hr>Previous month is: '.$Textual->prevMonthName('two').'<br />'; |
echo 'This month is: '.$Textual->thisMonthName('short').'<br />'; |
echo 'Next month is: '.$Textual->nextMonthName().'<br /><hr />'; |
echo 'Previous day is: '.$Textual->prevDayName().'<br />'; |
echo 'This day is: '.$Textual->thisDayName('short').'<br />'; |
echo 'Next day is: '.$Textual->nextDayName('one').'<br /><hr />'; |
echo "Creating: new Calendar_Month_Weekdays(date('Y'), date('n'), 6); - Saturday is first day of week<br />"; |
$Calendar = new Calendar_Month_Weekdays(date('Y'), date('n'), 6); |
// Decorate |
$Textual = & new Calendar_Decorator_Textual($Calendar); |
?> |
<p>Rendering calendar....</p> |
<table> |
<caption><?php echo $Textual->thisMonthName().' '.$Textual->thisYear(); ?></caption> |
<tr> |
<?php |
$dayheaders = $Textual->orderedWeekdays('short'); |
foreach ($dayheaders as $dayheader) { |
echo '<th>'.$dayheader.'</th>'; |
} |
?> |
</tr> |
<?php |
$Calendar->build(); |
while ($Day = $Calendar->fetch()) { |
if ($Day->isFirst()) { |
echo "<tr>\n"; |
} |
if ($Day->isEmpty()) { |
echo '<td> </td>'; |
} else { |
echo '<td>'.$Day->thisDay().'</td>'; |
} |
if ($Day->isLast()) { |
echo "</tr>\n"; |
} |
} |
?> |
</table> |
/branches/v1.3-critias/bibliotheque/pear/Calendar/docs/examples/19.phps |
---|
New file |
0,0 → 1,24 |
<?php |
/** |
* Description: demonstrates using the Weekday decorator |
*/ |
if (!@include 'Calendar'.DIRECTORY_SEPARATOR.'Calendar.php') { |
define('CALENDAR_ROOT', '../../'); |
} |
require_once CALENDAR_ROOT.'Day.php'; |
require_once CALENDAR_ROOT.'Decorator/Weekday.php'; |
$Day = new Calendar_Day(date('Y'), date('n'),date('d')); |
$WeekDay = & new Calendar_Decorator_Weekday($Day); |
// $WeekDay->setFirstDay(0); // Make Sunday first Day |
echo 'Yesterday: '.$WeekDay->prevWeekDay().'<br>'; |
echo 'Today: '.$WeekDay->thisWeekDay().'<br>'; |
echo 'Tomorrow: '.$WeekDay->nextWeekDay().'<br>'; |
$WeekDay->build(); |
echo 'Hours today:<br>'; |
while ( $Hour = $WeekDay->fetch() ) { |
echo $Hour->thisHour().'<br>'; |
} |
?> |
/branches/v1.3-critias/bibliotheque/pear/Calendar/docs/examples/20.php |
---|
New file |
0,0 → 1,240 |
<?php |
/** |
* Description: demonstrates a decorator used to "attach a payload" to a selection |
* to make it available when iterating over calendar children |
*/ |
//if you use ISO-8601 dates, switch to PearDate engine |
define('CALENDAR_ENGINE', 'PearDate'); |
if ( !@include 'Calendar/Calendar.php' ) { |
define('CALENDAR_ROOT','../../'); |
} |
require_once CALENDAR_ROOT . 'Month/Weekdays.php'; |
require_once CALENDAR_ROOT . 'Day.php'; |
require_once CALENDAR_ROOT . 'Decorator.php'; |
// accepts multiple entries |
class DiaryEvent extends Calendar_Decorator |
{ |
var $entries = array(); |
function DiaryEvent($calendar) { |
Calendar_Decorator::Calendar_Decorator($calendar); |
} |
function addEntry($entry) { |
$this->entries[] = $entry; |
} |
function getEntry() { |
$entry = each($this->entries); |
if ($entry) { |
return $entry['value']; |
} else { |
reset($this->entries); |
return false; |
} |
} |
} |
class MonthPayload_Decorator extends Calendar_Decorator |
{ |
//Calendar engine |
var $cE; |
var $tableHelper; |
var $year; |
var $month; |
var $firstDay = false; |
function build($events=array()) |
{ |
require_once CALENDAR_ROOT . 'Day.php'; |
require_once CALENDAR_ROOT . 'Table/Helper.php'; |
$this->tableHelper = & new Calendar_Table_Helper($this, $this->firstDay); |
$this->cE = & $this->getEngine(); |
$this->year = $this->thisYear(); |
$this->month = $this->thisMonth(); |
$daysInMonth = $this->cE->getDaysInMonth($this->year, $this->month); |
for ($i=1; $i<=$daysInMonth; $i++) { |
$Day = new Calendar_Day(2000,1,1); // Create Day with dummy values |
$Day->setTimeStamp($this->cE->dateToStamp($this->year, $this->month, $i)); |
$this->children[$i] = new DiaryEvent($Day); |
} |
if (count($events) > 0) { |
$this->setSelection($events); |
} |
Calendar_Month_Weekdays::buildEmptyDaysBefore(); |
Calendar_Month_Weekdays::shiftDays(); |
Calendar_Month_Weekdays::buildEmptyDaysAfter(); |
Calendar_Month_Weekdays::setWeekMarkers(); |
return true; |
} |
function setSelection($events) |
{ |
$daysInMonth = $this->cE->getDaysInMonth($this->year, $this->month); |
for ($i=1; $i<=$daysInMonth; $i++) { |
$stamp1 = $this->cE->dateToStamp($this->year, $this->month, $i); |
$stamp2 = $this->cE->dateToStamp($this->year, $this->month, $i+1); |
foreach ($events as $event) { |
if (($stamp1 >= $event['start'] && $stamp1 < $event['end']) || |
($stamp2 >= $event['start'] && $stamp2 < $event['end']) || |
($stamp1 <= $event['start'] && $stamp2 > $event['end']) |
) { |
$this->children[$i]->addEntry($event); |
$this->children[$i]->setSelected(); |
} |
} |
} |
} |
function fetch() |
{ |
$child = each($this->children); |
if ($child) { |
return $child['value']; |
} else { |
reset($this->children); |
return false; |
} |
} |
} |
// Calendar instance used to get the dates in the preferred format: |
// you can switch Calendar Engine and the example still works |
$cal = new Calendar; |
$events = array(); |
//add some events |
$events[] = array( |
'start' => $cal->cE->dateToStamp(2004, 6, 1, 10), |
'end' => $cal->cE->dateToStamp(2004, 6, 1, 12), |
'desc' => 'Important meeting' |
); |
$events[] = array( |
'start' => $cal->cE->dateToStamp(2004, 6, 1, 21), |
'end' => $cal->cE->dateToStamp(2004, 6, 1, 23, 59), |
'desc' => 'Dinner with the boss' |
); |
$events[] = array( |
'start' => $cal->cE->dateToStamp(2004, 6, 5), |
'end' => $cal->cE->dateToStamp(2004, 6, 10, 23, 59), |
'desc' => 'Holidays!' |
); |
$Month = & new Calendar_Month_Weekdays(2004, 6); |
$MonthDecorator = new MonthPayload_Decorator($Month); |
$MonthDecorator->build($events); |
?> |
<!doctype html public "-//W3C//DTD HTML 4.0 Transitional//EN"> |
<html> |
<head> |
<title> Calendar </title> |
<style text="text/css"> |
table { |
border-collapse: collapse; |
} |
caption { |
font-family: verdana; |
font-size: 14pt; |
padding-bottom: 4pt; |
} |
th { |
font-family: verdana; |
font-size: 11px; |
text-align: center; |
background-color: #e7e3e7; |
padding: 5pt; |
line-height: 150%; |
border: 1px solid #ccc; |
} |
td { |
font-family: verdana; |
font-size: 11px; |
text-align: left; |
vertical-align: top; |
} |
td.calCell { |
border: 1px solid #b5bece; |
padding: 3px; |
} |
td.calCellEmpty { |
background-color: #f3f3f7; |
} |
td.calCellBusy { |
background-color: #efeffa; |
} |
div.dayNumber { |
text-align: right; |
background-color: #f8f8f8; |
border-bottom: 1px solid #ccc; |
} |
ul { |
margin-left: 0; |
margin-top: 5pt; |
padding: 0 10pt 0 12pt; |
list-style-type: square; |
} |
</style> |
</head> |
<body> |
<h2>Sample Calendar Payload Decorator (using <?php echo CALENDAR_ENGINE; ?> engine)</h2> |
<table class="calendar" width="98%" cellspacing="0" cellpadding="0"> |
<caption> |
<?php echo $MonthDecorator->thisMonth().' / '.$MonthDecorator->thisYear(); ?> |
</caption> |
<tr> |
<th>Monday</th> |
<th>Tuesday</th> |
<th>Wednesday</th> |
<th>Thursday</th> |
<th>Friday</th> |
<th>Saturday</th> |
<th>Sunday</th> |
</tr> |
<?php |
while ($Day = $MonthDecorator->fetch()) { |
if ($Day->isFirst()) { |
echo "<tr>\n"; |
} |
echo '<td class="calCell'; |
if ($Day->isSelected()) { |
echo ' calCellBusy'; |
} elseif ($Day->isEmpty()) { |
echo ' calCellEmpty'; |
} |
echo '">'; |
echo '<div class="dayNumber">'.$Day->thisDay().'</div>'; |
if ($Day->isEmpty()) { |
echo ' '; |
} else { |
echo '<div class="dayContents"><ul>'; |
while ($entry = $Day->getEntry()) { |
echo '<li>'.$entry['desc'].'</li>'; |
//you can print the time range as well |
} |
echo '</ul></div>'; |
} |
echo '</td>'; |
if ($Day->isLast()) { |
echo "</tr>\n"; |
} |
} |
?> |
</table> |
</body> |
</html> |
/branches/v1.3-critias/bibliotheque/pear/Calendar/docs/examples/21.php |
---|
New file |
0,0 → 1,139 |
<?php |
/** |
* Description: a complete year with numeric week numbers |
*/ |
function getmicrotime(){ |
list($usec, $sec) = explode(" ",microtime()); |
return ((float)$usec + (float)$sec); |
} |
$start = getmicrotime(); |
if (!@include 'Calendar/Calendar.php') { |
define('CALENDAR_ROOT', '../../'); |
} |
require_once CALENDAR_ROOT.'Year.php'; |
require_once CALENDAR_ROOT.'Month/Weeks.php'; |
define ('CALENDAR_MONTH_STATE',CALENDAR_USE_MONTH_WEEKS); |
if (!isset($_GET['year'])) $_GET['year'] = date('Y'); |
$week_types = array( |
'n_in_year', |
'n_in_month', |
); |
if (!isset($_GET['week_type']) || !in_array($_GET['week_type'],$week_types) ) { |
$_GET['week_type'] = 'n_in_year'; |
} |
$Year = new Calendar_Year($_GET['year']); |
$Year->build(); |
?> |
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> |
<html> |
<head> |
<title> <?php echo $Year->thisYear(); ?> </title> |
<style type="text/css"> |
body { |
font-family: Georgia, serif; |
} |
caption.year { |
font-weight: bold; |
font-size: 120%; |
font-color: navy; |
} |
caption.month { |
font-size: 110%; |
font-color: navy; |
} |
table.month { |
border: thin groove #800080 |
} |
tr { |
vertical-align: top; |
} |
th, td { |
text-align: right; |
font-size: 70%; |
} |
#prev { |
float: left; |
font-size: 70%; |
} |
#next { |
float: right; |
font-size: 70%; |
} |
#week_type { |
float: none; |
font-size: 70%; |
} |
.weekNumbers { |
background-color: #e5e5f5; |
padding-right: 3pt; |
} |
</style> |
</head> |
<body> |
<table> |
<caption class="year"> |
<?php echo $Year->thisYear(); ?> |
<div id="next"> |
<a href="?year=<?php echo $Year->nextYear(); ?>&week_type=<?php echo $_GET['week_type']; ?>">>></a> |
</div> |
<div id="prev"> |
<a href="?year=<?php echo $Year->prevYear(); ?>&week_type=<?php echo $_GET['week_type']; ?>"><<</a> |
</div> |
<div id="week_type"> |
<a href="?year=<?php echo $Year->thisYear(); ?>&week_type=n_in_year">Weeks by Year</a> : |
<a href="?year=<?php echo $Year->thisYear(); ?>&week_type=n_in_month">Weeks by Month</a> |
</div> |
</caption> |
<?php |
$i = 0; |
while ($Month = $Year->fetch()) { |
switch ($i) { |
case 0: |
echo "<tr>\n"; |
break; |
case 3: |
case 6: |
case 9: |
echo "</tr>\n<tr>\n"; |
break; |
case 12: |
echo "</tr>\n"; |
break; |
} |
echo "<td>\n<table class=\"month\">\n"; |
echo '<caption class="month">'.date('F', $Month->thisMonth(TRUE)).'</caption>'; |
echo '<colgroup><col class="weekNumbers"><col span="7"></colgroup>'."\n"; |
echo "<tr>\n<th>Week</th><th>M</th><th>T</th><th>W</th><th>T</th><th>F</th><th>S</th><th>S</th>\n</tr>"; |
$Month->build(); |
while ($Week = $Month->fetch()) { |
echo "<tr>\n"; |
echo '<td>'.$Week->thisWeek($_GET['week_type'])."</td>\n"; |
$Week->build(); |
while ($Day = $Week->fetch()) { |
if ($Day->isEmpty()) { |
echo "<td> </td>\n"; |
} else { |
echo "<td>".$Day->thisDay()."</td>\n"; |
} |
} |
} |
echo "</table>\n</td>\n"; |
$i++; |
} |
?> |
</table> |
<p>Took: <?php echo ((getmicrotime()-$start)); ?></p> |
</body> |
</html> |
/branches/v1.3-critias/bibliotheque/pear/Calendar/docs/examples/22.php |
---|
New file |
0,0 → 1,46 |
<?php |
/** |
* Description: demonstrates using the Uri util |
*/ |
if (!@include 'Calendar/Calendar.php') { |
define('CALENDAR_ROOT', '../../'); |
} |
require_once CALENDAR_ROOT.'Month/Weekdays.php'; |
require_once CALENDAR_ROOT.'Util/Uri.php'; |
if (!isset($_GET['jahr'])) $_GET['jahr'] = date('Y'); |
if (!isset($_GET['monat'])) $_GET['monat'] = date('m'); |
// Build the month |
$Calendar = new Calendar_Month_Weekdays($_GET['jahr'], $_GET['monat']); |
echo ( '<p>The current month is ' |
.$Calendar->thisMonth().' of year '.$Calendar->thisYear().'</p>'); |
$Uri = & new Calendar_Util_Uri('jahr','monat'); |
$Uri->setFragments('jahr','monat'); |
echo "\"Vector\" URIs<pre>"; |
echo ( "Previous Uri:\t".htmlentities($Uri->prev($Calendar, 'month'))."\n" ); |
echo ( "This Uri:\t".htmlentities($Uri->this($Calendar, 'month'))."\n" ); |
echo ( "Next Uri:\t".htmlentities($Uri->next($Calendar, 'month'))."\n" ); |
echo "</pre>"; |
// Switch to scalar URIs |
$Uri->separator = '/'; // Default is & |
$Uri->scalar = true; // Omit variable names |
echo "\"Scalar\" URIs<pre>"; |
echo ( "Previous Uri:\t".$Uri->prev($Calendar, 'month')."\n" ); |
echo ( "This Uri:\t".$Uri->this($Calendar, 'month')."\n" ); |
echo ( "Next Uri:\t".$Uri->next($Calendar, 'month')."\n" ); |
echo "</pre>"; |
// Restore the vector URIs |
$Uri->separator = '&'; |
$Uri->scalar = false; |
?> |
<p> |
<a href="<?php echo($_SERVER['PHP_SELF'].'?'.$Uri->prev($Calendar, 'month'));?>">Prev</a> : |
<a href="<?php echo($_SERVER['PHP_SELF'].'?'.$Uri->next($Calendar, 'month'));?>">Next</a> |
</p> |
/branches/v1.3-critias/bibliotheque/pear/Calendar/docs/examples/23.php |
---|
New file |
0,0 → 1,66 |
<?php |
/** |
* Description: demonstrates using the Textual util |
*/ |
if (!@include 'Calendar'.DIRECTORY_SEPARATOR.'Calendar.php') { |
define('CALENDAR_ROOT', '../../'); |
} |
require_once CALENDAR_ROOT.'Day.php'; |
require_once CALENDAR_ROOT.'Month'.DIRECTORY_SEPARATOR.'Weekdays.php'; |
require_once CALENDAR_ROOT.'Util'.DIRECTORY_SEPARATOR.'Textual.php'; |
// Could change language like this |
// setlocale (LC_TIME, "de_DE"); // Unix based (probably) |
// setlocale (LC_TIME, "ge"); // Windows |
echo "<hr>Calling: Calendar_Util_Textual::monthNames('long');<pre>"; |
print_r(Calendar_Util_Textual::monthNames('long')); |
echo '</pre>'; |
echo "<hr>Calling: Calendar_Util_Textual::weekdayNames('two');<pre>"; |
print_r(Calendar_Util_Textual::weekdayNames('two')); |
echo '</pre>'; |
echo "<hr>Creating: new Calendar_Day(date('Y'), date('n'), date('d'));<br />"; |
$Calendar = new Calendar_Day(date('Y'), date('n'), date('d')); |
echo '<hr>Previous month is: '.Calendar_Util_Textual::prevMonthName($Calendar,'two').'<br />'; |
echo 'This month is: '.Calendar_Util_Textual::thisMonthName($Calendar,'short').'<br />'; |
echo 'Next month is: '.Calendar_Util_Textual::nextMonthName($Calendar).'<br /><hr />'; |
echo 'Previous day is: '.Calendar_Util_Textual::prevDayName($Calendar).'<br />'; |
echo 'This day is: '.Calendar_Util_Textual::thisDayName($Calendar,'short').'<br />'; |
echo 'Next day is: '.Calendar_Util_Textual::nextDayName($Calendar,'one').'<br /><hr />'; |
echo "Creating: new Calendar_Month_Weekdays(date('Y'), date('n'), 6); - Saturday is first day of week<br />"; |
$Calendar = new Calendar_Month_Weekdays(date('Y'), date('n'), 6); |
?> |
<p>Rendering calendar....</p> |
<table> |
<caption><?php echo Calendar_Util_Textual::thisMonthName($Calendar).' '.$Calendar->thisYear(); ?></caption> |
<tr> |
<?php |
$dayheaders = Calendar_Util_Textual::orderedWeekdays($Calendar,'short'); |
foreach ($dayheaders as $dayheader) { |
echo '<th>'.$dayheader.'</th>'; |
} |
?> |
</tr> |
<?php |
$Calendar->build(); |
while ($Day = $Calendar->fetch()) { |
if ($Day->isFirst()) { |
echo "<tr>\n"; |
} |
if ($Day->isEmpty()) { |
echo '<td> </td>'; |
} else { |
echo '<td>'.$Day->thisDay().'</td>'; |
} |
if ($Day->isLast()) { |
echo "</tr>\n"; |
} |
} |
?> |
</table> |
/branches/v1.3-critias/bibliotheque/pear/Calendar/docs/examples/2.phps |
---|
New file |
0,0 → 1,142 |
<?php |
/** |
* Description: Demonstrates building a calendar for a month using the Week class |
* Uses UnixTs engine |
*/ |
function getmicrotime(){ |
list($usec, $sec) = explode(" ",microtime()); |
return ((float)$usec + (float)$sec); |
} |
$start = getmicrotime(); |
// Force UnixTs engine (default setting) |
define('CALENDAR_ENGINE','UnixTS'); |
if (!@include 'Calendar'.DIRECTORY_SEPARATOR.'Calendar.php') { |
define('CALENDAR_ROOT', '../../'); |
} |
require_once CALENDAR_ROOT.'Month/Weeks.php'; |
require_once CALENDAR_ROOT.'Day.php'; |
// Initialize GET variables if not set |
if (!isset($_GET['y'])) $_GET['y'] = date('Y'); |
if (!isset($_GET['m'])) $_GET['m'] = date('m'); |
if (!isset($_GET['d'])) $_GET['d'] = date('d'); |
// Build a month object |
$Month = new Calendar_Month_Weeks($_GET['y'], $_GET['m']); |
// Create an array of days which are "selected" |
// Used for Week::build() below |
$selectedDays = array ( |
new Calendar_Day($_GET['y'],$_GET['m'], $_GET['d']), |
new Calendar_Day($_GET['y'], 12, 25), |
new Calendar_Day(date('Y'), date('m'), date('d')), |
); |
// Instruct month to build Week objects |
$Month->build(); |
// Construct strings for next/previous links |
$PMonth = $Month->prevMonth('object'); // Get previous month as object |
$prev = $_SERVER['PHP_SELF'].'?y='.$PMonth->thisYear().'&m='.$PMonth->thisMonth().'&d='.$PMonth->thisDay(); |
$NMonth = $Month->nextMonth('object'); |
$next = $_SERVER['PHP_SELF'].'?y='.$NMonth->thisYear().'&m='.$NMonth->thisMonth().'&d='.$NMonth->thisDay(); |
?> |
<!doctype html public "-//W3C//DTD HTML 4.0 Transitional//EN"> |
<html> |
<head> |
<title> Calendar </title> |
<style text="text/css"> |
table { |
background-color: silver; |
} |
caption { |
font-family: verdana; |
font-size: 12px; |
background-color: while; |
} |
.prevMonth { |
font-size: 10px; |
text-align: left; |
} |
.nextMonth { |
font-size: 10px; |
text-align: right; |
} |
th { |
font-family: verdana; |
font-size: 11px; |
color: navy; |
text-align: right; |
} |
td { |
font-family: verdana; |
font-size: 11px; |
text-align: right; |
} |
.selected { |
background-color: yellow; |
} |
.empty { |
color: white; |
} |
</style> |
</head> |
<body> |
<h2>Build with Calendar_Month_Weeks::build() then Calendar_Week::build()</h2> |
<table class="calendar"> |
<caption> |
<?php echo date('F Y', $Month->getTimeStamp()); ?> |
</caption> |
<tr> |
<th>M</th> |
<th>T</th> |
<th>W</th> |
<th>T</th> |
<th>F</th> |
<th>S</th> |
<th>S</th> |
</tr> |
<?php |
while ($Week = $Month->fetch()) { |
echo "<tr>\n"; |
// Build the days in the week, passing the selected days |
$Week->build($selectedDays); |
while ($Day = $Week->fetch()) { |
// Build a link string for each day |
$link = $_SERVER['PHP_SELF']. |
'?y='.$Day->thisYear(). |
'&m='.$Day->thisMonth(). |
'&d='.$Day->thisDay(); |
// Check to see if day is selected |
if ($Day->isSelected()) { |
echo '<td class="selected">'.$Day->thisDay().'</td>'."\n"; |
// Check to see if day is empty |
} else if ($Day->isEmpty()) { |
echo '<td class="empty">'.$Day->thisDay().'</td>'."\n"; |
} else { |
echo '<td><a href="'.$link.'">'.$Day->thisDay().'</a></td>'."\n"; |
} |
} |
echo '</tr>'."\n"; |
} |
?> |
<tr> |
<td> |
<a href="<?php echo $prev; ?>" class="prevMonth"><< </a> |
</td> |
<td colspan="5"> </td> |
<td> |
<a href="<?php echo $next; ?>" class="nextMonth"> >></a> |
</td> |
</tr> |
</table> |
<?php |
echo '<p><b>Took: '.(getmicrotime()-$start).' seconds</b></p>'; |
?> |
</body> |
</html> |
/branches/v1.3-critias/bibliotheque/pear/Calendar/docs/examples/4.phps |
---|
New file |
0,0 → 1,49 |
<?php |
/** |
* Description: shows how to perform validation with PEAR::Calendar |
*/ |
function getmicrotime(){ |
list($usec, $sec) = explode(' ', microtime()); |
return ((float)$usec + (float)$sec); |
} |
$start = getmicrotime(); |
if ( !@include 'Calendar/Calendar.php' ) { |
define('CALENDAR_ROOT', '../../'); |
} |
require_once CALENDAR_ROOT.'Second.php'; |
if (!isset($_GET['y'])) $_GET['y'] = date('Y'); |
if (!isset($_GET['m'])) $_GET['m'] = date('n'); |
if (!isset($_GET['d'])) $_GET['d'] = date('j'); |
if (!isset($_GET['h'])) $_GET['h'] = date('H'); |
if (!isset($_GET['i'])) $_GET['i'] = date('i'); |
if (!isset($_GET['s'])) $_GET['s'] = date('s'); |
$Unit = & new Calendar_Second($_GET['y'], $_GET['m'], $_GET['d'], $_GET['h'], $_GET['i'], $_GET['s']); |
echo '<p><b>Result:</b> '.$Unit->thisYear().'-'.$Unit->thisMonth().'-'.$Unit->thisDay(). |
' '.$Unit->thisHour().':'.$Unit->thisMinute().':'.$Unit->thisSecond(); |
if ($Unit->isValid()) { |
echo ' is valid!</p>'; |
} else { |
$V= & $Unit->getValidator(); |
echo ' is invalid:</p>'; |
while ($error = $V->fetch()) { |
echo $error->toString() .'<br />'; |
} |
} |
?> |
<p>Enter a date / time to validate:</p> |
<form action="<?php echo $_SERVER['PHP_SELF']; ?>" method="get"> |
Year: <input type="text" name="y" value="2039"><br /> |
Month: <input type="text" name="m" value="13"><br /> |
Day: <input type="text" name="d" value="32"><br /> |
Hour: <input type="text" name="h" value="24"><br /> |
Minute: <input type="text" name="i" value="-1"><br /> |
Second: <input type="text" name="s" value="60"><br /> |
<input type="submit" value="Validate"> |
</form> |
<p><b>Note:</b> Error messages can be controlled with the constants <code>CALENDAR_VALUE_TOOSMALL</code> and <code>CALENDAR_VALUE_TOOLARGE</code> - see <code>Calendar_Validator.php</code></p> |
<?php echo '<p><b>Took: '.(getmicrotime()-$start).' seconds</b></p>'; ?> |
/branches/v1.3-critias/bibliotheque/pear/Calendar/docs/examples/6.phps |
---|
New file |
0,0 → 1,210 |
<?php |
/** |
* Description: A "personal planner" with some WML for fun |
* Note this is done the stupid way - a giant if/else for WML or HTML |
* could be greatly simplified with some HTML/WML rendering classes... |
*/ |
function getmicrotime(){ |
list($usec, $sec) = explode(" ",microtime()); |
return ((float)$usec + (float)$sec); |
} |
$start = getmicrotime(); |
if ( !@include 'Calendar/Calendar.php' ) { |
define('CALENDAR_ROOT','../../'); |
} |
require_once CALENDAR_ROOT.'Month/Weekdays.php'; |
require_once CALENDAR_ROOT.'Day.php'; |
if (!isset($_GET['y'])) $_GET['y'] = date('Y'); |
if (!isset($_GET['m'])) $_GET['m'] = date('n'); |
if (!isset($_GET['d'])) $_GET['d'] = date('j'); |
$Month = & new Calendar_Month_Weekdays($_GET['y'],$_GET['m']); |
$Day = & new Calendar_Day($_GET['y'],$_GET['m'],$_GET['d']); |
$selection = array($Day); |
#-----------------------------------------------------------------------------# |
if ( isset($_GET['mime']) && $_GET['mime']=='wml' ) { |
header ('Content-Type: text/vnd.wap.wml'); |
echo ( '<?xml version="1.0"?>' ); |
?> |
<!DOCTYPE wml PUBLIC "-//WAPFORUM//DTD WML 1.1//EN" "http://www.wapforum.org/DTD/wml_1.1.xml"> |
<wml> |
<big><strong>Personal Planner Rendered with WML</strong></big> |
<?php |
if ( isset($_GET['viewday']) ) { |
?> |
<p><strong>Viewing <?php echo ( date('l, jS of F, Y',$Day->getTimeStamp()) ); ?></strong></p> |
<p> |
<anchor> |
Back to Month View |
<go href="<?php |
echo ( "?y=".$Day->thisYear()."&m=". |
$Day->thisMonth()."&d=".$Day->thisDay()."&mime=wml" ); |
?>"/> |
</anchor> |
</p> |
<table> |
<?php |
$Day->build(); |
while ( $Hour = & $Day->fetch() ) { |
echo ( "<tr>\n" ); |
echo ( "<td>".date('g a',$Hour->getTimeStamp())."</td><td>Free time!</td>\n" ); |
echo ( "</tr>\n" ); |
} |
?> |
</table> |
<?php |
} else { |
?> |
<p><strong><?php echo ( date('F Y',$Month->getTimeStamp()) ); ?></strong></p> |
<table> |
<tr> |
<td>M</td><td>T</td><td>W</td><td>T</td><td>F</td><td>S</td><td>S</td> |
</tr> |
<?php |
$Month->build($selection); |
while ( $Day = $Month->fetch() ) { |
if ( $Day->isFirst() ) { |
echo ( "<tr>\n" ); |
} |
if ( $Day->isEmpty() ) { |
echo ( "<td></td>\n" ); |
} else if ( $Day->isSelected() ) { |
echo ( "<td><anchor><strong><u>".$Day->thisDay()."</u></strong>\n<go href=\"".$_SERVER['PHP_SELF']."?viewday=true&y=". |
$Day->thisYear()."&m=".$Day->thisMonth()."&d=".$Day->thisDay(). |
"&mime=wml\" />\n</anchor></td>\n" ); |
} else { |
echo ( "<td><anchor>".$Day->thisDay()."\n<go href=\"?viewday=true&y=". |
$Day->thisYear()."&m=".$Day->thisMonth()."&d=".$Day->thisDay(). |
"&mime=wml\" /></anchor></td>\n" ); |
} |
if ( $Day->isLast() ) { |
echo ( "</tr>\n" ); |
} |
} |
?> |
<tr> |
<td> |
<anchor> |
<< |
<go href="<?php |
echo ( "?y=".$Month->thisYear()."&m=". |
$Month->prevMonth()."&d=".$Month->thisDay()."&mime=wml" ); |
?>"/> |
</anchor> |
</td> |
<td></td><td></td><td></td><td></td><td></td> |
<td> |
<anchor> |
>> |
<go href="<?php |
echo ( "?y=".$Month->thisYear()."&m=". |
$Month->nextMonth()."&d=".$Month->thisDay()."&mime=wml" ); |
?>"/> |
</anchor> |
</td> |
</tr> |
</table> |
<?php |
} |
?> |
<p><a href="<?php echo ( $_SERVER['PHP_SELF'] ); ?>">Back to HTML</a></p> |
<?php echo ( '<p>Took: '.(getmicrotime()-$start).' seconds</p>' ); ?> |
</wml> |
<?php |
#-----------------------------------------------------------------------------# |
} else { |
?> |
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> |
<html> |
<head> |
<title> HTML (+WML) Personal Planner </title> |
</head> |
<body> |
<h1>Personal Planner Rendered with HTML</h1> |
<p>To view in WML, click <a href="<?php echo ( $_SERVER['PHP_SELF'] ); ?>?mime=wml">here</a> or place a ?mime=wml at the end of any URL. |
Note that <a href="http://www.opera.com/download">Opera</a> supports WML natively and Mozilla / Firefox has the WMLBrowser |
plugin: <a href="http://wmlbrowser.mozdev.org">wmlbrowser.mozdev.org</a></p> |
<?php |
if ( isset($_GET['viewday']) ) { |
?> |
<p><strong>Viewing <?php echo ( date('l, jS of F, Y',$Day->getTimeStamp()) ); ?></strong></p> |
<p> |
<anchor> |
<a href="<?php |
echo ( "?y=".$Day->thisYear()."&m=". |
$Day->thisMonth()."&d=".$Day->thisDay()); |
?>">Back to Month View</a> |
</p> |
<table> |
<?php |
$Day->build(); |
while ( $Hour = & $Day->fetch() ) { |
echo ( "<tr>\n" ); |
echo ( "<td>".date('g a',$Hour->getTimeStamp())."</td><td>Free time!</td>\n" ); |
echo ( "</tr>\n" ); |
} |
?> |
</table> |
<?php |
} else { |
?> |
<p><strong><?php echo ( date('F Y',$Month->getTimeStamp()) ); ?></strong></p> |
<table> |
<tr> |
<td>M</td><td>T</td><td>W</td><td>T</td><td>F</td><td>S</td><td>S</td> |
</tr> |
<?php |
$Month->build($selection); |
while ( $Day = $Month->fetch() ) { |
if ( $Day->isFirst() ) { |
echo ( "<tr>\n" ); |
} |
if ( $Day->isEmpty() ) { |
echo ( "<td></td>\n" ); |
} else if ( $Day->isSelected() ) { |
echo ( "<td><a href=\"".$_SERVER['PHP_SELF']."?viewday=true&y=". |
$Day->thisYear()."&m=".$Day->thisMonth()."&d=".$Day->thisDay(). |
"&wml\"><strong><u>".$Day->thisDay()."</u></strong></a></td>\n" ); |
} else { |
echo ( "<td><a href=\"".$_SERVER['PHP_SELF']."?viewday=true&y=". |
$Day->thisYear()."&m=".$Day->thisMonth()."&d=".$Day->thisDay(). |
"\">".$Day->thisDay()."</a></td>\n" ); |
} |
if ( $Day->isLast() ) { |
echo ( "</tr>\n" ); |
} |
} |
?> |
<tr> |
<td> |
<a href="<?php |
echo ( "?y=".$Month->thisYear()."&m=". |
$Month->prevMonth()."&d=".$Month->thisDay() ); |
?>"> |
<<</a> |
</td> |
<td></td><td></td><td></td><td></td><td></td> |
<td> |
<a href="<?php |
echo ( "?y=".$Month->thisYear()."&m=". |
$Month->nextMonth()."&d=".$Month->thisDay() ); |
?>">>></a> |
</td> |
</tr> |
</table> |
<?php |
} |
?> |
<?php echo ( '<p><b>Took: '.(getmicrotime()-$start).' seconds</b></p>' ); ?> |
</body> |
</html> |
<?php |
} |
?> |
/branches/v1.3-critias/bibliotheque/pear/Calendar/docs/examples/8.phps |
---|
New file |
0,0 → 1,70 |
<?php |
/** |
* Description: client for the SOAP Calendar Server |
*/ |
if ( version_compare(phpversion(), "5.0.0", ">") ) { |
die('PHP 5 has problems with PEAR::SOAP Client (8.0RC3) |
- remove @ before include below to see why'); |
} |
if (!@include('SOAP'.DIRECTORY_SEPARATOR.'Client.php')) { |
die('You must have PEAR::SOAP installed'); |
} |
// Just to save manaul modification... |
$basePath = explode('/', $_SERVER['SCRIPT_NAME']); |
array_pop($basePath); |
$basePath = implode('/', $basePath); |
$url = 'http://'.$_SERVER['SERVER_NAME'].$basePath.'/7.php?wsdl'; |
if (!isset($_GET['y'])) $_GET['y'] = date('Y'); |
if (!isset($_GET['m'])) $_GET['m'] = date('n'); |
$wsdl = new SOAP_WSDL ($url); |
echo ( '<pre>'.$wsdl->generateProxyCode().'</pre>' ); |
$calendarClient = $wsdl->getProxy(); |
$month = $calendarClient->getMonth((int)$_GET['y'],(int)$_GET['m']); |
if ( PEAR::isError($month) ) { |
die ( $month->toString() ); |
} |
?> |
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> |
<html> |
<head> |
<title> Calendar over the Wire </title> |
</head> |
<body> |
<h1>Calendar Over the Wire (featuring PEAR::SOAP)</h1> |
<table> |
<caption><b><?php echo ( $month->monthname );?></b></caption> |
<tr> |
<th>M</th><th>T</th><th>W</th><th>T</th><th>F</th><th>S</th><th>S</th> |
</tr> |
<?php |
foreach ( $month->days as $day ) { |
if ( $day->isFirst === 1 ) |
echo ( "<tr>\n" ); |
if ( $day->isEmpty === 1 ) { |
echo ( "<td></td>" ); |
} else { |
echo ( "<td>".$day->day."</td>" ); |
} |
if ( $day->isLast === 1 ) |
echo ( "</tr>\n" ); |
} |
?> |
<tr> |
</table> |
<p>Enter Year and Month to View:</p> |
<form action="<?php echo ( $_SERVER['PHP_SELF'] ); ?>" method="get"> |
Year: <input type="text" size="4" name="y" value="<?php echo ( $_GET['y'] ); ?>"> |
Month: <input type="text" size="2" name="m" value="<?php echo ( $_GET['m'] ); ?>"> |
<input type="submit" value="Fetch Calendar"> |
</form> |
</body> |
</html> |
/branches/v1.3-critias/bibliotheque/pear/Calendar/docs/examples/10.phps |
---|
New file |
0,0 → 1,93 |
<?php |
/** |
* Description: demonstrates a decorator to provide simple output formatting |
* on the month while still allowing the days to be accessed via the decorator |
* In practice you _wouldn't_ do this - each decorator comes with a performance |
* hit for extra method calls. For this example some simple functions could help |
* format the month while the days are accessed via the normal Month object |
*/ |
if ( !@include 'Calendar/Calendar.php' ) { |
define('CALENDAR_ROOT','../../'); |
} |
require_once CALENDAR_ROOT.'Month/Weekdays.php'; |
require_once CALENDAR_ROOT.'Decorator.php'; |
// Decorate a Month with methods to improve formatting |
class MonthDecorator extends Calendar_Decorator { |
/** |
* @param Calendar_Month |
*/ |
function MonthDecorator(& $Month) { |
parent::Calendar_Decorator($Month); |
} |
/** |
* Override the prevMonth method to format the output |
*/ |
function prevMonth() { |
$prevStamp = parent::prevMonth(TRUE); |
// Build the URL for the previous month |
return $_SERVER['PHP_SELF'].'?y='.date('Y',$prevStamp). |
'&m='.date('n',$prevStamp).'&d='.date('j',$prevStamp); |
} |
/** |
* Override the thisMonth method to format the output |
*/ |
function thisMonth() { |
$thisStamp = parent::thisMonth(TRUE); |
// A human readable string from this month |
return date('F Y',$thisStamp); |
} |
/** |
* Override the nextMonth method to format the output |
*/ |
function nextMonth() { |
$nextStamp = parent::nextMonth(TRUE); |
// Build the URL for next month |
return $_SERVER['PHP_SELF'].'?y='.date('Y',$nextStamp). |
'&m='.date('n',$nextStamp).'&d='.date('j',$nextStamp); |
} |
} |
if (!isset($_GET['y'])) $_GET['y'] = date('Y'); |
if (!isset($_GET['m'])) $_GET['m'] = date('n'); |
// Creata a month as usual |
$Month = new Calendar_Month_Weekdays($_GET['y'],$_GET['m']); |
// Pass it to the decorator and use the decorator from now on... |
$MonthDecorator = new MonthDecorator($Month); |
$MonthDecorator->build(); |
?> |
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> |
<html> |
<head> |
<title> A Simple Decorator </title> |
</head> |
<body> |
<h1>A Simple Decorator</h1> |
<table> |
<caption><?php echo ( $MonthDecorator->thisMonth() ); ?></caption> |
<?php |
while ( $Day = $MonthDecorator->fetch() ) { |
if ( $Day->isFirst() ) { |
echo ( "\n<tr>\n" ); |
} |
if ( $Day->isEmpty() ) { |
echo ( "<td> </td>" ); |
} else { |
echo ( "<td>".$Day->thisDay()."</td>" ); |
} |
if ( $Day->isLast() ) { |
echo ( "\n</tr>\n" ); |
} |
} |
?> |
<tr> |
<td><a href="<?php echo ($MonthDecorator->prevMonth()); ?>">Prev</a></td> |
<td colspan="5"> </td> |
<td><a href="<?php echo ($MonthDecorator->nextMonth()); ?>">Next</a></td> |
</tr> |
</table> |
</body> |
</html> |
/branches/v1.3-critias/bibliotheque/pear/Calendar/docs/examples/20.phps |
---|
New file |
0,0 → 1,240 |
<?php |
/** |
* Description: demonstrates a decorator used to "attach a payload" to a selection |
* to make it available when iterating over calendar children |
*/ |
//if you use ISO-8601 dates, switch to PearDate engine |
define('CALENDAR_ENGINE', 'PearDate'); |
if ( !@include 'Calendar/Calendar.php' ) { |
define('CALENDAR_ROOT','../../'); |
} |
require_once CALENDAR_ROOT . 'Month/Weekdays.php'; |
require_once CALENDAR_ROOT . 'Day.php'; |
require_once CALENDAR_ROOT . 'Decorator.php'; |
// accepts multiple entries |
class DiaryEvent extends Calendar_Decorator |
{ |
var $entries = array(); |
function DiaryEvent($calendar) { |
Calendar_Decorator::Calendar_Decorator($calendar); |
} |
function addEntry($entry) { |
$this->entries[] = $entry; |
} |
function getEntry() { |
$entry = each($this->entries); |
if ($entry) { |
return $entry['value']; |
} else { |
reset($this->entries); |
return false; |
} |
} |
} |
class MonthPayload_Decorator extends Calendar_Decorator |
{ |
//Calendar engine |
var $cE; |
var $tableHelper; |
var $year; |
var $month; |
var $firstDay = false; |
function build($events=array()) |
{ |
require_once CALENDAR_ROOT . 'Day.php'; |
require_once CALENDAR_ROOT . 'Table/Helper.php'; |
$this->tableHelper = & new Calendar_Table_Helper($this, $this->firstDay); |
$this->cE = & $this->getEngine(); |
$this->year = $this->thisYear(); |
$this->month = $this->thisMonth(); |
$daysInMonth = $this->cE->getDaysInMonth($this->year, $this->month); |
for ($i=1; $i<=$daysInMonth; $i++) { |
$Day = new Calendar_Day(2000,1,1); // Create Day with dummy values |
$Day->setTimeStamp($this->cE->dateToStamp($this->year, $this->month, $i)); |
$this->children[$i] = new DiaryEvent($Day); |
} |
if (count($events) > 0) { |
$this->setSelection($events); |
} |
Calendar_Month_Weekdays::buildEmptyDaysBefore(); |
Calendar_Month_Weekdays::shiftDays(); |
Calendar_Month_Weekdays::buildEmptyDaysAfter(); |
Calendar_Month_Weekdays::setWeekMarkers(); |
return true; |
} |
function setSelection($events) |
{ |
$daysInMonth = $this->cE->getDaysInMonth($this->year, $this->month); |
for ($i=1; $i<=$daysInMonth; $i++) { |
$stamp1 = $this->cE->dateToStamp($this->year, $this->month, $i); |
$stamp2 = $this->cE->dateToStamp($this->year, $this->month, $i+1); |
foreach ($events as $event) { |
if (($stamp1 >= $event['start'] && $stamp1 < $event['end']) || |
($stamp2 >= $event['start'] && $stamp2 < $event['end']) || |
($stamp1 <= $event['start'] && $stamp2 > $event['end']) |
) { |
$this->children[$i]->addEntry($event); |
$this->children[$i]->setSelected(); |
} |
} |
} |
} |
function fetch() |
{ |
$child = each($this->children); |
if ($child) { |
return $child['value']; |
} else { |
reset($this->children); |
return false; |
} |
} |
} |
// Calendar instance used to get the dates in the preferred format: |
// you can switch Calendar Engine and the example still works |
$cal = new Calendar; |
$events = array(); |
//add some events |
$events[] = array( |
'start' => $cal->cE->dateToStamp(2004, 6, 1, 10), |
'end' => $cal->cE->dateToStamp(2004, 6, 1, 12), |
'desc' => 'Important meeting' |
); |
$events[] = array( |
'start' => $cal->cE->dateToStamp(2004, 6, 1, 21), |
'end' => $cal->cE->dateToStamp(2004, 6, 1, 23, 59), |
'desc' => 'Dinner with the boss' |
); |
$events[] = array( |
'start' => $cal->cE->dateToStamp(2004, 6, 5), |
'end' => $cal->cE->dateToStamp(2004, 6, 10, 23, 59), |
'desc' => 'Holidays!' |
); |
$Month = & new Calendar_Month_Weekdays(2004, 6); |
$MonthDecorator = new MonthPayload_Decorator($Month); |
$MonthDecorator->build($events); |
?> |
<!doctype html public "-//W3C//DTD HTML 4.0 Transitional//EN"> |
<html> |
<head> |
<title> Calendar </title> |
<style text="text/css"> |
table { |
border-collapse: collapse; |
} |
caption { |
font-family: verdana; |
font-size: 14pt; |
padding-bottom: 4pt; |
} |
th { |
font-family: verdana; |
font-size: 11px; |
text-align: center; |
background-color: #e7e3e7; |
padding: 5pt; |
line-height: 150%; |
border: 1px solid #ccc; |
} |
td { |
font-family: verdana; |
font-size: 11px; |
text-align: left; |
vertical-align: top; |
} |
td.calCell { |
border: 1px solid #b5bece; |
padding: 3px; |
} |
td.calCellEmpty { |
background-color: #f3f3f7; |
} |
td.calCellBusy { |
background-color: #efeffa; |
} |
div.dayNumber { |
text-align: right; |
background-color: #f8f8f8; |
border-bottom: 1px solid #ccc; |
} |
ul { |
margin-left: 0; |
margin-top: 5pt; |
padding: 0 10pt 0 12pt; |
list-style-type: square; |
} |
</style> |
</head> |
<body> |
<h2>Sample Calendar Payload Decorator (using <?php echo CALENDAR_ENGINE; ?> engine)</h2> |
<table class="calendar" width="98%" cellspacing="0" cellpadding="0"> |
<caption> |
<?php echo $MonthDecorator->thisMonth().' / '.$MonthDecorator->thisYear(); ?> |
</caption> |
<tr> |
<th>Monday</th> |
<th>Tuesday</th> |
<th>Wednesday</th> |
<th>Thursday</th> |
<th>Friday</th> |
<th>Saturday</th> |
<th>Sunday</th> |
</tr> |
<?php |
while ($Day = $MonthDecorator->fetch()) { |
if ($Day->isFirst()) { |
echo "<tr>\n"; |
} |
echo '<td class="calCell'; |
if ($Day->isSelected()) { |
echo ' calCellBusy'; |
} elseif ($Day->isEmpty()) { |
echo ' calCellEmpty'; |
} |
echo '">'; |
echo '<div class="dayNumber">'.$Day->thisDay().'</div>'; |
if ($Day->isEmpty()) { |
echo ' '; |
} else { |
echo '<div class="dayContents"><ul>'; |
while ($entry = $Day->getEntry()) { |
echo '<li>'.$entry['desc'].'</li>'; |
//you can print the time range as well |
} |
echo '</ul></div>'; |
} |
echo '</td>'; |
if ($Day->isLast()) { |
echo "</tr>\n"; |
} |
} |
?> |
</table> |
</body> |
</html> |
/branches/v1.3-critias/bibliotheque/pear/Calendar/docs/examples/12.phps |
---|
New file |
0,0 → 1,116 |
<?php |
/** |
* Description: a complete year |
*/ |
function getmicrotime(){ |
list($usec, $sec) = explode(" ",microtime()); |
return ((float)$usec + (float)$sec); |
} |
$start = getmicrotime(); |
if ( !@include 'Calendar/Calendar.php' ) { |
define('CALENDAR_ROOT','../../'); |
} |
require_once CALENDAR_ROOT.'Year.php'; |
define ('CALENDAR_MONTH_STATE',CALENDAR_USE_MONTH_WEEKDAYS); |
if ( !isset($_GET['year']) ) $_GET['year'] = date('Y'); |
$Year = new Calendar_Year($_GET['year']); |
$Year->build(); |
?> |
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> |
<html> |
<head> |
<title> <?php echo ( $Year->thisYear() ); ?> </title> |
<style type="text/css"> |
body { |
font-family: Georgia, serif; |
} |
caption.year { |
font-weight: bold; |
font-size: 120%; |
font-color: navy; |
} |
caption.month { |
font-size: 110%; |
font-color: navy; |
} |
table.month { |
border: thin groove #800080 |
} |
tr { |
vertical-align: top; |
} |
th, td { |
text-align: right; |
font-size: 70%; |
} |
#prev { |
float: left; |
font-size: 70%; |
} |
#next { |
float: right; |
font-size: 70%; |
} |
</style> |
</head> |
<body> |
<table> |
<caption class="year"> |
<?php echo ( $Year->thisYear() ); ?> |
<div id="next"> |
<a href="?year=<?php echo ( $Year->nextYear() ); ?>">>></a> |
</div> |
<div id="prev"> |
<a href="?year=<?php echo ( $Year->prevYear() ); ?>"><<</a> |
</div> |
</caption> |
<?php |
$i = 0; |
while ( $Month = $Year->fetch() ) { |
switch ( $i ) { |
case 0: |
echo ( "<tr>\n" ); |
break; |
case 3: |
case 6: |
case 9: |
echo ( "</tr>\n<tr>\n" ); |
break; |
case 12: |
echo ( "</tr>\n" ); |
break; |
} |
echo ( "<td>\n<table class=\"month\">\n" ); |
echo ( "<caption class=\"month\">".date('F',$Month->thisMonth(TRUE))."</caption>" ); |
echo ( "<tr>\n<th>M</th><th>T</th><th>W</th><th>T</th><th>F</th><th>S</th><th>S</th>\n</tr>" ); |
$Month->build(); |
while ( $Day = $Month->fetch() ) { |
if ( $Day->isFirst() ) { |
echo ( "<tr>\n" ); |
} |
if ( $Day->isEmpty() ) { |
echo ( "<td> </td>\n" ); |
} else { |
echo ( "<td>".$Day->thisDay()."</td>\n" ); |
} |
if ( $Day->isLast() ) { |
echo ( "</tr>\n" ); |
} |
} |
echo ( "</table>\n</td>\n" ); |
$i++; |
} |
?> |
</table> |
<p>Took: <?php echo ((getmicrotime()-$start)); ?></p> |
</body> |
</html> |
/branches/v1.3-critias/bibliotheque/pear/Calendar/docs/examples/22.phps |
---|
New file |
0,0 → 1,46 |
<?php |
/** |
* Description: demonstrates using the Uri util |
*/ |
if (!@include 'Calendar/Calendar.php') { |
define('CALENDAR_ROOT', '../../'); |
} |
require_once CALENDAR_ROOT.'Month/Weekdays.php'; |
require_once CALENDAR_ROOT.'Util/Uri.php'; |
if (!isset($_GET['jahr'])) $_GET['jahr'] = date('Y'); |
if (!isset($_GET['monat'])) $_GET['monat'] = date('m'); |
// Build the month |
$Calendar = new Calendar_Month_Weekdays($_GET['jahr'], $_GET['monat']); |
echo ( '<p>The current month is ' |
.$Calendar->thisMonth().' of year '.$Calendar->thisYear().'</p>'); |
$Uri = & new Calendar_Util_Uri('jahr','monat'); |
$Uri->setFragments('jahr','monat'); |
echo "\"Vector\" URIs<pre>"; |
echo ( "Previous Uri:\t".htmlentities($Uri->prev($Calendar, 'month'))."\n" ); |
echo ( "This Uri:\t".htmlentities($Uri->this($Calendar, 'month'))."\n" ); |
echo ( "Next Uri:\t".htmlentities($Uri->next($Calendar, 'month'))."\n" ); |
echo "</pre>"; |
// Switch to scalar URIs |
$Uri->separator = '/'; // Default is & |
$Uri->scalar = true; // Omit variable names |
echo "\"Scalar\" URIs<pre>"; |
echo ( "Previous Uri:\t".$Uri->prev($Calendar, 'month')."\n" ); |
echo ( "This Uri:\t".$Uri->this($Calendar, 'month')."\n" ); |
echo ( "Next Uri:\t".$Uri->next($Calendar, 'month')."\n" ); |
echo "</pre>"; |
// Restore the vector URIs |
$Uri->separator = '&'; |
$Uri->scalar = false; |
?> |
<p> |
<a href="<?php echo($_SERVER['PHP_SELF'].'?'.$Uri->prev($Calendar, 'month'));?>">Prev</a> : |
<a href="<?php echo($_SERVER['PHP_SELF'].'?'.$Uri->next($Calendar, 'month'));?>">Next</a> |
</p> |
/branches/v1.3-critias/bibliotheque/pear/Calendar/docs/examples/14.phps |
---|
New file |
0,0 → 1,141 |
<?php |
/** |
* Description: same as 3.php, but using the PEAR::Date engine |
* Note: make sure PEAR::Date is a stable release!!! |
*/ |
function getmicrotime(){ |
list($usec, $sec) = explode(" ",microtime()); |
return ((float)$usec + (float)$sec); |
} |
$start = getmicrotime(); |
// Switch to PEAR::Date engine |
define('CALENDAR_ENGINE', 'PearDate'); |
if (!@include 'Calendar'.DIRECTORY_SEPARATOR.'Calendar.php') { |
define('CALENDAR_ROOT','../../'); |
} |
require_once CALENDAR_ROOT.'Month/Weekdays.php'; |
require_once CALENDAR_ROOT.'Day.php'; |
// Initialize GET variables if not set |
if (!isset($_GET['y'])) $_GET['y'] = date('Y'); |
if (!isset($_GET['m'])) $_GET['m'] = date('m'); |
if (!isset($_GET['d'])) $_GET['d'] = date('d'); |
// Build the month |
$month = new Calendar_Month_Weekdays($_GET['y'], $_GET['m']); |
// Create an array of days which are "selected" |
// Used for Week::build() below |
$selectedDays = array ( |
new Calendar_Day($_GET['y'], $_GET['m'], $_GET['d']), |
new Calendar_Day($_GET['y'], 12, 25), |
); |
// Build the days in the month |
$month->build($selectedDays); |
// Construct strings for next/previous links |
$PMonth = $month->prevMonth('object'); // Get previous month as object |
$prev = $_SERVER['PHP_SELF'].'?y='.$PMonth->thisYear().'&m='.$PMonth->thisMonth().'&d='.$PMonth->thisDay(); |
$NMonth = $month->nextMonth('object'); |
$next = $_SERVER['PHP_SELF'].'?y='.$NMonth->thisYear().'&m='.$NMonth->thisMonth().'&d='.$NMonth->thisDay(); |
$thisDate = new Date($month->thisMonth('timestamp')); |
?> |
<!doctype html public "-//W3C//DTD HTML 4.0 Transitional//EN"> |
<html> |
<head> |
<title> Calendar using PEAR::Date Engine </title> |
<style text="text/css"> |
table { |
background-color: silver; |
} |
caption { |
font-family: verdana; |
font-size: 12px; |
background-color: while; |
} |
.prevMonth { |
font-size: 10px; |
text-align: left; |
} |
.nextMonth { |
font-size: 10px; |
text-align: right; |
} |
th { |
font-family: verdana; |
font-size: 11px; |
color: navy; |
text-align: right; |
} |
td { |
font-family: verdana; |
font-size: 11px; |
text-align: right; |
} |
.selected { |
background-color: yellow; |
} |
</style> |
</head> |
<body> |
<h2>Calendar using PEAR::Date Engine</h2> |
<table class="calendar"> |
<caption> |
<?php echo $thisDate->format('%B %Y'); ?> |
</caption> |
<tr> |
<th>M</th> |
<th>T</th> |
<th>W</th> |
<th>T</th> |
<th>F</th> |
<th>S</th> |
<th>S</th> |
</tr> |
<?php |
while ($day = $month->fetch()) { |
// Build a link string for each day |
$link = $_SERVER['PHP_SELF']. |
'?y='.$day->thisYear(). |
'&m='.$day->thisMonth(). |
'&d='.$day->thisDay(); |
// isFirst() to find start of week |
if ($day->isFirst()) |
echo "<tr>\n"; |
if ($day->isSelected()) { |
echo '<td class="selected">'.$day->thisDay().'</td>'."\n"; |
} else if ($day->isEmpty()) { |
echo '<td> </td>'."\n"; |
} else { |
echo '<td><a href="'.$link.'">'.$day->thisDay().'</a></td>'."\n"; |
} |
// isLast() to find end of week |
if ($day->isLast()) { |
echo "</tr>\n"; |
} |
} |
?> |
<tr> |
<td> |
<a href="<?php echo $prev; ?>" class="prevMonth"><< </a> |
</td> |
<td colspan="5"> </td> |
<td> |
<a href="<?php echo $next; ?>" class="nextMonth"> >></a> |
</td> |
</tr> |
</table> |
<?php |
echo '<p><b>Took: '.(getmicrotime()-$start).' seconds</b></p>'; |
?> |
</body> |
</html> |
/branches/v1.3-critias/bibliotheque/pear/Calendar/docs/examples/16.phps |
---|
New file |
0,0 → 1,31 |
<?php |
/** |
* Description: demonstrates using the Uri decorator |
*/ |
if (!@include 'Calendar/Calendar.php') { |
define('CALENDAR_ROOT', '../../'); |
} |
require_once CALENDAR_ROOT.'Month/Weekdays.php'; |
require_once CALENDAR_ROOT.'Decorator/Uri.php'; |
if (!isset($_GET['jahr'])) $_GET['jahr'] = date('Y'); |
if (!isset($_GET['monat'])) $_GET['monat'] = date('m'); |
// Build the month |
$Calendar = new Calendar_Month_Weekdays($_GET['jahr'], $_GET['monat']); |
echo ( '<p>The current month is ' |
.$Calendar->thisMonth().' of year '.$Calendar->thisYear().'</p>'); |
$Uri = & new Calendar_Decorator_Uri($Calendar); |
$Uri->setFragments('jahr','monat'); |
// $Uri->setSeperator('/'); // Default is & |
// $Uri->setScalar(); // Omit variable names |
echo ( "<pre>Previous Uri:\t".$Uri->prev('month')."\n" ); |
echo ( "This Uri:\t".$Uri->this('month')."\n" ); |
echo ( "Next Uri:\t".$Uri->next('month')."\n</pre>" ); |
?> |
<p> |
<a href="<?php echo($_SERVER['PHP_SELF'].'?'.$Uri->prev('month'));?>">Prev</a> : |
<a href="<?php echo($_SERVER['PHP_SELF'].'?'.$Uri->next('month'));?>">Next</a> |
</p> |
/branches/v1.3-critias/bibliotheque/pear/Calendar/docs/examples/18.phps |
---|
New file |
0,0 → 1,36 |
<?php |
/** |
* Description: demonstrates using the Wrapper decorator |
*/ |
if (!@include 'Calendar/Calendar.php') { |
define('CALENDAR_ROOT', '../../'); |
} |
require_once CALENDAR_ROOT.'Month.php'; |
require_once CALENDAR_ROOT.'Decorator.php'; // Not really needed but added to help this make sense |
require_once CALENDAR_ROOT.'Decorator/Wrapper.php'; |
class MyBoldDecorator extends Calendar_Decorator |
{ |
function MyBoldDecorator(&$Calendar) |
{ |
parent::Calendar_Decorator($Calendar); |
} |
function thisDay() |
{ |
return '<b>'.parent::thisDay().'</b>'; |
} |
} |
$Month = new Calendar_Month(date('Y'), date('n')); |
$Wrapper = & new Calendar_Decorator_Wrapper($Month); |
$Wrapper->build(); |
echo '<h2>The Wrapper decorator</h2>'; |
echo '<i>Day numbers are rendered in bold</i><br /> <br />'; |
while ($DecoratedDay = $Wrapper->fetch('MyBoldDecorator')) { |
echo $DecoratedDay->thisDay().'<br />'; |
} |
?> |
/branches/v1.3-critias/bibliotheque/pear/Calendar/docs/examples/10.php |
---|
New file |
0,0 → 1,93 |
<?php |
/** |
* Description: demonstrates a decorator to provide simple output formatting |
* on the month while still allowing the days to be accessed via the decorator |
* In practice you _wouldn't_ do this - each decorator comes with a performance |
* hit for extra method calls. For this example some simple functions could help |
* format the month while the days are accessed via the normal Month object |
*/ |
if ( !@include 'Calendar/Calendar.php' ) { |
define('CALENDAR_ROOT','../../'); |
} |
require_once CALENDAR_ROOT.'Month/Weekdays.php'; |
require_once CALENDAR_ROOT.'Decorator.php'; |
// Decorate a Month with methods to improve formatting |
class MonthDecorator extends Calendar_Decorator { |
/** |
* @param Calendar_Month |
*/ |
function MonthDecorator(& $Month) { |
parent::Calendar_Decorator($Month); |
} |
/** |
* Override the prevMonth method to format the output |
*/ |
function prevMonth() { |
$prevStamp = parent::prevMonth(TRUE); |
// Build the URL for the previous month |
return $_SERVER['PHP_SELF'].'?y='.date('Y',$prevStamp). |
'&m='.date('n',$prevStamp).'&d='.date('j',$prevStamp); |
} |
/** |
* Override the thisMonth method to format the output |
*/ |
function thisMonth() { |
$thisStamp = parent::thisMonth(TRUE); |
// A human readable string from this month |
return date('F Y',$thisStamp); |
} |
/** |
* Override the nextMonth method to format the output |
*/ |
function nextMonth() { |
$nextStamp = parent::nextMonth(TRUE); |
// Build the URL for next month |
return $_SERVER['PHP_SELF'].'?y='.date('Y',$nextStamp). |
'&m='.date('n',$nextStamp).'&d='.date('j',$nextStamp); |
} |
} |
if (!isset($_GET['y'])) $_GET['y'] = date('Y'); |
if (!isset($_GET['m'])) $_GET['m'] = date('n'); |
// Creata a month as usual |
$Month = new Calendar_Month_Weekdays($_GET['y'],$_GET['m']); |
// Pass it to the decorator and use the decorator from now on... |
$MonthDecorator = new MonthDecorator($Month); |
$MonthDecorator->build(); |
?> |
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> |
<html> |
<head> |
<title> A Simple Decorator </title> |
</head> |
<body> |
<h1>A Simple Decorator</h1> |
<table> |
<caption><?php echo ( $MonthDecorator->thisMonth() ); ?></caption> |
<?php |
while ( $Day = $MonthDecorator->fetch() ) { |
if ( $Day->isFirst() ) { |
echo ( "\n<tr>\n" ); |
} |
if ( $Day->isEmpty() ) { |
echo ( "<td> </td>" ); |
} else { |
echo ( "<td>".$Day->thisDay()."</td>" ); |
} |
if ( $Day->isLast() ) { |
echo ( "\n</tr>\n" ); |
} |
} |
?> |
<tr> |
<td><a href="<?php echo ($MonthDecorator->prevMonth()); ?>">Prev</a></td> |
<td colspan="5"> </td> |
<td><a href="<?php echo ($MonthDecorator->nextMonth()); ?>">Next</a></td> |
</tr> |
</table> |
</body> |
</html> |
/branches/v1.3-critias/bibliotheque/pear/Calendar/docs/examples/11.php |
---|
New file |
0,0 → 1,109 |
<?php |
/** |
* Description: demonstrates a decorator used to "attach a payload" to a selection |
* to make it available when iterating over calendar children |
*/ |
if ( !@include 'Calendar/Calendar.php' ) { |
define('CALENDAR_ROOT','../../'); |
} |
require_once CALENDAR_ROOT.'Day.php'; |
require_once CALENDAR_ROOT.'Hour.php'; |
require_once CALENDAR_ROOT.'Decorator.php'; |
// Decorator to "attach" functionality to selected hours |
class DiaryEvent extends Calendar_Decorator { |
var $entry; |
function DiaryEvent($calendar) { |
Calendar_Decorator::Calendar_Decorator($calendar); |
} |
function setEntry($entry) { |
$this->entry = $entry; |
} |
function getEntry() { |
return $this->entry; |
} |
} |
// Create a day to view the hours for |
$Day = & new Calendar_Day(2003,10,24); |
// A sample query to get the data for today (NOT ACTUALLY USED HERE) |
$sql = " |
SELECT |
* |
FROM |
diary |
WHERE |
eventtime >= '".$Day->thisDay(TRUE)."' |
AND |
eventtime < '".$Day->nextDay(TRUE)."';"; |
// An array simulating data from a database |
$result = array ( |
array('eventtime'=>mktime(9,0,0,10,24,2003),'entry'=>'Meeting with sales team'), |
array('eventtime'=>mktime(11,0,0,10,24,2003),'entry'=>'Conference call with Widget Inc.'), |
array('eventtime'=>mktime(15,0,0,10,24,2003),'entry'=>'Presentation to board of directors') |
); |
// An array to place selected hours in |
$selection = array(); |
// Loop through the "database result" |
foreach ( $result as $row ) { |
$Hour = new Calendar_Hour(2000,1,1,1); // Create Hour with dummy values |
$Hour->setTimeStamp($row['eventtime']); // Set the real time with setTimeStamp |
// Create the decorator, passing it the Hour |
$DiaryEvent = new DiaryEvent($Hour); |
// Attach the payload |
$DiaryEvent->setEntry($row['entry']); |
// Add the decorator to the selection |
$selection[] = $DiaryEvent; |
} |
// Build the hours in that day, passing the selection |
$Day->build($selection); |
?> |
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> |
<html> |
<head> |
<title> Passing a Selection Payload with a Decorator </title> |
</head> |
<body> |
<h1>Passing a Selection "Payload" using a Decorator</h1> |
<table> |
<caption><b>Your Schedule for <?php echo ( date('D nS F Y',$Day->thisDay(TRUE)) ); ?></b></caption> |
<tr> |
<th width="5%">Time</th> |
<th>Entry</th> |
</tr> |
<?php |
while ( $Hour = & $Day->fetch() ) { |
$hour = $Hour->thisHour(); |
$minute = $Hour->thisMinute(); |
// Office hours only... |
if ( $hour >= 8 && $hour <= 18 ) { |
echo ( "<tr>\n" ); |
echo ( "<td>$hour:$minute</td>\n" ); |
// If the hour is selected, call the decorator method... |
if ( $Hour->isSelected() ) { |
echo ( "<td bgcolor=\"silver\">".$Hour->getEntry()."</td>\n" ); |
} else { |
echo ( "<td> </td>\n" ); |
} |
echo ( "</tr>\n" ); |
} |
} |
?> |
</table> |
<p>The query to fetch this data, with help from PEAR::Calendar, might be;</p> |
<pre> |
<?php echo ( $sql ); ?> |
</pre> |
</body> |
</html> |
/branches/v1.3-critias/bibliotheque/pear/Calendar/docs/examples/12.php |
---|
New file |
0,0 → 1,116 |
<?php |
/** |
* Description: a complete year |
*/ |
function getmicrotime(){ |
list($usec, $sec) = explode(" ",microtime()); |
return ((float)$usec + (float)$sec); |
} |
$start = getmicrotime(); |
if ( !@include 'Calendar/Calendar.php' ) { |
define('CALENDAR_ROOT','../../'); |
} |
require_once CALENDAR_ROOT.'Year.php'; |
define ('CALENDAR_MONTH_STATE',CALENDAR_USE_MONTH_WEEKDAYS); |
if ( !isset($_GET['year']) ) $_GET['year'] = date('Y'); |
$Year = new Calendar_Year($_GET['year']); |
$Year->build(); |
?> |
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> |
<html> |
<head> |
<title> <?php echo ( $Year->thisYear() ); ?> </title> |
<style type="text/css"> |
body { |
font-family: Georgia, serif; |
} |
caption.year { |
font-weight: bold; |
font-size: 120%; |
font-color: navy; |
} |
caption.month { |
font-size: 110%; |
font-color: navy; |
} |
table.month { |
border: thin groove #800080 |
} |
tr { |
vertical-align: top; |
} |
th, td { |
text-align: right; |
font-size: 70%; |
} |
#prev { |
float: left; |
font-size: 70%; |
} |
#next { |
float: right; |
font-size: 70%; |
} |
</style> |
</head> |
<body> |
<table> |
<caption class="year"> |
<?php echo ( $Year->thisYear() ); ?> |
<div id="next"> |
<a href="?year=<?php echo ( $Year->nextYear() ); ?>">>></a> |
</div> |
<div id="prev"> |
<a href="?year=<?php echo ( $Year->prevYear() ); ?>"><<</a> |
</div> |
</caption> |
<?php |
$i = 0; |
while ( $Month = $Year->fetch() ) { |
switch ( $i ) { |
case 0: |
echo ( "<tr>\n" ); |
break; |
case 3: |
case 6: |
case 9: |
echo ( "</tr>\n<tr>\n" ); |
break; |
case 12: |
echo ( "</tr>\n" ); |
break; |
} |
echo ( "<td>\n<table class=\"month\">\n" ); |
echo ( "<caption class=\"month\">".date('F',$Month->thisMonth(TRUE))."</caption>" ); |
echo ( "<tr>\n<th>M</th><th>T</th><th>W</th><th>T</th><th>F</th><th>S</th><th>S</th>\n</tr>" ); |
$Month->build(); |
while ( $Day = $Month->fetch() ) { |
if ( $Day->isFirst() ) { |
echo ( "<tr>\n" ); |
} |
if ( $Day->isEmpty() ) { |
echo ( "<td> </td>\n" ); |
} else { |
echo ( "<td>".$Day->thisDay()."</td>\n" ); |
} |
if ( $Day->isLast() ) { |
echo ( "</tr>\n" ); |
} |
} |
echo ( "</table>\n</td>\n" ); |
$i++; |
} |
?> |
</table> |
<p>Took: <?php echo ((getmicrotime()-$start)); ?></p> |
</body> |
</html> |
/branches/v1.3-critias/bibliotheque/pear/Calendar/docs/examples/13.php |
---|
New file |
0,0 → 1,99 |
<?php |
/** |
* Description: same as 1.php, but using the PEAR::Date engine |
* Notice the use of the CALENDAR_ENGINE constant, which |
* switches the calculation "engine" |
* Note: make sure PEAR::Date is a stable release!!! |
*/ |
function getmicrotime(){ |
list($usec, $sec) = explode(" ",microtime()); |
return ((float)$usec + (float)$sec); |
} |
// Switch to PEAR::Date engine |
define('CALENDAR_ENGINE','PearDate'); |
if ( !@include 'Calendar/Calendar.php' ) { |
define('CALENDAR_ROOT','../../'); |
} |
if (!isset($_GET['y'])) $_GET['y'] = 2003; |
if (!isset($_GET['m'])) $_GET['m'] = 8; |
if (!isset($_GET['d'])) $_GET['d'] = 9; |
if (!isset($_GET['h'])) $_GET['h'] = 12; |
if (!isset($_GET['i'])) $_GET['i'] = 34; |
if (!isset($_GET['s'])) $_GET['s'] = 46; |
switch ( @$_GET['view'] ) { |
default: |
$_GET['view'] = 'calendar_year'; |
case 'calendar_year': |
require_once CALENDAR_ROOT.'Year.php'; |
$c = new Calendar_Year($_GET['y']); |
break; |
case 'calendar_month': |
require_once CALENDAR_ROOT.'Month.php'; |
$c = new Calendar_Month($_GET['y'],$_GET['m']); |
break; |
case 'calendar_day': |
require_once CALENDAR_ROOT.'Day.php'; |
$c = new Calendar_Day($_GET['y'],$_GET['m'],$_GET['d']); |
break; |
case 'calendar_hour': |
require_once CALENDAR_ROOT.'Hour.php'; |
$c = new Calendar_Hour($_GET['y'],$_GET['m'],$_GET['d'],$_GET['h']); |
break; |
case 'calendar_minute': |
require_once CALENDAR_ROOT.'Minute.php'; |
$c = new Calendar_Minute($_GET['y'],$_GET['m'],$_GET['d'],$_GET['h'],$_GET['i']); |
break; |
case 'calendar_second': |
require_once CALENDAR_ROOT.'Second.php'; |
$c = new Calendar_Second($_GET['y'],$_GET['m'],$_GET['d'],$_GET['h'],$_GET['i'],$_GET['s']); |
break; |
} |
// Convert timestamp to human readable date |
$date = new Date($c->getTimestamp()); |
echo ( '<h1>Using PEAR::Date engine</h1>' ); |
echo ( 'Viewing: '.@$_GET['view'].'<br />' ); |
echo ( 'The time is now: '.$date->format('%Y %a %e %T').'<br >' ); |
$i = 1; |
echo ( '<h1>First Iteration</h1>' ); |
echo ( '<p>The first iteration is more "expensive", the calendar data |
structures having to be built.</p>' ); |
$start = getmicrotime(); |
$c->build(); |
while ( $e = $c->fetch() ) { |
$class = strtolower(get_class($e)); |
$link ="&y=".$e->thisYear()."&m=".$e->thisMonth()."&d=".$e->thisDay(). |
"&h=".$e->thisHour()."&i=".$e->thisMinute()."&s=".$e->thisSecond(); |
$method = 'this'.str_replace('calendar_','',$class); |
echo ( "<a href=\"".$_SERVER['PHP_SELF']."?view=".$class.$link."\">".$e->{$method}()."</a> : " ); |
if ( ($i % 10) == 0 ) { |
echo ( '<br>' ); |
} |
$i++; |
} |
echo ( '<p><b>Took: '.(getmicrotime()-$start).' seconds</b></p>' ); |
$i = 1; |
echo ( '<h1>Second Iteration</h1>' ); |
echo ( '<p>This second iteration is faster, the data structures |
being re-used</p>' ); |
$start = getmicrotime(); |
while ( $e = $c->fetch() ) { |
$class = strtolower(get_class($e)); |
$link ="&y=".$e->thisYear()."&m=".$e->thisMonth()."&d=".$e->thisDay(). |
"&h=".$e->thisHour()."&i=".$e->thisMinute()."&s=".$e->thisSecond(); |
$method = 'this'.str_replace('calendar_','',$class); |
echo ( "<a href=\"".$_SERVER['PHP_SELF']."?view=".$class.$link."\">".$e->{$method}()."</a> : " ); |
if ( ($i % 10) == 0 ) { |
echo ( '<br>' ); |
} |
$i++; |
} |
echo ( '<p><b>Took: '.(getmicrotime()-$start).' seconds</b></p>' ); |
?> |
/branches/v1.3-critias/bibliotheque/pear/Calendar/docs/examples/1.phps |
---|
New file |
0,0 → 1,92 |
<?php |
/** |
* Description: Passes through all main calendar classes, beginning with year |
* and down to seconds, skipping weeks. Useful to test Calendar is (basically) |
* working correctly |
* |
*/ |
function getmicrotime(){ |
list($usec, $sec) = explode(" ",microtime()); |
return ((float)$usec + (float)$sec); |
} |
if ( !@include 'Calendar/Calendar.php' ) { |
define('CALENDAR_ROOT','../../'); |
} |
if (!isset($_GET['y'])) $_GET['y'] = 2003; |
if (!isset($_GET['m'])) $_GET['m'] = 8; |
if (!isset($_GET['d'])) $_GET['d'] = 9; |
if (!isset($_GET['h'])) $_GET['h'] = 12; |
if (!isset($_GET['i'])) $_GET['i'] = 34; |
if (!isset($_GET['s'])) $_GET['s'] = 46; |
switch ( @$_GET['view'] ) { |
default: |
$_GET['view'] = 'calendar_year'; |
case 'calendar_year': |
require_once CALENDAR_ROOT.'Year.php'; |
$c = new Calendar_Year($_GET['y']); |
break; |
case 'calendar_month': |
require_once CALENDAR_ROOT.'Month.php'; |
$c = new Calendar_Month($_GET['y'],$_GET['m']); |
break; |
case 'calendar_day': |
require_once CALENDAR_ROOT.'Day.php'; |
$c = new Calendar_Day($_GET['y'],$_GET['m'],$_GET['d']); |
break; |
case 'calendar_hour': |
require_once CALENDAR_ROOT.'Hour.php'; |
$c = new Calendar_Hour($_GET['y'],$_GET['m'],$_GET['d'],$_GET['h']); |
break; |
case 'calendar_minute': |
require_once CALENDAR_ROOT.'Minute.php'; |
$c = new Calendar_Minute($_GET['y'],$_GET['m'],$_GET['d'],$_GET['h'],$_GET['i']); |
break; |
case 'calendar_second': |
require_once CALENDAR_ROOT.'Second.php'; |
$c = new Calendar_Second($_GET['y'],$_GET['m'],$_GET['d'],$_GET['h'],$_GET['i'],$_GET['s']); |
break; |
} |
echo ( 'Viewing: '.@$_GET['view'].'<br />' ); |
echo ( 'The time is now: '.date('Y M d H:i:s',$c->getTimestamp()).'<br >' ); |
$i = 1; |
echo ( '<h1>First Iteration</h1>' ); |
echo ( '<p>The first iteration is more "expensive", the calendar data |
structures having to be built.</p>' ); |
$start = getmicrotime(); |
$c->build(); |
while ( $e = $c->fetch() ) { |
$class = strtolower(get_class($e)); |
$link ="&y=".$e->thisYear()."&m=".$e->thisMonth()."&d=".$e->thisDay(). |
"&h=".$e->thisHour()."&i=".$e->thisMinute()."&s=".$e->thisSecond(); |
$method = 'this'.str_replace('calendar_','',$class); |
echo ( "<a href=\"".$_SERVER['PHP_SELF']."?view=".$class.$link."\">".$e->{$method}()."</a> : " ); |
if ( ($i % 10) == 0 ) { |
echo ( '<br>' ); |
} |
$i++; |
} |
echo ( '<p><b>Took: '.(getmicrotime()-$start).' seconds</b></p>' ); |
$i = 1; |
echo ( '<h1>Second Iteration</h1>' ); |
echo ( '<p>This second iteration is faster, the data structures |
being re-used</p>' ); |
$start = getmicrotime(); |
while ( $e = $c->fetch() ) { |
$class = strtolower(get_class($e)); |
$link ="&y=".$e->thisYear()."&m=".$e->thisMonth()."&d=".$e->thisDay(). |
"&h=".$e->thisHour()."&i=".$e->thisMinute()."&s=".$e->thisSecond(); |
$method = 'this'.str_replace('calendar_','',$class); |
echo ( "<a href=\"".$_SERVER['PHP_SELF']."?view=".$class.$link."\">".$e->{$method}()."</a> : " ); |
if ( ($i % 10) == 0 ) { |
echo ( '<br>' ); |
} |
$i++; |
} |
echo ( '<p><b>Took: '.(getmicrotime()-$start).' seconds</b></p>' ); |
?> |
/branches/v1.3-critias/bibliotheque/pear/Calendar/docs/examples/index.html |
---|
New file |
0,0 → 1,50 |
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" |
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> |
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en"> |
<head> |
<title>PEAR::Calendar Examples</title> |
<style type="text/css"> |
body { |
font-family: georgia, serif; |
} |
pre { |
background-color: silver; |
} |
code { |
color: navy; |
background-color: #e2e3e4; |
} |
</style> |
</head> |
<body> |
<h1>PEAR::Calendar Examples</h1> |
<p>$Id: index.html,v 1.6 2004/08/17 09:10:53 hfuecks Exp $</p> |
<ul> |
<li><a href="1.php">1.php</a> [<a href="1.phps">src</a>] - shows basic usage, passing all the way down from <code>Calendar_Year</code> to <code>Calendar_Second</code> - more of a quick test it's working</li> |
<li><a href="2.php">2.php</a> [<a href="2.phps">src</a>] - shows how to build a tabular month using <code>Calendar_Month_Weeks</code>, <code>Calendar_Week</code>, <code>Calendar_Day</code> as well as selecting some dates.</li> |
<li><a href="3.php">3.php</a> [<a href="3.phps">src</a>] - shows how to build a tabular month using <code>Calendar_Month_Weekdays</code> and <code>Calendar_Day</code>, as well as selecting some dates (this method is faster).</li> |
<li><a href="4.php">4.php</a> [<a href="4.phps">src</a>] - shows how to use PEAR::Calendar for validation.</li> |
<li><a href="5.php">5.php</a> [<a href="5.phps">src</a>] - shows PEAR::Calendar in use to help generate a form.</li> |
<li><a href="6.php">6.php</a> [<a href="6.phps">src</a>] - a month and day "planner" calendar, which can be rendered both as HTML and WML.</li> |
<li><a href="7.php">7.php</a> [<a href="7.phps">src</a>] - a simple SOAP Calendar Server, using PEAR::SOAP and PEAR::Calendar</li> |
<li><a href="8.php">8.php</a> [<a href="8.phps">src</a>] - a WSDL SOAP client for the SOAP Calendar Server</li> |
<li><a href="9.php">9.php</a> [<a href="9.phps">src</a>] - quick example of i18n with <code>setlocale</code> (not working on SF)</li> |
<li><a href="10.php">10.php</a> [<a href="10.phps">src</a>] - an example of extending <code>Calendar_Decorator</code> to modify output</li> |
<li><a href="11.php">11.php</a> [<a href="11.phps">src</a>] - attaching a "payload" (e.g. results of a DB query) to a calendar using <code>Calendar_Decorator</code> to allow the payload to be available inside the main loop.</li> |
<li><a href="12.php">12.php</a> [<a href="12.phps">src</a>] - a complete year with months.</li> |
<li><a href="13.php">13.php</a> [<a href="13.phps">src</a>] - same as 1.php but using <code>Calendar_Engine_PearDate</code>, (see <a href="http://pear.php.net/Date">PEAR::Date</a>).</li> |
<li><a href="14.php">14.php</a> [<a href="14.phps">src</a>] - same as 3.php but using <code>Calendar_Engine_PearDate</code></li> |
<li><a href="15.php">15.php</a> [<a href="15.phps">src</a>] - paging through weeks </li> |
<li><a href="16.php">16.php</a> [<a href="16.phps">src</a>] - example of <code>Calendar_Decorator_Uri</code>. <i>Note</i> you should prefer <code>Calendar_Util_Uri</code> (see below) in most cases, for performance </li> |
<li><a href="17.php">17.php</a> [<a href="17.phps">src</a>] - example of <code>Calendar_Decorator_Textual</code>. <i>Note</i> you should prefer <code>Calendar_Util_Textual</code> (see below) in most cases, for performance</li> |
<li><a href="18.php">18.php</a> [<a href="18.phps">src</a>] - example of <code>Calendar_Decorator_Wrapper</code>.</li> |
<li><a href="19.php">19.php</a> [<a href="19.phps">src</a>] - example of <code>Calendar_Decorator_Weekday</code>.</li> |
<li><a href="20.php">20.php</a> [<a href="20.phps">src</a>] - shows how to attach a "payload" spanning multiple days, with more than one entry per day</li> |
<li><a href="21.php">21.php</a> [<a href="21.phps">src</a>] - same as 12.php but using <code>Calendar_Month_Weeks</code> instead of <code>Calendar_Month_Weekdays</code> to allow the week in the year or week in the month to be displayed.</li> |
<li><a href="22.php">22.php</a> [<a href="22.phps">src</a>] - demonstrates use of <code>Calendar_Util_Uri</code>.</li> |
<li><a href="23.php">23.php</a> [<a href="23.phps">src</a>] - demonstrates use of <code>Calendar_Util_Textual</code>.</li> |
<li><a href="24.php">24.php</a> [<a href="24.phps">src</a>] - <code>Calendar_Decorator_Weekday</code> combined with <code>Calendar_Decorator_Wrapper</code> to decorate days in the month.</li> |
</ul> |
</body> |
</html> |
/branches/v1.3-critias/bibliotheque/pear/Calendar/docs/examples/14.php |
---|
New file |
0,0 → 1,141 |
<?php |
/** |
* Description: same as 3.php, but using the PEAR::Date engine |
* Note: make sure PEAR::Date is a stable release!!! |
*/ |
function getmicrotime(){ |
list($usec, $sec) = explode(" ",microtime()); |
return ((float)$usec + (float)$sec); |
} |
$start = getmicrotime(); |
// Switch to PEAR::Date engine |
define('CALENDAR_ENGINE', 'PearDate'); |
if (!@include 'Calendar'.DIRECTORY_SEPARATOR.'Calendar.php') { |
define('CALENDAR_ROOT','../../'); |
} |
require_once CALENDAR_ROOT.'Month/Weekdays.php'; |
require_once CALENDAR_ROOT.'Day.php'; |
// Initialize GET variables if not set |
if (!isset($_GET['y'])) $_GET['y'] = date('Y'); |
if (!isset($_GET['m'])) $_GET['m'] = date('m'); |
if (!isset($_GET['d'])) $_GET['d'] = date('d'); |
// Build the month |
$month = new Calendar_Month_Weekdays($_GET['y'], $_GET['m']); |
// Create an array of days which are "selected" |
// Used for Week::build() below |
$selectedDays = array ( |
new Calendar_Day($_GET['y'], $_GET['m'], $_GET['d']), |
new Calendar_Day($_GET['y'], 12, 25), |
); |
// Build the days in the month |
$month->build($selectedDays); |
// Construct strings for next/previous links |
$PMonth = $month->prevMonth('object'); // Get previous month as object |
$prev = $_SERVER['PHP_SELF'].'?y='.$PMonth->thisYear().'&m='.$PMonth->thisMonth().'&d='.$PMonth->thisDay(); |
$NMonth = $month->nextMonth('object'); |
$next = $_SERVER['PHP_SELF'].'?y='.$NMonth->thisYear().'&m='.$NMonth->thisMonth().'&d='.$NMonth->thisDay(); |
$thisDate = new Date($month->thisMonth('timestamp')); |
?> |
<!doctype html public "-//W3C//DTD HTML 4.0 Transitional//EN"> |
<html> |
<head> |
<title> Calendar using PEAR::Date Engine </title> |
<style text="text/css"> |
table { |
background-color: silver; |
} |
caption { |
font-family: verdana; |
font-size: 12px; |
background-color: while; |
} |
.prevMonth { |
font-size: 10px; |
text-align: left; |
} |
.nextMonth { |
font-size: 10px; |
text-align: right; |
} |
th { |
font-family: verdana; |
font-size: 11px; |
color: navy; |
text-align: right; |
} |
td { |
font-family: verdana; |
font-size: 11px; |
text-align: right; |
} |
.selected { |
background-color: yellow; |
} |
</style> |
</head> |
<body> |
<h2>Calendar using PEAR::Date Engine</h2> |
<table class="calendar"> |
<caption> |
<?php echo $thisDate->format('%B %Y'); ?> |
</caption> |
<tr> |
<th>M</th> |
<th>T</th> |
<th>W</th> |
<th>T</th> |
<th>F</th> |
<th>S</th> |
<th>S</th> |
</tr> |
<?php |
while ($day = $month->fetch()) { |
// Build a link string for each day |
$link = $_SERVER['PHP_SELF']. |
'?y='.$day->thisYear(). |
'&m='.$day->thisMonth(). |
'&d='.$day->thisDay(); |
// isFirst() to find start of week |
if ($day->isFirst()) |
echo "<tr>\n"; |
if ($day->isSelected()) { |
echo '<td class="selected">'.$day->thisDay().'</td>'."\n"; |
} else if ($day->isEmpty()) { |
echo '<td> </td>'."\n"; |
} else { |
echo '<td><a href="'.$link.'">'.$day->thisDay().'</a></td>'."\n"; |
} |
// isLast() to find end of week |
if ($day->isLast()) { |
echo "</tr>\n"; |
} |
} |
?> |
<tr> |
<td> |
<a href="<?php echo $prev; ?>" class="prevMonth"><< </a> |
</td> |
<td colspan="5"> </td> |
<td> |
<a href="<?php echo $next; ?>" class="nextMonth"> >></a> |
</td> |
</tr> |
</table> |
<?php |
echo '<p><b>Took: '.(getmicrotime()-$start).' seconds</b></p>'; |
?> |
</body> |
</html> |
/branches/v1.3-critias/bibliotheque/pear/Calendar/docs/examples/3.phps |
---|
New file |
0,0 → 1,134 |
<?php |
/** |
* Description: Performs same behaviour as 2.php but uses Month::buildWeekDays() |
* and is faster |
*/ |
function getmicrotime(){ |
list($usec, $sec) = explode(" ",microtime()); |
return ((float)$usec + (float)$sec); |
} |
$start = getmicrotime(); |
if ( !@include 'Calendar/Calendar.php' ) { |
define('CALENDAR_ROOT','../../'); |
} |
require_once CALENDAR_ROOT.'Month/Weekdays.php'; |
require_once CALENDAR_ROOT.'Day.php'; |
if (!isset($_GET['y'])) $_GET['y'] = date('Y'); |
if (!isset($_GET['m'])) $_GET['m'] = date('m'); |
if (!isset($_GET['d'])) $_GET['d'] = date('d'); |
// Build the month |
$Month = new Calendar_Month_Weekdays($_GET['y'],$_GET['m']); |
// Construct strings for next/previous links |
$PMonth = $Month->prevMonth('object'); // Get previous month as object |
$prev = $_SERVER['PHP_SELF'].'?y='.$PMonth->thisYear().'&m='.$PMonth->thisMonth().'&d='.$PMonth->thisDay(); |
$NMonth = $Month->nextMonth('object'); |
$next = $_SERVER['PHP_SELF'].'?y='.$NMonth->thisYear().'&m='.$NMonth->thisMonth().'&d='.$NMonth->thisDay(); |
?> |
<!doctype html public "-//W3C//DTD HTML 4.0 Transitional//EN"> |
<html> |
<head> |
<title> Calendar </title> |
<style text="text/css"> |
table { |
background-color: silver; |
} |
caption { |
font-family: verdana; |
font-size: 12px; |
background-color: while; |
} |
.prevMonth { |
font-size: 10px; |
text-align: left; |
} |
.nextMonth { |
font-size: 10px; |
text-align: right; |
} |
th { |
font-family: verdana; |
font-size: 11px; |
color: navy; |
text-align: right; |
} |
td { |
font-family: verdana; |
font-size: 11px; |
text-align: right; |
} |
.selected { |
background-color: yellow; |
} |
</style> |
</head> |
<body> |
<?php |
$selectedDays = array ( |
new Calendar_Day($_GET['y'],$_GET['m'],$_GET['d']), |
new Calendar_Day($_GET['y'],12,25), |
); |
// Build the days in the month |
$Month->build($selectedDays); |
?> |
<h2>Built with Calendar_Month_Weekday::build()</h2> |
<table class="calendar"> |
<caption> |
<?php echo ( date('F Y',$Month->getTimeStamp())); ?> |
</caption> |
<tr> |
<th>M</th> |
<th>T</th> |
<th>W</th> |
<th>T</th> |
<th>F</th> |
<th>S</th> |
<th>S</th> |
</tr> |
<?php |
while ( $Day = $Month->fetch() ) { |
// Build a link string for each day |
$link = $_SERVER['PHP_SELF']. |
'?y='.$Day->thisYear(). |
'&m='.$Day->thisMonth(). |
'&d='.$Day->thisDay(); |
// isFirst() to find start of week |
if ( $Day->isFirst() ) |
echo ( "<tr>\n" ); |
if ( $Day->isSelected() ) { |
echo ( "<td class=\"selected\">".$Day->thisDay()."</td>\n" ); |
} else if ( $Day->isEmpty() ) { |
echo ( "<td> </td>\n" ); |
} else { |
echo ( "<td><a href=\"".$link."\">".$Day->thisDay()."</a></td>\n" ); |
} |
// isLast() to find end of week |
if ( $Day->isLast() ) |
echo ( "</tr>\n" ); |
} |
?> |
<tr> |
<td> |
<a href="<?php echo ($prev);?>" class="prevMonth"><< </a> |
</td> |
<td colspan="5"> </td> |
<td> |
<a href="<?php echo ($next);?>" class="nextMonth"> >></a> |
</td> |
</tr> |
</table> |
<?php |
echo ( '<p><b>Took: '.(getmicrotime()-$start).' seconds</b></p>' ); |
?> |
</body> |
</html> |
/branches/v1.3-critias/bibliotheque/pear/Calendar/docs/examples/15.php |
---|
New file |
0,0 → 1,58 |
<?php |
/** |
* Shows more on how a week can be used |
*/ |
function getmicrotime() { |
list($usec, $sec) = explode(" ", microtime()); |
return ((float)$usec + (float)$sec); |
} |
$start = getmicrotime(); |
if (!@include 'Calendar/Calendar.php') { |
define('CALENDAR_ROOT', '../../'); |
} |
require_once CALENDAR_ROOT.'Week.php'; |
if (!isset($_GET['y'])) $_GET['y'] = date('Y'); |
if (!isset($_GET['m'])) $_GET['m'] = date('m'); |
if (!isset($_GET['d'])) $_GET['d'] = 1; |
// Build the month |
$Week = new Calendar_Week($_GET['y'], $_GET['m'], $_GET['d']); |
/* |
$Validator = $Week->getValidator(); |
if (!$Validator->isValidWeek()) { |
die ('Please enter a valid week!'); |
} |
*/ |
?> |
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> |
<html> |
<head> |
<title> Paging Weeks </title> |
</head> |
<body> |
<h1>Paging Weeks</h1> |
<h2>Week: <?php echo $Week->thisWeek().' '.date('F Y',$Week->thisMonth(true)); ?></h2> |
<?php |
$Week->build(); |
while ($Day = $Week->fetch()) { |
echo '<p>'.date('jS F',$Day->thisDay(true))."</p>\n"; |
} |
$days = $Week->fetchAll(); |
$prevWeek = $Week->prevWeek('array'); |
$prevWeekLink = $_SERVER['PHP_SELF']. |
'?y='.$prevWeek['year']. |
'&m='.$prevWeek['month']. |
'&d='.$prevWeek['day']; |
$nextWeek = $Week->nextWeek('array'); |
$nextWeekLink = $_SERVER['PHP_SELF']. |
'?y='.$nextWeek['year']. |
'&m='.$nextWeek['month']. |
'&d='.$nextWeek['day']; |
?> |
<p><a href="<?php echo $prevWeekLink; ?>"><<</a> | <a href="<?php echo $nextWeekLink; ?>">>></a></p> |
</body> |
</html> |
/branches/v1.3-critias/bibliotheque/pear/Calendar/docs/examples/16.php |
---|
New file |
0,0 → 1,31 |
<?php |
/** |
* Description: demonstrates using the Uri decorator |
*/ |
if (!@include 'Calendar/Calendar.php') { |
define('CALENDAR_ROOT', '../../'); |
} |
require_once CALENDAR_ROOT.'Month/Weekdays.php'; |
require_once CALENDAR_ROOT.'Decorator/Uri.php'; |
if (!isset($_GET['jahr'])) $_GET['jahr'] = date('Y'); |
if (!isset($_GET['monat'])) $_GET['monat'] = date('m'); |
// Build the month |
$Calendar = new Calendar_Month_Weekdays($_GET['jahr'], $_GET['monat']); |
echo ( '<p>The current month is ' |
.$Calendar->thisMonth().' of year '.$Calendar->thisYear().'</p>'); |
$Uri = & new Calendar_Decorator_Uri($Calendar); |
$Uri->setFragments('jahr','monat'); |
// $Uri->setSeperator('/'); // Default is & |
// $Uri->setScalar(); // Omit variable names |
echo ( "<pre>Previous Uri:\t".$Uri->prev('month')."\n" ); |
echo ( "This Uri:\t".$Uri->this('month')."\n" ); |
echo ( "Next Uri:\t".$Uri->next('month')."\n</pre>" ); |
?> |
<p> |
<a href="<?php echo($_SERVER['PHP_SELF'].'?'.$Uri->prev('month'));?>">Prev</a> : |
<a href="<?php echo($_SERVER['PHP_SELF'].'?'.$Uri->next('month'));?>">Next</a> |
</p> |
/branches/v1.3-critias/bibliotheque/pear/Calendar/docs/examples/5.phps |
---|
New file |
0,0 → 1,132 |
<?php |
/** |
* Description: generating elements of a form with PEAR::Calendar, using |
* selections as well as validating the submission |
*/ |
function getmicrotime(){ |
list($usec, $sec) = explode(" ",microtime()); |
return ((float)$usec + (float)$sec); |
} |
$start = getmicrotime(); |
if ( !@include 'Calendar/Calendar.php' ) { |
define('CALENDAR_ROOT','../../'); |
} |
require_once CALENDAR_ROOT.'Year.php'; |
require_once CALENDAR_ROOT.'Month.php'; |
require_once CALENDAR_ROOT.'Day.php'; |
require_once CALENDAR_ROOT.'Hour.php'; |
require_once CALENDAR_ROOT.'Minute.php'; |
require_once CALENDAR_ROOT.'Second.php'; |
// Initialize if not set |
if (!isset($_POST['y'])) $_POST['y'] = date('Y'); |
if (!isset($_POST['m'])) $_POST['m'] = date('n'); |
if (!isset($_POST['d'])) $_POST['d'] = date('j'); |
if (!isset($_POST['h'])) $_POST['h'] = date('H'); |
if (!isset($_POST['i'])) $_POST['i'] = date('i'); |
if (!isset($_POST['s'])) $_POST['s'] = date('s'); |
?> |
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> |
<html> |
<head> |
<title> Select and Update </title> |
</head> |
<body> |
<h1>Select and Update</h1> |
<?php |
if ( isset($_POST['update']) ) { |
$Second = & new Calendar_Second($_POST['y'],$_POST['m'],$_POST['d'],$_POST['h'],$_POST['i'],$_POST['s']); |
if ( !$Second->isValid() ) { |
$V= & $Second->getValidator(); |
echo ('<p>Validation failed:</p>' ); |
while ( $error = $V->fetch() ) { |
echo ( $error->toString() .'<br>' ); |
} |
} else { |
echo ('<p>Validation success.</p>' ); |
echo ( '<p>New timestamp is: '.$Second->getTimeStamp().' which could be used to update a database, for example'); |
} |
} else { |
$Year = new Calendar_Year($_POST['y']); |
$Month = new Calendar_Month($_POST['y'],$_POST['m']); |
$Day = new Calendar_Day($_POST['y'],$_POST['m'],$_POST['d']); |
$Hour = new Calendar_Hour($_POST['y'],$_POST['m'],$_POST['d'],$_POST['h']); |
$Minute = new Calendar_Minute($_POST['y'],$_POST['m'],$_POST['d'],$_POST['h'],$_POST['i']); |
$Second = new Calendar_Second($_POST['y'],$_POST['m'],$_POST['d'],$_POST['h'],$_POST['i'],$_POST['s']); |
?> |
<p><b>Set the alarm clock</p></p> |
<form action="<?php echo ( $_SERVER['PHP_SELF'] ); ?>" method="post"> |
Year: <input type="text" name="y" value="<?php echo ( $_POST['y'] ); ?>" size="4"> |
Month:<select name="m"> |
<?php |
$selection = array($Month); |
$Year->build($selection); |
while ( $Child = & $Year->fetch() ) { |
if ( $Child->isSelected() ) { |
echo ( "<option value=\"".$Child->thisMonth()."\" selected>".$Child->thisMonth()."\n" ); |
} else { |
echo ( "<option value=\"".$Child->thisMonth()."\">".$Child->thisMonth()."\n" ); |
} |
} |
?> |
</select> |
Day:<select name="d"> |
<?php |
$selection = array($Day); |
$Month->build($selection); |
while ( $Child = & $Month->fetch() ) { |
if ( $Child->isSelected() ) { |
echo ( "<option value=\"".$Child->thisDay()."\" selected>".$Child->thisDay()."\n" ); |
} else { |
echo ( "<option value=\"".$Child->thisDay()."\">".$Child->thisDay()."\n" ); |
} |
} |
?> |
</select> |
Hour:<select name="h"> |
<?php |
$selection = array($Hour); |
$Day->build($selection); |
while ( $Child = & $Day->fetch() ) { |
if ( $Child->isSelected() ) { |
echo ( "<option value=\"".$Child->thisHour()."\" selected>".$Child->thisHour()."\n" ); |
} else { |
echo ( "<option value=\"".$Child->thisHour()."\">".$Child->thisHour()."\n" ); |
} |
} |
?> |
</select> |
Minute:<select name="i"> |
<?php |
$selection = array($Minute); |
$Hour->build($selection); |
while ( $Child = & $Hour->fetch() ) { |
if ( $Child->isSelected() ) { |
echo ( "<option value=\"".$Child->thisMinute()."\" selected>".$Child->thisMinute()."\n" ); |
} else { |
echo ( "<option value=\"".$Child->thisMinute()."\">".$Child->thisMinute()."\n" ); |
} |
} |
?> |
</select> |
Second:<select name="s"> |
<?php |
$selection = array($Second); |
$Minute->build($selection); |
while ( $Child = & $Minute->fetch() ) { |
if ( $Child->isSelected() ) { |
echo ( "<option value=\"".$Child->thisSecond()."\" selected>".$Child->thisSecond()."\n" ); |
} else { |
echo ( "<option value=\"".$Child->thisSecond()."\">".$Child->thisSecond()."\n" ); |
} |
} |
?> |
</select> |
<input type="submit" name="update" value="Set Alarm"><br> |
<?php |
} |
?> |
<?php echo ( '<p><b>Took: '.(getmicrotime()-$start).' seconds</b></p>' ); ?> |
</body> |
</html> |
/branches/v1.3-critias/bibliotheque/pear/Calendar/docs/examples/17.php |
---|
New file |
0,0 → 1,71 |
<?php |
/** |
* Description: demonstrates using the Textual decorator |
*/ |
if (!@include 'Calendar'.DIRECTORY_SEPARATOR.'Calendar.php') { |
define('CALENDAR_ROOT', '../../'); |
} |
require_once CALENDAR_ROOT.'Day.php'; |
require_once CALENDAR_ROOT.'Month'.DIRECTORY_SEPARATOR.'Weekdays.php'; |
require_once CALENDAR_ROOT.'Decorator'.DIRECTORY_SEPARATOR.'Textual.php'; |
// Could change language like this |
// setlocale (LC_TIME, "de_DE"); // Unix based (probably) |
// setlocale (LC_TIME, "ge"); // Windows |
echo "<hr>Calling: Calendar_Decorator_Textual::monthNames('long');<pre>"; |
print_r(Calendar_Decorator_Textual::monthNames('long')); |
echo '</pre>'; |
echo "<hr>Calling: Calendar_Decorator_Textual::weekdayNames('two');<pre>"; |
print_r(Calendar_Decorator_Textual::weekdayNames('two')); |
echo '</pre>'; |
echo "<hr>Creating: new Calendar_Day(date('Y'), date('n'), date('d'));<br />"; |
$Calendar = new Calendar_Day(date('Y'), date('n'), date('d')); |
// Decorate |
$Textual = & new Calendar_Decorator_Textual($Calendar); |
echo '<hr>Previous month is: '.$Textual->prevMonthName('two').'<br />'; |
echo 'This month is: '.$Textual->thisMonthName('short').'<br />'; |
echo 'Next month is: '.$Textual->nextMonthName().'<br /><hr />'; |
echo 'Previous day is: '.$Textual->prevDayName().'<br />'; |
echo 'This day is: '.$Textual->thisDayName('short').'<br />'; |
echo 'Next day is: '.$Textual->nextDayName('one').'<br /><hr />'; |
echo "Creating: new Calendar_Month_Weekdays(date('Y'), date('n'), 6); - Saturday is first day of week<br />"; |
$Calendar = new Calendar_Month_Weekdays(date('Y'), date('n'), 6); |
// Decorate |
$Textual = & new Calendar_Decorator_Textual($Calendar); |
?> |
<p>Rendering calendar....</p> |
<table> |
<caption><?php echo $Textual->thisMonthName().' '.$Textual->thisYear(); ?></caption> |
<tr> |
<?php |
$dayheaders = $Textual->orderedWeekdays('short'); |
foreach ($dayheaders as $dayheader) { |
echo '<th>'.$dayheader.'</th>'; |
} |
?> |
</tr> |
<?php |
$Calendar->build(); |
while ($Day = $Calendar->fetch()) { |
if ($Day->isFirst()) { |
echo "<tr>\n"; |
} |
if ($Day->isEmpty()) { |
echo '<td> </td>'; |
} else { |
echo '<td>'.$Day->thisDay().'</td>'; |
} |
if ($Day->isLast()) { |
echo "</tr>\n"; |
} |
} |
?> |
</table> |
/branches/v1.3-critias/bibliotheque/pear/Calendar/docs/examples/18.php |
---|
New file |
0,0 → 1,36 |
<?php |
/** |
* Description: demonstrates using the Wrapper decorator |
*/ |
if (!@include 'Calendar/Calendar.php') { |
define('CALENDAR_ROOT', '../../'); |
} |
require_once CALENDAR_ROOT.'Month.php'; |
require_once CALENDAR_ROOT.'Decorator.php'; // Not really needed but added to help this make sense |
require_once CALENDAR_ROOT.'Decorator/Wrapper.php'; |
class MyBoldDecorator extends Calendar_Decorator |
{ |
function MyBoldDecorator(&$Calendar) |
{ |
parent::Calendar_Decorator($Calendar); |
} |
function thisDay() |
{ |
return '<b>'.parent::thisDay().'</b>'; |
} |
} |
$Month = new Calendar_Month(date('Y'), date('n')); |
$Wrapper = & new Calendar_Decorator_Wrapper($Month); |
$Wrapper->build(); |
echo '<h2>The Wrapper decorator</h2>'; |
echo '<i>Day numbers are rendered in bold</i><br /> <br />'; |
while ($DecoratedDay = $Wrapper->fetch('MyBoldDecorator')) { |
echo $DecoratedDay->thisDay().'<br />'; |
} |
?> |
/branches/v1.3-critias/bibliotheque/pear/Calendar/docs/examples/19.php |
---|
New file |
0,0 → 1,24 |
<?php |
/** |
* Description: demonstrates using the Weekday decorator |
*/ |
if (!@include 'Calendar'.DIRECTORY_SEPARATOR.'Calendar.php') { |
define('CALENDAR_ROOT', '../../'); |
} |
require_once CALENDAR_ROOT.'Day.php'; |
require_once CALENDAR_ROOT.'Decorator/Weekday.php'; |
$Day = new Calendar_Day(date('Y'), date('n'),date('d')); |
$WeekDay = & new Calendar_Decorator_Weekday($Day); |
// $WeekDay->setFirstDay(0); // Make Sunday first Day |
echo 'Yesterday: '.$WeekDay->prevWeekDay().'<br>'; |
echo 'Today: '.$WeekDay->thisWeekDay().'<br>'; |
echo 'Tomorrow: '.$WeekDay->nextWeekDay().'<br>'; |
$WeekDay->build(); |
echo 'Hours today:<br>'; |
while ( $Hour = $WeekDay->fetch() ) { |
echo $Hour->thisHour().'<br>'; |
} |
?> |
/branches/v1.3-critias/bibliotheque/pear/Calendar/docs/examples/7.phps |
---|
New file |
0,0 → 1,92 |
<?php |
/** |
* Description: a SOAP Calendar Server |
*/ |
if (!@include('SOAP'.DIRECTORY_SEPARATOR.'Server.php')) { |
die('You must have PEAR::SOAP installed'); |
} |
if (!@include 'Calendar'.DIRECTORY_SEPARATOR.'Calendar.php') { |
define('CALENDAR_ROOT', '../../'); |
} |
class Calendar_Server |
{ |
var $__dispatch_map = array(); |
var $__typedef = array(); |
function Calendar_Server() |
{ |
$this->__dispatch_map['getMonth'] = |
array('in' => array('year' => 'int', 'month'=>'int'), |
'out' => array('month' => '{urn:PEAR_SOAP_Calendar}Month'), |
); |
$this->__typedef['Month'] = array ( |
'monthname' => 'string', |
'days' => '{urn:PEAR_SOAP_Calendar}MonthDays' |
); |
$this->__typedef['MonthDays'] = array (array ('{urn:PEAR_SOAP_Calendar}Day')); |
$this->__typedef['Day'] = array ( |
'isFirst' => 'int', |
'isLast' => 'int', |
'isEmpty' => 'int', |
'day' => 'int' ); |
} |
function __dispatch($methodname) |
{ |
if (isset($this->__dispatch_map[$methodname])) |
return $this->__dispatch_map[$methodname]; |
return NULL; |
} |
function getMonth($year, $month) |
{ |
require_once(CALENDAR_ROOT.'Month'.DIRECTORY_SEPARATOR.'Weekdays.php'); |
$Month = & new Calendar_Month_Weekdays($year,$month); |
if (!$Month->isValid()) { |
$V = & $Month->getValidator(); |
$errorMsg = ''; |
while ($error = $V->fetch()) { |
$errorMsg .= $error->toString()."\n"; |
} |
return new SOAP_Fault($errorMsg, 'Client'); |
} else { |
$monthname = date('F Y', $Month->getTimeStamp()); |
$days = array(); |
$Month->build(); |
while ($Day = & $Month->fetch()) { |
$day = array( |
'isFirst' => (int)$Day->isFirst(), |
'isLast' => (int)$Day->isLast(), |
'isEmpty' => (int)$Day->isEmpty(), |
'day' => (int)$Day->thisDay(), |
); |
$days[] = $day; |
} |
return array('monthname' => $monthname, 'days' => $days); |
} |
} |
} |
$server = new SOAP_Server(); |
$server->_auto_translation = true; |
$calendar = new Calendar_Server(); |
$server->addObjectMap($calendar, 'urn:PEAR_SOAP_Calendar'); |
if (strtoupper($_SERVER['REQUEST_METHOD'])=='POST') { |
$server->service($GLOBALS['HTTP_RAW_POST_DATA']); |
} else { |
require_once 'SOAP'.DIRECTORY_SEPARATOR.'Disco.php'; |
$disco = new SOAP_DISCO_Server($server, "PEAR_SOAP_Calendar"); |
if (isset($_SERVER['QUERY_STRING']) && |
strcasecmp($_SERVER['QUERY_STRING'], 'wsdl')==0) { |
header("Content-type: text/xml"); |
echo $disco->getWSDL(); |
} else { |
echo 'This is a PEAR::SOAP Calendar Server. For client try <a href="8.php">here</a><br />'; |
echo 'For WSDL try <a href="?wsdl">here</a>'; |
} |
exit; |
} |
?> |
/branches/v1.3-critias/bibliotheque/pear/Calendar/docs/examples/9.phps |
---|
New file |
0,0 → 1,16 |
<?php |
/** |
* Description: simple example on i18N |
*/ |
if ( !@include 'Calendar/Calendar.php' ) { |
define('CALENDAR_ROOT','../../'); |
} |
require_once CALENDAR_ROOT.'Day.php'; |
$Day = & new Calendar_Day(2003,10,23); |
setlocale (LC_TIME, "de_DE"); // Unix based (probably) |
// setlocale (LC_TIME, "ge"); // Windows |
echo ( strftime('%A %d %B %Y',$Day->getTimeStamp())); |
?> |
/branches/v1.3-critias/bibliotheque/pear/Calendar/docs/examples/1.php |
---|
New file |
0,0 → 1,92 |
<?php |
/** |
* Description: Passes through all main calendar classes, beginning with year |
* and down to seconds, skipping weeks. Useful to test Calendar is (basically) |
* working correctly |
* |
*/ |
function getmicrotime(){ |
list($usec, $sec) = explode(" ",microtime()); |
return ((float)$usec + (float)$sec); |
} |
if ( !@include 'Calendar/Calendar.php' ) { |
define('CALENDAR_ROOT','../../'); |
} |
if (!isset($_GET['y'])) $_GET['y'] = 2003; |
if (!isset($_GET['m'])) $_GET['m'] = 8; |
if (!isset($_GET['d'])) $_GET['d'] = 9; |
if (!isset($_GET['h'])) $_GET['h'] = 12; |
if (!isset($_GET['i'])) $_GET['i'] = 34; |
if (!isset($_GET['s'])) $_GET['s'] = 46; |
switch ( @$_GET['view'] ) { |
default: |
$_GET['view'] = 'calendar_year'; |
case 'calendar_year': |
require_once CALENDAR_ROOT.'Year.php'; |
$c = new Calendar_Year($_GET['y']); |
break; |
case 'calendar_month': |
require_once CALENDAR_ROOT.'Month.php'; |
$c = new Calendar_Month($_GET['y'],$_GET['m']); |
break; |
case 'calendar_day': |
require_once CALENDAR_ROOT.'Day.php'; |
$c = new Calendar_Day($_GET['y'],$_GET['m'],$_GET['d']); |
break; |
case 'calendar_hour': |
require_once CALENDAR_ROOT.'Hour.php'; |
$c = new Calendar_Hour($_GET['y'],$_GET['m'],$_GET['d'],$_GET['h']); |
break; |
case 'calendar_minute': |
require_once CALENDAR_ROOT.'Minute.php'; |
$c = new Calendar_Minute($_GET['y'],$_GET['m'],$_GET['d'],$_GET['h'],$_GET['i']); |
break; |
case 'calendar_second': |
require_once CALENDAR_ROOT.'Second.php'; |
$c = new Calendar_Second($_GET['y'],$_GET['m'],$_GET['d'],$_GET['h'],$_GET['i'],$_GET['s']); |
break; |
} |
echo ( 'Viewing: '.@$_GET['view'].'<br />' ); |
echo ( 'The time is now: '.date('Y M d H:i:s',$c->getTimestamp()).'<br >' ); |
$i = 1; |
echo ( '<h1>First Iteration</h1>' ); |
echo ( '<p>The first iteration is more "expensive", the calendar data |
structures having to be built.</p>' ); |
$start = getmicrotime(); |
$c->build(); |
while ( $e = $c->fetch() ) { |
$class = strtolower(get_class($e)); |
$link ="&y=".$e->thisYear()."&m=".$e->thisMonth()."&d=".$e->thisDay(). |
"&h=".$e->thisHour()."&i=".$e->thisMinute()."&s=".$e->thisSecond(); |
$method = 'this'.str_replace('calendar_','',$class); |
echo ( "<a href=\"".$_SERVER['PHP_SELF']."?view=".$class.$link."\">".$e->{$method}()."</a> : " ); |
if ( ($i % 10) == 0 ) { |
echo ( '<br>' ); |
} |
$i++; |
} |
echo ( '<p><b>Took: '.(getmicrotime()-$start).' seconds</b></p>' ); |
$i = 1; |
echo ( '<h1>Second Iteration</h1>' ); |
echo ( '<p>This second iteration is faster, the data structures |
being re-used</p>' ); |
$start = getmicrotime(); |
while ( $e = $c->fetch() ) { |
$class = strtolower(get_class($e)); |
$link ="&y=".$e->thisYear()."&m=".$e->thisMonth()."&d=".$e->thisDay(). |
"&h=".$e->thisHour()."&i=".$e->thisMinute()."&s=".$e->thisSecond(); |
$method = 'this'.str_replace('calendar_','',$class); |
echo ( "<a href=\"".$_SERVER['PHP_SELF']."?view=".$class.$link."\">".$e->{$method}()."</a> : " ); |
if ( ($i % 10) == 0 ) { |
echo ( '<br>' ); |
} |
$i++; |
} |
echo ( '<p><b>Took: '.(getmicrotime()-$start).' seconds</b></p>' ); |
?> |
/branches/v1.3-critias/bibliotheque/pear/Calendar/docs/examples/2.php |
---|
New file |
0,0 → 1,142 |
<?php |
/** |
* Description: Demonstrates building a calendar for a month using the Week class |
* Uses UnixTs engine |
*/ |
function getmicrotime(){ |
list($usec, $sec) = explode(" ",microtime()); |
return ((float)$usec + (float)$sec); |
} |
$start = getmicrotime(); |
// Force UnixTs engine (default setting) |
define('CALENDAR_ENGINE','UnixTS'); |
if (!@include 'Calendar'.DIRECTORY_SEPARATOR.'Calendar.php') { |
define('CALENDAR_ROOT', '../../'); |
} |
require_once CALENDAR_ROOT.'Month/Weeks.php'; |
require_once CALENDAR_ROOT.'Day.php'; |
// Initialize GET variables if not set |
if (!isset($_GET['y'])) $_GET['y'] = date('Y'); |
if (!isset($_GET['m'])) $_GET['m'] = date('m'); |
if (!isset($_GET['d'])) $_GET['d'] = date('d'); |
// Build a month object |
$Month = new Calendar_Month_Weeks($_GET['y'], $_GET['m']); |
// Create an array of days which are "selected" |
// Used for Week::build() below |
$selectedDays = array ( |
new Calendar_Day($_GET['y'],$_GET['m'], $_GET['d']), |
new Calendar_Day($_GET['y'], 12, 25), |
new Calendar_Day(date('Y'), date('m'), date('d')), |
); |
// Instruct month to build Week objects |
$Month->build(); |
// Construct strings for next/previous links |
$PMonth = $Month->prevMonth('object'); // Get previous month as object |
$prev = $_SERVER['PHP_SELF'].'?y='.$PMonth->thisYear().'&m='.$PMonth->thisMonth().'&d='.$PMonth->thisDay(); |
$NMonth = $Month->nextMonth('object'); |
$next = $_SERVER['PHP_SELF'].'?y='.$NMonth->thisYear().'&m='.$NMonth->thisMonth().'&d='.$NMonth->thisDay(); |
?> |
<!doctype html public "-//W3C//DTD HTML 4.0 Transitional//EN"> |
<html> |
<head> |
<title> Calendar </title> |
<style text="text/css"> |
table { |
background-color: silver; |
} |
caption { |
font-family: verdana; |
font-size: 12px; |
background-color: while; |
} |
.prevMonth { |
font-size: 10px; |
text-align: left; |
} |
.nextMonth { |
font-size: 10px; |
text-align: right; |
} |
th { |
font-family: verdana; |
font-size: 11px; |
color: navy; |
text-align: right; |
} |
td { |
font-family: verdana; |
font-size: 11px; |
text-align: right; |
} |
.selected { |
background-color: yellow; |
} |
.empty { |
color: white; |
} |
</style> |
</head> |
<body> |
<h2>Build with Calendar_Month_Weeks::build() then Calendar_Week::build()</h2> |
<table class="calendar"> |
<caption> |
<?php echo date('F Y', $Month->getTimeStamp()); ?> |
</caption> |
<tr> |
<th>M</th> |
<th>T</th> |
<th>W</th> |
<th>T</th> |
<th>F</th> |
<th>S</th> |
<th>S</th> |
</tr> |
<?php |
while ($Week = $Month->fetch()) { |
echo "<tr>\n"; |
// Build the days in the week, passing the selected days |
$Week->build($selectedDays); |
while ($Day = $Week->fetch()) { |
// Build a link string for each day |
$link = $_SERVER['PHP_SELF']. |
'?y='.$Day->thisYear(). |
'&m='.$Day->thisMonth(). |
'&d='.$Day->thisDay(); |
// Check to see if day is selected |
if ($Day->isSelected()) { |
echo '<td class="selected">'.$Day->thisDay().'</td>'."\n"; |
// Check to see if day is empty |
} else if ($Day->isEmpty()) { |
echo '<td class="empty">'.$Day->thisDay().'</td>'."\n"; |
} else { |
echo '<td><a href="'.$link.'">'.$Day->thisDay().'</a></td>'."\n"; |
} |
} |
echo '</tr>'."\n"; |
} |
?> |
<tr> |
<td> |
<a href="<?php echo $prev; ?>" class="prevMonth"><< </a> |
</td> |
<td colspan="5"> </td> |
<td> |
<a href="<?php echo $next; ?>" class="nextMonth"> >></a> |
</td> |
</tr> |
</table> |
<?php |
echo '<p><b>Took: '.(getmicrotime()-$start).' seconds</b></p>'; |
?> |
</body> |
</html> |
/branches/v1.3-critias/bibliotheque/pear/Calendar/docs/examples/3.php |
---|
New file |
0,0 → 1,134 |
<?php |
/** |
* Description: Performs same behaviour as 2.php but uses Month::buildWeekDays() |
* and is faster |
*/ |
function getmicrotime(){ |
list($usec, $sec) = explode(" ",microtime()); |
return ((float)$usec + (float)$sec); |
} |
$start = getmicrotime(); |
if ( !@include 'Calendar/Calendar.php' ) { |
define('CALENDAR_ROOT','../../'); |
} |
require_once CALENDAR_ROOT.'Month/Weekdays.php'; |
require_once CALENDAR_ROOT.'Day.php'; |
if (!isset($_GET['y'])) $_GET['y'] = date('Y'); |
if (!isset($_GET['m'])) $_GET['m'] = date('m'); |
if (!isset($_GET['d'])) $_GET['d'] = date('d'); |
// Build the month |
$Month = new Calendar_Month_Weekdays($_GET['y'],$_GET['m']); |
// Construct strings for next/previous links |
$PMonth = $Month->prevMonth('object'); // Get previous month as object |
$prev = $_SERVER['PHP_SELF'].'?y='.$PMonth->thisYear().'&m='.$PMonth->thisMonth().'&d='.$PMonth->thisDay(); |
$NMonth = $Month->nextMonth('object'); |
$next = $_SERVER['PHP_SELF'].'?y='.$NMonth->thisYear().'&m='.$NMonth->thisMonth().'&d='.$NMonth->thisDay(); |
?> |
<!doctype html public "-//W3C//DTD HTML 4.0 Transitional//EN"> |
<html> |
<head> |
<title> Calendar </title> |
<style text="text/css"> |
table { |
background-color: silver; |
} |
caption { |
font-family: verdana; |
font-size: 12px; |
background-color: while; |
} |
.prevMonth { |
font-size: 10px; |
text-align: left; |
} |
.nextMonth { |
font-size: 10px; |
text-align: right; |
} |
th { |
font-family: verdana; |
font-size: 11px; |
color: navy; |
text-align: right; |
} |
td { |
font-family: verdana; |
font-size: 11px; |
text-align: right; |
} |
.selected { |
background-color: yellow; |
} |
</style> |
</head> |
<body> |
<?php |
$selectedDays = array ( |
new Calendar_Day($_GET['y'],$_GET['m'],$_GET['d']), |
new Calendar_Day($_GET['y'],12,25), |
); |
// Build the days in the month |
$Month->build($selectedDays); |
?> |
<h2>Built with Calendar_Month_Weekday::build()</h2> |
<table class="calendar"> |
<caption> |
<?php echo ( date('F Y',$Month->getTimeStamp())); ?> |
</caption> |
<tr> |
<th>M</th> |
<th>T</th> |
<th>W</th> |
<th>T</th> |
<th>F</th> |
<th>S</th> |
<th>S</th> |
</tr> |
<?php |
while ( $Day = $Month->fetch() ) { |
// Build a link string for each day |
$link = $_SERVER['PHP_SELF']. |
'?y='.$Day->thisYear(). |
'&m='.$Day->thisMonth(). |
'&d='.$Day->thisDay(); |
// isFirst() to find start of week |
if ( $Day->isFirst() ) |
echo ( "<tr>\n" ); |
if ( $Day->isSelected() ) { |
echo ( "<td class=\"selected\">".$Day->thisDay()."</td>\n" ); |
} else if ( $Day->isEmpty() ) { |
echo ( "<td> </td>\n" ); |
} else { |
echo ( "<td><a href=\"".$link."\">".$Day->thisDay()."</a></td>\n" ); |
} |
// isLast() to find end of week |
if ( $Day->isLast() ) |
echo ( "</tr>\n" ); |
} |
?> |
<tr> |
<td> |
<a href="<?php echo ($prev);?>" class="prevMonth"><< </a> |
</td> |
<td colspan="5"> </td> |
<td> |
<a href="<?php echo ($next);?>" class="nextMonth"> >></a> |
</td> |
</tr> |
</table> |
<?php |
echo ( '<p><b>Took: '.(getmicrotime()-$start).' seconds</b></p>' ); |
?> |
</body> |
</html> |
/branches/v1.3-critias/bibliotheque/pear/Calendar/docs/examples/4.php |
---|
New file |
0,0 → 1,49 |
<?php |
/** |
* Description: shows how to perform validation with PEAR::Calendar |
*/ |
function getmicrotime(){ |
list($usec, $sec) = explode(' ', microtime()); |
return ((float)$usec + (float)$sec); |
} |
$start = getmicrotime(); |
if ( !@include 'Calendar/Calendar.php' ) { |
define('CALENDAR_ROOT', '../../'); |
} |
require_once CALENDAR_ROOT.'Second.php'; |
if (!isset($_GET['y'])) $_GET['y'] = date('Y'); |
if (!isset($_GET['m'])) $_GET['m'] = date('n'); |
if (!isset($_GET['d'])) $_GET['d'] = date('j'); |
if (!isset($_GET['h'])) $_GET['h'] = date('H'); |
if (!isset($_GET['i'])) $_GET['i'] = date('i'); |
if (!isset($_GET['s'])) $_GET['s'] = date('s'); |
$Unit = & new Calendar_Second($_GET['y'], $_GET['m'], $_GET['d'], $_GET['h'], $_GET['i'], $_GET['s']); |
echo '<p><b>Result:</b> '.$Unit->thisYear().'-'.$Unit->thisMonth().'-'.$Unit->thisDay(). |
' '.$Unit->thisHour().':'.$Unit->thisMinute().':'.$Unit->thisSecond(); |
if ($Unit->isValid()) { |
echo ' is valid!</p>'; |
} else { |
$V= & $Unit->getValidator(); |
echo ' is invalid:</p>'; |
while ($error = $V->fetch()) { |
echo $error->toString() .'<br />'; |
} |
} |
?> |
<p>Enter a date / time to validate:</p> |
<form action="<?php echo $_SERVER['PHP_SELF']; ?>" method="get"> |
Year: <input type="text" name="y" value="2039"><br /> |
Month: <input type="text" name="m" value="13"><br /> |
Day: <input type="text" name="d" value="32"><br /> |
Hour: <input type="text" name="h" value="24"><br /> |
Minute: <input type="text" name="i" value="-1"><br /> |
Second: <input type="text" name="s" value="60"><br /> |
<input type="submit" value="Validate"> |
</form> |
<p><b>Note:</b> Error messages can be controlled with the constants <code>CALENDAR_VALUE_TOOSMALL</code> and <code>CALENDAR_VALUE_TOOLARGE</code> - see <code>Calendar_Validator.php</code></p> |
<?php echo '<p><b>Took: '.(getmicrotime()-$start).' seconds</b></p>'; ?> |
/branches/v1.3-critias/bibliotheque/pear/Calendar/docs/examples/11.phps |
---|
New file |
0,0 → 1,109 |
<?php |
/** |
* Description: demonstrates a decorator used to "attach a payload" to a selection |
* to make it available when iterating over calendar children |
*/ |
if ( !@include 'Calendar/Calendar.php' ) { |
define('CALENDAR_ROOT','../../'); |
} |
require_once CALENDAR_ROOT.'Day.php'; |
require_once CALENDAR_ROOT.'Hour.php'; |
require_once CALENDAR_ROOT.'Decorator.php'; |
// Decorator to "attach" functionality to selected hours |
class DiaryEvent extends Calendar_Decorator { |
var $entry; |
function DiaryEvent($calendar) { |
Calendar_Decorator::Calendar_Decorator($calendar); |
} |
function setEntry($entry) { |
$this->entry = $entry; |
} |
function getEntry() { |
return $this->entry; |
} |
} |
// Create a day to view the hours for |
$Day = & new Calendar_Day(2003,10,24); |
// A sample query to get the data for today (NOT ACTUALLY USED HERE) |
$sql = " |
SELECT |
* |
FROM |
diary |
WHERE |
eventtime >= '".$Day->thisDay(TRUE)."' |
AND |
eventtime < '".$Day->nextDay(TRUE)."';"; |
// An array simulating data from a database |
$result = array ( |
array('eventtime'=>mktime(9,0,0,10,24,2003),'entry'=>'Meeting with sales team'), |
array('eventtime'=>mktime(11,0,0,10,24,2003),'entry'=>'Conference call with Widget Inc.'), |
array('eventtime'=>mktime(15,0,0,10,24,2003),'entry'=>'Presentation to board of directors') |
); |
// An array to place selected hours in |
$selection = array(); |
// Loop through the "database result" |
foreach ( $result as $row ) { |
$Hour = new Calendar_Hour(2000,1,1,1); // Create Hour with dummy values |
$Hour->setTimeStamp($row['eventtime']); // Set the real time with setTimeStamp |
// Create the decorator, passing it the Hour |
$DiaryEvent = new DiaryEvent($Hour); |
// Attach the payload |
$DiaryEvent->setEntry($row['entry']); |
// Add the decorator to the selection |
$selection[] = $DiaryEvent; |
} |
// Build the hours in that day, passing the selection |
$Day->build($selection); |
?> |
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> |
<html> |
<head> |
<title> Passing a Selection Payload with a Decorator </title> |
</head> |
<body> |
<h1>Passing a Selection "Payload" using a Decorator</h1> |
<table> |
<caption><b>Your Schedule for <?php echo ( date('D nS F Y',$Day->thisDay(TRUE)) ); ?></b></caption> |
<tr> |
<th width="5%">Time</th> |
<th>Entry</th> |
</tr> |
<?php |
while ( $Hour = & $Day->fetch() ) { |
$hour = $Hour->thisHour(); |
$minute = $Hour->thisMinute(); |
// Office hours only... |
if ( $hour >= 8 && $hour <= 18 ) { |
echo ( "<tr>\n" ); |
echo ( "<td>$hour:$minute</td>\n" ); |
// If the hour is selected, call the decorator method... |
if ( $Hour->isSelected() ) { |
echo ( "<td bgcolor=\"silver\">".$Hour->getEntry()."</td>\n" ); |
} else { |
echo ( "<td> </td>\n" ); |
} |
echo ( "</tr>\n" ); |
} |
} |
?> |
</table> |
<p>The query to fetch this data, with help from PEAR::Calendar, might be;</p> |
<pre> |
<?php echo ( $sql ); ?> |
</pre> |
</body> |
</html> |
/branches/v1.3-critias/bibliotheque/pear/Calendar/docs/examples/5.php |
---|
New file |
0,0 → 1,132 |
<?php |
/** |
* Description: generating elements of a form with PEAR::Calendar, using |
* selections as well as validating the submission |
*/ |
function getmicrotime(){ |
list($usec, $sec) = explode(" ",microtime()); |
return ((float)$usec + (float)$sec); |
} |
$start = getmicrotime(); |
if ( !@include 'Calendar/Calendar.php' ) { |
define('CALENDAR_ROOT','../../'); |
} |
require_once CALENDAR_ROOT.'Year.php'; |
require_once CALENDAR_ROOT.'Month.php'; |
require_once CALENDAR_ROOT.'Day.php'; |
require_once CALENDAR_ROOT.'Hour.php'; |
require_once CALENDAR_ROOT.'Minute.php'; |
require_once CALENDAR_ROOT.'Second.php'; |
// Initialize if not set |
if (!isset($_POST['y'])) $_POST['y'] = date('Y'); |
if (!isset($_POST['m'])) $_POST['m'] = date('n'); |
if (!isset($_POST['d'])) $_POST['d'] = date('j'); |
if (!isset($_POST['h'])) $_POST['h'] = date('H'); |
if (!isset($_POST['i'])) $_POST['i'] = date('i'); |
if (!isset($_POST['s'])) $_POST['s'] = date('s'); |
?> |
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> |
<html> |
<head> |
<title> Select and Update </title> |
</head> |
<body> |
<h1>Select and Update</h1> |
<?php |
if ( isset($_POST['update']) ) { |
$Second = & new Calendar_Second($_POST['y'],$_POST['m'],$_POST['d'],$_POST['h'],$_POST['i'],$_POST['s']); |
if ( !$Second->isValid() ) { |
$V= & $Second->getValidator(); |
echo ('<p>Validation failed:</p>' ); |
while ( $error = $V->fetch() ) { |
echo ( $error->toString() .'<br>' ); |
} |
} else { |
echo ('<p>Validation success.</p>' ); |
echo ( '<p>New timestamp is: '.$Second->getTimeStamp().' which could be used to update a database, for example'); |
} |
} else { |
$Year = new Calendar_Year($_POST['y']); |
$Month = new Calendar_Month($_POST['y'],$_POST['m']); |
$Day = new Calendar_Day($_POST['y'],$_POST['m'],$_POST['d']); |
$Hour = new Calendar_Hour($_POST['y'],$_POST['m'],$_POST['d'],$_POST['h']); |
$Minute = new Calendar_Minute($_POST['y'],$_POST['m'],$_POST['d'],$_POST['h'],$_POST['i']); |
$Second = new Calendar_Second($_POST['y'],$_POST['m'],$_POST['d'],$_POST['h'],$_POST['i'],$_POST['s']); |
?> |
<p><b>Set the alarm clock</p></p> |
<form action="<?php echo ( $_SERVER['PHP_SELF'] ); ?>" method="post"> |
Year: <input type="text" name="y" value="<?php echo ( $_POST['y'] ); ?>" size="4"> |
Month:<select name="m"> |
<?php |
$selection = array($Month); |
$Year->build($selection); |
while ( $Child = & $Year->fetch() ) { |
if ( $Child->isSelected() ) { |
echo ( "<option value=\"".$Child->thisMonth()."\" selected>".$Child->thisMonth()."\n" ); |
} else { |
echo ( "<option value=\"".$Child->thisMonth()."\">".$Child->thisMonth()."\n" ); |
} |
} |
?> |
</select> |
Day:<select name="d"> |
<?php |
$selection = array($Day); |
$Month->build($selection); |
while ( $Child = & $Month->fetch() ) { |
if ( $Child->isSelected() ) { |
echo ( "<option value=\"".$Child->thisDay()."\" selected>".$Child->thisDay()."\n" ); |
} else { |
echo ( "<option value=\"".$Child->thisDay()."\">".$Child->thisDay()."\n" ); |
} |
} |
?> |
</select> |
Hour:<select name="h"> |
<?php |
$selection = array($Hour); |
$Day->build($selection); |
while ( $Child = & $Day->fetch() ) { |
if ( $Child->isSelected() ) { |
echo ( "<option value=\"".$Child->thisHour()."\" selected>".$Child->thisHour()."\n" ); |
} else { |
echo ( "<option value=\"".$Child->thisHour()."\">".$Child->thisHour()."\n" ); |
} |
} |
?> |
</select> |
Minute:<select name="i"> |
<?php |
$selection = array($Minute); |
$Hour->build($selection); |
while ( $Child = & $Hour->fetch() ) { |
if ( $Child->isSelected() ) { |
echo ( "<option value=\"".$Child->thisMinute()."\" selected>".$Child->thisMinute()."\n" ); |
} else { |
echo ( "<option value=\"".$Child->thisMinute()."\">".$Child->thisMinute()."\n" ); |
} |
} |
?> |
</select> |
Second:<select name="s"> |
<?php |
$selection = array($Second); |
$Minute->build($selection); |
while ( $Child = & $Minute->fetch() ) { |
if ( $Child->isSelected() ) { |
echo ( "<option value=\"".$Child->thisSecond()."\" selected>".$Child->thisSecond()."\n" ); |
} else { |
echo ( "<option value=\"".$Child->thisSecond()."\">".$Child->thisSecond()."\n" ); |
} |
} |
?> |
</select> |
<input type="submit" name="update" value="Set Alarm"><br> |
<?php |
} |
?> |
<?php echo ( '<p><b>Took: '.(getmicrotime()-$start).' seconds</b></p>' ); ?> |
</body> |
</html> |
/branches/v1.3-critias/bibliotheque/pear/Calendar/docs/examples/21.phps |
---|
New file |
0,0 → 1,139 |
<?php |
/** |
* Description: a complete year with numeric week numbers |
*/ |
function getmicrotime(){ |
list($usec, $sec) = explode(" ",microtime()); |
return ((float)$usec + (float)$sec); |
} |
$start = getmicrotime(); |
if (!@include 'Calendar/Calendar.php') { |
define('CALENDAR_ROOT', '../../'); |
} |
require_once CALENDAR_ROOT.'Year.php'; |
require_once CALENDAR_ROOT.'Month/Weeks.php'; |
define ('CALENDAR_MONTH_STATE',CALENDAR_USE_MONTH_WEEKS); |
if (!isset($_GET['year'])) $_GET['year'] = date('Y'); |
$week_types = array( |
'n_in_year', |
'n_in_month', |
); |
if (!isset($_GET['week_type']) || !in_array($_GET['week_type'],$week_types) ) { |
$_GET['week_type'] = 'n_in_year'; |
} |
$Year = new Calendar_Year($_GET['year']); |
$Year->build(); |
?> |
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> |
<html> |
<head> |
<title> <?php echo $Year->thisYear(); ?> </title> |
<style type="text/css"> |
body { |
font-family: Georgia, serif; |
} |
caption.year { |
font-weight: bold; |
font-size: 120%; |
font-color: navy; |
} |
caption.month { |
font-size: 110%; |
font-color: navy; |
} |
table.month { |
border: thin groove #800080 |
} |
tr { |
vertical-align: top; |
} |
th, td { |
text-align: right; |
font-size: 70%; |
} |
#prev { |
float: left; |
font-size: 70%; |
} |
#next { |
float: right; |
font-size: 70%; |
} |
#week_type { |
float: none; |
font-size: 70%; |
} |
.weekNumbers { |
background-color: #e5e5f5; |
padding-right: 3pt; |
} |
</style> |
</head> |
<body> |
<table> |
<caption class="year"> |
<?php echo $Year->thisYear(); ?> |
<div id="next"> |
<a href="?year=<?php echo $Year->nextYear(); ?>&week_type=<?php echo $_GET['week_type']; ?>">>></a> |
</div> |
<div id="prev"> |
<a href="?year=<?php echo $Year->prevYear(); ?>&week_type=<?php echo $_GET['week_type']; ?>"><<</a> |
</div> |
<div id="week_type"> |
<a href="?year=<?php echo $Year->thisYear(); ?>&week_type=n_in_year">Weeks by Year</a> : |
<a href="?year=<?php echo $Year->thisYear(); ?>&week_type=n_in_month">Weeks by Month</a> |
</div> |
</caption> |
<?php |
$i = 0; |
while ($Month = $Year->fetch()) { |
switch ($i) { |
case 0: |
echo "<tr>\n"; |
break; |
case 3: |
case 6: |
case 9: |
echo "</tr>\n<tr>\n"; |
break; |
case 12: |
echo "</tr>\n"; |
break; |
} |
echo "<td>\n<table class=\"month\">\n"; |
echo '<caption class="month">'.date('F', $Month->thisMonth(TRUE)).'</caption>'; |
echo '<colgroup><col class="weekNumbers"><col span="7"></colgroup>'."\n"; |
echo "<tr>\n<th>Week</th><th>M</th><th>T</th><th>W</th><th>T</th><th>F</th><th>S</th><th>S</th>\n</tr>"; |
$Month->build(); |
while ($Week = $Month->fetch()) { |
echo "<tr>\n"; |
echo '<td>'.$Week->thisWeek($_GET['week_type'])."</td>\n"; |
$Week->build(); |
while ($Day = $Week->fetch()) { |
if ($Day->isEmpty()) { |
echo "<td> </td>\n"; |
} else { |
echo "<td>".$Day->thisDay()."</td>\n"; |
} |
} |
} |
echo "</table>\n</td>\n"; |
$i++; |
} |
?> |
</table> |
<p>Took: <?php echo ((getmicrotime()-$start)); ?></p> |
</body> |
</html> |
/branches/v1.3-critias/bibliotheque/pear/Calendar/docs/examples/6.php |
---|
New file |
0,0 → 1,210 |
<?php |
/** |
* Description: A "personal planner" with some WML for fun |
* Note this is done the stupid way - a giant if/else for WML or HTML |
* could be greatly simplified with some HTML/WML rendering classes... |
*/ |
function getmicrotime(){ |
list($usec, $sec) = explode(" ",microtime()); |
return ((float)$usec + (float)$sec); |
} |
$start = getmicrotime(); |
if ( !@include 'Calendar/Calendar.php' ) { |
define('CALENDAR_ROOT','../../'); |
} |
require_once CALENDAR_ROOT.'Month/Weekdays.php'; |
require_once CALENDAR_ROOT.'Day.php'; |
if (!isset($_GET['y'])) $_GET['y'] = date('Y'); |
if (!isset($_GET['m'])) $_GET['m'] = date('n'); |
if (!isset($_GET['d'])) $_GET['d'] = date('j'); |
$Month = & new Calendar_Month_Weekdays($_GET['y'],$_GET['m']); |
$Day = & new Calendar_Day($_GET['y'],$_GET['m'],$_GET['d']); |
$selection = array($Day); |
#-----------------------------------------------------------------------------# |
if ( isset($_GET['mime']) && $_GET['mime']=='wml' ) { |
header ('Content-Type: text/vnd.wap.wml'); |
echo ( '<?xml version="1.0"?>' ); |
?> |
<!DOCTYPE wml PUBLIC "-//WAPFORUM//DTD WML 1.1//EN" "http://www.wapforum.org/DTD/wml_1.1.xml"> |
<wml> |
<big><strong>Personal Planner Rendered with WML</strong></big> |
<?php |
if ( isset($_GET['viewday']) ) { |
?> |
<p><strong>Viewing <?php echo ( date('l, jS of F, Y',$Day->getTimeStamp()) ); ?></strong></p> |
<p> |
<anchor> |
Back to Month View |
<go href="<?php |
echo ( "?y=".$Day->thisYear()."&m=". |
$Day->thisMonth()."&d=".$Day->thisDay()."&mime=wml" ); |
?>"/> |
</anchor> |
</p> |
<table> |
<?php |
$Day->build(); |
while ( $Hour = & $Day->fetch() ) { |
echo ( "<tr>\n" ); |
echo ( "<td>".date('g a',$Hour->getTimeStamp())."</td><td>Free time!</td>\n" ); |
echo ( "</tr>\n" ); |
} |
?> |
</table> |
<?php |
} else { |
?> |
<p><strong><?php echo ( date('F Y',$Month->getTimeStamp()) ); ?></strong></p> |
<table> |
<tr> |
<td>M</td><td>T</td><td>W</td><td>T</td><td>F</td><td>S</td><td>S</td> |
</tr> |
<?php |
$Month->build($selection); |
while ( $Day = $Month->fetch() ) { |
if ( $Day->isFirst() ) { |
echo ( "<tr>\n" ); |
} |
if ( $Day->isEmpty() ) { |
echo ( "<td></td>\n" ); |
} else if ( $Day->isSelected() ) { |
echo ( "<td><anchor><strong><u>".$Day->thisDay()."</u></strong>\n<go href=\"".$_SERVER['PHP_SELF']."?viewday=true&y=". |
$Day->thisYear()."&m=".$Day->thisMonth()."&d=".$Day->thisDay(). |
"&mime=wml\" />\n</anchor></td>\n" ); |
} else { |
echo ( "<td><anchor>".$Day->thisDay()."\n<go href=\"?viewday=true&y=". |
$Day->thisYear()."&m=".$Day->thisMonth()."&d=".$Day->thisDay(). |
"&mime=wml\" /></anchor></td>\n" ); |
} |
if ( $Day->isLast() ) { |
echo ( "</tr>\n" ); |
} |
} |
?> |
<tr> |
<td> |
<anchor> |
<< |
<go href="<?php |
echo ( "?y=".$Month->thisYear()."&m=". |
$Month->prevMonth()."&d=".$Month->thisDay()."&mime=wml" ); |
?>"/> |
</anchor> |
</td> |
<td></td><td></td><td></td><td></td><td></td> |
<td> |
<anchor> |
>> |
<go href="<?php |
echo ( "?y=".$Month->thisYear()."&m=". |
$Month->nextMonth()."&d=".$Month->thisDay()."&mime=wml" ); |
?>"/> |
</anchor> |
</td> |
</tr> |
</table> |
<?php |
} |
?> |
<p><a href="<?php echo ( $_SERVER['PHP_SELF'] ); ?>">Back to HTML</a></p> |
<?php echo ( '<p>Took: '.(getmicrotime()-$start).' seconds</p>' ); ?> |
</wml> |
<?php |
#-----------------------------------------------------------------------------# |
} else { |
?> |
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> |
<html> |
<head> |
<title> HTML (+WML) Personal Planner </title> |
</head> |
<body> |
<h1>Personal Planner Rendered with HTML</h1> |
<p>To view in WML, click <a href="<?php echo ( $_SERVER['PHP_SELF'] ); ?>?mime=wml">here</a> or place a ?mime=wml at the end of any URL. |
Note that <a href="http://www.opera.com/download">Opera</a> supports WML natively and Mozilla / Firefox has the WMLBrowser |
plugin: <a href="http://wmlbrowser.mozdev.org">wmlbrowser.mozdev.org</a></p> |
<?php |
if ( isset($_GET['viewday']) ) { |
?> |
<p><strong>Viewing <?php echo ( date('l, jS of F, Y',$Day->getTimeStamp()) ); ?></strong></p> |
<p> |
<anchor> |
<a href="<?php |
echo ( "?y=".$Day->thisYear()."&m=". |
$Day->thisMonth()."&d=".$Day->thisDay()); |
?>">Back to Month View</a> |
</p> |
<table> |
<?php |
$Day->build(); |
while ( $Hour = & $Day->fetch() ) { |
echo ( "<tr>\n" ); |
echo ( "<td>".date('g a',$Hour->getTimeStamp())."</td><td>Free time!</td>\n" ); |
echo ( "</tr>\n" ); |
} |
?> |
</table> |
<?php |
} else { |
?> |
<p><strong><?php echo ( date('F Y',$Month->getTimeStamp()) ); ?></strong></p> |
<table> |
<tr> |
<td>M</td><td>T</td><td>W</td><td>T</td><td>F</td><td>S</td><td>S</td> |
</tr> |
<?php |
$Month->build($selection); |
while ( $Day = $Month->fetch() ) { |
if ( $Day->isFirst() ) { |
echo ( "<tr>\n" ); |
} |
if ( $Day->isEmpty() ) { |
echo ( "<td></td>\n" ); |
} else if ( $Day->isSelected() ) { |
echo ( "<td><a href=\"".$_SERVER['PHP_SELF']."?viewday=true&y=". |
$Day->thisYear()."&m=".$Day->thisMonth()."&d=".$Day->thisDay(). |
"&wml\"><strong><u>".$Day->thisDay()."</u></strong></a></td>\n" ); |
} else { |
echo ( "<td><a href=\"".$_SERVER['PHP_SELF']."?viewday=true&y=". |
$Day->thisYear()."&m=".$Day->thisMonth()."&d=".$Day->thisDay(). |
"\">".$Day->thisDay()."</a></td>\n" ); |
} |
if ( $Day->isLast() ) { |
echo ( "</tr>\n" ); |
} |
} |
?> |
<tr> |
<td> |
<a href="<?php |
echo ( "?y=".$Month->thisYear()."&m=". |
$Month->prevMonth()."&d=".$Month->thisDay() ); |
?>"> |
<<</a> |
</td> |
<td></td><td></td><td></td><td></td><td></td> |
<td> |
<a href="<?php |
echo ( "?y=".$Month->thisYear()."&m=". |
$Month->nextMonth()."&d=".$Month->thisDay() ); |
?>">>></a> |
</td> |
</tr> |
</table> |
<?php |
} |
?> |
<?php echo ( '<p><b>Took: '.(getmicrotime()-$start).' seconds</b></p>' ); ?> |
</body> |
</html> |
<?php |
} |
?> |
/branches/v1.3-critias/bibliotheque/pear/Calendar/docs/Readme |
---|
New file |
0,0 → 1,3 |
Readme |
See the PEAR manual at http://pear.php.net/manual/en/package.datetime.calendar.php for details. |
/branches/v1.3-critias/bibliotheque/pear/Calendar/Factory.php |
---|
New file |
0,0 → 1,145 |
<?php |
/* vim: set expandtab tabstop=4 shiftwidth=4: */ |
// |
// +----------------------------------------------------------------------+ |
// | PHP Version 4 | |
// +----------------------------------------------------------------------+ |
// | Copyright (c) 1997-2002 The PHP Group | |
// +----------------------------------------------------------------------+ |
// | This source file is subject to version 2.02 of the PHP license, | |
// | that is bundled with this package in the file LICENSE, and is | |
// | available at through the world-wide-web at | |
// | http://www.php.net/license/3_0.txt. | |
// | If you did not receive a copy of the PHP license and are unable to | |
// | obtain it through the world-wide-web, please send a note to | |
// | license@php.net so we can mail you a copy immediately. | |
// +----------------------------------------------------------------------+ |
// | Authors: Harry Fuecks <hfuecks@phppatterns.com> | |
// | Lorenzo Alberton <l dot alberton at quipo dot it> | |
// +----------------------------------------------------------------------+ |
// |
// $Id: Factory.php,v 1.3 2005/10/22 10:08:47 quipo Exp $ |
// |
/** |
* @package Calendar |
* @version $Id: Factory.php,v 1.3 2005/10/22 10:08:47 quipo Exp $ |
*/ |
/** |
* Allows Calendar include path to be redefined |
* @ignore |
*/ |
if (!defined('CALENDAR_ROOT')) { |
define('CALENDAR_ROOT', 'Calendar'.DIRECTORY_SEPARATOR); |
} |
/** |
* Load Calendar base class |
*/ |
require_once CALENDAR_ROOT.'Calendar.php'; |
/** |
* Contains a factory method to return a Singleton instance of a class |
* implementing the Calendar_Engine_Interface.<br> |
* For Month objects, to control type of month returned, use CALENDAR_MONTH_STATE |
* constact e.g.; |
* <code> |
* require_once 'Calendar/Factory.php'; |
* define ('CALENDAR_MONTH_STATE',CALENDAR_USE_MONTH_WEEKDAYS); // Use Calendar_Month_Weekdays |
* // define ('CALENDAR_MONTH_STATE',CALENDAR_USE_MONTH_WEEKS); // Use Calendar_Month_Weeks |
* // define ('CALENDAR_MONTH_STATE',CALENDAR_USE_MONTH); // Use Calendar_Month |
* </code> |
* It defaults to building Calendar_Month objects.<br> |
* Use the constract CALENDAR_FIRST_DAY_OF_WEEK to control the first day of the week |
* for Month or Week objects (e.g. 0 = Sunday, 6 = Saturday) |
* @package Calendar |
* @access protected |
*/ |
class Calendar_Factory |
{ |
/** |
* Creates a calendar object given the type and units |
* @param string class of calendar object to create |
* @param int year |
* @param int month |
* @param int day |
* @param int hour |
* @param int minute |
* @param int second |
* @return object subclass of Calendar |
* @access public |
* @static |
*/ |
function create($type, $y = 2000, $m = 1, $d = 1, $h = 0, $i = 0, $s = 0) |
{ |
$firstDay = defined('CALENDAR_FIRST_DAY_OF_WEEK') ? CALENDAR_FIRST_DAY_OF_WEEK : 1; |
switch ($type) { |
case 'Day': |
require_once CALENDAR_ROOT.'Day.php'; |
return new Calendar_Day($y,$m,$d); |
case 'Month': |
// Set default state for which month type to build |
if (!defined('CALENDAR_MONTH_STATE')) { |
define('CALENDAR_MONTH_STATE', CALENDAR_USE_MONTH); |
} |
switch (CALENDAR_MONTH_STATE) { |
case CALENDAR_USE_MONTH_WEEKDAYS: |
require_once CALENDAR_ROOT.'Month/Weekdays.php'; |
$class = 'Calendar_Month_Weekdays'; |
break; |
case CALENDAR_USE_MONTH_WEEKS: |
require_once CALENDAR_ROOT.'Month/Weeks.php'; |
$class = 'Calendar_Month_Weeks'; |
break; |
case CALENDAR_USE_MONTH: |
default: |
require_once CALENDAR_ROOT.'Month.php'; |
$class = 'Calendar_Month'; |
break; |
} |
return new $class($y, $m, $firstDay); |
case 'Week': |
require_once CALENDAR_ROOT.'Week.php'; |
return new Calendar_Week($y, $m, $d, $firstDay); |
case 'Hour': |
require_once CALENDAR_ROOT.'Hour.php'; |
return new Calendar_Hour($y, $m, $d, $h); |
case 'Minute': |
require_once CALENDAR_ROOT.'Minute.php'; |
return new Calendar_Minute($y, $m, $d, $h, $i); |
case 'Second': |
require_once CALENDAR_ROOT.'Second.php'; |
return new Calendar_Second($y,$m,$d,$h,$i,$s); |
case 'Year': |
require_once CALENDAR_ROOT.'Year.php'; |
return new Calendar_Year($y); |
default: |
require_once 'PEAR.php'; |
PEAR::raiseError( |
'Calendar_Factory::create() unrecognised type: '.$type, null, PEAR_ERROR_TRIGGER, |
E_USER_NOTICE, 'Calendar_Factory::create()'); |
return false; |
} |
} |
/** |
* Creates an instance of a calendar object, given a type and timestamp |
* @param string type of object to create |
* @param mixed timestamp (depending on Calendar engine being used) |
* @return object subclass of Calendar |
* @access public |
* @static |
*/ |
function & createByTimestamp($type, $stamp) |
{ |
$cE = & Calendar_Engine_Factory::getEngine(); |
$y = $cE->stampToYear($stamp); |
$m = $cE->stampToMonth($stamp); |
$d = $cE->stampToDay($stamp); |
$h = $cE->stampToHour($stamp); |
$i = $cE->stampToMinute($stamp); |
$s = $cE->stampToSecond($stamp); |
$cal = Calendar_Factory::create($type, $y, $m, $d, $h, $i, $s); |
return $cal; |
} |
} |
?> |
/branches/v1.3-critias/bibliotheque/pear/Calendar/Calendar.php |
---|
New file |
0,0 → 1,685 |
<?php |
/* vim: set expandtab tabstop=4 shiftwidth=4: */ |
// |
// +----------------------------------------------------------------------+ |
// | PHP Version 4 | |
// +----------------------------------------------------------------------+ |
// | Copyright (c) 1997-2002 The PHP Group | |
// +----------------------------------------------------------------------+ |
// | This source file is subject to version 2.02 of the PHP license, | |
// | that is bundled with this package in the file LICENSE, and is | |
// | available at through the world-wide-web at | |
// | http://www.php.net/license/3_0.txt. | |
// | If you did not receive a copy of the PHP license and are unable to | |
// | obtain it through the world-wide-web, please send a note to | |
// | license@php.net so we can mail you a copy immediately. | |
// +----------------------------------------------------------------------+ |
// | Authors: Harry Fuecks <hfuecks@phppatterns.com> | |
// | Lorenzo Alberton <l dot alberton at quipo dot it> | |
// +----------------------------------------------------------------------+ |
// |
// $Id: Calendar.php,v 1.3 2005/10/22 10:07:11 quipo Exp $ |
// |
/** |
* @package Calendar |
* @version $Id: Calendar.php,v 1.3 2005/10/22 10:07:11 quipo Exp $ |
*/ |
/** |
* Allows Calendar include path to be redefined |
*/ |
if (!defined('CALENDAR_ROOT')) { |
define('CALENDAR_ROOT', 'Calendar'.DIRECTORY_SEPARATOR); |
} |
/** |
* Constant which defines the calculation engine to use |
*/ |
if (!defined('CALENDAR_ENGINE')) { |
define('CALENDAR_ENGINE', 'UnixTS'); |
} |
/** |
* Define Calendar Month states |
*/ |
define('CALENDAR_USE_MONTH', 1); |
define('CALENDAR_USE_MONTH_WEEKDAYS', 2); |
define('CALENDAR_USE_MONTH_WEEKS', 3); |
/** |
* Contains a factory method to return a Singleton instance of a class |
* implementing the Calendar_Engine_Interface.<br> |
* <b>Note:</b> this class must be modified to "register" alternative |
* Calendar_Engines. The engine used can be controlled with the constant |
* CALENDAR_ENGINE |
* @see Calendar_Engine_Interface |
* @package Calendar |
* @access protected |
*/ |
class Calendar_Engine_Factory |
{ |
/** |
* Returns an instance of the engine |
* @return object instance of a calendar calculation engine |
* @access protected |
*/ |
function & getEngine() |
{ |
static $engine = false; |
switch (CALENDAR_ENGINE) { |
case 'PearDate': |
$class = 'Calendar_Engine_PearDate'; |
break; |
case 'UnixTS': |
default: |
$class = 'Calendar_Engine_UnixTS'; |
break; |
} |
if (!$engine) { |
if (!class_exists($class)) { |
require_once CALENDAR_ROOT.'Engine'.DIRECTORY_SEPARATOR.CALENDAR_ENGINE.'.php'; |
} |
$engine = new $class; |
} |
return $engine; |
} |
} |
/** |
* Base class for Calendar API. This class should not be instantiated |
* directly. |
* @abstract |
* @package Calendar |
*/ |
class Calendar |
{ |
/** |
* Instance of class implementing calendar engine interface |
* @var object |
* @access private |
*/ |
var $cE; |
/** |
* Instance of Calendar_Validator (lazy initialized when isValid() or |
* getValidor() is called |
* @var Calendar_Validator |
* @access private |
*/ |
var $validator; |
/** |
* Year for this calendar object e.g. 2003 |
* @access private |
* @var int |
*/ |
var $year; |
/** |
* Month for this calendar object e.g. 9 |
* @access private |
* @var int |
*/ |
var $month; |
/** |
* Day of month for this calendar object e.g. 23 |
* @access private |
* @var int |
*/ |
var $day; |
/** |
* Hour of day for this calendar object e.g. 13 |
* @access private |
* @var int |
*/ |
var $hour; |
/** |
* Minute of hour this calendar object e.g. 46 |
* @access private |
* @var int |
*/ |
var $minute; |
/** |
* Second of minute this calendar object e.g. 34 |
* @access private |
* @var int |
*/ |
var $second; |
/** |
* Marks this calendar object as selected (e.g. 'today') |
* @access private |
* @var boolean |
*/ |
var $selected = false; |
/** |
* Collection of child calendar objects created from subclasses |
* of Calendar. Type depends on the object which created them. |
* @access private |
* @var array |
*/ |
var $children = array(); |
/** |
* Constructs the Calendar |
* @param int year |
* @param int month |
* @param int day |
* @param int hour |
* @param int minute |
* @param int second |
* @access protected |
*/ |
function Calendar($y = 2000, $m = 1, $d = 1, $h = 0, $i = 0, $s = 0) |
{ |
static $cE = null; |
if (!isset($cE)) { |
$cE = & Calendar_Engine_Factory::getEngine(); |
} |
$this->cE = & $cE; |
$this->year = (int)$y; |
$this->month = (int)$m; |
$this->day = (int)$d; |
$this->hour = (int)$h; |
$this->minute = (int)$i; |
$this->second = (int)$s; |
} |
/** |
* Defines the calendar by a timestamp (Unix or ISO-8601), replacing values |
* passed to the constructor |
* @param int|string Unix or ISO-8601 timestamp |
* @return void |
* @access public |
*/ |
function setTimestamp($ts) |
{ |
$this->year = $this->cE->stampToYear($ts); |
$this->month = $this->cE->stampToMonth($ts); |
$this->day = $this->cE->stampToDay($ts); |
$this->hour = $this->cE->stampToHour($ts); |
$this->minute = $this->cE->stampToMinute($ts); |
$this->second = $this->cE->stampToSecond($ts); |
} |
/** |
* Returns a timestamp from the current date / time values. Format of |
* timestamp depends on Calendar_Engine implementation being used |
* @return int|string timestamp |
* @access public |
*/ |
function getTimestamp() |
{ |
return $this->cE->dateToStamp( |
$this->year, $this->month, $this->day, |
$this->hour, $this->minute, $this->second); |
} |
/** |
* Defines calendar object as selected (e.g. for today) |
* @param boolean state whether Calendar subclass |
* @return void |
* @access public |
*/ |
function setSelected($state = true) |
{ |
$this->selected = $state; |
} |
/** |
* True if the calendar subclass object is selected (e.g. today) |
* @return boolean |
* @access public |
*/ |
function isSelected() |
{ |
return $this->selected; |
} |
/** |
* Adjusts the date (helper method) |
* @return void |
* @access public |
*/ |
function adjust() |
{ |
$stamp = $this->getTimeStamp(); |
$this->year = $this->cE->stampToYear($stamp); |
$this->month = $this->cE->stampToMonth($stamp); |
$this->day = $this->cE->stampToDay($stamp); |
$this->hour = $this->cE->stampToHour($stamp); |
$this->minute = $this->cE->stampToMinute($stamp); |
$this->second = $this->cE->stampToSecond($stamp); |
} |
/** |
* Returns the date as an associative array (helper method) |
* @param mixed timestamp (leave empty for current timestamp) |
* @return array |
* @access public |
*/ |
function toArray($stamp=null) |
{ |
if (is_null($stamp)) { |
$stamp = $this->getTimeStamp(); |
} |
return array( |
'year' => $this->cE->stampToYear($stamp), |
'month' => $this->cE->stampToMonth($stamp), |
'day' => $this->cE->stampToDay($stamp), |
'hour' => $this->cE->stampToHour($stamp), |
'minute' => $this->cE->stampToMinute($stamp), |
'second' => $this->cE->stampToSecond($stamp) |
); |
} |
/** |
* Returns the value as an associative array (helper method) |
* @param string type of date object that return value represents |
* @param string $format ['int' | 'array' | 'timestamp' | 'object'] |
* @param mixed timestamp (depending on Calendar engine being used) |
* @param int integer default value (i.e. give me the answer quick) |
* @return mixed |
* @access private |
*/ |
function returnValue($returnType, $format, $stamp, $default) |
{ |
switch (strtolower($format)) { |
case 'int': |
return $default; |
case 'array': |
return $this->toArray($stamp); |
break; |
case 'object': |
require_once CALENDAR_ROOT.'Factory.php'; |
return Calendar_Factory::createByTimestamp($returnType,$stamp); |
break; |
case 'timestamp': |
default: |
return $stamp; |
break; |
} |
} |
/** |
* Abstract method for building the children of a calendar object. |
* Implemented by Calendar subclasses |
* @param array containing Calendar objects to select (optional) |
* @return boolean |
* @access public |
* @abstract |
*/ |
function build($sDates = array()) |
{ |
require_once 'PEAR.php'; |
PEAR::raiseError( |
'Calendar::build is abstract', null, PEAR_ERROR_TRIGGER, |
E_USER_NOTICE, 'Calendar::build()'); |
return false; |
} |
/** |
* Abstract method for selected data objects called from build |
* @param array |
* @return boolean |
* @access public |
* @abstract |
*/ |
function setSelection($sDates) |
{ |
require_once 'PEAR.php'; |
PEAR::raiseError( |
'Calendar::setSelection is abstract', null, PEAR_ERROR_TRIGGER, |
E_USER_NOTICE, 'Calendar::setSelection()'); |
return false; |
} |
/** |
* Iterator method for fetching child Calendar subclass objects |
* (e.g. a minute from an hour object). On reaching the end of |
* the collection, returns false and resets the collection for |
* further iteratations. |
* @return mixed either an object subclass of Calendar or false |
* @access public |
*/ |
function fetch() |
{ |
$child = each($this->children); |
if ($child) { |
return $child['value']; |
} else { |
reset($this->children); |
return false; |
} |
} |
/** |
* Fetches all child from the current collection of children |
* @return array |
* @access public |
*/ |
function fetchAll() |
{ |
return $this->children; |
} |
/** |
* Get the number Calendar subclass objects stored in the internal |
* collection. |
* @return int |
* @access public |
*/ |
function size() |
{ |
return count($this->children); |
} |
/** |
* Determine whether this date is valid, with the bounds determined by |
* the Calendar_Engine. The call is passed on to |
* Calendar_Validator::isValid |
* @return boolean |
* @access public |
*/ |
function isValid() |
{ |
$validator = & $this->getValidator(); |
return $validator->isValid(); |
} |
/** |
* Returns an instance of Calendar_Validator |
* @return Calendar_Validator |
* @access public |
*/ |
function & getValidator() |
{ |
if (!isset($this->validator)) { |
require_once CALENDAR_ROOT.'Validator.php'; |
$this->validator = new Calendar_Validator($this); |
} |
return $this->validator; |
} |
/** |
* Returns a reference to the current Calendar_Engine being used. Useful |
* for Calendar_Table_Helper and Calendar_Validator |
* @return object implementing Calendar_Engine_Inteface |
* @access protected |
*/ |
function & getEngine() |
{ |
return $this->cE; |
} |
/** |
* Set the CALENDAR_FIRST_DAY_OF_WEEK constant to the $firstDay value |
* if the constant is not set yet. |
* @throws E_USER_WARNING this method throws a WARNING if the |
* CALENDAR_FIRST_DAY_OF_WEEK constant is already defined and |
* the $firstDay parameter is set to a different value |
* @param integer $firstDay first day of the week (0=sunday, 1=monday, ...) |
* @return integer |
* @access protected |
*/ |
function defineFirstDayOfWeek($firstDay = null) |
{ |
if (defined('CALENDAR_FIRST_DAY_OF_WEEK')) { |
if (!is_null($firstDay) && ($firstDay != CALENDAR_FIRST_DAY_OF_WEEK)) { |
$msg = 'CALENDAR_FIRST_DAY_OF_WEEK constant already defined.' |
.' The $firstDay parameter will be ignored.'; |
trigger_error($msg, E_USER_WARNING); |
} |
return CALENDAR_FIRST_DAY_OF_WEEK; |
} |
if (is_null($firstDay)) { |
$firstDay = $this->cE->getFirstDayOfWeek( |
$this->thisYear(), |
$this->thisMonth(), |
$this->thisDay() |
); |
} |
define ('CALENDAR_FIRST_DAY_OF_WEEK', $firstDay); |
return CALENDAR_FIRST_DAY_OF_WEEK; |
} |
/** |
* Returns the value for the previous year |
* @param string return value format ['int' | 'timestamp' | 'object' | 'array'] |
* @return int e.g. 2002 or timestamp |
* @access public |
*/ |
function prevYear($format = 'int') |
{ |
$ts = $this->cE->dateToStamp($this->year-1, 1, 1, 0, 0, 0); |
return $this->returnValue('Year', $format, $ts, $this->year-1); |
} |
/** |
* Returns the value for this year |
* @param string return value format ['int' | 'timestamp' | 'object' | 'array'] |
* @return int e.g. 2003 or timestamp |
* @access public |
*/ |
function thisYear($format = 'int') |
{ |
$ts = $this->cE->dateToStamp($this->year, 1, 1, 0, 0, 0); |
return $this->returnValue('Year', $format, $ts, $this->year); |
} |
/** |
* Returns the value for next year |
* @param string return value format ['int' | 'timestamp' | 'object' | 'array'] |
* @return int e.g. 2004 or timestamp |
* @access public |
*/ |
function nextYear($format = 'int') |
{ |
$ts = $this->cE->dateToStamp($this->year+1, 1, 1, 0, 0, 0); |
return $this->returnValue('Year', $format, $ts, $this->year+1); |
} |
/** |
* Returns the value for the previous month |
* @param string return value format ['int' | 'timestamp' | 'object' | 'array'] |
* @return int e.g. 4 or Unix timestamp |
* @access public |
*/ |
function prevMonth($format = 'int') |
{ |
$ts = $this->cE->dateToStamp($this->year, $this->month-1, 1, 0, 0, 0); |
return $this->returnValue('Month', $format, $ts, $this->cE->stampToMonth($ts)); |
} |
/** |
* Returns the value for this month |
* @param string return value format ['int' | 'timestamp' | 'object' | 'array'] |
* @return int e.g. 5 or timestamp |
* @access public |
*/ |
function thisMonth($format = 'int') |
{ |
$ts = $this->cE->dateToStamp($this->year, $this->month, 1, 0, 0, 0); |
return $this->returnValue('Month', $format, $ts, $this->month); |
} |
/** |
* Returns the value for next month |
* @param string return value format ['int' | 'timestamp' | 'object' | 'array'] |
* @return int e.g. 6 or timestamp |
* @access public |
*/ |
function nextMonth($format = 'int') |
{ |
$ts = $this->cE->dateToStamp($this->year, $this->month+1, 1, 0, 0, 0); |
return $this->returnValue('Month', $format, $ts, $this->cE->stampToMonth($ts)); |
} |
/** |
* Returns the value for the previous day |
* @param string return value format ['int' | 'timestamp' | 'object' | 'array'] |
* @return int e.g. 10 or timestamp |
* @access public |
*/ |
function prevDay($format = 'int') |
{ |
$ts = $this->cE->dateToStamp( |
$this->year, $this->month, $this->day-1, 0, 0, 0); |
return $this->returnValue('Day', $format, $ts, $this->cE->stampToDay($ts)); |
} |
/** |
* Returns the value for this day |
* @param string return value format ['int' | 'timestamp' | 'object' | 'array'] |
* @return int e.g. 11 or timestamp |
* @access public |
*/ |
function thisDay($format = 'int') |
{ |
$ts = $this->cE->dateToStamp( |
$this->year, $this->month, $this->day, 0, 0, 0); |
return $this->returnValue('Day', $format, $ts, $this->day); |
} |
/** |
* Returns the value for the next day |
* @param string return value format ['int' | 'timestamp' | 'object' | 'array'] |
* @return int e.g. 12 or timestamp |
* @access public |
*/ |
function nextDay($format = 'int') |
{ |
$ts = $this->cE->dateToStamp( |
$this->year, $this->month, $this->day+1, 0, 0, 0); |
return $this->returnValue('Day', $format, $ts, $this->cE->stampToDay($ts)); |
} |
/** |
* Returns the value for the previous hour |
* @param string return value format ['int' | 'timestamp' | 'object' | 'array'] |
* @return int e.g. 13 or timestamp |
* @access public |
*/ |
function prevHour($format = 'int') |
{ |
$ts = $this->cE->dateToStamp( |
$this->year, $this->month, $this->day, $this->hour-1, 0, 0); |
return $this->returnValue('Hour', $format, $ts, $this->cE->stampToHour($ts)); |
} |
/** |
* Returns the value for this hour |
* @param string return value format ['int' | 'timestamp' | 'object' | 'array'] |
* @return int e.g. 14 or timestamp |
* @access public |
*/ |
function thisHour($format = 'int') |
{ |
$ts = $this->cE->dateToStamp( |
$this->year, $this->month, $this->day, $this->hour, 0, 0); |
return $this->returnValue('Hour', $format, $ts, $this->hour); |
} |
/** |
* Returns the value for the next hour |
* @param string return value format ['int' | 'timestamp' | 'object' | 'array'] |
* @return int e.g. 14 or timestamp |
* @access public |
*/ |
function nextHour($format = 'int') |
{ |
$ts = $this->cE->dateToStamp( |
$this->year, $this->month, $this->day, $this->hour+1, 0, 0); |
return $this->returnValue('Hour', $format, $ts, $this->cE->stampToHour($ts)); |
} |
/** |
* Returns the value for the previous minute |
* @param string return value format ['int' | 'timestamp' | 'object' | 'array'] |
* @return int e.g. 23 or timestamp |
* @access public |
*/ |
function prevMinute($format = 'int') |
{ |
$ts = $this->cE->dateToStamp( |
$this->year, $this->month, $this->day, |
$this->hour, $this->minute-1, 0); |
return $this->returnValue('Minute', $format, $ts, $this->cE->stampToMinute($ts)); |
} |
/** |
* Returns the value for this minute |
* @param string return value format ['int' | 'timestamp' | 'object' | 'array'] |
* @return int e.g. 24 or timestamp |
* @access public |
*/ |
function thisMinute($format = 'int') |
{ |
$ts = $this->cE->dateToStamp( |
$this->year, $this->month, $this->day, |
$this->hour, $this->minute, 0); |
return $this->returnValue('Minute', $format, $ts, $this->minute); |
} |
/** |
* Returns the value for the next minute |
* @param string return value format ['int' | 'timestamp' | 'object' | 'array'] |
* @return int e.g. 25 or timestamp |
* @access public |
*/ |
function nextMinute($format = 'int') |
{ |
$ts = $this->cE->dateToStamp( |
$this->year, $this->month, $this->day, |
$this->hour, $this->minute+1, 0); |
return $this->returnValue('Minute', $format, $ts, $this->cE->stampToMinute($ts)); |
} |
/** |
* Returns the value for the previous second |
* @param string return value format ['int' | 'timestamp' | 'object' | 'array'] |
* @return int e.g. 43 or timestamp |
* @access public |
*/ |
function prevSecond($format = 'int') |
{ |
$ts = $this->cE->dateToStamp( |
$this->year, $this->month, $this->day, |
$this->hour, $this->minute, $this->second-1); |
return $this->returnValue('Second', $format, $ts, $this->cE->stampToSecond($ts)); |
} |
/** |
* Returns the value for this second |
* @param string return value format ['int' | 'timestamp' | 'object' | 'array'] |
* @return int e.g. 44 or timestamp |
* @access public |
*/ |
function thisSecond($format = 'int') |
{ |
$ts = $this->cE->dateToStamp( |
$this->year, $this->month, $this->day, |
$this->hour, $this->minute, $this->second); |
return $this->returnValue('Second', $format, $ts, $this->second); |
} |
/** |
* Returns the value for the next second |
* @param string return value format ['int' | 'timestamp' | 'object' | 'array'] |
* @return int e.g. 45 or timestamp |
* @access public |
*/ |
function nextSecond($format = 'int') |
{ |
$ts = $this->cE->dateToStamp( |
$this->year, $this->month, $this->day, |
$this->hour, $this->minute, $this->second+1); |
return $this->returnValue('Second', $format, $ts, $this->cE->stampToSecond($ts)); |
} |
} |
?> |
/branches/v1.3-critias/bibliotheque/pear/Calendar/Second.php |
---|
New file |
0,0 → 1,98 |
<?php |
/* vim: set expandtab tabstop=4 shiftwidth=4: */ |
// |
// +----------------------------------------------------------------------+ |
// | PHP Version 4 | |
// +----------------------------------------------------------------------+ |
// | Copyright (c) 1997-2002 The PHP Group | |
// +----------------------------------------------------------------------+ |
// | This source file is subject to version 2.02 of the PHP license, | |
// | that is bundled with this package in the file LICENSE, and is | |
// | available at through the world-wide-web at | |
// | http://www.php.net/license/3_0.txt. | |
// | If you did not receive a copy of the PHP license and are unable to | |
// | obtain it through the world-wide-web, please send a note to | |
// | license@php.net so we can mail you a copy immediately. | |
// +----------------------------------------------------------------------+ |
// | Authors: Harry Fuecks <hfuecks@phppatterns.com> | |
// +----------------------------------------------------------------------+ |
// |
// $Id: Second.php,v 1.1 2004/05/24 22:25:42 quipo Exp $ |
// |
/** |
* @package Calendar |
* @version $Id: Second.php,v 1.1 2004/05/24 22:25:42 quipo Exp $ |
*/ |
/** |
* Allows Calendar include path to be redefined |
* @ignore |
*/ |
if (!defined('CALENDAR_ROOT')) { |
define('CALENDAR_ROOT', 'Calendar'.DIRECTORY_SEPARATOR); |
} |
/** |
* Load Calendar base class |
*/ |
require_once CALENDAR_ROOT.'Calendar.php'; |
/** |
* Represents a Second<br /> |
* <b>Note:</b> Seconds do not build other objects |
* so related methods are overridden to return NULL |
* @package Calendar |
*/ |
class Calendar_Second extends Calendar |
{ |
/** |
* Constructs Second |
* @param int year e.g. 2003 |
* @param int month e.g. 5 |
* @param int day e.g. 11 |
* @param int hour e.g. 13 |
* @param int minute e.g. 31 |
* @param int second e.g. 45 |
*/ |
function Calendar_Second($y, $m, $d, $h, $i, $s) |
{ |
Calendar::Calendar($y, $m, $d, $h, $i, $s); |
} |
/** |
* Overwrite build |
* @return NULL |
*/ |
function build() |
{ |
return null; |
} |
/** |
* Overwrite fetch |
* @return NULL |
*/ |
function fetch() |
{ |
return null; |
} |
/** |
* Overwrite fetchAll |
* @return NULL |
*/ |
function fetchAll() |
{ |
return null; |
} |
/** |
* Overwrite size |
* @return NULL |
*/ |
function size() |
{ |
return null; |
} |
} |
?> |
/branches/v1.3-critias/bibliotheque/pear/Calendar/tests/calendar_test.php |
---|
New file |
0,0 → 1,115 |
<?php |
// $Id: calendar_test.php,v 1.1 2004/05/24 22:25:43 quipo Exp $ |
require_once('simple_include.php'); |
require_once('calendar_include.php'); |
class TestOfCalendar extends UnitTestCase { |
var $cal; |
function TestOfCalendar($name='Test of Calendar') { |
$this->UnitTestCase($name); |
} |
function setUp() { |
$this->cal = new Calendar(2003,10,25,13,32,43); |
} |
function tearDown() { |
unset($this->cal); |
} |
function testPrevYear () { |
$this->assertEqual(2002,$this->cal->prevYear()); |
} |
function testPrevYear_Array () { |
$this->assertEqual( |
array( |
'year' => 2002, |
'month' => 1, |
'day' => 1, |
'hour' => 0, |
'minute' => 0, |
'second' => 0), |
$this->cal->prevYear('array')); |
} |
function testThisYear () { |
$this->assertEqual(2003,$this->cal->thisYear()); |
} |
function testNextYear () { |
$this->assertEqual(2004,$this->cal->nextYear()); |
} |
function testPrevMonth () { |
$this->assertEqual(9,$this->cal->prevMonth()); |
} |
function testPrevMonth_Array () { |
$this->assertEqual( |
array( |
'year' => 2003, |
'month' => 9, |
'day' => 1, |
'hour' => 0, |
'minute' => 0, |
'second' => 0), |
$this->cal->prevMonth('array')); |
} |
function testThisMonth () { |
$this->assertEqual(10,$this->cal->thisMonth()); |
} |
function testNextMonth () { |
$this->assertEqual(11,$this->cal->nextMonth()); |
} |
function testPrevDay () { |
$this->assertEqual(24,$this->cal->prevDay()); |
} |
function testPrevDay_Array () { |
$this->assertEqual( |
array( |
'year' => 2003, |
'month' => 10, |
'day' => 24, |
'hour' => 0, |
'minute' => 0, |
'second' => 0), |
$this->cal->prevDay('array')); |
} |
function testThisDay () { |
$this->assertEqual(25,$this->cal->thisDay()); |
} |
function testNextDay () { |
$this->assertEqual(26,$this->cal->nextDay()); |
} |
function testPrevHour () { |
$this->assertEqual(12,$this->cal->prevHour()); |
} |
function testThisHour () { |
$this->assertEqual(13,$this->cal->thisHour()); |
} |
function testNextHour () { |
$this->assertEqual(14,$this->cal->nextHour()); |
} |
function testPrevMinute () { |
$this->assertEqual(31,$this->cal->prevMinute()); |
} |
function testThisMinute () { |
$this->assertEqual(32,$this->cal->thisMinute()); |
} |
function testNextMinute () { |
$this->assertEqual(33,$this->cal->nextMinute()); |
} |
function testPrevSecond () { |
$this->assertEqual(42,$this->cal->prevSecond()); |
} |
function testThisSecond () { |
$this->assertEqual(43,$this->cal->thisSecond()); |
} |
function testNextSecond () { |
$this->assertEqual(44,$this->cal->nextSecond()); |
} |
function testSetTimeStamp() { |
$stamp = mktime(13,32,43,10,25,2003); |
$this->cal->setTimeStamp($stamp); |
$this->assertEqual($stamp,$this->cal->getTimeStamp()); |
} |
function testGetTimeStamp() { |
$stamp = mktime(13,32,43,10,25,2003); |
$this->assertEqual($stamp,$this->cal->getTimeStamp()); |
} |
} |
?> |
/branches/v1.3-critias/bibliotheque/pear/Calendar/tests/peardate_engine_test.php |
---|
New file |
0,0 → 1,124 |
<?php |
// $Id: peardate_engine_test.php,v 1.2 2004/08/16 11:36:51 hfuecks Exp $ |
require_once('simple_include.php'); |
require_once('calendar_include.php'); |
class TestOfPearDateEngine extends UnitTestCase { |
var $engine; |
function TestOfPearDateEngine() { |
$this->UnitTestCase('Test of Calendar_Engine_PearDate'); |
} |
function setUp() { |
$this->engine = new Calendar_Engine_PearDate(); |
} |
function testGetSecondsInMinute() { |
$this->assertEqual($this->engine->getSecondsInMinute(),60); |
} |
function testGetMinutesInHour() { |
$this->assertEqual($this->engine->getMinutesInHour(),60); |
} |
function testGetHoursInDay() { |
$this->assertEqual($this->engine->getHoursInDay(),24); |
} |
function testGetFirstDayOfWeek() { |
$this->assertEqual($this->engine->getFirstDayOfWeek(),1); |
} |
function testGetWeekDays() { |
$this->assertEqual($this->engine->getWeekDays(),array(0,1,2,3,4,5,6)); |
} |
function testGetDaysInWeek() { |
$this->assertEqual($this->engine->getDaysInWeek(),7); |
} |
function testGetWeekNInYear() { |
$this->assertEqual($this->engine->getWeekNInYear(2003, 11, 3), 45); |
} |
function testGetWeekNInMonth() { |
$this->assertEqual($this->engine->getWeekNInMonth(2003, 11, 3), 2); |
} |
function testGetWeeksInMonth0() { |
$this->assertEqual($this->engine->getWeeksInMonth(2003, 11, 0), 6); //week starts on sunday |
} |
function testGetWeeksInMonth1() { |
$this->assertEqual($this->engine->getWeeksInMonth(2003, 11, 1), 5); //week starts on monday |
} |
function testGetWeeksInMonth2() { |
$this->assertEqual($this->engine->getWeeksInMonth(2003, 2, 6), 4); //week starts on saturday |
} |
function testGetWeeksInMonth3() { |
// Unusual cases that can cause fails (shows up with example 21.php) |
$this->assertEqual($this->engine->getWeeksInMonth(2004,2,1),5); |
$this->assertEqual($this->engine->getWeeksInMonth(2004,8,1),6); |
} |
function testGetDayOfWeek() { |
$this->assertEqual($this->engine->getDayOfWeek(2003, 11, 18), 2); |
} |
function testGetFirstDayInMonth() { |
$this->assertEqual($this->engine->getFirstDayInMonth(2003,10),3); |
} |
function testGetDaysInMonth() { |
$this->assertEqual($this->engine->getDaysInMonth(2003,10),31); |
} |
function testGetMinYears() { |
$this->assertEqual($this->engine->getMinYears(),0); |
} |
function testGetMaxYears() { |
$this->assertEqual($this->engine->getMaxYears(),9999); |
} |
function testDateToStamp() { |
$stamp = '2003-10-15 13:30:45'; |
$this->assertEqual($this->engine->dateToStamp(2003,10,15,13,30,45),$stamp); |
} |
function testStampToSecond() { |
$stamp = '2003-10-15 13:30:45'; |
$this->assertEqual($this->engine->stampToSecond($stamp),45); |
} |
function testStampToMinute() { |
$stamp = '2003-10-15 13:30:45'; |
$this->assertEqual($this->engine->stampToMinute($stamp),30); |
} |
function testStampToHour() { |
$stamp = '2003-10-15 13:30:45'; |
$this->assertEqual($this->engine->stampToHour($stamp),13); |
} |
function testStampToDay() { |
$stamp = '2003-10-15 13:30:45'; |
$this->assertEqual($this->engine->stampToDay($stamp),15); |
} |
function testStampToMonth() { |
$stamp = '2003-10-15 13:30:45'; |
$this->assertEqual($this->engine->stampToMonth($stamp),10); |
} |
function testStampToYear() { |
$stamp = '2003-10-15 13:30:45'; |
$this->assertEqual($this->engine->stampToYear($stamp),2003); |
} |
function testAdjustDate() { |
$stamp = '2004-01-01 13:30:45'; |
$y = $this->engine->stampToYear($stamp); |
$m = $this->engine->stampToMonth($stamp); |
$d = $this->engine->stampToDay($stamp); |
//the first day of the month should be thursday |
$this->assertEqual($this->engine->getDayOfWeek($y, $m, $d), 4); |
$m--; // 2004-00-01 => 2003-12-01 |
$this->engine->adjustDate($y, $m, $d, $dummy, $dummy, $dummy); |
$this->assertEqual($y, 2003); |
$this->assertEqual($m, 12); |
$this->assertEqual($d, 1); |
// get last day and check if it's wednesday |
$d = $this->engine->getDaysInMonth($y, $m); |
$this->assertEqual($this->engine->getDayOfWeek($y, $m, $d), 3); |
} |
} |
if (!defined('TEST_RUNNING')) { |
define('TEST_RUNNING', true); |
$test = &new TestOfPearDateEngine(); |
$test->run(new HtmlReporter()); |
} |
?> |
/branches/v1.3-critias/bibliotheque/pear/Calendar/tests/second_test.php |
---|
New file |
0,0 → 1,34 |
<?php |
// $Id: second_test.php,v 1.1 2004/05/24 22:25:43 quipo Exp $ |
require_once('simple_include.php'); |
require_once('calendar_include.php'); |
require_once('./calendar_test.php'); |
class TestOfSecond extends TestOfCalendar { |
function TestOfSecond() { |
$this->UnitTestCase('Test of Second'); |
} |
function setUp() { |
$this->cal = new Calendar_Second(2003,10,25,13,32,43); |
} |
function testPrevDay_Array () { |
$this->assertEqual( |
array( |
'year' => 2003, |
'month' => 10, |
'day' => 24, |
'hour' => 0, |
'minute' => 0, |
'second' => 0), |
$this->cal->prevDay('array')); |
} |
} |
if (!defined('TEST_RUNNING')) { |
define('TEST_RUNNING', true); |
$test = &new TestOfSecond(); |
$test->run(new HtmlReporter()); |
} |
?> |
/branches/v1.3-critias/bibliotheque/pear/Calendar/tests/day_test.php |
---|
New file |
0,0 → 1,107 |
<?php |
// $Id: day_test.php,v 1.1 2004/05/24 22:25:43 quipo Exp $ |
require_once('simple_include.php'); |
require_once('calendar_include.php'); |
require_once('./calendar_test.php'); |
class TestOfDay extends TestOfCalendar { |
function TestOfDay() { |
$this->UnitTestCase('Test of Day'); |
} |
function setUp() { |
$this->cal = new Calendar_Day(2003,10,25); |
} |
function testPrevDay_Array () { |
$this->assertEqual( |
array( |
'year' => 2003, |
'month' => 10, |
'day' => 24, |
'hour' => 0, |
'minute' => 0, |
'second' => 0), |
$this->cal->prevDay('array')); |
} |
function testPrevHour () { |
$this->assertEqual(23,$this->cal->prevHour()); |
} |
function testThisHour () { |
$this->assertEqual(0,$this->cal->thisHour()); |
} |
function testNextHour () { |
$this->assertEqual(1,$this->cal->nextHour()); |
} |
function testPrevMinute () { |
$this->assertEqual(59,$this->cal->prevMinute()); |
} |
function testThisMinute () { |
$this->assertEqual(0,$this->cal->thisMinute()); |
} |
function testNextMinute () { |
$this->assertEqual(1,$this->cal->nextMinute()); |
} |
function testPrevSecond () { |
$this->assertEqual(59,$this->cal->prevSecond()); |
} |
function testThisSecond () { |
$this->assertEqual(0,$this->cal->thisSecond()); |
} |
function testNextSecond () { |
$this->assertEqual(1,$this->cal->nextSecond()); |
} |
function testGetTimeStamp() { |
$stamp = mktime(0,0,0,10,25,2003); |
$this->assertEqual($stamp,$this->cal->getTimeStamp()); |
} |
} |
class TestOfDayBuild extends TestOfDay { |
function TestOfDayBuild() { |
$this->UnitTestCase('Test of Day::build()'); |
} |
function testSize() { |
$this->cal->build(); |
$this->assertEqual(24,$this->cal->size()); |
} |
function testFetch() { |
$this->cal->build(); |
$i=0; |
while ( $Child = $this->cal->fetch() ) { |
$i++; |
} |
$this->assertEqual(24,$i); |
} |
function testFetchAll() { |
$this->cal->build(); |
$children = array(); |
$i = 0; |
while ( $Child = $this->cal->fetch() ) { |
$children[$i]=$Child; |
$i++; |
} |
$this->assertEqual($children,$this->cal->fetchAll()); |
} |
function testSelection() { |
require_once(CALENDAR_ROOT . 'Hour.php'); |
$selection = array(new Calendar_Hour(2003,10,25,13)); |
$this->cal->build($selection); |
$i = 0; |
while ( $Child = $this->cal->fetch() ) { |
if ( $i == 13 ) |
break; |
$i++; |
} |
$this->assertTrue($Child->isSelected()); |
} |
} |
if (!defined('TEST_RUNNING')) { |
define('TEST_RUNNING', true); |
$test = &new TestOfDay(); |
$test->run(new HtmlReporter()); |
$test = &new TestOfDayBuild(); |
$test->run(new HtmlReporter()); |
} |
?> |
/branches/v1.3-critias/bibliotheque/pear/Calendar/tests/calendar_include.php |
---|
New file |
0,0 → 1,28 |
<?php |
// $Id: calendar_include.php,v 1.4 2004/08/16 12:56:10 hfuecks Exp $ |
if ( !@include 'Calendar/Calendar.php' ) { |
@define('CALENDAR_ROOT','../'); |
} |
require_once(CALENDAR_ROOT . 'Year.php'); |
require_once(CALENDAR_ROOT . 'Month.php'); |
require_once(CALENDAR_ROOT . 'Day.php'); |
require_once(CALENDAR_ROOT . 'Week.php'); |
require_once(CALENDAR_ROOT . 'Hour.php'); |
require_once(CALENDAR_ROOT . 'Minute.php'); |
require_once(CALENDAR_ROOT . 'Second.php'); |
require_once(CALENDAR_ROOT . 'Month.php'); |
require_once(CALENDAR_ROOT . 'Decorator.php'); |
require_once(CALENDAR_ROOT . 'Month/Weekdays.php'); |
require_once(CALENDAR_ROOT . 'Month/Weeks.php'); |
require_once(CALENDAR_ROOT . 'Validator.php'); |
require_once(CALENDAR_ROOT . 'Engine/Interface.php'); |
require_once(CALENDAR_ROOT . 'Engine/UnixTs.php'); |
require_once(CALENDAR_ROOT . 'Engine/PearDate.php'); |
require_once(CALENDAR_ROOT . 'Table/Helper.php'); |
require_once(CALENDAR_ROOT . 'Decorator/Textual.php'); |
require_once(CALENDAR_ROOT . 'Decorator/Uri.php'); |
require_once(CALENDAR_ROOT . 'Decorator/Weekday.php'); |
require_once(CALENDAR_ROOT . 'Decorator/Wrapper.php'); |
require_once(CALENDAR_ROOT . 'Util/Uri.php'); |
require_once(CALENDAR_ROOT . 'Util/Textual.php'); |
?> |
/branches/v1.3-critias/bibliotheque/pear/Calendar/tests/unixts_engine_test.php |
---|
New file |
0,0 → 1,104 |
<?php |
// $Id: unixts_engine_test.php,v 1.2 2004/08/16 11:36:51 hfuecks Exp $ |
require_once('simple_include.php'); |
require_once('calendar_include.php'); |
class TestOfUnixTsEngine extends UnitTestCase { |
var $engine; |
function TestOfUnixTsEngine() { |
$this->UnitTestCase('Test of Calendar_Engine_UnixTs'); |
} |
function setUp() { |
$this->engine = new Calendar_Engine_UnixTs(); |
} |
function testGetSecondsInMinute() { |
$this->assertEqual($this->engine->getSecondsInMinute(),60); |
} |
function testGetMinutesInHour() { |
$this->assertEqual($this->engine->getMinutesInHour(),60); |
} |
function testGetHoursInDay() { |
$this->assertEqual($this->engine->getHoursInDay(),24); |
} |
function testGetFirstDayOfWeek() { |
$this->assertEqual($this->engine->getFirstDayOfWeek(),1); |
} |
function testGetWeekDays() { |
$this->assertEqual($this->engine->getWeekDays(),array(0,1,2,3,4,5,6)); |
} |
function testGetDaysInWeek() { |
$this->assertEqual($this->engine->getDaysInWeek(),7); |
} |
function testGetWeekNInYear() { |
$this->assertEqual($this->engine->getWeekNInYear(2003, 11, 3), 45); |
} |
function testGetWeekNInMonth() { |
$this->assertEqual($this->engine->getWeekNInMonth(2003, 11, 3), 2); |
} |
function testGetWeeksInMonth0() { |
$this->assertEqual($this->engine->getWeeksInMonth(2003, 11, 0), 6); //week starts on sunday |
} |
function testGetWeeksInMonth1() { |
$this->assertEqual($this->engine->getWeeksInMonth(2003, 11, 1), 5); //week starts on monday |
} |
function testGetWeeksInMonth2() { |
$this->assertEqual($this->engine->getWeeksInMonth(2003, 2, 6), 4); //week starts on saturday |
} |
function testGetWeeksInMonth3() { |
// Unusual cases that can cause fails (shows up with example 21.php) |
$this->assertEqual($this->engine->getWeeksInMonth(2004,2,1),5); |
$this->assertEqual($this->engine->getWeeksInMonth(2004,8,1),6); |
} |
function testGetDayOfWeek() { |
$this->assertEqual($this->engine->getDayOfWeek(2003, 11, 18), 2); |
} |
function testGetFirstDayInMonth() { |
$this->assertEqual($this->engine->getFirstDayInMonth(2003,10),3); |
} |
function testGetDaysInMonth() { |
$this->assertEqual($this->engine->getDaysInMonth(2003,10),31); |
} |
function testGetMinYears() { |
$test = strpos(PHP_OS, 'WIN') >= 0 ? 1970 : 1902; |
$this->assertEqual($this->engine->getMinYears(),$test); |
} |
function testGetMaxYears() { |
$this->assertEqual($this->engine->getMaxYears(),2037); |
} |
function testDateToStamp() { |
$stamp = mktime(0,0,0,10,15,2003); |
$this->assertEqual($this->engine->dateToStamp(2003,10,15,0,0,0),$stamp); |
} |
function testStampToSecond() { |
$stamp = mktime(13,30,45,10,15,2003); |
$this->assertEqual($this->engine->stampToSecond($stamp),45); |
} |
function testStampToMinute() { |
$stamp = mktime(13,30,45,10,15,2003); |
$this->assertEqual($this->engine->stampToMinute($stamp),30); |
} |
function testStampToHour() { |
$stamp = mktime(13,30,45,10,15,2003); |
$this->assertEqual($this->engine->stampToHour($stamp),13); |
} |
function testStampToDay() { |
$stamp = mktime(13,30,45,10,15,2003); |
$this->assertEqual($this->engine->stampToDay($stamp),15); |
} |
function testStampToMonth() { |
$stamp = mktime(13,30,45,10,15,2003); |
$this->assertEqual($this->engine->stampToMonth($stamp),10); |
} |
function testStampToYear() { |
$stamp = mktime(13,30,45,10,15,2003); |
$this->assertEqual($this->engine->stampToYear($stamp),2003); |
} |
} |
if (!defined('TEST_RUNNING')) { |
define('TEST_RUNNING', true); |
$test = &new TestOfUnixTsEngine(); |
$test->run(new HtmlReporter()); |
} |
?> |
/branches/v1.3-critias/bibliotheque/pear/Calendar/tests/decorator_test.php |
---|
New file |
0,0 → 1,268 |
<?php |
// $Id: decorator_test.php,v 1.1 2004/05/24 22:25:43 quipo Exp $ |
require_once('simple_include.php'); |
require_once('calendar_include.php'); |
Mock::generate('Calendar_Engine_Interface','Mock_Calendar_Engine'); |
Mock::generate('Calendar_Second','Mock_Calendar_Second'); |
Mock::generate('Calendar_Week','Mock_Calendar_Week'); |
Mock::generate('Calendar_Day','Mock_Calendar_Day'); |
class TestOfDecorator extends UnitTestCase { |
var $mockengine; |
var $mockcal; |
var $decorator; |
function TestOfDecorator() { |
$this->UnitTestCase('Test of Calendar_Decorator'); |
} |
function setUp() { |
$this->mockengine = new Mock_Calendar_Engine($this); |
$this->mockcal = new Mock_Calendar_Second($this); |
$this->mockcal->setReturnValue('prevYear',2002); |
$this->mockcal->setReturnValue('thisYear',2003); |
$this->mockcal->setReturnValue('nextYear',2004); |
$this->mockcal->setReturnValue('prevMonth',9); |
$this->mockcal->setReturnValue('thisMonth',10); |
$this->mockcal->setReturnValue('nextMonth',11); |
$this->mockcal->setReturnValue('prevDay',14); |
$this->mockcal->setReturnValue('thisDay',15); |
$this->mockcal->setReturnValue('nextDay',16); |
$this->mockcal->setReturnValue('prevHour',12); |
$this->mockcal->setReturnValue('thisHour',13); |
$this->mockcal->setReturnValue('nextHour',14); |
$this->mockcal->setReturnValue('prevMinute',29); |
$this->mockcal->setReturnValue('thisMinute',30); |
$this->mockcal->setReturnValue('nextMinute',31); |
$this->mockcal->setReturnValue('prevSecond',44); |
$this->mockcal->setReturnValue('thisSecond',45); |
$this->mockcal->setReturnValue('nextSecond',46); |
$this->mockcal->setReturnValue('getEngine',$this->mockengine); |
$this->mockcal->setReturnValue('getTimestamp',12345); |
} |
function tearDown() { |
unset ( $this->engine ); |
unset ( $this->mockcal ); |
} |
function testPrevYear() { |
$this->mockcal->expectOnce('prevYear',array('int')); |
$Decorator =& new Calendar_Decorator($this->mockcal); |
$this->assertEqual(2002,$Decorator->prevYear()); |
} |
function testThisYear() { |
$this->mockcal->expectOnce('thisYear',array('int')); |
$Decorator =& new Calendar_Decorator($this->mockcal); |
$this->assertEqual(2003,$Decorator->thisYear()); |
} |
function testNextYear() { |
$this->mockcal->expectOnce('nextYear',array('int')); |
$Decorator =& new Calendar_Decorator($this->mockcal); |
$this->assertEqual(2004,$Decorator->nextYear()); |
} |
function testPrevMonth() { |
$this->mockcal->expectOnce('prevMonth',array('int')); |
$Decorator =& new Calendar_Decorator($this->mockcal); |
$this->assertEqual(9,$Decorator->prevMonth()); |
} |
function testThisMonth() { |
$this->mockcal->expectOnce('thisMonth',array('int')); |
$Decorator =& new Calendar_Decorator($this->mockcal); |
$this->assertEqual(10,$Decorator->thisMonth()); |
} |
function testNextMonth() { |
$this->mockcal->expectOnce('nextMonth',array('int')); |
$Decorator =& new Calendar_Decorator($this->mockcal); |
$this->assertEqual(11,$Decorator->nextMonth()); |
} |
function testPrevWeek() { |
$mockweek = & new Mock_Calendar_Week($this); |
$mockweek->setReturnValue('prevWeek',1); |
$mockweek->expectOnce('prevWeek',array('n_in_month')); |
$Decorator =& new Calendar_Decorator($mockweek); |
$this->assertEqual(1,$Decorator->prevWeek()); |
} |
function testThisWeek() { |
$mockweek = & new Mock_Calendar_Week($this); |
$mockweek->setReturnValue('thisWeek',2); |
$mockweek->expectOnce('thisWeek',array('n_in_month')); |
$Decorator =& new Calendar_Decorator($mockweek); |
$this->assertEqual(2,$Decorator->thisWeek()); |
} |
function testNextWeek() { |
$mockweek = & new Mock_Calendar_Week($this); |
$mockweek->setReturnValue('nextWeek',3); |
$mockweek->expectOnce('nextWeek',array('n_in_month')); |
$Decorator =& new Calendar_Decorator($mockweek); |
$this->assertEqual(3,$Decorator->nextWeek()); |
} |
function testPrevDay() { |
$this->mockcal->expectOnce('prevDay',array('int')); |
$Decorator =& new Calendar_Decorator($this->mockcal); |
$this->assertEqual(14,$Decorator->prevDay()); |
} |
function testThisDay() { |
$this->mockcal->expectOnce('thisDay',array('int')); |
$Decorator =& new Calendar_Decorator($this->mockcal); |
$this->assertEqual(15,$Decorator->thisDay()); |
} |
function testNextDay() { |
$this->mockcal->expectOnce('nextDay',array('int')); |
$Decorator =& new Calendar_Decorator($this->mockcal); |
$this->assertEqual(16,$Decorator->nextDay()); |
} |
function testPrevHour() { |
$this->mockcal->expectOnce('prevHour',array('int')); |
$Decorator =& new Calendar_Decorator($this->mockcal); |
$this->assertEqual(12,$Decorator->prevHour()); |
} |
function testThisHour() { |
$this->mockcal->expectOnce('thisHour',array('int')); |
$Decorator =& new Calendar_Decorator($this->mockcal); |
$this->assertEqual(13,$Decorator->thisHour()); |
} |
function testNextHour() { |
$this->mockcal->expectOnce('nextHour',array('int')); |
$Decorator =& new Calendar_Decorator($this->mockcal); |
$this->assertEqual(14,$Decorator->nextHour()); |
} |
function testPrevMinute() { |
$this->mockcal->expectOnce('prevMinute',array('int')); |
$Decorator =& new Calendar_Decorator($this->mockcal); |
$this->assertEqual(29,$Decorator->prevMinute()); |
} |
function testThisMinute() { |
$this->mockcal->expectOnce('thisMinute',array('int')); |
$Decorator =& new Calendar_Decorator($this->mockcal); |
$this->assertEqual(30,$Decorator->thisMinute()); |
} |
function testNextMinute() { |
$this->mockcal->expectOnce('nextMinute',array('int')); |
$Decorator =& new Calendar_Decorator($this->mockcal); |
$this->assertEqual(31,$Decorator->nextMinute()); |
} |
function testPrevSecond() { |
$this->mockcal->expectOnce('prevSecond',array('int')); |
$Decorator =& new Calendar_Decorator($this->mockcal); |
$this->assertEqual(44,$Decorator->prevSecond()); |
} |
function testThisSecond() { |
$this->mockcal->expectOnce('thisSecond',array('int')); |
$Decorator =& new Calendar_Decorator($this->mockcal); |
$this->assertEqual(45,$Decorator->thisSecond()); |
} |
function testNextSecond() { |
$this->mockcal->expectOnce('nextSecond',array('int')); |
$Decorator =& new Calendar_Decorator($this->mockcal); |
$this->assertEqual(46,$Decorator->nextSecond()); |
} |
function testGetEngine() { |
$Decorator =& new Calendar_Decorator($this->mockcal); |
$this->assertIsA($Decorator->getEngine(),'Mock_Calendar_Engine'); |
} |
function testSetTimestamp() { |
$this->mockcal->expectOnce('setTimestamp',array('12345')); |
$Decorator =& new Calendar_Decorator($this->mockcal); |
$Decorator->setTimestamp('12345'); |
} |
function testGetTimestamp() { |
$Decorator =& new Calendar_Decorator($this->mockcal); |
$this->assertEqual(12345,$Decorator->getTimestamp()); |
} |
function testSetSelected() { |
$this->mockcal->expectOnce('setSelected',array(true)); |
$Decorator =& new Calendar_Decorator($this->mockcal); |
$Decorator->setSelected(); |
} |
function testIsSelected() { |
$this->mockcal->setReturnValue('isSelected',true); |
$Decorator =& new Calendar_Decorator($this->mockcal); |
$this->assertTrue($Decorator->isSelected()); |
} |
function testAdjust() { |
$this->mockcal->expectOnce('adjust',array()); |
$Decorator =& new Calendar_Decorator($this->mockcal); |
$Decorator->adjust(); |
} |
function testToArray() { |
$this->mockcal->expectOnce('toArray',array(12345)); |
$testArray = array('foo'=>'bar'); |
$this->mockcal->setReturnValue('toArray',$testArray); |
$Decorator =& new Calendar_Decorator($this->mockcal); |
$this->assertEqual($testArray,$Decorator->toArray(12345)); |
} |
function testReturnValue() { |
$this->mockcal->expectOnce('returnValue',array('a','b','c','d')); |
$this->mockcal->setReturnValue('returnValue','foo'); |
$Decorator =& new Calendar_Decorator($this->mockcal); |
$this->assertEqual('foo',$Decorator->returnValue('a','b','c','d')); |
} |
function testSetFirst() { |
$mockday = & new Mock_Calendar_Day($this); |
$mockday->expectOnce('setFirst',array(true)); |
$Decorator =& new Calendar_Decorator($mockday); |
$Decorator->setFirst(); |
} |
function testSetLast() { |
$mockday = & new Mock_Calendar_Day($this); |
$mockday->expectOnce('setLast',array(true)); |
$Decorator =& new Calendar_Decorator($mockday); |
$Decorator->setLast(); |
} |
function testIsFirst() { |
$mockday = & new Mock_Calendar_Day($this); |
$mockday->setReturnValue('isFirst',TRUE); |
$Decorator =& new Calendar_Decorator($mockday); |
$this->assertTrue($Decorator->isFirst()); |
} |
function testIsLast() { |
$mockday = & new Mock_Calendar_Day($this); |
$mockday->setReturnValue('isLast',TRUE); |
$Decorator =& new Calendar_Decorator($mockday); |
$this->assertTrue($Decorator->isLast()); |
} |
function testSetEmpty() { |
$mockday = & new Mock_Calendar_Day($this); |
$mockday->expectOnce('setEmpty',array(true)); |
$Decorator =& new Calendar_Decorator($mockday); |
$Decorator->setEmpty(); |
} |
function testIsEmpty() { |
$mockday = & new Mock_Calendar_Day($this); |
$mockday->setReturnValue('isEmpty',TRUE); |
$Decorator =& new Calendar_Decorator($mockday); |
$this->assertTrue($Decorator->isEmpty()); |
} |
function testBuild() { |
$testArray=array('foo'=>'bar'); |
$this->mockcal->expectOnce('build',array($testArray)); |
$Decorator =& new Calendar_Decorator($this->mockcal); |
$Decorator->build($testArray); |
} |
function testFetch() { |
$this->mockcal->expectOnce('fetch',array()); |
$Decorator =& new Calendar_Decorator($this->mockcal); |
$Decorator->fetch(); |
} |
function testFetchAll() { |
$this->mockcal->expectOnce('fetchAll',array()); |
$Decorator =& new Calendar_Decorator($this->mockcal); |
$Decorator->fetchAll(); |
} |
function testSize() { |
$this->mockcal->expectOnce('size',array()); |
$Decorator =& new Calendar_Decorator($this->mockcal); |
$Decorator->size(); |
} |
function testIsValid() { |
$this->mockcal->expectOnce('isValid',array()); |
$Decorator =& new Calendar_Decorator($this->mockcal); |
$Decorator->isValid(); |
} |
function testGetValidator() { |
$this->mockcal->expectOnce('getValidator',array()); |
$Decorator =& new Calendar_Decorator($this->mockcal); |
$Decorator->getValidator(); |
} |
} |
?> |
/branches/v1.3-critias/bibliotheque/pear/Calendar/tests/month_weeks_test.php |
---|
New file |
0,0 → 1,125 |
<?php |
// $Id: month_weeks_test.php,v 1.1 2004/05/24 22:25:43 quipo Exp $ |
require_once('simple_include.php'); |
require_once('calendar_include.php'); |
require_once('./calendar_test.php'); |
class TestOfMonthWeeks extends TestOfCalendar { |
function TestOfMonthWeeks() { |
$this->UnitTestCase('Test of Month Weeks'); |
} |
function setUp() { |
$this->cal = new Calendar_Month_Weeks(2003,10); |
} |
function testPrevDay () { |
$this->assertEqual(30,$this->cal->prevDay()); |
} |
function testPrevDay_Array () { |
$this->assertEqual( |
array( |
'year' => 2003, |
'month' => 9, |
'day' => 30, |
'hour' => 0, |
'minute' => 0, |
'second' => 0), |
$this->cal->prevDay('array')); |
} |
function testThisDay () { |
$this->assertEqual(1,$this->cal->thisDay()); |
} |
function testNextDay () { |
$this->assertEqual(2,$this->cal->nextDay()); |
} |
function testPrevHour () { |
$this->assertEqual(23,$this->cal->prevHour()); |
} |
function testThisHour () { |
$this->assertEqual(0,$this->cal->thisHour()); |
} |
function testNextHour () { |
$this->assertEqual(1,$this->cal->nextHour()); |
} |
function testPrevMinute () { |
$this->assertEqual(59,$this->cal->prevMinute()); |
} |
function testThisMinute () { |
$this->assertEqual(0,$this->cal->thisMinute()); |
} |
function testNextMinute () { |
$this->assertEqual(1,$this->cal->nextMinute()); |
} |
function testPrevSecond () { |
$this->assertEqual(59,$this->cal->prevSecond()); |
} |
function testThisSecond () { |
$this->assertEqual(0,$this->cal->thisSecond()); |
} |
function testNextSecond () { |
$this->assertEqual(1,$this->cal->nextSecond()); |
} |
function testGetTimeStamp() { |
$stamp = mktime(0,0,0,10,1,2003); |
$this->assertEqual($stamp,$this->cal->getTimeStamp()); |
} |
} |
class TestOfMonthWeeksBuild extends TestOfMonthWeeks { |
function TestOfMonthWeeksBuild() { |
$this->UnitTestCase('Test of Month_Weeks::build()'); |
} |
function testSize() { |
$this->cal->build(); |
$this->assertEqual(5,$this->cal->size()); |
} |
function testFetch() { |
$this->cal->build(); |
$i=0; |
while ( $Child = $this->cal->fetch() ) { |
$i++; |
} |
$this->assertEqual(5,$i); |
} |
/* Recusive dependency issue with SimpleTest |
function testFetchAll() { |
$this->cal->build(); |
$children = array(); |
$i = 1; |
while ( $Child = $this->cal->fetch() ) { |
$children[$i]=$Child; |
$i++; |
} |
$this->assertEqual($children,$this->cal->fetchAll()); |
} |
*/ |
function testSelection() { |
require_once(CALENDAR_ROOT . 'Week.php'); |
$selection = array(new Calendar_Week(2003, 10, 12)); |
$this->cal->build($selection); |
$i = 1; |
while ($Child = $this->cal->fetch()) { |
if ($i == 2) { |
break; //12-10-2003 is the 2nd day of the week |
} |
$i++; |
} |
$this->assertTrue($Child->isSelected()); |
} |
function testEmptyDaysBefore_AfterAdjust() { |
$this->cal = new Calendar_Month_Weeks(2004,0); |
$this->cal->build(); |
$this->assertEqual(0,$this->cal->tableHelper->getEmptyDaysBefore()); |
} |
} |
if (!defined('TEST_RUNNING')) { |
define('TEST_RUNNING', true); |
$test = &new TestOfMonthWeeks(); |
$test->run(new HtmlReporter()); |
$test = &new TestOfMonthWeeksBuild(); |
$test->run(new HtmlReporter()); |
} |
?> |
/branches/v1.3-critias/bibliotheque/pear/Calendar/tests/util_textual_test.php |
---|
New file |
0,0 → 1,191 |
<?php |
// $Id: util_textual_test.php,v 1.1 2004/08/16 12:56:10 hfuecks Exp $ |
require_once('simple_include.php'); |
require_once('calendar_include.php'); |
require_once('./decorator_test.php'); |
class TestOfUtilTextual extends UnitTestCase { |
var $mockengine; |
var $mockcal; |
function TestOfUtilTextual() { |
$this->UnitTestCase('Test of Calendar_Util_Textual'); |
} |
function setUp() { |
$this->mockengine = new Mock_Calendar_Engine($this); |
$this->mockcal = new Mock_Calendar_Second($this); |
$this->mockcal->setReturnValue('prevYear',2002); |
$this->mockcal->setReturnValue('thisYear',2003); |
$this->mockcal->setReturnValue('nextYear',2004); |
$this->mockcal->setReturnValue('prevMonth',9); |
$this->mockcal->setReturnValue('thisMonth',10); |
$this->mockcal->setReturnValue('nextMonth',11); |
$this->mockcal->setReturnValue('prevDay',14); |
$this->mockcal->setReturnValue('thisDay',15); |
$this->mockcal->setReturnValue('nextDay',16); |
$this->mockcal->setReturnValue('prevHour',12); |
$this->mockcal->setReturnValue('thisHour',13); |
$this->mockcal->setReturnValue('nextHour',14); |
$this->mockcal->setReturnValue('prevMinute',29); |
$this->mockcal->setReturnValue('thisMinute',30); |
$this->mockcal->setReturnValue('nextMinute',31); |
$this->mockcal->setReturnValue('prevSecond',44); |
$this->mockcal->setReturnValue('thisSecond',45); |
$this->mockcal->setReturnValue('nextSecond',46); |
$this->mockcal->setReturnValue('getEngine',$this->mockengine); |
$this->mockcal->setReturnValue('getTimestamp',12345); |
} |
function tearDown() { |
unset ( $this->engine ); |
unset ( $this->mockcal ); |
} |
function testMonthNamesLong() { |
$monthNames = array( |
1=>'January', |
2=>'February', |
3=>'March', |
4=>'April', |
5=>'May', |
6=>'June', |
7=>'July', |
8=>'August', |
9=>'September', |
10=>'October', |
11=>'November', |
12=>'December', |
); |
$this->assertEqual($monthNames,Calendar_Util_Textual::monthNames()); |
} |
function testMonthNamesShort() { |
$monthNames = array( |
1=>'Jan', |
2=>'Feb', |
3=>'Mar', |
4=>'Apr', |
5=>'May', |
6=>'Jun', |
7=>'Jul', |
8=>'Aug', |
9=>'Sep', |
10=>'Oct', |
11=>'Nov', |
12=>'Dec', |
); |
$this->assertEqual($monthNames,Calendar_Util_Textual::monthNames('short')); |
} |
function testMonthNamesTwo() { |
$monthNames = array( |
1=>'Ja', |
2=>'Fe', |
3=>'Ma', |
4=>'Ap', |
5=>'Ma', |
6=>'Ju', |
7=>'Ju', |
8=>'Au', |
9=>'Se', |
10=>'Oc', |
11=>'No', |
12=>'De', |
); |
$this->assertEqual($monthNames,Calendar_Util_Textual::monthNames('two')); |
} |
function testMonthNamesOne() { |
$monthNames = array( |
1=>'J', |
2=>'F', |
3=>'M', |
4=>'A', |
5=>'M', |
6=>'J', |
7=>'J', |
8=>'A', |
9=>'S', |
10=>'O', |
11=>'N', |
12=>'D', |
); |
$this->assertEqual($monthNames,Calendar_Util_Textual::monthNames('one')); |
} |
function testWeekdayNamesLong() { |
$weekdayNames = array( |
0=>'Sunday', |
1=>'Monday', |
2=>'Tuesday', |
3=>'Wednesday', |
4=>'Thursday', |
5=>'Friday', |
6=>'Saturday', |
); |
$this->assertEqual($weekdayNames,Calendar_Util_Textual::weekdayNames()); |
} |
function testWeekdayNamesShort() { |
$weekdayNames = array( |
0=>'Sun', |
1=>'Mon', |
2=>'Tue', |
3=>'Wed', |
4=>'Thu', |
5=>'Fri', |
6=>'Sat', |
); |
$this->assertEqual($weekdayNames,Calendar_Util_Textual::weekdayNames('short')); |
} |
function testWeekdayNamesTwo() { |
$weekdayNames = array( |
0=>'Su', |
1=>'Mo', |
2=>'Tu', |
3=>'We', |
4=>'Th', |
5=>'Fr', |
6=>'Sa', |
); |
$this->assertEqual($weekdayNames,Calendar_Util_Textual::weekdayNames('two')); |
} |
function testWeekdayNamesOne() { |
$weekdayNames = array( |
0=>'S', |
1=>'M', |
2=>'T', |
3=>'W', |
4=>'T', |
5=>'F', |
6=>'S', |
); |
$this->assertEqual($weekdayNames,Calendar_Util_Textual::weekdayNames('one')); |
} |
function testPrevMonthNameShort() { |
$this->assertEqual('Sep',Calendar_Util_Textual::prevMonthName($this->mockcal,'short')); |
} |
function testThisMonthNameShort() { |
$this->assertEqual('Oct',Calendar_Util_Textual::thisMonthName($this->mockcal,'short')); |
} |
function testNextMonthNameShort() { |
$this->assertEqual('Nov',Calendar_Util_Textual::nextMonthName($this->mockcal,'short')); |
} |
function testThisDayNameShort() { |
$this->assertEqual('Wed',Calendar_Util_Textual::thisDayName($this->mockcal,'short')); |
} |
function testOrderedWeekdaysShort() { |
$weekdayNames = array( |
0=>'Sun', |
1=>'Mon', |
2=>'Tue', |
3=>'Wed', |
4=>'Thu', |
5=>'Fri', |
6=>'Sat', |
); |
$this->assertEqual($weekdayNames,Calendar_Util_Textual::orderedWeekdays($this->mockcal,'short')); |
} |
} |
if (!defined('TEST_RUNNING')) { |
define('TEST_RUNNING', true); |
$test = &new TestOfUtilTextual(); |
$test->run(new HtmlReporter()); |
} |
?> |
/branches/v1.3-critias/bibliotheque/pear/Calendar/tests/validator_unit_test.php |
---|
New file |
0,0 → 1,210 |
<?php |
// $Id: validator_unit_test.php,v 1.1 2004/05/24 22:25:43 quipo Exp $ |
require_once('simple_include.php'); |
require_once('calendar_include.php'); |
Mock::generate('Calendar_Engine_Interface','Mock_Calendar_Engine'); |
Mock::generate('Calendar_Second','Mock_Calendar_Second'); |
class TestOfValidator extends UnitTestCase { |
var $mockengine; |
var $mockcal; |
function TestOfValidator() { |
$this->UnitTestCase('Test of Validator'); |
} |
function setUp() { |
$this->mockengine = new Mock_Calendar_Engine($this); |
$this->mockengine->setReturnValue('getMinYears',1970); |
$this->mockengine->setReturnValue('getMaxYears',2037); |
$this->mockengine->setReturnValue('getMonthsInYear',12); |
$this->mockengine->setReturnValue('getDaysInMonth',30); |
$this->mockengine->setReturnValue('getHoursInDay',24); |
$this->mockengine->setReturnValue('getMinutesInHour',60); |
$this->mockengine->setReturnValue('getSecondsInMinute',60); |
$this->mockcal = new Mock_Calendar_Second($this); |
$this->mockcal->setReturnValue('getEngine',$this->mockengine); |
} |
function tearDown() { |
unset ($this->mockengine); |
unset ($this->mocksecond); |
} |
function testIsValidYear() { |
$this->mockcal->setReturnValue('thisYear',2000); |
$Validator = & new Calendar_Validator($this->mockcal); |
$this->assertTrue($Validator->isValidYear()); |
} |
function testIsValidYearTooSmall() { |
$this->mockcal->setReturnValue('thisYear',1969); |
$Validator = & new Calendar_Validator($this->mockcal); |
$this->assertFalse($Validator->isValidYear()); |
} |
function testIsValidYearTooLarge() { |
$this->mockcal->setReturnValue('thisYear',2038); |
$Validator = & new Calendar_Validator($this->mockcal); |
$this->assertFalse($Validator->isValidYear()); |
} |
function testIsValidMonth() { |
$this->mockcal->setReturnValue('thisMonth',10); |
$Validator = & new Calendar_Validator($this->mockcal); |
$this->assertTrue($Validator->isValidMonth()); |
} |
function testIsValidMonthTooSmall() { |
$this->mockcal->setReturnValue('thisMonth',0); |
$Validator = & new Calendar_Validator($this->mockcal); |
$this->assertFalse($Validator->isValidMonth()); |
} |
function testIsValidMonthTooLarge() { |
$this->mockcal->setReturnValue('thisMonth',13); |
$Validator = & new Calendar_Validator($this->mockcal); |
$this->assertFalse($Validator->isValidMonth()); |
} |
function testIsValidDay() { |
$this->mockcal->setReturnValue('thisDay',10); |
$Validator = & new Calendar_Validator($this->mockcal); |
$this->assertTrue($Validator->isValidDay()); |
} |
function testIsValidDayTooSmall() { |
$this->mockcal->setReturnValue('thisDay',0); |
$Validator = & new Calendar_Validator($this->mockcal); |
$this->assertFalse($Validator->isValidDay()); |
} |
function testIsValidDayTooLarge() { |
$this->mockcal->setReturnValue('thisDay',31); |
$Validator = & new Calendar_Validator($this->mockcal); |
$this->assertFalse($Validator->isValidDay()); |
} |
function testIsValidHour() { |
$this->mockcal->setReturnValue('thisHour',10); |
$Validator = & new Calendar_Validator($this->mockcal); |
$this->assertTrue($Validator->isValidHour()); |
} |
function testIsValidHourTooSmall() { |
$this->mockcal->setReturnValue('thisHour',-1); |
$Validator = & new Calendar_Validator($this->mockcal); |
$this->assertFalse($Validator->isValidHour()); |
} |
function testIsValidHourTooLarge() { |
$this->mockcal->setReturnValue('thisHour',24); |
$Validator = & new Calendar_Validator($this->mockcal); |
$this->assertFalse($Validator->isValidHour()); |
} |
function testIsValidMinute() { |
$this->mockcal->setReturnValue('thisMinute',30); |
$Validator = & new Calendar_Validator($this->mockcal); |
$this->assertTrue($Validator->isValidMinute()); |
} |
function testIsValidMinuteTooSmall() { |
$this->mockcal->setReturnValue('thisMinute',-1); |
$Validator = & new Calendar_Validator($this->mockcal); |
$this->assertFalse($Validator->isValidMinute()); |
} |
function testIsValidMinuteTooLarge() { |
$this->mockcal->setReturnValue('thisMinute',60); |
$Validator = & new Calendar_Validator($this->mockcal); |
$this->assertFalse($Validator->isValidMinute()); |
} |
function testIsValidSecond() { |
$this->mockcal->setReturnValue('thisSecond',30); |
$Validator = & new Calendar_Validator($this->mockcal); |
$this->assertTrue($Validator->isValidSecond()); |
} |
function testIsValidSecondTooSmall() { |
$this->mockcal->setReturnValue('thisSecond',-1); |
$Validator = & new Calendar_Validator($this->mockcal); |
$this->assertFalse($Validator->isValidSecond()); |
} |
function testIsValidSecondTooLarge() { |
$this->mockcal->setReturnValue('thisSecond',60); |
$Validator = & new Calendar_Validator($this->mockcal); |
$this->assertFalse($Validator->isValidSecond()); |
} |
function testIsValid() { |
$this->mockcal->setReturnValue('thisYear',2000); |
$this->mockcal->setReturnValue('thisMonth',5); |
$this->mockcal->setReturnValue('thisDay',15); |
$this->mockcal->setReturnValue('thisHour',13); |
$this->mockcal->setReturnValue('thisMinute',30); |
$this->mockcal->setReturnValue('thisSecond',40); |
$Validator = & new Calendar_Validator($this->mockcal); |
$this->assertTrue($Validator->isValid()); |
} |
function testIsValidAllWrong() { |
$this->mockcal->setReturnValue('thisYear',2038); |
$this->mockcal->setReturnValue('thisMonth',13); |
$this->mockcal->setReturnValue('thisDay',31); |
$this->mockcal->day = 31; |
$this->mockcal->setReturnValue('thisHour',24); |
$this->mockcal->setReturnValue('thisMinute',60); |
$this->mockcal->setReturnValue('thisSecond',60); |
$Validator = & new Calendar_Validator($this->mockcal); |
$this->assertFalse($Validator->isValid()); |
$i = 0; |
while ( $Validator->fetch() ) { |
$i++; |
} |
$this->assertEqual($i,6); |
} |
} |
class TestOfValidatorLive extends UnitTestCase { |
function TestOfValidatorLive() { |
$this->UnitTestCase('Test of Validator Live'); |
} |
function testYear() { |
$Unit = new Calendar_Year(2038); |
$Validator = & $Unit->getValidator(); |
$this->assertFalse($Validator->isValidYear()); |
} |
function testMonth() { |
$Unit = new Calendar_Month(2000,13); |
$Validator = & $Unit->getValidator(); |
$this->assertFalse($Validator->isValidMonth()); |
} |
/* |
function testWeek() { |
$Unit = new Calendar_Week(2000,12,7); |
$Validator = & $Unit->getValidator(); |
$this->assertFalse($Validator->isValidWeek()); |
} |
*/ |
function testDay() { |
$Unit = new Calendar_Day(2000,12,32); |
$Validator = & $Unit->getValidator(); |
$this->assertFalse($Validator->isValidDay()); |
} |
function testHour() { |
$Unit = new Calendar_Hour(2000,12,20,24); |
$Validator = & $Unit->getValidator(); |
$this->assertFalse($Validator->isValidHour()); |
} |
function testMinute() { |
$Unit = new Calendar_Minute(2000,12,20,23,60); |
$Validator = & $Unit->getValidator(); |
$this->assertFalse($Validator->isValidMinute()); |
} |
function testSecond() { |
$Unit = new Calendar_Second(2000,12,20,23,59,60); |
$Validator = & $Unit->getValidator(); |
$this->assertFalse($Validator->isValidSecond()); |
} |
function testAllBad() { |
$Unit = new Calendar_Second(2000,13,32,24,60,60); |
$this->assertFalse($Unit->isValid()); |
$Validator = & $Unit->getValidator(); |
$i = 0; |
while ( $Validator->fetch() ) { |
$i++; |
} |
$this->assertEqual($i,5); |
} |
} |
if (!defined('TEST_RUNNING')) { |
define('TEST_RUNNING', true); |
$test = &new TestOfValidator(); |
$test->run(new HtmlReporter()); |
$test = &new TestOfValidatorLive(); |
$test->run(new HtmlReporter()); |
} |
?> |
/branches/v1.3-critias/bibliotheque/pear/Calendar/tests/decorator_textual_test.php |
---|
New file |
0,0 → 1,174 |
<?php |
// $Id: decorator_textual_test.php,v 1.1 2004/05/24 22:25:43 quipo Exp $ |
require_once('simple_include.php'); |
require_once('calendar_include.php'); |
require_once('./decorator_test.php'); |
class TestOfDecoratorTextual extends TestOfDecorator { |
function TestOfDecoratorTextual() { |
$this->UnitTestCase('Test of Calendar_Decorator_Textual'); |
} |
function testMonthNamesLong() { |
$Textual = new Calendar_Decorator_Textual($this->mockcal); |
$monthNames = array( |
1=>'January', |
2=>'February', |
3=>'March', |
4=>'April', |
5=>'May', |
6=>'June', |
7=>'July', |
8=>'August', |
9=>'September', |
10=>'October', |
11=>'November', |
12=>'December', |
); |
$this->assertEqual($monthNames,$Textual->monthNames()); |
} |
function testMonthNamesShort() { |
$Textual = new Calendar_Decorator_Textual($this->mockcal); |
$monthNames = array( |
1=>'Jan', |
2=>'Feb', |
3=>'Mar', |
4=>'Apr', |
5=>'May', |
6=>'Jun', |
7=>'Jul', |
8=>'Aug', |
9=>'Sep', |
10=>'Oct', |
11=>'Nov', |
12=>'Dec', |
); |
$this->assertEqual($monthNames,$Textual->monthNames('short')); |
} |
function testMonthNamesTwo() { |
$Textual = new Calendar_Decorator_Textual($this->mockcal); |
$monthNames = array( |
1=>'Ja', |
2=>'Fe', |
3=>'Ma', |
4=>'Ap', |
5=>'Ma', |
6=>'Ju', |
7=>'Ju', |
8=>'Au', |
9=>'Se', |
10=>'Oc', |
11=>'No', |
12=>'De', |
); |
$this->assertEqual($monthNames,$Textual->monthNames('two')); |
} |
function testMonthNamesOne() { |
$Textual = new Calendar_Decorator_Textual($this->mockcal); |
$monthNames = array( |
1=>'J', |
2=>'F', |
3=>'M', |
4=>'A', |
5=>'M', |
6=>'J', |
7=>'J', |
8=>'A', |
9=>'S', |
10=>'O', |
11=>'N', |
12=>'D', |
); |
$this->assertEqual($monthNames,$Textual->monthNames('one')); |
} |
function testWeekdayNamesLong() { |
$Textual = new Calendar_Decorator_Textual($this->mockcal); |
$weekdayNames = array( |
0=>'Sunday', |
1=>'Monday', |
2=>'Tuesday', |
3=>'Wednesday', |
4=>'Thursday', |
5=>'Friday', |
6=>'Saturday', |
); |
$this->assertEqual($weekdayNames,$Textual->weekdayNames()); |
} |
function testWeekdayNamesShort() { |
$Textual = new Calendar_Decorator_Textual($this->mockcal); |
$weekdayNames = array( |
0=>'Sun', |
1=>'Mon', |
2=>'Tue', |
3=>'Wed', |
4=>'Thu', |
5=>'Fri', |
6=>'Sat', |
); |
$this->assertEqual($weekdayNames,$Textual->weekdayNames('short')); |
} |
function testWeekdayNamesTwo() { |
$Textual = new Calendar_Decorator_Textual($this->mockcal); |
$weekdayNames = array( |
0=>'Su', |
1=>'Mo', |
2=>'Tu', |
3=>'We', |
4=>'Th', |
5=>'Fr', |
6=>'Sa', |
); |
$this->assertEqual($weekdayNames,$Textual->weekdayNames('two')); |
} |
function testWeekdayNamesOne() { |
$Textual = new Calendar_Decorator_Textual($this->mockcal); |
$weekdayNames = array( |
0=>'S', |
1=>'M', |
2=>'T', |
3=>'W', |
4=>'T', |
5=>'F', |
6=>'S', |
); |
$this->assertEqual($weekdayNames,$Textual->weekdayNames('one')); |
} |
function testPrevMonthNameShort() { |
$Textual = new Calendar_Decorator_Textual($this->mockcal); |
$this->assertEqual('Sep',$Textual->prevMonthName('short')); |
} |
function testThisMonthNameShort() { |
$Textual = new Calendar_Decorator_Textual($this->mockcal); |
$this->assertEqual('Oct',$Textual->thisMonthName('short')); |
} |
function testNextMonthNameShort() { |
$Textual = new Calendar_Decorator_Textual($this->mockcal); |
$this->assertEqual('Nov',$Textual->nextMonthName('short')); |
} |
function testThisDayNameShort() { |
$Textual = new Calendar_Decorator_Textual($this->mockcal); |
$this->assertEqual('Wed',$Textual->thisDayName('short')); |
} |
function testOrderedWeekdaysShort() { |
$weekdayNames = array( |
0=>'Sun', |
1=>'Mon', |
2=>'Tue', |
3=>'Wed', |
4=>'Thu', |
5=>'Fri', |
6=>'Sat', |
); |
$Textual = new Calendar_Decorator_Textual($this->mockcal); |
$this->assertEqual($weekdayNames,$Textual->orderedWeekdays('short')); |
} |
} |
if (!defined('TEST_RUNNING')) { |
define('TEST_RUNNING', true); |
$test = &new TestOfDecoratorTextual(); |
$test->run(new HtmlReporter()); |
} |
?> |
/branches/v1.3-critias/bibliotheque/pear/Calendar/tests/all_tests.php |
---|
New file |
0,0 → 1,34 |
<?php |
// $Id: all_tests.php,v 1.2 2004/08/16 08:55:24 hfuecks Exp $ |
require_once('simple_include.php'); |
require_once('calendar_include.php'); |
define("TEST_RUNNING", true); |
require_once('./calendar_tests.php'); |
require_once('./calendar_tabular_tests.php'); |
require_once('./validator_tests.php'); |
require_once('./calendar_engine_tests.php'); |
require_once('./calendar_engine_tests.php'); |
require_once('./table_helper_tests.php'); |
require_once('./decorator_tests.php'); |
require_once('./util_tests.php'); |
class AllTests extends GroupTest { |
function AllTests() { |
$this->GroupTest('All PEAR::Calendar Tests'); |
$this->AddTestCase(new CalendarTests()); |
$this->AddTestCase(new CalendarTabularTests()); |
$this->AddTestCase(new ValidatorTests()); |
$this->AddTestCase(new CalendarEngineTests()); |
$this->AddTestCase(new TableHelperTests()); |
$this->AddTestCase(new DecoratorTests()); |
$this->AddTestCase(new UtilTests()); |
} |
} |
$test = &new AllTests(); |
$test->run(new HtmlReporter()); |
?> |
/branches/v1.3-critias/bibliotheque/pear/Calendar/tests/simple_include.php |
---|
New file |
0,0 → 1,10 |
<?php |
// $Id: simple_include.php,v 1.1 2004/05/24 22:25:43 quipo Exp $ |
if (!defined('SIMPLE_TEST')) { |
define('SIMPLE_TEST', '../../../simpletest/'); |
} |
require_once(SIMPLE_TEST . 'unit_tester.php'); |
require_once(SIMPLE_TEST . 'reporter.php'); |
require_once(SIMPLE_TEST . 'mock_objects.php'); |
?> |
/branches/v1.3-critias/bibliotheque/pear/Calendar/tests/validator_error_test.php |
---|
New file |
0,0 → 1,34 |
<?php |
// $Id: validator_error_test.php,v 1.1 2004/05/24 22:25:43 quipo Exp $ |
require_once('simple_include.php'); |
require_once('calendar_include.php'); |
class TestOfValidationError extends UnitTestCase { |
var $vError; |
function TestOfValidationError() { |
$this->UnitTestCase('Test of Validation Error'); |
} |
function setUp() { |
$this->vError = new Calendar_Validation_Error('foo',20,'bar'); |
} |
function testGetUnit() { |
$this->assertEqual($this->vError->getUnit(),'foo'); |
} |
function testGetValue() { |
$this->assertEqual($this->vError->getValue(),20); |
} |
function testGetMessage() { |
$this->assertEqual($this->vError->getMessage(),'bar'); |
} |
function testToString() { |
$this->assertEqual($this->vError->toString(),'foo = 20 [bar]'); |
} |
} |
if (!defined('TEST_RUNNING')) { |
define('TEST_RUNNING', true); |
$test = &new TestOfValidationError(); |
$test->run(new HtmlReporter()); |
} |
?> |
/branches/v1.3-critias/bibliotheque/pear/Calendar/tests/year_test.php |
---|
New file |
0,0 → 1,142 |
<?php |
// $Id: year_test.php,v 1.1 2004/05/24 22:25:43 quipo Exp $ |
require_once('simple_include.php'); |
require_once('calendar_include.php'); |
require_once('./calendar_test.php'); |
class TestOfYear extends TestOfCalendar { |
function TestOfYear() { |
$this->UnitTestCase('Test of Year'); |
} |
function setUp() { |
$this->cal = new Calendar_Year(2003); |
} |
function testPrevYear_Object() { |
$this->assertEqual(new Calendar_Year(2002), $this->cal->prevYear('object')); |
} |
function testThisYear_Object() { |
$this->assertEqual(new Calendar_Year(2003), $this->cal->thisYear('object')); |
} |
function testPrevMonth () { |
$this->assertEqual(12,$this->cal->prevMonth()); |
} |
function testPrevMonth_Array () { |
$this->assertEqual( |
array( |
'year' => 2002, |
'month' => 12, |
'day' => 1, |
'hour' => 0, |
'minute' => 0, |
'second' => 0), |
$this->cal->prevMonth('array')); |
} |
function testThisMonth () { |
$this->assertEqual(1,$this->cal->thisMonth()); |
} |
function testNextMonth () { |
$this->assertEqual(2,$this->cal->nextMonth()); |
} |
function testPrevDay () { |
$this->assertEqual(31,$this->cal->prevDay()); |
} |
function testPrevDay_Array () { |
$this->assertEqual( |
array( |
'year' => 2002, |
'month' => 12, |
'day' => 31, |
'hour' => 0, |
'minute' => 0, |
'second' => 0), |
$this->cal->prevDay('array')); |
} |
function testThisDay () { |
$this->assertEqual(1,$this->cal->thisDay()); |
} |
function testNextDay () { |
$this->assertEqual(2,$this->cal->nextDay()); |
} |
function testPrevHour () { |
$this->assertEqual(23,$this->cal->prevHour()); |
} |
function testThisHour () { |
$this->assertEqual(0,$this->cal->thisHour()); |
} |
function testNextHour () { |
$this->assertEqual(1,$this->cal->nextHour()); |
} |
function testPrevMinute () { |
$this->assertEqual(59,$this->cal->prevMinute()); |
} |
function testThisMinute () { |
$this->assertEqual(0,$this->cal->thisMinute()); |
} |
function testNextMinute () { |
$this->assertEqual(1,$this->cal->nextMinute()); |
} |
function testPrevSecond () { |
$this->assertEqual(59,$this->cal->prevSecond()); |
} |
function testThisSecond () { |
$this->assertEqual(0,$this->cal->thisSecond()); |
} |
function testNextSecond () { |
$this->assertEqual(1,$this->cal->nextSecond()); |
} |
function testGetTimeStamp() { |
$stamp = mktime(0,0,0,1,1,2003); |
$this->assertEqual($stamp,$this->cal->getTimeStamp()); |
} |
} |
class TestOfYearBuild extends TestOfYear { |
function TestOfYearBuild() { |
$this->UnitTestCase('Test of Year::build()'); |
} |
function testSize() { |
$this->cal->build(); |
$this->assertEqual(12,$this->cal->size()); |
} |
function testFetch() { |
$this->cal->build(); |
$i=0; |
while ( $Child = $this->cal->fetch() ) { |
$i++; |
} |
$this->assertEqual(12,$i); |
} |
function testFetchAll() { |
$this->cal->build(); |
$children = array(); |
$i = 1; |
while ( $Child = $this->cal->fetch() ) { |
$children[$i]=$Child; |
$i++; |
} |
$this->assertEqual($children,$this->cal->fetchAll()); |
} |
function testSelection() { |
require_once(CALENDAR_ROOT . 'Month.php'); |
$selection = array(new Calendar_Month(2003,10)); |
$this->cal->build($selection); |
$i = 1; |
while ( $Child = $this->cal->fetch() ) { |
if ( $i == 10 ) |
break; |
$i++; |
} |
$this->assertTrue($Child->isSelected()); |
} |
} |
if (!defined('TEST_RUNNING')) { |
define('TEST_RUNNING', true); |
$test = &new TestOfYear(); |
$test->run(new HtmlReporter()); |
$test = &new TestOfYearBuild(); |
$test->run(new HtmlReporter()); |
} |
?> |
/branches/v1.3-critias/bibliotheque/pear/Calendar/tests/decorator_tests.php |
---|
New file |
0,0 → 1,21 |
<?php |
// $Id: decorator_tests.php,v 1.1 2004/05/24 22:25:43 quipo Exp $ |
require_once('simple_include.php'); |
require_once('calendar_include.php'); |
class DecoratorTests extends GroupTest { |
function DecoratorTests() { |
$this->GroupTest('Decorator Tests'); |
$this->addTestFile('decorator_test.php'); |
$this->addTestFile('decorator_textual_test.php'); |
$this->addTestFile('decorator_uri_test.php'); |
} |
} |
if (!defined('TEST_RUNNING')) { |
define('TEST_RUNNING', true); |
$test = &new DecoratorTests(); |
$test->run(new HtmlReporter()); |
} |
?> |
/branches/v1.3-critias/bibliotheque/pear/Calendar/tests/validator_tests.php |
---|
New file |
0,0 → 1,20 |
<?php |
// $Id: validator_tests.php,v 1.1 2004/05/24 22:25:43 quipo Exp $ |
require_once('simple_include.php'); |
require_once('calendar_include.php'); |
class ValidatorTests extends GroupTest { |
function ValidatorTests() { |
$this->GroupTest('Validator Tests'); |
$this->addTestFile('validator_unit_test.php'); |
$this->addTestFile('validator_error_test.php'); |
} |
} |
if (!defined('TEST_RUNNING')) { |
define('TEST_RUNNING', true); |
$test = &new ValidatorTests(); |
$test->run(new HtmlReporter()); |
} |
?> |
/branches/v1.3-critias/bibliotheque/pear/Calendar/tests/README |
---|
New file |
0,0 → 1,7 |
These tests require Simple Test: http://www.lastcraft.com/simple_test.php |
Ideally they would use PEAR::PHPUnit but the current version has bugs and |
lacks alot of the functionality (e.g. Mock Objects) which Simple Test |
provides. |
Modifying the simple_include.php script for your simple test install dir |
/branches/v1.3-critias/bibliotheque/pear/Calendar/tests/table_helper_tests.php |
---|
New file |
0,0 → 1,19 |
<?php |
// $Id: table_helper_tests.php,v 1.1 2004/05/24 22:25:43 quipo Exp $ |
require_once('simple_include.php'); |
require_once('calendar_include.php'); |
class TableHelperTests extends GroupTest { |
function TableHelperTests() { |
$this->GroupTest('Table Helper Tests'); |
$this->addTestFile('helper_test.php'); |
} |
} |
if (!defined('TEST_RUNNING')) { |
define('TEST_RUNNING', true); |
$test = &new TableHelperTests(); |
$test->run(new HtmlReporter()); |
} |
?> |
/branches/v1.3-critias/bibliotheque/pear/Calendar/tests/hour_test.php |
---|
New file |
0,0 → 1,98 |
<?php |
// $Id: hour_test.php,v 1.1 2004/05/24 22:25:43 quipo Exp $ |
require_once('simple_include.php'); |
require_once('calendar_include.php'); |
require_once('./calendar_test.php'); |
class TestOfHour extends TestOfCalendar { |
function TestOfHour() { |
$this->UnitTestCase('Test of Hour'); |
} |
function setUp() { |
$this->cal = new Calendar_Hour(2003,10,25,13); |
} |
function testPrevDay_Array () { |
$this->assertEqual( |
array( |
'year' => 2003, |
'month' => 10, |
'day' => 24, |
'hour' => 0, |
'minute' => 0, |
'second' => 0), |
$this->cal->prevDay('array')); |
} |
function testPrevMinute () { |
$this->assertEqual(59,$this->cal->prevMinute()); |
} |
function testThisMinute () { |
$this->assertEqual(0,$this->cal->thisMinute()); |
} |
function testNextMinute () { |
$this->assertEqual(1,$this->cal->nextMinute()); |
} |
function testPrevSecond () { |
$this->assertEqual(59,$this->cal->prevSecond()); |
} |
function testThisSecond () { |
$this->assertEqual(0,$this->cal->thisSecond()); |
} |
function testNextSecond () { |
$this->assertEqual(1,$this->cal->nextSecond()); |
} |
function testGetTimeStamp() { |
$stamp = mktime(13,0,0,10,25,2003); |
$this->assertEqual($stamp,$this->cal->getTimeStamp()); |
} |
} |
class TestOfHourBuild extends TestOfHour { |
function TestOfHourBuild() { |
$this->UnitTestCase('Test of Hour::build()'); |
} |
function testSize() { |
$this->cal->build(); |
$this->assertEqual(60,$this->cal->size()); |
} |
function testFetch() { |
$this->cal->build(); |
$i=0; |
while ( $Child = $this->cal->fetch() ) { |
$i++; |
} |
$this->assertEqual(60,$i); |
} |
function testFetchAll() { |
$this->cal->build(); |
$children = array(); |
$i = 0; |
while ( $Child = $this->cal->fetch() ) { |
$children[$i]=$Child; |
$i++; |
} |
$this->assertEqual($children,$this->cal->fetchAll()); |
} |
function testSelection() { |
require_once(CALENDAR_ROOT . 'Minute.php'); |
$selection = array(new Calendar_Minute(2003,10,25,13,32)); |
$this->cal->build($selection); |
$i = 0; |
while ( $Child = $this->cal->fetch() ) { |
if ( $i == 32 ) |
break; |
$i++; |
} |
$this->assertTrue($Child->isSelected()); |
} |
} |
if (!defined('TEST_RUNNING')) { |
define('TEST_RUNNING', true); |
$test = &new TestOfHour(); |
$test->run(new HtmlReporter()); |
$test = &new TestOfHourBuild(); |
$test->run(new HtmlReporter()); |
} |
?> |
/branches/v1.3-critias/bibliotheque/pear/Calendar/tests/week_firstday_0_test.php |
---|
New file |
0,0 → 1,241 |
<?php |
// $Id: week_firstday_0_test.php,v 1.1 2005/10/20 18:57:52 quipo Exp $ |
define('CALENDAR_FIRST_DAY_OF_WEEK', 0); //force firstDay = Sunday |
require_once('simple_include.php'); |
require_once('calendar_include.php'); |
require_once('./calendar_test.php'); |
class TestOfWeek_firstday_0 extends TestOfCalendar { |
function TestOfWeek_firstday_0() { |
$this->UnitTestCase('Test of Week - Week Starting on Sunday'); |
} |
function setUp() { |
$this->cal = Calendar_Factory::create('Week', 2003, 10, 9); |
//print_r($this->cal); |
} |
function testPrevDay () { |
$this->assertEqual(8, $this->cal->prevDay()); |
} |
function testPrevDay_Array () { |
$this->assertEqual( |
array( |
'year' => 2003, |
'month' => 10, |
'day' => 8, |
'hour' => 0, |
'minute' => 0, |
'second' => 0), |
$this->cal->prevDay('array')); |
} |
function testThisDay () { |
$this->assertEqual(9, $this->cal->thisDay()); |
} |
function testNextDay () { |
$this->assertEqual(10, $this->cal->nextDay()); |
} |
function testPrevHour () { |
$this->assertEqual(23, $this->cal->prevHour()); |
} |
function testThisHour () { |
$this->assertEqual(0, $this->cal->thisHour()); |
} |
function testNextHour () { |
$this->assertEqual(1, $this->cal->nextHour()); |
} |
function testPrevMinute () { |
$this->assertEqual(59, $this->cal->prevMinute()); |
} |
function testThisMinute () { |
$this->assertEqual(0, $this->cal->thisMinute()); |
} |
function testNextMinute () { |
$this->assertEqual(1, $this->cal->nextMinute()); |
} |
function testPrevSecond () { |
$this->assertEqual(59, $this->cal->prevSecond()); |
} |
function testThisSecond () { |
$this->assertEqual(0, $this->cal->thisSecond()); |
} |
function testNextSecond () { |
$this->assertEqual(1, $this->cal->nextSecond()); |
} |
function testGetTimeStamp() { |
$stamp = mktime(0,0,0,10,9,2003); |
$this->assertEqual($stamp,$this->cal->getTimeStamp()); |
} |
function testNewTimeStamp() { |
$stamp = mktime(0,0,0,7,28,2004); |
$this->cal->setTimestamp($stamp); |
$this->assertEqual('29 2004', date('W Y', $this->cal->prevWeek(true))); |
$this->assertEqual('30 2004', date('W Y', $this->cal->thisWeek(true))); |
$this->assertEqual('31 2004', date('W Y', $this->cal->nextWeek(true))); |
} |
function testPrevWeekInMonth() { |
$this->assertEqual(1, $this->cal->prevWeek()); |
$stamp = mktime(0,0,0,2,3,2005); |
$this->cal->setTimestamp($stamp); |
$this->assertEqual(0, $this->cal->prevWeek()); |
} |
function testThisWeekInMonth() { |
$this->assertEqual(2, $this->cal->thisWeek()); |
$stamp = mktime(0,0,0,2,3,2005); |
$this->cal->setTimestamp($stamp); |
$this->assertEqual(1, $this->cal->thisWeek()); |
$stamp = mktime(0,0,0,1,1,2005); |
$this->cal->setTimestamp($stamp); |
$this->assertEqual(1, $this->cal->thisWeek()); |
$stamp = mktime(0,0,0,1,3,2005); |
$this->cal->setTimestamp($stamp); |
$this->assertEqual(2, $this->cal->thisWeek()); |
} |
function testNextWeekInMonth() { |
$this->assertEqual(3, $this->cal->nextWeek()); |
$stamp = mktime(0,0,0,2,3,2005); |
$this->cal->setTimestamp($stamp); |
$this->assertEqual(2, $this->cal->nextWeek()); |
} |
function testPrevWeekInYear() { |
$this->assertEqual(date('W', $this->cal->prevWeek('timestamp')), $this->cal->prevWeek('n_in_year')); |
$stamp = mktime(0,0,0,1,1,2004); |
$this->cal->setTimestamp($stamp); |
$this->assertEqual(date('W', $this->cal->nextWeek('timestamp')), $this->cal->nextWeek('n_in_year')); |
} |
function testThisWeekInYear() { |
$this->assertEqual(date('W', $this->cal->thisWeek('timestamp')), $this->cal->thisWeek('n_in_year')); |
$stamp = mktime(0,0,0,1,1,2004); |
$this->cal->setTimestamp($stamp); |
$this->assertEqual(date('W', $this->cal->thisWeek('timestamp')), $this->cal->thisWeek('n_in_year')); |
} |
function testFirstWeekInYear() { |
$stamp = mktime(0,0,0,1,4,2004); |
$this->cal->setTimestamp($stamp); |
$this->assertEqual(1, $this->cal->thisWeek('n_in_year')); |
} |
function testNextWeekInYear() { |
$this->assertEqual(date('W', $this->cal->nextWeek('timestamp')), $this->cal->nextWeek('n_in_year')); |
} |
function testPrevWeekArray() { |
$testArray = array( |
'year'=>2003, |
'month'=>9, |
'day'=>28, |
'hour'=>0, |
'minute'=>0, |
'second'=>0 |
); |
$this->assertEqual($testArray, $this->cal->prevWeek('array')); |
} |
function testThisWeekArray() { |
$testArray = array( |
'year'=>2003, |
'month'=>10, |
'day'=>5, |
'hour'=>0, |
'minute'=>0, |
'second'=>0 |
); |
$this->assertEqual($testArray, $this->cal->thisWeek('array')); |
} |
function testNextWeekArray() { |
$testArray = array( |
'year'=>2003, |
'month'=>10, |
'day'=>12, |
'hour'=>0, |
'minute'=>0, |
'second'=>0 |
); |
$this->assertEqual($testArray, $this->cal->nextWeek('array')); |
} |
function testPrevWeekObject() { |
$testWeek = Calendar_Factory::create('Week', 2003,9,28); |
$Week = $this->cal->prevWeek('object'); |
$this->assertEqual($testWeek->getTimeStamp(),$Week->getTimeStamp()); |
} |
function testThisWeekObject() { |
$testWeek = Calendar_Factory::create('Week', 2003,10,5); |
$Week = $this->cal->thisWeek('object'); |
$this->assertEqual($testWeek->getTimeStamp(),$Week->getTimeStamp()); |
} |
function testNextWeekObject() { |
$testWeek = Calendar_Factory::create('Week', 2003,10,12); |
$Week = $this->cal->nextWeek('object'); |
$this->assertEqual($testWeek->getTimeStamp(),$Week->getTimeStamp()); |
} |
} |
class TestOfWeek_firstday_0_Build extends TestOfWeek_firstday_0 { |
function TestOfWeek_firstday_0_Build() { |
$this->UnitTestCase('Test of Week::build() - FirstDay = Sunday'); |
} |
function testSize() { |
$this->cal->build(); |
$this->assertEqual(7, $this->cal->size()); |
} |
function testFetch() { |
$this->cal->build(); |
$i=0; |
while ($Child = $this->cal->fetch()) { |
$i++; |
} |
$this->assertEqual(7, $i); |
} |
function testFetchAll() { |
$this->cal->build(); |
$children = array(); |
$i = 1; |
while ( $Child = $this->cal->fetch() ) { |
$children[$i]=$Child; |
$i++; |
} |
$this->assertEqual($children,$this->cal->fetchAll()); |
} |
function testSelection() { |
require_once(CALENDAR_ROOT . 'Day.php'); |
$selection = array(Calendar_Factory::create('Day', 2003, 10, 6)); |
$this->cal->build($selection); |
$i = 1; |
while ($Child = $this->cal->fetch()) { |
if ($i == 2) { |
break; //06-10-2003 is the 2nd day of the week |
} |
$i++; |
} |
$this->assertTrue($Child->isSelected()); |
} |
function testSelectionCornerCase() { |
require_once(CALENDAR_ROOT . 'Day.php'); |
$selectedDays = array( |
Calendar_Factory::create('Day', 2003, 12, 28), |
Calendar_Factory::create('Day', 2003, 12, 29), |
Calendar_Factory::create('Day', 2003, 12, 30), |
Calendar_Factory::create('Day', 2003, 12, 31), |
Calendar_Factory::create('Day', 2004, 01, 01), |
Calendar_Factory::create('Day', 2004, 01, 02), |
Calendar_Factory::create('Day', 2004, 01, 03) |
); |
$this->cal = Calendar_Factory::create('Week', 2003, 12, 31, 0); |
$this->cal->build($selectedDays); |
while ($Day = $this->cal->fetch()) { |
$this->assertTrue($Day->isSelected()); |
} |
$this->cal = Calendar_Factory::create('Week', 2004, 1, 1, 0); |
$this->cal->build($selectedDays); |
while ($Day = $this->cal->fetch()) { |
$this->assertTrue($Day->isSelected()); |
} |
} |
} |
if (!defined('TEST_RUNNING')) { |
define('TEST_RUNNING', true); |
$test = &new TestOfWeek_firstday_0(); |
$test->run(new HtmlReporter()); |
$test = &new TestOfWeek_firstday_0_Build(); |
$test->run(new HtmlReporter()); |
} |
?> |
/branches/v1.3-critias/bibliotheque/pear/Calendar/tests/helper_test.php |
---|
New file |
0,0 → 1,83 |
<?php |
// $Id: helper_test.php,v 1.1 2004/05/24 22:25:43 quipo Exp $ |
require_once('simple_include.php'); |
require_once('calendar_include.php'); |
Mock::generate('Calendar_Engine_Interface','Mock_Calendar_Engine'); |
Mock::generate('Calendar_Second','Mock_Calendar_Second'); |
class TestOfTableHelper extends UnitTestCase { |
var $mockengine; |
var $mockcal; |
function TestOfTableHelper() { |
$this->UnitTestCase('Test of Calendar_Table_Helper'); |
} |
function setUp() { |
$this->mockengine = new Mock_Calendar_Engine($this); |
$this->mockengine->setReturnValue('getMinYears',1970); |
$this->mockengine->setReturnValue('getMaxYears',2037); |
$this->mockengine->setReturnValue('getMonthsInYear',12); |
$this->mockengine->setReturnValue('getDaysInMonth',31); |
$this->mockengine->setReturnValue('getHoursInDay',24); |
$this->mockengine->setReturnValue('getMinutesInHour',60); |
$this->mockengine->setReturnValue('getSecondsInMinute',60); |
$this->mockengine->setReturnValue('getWeekDays',array(0,1,2,3,4,5,6)); |
$this->mockengine->setReturnValue('getDaysInWeek',7); |
$this->mockengine->setReturnValue('getFirstDayOfWeek',1); |
$this->mockengine->setReturnValue('getFirstDayInMonth',3); |
$this->mockcal = new Mock_Calendar_Second($this); |
$this->mockcal->setReturnValue('thisYear',2003); |
$this->mockcal->setReturnValue('thisMonth',10); |
$this->mockcal->setReturnValue('thisDay',15); |
$this->mockcal->setReturnValue('thisHour',13); |
$this->mockcal->setReturnValue('thisMinute',30); |
$this->mockcal->setReturnValue('thisSecond',45); |
$this->mockcal->setReturnValue('getEngine',$this->mockengine); |
} |
function testGetFirstDay() { |
for ( $i = 0; $i <= 7; $i++ ) { |
$Helper = & new Calendar_Table_Helper($this->mockcal,$i); |
$this->assertEqual($Helper->getFirstDay(),$i); |
} |
} |
function testGetDaysOfWeekMonday() { |
$Helper = & new Calendar_Table_Helper($this->mockcal); |
$this->assertEqual($Helper->getDaysOfWeek(),array(1,2,3,4,5,6,0)); |
} |
function testGetDaysOfWeekSunday() { |
$Helper = & new Calendar_Table_Helper($this->mockcal,0); |
$this->assertEqual($Helper->getDaysOfWeek(),array(0,1,2,3,4,5,6)); |
} |
function testGetDaysOfWeekThursday() { |
$Helper = & new Calendar_Table_Helper($this->mockcal,4); |
$this->assertEqual($Helper->getDaysOfWeek(),array(4,5,6,0,1,2,3)); |
} |
function testGetNumWeeks() { |
$Helper = & new Calendar_Table_Helper($this->mockcal); |
$this->assertEqual($Helper->getNumWeeks(),5); |
} |
function testGetNumTableDaysInMonth() { |
$Helper = & new Calendar_Table_Helper($this->mockcal); |
$this->assertEqual($Helper->getNumTableDaysInMonth(),35); |
} |
function testGetEmptyDaysBefore() { |
$Helper = & new Calendar_Table_Helper($this->mockcal); |
$this->assertEqual($Helper->getEmptyDaysBefore(),2); |
} |
function testGetEmptyDaysAfter() { |
$Helper = & new Calendar_Table_Helper($this->mockcal); |
$this->assertEqual($Helper->getEmptyDaysAfter(),33); |
} |
function testGetEmptyDaysAfterOffset() { |
$Helper = & new Calendar_Table_Helper($this->mockcal); |
$this->assertEqual($Helper->getEmptyDaysAfterOffset(),5); |
} |
} |
if (!defined('TEST_RUNNING')) { |
define('TEST_RUNNING', true); |
$test = &new TestOfTableHelper(); |
$test->run(new HtmlReporter()); |
} |
?> |
/branches/v1.3-critias/bibliotheque/pear/Calendar/tests/month_weekdays_test.php |
---|
New file |
0,0 → 1,130 |
<?php |
// $Id: month_weekdays_test.php,v 1.1 2004/05/24 22:25:43 quipo Exp $ |
require_once('simple_include.php'); |
require_once('calendar_include.php'); |
require_once('./calendar_test.php'); |
class TestOfMonthWeekdays extends TestOfCalendar { |
function TestOfMonthWeekdays() { |
$this->UnitTestCase('Test of Month Weekdays'); |
} |
function setUp() { |
$this->cal = new Calendar_Month_Weekdays(2003,10); |
} |
function testPrevDay () { |
$this->assertEqual(30,$this->cal->prevDay()); |
} |
function testPrevDay_Array () { |
$this->assertEqual( |
array( |
'year' => 2003, |
'month' => 9, |
'day' => 30, |
'hour' => 0, |
'minute' => 0, |
'second' => 0), |
$this->cal->prevDay('array')); |
} |
function testThisDay () { |
$this->assertEqual(1,$this->cal->thisDay()); |
} |
function testNextDay () { |
$this->assertEqual(2,$this->cal->nextDay()); |
} |
function testPrevHour () { |
$this->assertEqual(23,$this->cal->prevHour()); |
} |
function testThisHour () { |
$this->assertEqual(0,$this->cal->thisHour()); |
} |
function testNextHour () { |
$this->assertEqual(1,$this->cal->nextHour()); |
} |
function testPrevMinute () { |
$this->assertEqual(59,$this->cal->prevMinute()); |
} |
function testThisMinute () { |
$this->assertEqual(0,$this->cal->thisMinute()); |
} |
function testNextMinute () { |
$this->assertEqual(1,$this->cal->nextMinute()); |
} |
function testPrevSecond () { |
$this->assertEqual(59,$this->cal->prevSecond()); |
} |
function testThisSecond () { |
$this->assertEqual(0,$this->cal->thisSecond()); |
} |
function testNextSecond () { |
$this->assertEqual(1,$this->cal->nextSecond()); |
} |
function testGetTimeStamp() { |
$stamp = mktime(0,0,0,10,1,2003); |
$this->assertEqual($stamp,$this->cal->getTimeStamp()); |
} |
} |
class TestOfMonthWeekdaysBuild extends TestOfMonthWeekdays { |
function TestOfMonthWeekdaysBuild() { |
$this->UnitTestCase('Test of Month_Weekdays::build()'); |
} |
function testSize() { |
$this->cal->build(); |
$this->assertEqual(35,$this->cal->size()); |
} |
function testFetch() { |
$this->cal->build(); |
$i=0; |
while ( $Child = $this->cal->fetch() ) { |
$i++; |
} |
$this->assertEqual(35,$i); |
} |
function testFetchAll() { |
$this->cal->build(); |
$children = array(); |
$i = 1; |
while ( $Child = $this->cal->fetch() ) { |
$children[$i]=$Child; |
$i++; |
} |
$this->assertEqual($children,$this->cal->fetchAll()); |
} |
function testSelection() { |
require_once(CALENDAR_ROOT . 'Day.php'); |
$selection = array(new Calendar_Day(2003,10,25)); |
$this->cal->build($selection); |
$i = 1; |
while ( $Child = $this->cal->fetch() ) { |
if ( $i == 27 ) |
break; |
$i++; |
} |
$this->assertTrue($Child->isSelected()); |
} |
function testEmptyCount() { |
$this->cal->build(); |
$empty = 0; |
while ( $Child = $this->cal->fetch() ) { |
if ( $Child->isEmpty() ) |
$empty++; |
} |
$this->assertEqual(4,$empty); |
} |
function testEmptyDaysBefore_AfterAdjust() { |
$this->cal = new Calendar_Month_Weekdays(2004,0); |
$this->cal->build(); |
$this->assertEqual(0,$this->cal->tableHelper->getEmptyDaysBefore()); |
} |
} |
if (!defined('TEST_RUNNING')) { |
define('TEST_RUNNING', true); |
$test = &new TestOfMonthWeekdays(); |
$test->run(new HtmlReporter()); |
$test = &new TestOfMonthWeekdaysBuild(); |
$test->run(new HtmlReporter()); |
} |
?> |
/branches/v1.3-critias/bibliotheque/pear/Calendar/tests/calendar_engine_tests.php |
---|
New file |
0,0 → 1,20 |
<?php |
// $Id: calendar_engine_tests.php,v 1.1 2004/05/24 22:25:43 quipo Exp $ |
require_once('simple_include.php'); |
require_once('calendar_include.php'); |
class CalendarEngineTests extends GroupTest { |
function CalendarEngineTests() { |
$this->GroupTest('Calendar Engine Tests'); |
$this->addTestFile('peardate_engine_test.php'); |
$this->addTestFile('unixts_engine_test.php'); |
} |
} |
if (!defined('TEST_RUNNING')) { |
define('TEST_RUNNING', true); |
$test = &new CalendarEngineTests(); |
$test->run(new HtmlReporter()); |
} |
?> |
/branches/v1.3-critias/bibliotheque/pear/Calendar/tests/month_test.php |
---|
New file |
0,0 → 1,119 |
<?php |
// $Id: month_test.php,v 1.1 2004/05/24 22:25:43 quipo Exp $ |
require_once('simple_include.php'); |
require_once('calendar_include.php'); |
require_once('./calendar_test.php'); |
class TestOfMonth extends TestOfCalendar { |
function TestOfMonth() { |
$this->UnitTestCase('Test of Month'); |
} |
function setUp() { |
$this->cal = new Calendar_Month(2003,10); |
} |
function testPrevMonth_Object() { |
$this->assertEqual(new Calendar_Month(2003, 9), $this->cal->prevMonth('object')); |
} |
function testPrevDay () { |
$this->assertEqual(30,$this->cal->prevDay()); |
} |
function testPrevDay_Array () { |
$this->assertEqual( |
array( |
'year' => 2003, |
'month' => 9, |
'day' => 30, |
'hour' => 0, |
'minute' => 0, |
'second' => 0), |
$this->cal->prevDay('array')); |
} |
function testThisDay () { |
$this->assertEqual(1,$this->cal->thisDay()); |
} |
function testNextDay () { |
$this->assertEqual(2,$this->cal->nextDay()); |
} |
function testPrevHour () { |
$this->assertEqual(23,$this->cal->prevHour()); |
} |
function testThisHour () { |
$this->assertEqual(0,$this->cal->thisHour()); |
} |
function testNextHour () { |
$this->assertEqual(1,$this->cal->nextHour()); |
} |
function testPrevMinute () { |
$this->assertEqual(59,$this->cal->prevMinute()); |
} |
function testThisMinute () { |
$this->assertEqual(0,$this->cal->thisMinute()); |
} |
function testNextMinute () { |
$this->assertEqual(1,$this->cal->nextMinute()); |
} |
function testPrevSecond () { |
$this->assertEqual(59,$this->cal->prevSecond()); |
} |
function testThisSecond () { |
$this->assertEqual(0,$this->cal->thisSecond()); |
} |
function testNextSecond () { |
$this->assertEqual(1,$this->cal->nextSecond()); |
} |
function testGetTimeStamp() { |
$stamp = mktime(0,0,0,10,1,2003); |
$this->assertEqual($stamp,$this->cal->getTimeStamp()); |
} |
} |
class TestOfMonthBuild extends TestOfMonth { |
function TestOfMonthBuild() { |
$this->UnitTestCase('Test of Month::build()'); |
} |
function testSize() { |
$this->cal->build(); |
$this->assertEqual(31,$this->cal->size()); |
} |
function testFetch() { |
$this->cal->build(); |
$i=0; |
while ( $Child = $this->cal->fetch() ) { |
$i++; |
} |
$this->assertEqual(31,$i); |
} |
function testFetchAll() { |
$this->cal->build(); |
$children = array(); |
$i = 1; |
while ( $Child = $this->cal->fetch() ) { |
$children[$i]=$Child; |
$i++; |
} |
$this->assertEqual($children,$this->cal->fetchAll()); |
} |
function testSelection() { |
require_once(CALENDAR_ROOT . 'Day.php'); |
$selection = array(new Calendar_Day(2003,10,25)); |
$this->cal->build($selection); |
$i = 1; |
while ( $Child = $this->cal->fetch() ) { |
if ( $i == 25 ) |
break; |
$i++; |
} |
$this->assertTrue($Child->isSelected()); |
} |
} |
if (!defined('TEST_RUNNING')) { |
define('TEST_RUNNING', true); |
$test = &new TestOfMonth(); |
$test->run(new HtmlReporter()); |
$test = &new TestOfMonthBuild(); |
$test->run(new HtmlReporter()); |
} |
?> |
/branches/v1.3-critias/bibliotheque/pear/Calendar/tests/week_test.php |
---|
New file |
0,0 → 1,241 |
<?php |
// $Id: week_test.php,v 1.4 2005/10/20 18:56:21 quipo Exp $ |
define('CALENDAR_FIRST_DAY_OF_WEEK', 1); //force firstDay = monday |
require_once('simple_include.php'); |
require_once('calendar_include.php'); |
require_once('./calendar_test.php'); |
class TestOfWeek extends TestOfCalendar { |
function TestOfWeek() { |
$this->UnitTestCase('Test of Week'); |
} |
function setUp() { |
$this->cal = Calendar_Factory::create('Week', 2003, 10, 9); |
//print_r($this->cal); |
} |
function testPrevDay () { |
$this->assertEqual(8, $this->cal->prevDay()); |
} |
function testPrevDay_Array () { |
$this->assertEqual( |
array( |
'year' => 2003, |
'month' => 10, |
'day' => 8, |
'hour' => 0, |
'minute' => 0, |
'second' => 0), |
$this->cal->prevDay('array')); |
} |
function testThisDay () { |
$this->assertEqual(9, $this->cal->thisDay()); |
} |
function testNextDay () { |
$this->assertEqual(10, $this->cal->nextDay()); |
} |
function testPrevHour () { |
$this->assertEqual(23, $this->cal->prevHour()); |
} |
function testThisHour () { |
$this->assertEqual(0, $this->cal->thisHour()); |
} |
function testNextHour () { |
$this->assertEqual(1, $this->cal->nextHour()); |
} |
function testPrevMinute () { |
$this->assertEqual(59, $this->cal->prevMinute()); |
} |
function testThisMinute () { |
$this->assertEqual(0, $this->cal->thisMinute()); |
} |
function testNextMinute () { |
$this->assertEqual(1, $this->cal->nextMinute()); |
} |
function testPrevSecond () { |
$this->assertEqual(59, $this->cal->prevSecond()); |
} |
function testThisSecond () { |
$this->assertEqual(0, $this->cal->thisSecond()); |
} |
function testNextSecond () { |
$this->assertEqual(1, $this->cal->nextSecond()); |
} |
function testGetTimeStamp() { |
$stamp = mktime(0,0,0,10,9,2003); |
$this->assertEqual($stamp,$this->cal->getTimeStamp()); |
} |
function testNewTimeStamp() { |
$stamp = mktime(0,0,0,7,28,2004); |
$this->cal->setTimestamp($stamp); |
$this->assertEqual('30 2004', date('W Y', $this->cal->prevWeek(true))); |
$this->assertEqual('31 2004', date('W Y', $this->cal->thisWeek(true))); |
$this->assertEqual('32 2004', date('W Y', $this->cal->nextWeek(true))); |
} |
function testPrevWeekInMonth() { |
$this->assertEqual(1, $this->cal->prevWeek()); |
$stamp = mktime(0,0,0,2,3,2005); |
$this->cal->setTimestamp($stamp); |
$this->assertEqual(0, $this->cal->prevWeek()); |
} |
function testThisWeekInMonth() { |
$this->assertEqual(2, $this->cal->thisWeek()); |
$stamp = mktime(0,0,0,2,3,2005); |
$this->cal->setTimestamp($stamp); |
$this->assertEqual(1, $this->cal->thisWeek()); |
$stamp = mktime(0,0,0,1,1,2005); |
$this->cal->setTimestamp($stamp); |
$this->assertEqual(1, $this->cal->thisWeek()); |
$stamp = mktime(0,0,0,1,3,2005); |
$this->cal->setTimestamp($stamp); |
$this->assertEqual(2, $this->cal->thisWeek()); |
} |
function testNextWeekInMonth() { |
$this->assertEqual(3, $this->cal->nextWeek()); |
$stamp = mktime(0,0,0,2,3,2005); |
$this->cal->setTimestamp($stamp); |
$this->assertEqual(2, $this->cal->nextWeek()); |
} |
function testPrevWeekInYear() { |
$this->assertEqual(date('W', $this->cal->prevWeek('timestamp')), $this->cal->prevWeek('n_in_year')); |
$stamp = mktime(0,0,0,1,1,2004); |
$this->cal->setTimestamp($stamp); |
$this->assertEqual(date('W', $this->cal->nextWeek('timestamp')), $this->cal->nextWeek('n_in_year')); |
} |
function testThisWeekInYear() { |
$this->assertEqual(date('W', $this->cal->thisWeek('timestamp')), $this->cal->thisWeek('n_in_year')); |
$stamp = mktime(0,0,0,1,1,2004); |
$this->cal->setTimestamp($stamp); |
$this->assertEqual(date('W', $this->cal->thisWeek('timestamp')), $this->cal->thisWeek('n_in_year')); |
} |
function testFirstWeekInYear() { |
$stamp = mktime(0,0,0,1,4,2004); |
$this->cal->setTimestamp($stamp); |
$this->assertEqual(1, $this->cal->thisWeek('n_in_year')); |
} |
function testNextWeekInYear() { |
$this->assertEqual(date('W', $this->cal->nextWeek('timestamp')), $this->cal->nextWeek('n_in_year')); |
} |
function testPrevWeekArray() { |
$testArray = array( |
'year'=>2003, |
'month'=>9, |
'day'=>29, |
'hour'=>0, |
'minute'=>0, |
'second'=>0 |
); |
$this->assertEqual($testArray, $this->cal->prevWeek('array')); |
} |
function testThisWeekArray() { |
$testArray = array( |
'year'=>2003, |
'month'=>10, |
'day'=>6, |
'hour'=>0, |
'minute'=>0, |
'second'=>0 |
); |
$this->assertEqual($testArray, $this->cal->thisWeek('array')); |
} |
function testNextWeekArray() { |
$testArray = array( |
'year'=>2003, |
'month'=>10, |
'day'=>13, |
'hour'=>0, |
'minute'=>0, |
'second'=>0 |
); |
$this->assertEqual($testArray, $this->cal->nextWeek('array')); |
} |
function testPrevWeekObject() { |
$testWeek = Calendar_Factory::create('Week', 2003, 9, 29); //week starts on monday |
$Week = $this->cal->prevWeek('object'); |
$this->assertEqual($testWeek->getTimeStamp(), $Week->getTimeStamp()); |
} |
function testThisWeekObject() { |
$testWeek = Calendar_Factory::create('Week', 2003, 10, 6); //week starts on monday |
$Week = $this->cal->thisWeek('object'); |
$this->assertEqual($testWeek->getTimeStamp(), $Week->getTimeStamp()); |
} |
function testNextWeekObject() { |
$testWeek = Calendar_Factory::create('Week', 2003, 10, 13); //week starts on monday |
$Week = $this->cal->nextWeek('object'); |
$this->assertEqual($testWeek->getTimeStamp(), $Week->getTimeStamp()); |
} |
} |
class TestOfWeekBuild extends TestOfWeek { |
function TestOfWeekBuild() { |
$this->UnitTestCase('Test of Week::build()'); |
} |
function testSize() { |
$this->cal->build(); |
$this->assertEqual(7, $this->cal->size()); |
} |
function testFetch() { |
$this->cal->build(); |
$i=0; |
while ($Child = $this->cal->fetch()) { |
$i++; |
} |
$this->assertEqual(7, $i); |
} |
function testFetchAll() { |
$this->cal->build(); |
$children = array(); |
$i = 1; |
while ( $Child = $this->cal->fetch() ) { |
$children[$i]=$Child; |
$i++; |
} |
$this->assertEqual($children,$this->cal->fetchAll()); |
} |
function testSelection() { |
require_once(CALENDAR_ROOT . 'Day.php'); |
$selection = array(Calendar_Factory::create('Day', 2003, 10, 7)); |
$this->cal->build($selection); |
$i = 1; |
while ($Child = $this->cal->fetch()) { |
if ($i == 2) { |
break; //07-10-2003 is the 2nd day of the week (starting on monday) |
} |
$i++; |
} |
$this->assertTrue($Child->isSelected()); |
} |
function testSelectionCornerCase() { |
require_once(CALENDAR_ROOT . 'Day.php'); |
$selectedDays = array( |
Calendar_Factory::create('Day', 2003, 12, 29), |
Calendar_Factory::create('Day', 2003, 12, 30), |
Calendar_Factory::create('Day', 2003, 12, 31), |
Calendar_Factory::create('Day', 2004, 01, 01), |
Calendar_Factory::create('Day', 2004, 01, 02), |
Calendar_Factory::create('Day', 2004, 01, 03), |
Calendar_Factory::create('Day', 2004, 01, 04) |
); |
$this->cal = Calendar_Factory::create('Week', 2003, 12, 31, 0); |
$this->cal->build($selectedDays); |
while ($Day = $this->cal->fetch()) { |
$this->assertTrue($Day->isSelected()); |
} |
$this->cal = Calendar_Factory::create('Week', 2004, 1, 1, 0); |
$this->cal->build($selectedDays); |
while ($Day = $this->cal->fetch()) { |
$this->assertTrue($Day->isSelected()); |
} |
} |
} |
if (!defined('TEST_RUNNING')) { |
define('TEST_RUNNING', true); |
$test = &new TestOfWeek(); |
$test->run(new HtmlReporter()); |
$test = &new TestOfWeekBuild(); |
$test->run(new HtmlReporter()); |
} |
?> |
/branches/v1.3-critias/bibliotheque/pear/Calendar/tests/calendar_tests.php |
---|
New file |
0,0 → 1,25 |
<?php |
// $Id: calendar_tests.php,v 1.1 2004/05/24 22:25:43 quipo Exp $ |
require_once('simple_include.php'); |
require_once('calendar_include.php'); |
class CalendarTests extends GroupTest { |
function CalendarTests() { |
$this->GroupTest('Calendar Tests'); |
$this->addTestFile('calendar_test.php'); |
$this->addTestFile('year_test.php'); |
$this->addTestFile('month_test.php'); |
$this->addTestFile('day_test.php'); |
$this->addTestFile('hour_test.php'); |
$this->addTestFile('minute_test.php'); |
$this->addTestFile('second_test.php'); |
} |
} |
if (!defined('TEST_RUNNING')) { |
define('TEST_RUNNING', true); |
$test = &new CalendarTests(); |
$test->run(new HtmlReporter()); |
} |
?> |
/branches/v1.3-critias/bibliotheque/pear/Calendar/tests/util_uri_test.php |
---|
New file |
0,0 → 1,54 |
<?php |
// $Id: util_uri_test.php,v 1.1 2004/08/16 08:55:24 hfuecks Exp $ |
require_once('simple_include.php'); |
require_once('calendar_include.php'); |
Mock::generate('Calendar_Day','Mock_Calendar_Day'); |
Mock::generate('Calendar_Engine_Interface','Mock_Calendar_Engine'); |
class TestOfUtilUri extends UnitTestCase { |
var $MockCal; |
function TestOfUtilUri() { |
$this->UnitTestCase('Test of Calendar_Util_Uri'); |
} |
function setUp() { |
$this->MockCal = & new Mock_Calendar_Day($this); |
$this->MockCal->setReturnValue('getEngine',new Mock_Calendar_Engine($this)); |
} |
function testFragments() { |
$Uri = new Calendar_Util_Uri('y','m','d','h','m','s'); |
$Uri->setFragments('year','month','day','hour','minute','second'); |
$this->assertEqual( |
'year=&month=&day=&hour=&minute=&second=', |
$Uri->this($this->MockCal, 'second') |
); |
} |
function testScalarFragments() { |
$Uri = new Calendar_Util_Uri('year','month','day','hour','minute','second'); |
$Uri->scalar = true; |
$this->assertEqual( |
'&&&&&', |
$Uri->this($this->MockCal, 'second') |
); |
} |
function testSetSeperator() { |
$Uri = new Calendar_Util_Uri('year','month','day','hour','minute','second'); |
$Uri->separator = '/'; |
$this->assertEqual( |
'year=/month=/day=/hour=/minute=/second=', |
$Uri->this($this->MockCal, 'second') |
); |
} |
} |
if (!defined('TEST_RUNNING')) { |
define('TEST_RUNNING', true); |
$test = &new TestOfUtilUri(); |
$test->run(new HtmlReporter()); |
} |
?> |
/branches/v1.3-critias/bibliotheque/pear/Calendar/tests/util_tests.php |
---|
New file |
0,0 → 1,20 |
<?php |
// $Id: util_tests.php,v 1.2 2004/08/16 12:56:10 hfuecks Exp $ |
require_once('simple_include.php'); |
require_once('calendar_include.php'); |
class UtilTests extends GroupTest { |
function UtilTests() { |
$this->GroupTest('Util Tests'); |
$this->addTestFile('util_uri_test.php'); |
$this->addTestFile('util_textual_test.php'); |
} |
} |
if (!defined('TEST_RUNNING')) { |
define('TEST_RUNNING', true); |
$test = &new UtilTests(); |
$test->run(new HtmlReporter()); |
} |
?> |
/branches/v1.3-critias/bibliotheque/pear/Calendar/tests/minute_test.php |
---|
New file |
0,0 → 1,99 |
<?php |
// $Id: minute_test.php,v 1.1 2004/05/24 22:25:43 quipo Exp $ |
require_once('simple_include.php'); |
require_once('calendar_include.php'); |
require_once('./calendar_test.php'); |
class TestOfMinute extends TestOfCalendar { |
function TestOfMinute() { |
$this->UnitTestCase('Test of Minute'); |
} |
function setUp() { |
$this->cal = new Calendar_Minute(2003,10,25,13,32); |
} |
function testPrevDay_Array () { |
$this->assertEqual( |
array( |
'year' => 2003, |
'month' => 10, |
'day' => 24, |
'hour' => 0, |
'minute' => 0, |
'second' => 0), |
$this->cal->prevDay('array')); |
} |
function testPrevSecond () { |
$this->assertEqual(59,$this->cal->prevSecond()); |
} |
function testThisSecond () { |
$this->assertEqual(0,$this->cal->thisSecond()); |
} |
function testThisSecond_Timestamp () { |
$this->assertEqual($this->cal->cE->dateToStamp( |
2003, 10, 25, 13, 32, 0), |
$this->cal->thisSecond('timestamp')); |
} |
function testNextSecond () { |
$this->assertEqual(1,$this->cal->nextSecond()); |
} |
function testNextSecond_Timestamp () { |
$this->assertEqual($this->cal->cE->dateToStamp( |
2003, 10, 25, 13, 32, 1), |
$this->cal->nextSecond('timestamp')); |
} |
function testGetTimeStamp() { |
$stamp = mktime(13,32,0,10,25,2003); |
$this->assertEqual($stamp,$this->cal->getTimeStamp()); |
} |
} |
class TestOfMinuteBuild extends TestOfMinute { |
function TestOfMinuteBuild() { |
$this->UnitTestCase('Test of Minute::build()'); |
} |
function testSize() { |
$this->cal->build(); |
$this->assertEqual(60,$this->cal->size()); |
} |
function testFetch() { |
$this->cal->build(); |
$i=0; |
while ( $Child = $this->cal->fetch() ) { |
$i++; |
} |
$this->assertEqual(60,$i); |
} |
function testFetchAll() { |
$this->cal->build(); |
$children = array(); |
$i = 0; |
while ( $Child = $this->cal->fetch() ) { |
$children[$i]=$Child; |
$i++; |
} |
$this->assertEqual($children,$this->cal->fetchAll()); |
} |
function testSelection() { |
require_once(CALENDAR_ROOT . 'Second.php'); |
$selection = array(new Calendar_Second(2003,10,25,13,32,43)); |
$this->cal->build($selection); |
$i = 0; |
while ( $Child = $this->cal->fetch() ) { |
if ( $i == 43 ) |
break; |
$i++; |
} |
$this->assertTrue($Child->isSelected()); |
} |
} |
if (!defined('TEST_RUNNING')) { |
define('TEST_RUNNING', true); |
$test = &new TestOfMinute(); |
$test->run(new HtmlReporter()); |
$test = &new TestOfMinuteBuild(); |
$test->run(new HtmlReporter()); |
} |
?> |
/branches/v1.3-critias/bibliotheque/pear/Calendar/tests/decorator_uri_test.php |
---|
New file |
0,0 → 1,37 |
<?php |
// $Id: decorator_uri_test.php,v 1.2 2004/07/08 10:18:48 quipo Exp $ |
require_once('simple_include.php'); |
require_once('calendar_include.php'); |
require_once('./decorator_test.php'); |
class TestOfDecoratorUri extends TestOfDecorator { |
function TestOfDecoratorUri() { |
$this->UnitTestCase('Test of Calendar_Decorator_Uri'); |
} |
function testFragments() { |
$Uri = new Calendar_Decorator_Uri($this->mockcal); |
$Uri->setFragments('year','month','day','hour','minute','second'); |
$this->assertEqual('year=&month=&day=&hour=&minute=&second=',$Uri->this('second')); |
} |
function testScalarFragments() { |
$Uri = new Calendar_Decorator_Uri($this->mockcal); |
$Uri->setFragments('year','month','day','hour','minute','second'); |
$Uri->setScalar(); |
$this->assertEqual('&&&&&',$Uri->this('second')); |
} |
function testSetSeperator() { |
$Uri = new Calendar_Decorator_Uri($this->mockcal); |
$Uri->setFragments('year','month','day','hour','minute','second'); |
$Uri->setSeparator('/'); |
$this->assertEqual('year=/month=/day=/hour=/minute=/second=',$Uri->this('second')); |
} |
} |
if (!defined('TEST_RUNNING')) { |
define('TEST_RUNNING', true); |
$test = &new TestOfDecoratorUri(); |
$test->run(new HtmlReporter()); |
} |
?> |
/branches/v1.3-critias/bibliotheque/pear/Calendar/tests/calendar_tabular_tests.php |
---|
New file |
0,0 → 1,22 |
<?php |
// $Id: calendar_tabular_tests.php,v 1.2 2005/10/20 18:59:45 quipo Exp $ |
require_once('simple_include.php'); |
require_once('calendar_include.php'); |
class CalendarTabularTests extends GroupTest { |
function CalendarTabularTests() { |
$this->GroupTest('Calendar Tabular Tests'); |
$this->addTestFile('month_weekdays_test.php'); |
$this->addTestFile('month_weeks_test.php'); |
$this->addTestFile('week_test.php'); |
//$this->addTestFile('week_firstday_0_test.php'); //switch with the above |
} |
} |
if (!defined('TEST_RUNNING')) { |
define('TEST_RUNNING', true); |
$test = &new CalendarTabularTests(); |
$test->run(new HtmlReporter()); |
} |
?> |
/branches/v1.3-critias/bibliotheque/pear/Calendar/Day.php |
---|
New file |
0,0 → 1,197 |
<?php |
/* vim: set expandtab tabstop=4 shiftwidth=4: */ |
// |
// +----------------------------------------------------------------------+ |
// | PHP Version 4 | |
// +----------------------------------------------------------------------+ |
// | Copyright (c) 1997-2002 The PHP Group | |
// +----------------------------------------------------------------------+ |
// | This source file is subject to version 2.02 of the PHP license, | |
// | that is bundled with this package in the file LICENSE, and is | |
// | available at through the world-wide-web at | |
// | http://www.php.net/license/3_0.txt. | |
// | If you did not receive a copy of the PHP license and are unable to | |
// | obtain it through the world-wide-web, please send a note to | |
// | license@php.net so we can mail you a copy immediately. | |
// +----------------------------------------------------------------------+ |
// | Authors: Harry Fuecks <hfuecks@phppatterns.com> | |
// +----------------------------------------------------------------------+ |
// |
// $Id: Day.php,v 1.1 2004/05/24 22:25:42 quipo Exp $ |
// |
/** |
* @package Calendar |
* @version $Id: Day.php,v 1.1 2004/05/24 22:25:42 quipo Exp $ |
*/ |
/** |
* Allows Calendar include path to be redefined |
* @ignore |
*/ |
if (!defined('CALENDAR_ROOT')) { |
define('CALENDAR_ROOT', 'Calendar'.DIRECTORY_SEPARATOR); |
} |
/** |
* Load Calendar base class |
*/ |
require_once CALENDAR_ROOT.'Calendar.php'; |
/** |
* Represents a Day and builds Hours. |
* <code> |
* require_once 'Calendar'.DIRECTORY_SEPARATOR.'Day.php'; |
* $Day = & new Calendar_Day(2003, 10, 21); // Oct 21st 2003 |
* while ($Hour = & $Day->fetch()) { |
* echo $Hour->thisHour().'<br />'; |
* } |
* </code> |
* @package Calendar |
* @access public |
*/ |
class Calendar_Day extends Calendar |
{ |
/** |
* Marks the Day at the beginning of a week |
* @access private |
* @var boolean |
*/ |
var $first = false; |
/** |
* Marks the Day at the end of a week |
* @access private |
* @var boolean |
*/ |
var $last = false; |
/** |
* Used for tabular calendars |
* @access private |
* @var boolean |
*/ |
var $empty = false; |
/** |
* Constructs Calendar_Day |
* @param int year e.g. 2003 |
* @param int month e.g. 8 |
* @param int day e.g. 15 |
* @access public |
*/ |
function Calendar_Day($y, $m, $d) |
{ |
Calendar::Calendar($y, $m, $d); |
} |
/** |
* Builds the Hours of the Day |
* @param array (optional) Caledar_Hour objects representing selected dates |
* @return boolean |
* @access public |
*/ |
function build($sDates = array()) |
{ |
require_once CALENDAR_ROOT.'Hour.php'; |
$hID = $this->cE->getHoursInDay($this->year, $this->month, $this->day); |
for ($i=0; $i < $hID; $i++) { |
$this->children[$i]= |
new Calendar_Hour($this->year, $this->month, $this->day, $i); |
} |
if (count($sDates) > 0) { |
$this->setSelection($sDates); |
} |
return true; |
} |
/** |
* Called from build() |
* @param array |
* @return void |
* @access private |
*/ |
function setSelection($sDates) |
{ |
foreach ($sDates as $sDate) { |
if ($this->year == $sDate->thisYear() |
&& $this->month == $sDate->thisMonth() |
&& $this->day == $sDate->thisDay()) |
{ |
$key = (int)$sDate->thisHour(); |
if (isset($this->children[$key])) { |
$sDate->setSelected(); |
$this->children[$key] = $sDate; |
} |
} |
} |
} |
/** |
* Defines Day object as first in a week |
* Only used by Calendar_Month_Weekdays::build() |
* @param boolean state |
* @return void |
* @access private |
*/ |
function setFirst ($state = true) |
{ |
$this->first = $state; |
} |
/** |
* Defines Day object as last in a week |
* Used only following Calendar_Month_Weekdays::build() |
* @param boolean state |
* @return void |
* @access private |
*/ |
function setLast($state = true) |
{ |
$this->last = $state; |
} |
/** |
* Returns true if Day object is first in a Week |
* Only relevant when Day is created by Calendar_Month_Weekdays::build() |
* @return boolean |
* @access public |
*/ |
function isFirst() { |
return $this->first; |
} |
/** |
* Returns true if Day object is last in a Week |
* Only relevant when Day is created by Calendar_Month_Weekdays::build() |
* @return boolean |
* @access public |
*/ |
function isLast() |
{ |
return $this->last; |
} |
/** |
* Defines Day object as empty |
* Only used by Calendar_Month_Weekdays::build() |
* @param boolean state |
* @return void |
* @access private |
*/ |
function setEmpty ($state = true) |
{ |
$this->empty = $state; |
} |
/** |
* @return boolean |
* @access public |
*/ |
function isEmpty() |
{ |
return $this->empty; |
} |
} |
?> |
/branches/v1.3-critias/bibliotheque/pear/Calendar/Hour.php |
---|
New file |
0,0 → 1,113 |
<?php |
/* vim: set expandtab tabstop=4 shiftwidth=4: */ |
// |
// +----------------------------------------------------------------------+ |
// | PHP Version 4 | |
// +----------------------------------------------------------------------+ |
// | Copyright (c) 1997-2002 The PHP Group | |
// +----------------------------------------------------------------------+ |
// | This source file is subject to version 2.02 of the PHP license, | |
// | that is bundled with this package in the file LICENSE, and is | |
// | available at through the world-wide-web at | |
// | http://www.php.net/license/3_0.txt. | |
// | If you did not receive a copy of the PHP license and are unable to | |
// | obtain it through the world-wide-web, please send a note to | |
// | license@php.net so we can mail you a copy immediately. | |
// +----------------------------------------------------------------------+ |
// | Authors: Harry Fuecks <hfuecks@phppatterns.com> | |
// +----------------------------------------------------------------------+ |
// |
// $Id: Hour.php,v 1.1 2004/05/24 22:25:42 quipo Exp $ |
// |
/** |
* @package Calendar |
* @version $Id: Hour.php,v 1.1 2004/05/24 22:25:42 quipo Exp $ |
*/ |
/** |
* Allows Calendar include path to be redefined |
* @ignore |
*/ |
if (!defined('CALENDAR_ROOT')) { |
define('CALENDAR_ROOT', 'Calendar'.DIRECTORY_SEPARATOR); |
} |
/** |
* Load Calendar base class |
*/ |
require_once CALENDAR_ROOT.'Calendar.php'; |
/** |
* Represents an Hour and builds Minutes |
* <code> |
* require_once 'Calendar'.DIRECTORY_SEPARATOR.'Hour.php'; |
* $Hour = & new Calendar_Hour(2003, 10, 21, 15); // Oct 21st 2003, 3pm |
* $Hour->build(); // Build Calendar_Minute objects |
* while ($Minute = & $Hour->fetch()) { |
* echo $Minute->thisMinute().'<br />'; |
* } |
* </code> |
* @package Calendar |
* @access public |
*/ |
class Calendar_Hour extends Calendar |
{ |
/** |
* Constructs Calendar_Hour |
* @param int year e.g. 2003 |
* @param int month e.g. 5 |
* @param int day e.g. 11 |
* @param int hour e.g. 13 |
* @access public |
*/ |
function Calendar_Hour($y, $m, $d, $h) |
{ |
Calendar::Calendar($y, $m, $d, $h); |
} |
/** |
* Builds the Minutes in the Hour |
* @param array (optional) Calendar_Minute objects representing selected dates |
* @return boolean |
* @access public |
*/ |
function build($sDates=array()) |
{ |
require_once CALENDAR_ROOT.'Minute.php'; |
$mIH = $this->cE->getMinutesInHour($this->year, $this->month, $this->day, |
$this->hour); |
for ($i=0; $i < $mIH; $i++) { |
$this->children[$i]= |
new Calendar_Minute($this->year, $this->month, $this->day, |
$this->hour, $i); |
} |
if (count($sDates) > 0) { |
$this->setSelection($sDates); |
} |
return true; |
} |
/** |
* Called from build() |
* @param array |
* @return void |
* @access private |
*/ |
function setSelection($sDates) |
{ |
foreach ($sDates as $sDate) { |
if ($this->year == $sDate->thisYear() |
&& $this->month == $sDate->thisMonth() |
&& $this->day == $sDate->thisDay() |
&& $this->hour == $sDate->thisHour()) |
{ |
$key = (int)$sDate->thisMinute(); |
if (isset($this->children[$key])) { |
$sDate->setSelected(); |
$this->children[$key] = $sDate; |
} |
} |
} |
} |
} |
?> |
/branches/v1.3-critias/bibliotheque/pear/Calendar/Engine/PearDate.php |
---|
New file |
0,0 → 1,407 |
<?php |
/* vim: set expandtab tabstop=4 shiftwidth=4: */ |
// |
// +----------------------------------------------------------------------+ |
// | PHP Version 4 | |
// +----------------------------------------------------------------------+ |
// | Copyright (c) 1997-2002 The PHP Group | |
// +----------------------------------------------------------------------+ |
// | This source file is subject to version 2.02 of the PHP license, | |
// | that is bundled with this package in the file LICENSE, and is | |
// | available at through the world-wide-web at | |
// | http://www.php.net/license/3_0.txt. | |
// | If you did not receive a copy of the PHP license and are unable to | |
// | obtain it through the world-wide-web, please send a note to | |
// | license@php.net so we can mail you a copy immediately. | |
// +----------------------------------------------------------------------+ |
// | Authors: Lorenzo Alberton <l dot alberton at quipo dot it> | |
// +----------------------------------------------------------------------+ |
// |
// $Id: PearDate.php,v 1.8 2004/08/20 20:00:55 quipo Exp $ |
// |
/** |
* @package Calendar |
* @version $Id: PearDate.php,v 1.8 2004/08/20 20:00:55 quipo Exp $ |
*/ |
/** |
* Load PEAR::Date class |
*/ |
require_once 'Date.php'; |
/** |
* Performs calendar calculations based on the PEAR::Date class |
* Timestamps are in the ISO-8601 format (YYYY-MM-DD HH:MM:SS) |
* @package Calendar |
* @access protected |
*/ |
class Calendar_Engine_PearDate /* implements Calendar_Engine_Interface */ |
{ |
/** |
* Makes sure a given timestamp is only ever parsed once |
* Uses a static variable to prevent date() being used twice |
* for a date which is already known |
* @param mixed Any timestamp format recognized by Pear::Date |
* @return object Pear::Date object |
* @access protected |
*/ |
function stampCollection($stamp) |
{ |
static $stamps = array(); |
if (!isset($stamps[$stamp])) { |
$stamps[$stamp] = new Date($stamp); |
} |
return $stamps[$stamp]; |
} |
/** |
* Returns a numeric year given a iso-8601 datetime |
* @param string iso-8601 datetime (YYYY-MM-DD HH:MM:SS) |
* @return int year (e.g. 2003) |
* @access protected |
*/ |
function stampToYear($stamp) |
{ |
$date = Calendar_Engine_PearDate::stampCollection($stamp); |
return (int)$date->year; |
} |
/** |
* Returns a numeric month given a iso-8601 datetime |
* @param string iso-8601 datetime (YYYY-MM-DD HH:MM:SS) |
* @return int month (e.g. 9) |
* @access protected |
*/ |
function stampToMonth($stamp) |
{ |
$date = Calendar_Engine_PearDate::stampCollection($stamp); |
return (int)$date->month; |
} |
/** |
* Returns a numeric day given a iso-8601 datetime |
* @param string iso-8601 datetime (YYYY-MM-DD HH:MM:SS) |
* @return int day (e.g. 15) |
* @access protected |
*/ |
function stampToDay($stamp) |
{ |
$date = Calendar_Engine_PearDate::stampCollection($stamp); |
return (int)$date->day; |
} |
/** |
* Returns a numeric hour given a iso-8601 datetime |
* @param string iso-8601 datetime (YYYY-MM-DD HH:MM:SS) |
* @return int hour (e.g. 13) |
* @access protected |
*/ |
function stampToHour($stamp) |
{ |
$date = Calendar_Engine_PearDate::stampCollection($stamp); |
return (int)$date->hour; |
} |
/** |
* Returns a numeric minute given a iso-8601 datetime |
* @param string iso-8601 datetime (YYYY-MM-DD HH:MM:SS) |
* @return int minute (e.g. 34) |
* @access protected |
*/ |
function stampToMinute($stamp) |
{ |
$date = Calendar_Engine_PearDate::stampCollection($stamp); |
return (int)$date->minute; |
} |
/** |
* Returns a numeric second given a iso-8601 datetime |
* @param string iso-8601 datetime (YYYY-MM-DD HH:MM:SS) |
* @return int second (e.g. 51) |
* @access protected |
*/ |
function stampToSecond($stamp) |
{ |
$date = Calendar_Engine_PearDate::stampCollection($stamp); |
return (int)$date->second; |
} |
/** |
* Returns a iso-8601 datetime |
* @param int year (2003) |
* @param int month (9) |
* @param int day (13) |
* @param int hour (13) |
* @param int minute (34) |
* @param int second (53) |
* @return string iso-8601 datetime |
* @access protected |
*/ |
function dateToStamp($y, $m, $d, $h=0, $i=0, $s=0) |
{ |
$r = array(); |
Calendar_Engine_PearDate::adjustDate($y, $m, $d, $h, $i, $s); |
$key = $y.$m.$d.$h.$i.$s; |
if (!isset($r[$key])) { |
$r[$key] = sprintf("%04d-%02d-%02d %02d:%02d:%02d", |
$y, $m, $d, $h, $i, $s); |
} |
return $r[$key]; |
} |
/** |
* Set the correct date values (useful for math operations on dates) |
* @param int year (2003) |
* @param int month (9) |
* @param int day (13) |
* @param int hour (13) |
* @param int minute (34) |
* @param int second (53) |
* @access protected |
*/ |
function adjustDate(&$y, &$m, &$d, &$h, &$i, &$s) |
{ |
if ($s < 0) { |
$m -= floor($s / 60); |
$s = -$s % 60; |
} |
if ($s > 60) { |
$m += floor($s / 60); |
$s %= 60; |
} |
if ($i < 0) { |
$h -= floor($i / 60); |
$i = -$i % 60; |
} |
if ($i > 60) { |
$h += floor($i / 60); |
$i %= 60; |
} |
if ($h < 0) { |
$d -= floor($h / 24); |
$h = -$h % 24; |
} |
if ($h > 24) { |
$d += floor($h / 24); |
$h %= 24; |
} |
for(; $m < 1; $y--, $m+=12); |
for(; $m > 12; $y++, $m-=12); |
while ($d < 1) { |
if ($m > 1) { |
$m--; |
} else { |
$m = 12; |
$y--; |
} |
$d += Date_Calc::daysInMonth($m, $y); |
} |
for ($max_days = Date_Calc::daysInMonth($m, $y); $d > $max_days; ) { |
$d -= $max_days; |
if ($m < 12) { |
$m++; |
} else { |
$m = 1; |
$y++; |
} |
} |
} |
/** |
* The upper limit on years that the Calendar Engine can work with |
* @return int 9999 |
* @access protected |
*/ |
function getMaxYears() |
{ |
return 9999; |
} |
/** |
* The lower limit on years that the Calendar Engine can work with |
* @return int 0 |
* @access protected |
*/ |
function getMinYears() |
{ |
return 0; |
} |
/** |
* Returns the number of months in a year |
* @return int (12) |
* @access protected |
*/ |
function getMonthsInYear($y=null) |
{ |
return 12; |
} |
/** |
* Returns the number of days in a month, given year and month |
* @param int year (2003) |
* @param int month (9) |
* @return int days in month |
* @access protected |
*/ |
function getDaysInMonth($y, $m) |
{ |
return (int)Date_Calc::daysInMonth($m, $y); |
} |
/** |
* Returns numeric representation of the day of the week in a month, |
* given year and month |
* @param int year (2003) |
* @param int month (9) |
* @return int from 0 to 7 |
* @access protected |
*/ |
function getFirstDayInMonth($y, $m) |
{ |
return (int)Date_Calc::dayOfWeek(1, $m, $y); |
} |
/** |
* Returns the number of days in a week |
* @param int year (2003) |
* @param int month (9) |
* @param int day (4) |
* @return int (7) |
* @access protected |
*/ |
function getDaysInWeek($y=NULL, $m=NULL, $d=NULL) |
{ |
return 7; |
} |
/** |
* Returns the number of the week in the year (ISO-8601), given a date |
* @param int year (2003) |
* @param int month (9) |
* @param int day (4) |
* @return int week number |
* @access protected |
*/ |
function getWeekNInYear($y, $m, $d) |
{ |
return Date_Calc::weekOfYear($d, $m, $y); //beware, Date_Calc doesn't follow ISO-8601 standard! |
} |
/** |
* Returns the number of the week in the month, given a date |
* @param int year (2003) |
* @param int month (9) |
* @param int day (4) |
* @param int first day of the week (default: monday) |
* @return int week number |
* @access protected |
*/ |
function getWeekNInMonth($y, $m, $d, $firstDay=1) |
{ |
$weekEnd = ($firstDay == 0) ? $this->getDaysInWeek()-1 : $firstDay-1; |
$end_of_week = (int)Date_Calc::nextDayOfWeek($weekEnd, 1, $m, $y, '%e', true); |
$w = 1; |
while ($d > $end_of_week) { |
++$w; |
$end_of_week += $this->getDaysInWeek(); |
} |
return $w; |
} |
/** |
* Returns the number of weeks in the month |
* @param int year (2003) |
* @param int month (9) |
* @param int first day of the week (default: monday) |
* @return int weeks number |
* @access protected |
*/ |
function getWeeksInMonth($y, $m, $firstDay=1) |
{ |
$FDOM = Date_Calc::firstOfMonthWeekday($m, $y); |
if ($FDOM == 0) { |
$FDOM = $this->getDaysInWeek(); |
} |
if ($FDOM > $firstDay) { |
$daysInTheFirstWeek = $this->getDaysInWeek() - $FDOM + $firstDay; |
$weeks = 1; |
} else { |
$daysInTheFirstWeek = $firstDay - $FDOM; |
$weeks = 0; |
} |
$daysInTheFirstWeek %= $this->getDaysInWeek(); |
return (int)(ceil(($this->getDaysInMonth($y, $m) - $daysInTheFirstWeek) / |
$this->getDaysInWeek()) + $weeks); |
} |
/** |
* Returns the number of the day of the week (0=sunday, 1=monday...) |
* @param int year (2003) |
* @param int month (9) |
* @param int day (4) |
* @return int weekday number |
* @access protected |
*/ |
function getDayOfWeek($y, $m, $d) |
{ |
return Date_Calc::dayOfWeek($d, $m, $y); |
} |
/** |
* Returns a list of integer days of the week beginning 0 |
* @param int year (2003) |
* @param int month (9) |
* @param int day (4) |
* @return array (0, 1, 2, 3, 4, 5, 6) 1 = Monday |
* @access protected |
*/ |
function getWeekDays($y=NULL, $m=NULL, $d=NULL) |
{ |
return array(0, 1, 2, 3, 4, 5, 6); |
} |
/** |
* Returns the default first day of the week |
* @param int year (2003) |
* @param int month (9) |
* @param int day (4) |
* @return int (default 1 = Monday) |
* @access protected |
*/ |
function getFirstDayOfWeek($y=NULL, $m=NULL, $d=NULL) |
{ |
return 1; |
} |
/** |
* Returns the number of hours in a day |
* @return int (24) |
* @access protected |
*/ |
function getHoursInDay($y=null,$m=null,$d=null) |
{ |
return 24; |
} |
/** |
* Returns the number of minutes in an hour |
* @return int (60) |
* @access protected |
*/ |
function getMinutesInHour($y=null,$m=null,$d=null,$h=null) |
{ |
return 60; |
} |
/** |
* Returns the number of seconds in a minutes |
* @return int (60) |
* @access protected |
*/ |
function getSecondsInMinute($y=null,$m=null,$d=null,$h=null,$i=null) |
{ |
return 60; |
} |
} |
?> |
/branches/v1.3-critias/bibliotheque/pear/Calendar/Engine/UnixTS.php |
---|
New file |
0,0 → 1,365 |
<?php |
/* vim: set expandtab tabstop=4 shiftwidth=4: */ |
// |
// +----------------------------------------------------------------------+ |
// | PHP Version 4 | |
// +----------------------------------------------------------------------+ |
// | Copyright (c) 1997-2002 The PHP Group | |
// +----------------------------------------------------------------------+ |
// | This source file is subject to version 2.02 of the PHP license, | |
// | that is bundled with this package in the file LICENSE, and is | |
// | available at through the world-wide-web at | |
// | http://www.php.net/license/3_0.txt. | |
// | If you did not receive a copy of the PHP license and are unable to | |
// | obtain it through the world-wide-web, please send a note to | |
// | license@php.net so we can mail you a copy immediately. | |
// +----------------------------------------------------------------------+ |
// | Authors: Harry Fuecks <hfuecks@phppatterns.com> | |
// +----------------------------------------------------------------------+ |
// |
// $Id: UnixTS.php,v 1.9 2004/08/20 20:00:55 quipo Exp $ |
// |
/** |
* @package Calendar |
* @version $Id: UnixTS.php,v 1.9 2004/08/20 20:00:55 quipo Exp $ |
*/ |
/** |
* Performs calendar calculations based on the PHP date() function and |
* Unix timestamps (using PHP's mktime() function). |
* @package Calendar |
* @access protected |
*/ |
class Calendar_Engine_UnixTS /* implements Calendar_Engine_Interface */ |
{ |
/** |
* Makes sure a given timestamp is only ever parsed once |
* <pre> |
* array ( |
* [0] => year (e.g 2003), |
* [1] => month (e.g 9), |
* [2] => day (e.g 6), |
* [3] => hour (e.g 14), |
* [4] => minute (e.g 34), |
* [5] => second (e.g 45), |
* [6] => num days in month (e.g. 31), |
* [7] => week in year (e.g. 50), |
* [8] => day in week (e.g. 0 for Sunday) |
* ) |
* </pre> |
* Uses a static variable to prevent date() being used twice |
* for a date which is already known |
* @param int Unix timestamp |
* @return array |
* @access protected |
*/ |
function stampCollection($stamp) |
{ |
static $stamps = array(); |
if ( !isset($stamps[$stamp]) ) { |
$date = @date('Y n j H i s t W w',$stamp); |
$stamps[$stamp] = sscanf($date, "%d %d %d %d %d %d %d %d %d"); |
} |
return $stamps[$stamp]; |
} |
/** |
* Returns a numeric year given a timestamp |
* @param int Unix timestamp |
* @return int year (e.g. 2003) |
* @access protected |
*/ |
function stampToYear($stamp) |
{ |
$date = Calendar_Engine_UnixTS::stampCollection($stamp); |
return (int)$date[0]; |
} |
/** |
* Returns a numeric month given a timestamp |
* @param int Unix timestamp |
* @return int month (e.g. 9) |
* @access protected |
*/ |
function stampToMonth($stamp) |
{ |
$date = Calendar_Engine_UnixTS::stampCollection($stamp); |
return (int)$date[1]; |
} |
/** |
* Returns a numeric day given a timestamp |
* @param int Unix timestamp |
* @return int day (e.g. 15) |
* @access protected |
*/ |
function stampToDay($stamp) |
{ |
$date = Calendar_Engine_UnixTS::stampCollection($stamp); |
return (int)$date[2]; |
} |
/** |
* Returns a numeric hour given a timestamp |
* @param int Unix timestamp |
* @return int hour (e.g. 13) |
* @access protected |
*/ |
function stampToHour($stamp) |
{ |
$date = Calendar_Engine_UnixTS::stampCollection($stamp); |
return (int)$date[3]; |
} |
/** |
* Returns a numeric minute given a timestamp |
* @param int Unix timestamp |
* @return int minute (e.g. 34) |
* @access protected |
*/ |
function stampToMinute($stamp) |
{ |
$date = Calendar_Engine_UnixTS::stampCollection($stamp); |
return (int)$date[4]; |
} |
/** |
* Returns a numeric second given a timestamp |
* @param int Unix timestamp |
* @return int second (e.g. 51) |
* @access protected |
*/ |
function stampToSecond($stamp) |
{ |
$date = Calendar_Engine_UnixTS::stampCollection($stamp); |
return (int)$date[5]; |
} |
/** |
* Returns a timestamp |
* @param int year (2003) |
* @param int month (9) |
* @param int day (13) |
* @param int hour (13) |
* @param int minute (34) |
* @param int second (53) |
* @return int Unix timestamp |
* @access protected |
*/ |
function dateToStamp($y, $m, $d, $h=0, $i=0, $s=0) |
{ |
static $dates = array(); |
if ( !isset($dates[$y][$m][$d][$h][$i][$s]) ) { |
$dates[$y][$m][$d][$h][$i][$s] = @mktime($h, $i, $s, $m, $d, $y); |
} |
return $dates[$y][$m][$d][$h][$i][$s]; |
} |
/** |
* The upper limit on years that the Calendar Engine can work with |
* @return int (2037) |
* @access protected |
*/ |
function getMaxYears() |
{ |
return 2037; |
} |
/** |
* The lower limit on years that the Calendar Engine can work with |
* @return int (1970 if it's Windows and 1902 for all other OSs) |
* @access protected |
*/ |
function getMinYears() |
{ |
return $min = strpos(PHP_OS, 'WIN') === false ? 1902 : 1970; |
} |
/** |
* Returns the number of months in a year |
* @return int (12) |
* @access protected |
*/ |
function getMonthsInYear($y=null) |
{ |
return 12; |
} |
/** |
* Returns the number of days in a month, given year and month |
* @param int year (2003) |
* @param int month (9) |
* @return int days in month |
* @access protected |
*/ |
function getDaysInMonth($y, $m) |
{ |
$stamp = Calendar_Engine_UnixTS::dateToStamp($y,$m,1); |
$date = Calendar_Engine_UnixTS::stampCollection($stamp); |
return $date[6]; |
} |
/** |
* Returns numeric representation of the day of the week in a month, |
* given year and month |
* @param int year (2003) |
* @param int month (9) |
* @return int from 0 to 6 |
* @access protected |
*/ |
function getFirstDayInMonth($y, $m) |
{ |
$stamp = Calendar_Engine_UnixTS::dateToStamp($y,$m,1); |
$date = Calendar_Engine_UnixTS::stampCollection($stamp); |
return $date[8]; |
} |
/** |
* Returns the number of days in a week |
* @param int year (2003) |
* @param int month (9) |
* @param int day (4) |
* @return int (7) |
* @access protected |
*/ |
function getDaysInWeek($y=NULL, $m=NULL, $d=NULL) |
{ |
return 7; |
} |
/** |
* Returns the number of the week in the year (ISO-8601), given a date |
* @param int year (2003) |
* @param int month (9) |
* @param int day (4) |
* @return int week number |
* @access protected |
*/ |
function getWeekNInYear($y, $m, $d) |
{ |
$stamp = Calendar_Engine_UnixTS::dateToStamp($y,$m,$d); |
$date = Calendar_Engine_UnixTS::stampCollection($stamp); |
return $date[7]; |
} |
/** |
* Returns the number of the week in the month, given a date |
* @param int year (2003) |
* @param int month (9) |
* @param int day (4) |
* @param int first day of the week (default: monday) |
* @return int week number |
* @access protected |
*/ |
function getWeekNInMonth($y, $m, $d, $firstDay=1) |
{ |
$weekEnd = ($firstDay == 0) ? $this->getDaysInWeek()-1 : $firstDay-1; |
$end_of_week = 1; |
while (@date('w', @mktime(0, 0, 0, $m, $end_of_week, $y)) != $weekEnd) { |
++$end_of_week; //find first weekend of the month |
} |
$w = 1; |
while ($d > $end_of_week) { |
++$w; |
$end_of_week += $this->getDaysInWeek(); |
} |
return $w; |
} |
/** |
* Returns the number of weeks in the month |
* @param int year (2003) |
* @param int month (9) |
* @param int first day of the week (default: monday) |
* @return int weeks number |
* @access protected |
*/ |
function getWeeksInMonth($y, $m, $firstDay=1) |
{ |
$FDOM = $this->getFirstDayInMonth($y, $m); |
if ($FDOM == 0) { |
$FDOM = $this->getDaysInWeek(); |
} |
if ($FDOM > $firstDay) { |
$daysInTheFirstWeek = $this->getDaysInWeek() - $FDOM + $firstDay; |
$weeks = 1; |
} else { |
$daysInTheFirstWeek = $firstDay - $FDOM; |
$weeks = 0; |
} |
$daysInTheFirstWeek %= $this->getDaysInWeek(); |
return (int)(ceil(($this->getDaysInMonth($y, $m) - $daysInTheFirstWeek) / |
$this->getDaysInWeek()) + $weeks); |
} |
/** |
* Returns the number of the day of the week (0=sunday, 1=monday...) |
* @param int year (2003) |
* @param int month (9) |
* @param int day (4) |
* @return int weekday number |
* @access protected |
*/ |
function getDayOfWeek($y, $m, $d) |
{ |
$stamp = Calendar_Engine_UnixTS::dateToStamp($y,$m,$d); |
$date = Calendar_Engine_UnixTS::stampCollection($stamp); |
return $date[8]; |
} |
/** |
* Returns a list of integer days of the week beginning 0 |
* @param int year (2003) |
* @param int month (9) |
* @param int day (4) |
* @return array (0,1,2,3,4,5,6) 1 = Monday |
* @access protected |
*/ |
function getWeekDays($y=NULL, $m=NULL, $d=NULL) |
{ |
return array(0, 1, 2, 3, 4, 5, 6); |
} |
/** |
* Returns the default first day of the week |
* @param int year (2003) |
* @param int month (9) |
* @param int day (4) |
* @return int (default 1 = Monday) |
* @access protected |
*/ |
function getFirstDayOfWeek($y=NULL, $m=NULL, $d=NULL) |
{ |
return 1; |
} |
/** |
* Returns the number of hours in a day |
* @return int (24) |
* @access protected |
*/ |
function getHoursInDay($y=null,$m=null,$d=null) |
{ |
return 24; |
} |
/** |
* Returns the number of minutes in an hour |
* @return int (60) |
* @access protected |
*/ |
function getMinutesInHour($y=null,$m=null,$d=null,$h=null) |
{ |
return 60; |
} |
/** |
* Returns the number of seconds in a minutes |
* @return int (60) |
* @access protected |
*/ |
function getSecondsInMinute($y=null,$m=null,$d=null,$h=null,$i=null) |
{ |
return 60; |
} |
} |
?> |
/branches/v1.3-critias/bibliotheque/pear/Calendar/Engine/Interface.php |
---|
New file |
0,0 → 1,293 |
<?php |
/* vim: set expandtab tabstop=4 shiftwidth=4: */ |
// |
// +----------------------------------------------------------------------+ |
// | PHP Version 4 | |
// +----------------------------------------------------------------------+ |
// | Copyright (c) 1997-2002 The PHP Group | |
// +----------------------------------------------------------------------+ |
// | This source file is subject to version 2.02 of the PHP license, | |
// | that is bundled with this package in the file LICENSE, and is | |
// | available at through the world-wide-web at | |
// | http://www.php.net/license/3_0.txt. | |
// | If you did not receive a copy of the PHP license and are unable to | |
// | obtain it through the world-wide-web, please send a note to | |
// | license@php.net so we can mail you a copy immediately. | |
// +----------------------------------------------------------------------+ |
// | Authors: Harry Fuecks <hfuecks@phppatterns.com> | |
// +----------------------------------------------------------------------+ |
// |
// $Id: Interface.php,v 1.5 2004/08/16 12:29:18 hfuecks Exp $ |
// |
/** |
* @package Calendar |
* @version $Id: Interface.php,v 1.5 2004/08/16 12:29:18 hfuecks Exp $ |
*/ |
/** |
* The methods the classes implementing the Calendar_Engine must implement. |
* Note this class is not used but simply to help development |
* @package Calendar |
* @access protected |
*/ |
class Calendar_Engine_Interface |
{ |
/** |
* Provides a mechansim to make sure parsing of timestamps |
* into human dates is only performed once per timestamp. |
* Typically called "internally" by methods like stampToYear. |
* Return value can vary, depending on the specific implementation |
* @param int timestamp (depending on implementation) |
* @return mixed |
* @access protected |
*/ |
function stampCollection($stamp) |
{ |
} |
/** |
* Returns a numeric year given a timestamp |
* @param int timestamp (depending on implementation) |
* @return int year (e.g. 2003) |
* @access protected |
*/ |
function stampToYear($stamp) |
{ |
} |
/** |
* Returns a numeric month given a timestamp |
* @param int timestamp (depending on implementation) |
* @return int month (e.g. 9) |
* @access protected |
*/ |
function stampToMonth($stamp) |
{ |
} |
/** |
* Returns a numeric day given a timestamp |
* @param int timestamp (depending on implementation) |
* @return int day (e.g. 15) |
* @access protected |
*/ |
function stampToDay($stamp) |
{ |
} |
/** |
* Returns a numeric hour given a timestamp |
* @param int timestamp (depending on implementation) |
* @return int hour (e.g. 13) |
* @access protected |
*/ |
function stampToHour($stamp) |
{ |
} |
/** |
* Returns a numeric minute given a timestamp |
* @param int timestamp (depending on implementation) |
* @return int minute (e.g. 34) |
* @access protected |
*/ |
function stampToMinute($stamp) |
{ |
} |
/** |
* Returns a numeric second given a timestamp |
* @param int timestamp (depending on implementation) |
* @return int second (e.g. 51) |
* @access protected |
*/ |
function stampToSecond($stamp) |
{ |
} |
/** |
* Returns a timestamp. Can be worth "caching" generated |
* timestamps in a static variable, identified by the |
* params this method accepts, to timestamp will only |
* be calculated once. |
* @param int year (e.g. 2003) |
* @param int month (e.g. 9) |
* @param int day (e.g. 13) |
* @param int hour (e.g. 13) |
* @param int minute (e.g. 34) |
* @param int second (e.g. 53) |
* @return int (depends on implementation) |
* @access protected |
*/ |
function dateToStamp($y,$m,$d,$h,$i,$s) |
{ |
} |
/** |
* The upper limit on years that the Calendar Engine can work with |
* @return int (e.g. 2037) |
* @access protected |
*/ |
function getMaxYears() |
{ |
} |
/** |
* The lower limit on years that the Calendar Engine can work with |
* @return int (e.g 1902) |
* @access protected |
*/ |
function getMinYears() |
{ |
} |
/** |
* Returns the number of months in a year |
* @param int (optional) year to get months for |
* @return int (e.g. 12) |
* @access protected |
*/ |
function getMonthsInYear($y=null) |
{ |
} |
/** |
* Returns the number of days in a month, given year and month |
* @param int year (e.g. 2003) |
* @param int month (e.g. 9) |
* @return int days in month |
* @access protected |
*/ |
function getDaysInMonth($y, $m) |
{ |
} |
/** |
* Returns numeric representation of the day of the week in a month, |
* given year and month |
* @param int year (e.g. 2003) |
* @param int month (e.g. 9) |
* @return int |
* @access protected |
*/ |
function getFirstDayInMonth ($y, $m) |
{ |
} |
/** |
* Returns the number of days in a week |
* @param int year (2003) |
* @param int month (9) |
* @param int day (4) |
* @return int (e.g. 7) |
* @access protected |
*/ |
function getDaysInWeek($y=NULL, $m=NULL, $d=NULL) |
{ |
} |
/** |
* Returns the number of the week in the year (ISO-8601), given a date |
* @param int year (2003) |
* @param int month (9) |
* @param int day (4) |
* @return int week number |
* @access protected |
*/ |
function getWeekNInYear($y, $m, $d) |
{ |
} |
/** |
* Returns the number of the week in the month, given a date |
* @param int year (2003) |
* @param int month (9) |
* @param int day (4) |
* @param int first day of the week (default: 1 - monday) |
* @return int week number |
* @access protected |
*/ |
function getWeekNInMonth($y, $m, $d, $firstDay=1) |
{ |
} |
/** |
* Returns the number of weeks in the month |
* @param int year (2003) |
* @param int month (9) |
* @param int first day of the week (default: 1 - monday) |
* @return int weeks number |
* @access protected |
*/ |
function getWeeksInMonth($y, $m) |
{ |
} |
/** |
* Returns the number of the day of the week (0=sunday, 1=monday...) |
* @param int year (2003) |
* @param int month (9) |
* @param int day (4) |
* @return int weekday number |
* @access protected |
*/ |
function getDayOfWeek($y, $m, $d) |
{ |
} |
/** |
* Returns the numeric values of the days of the week. |
* @param int year (2003) |
* @param int month (9) |
* @param int day (4) |
* @return array list of numeric values of days in week, beginning 0 |
* @access protected |
*/ |
function getWeekDays($y=NULL, $m=NULL, $d=NULL) |
{ |
} |
/** |
* Returns the default first day of the week as an integer. Must be a |
* member of the array returned from getWeekDays |
* @param int year (2003) |
* @param int month (9) |
* @param int day (4) |
* @return int (e.g. 1 for Monday) |
* @see getWeekDays |
* @access protected |
*/ |
function getFirstDayOfWeek($y=NULL, $m=NULL, $d=NULL) |
{ |
} |
/** |
* Returns the number of hours in a day<br> |
* @param int (optional) day to get hours for |
* @return int (e.g. 24) |
* @access protected |
*/ |
function getHoursInDay($y=null,$m=null,$d=null) |
{ |
} |
/** |
* Returns the number of minutes in an hour |
* @param int (optional) hour to get minutes for |
* @return int |
* @access protected |
*/ |
function getMinutesInHour($y=null,$m=null,$d=null,$h=null) |
{ |
} |
/** |
* Returns the number of seconds in a minutes |
* @param int (optional) minute to get seconds for |
* @return int |
* @access protected |
*/ |
function getSecondsInMinute($y=null,$m=null,$d=null,$h=null,$i=null) |
{ |
} |
} |
?> |
/branches/v1.3-critias/bibliotheque/pear/Calendar/Decorator.php |
---|
New file |
0,0 → 1,558 |
<?php |
/* vim: set expandtab tabstop=4 shiftwidth=4: */ |
// |
// +----------------------------------------------------------------------+ |
// | PHP Version 4 | |
// +----------------------------------------------------------------------+ |
// | Copyright (c) 1997-2002 The PHP Group | |
// +----------------------------------------------------------------------+ |
// | This source file is subject to version 2.02 of the PHP license, | |
// | that is bundled with this package in the file LICENSE, and is | |
// | available at through the world-wide-web at | |
// | http://www.php.net/license/3_0.txt. | |
// | If you did not receive a copy of the PHP license and are unable to | |
// | obtain it through the world-wide-web, please send a note to | |
// | license@php.net so we can mail you a copy immediately. | |
// +----------------------------------------------------------------------+ |
// | Authors: Harry Fuecks <hfuecks@phppatterns.com> | |
// +----------------------------------------------------------------------+ |
// |
// $Id: Decorator.php,v 1.3 2005/10/22 10:29:46 quipo Exp $ |
// |
/** |
* @package Calendar |
* @version $Id: Decorator.php,v 1.3 2005/10/22 10:29:46 quipo Exp $ |
*/ |
/** |
* Decorates any calendar class. |
* Create a subclass of this class for your own "decoration". |
* Used for "selections" |
* <code> |
* class DayDecorator extends Calendar_Decorator |
* { |
* function thisDay($format = 'int') |
* { |
.* $day = parent::thisDay('timestamp'); |
.* return date('D', $day); |
* } |
* } |
* $Day = & new Calendar_Day(2003, 10, 25); |
* $DayDecorator = & new DayDecorator($Day); |
* echo $DayDecorator->thisDay(); // Outputs "Sat" |
* </code> |
* @abstract |
* @package Calendar |
*/ |
class Calendar_Decorator |
{ |
/** |
* Subclass of Calendar being decorated |
* @var object |
* @access private |
*/ |
var $calendar; |
/** |
* Constructs the Calendar_Decorator |
* @param object subclass to Calendar to decorate |
*/ |
function Calendar_Decorator(& $calendar) |
{ |
$this->calendar = & $calendar; |
} |
/** |
* Defines the calendar by a Unix timestamp, replacing values |
* passed to the constructor |
* @param int Unix timestamp |
* @return void |
* @access public |
*/ |
function setTimestamp($ts) |
{ |
$this->calendar->setTimestamp($ts); |
} |
/** |
* Returns a timestamp from the current date / time values. Format of |
* timestamp depends on Calendar_Engine implementation being used |
* @return int timestamp |
* @access public |
*/ |
function getTimestamp() |
{ |
return $this->calendar->getTimeStamp(); |
} |
/** |
* Defines calendar object as selected (e.g. for today) |
* @param boolean state whether Calendar subclass |
* @return void |
* @access public |
*/ |
function setSelected($state = true) |
{ |
$this->calendar->setSelected($state = true); |
} |
/** |
* True if the calendar subclass object is selected (e.g. today) |
* @return boolean |
* @access public |
*/ |
function isSelected() |
{ |
return $this->calendar->isSelected(); |
} |
/** |
* Adjusts the date (helper method) |
* @return void |
* @access public |
*/ |
function adjust() |
{ |
$this->calendar->adjust(); |
} |
/** |
* Returns the date as an associative array (helper method) |
* @param mixed timestamp (leave empty for current timestamp) |
* @return array |
* @access public |
*/ |
function toArray($stamp=null) |
{ |
return $this->calendar->toArray($stamp); |
} |
/** |
* Returns the value as an associative array (helper method) |
* @param string type of date object that return value represents |
* @param string $format ['int' | 'array' | 'timestamp' | 'object'] |
* @param mixed timestamp (depending on Calendar engine being used) |
* @param int integer default value (i.e. give me the answer quick) |
* @return mixed |
* @access private |
*/ |
function returnValue($returnType, $format, $stamp, $default) |
{ |
return $this->calendar->returnValue($returnType, $format, $stamp, $default); |
} |
/** |
* Defines Day object as first in a week |
* Only used by Calendar_Month_Weekdays::build() |
* @param boolean state |
* @return void |
* @access private |
*/ |
function setFirst ($state = true) |
{ |
if ( method_exists($this->calendar,'setFirst') ) { |
$this->calendar->setFirst($state); |
} |
} |
/** |
* Defines Day object as last in a week |
* Used only following Calendar_Month_Weekdays::build() |
* @param boolean state |
* @return void |
* @access private |
*/ |
function setLast($state = true) |
{ |
if ( method_exists($this->calendar,'setLast') ) { |
$this->calendar->setLast($state); |
} |
} |
/** |
* Returns true if Day object is first in a Week |
* Only relevant when Day is created by Calendar_Month_Weekdays::build() |
* @return boolean |
* @access public |
*/ |
function isFirst() { |
if ( method_exists($this->calendar,'isFirst') ) { |
return $this->calendar->isFirst(); |
} |
} |
/** |
* Returns true if Day object is last in a Week |
* Only relevant when Day is created by Calendar_Month_Weekdays::build() |
* @return boolean |
* @access public |
*/ |
function isLast() |
{ |
if ( method_exists($this->calendar,'isLast') ) { |
return $this->calendar->isLast(); |
} |
} |
/** |
* Defines Day object as empty |
* Only used by Calendar_Month_Weekdays::build() |
* @param boolean state |
* @return void |
* @access private |
*/ |
function setEmpty ($state = true) |
{ |
if ( method_exists($this->calendar,'setEmpty') ) { |
$this->calendar->setEmpty($state); |
} |
} |
/** |
* @return boolean |
* @access public |
*/ |
function isEmpty() |
{ |
if ( method_exists($this->calendar,'isEmpty') ) { |
return $this->calendar->isEmpty(); |
} |
} |
/** |
* Build the children |
* @param array containing Calendar objects to select (optional) |
* @return boolean |
* @access public |
* @abstract |
*/ |
function build($sDates = array()) |
{ |
$this->calendar->build($sDates); |
} |
/** |
* Iterator method for fetching child Calendar subclass objects |
* (e.g. a minute from an hour object). On reaching the end of |
* the collection, returns false and resets the collection for |
* further iteratations. |
* @return mixed either an object subclass of Calendar or false |
* @access public |
*/ |
function fetch() |
{ |
return $this->calendar->fetch(); |
} |
/** |
* Fetches all child from the current collection of children |
* @return array |
* @access public |
*/ |
function fetchAll() |
{ |
return $this->calendar->fetchAll(); |
} |
/** |
* Get the number Calendar subclass objects stored in the internal |
* collection. |
* @return int |
* @access public |
*/ |
function size() |
{ |
return $this->calendar->size(); |
} |
/** |
* Determine whether this date is valid, with the bounds determined by |
* the Calendar_Engine. The call is passed on to |
* Calendar_Validator::isValid |
* @return boolean |
* @access public |
*/ |
function isValid() |
{ |
return $this->calendar->isValid(); |
} |
/** |
* Returns an instance of Calendar_Validator |
* @return Calendar_Validator |
* @access public |
*/ |
function & getValidator() |
{ |
$validator = $this->calendar->getValidator(); |
return $validator; |
} |
/** |
* Returns a reference to the current Calendar_Engine being used. Useful |
* for Calendar_Table_Helper and Calendar_Validator |
* @return object implementing Calendar_Engine_Inteface |
* @access private |
*/ |
function & getEngine() |
{ |
return $this->calendar->getEngine(); |
} |
/** |
* Returns the value for the previous year |
* @param string return value format ['int' | 'timestamp' | 'object' | 'array'] |
* @return int e.g. 2002 or timestamp |
* @access public |
*/ |
function prevYear($format = 'int') |
{ |
return $this->calendar->prevYear($format); |
} |
/** |
* Returns the value for this year |
* @param string return value format ['int' | 'timestamp' | 'object' | 'array'] |
* @return int e.g. 2003 or timestamp |
* @access public |
*/ |
function thisYear($format = 'int') |
{ |
return $this->calendar->thisYear($format); |
} |
/** |
* Returns the value for next year |
* @param string return value format ['int' | 'timestamp' | 'object' | 'array'] |
* @return int e.g. 2004 or timestamp |
* @access public |
*/ |
function nextYear($format = 'int') |
{ |
return $this->calendar->nextYear($format); |
} |
/** |
* Returns the value for the previous month |
* @param string return value format ['int' | 'timestamp' | 'object' | 'array'] |
* @return int e.g. 4 or Unix timestamp |
* @access public |
*/ |
function prevMonth($format = 'int') |
{ |
return $this->calendar->prevMonth($format); |
} |
/** |
* Returns the value for this month |
* @param string return value format ['int' | 'timestamp' | 'object' | 'array'] |
* @return int e.g. 5 or timestamp |
* @access public |
*/ |
function thisMonth($format = 'int') |
{ |
return $this->calendar->thisMonth($format); |
} |
/** |
* Returns the value for next month |
* @param string return value format ['int' | 'timestamp' | 'object' | 'array'] |
* @return int e.g. 6 or timestamp |
* @access public |
*/ |
function nextMonth($format = 'int') |
{ |
return $this->calendar->nextMonth($format); |
} |
/** |
* Returns the value for the previous week |
* @param string return value format ['int' | 'timestamp' | 'object' | 'array'] |
* @return int e.g. 4 or Unix timestamp |
* @access public |
*/ |
function prevWeek($format = 'n_in_month') |
{ |
if ( method_exists($this->calendar,'prevWeek') ) { |
return $this->calendar->prevWeek($format); |
} else { |
require_once 'PEAR.php'; |
PEAR::raiseError( |
'Cannot call prevWeek on Calendar object of type: '. |
get_class($this->calendar), 133, PEAR_ERROR_TRIGGER, |
E_USER_NOTICE, 'Calendar_Decorator::prevWeek()'); |
return false; |
} |
} |
/** |
* Returns the value for this week |
* @param string return value format ['int' | 'timestamp' | 'object' | 'array'] |
* @return int e.g. 5 or timestamp |
* @access public |
*/ |
function thisWeek($format = 'n_in_month') |
{ |
if ( method_exists($this->calendar,'thisWeek') ) { |
return $this->calendar->thisWeek($format); |
} else { |
require_once 'PEAR.php'; |
PEAR::raiseError( |
'Cannot call thisWeek on Calendar object of type: '. |
get_class($this->calendar), 133, PEAR_ERROR_TRIGGER, |
E_USER_NOTICE, 'Calendar_Decorator::thisWeek()'); |
return false; |
} |
} |
/** |
* Returns the value for next week |
* @param string return value format ['int' | 'timestamp' | 'object' | 'array'] |
* @return int e.g. 6 or timestamp |
* @access public |
*/ |
function nextWeek($format = 'n_in_month') |
{ |
if ( method_exists($this->calendar,'nextWeek') ) { |
return $this->calendar->nextWeek($format); |
} else { |
require_once 'PEAR.php'; |
PEAR::raiseError( |
'Cannot call thisWeek on Calendar object of type: '. |
get_class($this->calendar), 133, PEAR_ERROR_TRIGGER, |
E_USER_NOTICE, 'Calendar_Decorator::nextWeek()'); |
return false; |
} |
} |
/** |
* Returns the value for the previous day |
* @param string return value format ['int' | 'timestamp' | 'object' | 'array'] |
* @return int e.g. 10 or timestamp |
* @access public |
*/ |
function prevDay($format = 'int') { |
return $this->calendar->prevDay($format); |
} |
/** |
* Returns the value for this day |
* @param string return value format ['int' | 'timestamp' | 'object' | 'array'] |
* @return int e.g. 11 or timestamp |
* @access public |
*/ |
function thisDay($format = 'int') |
{ |
return $this->calendar->thisDay($format); |
} |
/** |
* Returns the value for the next day |
* @param string return value format ['int' | 'timestamp' | 'object' | 'array'] |
* @return int e.g. 12 or timestamp |
* @access public |
*/ |
function nextDay($format = 'int') |
{ |
return $this->calendar->nextDay($format); |
} |
/** |
* Returns the value for the previous hour |
* @param string return value format ['int' | 'timestamp' | 'object' | 'array'] |
* @return int e.g. 13 or timestamp |
* @access public |
*/ |
function prevHour($format = 'int') |
{ |
return $this->calendar->prevHour($format); |
} |
/** |
* Returns the value for this hour |
* @param string return value format ['int' | 'timestamp' | 'object' | 'array'] |
* @return int e.g. 14 or timestamp |
* @access public |
*/ |
function thisHour($format = 'int') |
{ |
return $this->calendar->thisHour($format); |
} |
/** |
* Returns the value for the next hour |
* @param string return value format ['int' | 'timestamp' | 'object' | 'array'] |
* @return int e.g. 14 or timestamp |
* @access public |
*/ |
function nextHour($format = 'int') |
{ |
return $this->calendar->nextHour($format); |
} |
/** |
* Returns the value for the previous minute |
* @param string return value format ['int' | 'timestamp' | 'object' | 'array'] |
* @return int e.g. 23 or timestamp |
* @access public |
*/ |
function prevMinute($format = 'int') |
{ |
return $this->calendar->prevMinute($format); |
} |
/** |
* Returns the value for this minute |
* @param string return value format ['int' | 'timestamp' | 'object' | 'array'] |
* @return int e.g. 24 or timestamp |
* @access public |
*/ |
function thisMinute($format = 'int') |
{ |
return $this->calendar->thisMinute($format); |
} |
/** |
* Returns the value for the next minute |
* @param string return value format ['int' | 'timestamp' | 'object' | 'array'] |
* @return int e.g. 25 or timestamp |
* @access public |
*/ |
function nextMinute($format = 'int') |
{ |
return $this->calendar->nextMinute($format); |
} |
/** |
* Returns the value for the previous second |
* @param string return value format ['int' | 'timestamp' | 'object' | 'array'] |
* @return int e.g. 43 or timestamp |
* @access public |
*/ |
function prevSecond($format = 'int') |
{ |
return $this->calendar->prevSecond($format); |
} |
/** |
* Returns the value for this second |
* @param string return value format ['int' | 'timestamp' | 'object' | 'array'] |
* @return int e.g. 44 or timestamp |
* @access public |
*/ |
function thisSecond($format = 'int') |
{ |
return $this->calendar->thisSecond($format); |
} |
/** |
* Returns the value for the next second |
* @param string return value format ['int' | 'timestamp' | 'object' | 'array'] |
* @return int e.g. 45 or timestamp |
* @access public |
*/ |
function nextSecond($format = 'int') |
{ |
return $this->calendar->nextSecond($format); |
} |
} |
?> |
/branches/v1.3-critias/bibliotheque/pear/Calendar/Month.php |
---|
New file |
0,0 → 1,114 |
<?php |
/* vim: set expandtab tabstop=4 shiftwidth=4: */ |
// |
// +----------------------------------------------------------------------+ |
// | PHP Version 4 | |
// +----------------------------------------------------------------------+ |
// | Copyright (c) 1997-2002 The PHP Group | |
// +----------------------------------------------------------------------+ |
// | This source file is subject to version 2.02 of the PHP license, | |
// | that is bundled with this package in the file LICENSE, and is | |
// | available at through the world-wide-web at | |
// | http://www.php.net/license/3_0.txt. | |
// | If you did not receive a copy of the PHP license and are unable to | |
// | obtain it through the world-wide-web, please send a note to | |
// | license@php.net so we can mail you a copy immediately. | |
// +----------------------------------------------------------------------+ |
// | Authors: Harry Fuecks <hfuecks@phppatterns.com> | |
// +----------------------------------------------------------------------+ |
// |
// $Id: Month.php,v 1.3 2005/10/22 10:10:26 quipo Exp $ |
// |
/** |
* @package Calendar |
* @version $Id: Month.php,v 1.3 2005/10/22 10:10:26 quipo Exp $ |
*/ |
/** |
* Allows Calendar include path to be redefined |
* @ignore |
*/ |
if (!defined('CALENDAR_ROOT')) { |
define('CALENDAR_ROOT', 'Calendar'.DIRECTORY_SEPARATOR); |
} |
/** |
* Load Calendar base class |
*/ |
require_once CALENDAR_ROOT.'Calendar.php'; |
/** |
* Represents a Month and builds Days |
* <code> |
* require_once 'Calendar/Month.php'; |
* $Month = & new Calendar_Month(2003, 10); // Oct 2003 |
* $Month->build(); // Build Calendar_Day objects |
* while ($Day = & $Month->fetch()) { |
* echo $Day->thisDay().'<br />'; |
* } |
* </code> |
* @package Calendar |
* @access public |
*/ |
class Calendar_Month extends Calendar |
{ |
/** |
* Constructs Calendar_Month |
* @param int $y year e.g. 2003 |
* @param int $m month e.g. 5 |
* @param int $firstDay first day of the week [optional] |
* @access public |
*/ |
function Calendar_Month($y, $m, $firstDay=null) |
{ |
Calendar::Calendar($y, $m); |
$this->firstDay = $this->defineFirstDayOfWeek($firstDay); |
} |
/** |
* Builds Day objects for this Month. Creates as many Calendar_Day objects |
* as there are days in the month |
* @param array (optional) Calendar_Day objects representing selected dates |
* @return boolean |
* @access public |
*/ |
function build($sDates=array()) |
{ |
require_once CALENDAR_ROOT.'Day.php'; |
$daysInMonth = $this->cE->getDaysInMonth($this->year, $this->month); |
for ($i=1; $i<=$daysInMonth; $i++) { |
$this->children[$i] = new Calendar_Day($this->year, $this->month, $i); |
} |
if (count($sDates) > 0) { |
$this->setSelection($sDates); |
} |
return true; |
} |
/** |
* Called from build() |
* @param array |
* @return void |
* @access private |
*/ |
function setSelection($sDates) |
{ |
foreach ($sDates as $sDate) { |
if ($this->year == $sDate->thisYear() |
&& $this->month == $sDate->thisMonth() |
) { |
$key = $sDate->thisDay(); |
if (isset($this->children[$key])) { |
$sDate->setSelected(); |
$class = strtolower(get_class($sDate)); |
if ($class == 'calendar_day' || $class == 'calendar_decorator') { |
$sDate->setFirst($this->children[$key]->isFirst()); |
$sDate->setLast($this->children[$key]->isLast()); |
} |
$this->children[$key] = $sDate; |
} |
} |
} |
} |
} |
?> |
/branches/v1.3-critias/bibliotheque/pear/Calendar/Validator.php |
---|
New file |
0,0 → 1,335 |
<?php |
/* vim: set expandtab tabstop=4 shiftwidth=4: */ |
// |
// +----------------------------------------------------------------------+ |
// | PHP Version 4 | |
// +----------------------------------------------------------------------+ |
// | Copyright (c) 1997-2002 The PHP Group | |
// +----------------------------------------------------------------------+ |
// | This source file is subject to version 2.02 of the PHP license, | |
// | that is bundled with this package in the file LICENSE, and is | |
// | available at through the world-wide-web at | |
// | http://www.php.net/license/3_0.txt. | |
// | If you did not receive a copy of the PHP license and are unable to | |
// | obtain it through the world-wide-web, please send a note to | |
// | license@php.net so we can mail you a copy immediately. | |
// +----------------------------------------------------------------------+ |
// | Authors: Harry Fuecks <hfuecks@phppatterns.com> | |
// +----------------------------------------------------------------------+ |
// |
// $Id: Validator.php,v 1.1 2004/05/24 22:25:42 quipo Exp $ |
// |
/** |
* @package Calendar |
* @version $Id: Validator.php,v 1.1 2004/05/24 22:25:42 quipo Exp $ |
*/ |
/** |
* Validation Error Messages |
*/ |
if (!defined('CALENDAR_VALUE_TOOSMALL')) { |
define('CALENDAR_VALUE_TOOSMALL', 'Too small: min = '); |
} |
if (!defined('CALENDAR_VALUE_TOOLARGE')) { |
define('CALENDAR_VALUE_TOOLARGE', 'Too large: max = '); |
} |
/** |
* Used to validate any given Calendar date object. Instances of this class |
* can be obtained from any data object using the getValidator method |
* @see Calendar::getValidator() |
* @package Calendar |
* @access public |
*/ |
class Calendar_Validator |
{ |
/** |
* Instance of the Calendar date object to validate |
* @var object |
* @access private |
*/ |
var $calendar; |
/** |
* Instance of the Calendar_Engine |
* @var object |
* @access private |
*/ |
var $cE; |
/** |
* Array of errors for validation failures |
* @var array |
* @access private |
*/ |
var $errors = array(); |
/** |
* Constructs Calendar_Validator |
* @param object subclass of Calendar |
* @access public |
*/ |
function Calendar_Validator(& $calendar) |
{ |
$this->calendar = & $calendar; |
$this->cE = & $calendar->getEngine(); |
} |
/** |
* Calls all the other isValidXXX() methods in the validator |
* @return boolean |
* @access public |
*/ |
function isValid() |
{ |
$checks = array('isValidYear', 'isValidMonth', 'isValidDay', |
'isValidHour', 'isValidMinute', 'isValidSecond'); |
$valid = true; |
foreach ($checks as $check) { |
if (!$this->{$check}()) { |
$valid = false; |
} |
} |
return $valid; |
} |
/** |
* Check whether this is a valid year |
* @return boolean |
* @access public |
*/ |
function isValidYear() |
{ |
$y = $this->calendar->thisYear(); |
$min = $this->cE->getMinYears(); |
if ($min > $y) { |
$this->errors[] = new Calendar_Validation_Error( |
'Year', $y, CALENDAR_VALUE_TOOSMALL.$min); |
return false; |
} |
$max = $this->cE->getMaxYears(); |
if ($y > $max) { |
$this->errors[] = new Calendar_Validation_Error( |
'Year', $y, CALENDAR_VALUE_TOOLARGE.$max); |
return false; |
} |
return true; |
} |
/** |
* Check whether this is a valid month |
* @return boolean |
* @access public |
*/ |
function isValidMonth() |
{ |
$m = $this->calendar->thisMonth(); |
$min = 1; |
if ($min > $m) { |
$this->errors[] = new Calendar_Validation_Error( |
'Month', $m, CALENDAR_VALUE_TOOSMALL.$min); |
return false; |
} |
$max = $this->cE->getMonthsInYear($this->calendar->thisYear()); |
if ($m > $max) { |
$this->errors[] = new Calendar_Validation_Error( |
'Month', $m, CALENDAR_VALUE_TOOLARGE.$max); |
return false; |
} |
return true; |
} |
/** |
* Check whether this is a valid day |
* @return boolean |
* @access public |
*/ |
function isValidDay() |
{ |
$d = $this->calendar->thisDay(); |
$min = 1; |
if ($min > $d) { |
$this->errors[] = new Calendar_Validation_Error( |
'Day', $d, CALENDAR_VALUE_TOOSMALL.$min); |
return false; |
} |
$max = $this->cE->getDaysInMonth( |
$this->calendar->thisYear(), $this->calendar->thisMonth()); |
if ($d > $max) { |
$this->errors[] = new Calendar_Validation_Error( |
'Day', $d, CALENDAR_VALUE_TOOLARGE.$max); |
return false; |
} |
return true; |
} |
/** |
* Check whether this is a valid hour |
* @return boolean |
* @access public |
*/ |
function isValidHour() |
{ |
$h = $this->calendar->thisHour(); |
$min = 0; |
if ($min > $h) { |
$this->errors[] = new Calendar_Validation_Error( |
'Hour', $h, CALENDAR_VALUE_TOOSMALL.$min); |
return false; |
} |
$max = ($this->cE->getHoursInDay($this->calendar->thisDay())-1); |
if ($h > $max) { |
$this->errors[] = new Calendar_Validation_Error( |
'Hour', $h, CALENDAR_VALUE_TOOLARGE.$max); |
return false; |
} |
return true; |
} |
/** |
* Check whether this is a valid minute |
* @return boolean |
* @access public |
*/ |
function isValidMinute() |
{ |
$i = $this->calendar->thisMinute(); |
$min = 0; |
if ($min > $i) { |
$this->errors[] = new Calendar_Validation_Error( |
'Minute', $i, CALENDAR_VALUE_TOOSMALL.$min); |
return false; |
} |
$max = ($this->cE->getMinutesInHour($this->calendar->thisHour())-1); |
if ($i > $max) { |
$this->errors[] = new Calendar_Validation_Error( |
'Minute', $i, CALENDAR_VALUE_TOOLARGE.$max); |
return false; |
} |
return true; |
} |
/** |
* Check whether this is a valid second |
* @return boolean |
* @access public |
*/ |
function isValidSecond() |
{ |
$s = $this->calendar->thisSecond(); |
$min = 0; |
if ($min > $s) { |
$this->errors[] = new Calendar_Validation_Error( |
'Second', $s, CALENDAR_VALUE_TOOSMALL.$min); |
return false; |
} |
$max = ($this->cE->getSecondsInMinute($this->calendar->thisMinute())-1); |
if ($s > $max) { |
$this->errors[] = new Calendar_Validation_Error( |
'Second', $s, CALENDAR_VALUE_TOOLARGE.$max); |
return false; |
} |
return true; |
} |
/** |
* Iterates over any validation errors |
* @return mixed either Calendar_Validation_Error or false |
* @access public |
*/ |
function fetch() |
{ |
$error = each ($this->errors); |
if ($error) { |
return $error['value']; |
} else { |
reset($this->errors); |
return false; |
} |
} |
} |
/** |
* For Validation Error messages |
* @see Calendar::fetch() |
* @package Calendar |
* @access public |
*/ |
class Calendar_Validation_Error |
{ |
/** |
* Date unit (e.g. month,hour,second) which failed test |
* @var string |
* @access private |
*/ |
var $unit; |
/** |
* Value of unit which failed test |
* @var int |
* @access private |
*/ |
var $value; |
/** |
* Validation error message |
* @var string |
* @access private |
*/ |
var $message; |
/** |
* Constructs Calendar_Validation_Error |
* @param string Date unit (e.g. month,hour,second) |
* @param int Value of unit which failed test |
* @param string Validation error message |
* @access protected |
*/ |
function Calendar_Validation_Error($unit,$value,$message) |
{ |
$this->unit = $unit; |
$this->value = $value; |
$this->message = $message; |
} |
/** |
* Returns the Date unit |
* @return string |
* @access public |
*/ |
function getUnit() |
{ |
return $this->unit; |
} |
/** |
* Returns the value of the unit |
* @return int |
* @access public |
*/ |
function getValue() |
{ |
return $this->value; |
} |
/** |
* Returns the validation error message |
* @return string |
* @access public |
*/ |
function getMessage() |
{ |
return $this->message; |
} |
/** |
* Returns a string containing the unit, value and error message |
* @return string |
* @access public |
*/ |
function toString () |
{ |
return $this->unit.' = '.$this->value.' ['.$this->message.']'; |
} |
} |
?> |
/branches/v1.3-critias/bibliotheque/pear/Calendar/Util/Uri.php |
---|
New file |
0,0 → 1,169 |
<?php |
/* vim: set expandtab tabstop=4 shiftwidth=4: */ |
// |
// +----------------------------------------------------------------------+ |
// | PHP | |
// +----------------------------------------------------------------------+ |
// | Copyright (c) 1997-2002 The PHP Group | |
// +----------------------------------------------------------------------+ |
// | This source file is subject to version 2.02 of the PHP license, | |
// | that is bundled with this package in the file LICENSE, and is | |
// | available at through the world-wide-web at | |
// | http://www.php.net/license/3_0.txt. | |
// | If you did not receive a copy of the PHP license and are unable to | |
// | obtain it through the world-wide-web, please send a note to | |
// | license@php.net so we can mail you a copy immediately. | |
// +----------------------------------------------------------------------+ |
// | Authors: Harry Fuecks <hfuecks@phppatterns.com> | |
// | Lorenzo Alberton <l dot alberton at quipo dot it> | |
// +----------------------------------------------------------------------+ |
// |
// $Id: Uri.php,v 1.1 2004/08/16 09:03:55 hfuecks Exp $ |
// |
/** |
* @package Calendar |
* @version $Id: Uri.php,v 1.1 2004/08/16 09:03:55 hfuecks Exp $ |
*/ |
/** |
* Utility to help building HTML links for navigating the calendar<br /> |
* <code> |
* $Day = new Calendar_Day(2003, 10, 23); |
* $Uri = & new Calendar_Util_Uri('year', 'month', 'day'); |
* echo $Uri->prev($Day,'month'); // Displays year=2003&month=10 |
* echo $Uri->prev($Day,'day'); // Displays year=2003&month=10&day=22 |
* $Uri->seperator = '/'; |
* $Uri->scalar = true; |
* echo $Uri->prev($Day,'month'); // Displays 2003/10 |
* echo $Uri->prev($Day,'day'); // Displays 2003/10/22 |
* </code> |
* @package Calendar |
* @access public |
*/ |
class Calendar_Util_Uri |
{ |
/** |
* Uri fragments for year, month, day etc. |
* @var array |
* @access private |
*/ |
var $uris = array(); |
/** |
* String to separate fragments with. |
* Set to just & for HTML. |
* For a scalar URL you might use / as the seperator |
* @var string (default XHTML &) |
* @access public |
*/ |
var $separator = '&'; |
/** |
* To output a "scalar" string - variable names omitted. |
* Used for urls like index.php/2004/8/12 |
* @var boolean (default false) |
* @access public |
*/ |
var $scalar = false; |
/** |
* Constructs Calendar_Decorator_Uri |
* The term "fragment" means <i>name</i> of a calendar GET variables in the URL |
* @param string URI fragment for year |
* @param string (optional) URI fragment for month |
* @param string (optional) URI fragment for day |
* @param string (optional) URI fragment for hour |
* @param string (optional) URI fragment for minute |
* @param string (optional) URI fragment for second |
* @access public |
*/ |
function Calendar_Util_Uri($y, $m=null, $d=null, $h=null, $i=null, $s=null) |
{ |
$this->setFragments($y, $m, $d, $h, $i, $s); |
} |
/** |
* Sets the URI fragment names |
* @param string URI fragment for year |
* @param string (optional) URI fragment for month |
* @param string (optional) URI fragment for day |
* @param string (optional) URI fragment for hour |
* @param string (optional) URI fragment for minute |
* @param string (optional) URI fragment for second |
* @return void |
* @access public |
*/ |
function setFragments($y, $m=null, $d=null, $h=null, $i=null, $s=null) { |
if (!is_null($y)) $this->uris['Year'] = $y; |
if (!is_null($m)) $this->uris['Month'] = $m; |
if (!is_null($d)) $this->uris['Day'] = $d; |
if (!is_null($h)) $this->uris['Hour'] = $h; |
if (!is_null($i)) $this->uris['Minute'] = $i; |
if (!is_null($s)) $this->uris['Second'] = $s; |
} |
/** |
* Gets the URI string for the previous calendar unit |
* @param object subclassed from Calendar e.g. Calendar_Month |
* @param string calendar unit ( must be year, month, week, day, hour, minute or second) |
* @return string |
* @access public |
*/ |
function prev($Calendar, $unit) |
{ |
$method = 'prev'.$unit; |
$stamp = $Calendar->{$method}('timestamp'); |
return $this->buildUriString($Calendar, $method, $stamp); |
} |
/** |
* Gets the URI string for the current calendar unit |
* @param object subclassed from Calendar e.g. Calendar_Month |
* @param string calendar unit ( must be year, month, week, day, hour, minute or second) |
* @return string |
* @access public |
*/ |
function this($Calendar, $unit) |
{ |
$method = 'this'.$unit; |
$stamp = $Calendar->{$method}('timestamp'); |
return $this->buildUriString($Calendar, $method, $stamp); |
} |
/** |
* Gets the URI string for the next calendar unit |
* @param object subclassed from Calendar e.g. Calendar_Month |
* @param string calendar unit ( must be year, month, week, day, hour, minute or second) |
* @return string |
* @access public |
*/ |
function next($Calendar, $unit) |
{ |
$method = 'next'.$unit; |
$stamp = $Calendar->{$method}('timestamp'); |
return $this->buildUriString($Calendar, $method, $stamp); |
} |
/** |
* Build the URI string |
* @param string method substring |
* @param int timestamp |
* @return string build uri string |
* @access private |
*/ |
function buildUriString($Calendar, $method, $stamp) |
{ |
$uriString = ''; |
$cE = & $Calendar->getEngine(); |
$separator = ''; |
foreach ($this->uris as $unit => $uri) { |
$call = 'stampTo'.$unit; |
$uriString .= $separator; |
if (!$this->scalar) $uriString .= $uri.'='; |
$uriString .= $cE->{$call}($stamp); |
$separator = $this->separator; |
} |
return $uriString; |
} |
} |
?> |
/branches/v1.3-critias/bibliotheque/pear/Calendar/Util/Textual.php |
---|
New file |
0,0 → 1,239 |
<?php |
/* vim: set expandtab tabstop=4 shiftwidth=4: */ |
// |
// +----------------------------------------------------------------------+ |
// | PHP Version 4 | |
// +----------------------------------------------------------------------+ |
// | Copyright (c) 1997-2002 The PHP Group | |
// +----------------------------------------------------------------------+ |
// | This source file is subject to version 2.02 of the PHP license, | |
// | that is bundled with this package in the file LICENSE, and is | |
// | available at through the world-wide-web at | |
// | http://www.php.net/license/3_0.txt. | |
// | If you did not receive a copy of the PHP license and are unable to | |
// | obtain it through the world-wide-web, please send a note to | |
// | license@php.net so we can mail you a copy immediately. | |
// +----------------------------------------------------------------------+ |
// | Authors: Harry Fuecks <hfuecks@phppatterns.com> | |
// | Lorenzo Alberton <l dot alberton at quipo dot it> | |
// +----------------------------------------------------------------------+ |
// |
// $Id: Textual.php,v 1.2 2004/08/16 13:13:09 hfuecks Exp $ |
// |
/** |
* @package Calendar |
* @version $Id: Textual.php,v 1.2 2004/08/16 13:13:09 hfuecks Exp $ |
*/ |
/** |
* Allows Calendar include path to be redefined |
* @ignore |
*/ |
if (!defined('CALENDAR_ROOT')) { |
define('CALENDAR_ROOT', 'Calendar'.DIRECTORY_SEPARATOR); |
} |
/** |
* Load Calendar decorator base class |
*/ |
require_once CALENDAR_ROOT.'Decorator.php'; |
/** |
* Static utlities to help with fetching textual representations of months and |
* days of the week. |
* @package Calendar |
* @access public |
*/ |
class Calendar_Util_Textual |
{ |
/** |
* Returns an array of 12 month names (first index = 1) |
* @param string (optional) format of returned months (one,two,short or long) |
* @return array |
* @access public |
* @static |
*/ |
function monthNames($format='long') |
{ |
$formats = array('one'=>'%b', 'two'=>'%b', 'short'=>'%b', 'long'=>'%B'); |
if (!array_key_exists($format,$formats)) { |
$format = 'long'; |
} |
$months = array(); |
for ($i=1; $i<=12; $i++) { |
$stamp = mktime(0, 0, 0, $i, 1, 2003); |
$month = strftime($formats[$format], $stamp); |
switch($format) { |
case 'one': |
$month = substr($month, 0, 1); |
break; |
case 'two': |
$month = substr($month, 0, 2); |
break; |
} |
$months[$i] = $month; |
} |
return $months; |
} |
/** |
* Returns an array of 7 week day names (first index = 0) |
* @param string (optional) format of returned days (one,two,short or long) |
* @return array |
* @access public |
* @static |
*/ |
function weekdayNames($format='long') |
{ |
$formats = array('one'=>'%a', 'two'=>'%a', 'short'=>'%a', 'long'=>'%A'); |
if (!array_key_exists($format,$formats)) { |
$format = 'long'; |
} |
$days = array(); |
for ($i=0; $i<=6; $i++) { |
$stamp = mktime(0, 0, 0, 11, $i+2, 2003); |
$day = strftime($formats[$format], $stamp); |
switch($format) { |
case 'one': |
$day = substr($day, 0, 1); |
break; |
case 'two': |
$day = substr($day, 0, 2); |
break; |
} |
$days[$i] = $day; |
} |
return $days; |
} |
/** |
* Returns textual representation of the previous month of the decorated calendar object |
* @param object subclass of Calendar e.g. Calendar_Month |
* @param string (optional) format of returned months (one,two,short or long) |
* @return string |
* @access public |
* @static |
*/ |
function prevMonthName($Calendar, $format='long') |
{ |
$months = Calendar_Util_Textual::monthNames($format); |
return $months[$Calendar->prevMonth()]; |
} |
/** |
* Returns textual representation of the month of the decorated calendar object |
* @param object subclass of Calendar e.g. Calendar_Month |
* @param string (optional) format of returned months (one,two,short or long) |
* @return string |
* @access public |
* @static |
*/ |
function thisMonthName($Calendar, $format='long') |
{ |
$months = Calendar_Util_Textual::monthNames($format); |
return $months[$Calendar->thisMonth()]; |
} |
/** |
* Returns textual representation of the next month of the decorated calendar object |
* @param object subclass of Calendar e.g. Calendar_Month |
* @param string (optional) format of returned months (one,two,short or long) |
* @return string |
* @access public |
* @static |
*/ |
function nextMonthName($Calendar, $format='long') |
{ |
$months = Calendar_Util_Textual::monthNames($format); |
return $months[$Calendar->nextMonth()]; |
} |
/** |
* Returns textual representation of the previous day of week of the decorated calendar object |
* <b>Note:</b> Requires PEAR::Date |
* @param object subclass of Calendar e.g. Calendar_Month |
* @param string (optional) format of returned months (one,two,short or long) |
* @return string |
* @access public |
* @static |
*/ |
function prevDayName($Calendar, $format='long') |
{ |
$days = Calendar_Util_Textual::weekdayNames($format); |
$stamp = $Calendar->prevDay('timestamp'); |
$cE = $Calendar->getEngine(); |
require_once 'Date/Calc.php'; |
$day = Date_Calc::dayOfWeek($cE->stampToDay($stamp), |
$cE->stampToMonth($stamp), $cE->stampToYear($stamp)); |
return $days[$day]; |
} |
/** |
* Returns textual representation of the day of week of the decorated calendar object |
* <b>Note:</b> Requires PEAR::Date |
* @param object subclass of Calendar e.g. Calendar_Month |
* @param string (optional) format of returned months (one,two,short or long) |
* @return string |
* @access public |
* @static |
*/ |
function thisDayName($Calendar, $format='long') |
{ |
$days = Calendar_Util_Textual::weekdayNames($format); |
require_once 'Date/Calc.php'; |
$day = Date_Calc::dayOfWeek($Calendar->thisDay(), $Calendar->thisMonth(), $Calendar->thisYear()); |
return $days[$day]; |
} |
/** |
* Returns textual representation of the next day of week of the decorated calendar object |
* @param object subclass of Calendar e.g. Calendar_Month |
* @param string (optional) format of returned months (one,two,short or long) |
* @return string |
* @access public |
* @static |
*/ |
function nextDayName($Calendar, $format='long') |
{ |
$days = Calendar_Util_Textual::weekdayNames($format); |
$stamp = $Calendar->nextDay('timestamp'); |
$cE = $Calendar->getEngine(); |
require_once 'Date/Calc.php'; |
$day = Date_Calc::dayOfWeek($cE->stampToDay($stamp), |
$cE->stampToMonth($stamp), $cE->stampToYear($stamp)); |
return $days[$day]; |
} |
/** |
* Returns the days of the week using the order defined in the decorated |
* calendar object. Only useful for Calendar_Month_Weekdays, Calendar_Month_Weeks |
* and Calendar_Week. Otherwise the returned array will begin on Sunday |
* @param object subclass of Calendar e.g. Calendar_Month |
* @param string (optional) format of returned months (one,two,short or long) |
* @return array ordered array of week day names |
* @access public |
* @static |
*/ |
function orderedWeekdays($Calendar, $format='long') |
{ |
$days = Calendar_Util_Textual::weekdayNames($format); |
// Not so good - need methods to access this information perhaps... |
if (isset($Calendar->tableHelper)) { |
$ordereddays = $Calendar->tableHelper->daysOfWeek; |
} else { |
$ordereddays = array(0, 1, 2, 3, 4, 5, 6); |
} |
$ordereddays = array_flip($ordereddays); |
$i = 0; |
$returndays = array(); |
foreach ($ordereddays as $key => $value) { |
$returndays[$i] = $days[$key]; |
$i++; |
} |
return $returndays; |
} |
} |
?> |
/branches/v1.3-critias/bibliotheque/pear/Calendar/Week.php |
---|
New file |
0,0 → 1,394 |
<?php |
/* vim: set expandtab tabstop=4 shiftwidth=4: */ |
// |
// +----------------------------------------------------------------------+ |
// | PHP Version 4 | |
// +----------------------------------------------------------------------+ |
// | Copyright (c) 1997-2002 The PHP Group | |
// +----------------------------------------------------------------------+ |
// | This source file is subject to version 2.02 of the PHP license, | |
// | that is bundled with this package in the file LICENSE, and is | |
// | available at through the world-wide-web at | |
// | http://www.php.net/license/3_0.txt. | |
// | If you did not receive a copy of the PHP license and are unable to | |
// | obtain it through the world-wide-web, please send a note to | |
// | license@php.net so we can mail you a copy immediately. | |
// +----------------------------------------------------------------------+ |
// | Authors: Harry Fuecks <hfuecks@phppatterns.com> | |
// | Lorenzo Alberton <l dot alberton at quipo dot it> | |
// +----------------------------------------------------------------------+ |
// |
// $Id: Week.php,v 1.7 2005/10/22 10:26:49 quipo Exp $ |
// |
/** |
* @package Calendar |
* @version $Id: Week.php,v 1.7 2005/10/22 10:26:49 quipo Exp $ |
*/ |
/** |
* Allows Calendar include path to be redefined |
* @ignore |
*/ |
if (!defined('CALENDAR_ROOT')) { |
define('CALENDAR_ROOT', 'Calendar'.DIRECTORY_SEPARATOR); |
} |
/** |
* Load Calendar base class |
*/ |
require_once CALENDAR_ROOT.'Calendar.php'; |
/** |
* Represents a Week and builds Days in tabular format<br> |
* <code> |
* require_once 'Calendar'.DIRECTORY_SEPARATOR.'Week.php'; |
* $Week = & new Calendar_Week(2003, 10, 1); Oct 2003, 1st tabular week |
* echo '<tr>'; |
* while ($Day = & $Week->fetch()) { |
* if ($Day->isEmpty()) { |
* echo '<td> </td>'; |
* } else { |
* echo '<td>'.$Day->thisDay().'</td>'; |
* } |
* } |
* echo '</tr>'; |
* </code> |
* @package Calendar |
* @access public |
*/ |
class Calendar_Week extends Calendar |
{ |
/** |
* Instance of Calendar_Table_Helper |
* @var Calendar_Table_Helper |
* @access private |
*/ |
var $tableHelper; |
/** |
* Stores the timestamp of the first day of this week |
* @access private |
* @var object |
*/ |
var $thisWeek; |
/** |
* Stores the timestamp of first day of previous week |
* @access private |
* @var object |
*/ |
var $prevWeek; |
/** |
* Stores the timestamp of first day of next week |
* @access private |
* @var object |
*/ |
var $nextWeek; |
/** |
* Used by build() to set empty days |
* @access private |
* @var boolean |
*/ |
var $firstWeek = false; |
/** |
* Used by build() to set empty days |
* @access private |
* @var boolean |
*/ |
var $lastWeek = false; |
/** |
* First day of the week (0=sunday, 1=monday...) |
* @access private |
* @var boolean |
*/ |
var $firstDay = 1; |
/** |
* Constructs Week |
* @param int year e.g. 2003 |
* @param int month e.g. 5 |
* @param int a day of the desired week |
* @param int (optional) first day of week (e.g. 0 for Sunday, 2 for Tuesday etc.) |
* @access public |
*/ |
function Calendar_Week($y, $m, $d, $firstDay=null) |
{ |
require_once CALENDAR_ROOT.'Table/Helper.php'; |
Calendar::Calendar($y, $m, $d); |
$this->firstDay = $this->defineFirstDayOfWeek($firstDay); |
$this->tableHelper = new Calendar_Table_Helper($this, $this->firstDay); |
$this->thisWeek = $this->tableHelper->getWeekStart($y, $m, $d, $this->firstDay); |
$this->prevWeek = $this->tableHelper->getWeekStart($y, $m, $d - $this->cE->getDaysInWeek( |
$this->thisYear(), |
$this->thisMonth(), |
$this->thisDay()), $this->firstDay); |
$this->nextWeek = $this->tableHelper->getWeekStart($y, $m, $d + $this->cE->getDaysInWeek( |
$this->thisYear(), |
$this->thisMonth(), |
$this->thisDay()), $this->firstDay); |
} |
/** |
* Defines the calendar by a timestamp (Unix or ISO-8601), replacing values |
* passed to the constructor |
* @param int|string Unix or ISO-8601 timestamp |
* @return void |
* @access public |
*/ |
function setTimestamp($ts) |
{ |
parent::setTimestamp($ts); |
$this->thisWeek = $this->tableHelper->getWeekStart( |
$this->year, $this->month, $this->day, $this->firstDay |
); |
$this->prevWeek = $this->tableHelper->getWeekStart( |
$this->year, $this->month, $this->day - $this->cE->getDaysInWeek( |
$this->thisYear(), |
$this->thisMonth(), |
$this->thisDay()), $this->firstDay |
); |
$this->nextWeek = $this->tableHelper->getWeekStart( |
$this->year, $this->month, $this->day + $this->cE->getDaysInWeek( |
$this->thisYear(), |
$this->thisMonth(), |
$this->thisDay()), $this->firstDay |
); |
} |
/** |
* Builds Calendar_Day objects for this Week |
* @param array (optional) Calendar_Day objects representing selected dates |
* @return boolean |
* @access public |
*/ |
function build($sDates = array()) |
{ |
require_once CALENDAR_ROOT.'Day.php'; |
$year = $this->cE->stampToYear($this->thisWeek); |
$month = $this->cE->stampToMonth($this->thisWeek); |
$day = $this->cE->stampToDay($this->thisWeek); |
$end = $this->cE->getDaysInWeek( |
$this->thisYear(), |
$this->thisMonth(), |
$this->thisDay() |
); |
for ($i=1; $i <= $end; $i++) { |
$stamp = $this->cE->dateToStamp($year, $month, $day++); |
$this->children[$i] = new Calendar_Day( |
$this->cE->stampToYear($stamp), |
$this->cE->stampToMonth($stamp), |
$this->cE->stampToDay($stamp)); |
} |
//set empty days (@see Calendar_Month_Weeks::build()) |
if ($this->firstWeek) { |
$eBefore = $this->tableHelper->getEmptyDaysBefore(); |
for ($i=1; $i <= $eBefore; $i++) { |
$this->children[$i]->setEmpty(); |
} |
} |
if ($this->lastWeek) { |
$eAfter = $this->tableHelper->getEmptyDaysAfterOffset(); |
for ($i = $eAfter+1; $i <= $end; $i++) { |
$this->children[$i]->setEmpty(); |
} |
} |
if (count($sDates) > 0) { |
$this->setSelection($sDates); |
} |
return true; |
} |
/** |
* @param boolean |
* @return void |
* @access private |
*/ |
function setFirst($state=true) |
{ |
$this->firstWeek = $state; |
} |
/** |
* @param boolean |
* @return void |
* @access private |
*/ |
function setLast($state=true) |
{ |
$this->lastWeek = $state; |
} |
/** |
* Called from build() |
* @param array |
* @return void |
* @access private |
*/ |
function setSelection($sDates) |
{ |
foreach ($sDates as $sDate) { |
foreach ($this->children as $key => $child) { |
if ($child->thisDay() == $sDate->thisDay() && |
$child->thisMonth() == $sDate->thisMonth() && |
$child->thisYear() == $sDate->thisYear() |
) { |
$this->children[$key] = $sDate; |
$this->children[$key]->setSelected(); |
} |
} |
} |
reset($this->children); |
} |
/** |
* Gets the value of the previous week, according to the requested format |
* |
* @param string $format ['timestamp' | 'n_in_month' | 'n_in_year' | 'array'] |
* @return mixed |
* @access public |
*/ |
function prevWeek($format = 'n_in_month') |
{ |
switch (strtolower($format)) { |
case 'int': |
case 'n_in_month': |
return ($this->firstWeek) ? null : $this->thisWeek('n_in_month') -1; |
break; |
case 'n_in_year': |
return $this->cE->getWeekNInYear( |
$this->cE->stampToYear($this->prevWeek), |
$this->cE->stampToMonth($this->prevWeek), |
$this->cE->stampToDay($this->prevWeek)); |
break; |
case 'array': |
return $this->toArray($this->prevWeek); |
break; |
case 'object': |
require_once CALENDAR_ROOT.'Factory.php'; |
return Calendar_Factory::createByTimestamp('Week', $this->prevWeek); |
break; |
case 'timestamp': |
default: |
return $this->prevWeek; |
break; |
} |
} |
/** |
* Gets the value of the current week, according to the requested format |
* |
* @param string $format ['timestamp' | 'n_in_month' | 'n_in_year' | 'array'] |
* @return mixed |
* @access public |
*/ |
function thisWeek($format = 'n_in_month') |
{ |
switch (strtolower($format)) { |
case 'int': |
case 'n_in_month': |
if ($this->firstWeek) { |
return 1; |
} |
if ($this->lastWeek) { |
return $this->cE->getWeeksInMonth( |
$this->thisYear(), |
$this->thisMonth(), |
$this->firstDay); |
} |
return $this->cE->getWeekNInMonth( |
$this->thisYear(), |
$this->thisMonth(), |
$this->thisDay(), |
$this->firstDay); |
break; |
case 'n_in_year': |
return $this->cE->getWeekNInYear( |
$this->cE->stampToYear($this->thisWeek), |
$this->cE->stampToMonth($this->thisWeek), |
$this->cE->stampToDay($this->thisWeek)); |
break; |
case 'array': |
return $this->toArray($this->thisWeek); |
break; |
case 'object': |
require_once CALENDAR_ROOT.'Factory.php'; |
return Calendar_Factory::createByTimestamp('Week', $this->thisWeek); |
break; |
case 'timestamp': |
default: |
return $this->thisWeek; |
break; |
} |
} |
/** |
* Gets the value of the following week, according to the requested format |
* |
* @param string $format ['timestamp' | 'n_in_month' | 'n_in_year' | 'array'] |
* @return mixed |
* @access public |
*/ |
function nextWeek($format = 'n_in_month') |
{ |
switch (strtolower($format)) { |
case 'int': |
case 'n_in_month': |
return ($this->lastWeek) ? null : $this->thisWeek('n_in_month') +1; |
break; |
case 'n_in_year': |
return $this->cE->getWeekNInYear( |
$this->cE->stampToYear($this->nextWeek), |
$this->cE->stampToMonth($this->nextWeek), |
$this->cE->stampToDay($this->nextWeek)); |
break; |
case 'array': |
return $this->toArray($this->nextWeek); |
break; |
case 'object': |
require_once CALENDAR_ROOT.'Factory.php'; |
return Calendar_Factory::createByTimestamp('Week', $this->nextWeek); |
break; |
case 'timestamp': |
default: |
return $this->nextWeek; |
break; |
} |
} |
/** |
* Returns the instance of Calendar_Table_Helper. |
* Called from Calendar_Validator::isValidWeek |
* @return Calendar_Table_Helper |
* @access protected |
*/ |
function & getHelper() |
{ |
return $this->tableHelper; |
} |
/** |
* Makes sure theres a value for $this->day |
* @return void |
* @access private |
*/ |
function findFirstDay() |
{ |
if (!count($this->children) > 0) { |
$this->build(); |
foreach ($this->children as $Day) { |
if (!$Day->isEmpty()) { |
$this->day = $Day->thisDay(); |
break; |
} |
} |
} |
} |
} |
?> |
/branches/v1.3-critias/bibliotheque/pear/Calendar/Decorator/Textual.php |
---|
New file |
0,0 → 1,169 |
<?php |
/* vim: set expandtab tabstop=4 shiftwidth=4: */ |
// |
// +----------------------------------------------------------------------+ |
// | PHP Version 4 | |
// +----------------------------------------------------------------------+ |
// | Copyright (c) 1997-2002 The PHP Group | |
// +----------------------------------------------------------------------+ |
// | This source file is subject to version 2.02 of the PHP license, | |
// | that is bundled with this package in the file LICENSE, and is | |
// | available at through the world-wide-web at | |
// | http://www.php.net/license/3_0.txt. | |
// | If you did not receive a copy of the PHP license and are unable to | |
// | obtain it through the world-wide-web, please send a note to | |
// | license@php.net so we can mail you a copy immediately. | |
// +----------------------------------------------------------------------+ |
// | Authors: Harry Fuecks <hfuecks@phppatterns.com> | |
// | Lorenzo Alberton <l dot alberton at quipo dot it> | |
// +----------------------------------------------------------------------+ |
// |
// $Id: Textual.php,v 1.3 2004/08/16 13:02:44 hfuecks Exp $ |
// |
/** |
* @package Calendar |
* @version $Id: Textual.php,v 1.3 2004/08/16 13:02:44 hfuecks Exp $ |
*/ |
/** |
* Allows Calendar include path to be redefined |
* @ignore |
*/ |
if (!defined('CALENDAR_ROOT')) { |
define('CALENDAR_ROOT', 'Calendar'.DIRECTORY_SEPARATOR); |
} |
/** |
* Load Calendar decorator base class |
*/ |
require_once CALENDAR_ROOT.'Decorator.php'; |
/** |
* Load the Uri utility |
*/ |
require_once CALENDAR_ROOT.'Util'.DIRECTORY_SEPARATOR.'Textual.php'; |
/** |
* Decorator to help with fetching textual representations of months and |
* days of the week. |
* <b>Note:</b> for performance you should prefer Calendar_Util_Textual unless you |
* have a specific need to use a decorator |
* @package Calendar |
* @access public |
*/ |
class Calendar_Decorator_Textual extends Calendar_Decorator |
{ |
/** |
* Constructs Calendar_Decorator_Textual |
* @param object subclass of Calendar |
* @access public |
*/ |
function Calendar_Decorator_Textual(&$Calendar) |
{ |
parent::Calendar_Decorator($Calendar); |
} |
/** |
* Returns an array of 12 month names (first index = 1) |
* @param string (optional) format of returned months (one,two,short or long) |
* @return array |
* @access public |
* @static |
*/ |
function monthNames($format='long') |
{ |
return Calendar_Util_Textual::monthNames($format); |
} |
/** |
* Returns an array of 7 week day names (first index = 0) |
* @param string (optional) format of returned days (one,two,short or long) |
* @return array |
* @access public |
* @static |
*/ |
function weekdayNames($format='long') |
{ |
return Calendar_Util_Textual::weekdayNames($format); |
} |
/** |
* Returns textual representation of the previous month of the decorated calendar object |
* @param string (optional) format of returned months (one,two,short or long) |
* @return string |
* @access public |
*/ |
function prevMonthName($format='long') |
{ |
return Calendar_Util_Textual::prevMonthName($this->calendar,$format); |
} |
/** |
* Returns textual representation of the month of the decorated calendar object |
* @param string (optional) format of returned months (one,two,short or long) |
* @return string |
* @access public |
*/ |
function thisMonthName($format='long') |
{ |
return Calendar_Util_Textual::thisMonthName($this->calendar,$format); |
} |
/** |
* Returns textual representation of the next month of the decorated calendar object |
* @param string (optional) format of returned months (one,two,short or long) |
* @return string |
* @access public |
*/ |
function nextMonthName($format='long') |
{ |
return Calendar_Util_Textual::nextMonthName($this->calendar,$format); |
} |
/** |
* Returns textual representation of the previous day of week of the decorated calendar object |
* @param string (optional) format of returned months (one,two,short or long) |
* @return string |
* @access public |
*/ |
function prevDayName($format='long') |
{ |
return Calendar_Util_Textual::prevDayName($this->calendar,$format); |
} |
/** |
* Returns textual representation of the day of week of the decorated calendar object |
* @param string (optional) format of returned months (one,two,short or long) |
* @return string |
* @access public |
*/ |
function thisDayName($format='long') |
{ |
return Calendar_Util_Textual::thisDayName($this->calendar,$format); |
} |
/** |
* Returns textual representation of the next day of week of the decorated calendar object |
* @param string (optional) format of returned months (one,two,short or long) |
* @return string |
* @access public |
*/ |
function nextDayName($format='long') |
{ |
return Calendar_Util_Textual::nextDayName($this->calendar,$format); |
} |
/** |
* Returns the days of the week using the order defined in the decorated |
* calendar object. Only useful for Calendar_Month_Weekdays, Calendar_Month_Weeks |
* and Calendar_Week. Otherwise the returned array will begin on Sunday |
* @param string (optional) format of returned months (one,two,short or long) |
* @return array ordered array of week day names |
* @access public |
*/ |
function orderedWeekdays($format='long') |
{ |
return Calendar_Util_Textual::orderedWeekdays($this->calendar,$format); |
} |
} |
?> |
/branches/v1.3-critias/bibliotheque/pear/Calendar/Decorator/Weekday.php |
---|
New file |
0,0 → 1,148 |
<?php |
/* vim: set expandtab tabstop=4 shiftwidth=4: */ |
// |
// +----------------------------------------------------------------------+ |
// | PHP Version 4 | |
// +----------------------------------------------------------------------+ |
// | Copyright (c) 1997-2002 The PHP Group | |
// +----------------------------------------------------------------------+ |
// | This source file is subject to version 2.02 of the PHP license, | |
// | that is bundled with this package in the file LICENSE, and is | |
// | available at through the world-wide-web at | |
// | http://www.php.net/license/3_0.txt. | |
// | If you did not receive a copy of the PHP license and are unable to | |
// | obtain it through the world-wide-web, please send a note to | |
// | license@php.net so we can mail you a copy immediately. | |
// +----------------------------------------------------------------------+ |
// | Authors: Harry Fuecks <hfuecks@phppatterns.com> | |
// | Lorenzo Alberton <l dot alberton at quipo dot it> | |
// +----------------------------------------------------------------------+ |
// |
// $Id: Weekday.php,v 1.3 2004/08/16 12:25:15 hfuecks Exp $ |
// |
/** |
* @package Calendar |
* @version $Id: Weekday.php,v 1.3 2004/08/16 12:25:15 hfuecks Exp $ |
*/ |
/** |
* Allows Calendar include path to be redefined |
* @ignore |
*/ |
if (!defined('CALENDAR_ROOT')) { |
define('CALENDAR_ROOT', 'Calendar'.DIRECTORY_SEPARATOR); |
} |
/** |
* Load Calendar decorator base class |
*/ |
require_once CALENDAR_ROOT.'Decorator.php'; |
/** |
* Load a Calendar_Day |
*/ |
require_once CALENDAR_ROOT.'Day.php'; |
/** |
* Decorator for fetching the day of the week |
* <code> |
* $Day = new Calendar_Day(2003, 10, 23); |
* $Weekday = & new Calendar_Decorator_Weekday($Day); |
* $Weekday->setFirstDay(0); // Set first day of week to Sunday (default Mon) |
* echo $Weekday->thisWeekDay(); // Displays 5 - fifth day of week relative to Sun |
* </code> |
* @package Calendar |
* @access public |
*/ |
class Calendar_Decorator_Weekday extends Calendar_Decorator |
{ |
/** |
* First day of week |
* @var int (default = 1 for Monday) |
* @access private |
*/ |
var $firstDay = 1; |
/** |
* Constructs Calendar_Decorator_Weekday |
* @param object subclass of Calendar |
* @access public |
*/ |
function Calendar_Decorator_Weekday(& $Calendar) |
{ |
parent::Calendar_Decorator($Calendar); |
} |
/** |
* Sets the first day of the week (0 = Sunday, 1 = Monday (default) etc) |
* @param int first day of week |
* @return void |
* @access public |
*/ |
function setFirstDay($firstDay) { |
$this->firstDay = (int)$firstDay; |
} |
/** |
* Returns the previous weekday |
* @param string (default = 'int') return value format |
* @return int numeric day of week or timestamp |
* @access public |
*/ |
function prevWeekDay($format = 'int') |
{ |
$ts = $this->calendar->prevDay('timestamp'); |
$Day = new Calendar_Day(2000,1,1); |
$Day->setTimeStamp($ts); |
$day = $this->calendar->cE->getDayOfWeek($Day->thisYear(),$Day->thisMonth(),$Day->thisDay()); |
$day = $this->adjustWeekScale($day); |
return $this->returnValue('Day', $format, $ts, $day); |
} |
/** |
* Returns the current weekday |
* @param string (default = 'int') return value format |
* @return int numeric day of week or timestamp |
* @access public |
*/ |
function thisWeekDay($format = 'int') |
{ |
$ts = $this->calendar->thisDay('timestamp'); |
$day = $this->calendar->cE->getDayOfWeek($this->calendar->year,$this->calendar->month,$this->calendar->day); |
$day = $this->adjustWeekScale($day); |
return $this->returnValue('Day', $format, $ts, $day); |
} |
/** |
* Returns the next weekday |
* @param string (default = 'int') return value format |
* @return int numeric day of week or timestamp |
* @access public |
*/ |
function nextWeekDay($format = 'int') |
{ |
$ts = $this->calendar->nextDay('timestamp'); |
$Day = new Calendar_Day(2000,1,1); |
$Day->setTimeStamp($ts); |
$day = $this->calendar->cE->getDayOfWeek($Day->thisYear(),$Day->thisMonth(),$Day->thisDay()); |
$day = $this->adjustWeekScale($day); |
return $this->returnValue('Day', $format, $ts, $day); |
} |
/** |
* Adjusts the day of the week relative to the first day of the week |
* @param int day of week calendar from Calendar_Engine |
* @return int day of week adjusted to first day |
* @access private |
*/ |
function adjustWeekScale($dayOfWeek) { |
$dayOfWeek = $dayOfWeek - $this->firstDay; |
if ( $dayOfWeek >= 0 ) { |
return $dayOfWeek; |
} else { |
return $this->calendar->cE->getDaysInWeek( |
$this->calendar->year,$this->calendar->month,$this->calendar->day |
) + $dayOfWeek; |
} |
} |
} |
?> |
/branches/v1.3-critias/bibliotheque/pear/Calendar/Decorator/Uri.php |
---|
New file |
0,0 → 1,151 |
<?php |
/* vim: set expandtab tabstop=4 shiftwidth=4: */ |
// |
// +----------------------------------------------------------------------+ |
// | PHP Version 4 | |
// +----------------------------------------------------------------------+ |
// | Copyright (c) 1997-2002 The PHP Group | |
// +----------------------------------------------------------------------+ |
// | This source file is subject to version 2.02 of the PHP license, | |
// | that is bundled with this package in the file LICENSE, and is | |
// | available at through the world-wide-web at | |
// | http://www.php.net/license/3_0.txt. | |
// | If you did not receive a copy of the PHP license and are unable to | |
// | obtain it through the world-wide-web, please send a note to | |
// | license@php.net so we can mail you a copy immediately. | |
// +----------------------------------------------------------------------+ |
// | Authors: Harry Fuecks <hfuecks@phppatterns.com> | |
// | Lorenzo Alberton <l dot alberton at quipo dot it> | |
// +----------------------------------------------------------------------+ |
// |
// $Id: Uri.php,v 1.3 2004/08/16 09:04:20 hfuecks Exp $ |
// |
/** |
* @package Calendar |
* @version $Id: Uri.php,v 1.3 2004/08/16 09:04:20 hfuecks Exp $ |
*/ |
/** |
* Allows Calendar include path to be redefined |
* @ignore |
*/ |
if (!defined('CALENDAR_ROOT')) { |
define('CALENDAR_ROOT', 'Calendar'.DIRECTORY_SEPARATOR); |
} |
/** |
* Load Calendar decorator base class |
*/ |
require_once CALENDAR_ROOT.'Decorator.php'; |
/** |
* Load the Uri utility |
*/ |
require_once CALENDAR_ROOT.'Util'.DIRECTORY_SEPARATOR.'Uri.php'; |
/** |
* Decorator to help with building HTML links for navigating the calendar<br /> |
* <b>Note:</b> for performance you should prefer Calendar_Util_Uri unless you |
* have a specific need to use a decorator |
* <code> |
* $Day = new Calendar_Day(2003, 10, 23); |
* $Uri = & new Calendar_Decorator_Uri($Day); |
* $Uri->setFragments('year', 'month', 'day'); |
* echo $Uri->getPrev(); // Displays year=2003&month=10&day=22 |
* </code> |
* @see Calendar_Util_Uri |
* @package Calendar |
* @access public |
*/ |
class Calendar_Decorator_Uri extends Calendar_Decorator |
{ |
/** |
* @var Calendar_Util_Uri |
* @access private |
*/ |
var $Uri; |
/** |
* Constructs Calendar_Decorator_Uri |
* @param object subclass of Calendar |
* @access public |
*/ |
function Calendar_Decorator_Uri(&$Calendar) |
{ |
parent::Calendar_Decorator($Calendar); |
} |
/** |
* Sets the URI fragment names |
* @param string URI fragment for year |
* @param string (optional) URI fragment for month |
* @param string (optional) URI fragment for day |
* @param string (optional) URI fragment for hour |
* @param string (optional) URI fragment for minute |
* @param string (optional) URI fragment for second |
* @return void |
* @access public |
*/ |
function setFragments($y, $m=null, $d=null, $h=null, $i=null, $s=null) { |
$this->Uri = & new Calendar_Util_Uri($y, $m, $d, $h, $i, $s); |
} |
/** |
* Sets the separator string between fragments |
* @param string separator e.g. / |
* @return void |
* @access public |
*/ |
function setSeparator($separator) |
{ |
$this->Uri->separator = $separator; |
} |
/** |
* Puts Uri decorator into "scalar mode" - URI variable names are not |
* returned |
* @param boolean (optional) |
* @return void |
* @access public |
*/ |
function setScalar($state=true) |
{ |
$this->Uri->scalar = $state; |
} |
/** |
* Gets the URI string for the previous calendar unit |
* @param string calendar unit to fetch uri for (year,month,week or day etc) |
* @return string |
* @access public |
*/ |
function prev($method) |
{ |
return $this->Uri->prev($this, $method); |
} |
/** |
* Gets the URI string for the current calendar unit |
* @param string calendar unit to fetch uri for (year,month,week or day etc) |
* @return string |
* @access public |
*/ |
function this($method) |
{ |
return $this->Uri->this($this, $method); |
} |
/** |
* Gets the URI string for the next calendar unit |
* @param string calendar unit to fetch uri for (year,month,week or day etc) |
* @return string |
* @access public |
*/ |
function next($method) |
{ |
return $this->Uri->next($this, $method); |
} |
} |
?> |
/branches/v1.3-critias/bibliotheque/pear/Calendar/Decorator/Wrapper.php |
---|
New file |
0,0 → 1,90 |
<?php |
/* vim: set expandtab tabstop=4 shiftwidth=4: */ |
// |
// +----------------------------------------------------------------------+ |
// | PHP Version 4 | |
// +----------------------------------------------------------------------+ |
// | Copyright (c) 1997-2002 The PHP Group | |
// +----------------------------------------------------------------------+ |
// | This source file is subject to version 2.02 of the PHP license, | |
// | that is bundled with this package in the file LICENSE, and is | |
// | available at through the world-wide-web at | |
// | http://www.php.net/license/3_0.txt. | |
// | If you did not receive a copy of the PHP license and are unable to | |
// | obtain it through the world-wide-web, please send a note to | |
// | license@php.net so we can mail you a copy immediately. | |
// +----------------------------------------------------------------------+ |
// | Authors: Harry Fuecks <hfuecks@phppatterns.com> | |
// | Lorenzo Alberton <l dot alberton at quipo dot it> | |
// +----------------------------------------------------------------------+ |
// |
// $Id: Wrapper.php,v 1.2 2005/11/03 20:35:03 quipo Exp $ |
// |
/** |
* @package Calendar |
* @version $Id: Wrapper.php,v 1.2 2005/11/03 20:35:03 quipo Exp $ |
*/ |
/** |
* Allows Calendar include path to be redefined |
* @ignore |
*/ |
if (!defined('CALENDAR_ROOT')) { |
define('CALENDAR_ROOT', 'Calendar'.DIRECTORY_SEPARATOR); |
} |
/** |
* Load Calendar decorator base class |
*/ |
require_once CALENDAR_ROOT.'Decorator.php'; |
/** |
* Decorator to help with wrapping built children in another decorator |
* @package Calendar |
* @access public |
*/ |
class Calendar_Decorator_Wrapper extends Calendar_Decorator |
{ |
/** |
* Constructs Calendar_Decorator_Wrapper |
* @param object subclass of Calendar |
* @access public |
*/ |
function Calendar_Decorator_Wrapper(&$Calendar) |
{ |
parent::Calendar_Decorator($Calendar); |
} |
/** |
* Wraps objects returned from fetch in the named Decorator class |
* @param string name of Decorator class to wrap with |
* @return object instance of named decorator |
* @access public |
*/ |
function & fetch($decorator) |
{ |
$Calendar = parent::fetch(); |
if ($Calendar) { |
$ret =& new $decorator($Calendar); |
} else { |
$ret = false; |
} |
return $ret; |
} |
/** |
* Wraps the returned calendar objects from fetchAll in the named decorator |
* @param string name of Decorator class to wrap with |
* @return array |
* @access public |
*/ |
function fetchAll($decorator) |
{ |
$children = parent::fetchAll(); |
foreach ($children as $key => $Calendar) { |
$children[$key] = & new $decorator($Calendar); |
} |
return $children; |
} |
} |
?> |
/branches/v1.3-critias/bibliotheque/pear/System.php |
---|
New file |
0,0 → 1,622 |
<?php |
/** |
* File/Directory manipulation |
* |
* PHP versions 4 and 5 |
* |
* @category pear |
* @package System |
* @author Tomas V.V.Cox <cox@idecnet.com> |
* @copyright 1997-2009 The Authors |
* @license http://opensource.org/licenses/bsd-license.php New BSD License |
* @link http://pear.php.net/package/PEAR |
* @since File available since Release 0.1 |
*/ |
/** |
* base class |
*/ |
require_once 'PEAR.php'; |
require_once 'Console/Getopt.php'; |
$GLOBALS['_System_temp_files'] = array(); |
/** |
* System offers cross plattform compatible system functions |
* |
* Static functions for different operations. Should work under |
* Unix and Windows. The names and usage has been taken from its respectively |
* GNU commands. The functions will return (bool) false on error and will |
* trigger the error with the PHP trigger_error() function (you can silence |
* the error by prefixing a '@' sign after the function call, but this |
* is not recommended practice. Instead use an error handler with |
* {@link set_error_handler()}). |
* |
* Documentation on this class you can find in: |
* http://pear.php.net/manual/ |
* |
* Example usage: |
* if (!@System::rm('-r file1 dir1')) { |
* print "could not delete file1 or dir1"; |
* } |
* |
* In case you need to to pass file names with spaces, |
* pass the params as an array: |
* |
* System::rm(array('-r', $file1, $dir1)); |
* |
* @category pear |
* @package System |
* @author Tomas V.V. Cox <cox@idecnet.com> |
* @copyright 1997-2006 The PHP Group |
* @license http://opensource.org/licenses/bsd-license.php New BSD License |
* @version Release: 1.10.1 |
* @link http://pear.php.net/package/PEAR |
* @since Class available since Release 0.1 |
* @static |
*/ |
class System |
{ |
/** |
* returns the commandline arguments of a function |
* |
* @param string $argv the commandline |
* @param string $short_options the allowed option short-tags |
* @param string $long_options the allowed option long-tags |
* @return array the given options and there values |
*/ |
public static function _parseArgs($argv, $short_options, $long_options = null) |
{ |
if (!is_array($argv) && $argv !== null) { |
/* |
// Quote all items that are a short option |
$av = preg_split('/(\A| )--?[a-z0-9]+[ =]?((?<!\\\\)((,\s*)|((?<!,)\s+))?)/i', $argv, -1, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_OFFSET_CAPTURE); |
$offset = 0; |
foreach ($av as $a) { |
$b = trim($a[0]); |
if ($b{0} == '"' || $b{0} == "'") { |
continue; |
} |
$escape = escapeshellarg($b); |
$pos = $a[1] + $offset; |
$argv = substr_replace($argv, $escape, $pos, strlen($b)); |
$offset += 2; |
} |
*/ |
// Find all items, quoted or otherwise |
preg_match_all("/(?:[\"'])(.*?)(?:['\"])|([^\s]+)/", $argv, $av); |
$argv = $av[1]; |
foreach ($av[2] as $k => $a) { |
if (empty($a)) { |
continue; |
} |
$argv[$k] = trim($a) ; |
} |
} |
return Console_Getopt::getopt2($argv, $short_options, $long_options); |
} |
/** |
* Output errors with PHP trigger_error(). You can silence the errors |
* with prefixing a "@" sign to the function call: @System::mkdir(..); |
* |
* @param mixed $error a PEAR error or a string with the error message |
* @return bool false |
*/ |
protected static function raiseError($error) |
{ |
if (PEAR::isError($error)) { |
$error = $error->getMessage(); |
} |
trigger_error($error, E_USER_WARNING); |
return false; |
} |
/** |
* Creates a nested array representing the structure of a directory |
* |
* System::_dirToStruct('dir1', 0) => |
* Array |
* ( |
* [dirs] => Array |
* ( |
* [0] => dir1 |
* ) |
* |
* [files] => Array |
* ( |
* [0] => dir1/file2 |
* [1] => dir1/file3 |
* ) |
* ) |
* @param string $sPath Name of the directory |
* @param integer $maxinst max. deep of the lookup |
* @param integer $aktinst starting deep of the lookup |
* @param bool $silent if true, do not emit errors. |
* @return array the structure of the dir |
*/ |
protected static function _dirToStruct($sPath, $maxinst, $aktinst = 0, $silent = false) |
{ |
$struct = array('dirs' => array(), 'files' => array()); |
if (($dir = @opendir($sPath)) === false) { |
if (!$silent) { |
System::raiseError("Could not open dir $sPath"); |
} |
return $struct; // XXX could not open error |
} |
$struct['dirs'][] = $sPath = realpath($sPath); // XXX don't add if '.' or '..' ? |
$list = array(); |
while (false !== ($file = readdir($dir))) { |
if ($file != '.' && $file != '..') { |
$list[] = $file; |
} |
} |
closedir($dir); |
natsort($list); |
if ($aktinst < $maxinst || $maxinst == 0) { |
foreach ($list as $val) { |
$path = $sPath . DIRECTORY_SEPARATOR . $val; |
if (is_dir($path) && !is_link($path)) { |
$tmp = System::_dirToStruct($path, $maxinst, $aktinst+1, $silent); |
$struct = array_merge_recursive($struct, $tmp); |
} else { |
$struct['files'][] = $path; |
} |
} |
} |
return $struct; |
} |
/** |
* Creates a nested array representing the structure of a directory and files |
* |
* @param array $files Array listing files and dirs |
* @return array |
* @static |
* @see System::_dirToStruct() |
*/ |
protected static function _multipleToStruct($files) |
{ |
$struct = array('dirs' => array(), 'files' => array()); |
settype($files, 'array'); |
foreach ($files as $file) { |
if (is_dir($file) && !is_link($file)) { |
$tmp = System::_dirToStruct($file, 0); |
$struct = array_merge_recursive($tmp, $struct); |
} else { |
if (!in_array($file, $struct['files'])) { |
$struct['files'][] = $file; |
} |
} |
} |
return $struct; |
} |
/** |
* The rm command for removing files. |
* Supports multiple files and dirs and also recursive deletes |
* |
* @param string $args the arguments for rm |
* @return mixed PEAR_Error or true for success |
* @static |
* @access public |
*/ |
public static function rm($args) |
{ |
$opts = System::_parseArgs($args, 'rf'); // "f" does nothing but I like it :-) |
if (PEAR::isError($opts)) { |
return System::raiseError($opts); |
} |
foreach ($opts[0] as $opt) { |
if ($opt[0] == 'r') { |
$do_recursive = true; |
} |
} |
$ret = true; |
if (isset($do_recursive)) { |
$struct = System::_multipleToStruct($opts[1]); |
foreach ($struct['files'] as $file) { |
if (!@unlink($file)) { |
$ret = false; |
} |
} |
rsort($struct['dirs']); |
foreach ($struct['dirs'] as $dir) { |
if (!@rmdir($dir)) { |
$ret = false; |
} |
} |
} else { |
foreach ($opts[1] as $file) { |
$delete = (is_dir($file)) ? 'rmdir' : 'unlink'; |
if (!@$delete($file)) { |
$ret = false; |
} |
} |
} |
return $ret; |
} |
/** |
* Make directories. |
* |
* The -p option will create parent directories |
* @param string $args the name of the director(y|ies) to create |
* @return bool True for success |
*/ |
public static function mkDir($args) |
{ |
$opts = System::_parseArgs($args, 'pm:'); |
if (PEAR::isError($opts)) { |
return System::raiseError($opts); |
} |
$mode = 0777; // default mode |
foreach ($opts[0] as $opt) { |
if ($opt[0] == 'p') { |
$create_parents = true; |
} elseif ($opt[0] == 'm') { |
// if the mode is clearly an octal number (starts with 0) |
// convert it to decimal |
if (strlen($opt[1]) && $opt[1]{0} == '0') { |
$opt[1] = octdec($opt[1]); |
} else { |
// convert to int |
$opt[1] += 0; |
} |
$mode = $opt[1]; |
} |
} |
$ret = true; |
if (isset($create_parents)) { |
foreach ($opts[1] as $dir) { |
$dirstack = array(); |
while ((!file_exists($dir) || !is_dir($dir)) && |
$dir != DIRECTORY_SEPARATOR) { |
array_unshift($dirstack, $dir); |
$dir = dirname($dir); |
} |
while ($newdir = array_shift($dirstack)) { |
if (!is_writeable(dirname($newdir))) { |
$ret = false; |
break; |
} |
if (!mkdir($newdir, $mode)) { |
$ret = false; |
} |
} |
} |
} else { |
foreach($opts[1] as $dir) { |
if ((@file_exists($dir) || !is_dir($dir)) && !mkdir($dir, $mode)) { |
$ret = false; |
} |
} |
} |
return $ret; |
} |
/** |
* Concatenate files |
* |
* Usage: |
* 1) $var = System::cat('sample.txt test.txt'); |
* 2) System::cat('sample.txt test.txt > final.txt'); |
* 3) System::cat('sample.txt test.txt >> final.txt'); |
* |
* Note: as the class use fopen, urls should work also (test that) |
* |
* @param string $args the arguments |
* @return boolean true on success |
*/ |
public static function &cat($args) |
{ |
$ret = null; |
$files = array(); |
if (!is_array($args)) { |
$args = preg_split('/\s+/', $args, -1, PREG_SPLIT_NO_EMPTY); |
} |
$count_args = count($args); |
for ($i = 0; $i < $count_args; $i++) { |
if ($args[$i] == '>') { |
$mode = 'wb'; |
$outputfile = $args[$i+1]; |
break; |
} elseif ($args[$i] == '>>') { |
$mode = 'ab+'; |
$outputfile = $args[$i+1]; |
break; |
} else { |
$files[] = $args[$i]; |
} |
} |
$outputfd = false; |
if (isset($mode)) { |
if (!$outputfd = fopen($outputfile, $mode)) { |
$err = System::raiseError("Could not open $outputfile"); |
return $err; |
} |
$ret = true; |
} |
foreach ($files as $file) { |
if (!$fd = fopen($file, 'r')) { |
System::raiseError("Could not open $file"); |
continue; |
} |
while ($cont = fread($fd, 2048)) { |
if (is_resource($outputfd)) { |
fwrite($outputfd, $cont); |
} else { |
$ret .= $cont; |
} |
} |
fclose($fd); |
} |
if (is_resource($outputfd)) { |
fclose($outputfd); |
} |
return $ret; |
} |
/** |
* Creates temporary files or directories. This function will remove |
* the created files when the scripts finish its execution. |
* |
* Usage: |
* 1) $tempfile = System::mktemp("prefix"); |
* 2) $tempdir = System::mktemp("-d prefix"); |
* 3) $tempfile = System::mktemp(); |
* 4) $tempfile = System::mktemp("-t /var/tmp prefix"); |
* |
* prefix -> The string that will be prepended to the temp name |
* (defaults to "tmp"). |
* -d -> A temporary dir will be created instead of a file. |
* -t -> The target dir where the temporary (file|dir) will be created. If |
* this param is missing by default the env vars TMP on Windows or |
* TMPDIR in Unix will be used. If these vars are also missing |
* c:\windows\temp or /tmp will be used. |
* |
* @param string $args The arguments |
* @return mixed the full path of the created (file|dir) or false |
* @see System::tmpdir() |
*/ |
public static function mktemp($args = null) |
{ |
static $first_time = true; |
$opts = System::_parseArgs($args, 't:d'); |
if (PEAR::isError($opts)) { |
return System::raiseError($opts); |
} |
foreach ($opts[0] as $opt) { |
if ($opt[0] == 'd') { |
$tmp_is_dir = true; |
} elseif ($opt[0] == 't') { |
$tmpdir = $opt[1]; |
} |
} |
$prefix = (isset($opts[1][0])) ? $opts[1][0] : 'tmp'; |
if (!isset($tmpdir)) { |
$tmpdir = System::tmpdir(); |
} |
if (!System::mkDir(array('-p', $tmpdir))) { |
return false; |
} |
$tmp = tempnam($tmpdir, $prefix); |
if (isset($tmp_is_dir)) { |
unlink($tmp); // be careful possible race condition here |
if (!mkdir($tmp, 0700)) { |
return System::raiseError("Unable to create temporary directory $tmpdir"); |
} |
} |
$GLOBALS['_System_temp_files'][] = $tmp; |
if (isset($tmp_is_dir)) { |
//$GLOBALS['_System_temp_files'][] = dirname($tmp); |
} |
if ($first_time) { |
PEAR::registerShutdownFunc(array('System', '_removeTmpFiles')); |
$first_time = false; |
} |
return $tmp; |
} |
/** |
* Remove temporary files created my mkTemp. This function is executed |
* at script shutdown time |
*/ |
public static function _removeTmpFiles() |
{ |
if (count($GLOBALS['_System_temp_files'])) { |
$delete = $GLOBALS['_System_temp_files']; |
array_unshift($delete, '-r'); |
System::rm($delete); |
$GLOBALS['_System_temp_files'] = array(); |
} |
} |
/** |
* Get the path of the temporal directory set in the system |
* by looking in its environments variables. |
* Note: php.ini-recommended removes the "E" from the variables_order setting, |
* making unavaible the $_ENV array, that s why we do tests with _ENV |
* |
* @return string The temporary directory on the system |
*/ |
public static function tmpdir() |
{ |
if (OS_WINDOWS) { |
if ($var = isset($_ENV['TMP']) ? $_ENV['TMP'] : getenv('TMP')) { |
return $var; |
} |
if ($var = isset($_ENV['TEMP']) ? $_ENV['TEMP'] : getenv('TEMP')) { |
return $var; |
} |
if ($var = isset($_ENV['USERPROFILE']) ? $_ENV['USERPROFILE'] : getenv('USERPROFILE')) { |
return $var; |
} |
if ($var = isset($_ENV['windir']) ? $_ENV['windir'] : getenv('windir')) { |
return $var; |
} |
return getenv('SystemRoot') . '\temp'; |
} |
if ($var = isset($_ENV['TMPDIR']) ? $_ENV['TMPDIR'] : getenv('TMPDIR')) { |
return $var; |
} |
return realpath('/tmp'); |
} |
/** |
* The "which" command (show the full path of a command) |
* |
* @param string $program The command to search for |
* @param mixed $fallback Value to return if $program is not found |
* |
* @return mixed A string with the full path or false if not found |
* @author Stig Bakken <ssb@php.net> |
*/ |
public static function which($program, $fallback = false) |
{ |
// enforce API |
if (!is_string($program) || '' == $program) { |
return $fallback; |
} |
// full path given |
if (basename($program) != $program) { |
$path_elements[] = dirname($program); |
$program = basename($program); |
} else { |
$path = getenv('PATH'); |
if (!$path) { |
$path = getenv('Path'); // some OSes are just stupid enough to do this |
} |
$path_elements = explode(PATH_SEPARATOR, $path); |
} |
if (OS_WINDOWS) { |
$exe_suffixes = getenv('PATHEXT') |
? explode(PATH_SEPARATOR, getenv('PATHEXT')) |
: array('.exe','.bat','.cmd','.com'); |
// allow passing a command.exe param |
if (strpos($program, '.') !== false) { |
array_unshift($exe_suffixes, ''); |
} |
} else { |
$exe_suffixes = array(''); |
} |
foreach ($exe_suffixes as $suff) { |
foreach ($path_elements as $dir) { |
$file = $dir . DIRECTORY_SEPARATOR . $program . $suff; |
if (is_executable($file)) { |
return $file; |
} |
} |
} |
return $fallback; |
} |
/** |
* The "find" command |
* |
* Usage: |
* |
* System::find($dir); |
* System::find("$dir -type d"); |
* System::find("$dir -type f"); |
* System::find("$dir -name *.php"); |
* System::find("$dir -name *.php -name *.htm*"); |
* System::find("$dir -maxdepth 1"); |
* |
* Params implmented: |
* $dir -> Start the search at this directory |
* -type d -> return only directories |
* -type f -> return only files |
* -maxdepth <n> -> max depth of recursion |
* -name <pattern> -> search pattern (bash style). Multiple -name param allowed |
* |
* @param mixed Either array or string with the command line |
* @return array Array of found files |
*/ |
public static function find($args) |
{ |
if (!is_array($args)) { |
$args = preg_split('/\s+/', $args, -1, PREG_SPLIT_NO_EMPTY); |
} |
$dir = realpath(array_shift($args)); |
if (!$dir) { |
return array(); |
} |
$patterns = array(); |
$depth = 0; |
$do_files = $do_dirs = true; |
$args_count = count($args); |
for ($i = 0; $i < $args_count; $i++) { |
switch ($args[$i]) { |
case '-type': |
if (in_array($args[$i+1], array('d', 'f'))) { |
if ($args[$i+1] == 'd') { |
$do_files = false; |
} else { |
$do_dirs = false; |
} |
} |
$i++; |
break; |
case '-name': |
$name = preg_quote($args[$i+1], '#'); |
// our magic characters ? and * have just been escaped, |
// so now we change the escaped versions to PCRE operators |
$name = strtr($name, array('\?' => '.', '\*' => '.*')); |
$patterns[] = '('.$name.')'; |
$i++; |
break; |
case '-maxdepth': |
$depth = $args[$i+1]; |
break; |
} |
} |
$path = System::_dirToStruct($dir, $depth, 0, true); |
if ($do_files && $do_dirs) { |
$files = array_merge($path['files'], $path['dirs']); |
} elseif ($do_dirs) { |
$files = $path['dirs']; |
} else { |
$files = $path['files']; |
} |
if (count($patterns)) { |
$dsq = preg_quote(DIRECTORY_SEPARATOR, '#'); |
$pattern = '#(^|'.$dsq.')'.implode('|', $patterns).'($|'.$dsq.')#'; |
$ret = array(); |
$files_count = count($files); |
for ($i = 0; $i < $files_count; $i++) { |
// only search in the part of the file below the current directory |
$filepart = basename($files[$i]); |
if (preg_match($pattern, $filepart)) { |
$ret[] = $files[$i]; |
} |
} |
return $ret; |
} |
return $files; |
} |
} |
/branches/v1.3-critias/bibliotheque/pear/DB.php |
---|
New file |
0,0 → 1,1504 |
<?php |
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */ |
/** |
* Database independent query interface |
* |
* PHP version 5 |
* |
* LICENSE: This source file is subject to version 3.0 of the PHP license |
* that is available through the world-wide-web at the following URI: |
* http://www.php.net/license/3_0.txt. If you did not receive a copy of |
* the PHP License and are unable to obtain it through the web, please |
* send a note to license@php.net so we can mail you a copy immediately. |
* |
* @category Database |
* @package DB |
* @author Stig Bakken <ssb@php.net> |
* @author Tomas V.V.Cox <cox@idecnet.com> |
* @author Daniel Convissor <danielc@php.net> |
* @copyright 1997-2007 The PHP Group |
* @license http://www.php.net/license/3_0.txt PHP License 3.0 |
* @version CVS: $Id$ |
* @link http://pear.php.net/package/DB |
*/ |
/** |
* Obtain the PEAR class so it can be extended from |
*/ |
require_once 'PEAR.php'; |
// {{{ constants |
// {{{ error codes |
/**#@+ |
* One of PEAR DB's portable error codes. |
* @see DB_common::errorCode(), DB::errorMessage() |
* |
* {@internal If you add an error code here, make sure you also add a textual |
* version of it in DB::errorMessage().}} |
*/ |
/** |
* The code returned by many methods upon success |
*/ |
define('DB_OK', 1); |
/** |
* Unkown error |
*/ |
define('DB_ERROR', -1); |
/** |
* Syntax error |
*/ |
define('DB_ERROR_SYNTAX', -2); |
/** |
* Tried to insert a duplicate value into a primary or unique index |
*/ |
define('DB_ERROR_CONSTRAINT', -3); |
/** |
* An identifier in the query refers to a non-existant object |
*/ |
define('DB_ERROR_NOT_FOUND', -4); |
/** |
* Tried to create a duplicate object |
*/ |
define('DB_ERROR_ALREADY_EXISTS', -5); |
/** |
* The current driver does not support the action you attempted |
*/ |
define('DB_ERROR_UNSUPPORTED', -6); |
/** |
* The number of parameters does not match the number of placeholders |
*/ |
define('DB_ERROR_MISMATCH', -7); |
/** |
* A literal submitted did not match the data type expected |
*/ |
define('DB_ERROR_INVALID', -8); |
/** |
* The current DBMS does not support the action you attempted |
*/ |
define('DB_ERROR_NOT_CAPABLE', -9); |
/** |
* A literal submitted was too long so the end of it was removed |
*/ |
define('DB_ERROR_TRUNCATED', -10); |
/** |
* A literal number submitted did not match the data type expected |
*/ |
define('DB_ERROR_INVALID_NUMBER', -11); |
/** |
* A literal date submitted did not match the data type expected |
*/ |
define('DB_ERROR_INVALID_DATE', -12); |
/** |
* Attempt to divide something by zero |
*/ |
define('DB_ERROR_DIVZERO', -13); |
/** |
* A database needs to be selected |
*/ |
define('DB_ERROR_NODBSELECTED', -14); |
/** |
* Could not create the object requested |
*/ |
define('DB_ERROR_CANNOT_CREATE', -15); |
/** |
* Could not drop the database requested because it does not exist |
*/ |
define('DB_ERROR_CANNOT_DROP', -17); |
/** |
* An identifier in the query refers to a non-existant table |
*/ |
define('DB_ERROR_NOSUCHTABLE', -18); |
/** |
* An identifier in the query refers to a non-existant column |
*/ |
define('DB_ERROR_NOSUCHFIELD', -19); |
/** |
* The data submitted to the method was inappropriate |
*/ |
define('DB_ERROR_NEED_MORE_DATA', -20); |
/** |
* The attempt to lock the table failed |
*/ |
define('DB_ERROR_NOT_LOCKED', -21); |
/** |
* The number of columns doesn't match the number of values |
*/ |
define('DB_ERROR_VALUE_COUNT_ON_ROW', -22); |
/** |
* The DSN submitted has problems |
*/ |
define('DB_ERROR_INVALID_DSN', -23); |
/** |
* Could not connect to the database |
*/ |
define('DB_ERROR_CONNECT_FAILED', -24); |
/** |
* The PHP extension needed for this DBMS could not be found |
*/ |
define('DB_ERROR_EXTENSION_NOT_FOUND',-25); |
/** |
* The present user has inadequate permissions to perform the task requestd |
*/ |
define('DB_ERROR_ACCESS_VIOLATION', -26); |
/** |
* The database requested does not exist |
*/ |
define('DB_ERROR_NOSUCHDB', -27); |
/** |
* Tried to insert a null value into a column that doesn't allow nulls |
*/ |
define('DB_ERROR_CONSTRAINT_NOT_NULL',-29); |
/**#@-*/ |
// }}} |
// {{{ prepared statement-related |
/**#@+ |
* Identifiers for the placeholders used in prepared statements. |
* @see DB_common::prepare() |
*/ |
/** |
* Indicates a scalar (<kbd>?</kbd>) placeholder was used |
* |
* Quote and escape the value as necessary. |
*/ |
define('DB_PARAM_SCALAR', 1); |
/** |
* Indicates an opaque (<kbd>&</kbd>) placeholder was used |
* |
* The value presented is a file name. Extract the contents of that file |
* and place them in this column. |
*/ |
define('DB_PARAM_OPAQUE', 2); |
/** |
* Indicates a misc (<kbd>!</kbd>) placeholder was used |
* |
* The value should not be quoted or escaped. |
*/ |
define('DB_PARAM_MISC', 3); |
/**#@-*/ |
// }}} |
// {{{ binary data-related |
/**#@+ |
* The different ways of returning binary data from queries. |
*/ |
/** |
* Sends the fetched data straight through to output |
*/ |
define('DB_BINMODE_PASSTHRU', 1); |
/** |
* Lets you return data as usual |
*/ |
define('DB_BINMODE_RETURN', 2); |
/** |
* Converts the data to hex format before returning it |
* |
* For example the string "123" would become "313233". |
*/ |
define('DB_BINMODE_CONVERT', 3); |
/**#@-*/ |
// }}} |
// {{{ fetch modes |
/**#@+ |
* Fetch Modes. |
* @see DB_common::setFetchMode() |
*/ |
/** |
* Indicates the current default fetch mode should be used |
* @see DB_common::$fetchmode |
*/ |
define('DB_FETCHMODE_DEFAULT', 0); |
/** |
* Column data indexed by numbers, ordered from 0 and up |
*/ |
define('DB_FETCHMODE_ORDERED', 1); |
/** |
* Column data indexed by column names |
*/ |
define('DB_FETCHMODE_ASSOC', 2); |
/** |
* Column data as object properties |
*/ |
define('DB_FETCHMODE_OBJECT', 3); |
/** |
* For multi-dimensional results, make the column name the first level |
* of the array and put the row number in the second level of the array |
* |
* This is flipped from the normal behavior, which puts the row numbers |
* in the first level of the array and the column names in the second level. |
*/ |
define('DB_FETCHMODE_FLIPPED', 4); |
/**#@-*/ |
/**#@+ |
* Old fetch modes. Left here for compatibility. |
*/ |
define('DB_GETMODE_ORDERED', DB_FETCHMODE_ORDERED); |
define('DB_GETMODE_ASSOC', DB_FETCHMODE_ASSOC); |
define('DB_GETMODE_FLIPPED', DB_FETCHMODE_FLIPPED); |
/**#@-*/ |
// }}} |
// {{{ tableInfo() && autoPrepare()-related |
/**#@+ |
* The type of information to return from the tableInfo() method. |
* |
* Bitwised constants, so they can be combined using <kbd>|</kbd> |
* and removed using <kbd>^</kbd>. |
* |
* @see DB_common::tableInfo() |
* |
* {@internal Since the TABLEINFO constants are bitwised, if more of them are |
* added in the future, make sure to adjust DB_TABLEINFO_FULL accordingly.}} |
*/ |
define('DB_TABLEINFO_ORDER', 1); |
define('DB_TABLEINFO_ORDERTABLE', 2); |
define('DB_TABLEINFO_FULL', 3); |
/**#@-*/ |
/**#@+ |
* The type of query to create with the automatic query building methods. |
* @see DB_common::autoPrepare(), DB_common::autoExecute() |
*/ |
define('DB_AUTOQUERY_INSERT', 1); |
define('DB_AUTOQUERY_UPDATE', 2); |
/**#@-*/ |
// }}} |
// {{{ portability modes |
/**#@+ |
* Portability Modes. |
* |
* Bitwised constants, so they can be combined using <kbd>|</kbd> |
* and removed using <kbd>^</kbd>. |
* |
* @see DB_common::setOption() |
* |
* {@internal Since the PORTABILITY constants are bitwised, if more of them are |
* added in the future, make sure to adjust DB_PORTABILITY_ALL accordingly.}} |
*/ |
/** |
* Turn off all portability features |
*/ |
define('DB_PORTABILITY_NONE', 0); |
/** |
* Convert names of tables and fields to lower case |
* when using the get*(), fetch*() and tableInfo() methods |
*/ |
define('DB_PORTABILITY_LOWERCASE', 1); |
/** |
* Right trim the data output by get*() and fetch*() |
*/ |
define('DB_PORTABILITY_RTRIM', 2); |
/** |
* Force reporting the number of rows deleted |
*/ |
define('DB_PORTABILITY_DELETE_COUNT', 4); |
/** |
* Enable hack that makes numRows() work in Oracle |
*/ |
define('DB_PORTABILITY_NUMROWS', 8); |
/** |
* Makes certain error messages in certain drivers compatible |
* with those from other DBMS's |
* |
* + mysql, mysqli: change unique/primary key constraints |
* DB_ERROR_ALREADY_EXISTS -> DB_ERROR_CONSTRAINT |
* |
* + odbc(access): MS's ODBC driver reports 'no such field' as code |
* 07001, which means 'too few parameters.' When this option is on |
* that code gets mapped to DB_ERROR_NOSUCHFIELD. |
*/ |
define('DB_PORTABILITY_ERRORS', 16); |
/** |
* Convert null values to empty strings in data output by |
* get*() and fetch*() |
*/ |
define('DB_PORTABILITY_NULL_TO_EMPTY', 32); |
/** |
* Turn on all portability features |
*/ |
define('DB_PORTABILITY_ALL', 63); |
/**#@-*/ |
// }}} |
// }}} |
// {{{ class DB |
/** |
* Database independent query interface |
* |
* The main "DB" class is simply a container class with some static |
* methods for creating DB objects as well as some utility functions |
* common to all parts of DB. |
* |
* The object model of DB is as follows (indentation means inheritance): |
* <pre> |
* DB The main DB class. This is simply a utility class |
* with some "static" methods for creating DB objects as |
* well as common utility functions for other DB classes. |
* |
* DB_common The base for each DB implementation. Provides default |
* | implementations (in OO lingo virtual methods) for |
* | the actual DB implementations as well as a bunch of |
* | query utility functions. |
* | |
* +-DB_mysql The DB implementation for MySQL. Inherits DB_common. |
* When calling DB::factory or DB::connect for MySQL |
* connections, the object returned is an instance of this |
* class. |
* </pre> |
* |
* @category Database |
* @package DB |
* @author Stig Bakken <ssb@php.net> |
* @author Tomas V.V.Cox <cox@idecnet.com> |
* @author Daniel Convissor <danielc@php.net> |
* @copyright 1997-2007 The PHP Group |
* @license http://www.php.net/license/3_0.txt PHP License 3.0 |
* @version Release: 1.9.2 |
* @link http://pear.php.net/package/DB |
*/ |
class DB |
{ |
// {{{ factory() |
/** |
* Create a new DB object for the specified database type but don't |
* connect to the database |
* |
* @param string $type the database type (eg "mysql") |
* @param array $options an associative array of option names and values |
* |
* @return object a new DB object. A DB_Error object on failure. |
* |
* @see DB_common::setOption() |
*/ |
public static function factory($type, $options = false) |
{ |
if (!is_array($options)) { |
$options = array('persistent' => $options); |
} |
if (isset($options['debug']) && $options['debug'] >= 2) { |
// expose php errors with sufficient debug level |
include_once "DB/{$type}.php"; |
} else { |
@include_once "DB/{$type}.php"; |
} |
$classname = "DB_${type}"; |
if (!class_exists($classname)) { |
$tmp = PEAR::raiseError(null, DB_ERROR_NOT_FOUND, null, null, |
"Unable to include the DB/{$type}.php" |
. " file for '$dsn'", |
'DB_Error', true); |
return $tmp; |
} |
@$obj = new $classname; |
foreach ($options as $option => $value) { |
$test = $obj->setOption($option, $value); |
if (DB::isError($test)) { |
return $test; |
} |
} |
return $obj; |
} |
// }}} |
// {{{ connect() |
/** |
* Create a new DB object including a connection to the specified database |
* |
* Example 1. |
* <code> |
* require_once 'DB.php'; |
* |
* $dsn = 'pgsql://user:password@host/database'; |
* $options = array( |
* 'debug' => 2, |
* 'portability' => DB_PORTABILITY_ALL, |
* ); |
* |
* $db = DB::connect($dsn, $options); |
* if (PEAR::isError($db)) { |
* die($db->getMessage()); |
* } |
* </code> |
* |
* @param mixed $dsn the string "data source name" or array in the |
* format returned by DB::parseDSN() |
* @param array $options an associative array of option names and values |
* |
* @return object a new DB object. A DB_Error object on failure. |
* |
* @uses DB_dbase::connect(), DB_fbsql::connect(), DB_ibase::connect(), |
* DB_ifx::connect(), DB_msql::connect(), DB_mssql::connect(), |
* DB_mysql::connect(), DB_mysqli::connect(), DB_oci8::connect(), |
* DB_odbc::connect(), DB_pgsql::connect(), DB_sqlite::connect(), |
* DB_sybase::connect() |
* |
* @uses DB::parseDSN(), DB_common::setOption(), PEAR::isError() |
*/ |
public static function connect($dsn, $options = array()) |
{ |
$dsninfo = DB::parseDSN($dsn); |
$type = $dsninfo['phptype']; |
if (!is_array($options)) { |
/* |
* For backwards compatibility. $options used to be boolean, |
* indicating whether the connection should be persistent. |
*/ |
$options = array('persistent' => $options); |
} |
if (isset($options['debug']) && $options['debug'] >= 2) { |
// expose php errors with sufficient debug level |
include_once "DB/${type}.php"; |
} else { |
@include_once "DB/${type}.php"; |
} |
$classname = "DB_${type}"; |
if (!class_exists($classname)) { |
$tmp = PEAR::raiseError(null, DB_ERROR_NOT_FOUND, null, null, |
"Unable to include the DB/{$type}.php" |
. " file for '" |
. DB::getDSNString($dsn, true) . "'", |
'DB_Error', true); |
return $tmp; |
} |
@$obj = new $classname; |
foreach ($options as $option => $value) { |
$test = $obj->setOption($option, $value); |
if (DB::isError($test)) { |
return $test; |
} |
} |
$err = $obj->connect($dsninfo, $obj->getOption('persistent')); |
if (DB::isError($err)) { |
if (is_array($dsn)) { |
$err->addUserInfo(DB::getDSNString($dsn, true)); |
} else { |
$err->addUserInfo($dsn); |
} |
return $err; |
} |
return $obj; |
} |
// }}} |
// {{{ apiVersion() |
/** |
* Return the DB API version |
* |
* @return string the DB API version number |
*/ |
function apiVersion() |
{ |
return '1.9.2'; |
} |
// }}} |
// {{{ isError() |
/** |
* Determines if a variable is a DB_Error object |
* |
* @param mixed $value the variable to check |
* |
* @return bool whether $value is DB_Error object |
*/ |
public static function isError($value) |
{ |
return is_object($value) && is_a($value, 'DB_Error'); |
} |
// }}} |
// {{{ isConnection() |
/** |
* Determines if a value is a DB_<driver> object |
* |
* @param mixed $value the value to test |
* |
* @return bool whether $value is a DB_<driver> object |
*/ |
public static function isConnection($value) |
{ |
return (is_object($value) && |
is_subclass_of($value, 'db_common') && |
method_exists($value, 'simpleQuery')); |
} |
// }}} |
// {{{ isManip() |
/** |
* Tell whether a query is a data manipulation or data definition query |
* |
* Examples of data manipulation queries are INSERT, UPDATE and DELETE. |
* Examples of data definition queries are CREATE, DROP, ALTER, GRANT, |
* REVOKE. |
* |
* @param string $query the query |
* |
* @return boolean whether $query is a data manipulation query |
*/ |
public static function isManip($query) |
{ |
$manips = 'INSERT|UPDATE|DELETE|REPLACE|' |
. 'CREATE|DROP|' |
. 'LOAD DATA|SELECT .* INTO .* FROM|COPY|' |
. 'ALTER|GRANT|REVOKE|' |
. 'LOCK|UNLOCK'; |
if (preg_match('/^\s*"?(' . $manips . ')\s+/i', $query)) { |
return true; |
} |
return false; |
} |
// }}} |
// {{{ errorMessage() |
/** |
* Return a textual error message for a DB error code |
* |
* @param integer $value the DB error code |
* |
* @return string the error message or false if the error code was |
* not recognized |
*/ |
public static function errorMessage($value) |
{ |
static $errorMessages; |
if (!isset($errorMessages)) { |
$errorMessages = array( |
DB_ERROR => 'unknown error', |
DB_ERROR_ACCESS_VIOLATION => 'insufficient permissions', |
DB_ERROR_ALREADY_EXISTS => 'already exists', |
DB_ERROR_CANNOT_CREATE => 'can not create', |
DB_ERROR_CANNOT_DROP => 'can not drop', |
DB_ERROR_CONNECT_FAILED => 'connect failed', |
DB_ERROR_CONSTRAINT => 'constraint violation', |
DB_ERROR_CONSTRAINT_NOT_NULL=> 'null value violates not-null constraint', |
DB_ERROR_DIVZERO => 'division by zero', |
DB_ERROR_EXTENSION_NOT_FOUND=> 'extension not found', |
DB_ERROR_INVALID => 'invalid', |
DB_ERROR_INVALID_DATE => 'invalid date or time', |
DB_ERROR_INVALID_DSN => 'invalid DSN', |
DB_ERROR_INVALID_NUMBER => 'invalid number', |
DB_ERROR_MISMATCH => 'mismatch', |
DB_ERROR_NEED_MORE_DATA => 'insufficient data supplied', |
DB_ERROR_NODBSELECTED => 'no database selected', |
DB_ERROR_NOSUCHDB => 'no such database', |
DB_ERROR_NOSUCHFIELD => 'no such field', |
DB_ERROR_NOSUCHTABLE => 'no such table', |
DB_ERROR_NOT_CAPABLE => 'DB backend not capable', |
DB_ERROR_NOT_FOUND => 'not found', |
DB_ERROR_NOT_LOCKED => 'not locked', |
DB_ERROR_SYNTAX => 'syntax error', |
DB_ERROR_UNSUPPORTED => 'not supported', |
DB_ERROR_TRUNCATED => 'truncated', |
DB_ERROR_VALUE_COUNT_ON_ROW => 'value count on row', |
DB_OK => 'no error', |
); |
} |
if (DB::isError($value)) { |
$value = $value->getCode(); |
} |
return isset($errorMessages[$value]) ? $errorMessages[$value] |
: $errorMessages[DB_ERROR]; |
} |
// }}} |
// {{{ parseDSN() |
/** |
* Parse a data source name |
* |
* Additional keys can be added by appending a URI query string to the |
* end of the DSN. |
* |
* The format of the supplied DSN is in its fullest form: |
* <code> |
* phptype(dbsyntax)://username:password@protocol+hostspec/database?option=8&another=true |
* </code> |
* |
* Most variations are allowed: |
* <code> |
* phptype://username:password@protocol+hostspec:110//usr/db_file.db?mode=0644 |
* phptype://username:password@hostspec/database_name |
* phptype://username:password@hostspec |
* phptype://username@hostspec |
* phptype://hostspec/database |
* phptype://hostspec |
* phptype(dbsyntax) |
* phptype |
* </code> |
* |
* @param string $dsn Data Source Name to be parsed |
* |
* @return array an associative array with the following keys: |
* + phptype: Database backend used in PHP (mysql, odbc etc.) |
* + dbsyntax: Database used with regards to SQL syntax etc. |
* + protocol: Communication protocol to use (tcp, unix etc.) |
* + hostspec: Host specification (hostname[:port]) |
* + database: Database to use on the DBMS server |
* + username: User name for login |
* + password: Password for login |
*/ |
public static function parseDSN($dsn) |
{ |
$parsed = array( |
'phptype' => false, |
'dbsyntax' => false, |
'username' => false, |
'password' => false, |
'protocol' => false, |
'hostspec' => false, |
'port' => false, |
'socket' => false, |
'database' => false, |
); |
if (is_array($dsn)) { |
$dsn = array_merge($parsed, $dsn); |
if (!$dsn['dbsyntax']) { |
$dsn['dbsyntax'] = $dsn['phptype']; |
} |
return $dsn; |
} |
// Find phptype and dbsyntax |
if (($pos = strpos($dsn, '://')) !== false) { |
$str = substr($dsn, 0, $pos); |
$dsn = substr($dsn, $pos + 3); |
} else { |
$str = $dsn; |
$dsn = null; |
} |
// Get phptype and dbsyntax |
// $str => phptype(dbsyntax) |
if (preg_match('|^(.+?)\((.*?)\)$|', $str, $arr)) { |
$parsed['phptype'] = $arr[1]; |
$parsed['dbsyntax'] = !$arr[2] ? $arr[1] : $arr[2]; |
} else { |
$parsed['phptype'] = $str; |
$parsed['dbsyntax'] = $str; |
} |
if (!count($dsn)) { |
return $parsed; |
} |
// Get (if found): username and password |
// $dsn => username:password@protocol+hostspec/database |
if (($at = strrpos($dsn,'@')) !== false) { |
$str = substr($dsn, 0, $at); |
$dsn = substr($dsn, $at + 1); |
if (($pos = strpos($str, ':')) !== false) { |
$parsed['username'] = rawurldecode(substr($str, 0, $pos)); |
$parsed['password'] = rawurldecode(substr($str, $pos + 1)); |
} else { |
$parsed['username'] = rawurldecode($str); |
} |
} |
// Find protocol and hostspec |
if (preg_match('|^([^(]+)\((.*?)\)/?(.*?)$|', $dsn, $match)) { |
// $dsn => proto(proto_opts)/database |
$proto = $match[1]; |
$proto_opts = $match[2] ? $match[2] : false; |
$dsn = $match[3]; |
} else { |
// $dsn => protocol+hostspec/database (old format) |
if (strpos($dsn, '+') !== false) { |
list($proto, $dsn) = explode('+', $dsn, 2); |
} |
if (strpos($dsn, '/') !== false) { |
list($proto_opts, $dsn) = explode('/', $dsn, 2); |
} else { |
$proto_opts = $dsn; |
$dsn = null; |
} |
} |
// process the different protocol options |
$parsed['protocol'] = (!empty($proto)) ? $proto : 'tcp'; |
$proto_opts = rawurldecode($proto_opts); |
if (strpos($proto_opts, ':') !== false) { |
list($proto_opts, $parsed['port']) = explode(':', $proto_opts); |
} |
if ($parsed['protocol'] == 'tcp') { |
$parsed['hostspec'] = $proto_opts; |
} elseif ($parsed['protocol'] == 'unix') { |
$parsed['socket'] = $proto_opts; |
} |
// Get dabase if any |
// $dsn => database |
if ($dsn) { |
if (($pos = strpos($dsn, '?')) === false) { |
// /database |
$parsed['database'] = rawurldecode($dsn); |
} else { |
// /database?param1=value1¶m2=value2 |
$parsed['database'] = rawurldecode(substr($dsn, 0, $pos)); |
$dsn = substr($dsn, $pos + 1); |
if (strpos($dsn, '&') !== false) { |
$opts = explode('&', $dsn); |
} else { // database?param1=value1 |
$opts = array($dsn); |
} |
foreach ($opts as $opt) { |
list($key, $value) = explode('=', $opt); |
if (!isset($parsed[$key])) { |
// don't allow params overwrite |
$parsed[$key] = rawurldecode($value); |
} |
} |
} |
} |
return $parsed; |
} |
// }}} |
// {{{ getDSNString() |
/** |
* Returns the given DSN in a string format suitable for output. |
* |
* @param array|string the DSN to parse and format |
* @param boolean true to hide the password, false to include it |
* @return string |
*/ |
public static function getDSNString($dsn, $hidePassword) { |
/* Calling parseDSN will ensure that we have all the array elements |
* defined, and means that we deal with strings and array in the same |
* manner. */ |
$dsnArray = DB::parseDSN($dsn); |
if ($hidePassword) { |
$dsnArray['password'] = 'PASSWORD'; |
} |
/* Protocol is special-cased, as using the default "tcp" along with an |
* Oracle TNS connection string fails. */ |
if (is_string($dsn) && strpos($dsn, 'tcp') === false && $dsnArray['protocol'] == 'tcp') { |
$dsnArray['protocol'] = false; |
} |
// Now we just have to construct the actual string. This is ugly. |
$dsnString = $dsnArray['phptype']; |
if ($dsnArray['dbsyntax']) { |
$dsnString .= '('.$dsnArray['dbsyntax'].')'; |
} |
$dsnString .= '://' |
.$dsnArray['username'] |
.':' |
.$dsnArray['password'] |
.'@' |
.$dsnArray['protocol']; |
if ($dsnArray['socket']) { |
$dsnString .= '('.$dsnArray['socket'].')'; |
} |
if ($dsnArray['protocol'] && $dsnArray['hostspec']) { |
$dsnString .= '+'; |
} |
$dsnString .= $dsnArray['hostspec']; |
if ($dsnArray['port']) { |
$dsnString .= ':'.$dsnArray['port']; |
} |
$dsnString .= '/'.$dsnArray['database']; |
/* Option handling. Unfortunately, parseDSN simply places options into |
* the top-level array, so we'll first get rid of the fields defined by |
* DB and see what's left. */ |
unset($dsnArray['phptype'], |
$dsnArray['dbsyntax'], |
$dsnArray['username'], |
$dsnArray['password'], |
$dsnArray['protocol'], |
$dsnArray['socket'], |
$dsnArray['hostspec'], |
$dsnArray['port'], |
$dsnArray['database'] |
); |
if (count($dsnArray) > 0) { |
$dsnString .= '?'; |
$i = 0; |
foreach ($dsnArray as $key => $value) { |
if (++$i > 1) { |
$dsnString .= '&'; |
} |
$dsnString .= $key.'='.$value; |
} |
} |
return $dsnString; |
} |
// }}} |
} |
// }}} |
// {{{ class DB_Error |
/** |
* DB_Error implements a class for reporting portable database error |
* messages |
* |
* @category Database |
* @package DB |
* @author Stig Bakken <ssb@php.net> |
* @copyright 1997-2007 The PHP Group |
* @license http://www.php.net/license/3_0.txt PHP License 3.0 |
* @version Release: 1.9.2 |
* @link http://pear.php.net/package/DB |
*/ |
class DB_Error extends PEAR_Error |
{ |
// {{{ constructor |
/** |
* DB_Error constructor |
* |
* @param mixed $code DB error code, or string with error message |
* @param int $mode what "error mode" to operate in |
* @param int $level what error level to use for $mode & |
* PEAR_ERROR_TRIGGER |
* @param mixed $debuginfo additional debug info, such as the last query |
* |
* @see PEAR_Error |
*/ |
function __construct($code = DB_ERROR, $mode = PEAR_ERROR_RETURN, |
$level = E_USER_NOTICE, $debuginfo = null) |
{ |
if (is_int($code)) { |
parent::__construct('DB Error: ' . DB::errorMessage($code), $code, |
$mode, $level, $debuginfo); |
} else { |
parent::__construct("DB Error: $code", DB_ERROR, |
$mode, $level, $debuginfo); |
} |
} |
/** |
* Workaround to both avoid the "Redefining already defined constructor" |
* PHP error and provide backward compatibility in case someone is calling |
* DB_Error() dynamically |
*/ |
public function __call($method, $arguments) |
{ |
if ($method == 'DB_Error') { |
return call_user_func_array(array($this, '__construct'), $arguments); |
} |
trigger_error( |
'Call to undefined method DB_Error::' . $method . '()', E_USER_ERROR |
); |
} |
// }}} |
} |
// }}} |
// {{{ class DB_result |
/** |
* This class implements a wrapper for a DB result set |
* |
* A new instance of this class will be returned by the DB implementation |
* after processing a query that returns data. |
* |
* @category Database |
* @package DB |
* @author Stig Bakken <ssb@php.net> |
* @copyright 1997-2007 The PHP Group |
* @license http://www.php.net/license/3_0.txt PHP License 3.0 |
* @version Release: 1.9.2 |
* @link http://pear.php.net/package/DB |
*/ |
class DB_result |
{ |
// {{{ properties |
/** |
* Should results be freed automatically when there are no more rows? |
* @var boolean |
* @see DB_common::$options |
*/ |
var $autofree; |
/** |
* A reference to the DB_<driver> object |
* @var object |
*/ |
var $dbh; |
/** |
* The current default fetch mode |
* @var integer |
* @see DB_common::$fetchmode |
*/ |
var $fetchmode; |
/** |
* The name of the class into which results should be fetched when |
* DB_FETCHMODE_OBJECT is in effect |
* |
* @var string |
* @see DB_common::$fetchmode_object_class |
*/ |
var $fetchmode_object_class; |
/** |
* The number of rows to fetch from a limit query |
* @var integer |
*/ |
var $limit_count = null; |
/** |
* The row to start fetching from in limit queries |
* @var integer |
*/ |
var $limit_from = null; |
/** |
* The execute parameters that created this result |
* @var array |
* @since Property available since Release 1.7.0 |
*/ |
var $parameters; |
/** |
* The query string that created this result |
* |
* Copied here incase it changes in $dbh, which is referenced |
* |
* @var string |
* @since Property available since Release 1.7.0 |
*/ |
var $query; |
/** |
* The query result resource id created by PHP |
* @var resource |
*/ |
var $result; |
/** |
* The present row being dealt with |
* @var integer |
*/ |
var $row_counter = null; |
/** |
* The prepared statement resource id created by PHP in $dbh |
* |
* This resource is only available when the result set was created using |
* a driver's native execute() method, not PEAR DB's emulated one. |
* |
* Copied here incase it changes in $dbh, which is referenced |
* |
* {@internal Mainly here because the InterBase/Firebird API is only |
* able to retrieve data from result sets if the statemnt handle is |
* still in scope.}} |
* |
* @var resource |
* @since Property available since Release 1.7.0 |
*/ |
var $statement; |
// }}} |
// {{{ constructor |
/** |
* This constructor sets the object's properties |
* |
* @param object &$dbh the DB object reference |
* @param resource $result the result resource id |
* @param array $options an associative array with result options |
* |
* @return void |
*/ |
function __construct(&$dbh, $result, $options = array()) |
{ |
$this->autofree = $dbh->options['autofree']; |
$this->dbh = &$dbh; |
$this->fetchmode = $dbh->fetchmode; |
$this->fetchmode_object_class = $dbh->fetchmode_object_class; |
$this->parameters = $dbh->last_parameters; |
$this->query = $dbh->last_query; |
$this->result = $result; |
$this->statement = empty($dbh->last_stmt) ? null : $dbh->last_stmt; |
foreach ($options as $key => $value) { |
$this->setOption($key, $value); |
} |
} |
/** |
* Set options for the DB_result object |
* |
* @param string $key the option to set |
* @param mixed $value the value to set the option to |
* |
* @return void |
*/ |
function setOption($key, $value = null) |
{ |
switch ($key) { |
case 'limit_from': |
$this->limit_from = $value; |
break; |
case 'limit_count': |
$this->limit_count = $value; |
} |
} |
// }}} |
// {{{ fetchRow() |
/** |
* Fetch a row of data and return it by reference into an array |
* |
* The type of array returned can be controlled either by setting this |
* method's <var>$fetchmode</var> parameter or by changing the default |
* fetch mode setFetchMode() before calling this method. |
* |
* There are two options for standardizing the information returned |
* from databases, ensuring their values are consistent when changing |
* DBMS's. These portability options can be turned on when creating a |
* new DB object or by using setOption(). |
* |
* + <var>DB_PORTABILITY_LOWERCASE</var> |
* convert names of fields to lower case |
* |
* + <var>DB_PORTABILITY_RTRIM</var> |
* right trim the data |
* |
* @param int $fetchmode the constant indicating how to format the data |
* @param int $rownum the row number to fetch (index starts at 0) |
* |
* @return mixed an array or object containing the row's data, |
* NULL when the end of the result set is reached |
* or a DB_Error object on failure. |
* |
* @see DB_common::setOption(), DB_common::setFetchMode() |
*/ |
function &fetchRow($fetchmode = DB_FETCHMODE_DEFAULT, $rownum = null) |
{ |
if ($fetchmode === DB_FETCHMODE_DEFAULT) { |
$fetchmode = $this->fetchmode; |
} |
if ($fetchmode === DB_FETCHMODE_OBJECT) { |
$fetchmode = DB_FETCHMODE_ASSOC; |
$object_class = $this->fetchmode_object_class; |
} |
if (is_null($rownum) && $this->limit_from !== null) { |
if ($this->row_counter === null) { |
$this->row_counter = $this->limit_from; |
// Skip rows |
if ($this->dbh->features['limit'] === false) { |
$i = 0; |
while ($i++ < $this->limit_from) { |
$this->dbh->fetchInto($this->result, $arr, $fetchmode); |
} |
} |
} |
if ($this->row_counter >= ($this->limit_from + $this->limit_count)) |
{ |
if ($this->autofree) { |
$this->free(); |
} |
$tmp = null; |
return $tmp; |
} |
if ($this->dbh->features['limit'] === 'emulate') { |
$rownum = $this->row_counter; |
} |
$this->row_counter++; |
} |
$res = $this->dbh->fetchInto($this->result, $arr, $fetchmode, $rownum); |
if ($res === DB_OK) { |
if (isset($object_class)) { |
// The default mode is specified in the |
// DB_common::fetchmode_object_class property |
if ($object_class == 'stdClass') { |
$arr = (object) $arr; |
} else { |
$arr = new $object_class($arr); |
} |
} |
return $arr; |
} |
if ($res == null && $this->autofree) { |
$this->free(); |
} |
return $res; |
} |
// }}} |
// {{{ fetchInto() |
/** |
* Fetch a row of data into an array which is passed by reference |
* |
* The type of array returned can be controlled either by setting this |
* method's <var>$fetchmode</var> parameter or by changing the default |
* fetch mode setFetchMode() before calling this method. |
* |
* There are two options for standardizing the information returned |
* from databases, ensuring their values are consistent when changing |
* DBMS's. These portability options can be turned on when creating a |
* new DB object or by using setOption(). |
* |
* + <var>DB_PORTABILITY_LOWERCASE</var> |
* convert names of fields to lower case |
* |
* + <var>DB_PORTABILITY_RTRIM</var> |
* right trim the data |
* |
* @param array &$arr the variable where the data should be placed |
* @param int $fetchmode the constant indicating how to format the data |
* @param int $rownum the row number to fetch (index starts at 0) |
* |
* @return mixed DB_OK if a row is processed, NULL when the end of the |
* result set is reached or a DB_Error object on failure |
* |
* @see DB_common::setOption(), DB_common::setFetchMode() |
*/ |
function fetchInto(&$arr, $fetchmode = DB_FETCHMODE_DEFAULT, $rownum = null) |
{ |
if ($fetchmode === DB_FETCHMODE_DEFAULT) { |
$fetchmode = $this->fetchmode; |
} |
if ($fetchmode === DB_FETCHMODE_OBJECT) { |
$fetchmode = DB_FETCHMODE_ASSOC; |
$object_class = $this->fetchmode_object_class; |
} |
if (is_null($rownum) && $this->limit_from !== null) { |
if ($this->row_counter === null) { |
$this->row_counter = $this->limit_from; |
// Skip rows |
if ($this->dbh->features['limit'] === false) { |
$i = 0; |
while ($i++ < $this->limit_from) { |
$this->dbh->fetchInto($this->result, $arr, $fetchmode); |
} |
} |
} |
if ($this->row_counter >= ( |
$this->limit_from + $this->limit_count)) |
{ |
if ($this->autofree) { |
$this->free(); |
} |
return null; |
} |
if ($this->dbh->features['limit'] === 'emulate') { |
$rownum = $this->row_counter; |
} |
$this->row_counter++; |
} |
$res = $this->dbh->fetchInto($this->result, $arr, $fetchmode, $rownum); |
if ($res === DB_OK) { |
if (isset($object_class)) { |
// default mode specified in the |
// DB_common::fetchmode_object_class property |
if ($object_class == 'stdClass') { |
$arr = (object) $arr; |
} else { |
$arr = new $object_class($arr); |
} |
} |
return DB_OK; |
} |
if ($res == null && $this->autofree) { |
$this->free(); |
} |
return $res; |
} |
// }}} |
// {{{ numCols() |
/** |
* Get the the number of columns in a result set |
* |
* @return int the number of columns. A DB_Error object on failure. |
*/ |
function numCols() |
{ |
return $this->dbh->numCols($this->result); |
} |
// }}} |
// {{{ numRows() |
/** |
* Get the number of rows in a result set |
* |
* @return int the number of rows. A DB_Error object on failure. |
*/ |
function numRows() |
{ |
if ($this->dbh->features['numrows'] === 'emulate' |
&& $this->dbh->options['portability'] & DB_PORTABILITY_NUMROWS) |
{ |
if ($this->dbh->features['prepare']) { |
$res = $this->dbh->query($this->query, $this->parameters); |
} else { |
$res = $this->dbh->query($this->query); |
} |
if (DB::isError($res)) { |
return $res; |
} |
$i = 0; |
while ($res->fetchInto($tmp, DB_FETCHMODE_ORDERED)) { |
$i++; |
} |
$count = $i; |
} else { |
$count = $this->dbh->numRows($this->result); |
} |
/* fbsql is checked for here because limit queries are implemented |
* using a TOP() function, which results in fbsql_num_rows still |
* returning the total number of rows that would have been returned, |
* rather than the real number. As a result, we'll just do the limit |
* calculations for fbsql in the same way as a database with emulated |
* limits. Unfortunately, we can't just do this in DB_fbsql::numRows() |
* because that only gets the result resource, rather than the full |
* DB_Result object. */ |
if (($this->dbh->features['limit'] === 'emulate' |
&& $this->limit_from !== null) |
|| $this->dbh->phptype == 'fbsql') { |
$limit_count = is_null($this->limit_count) ? $count : $this->limit_count; |
if ($count < $this->limit_from) { |
$count = 0; |
} elseif ($count < ($this->limit_from + $limit_count)) { |
$count -= $this->limit_from; |
} else { |
$count = $limit_count; |
} |
} |
return $count; |
} |
// }}} |
// {{{ nextResult() |
/** |
* Get the next result if a batch of queries was executed |
* |
* @return bool true if a new result is available or false if not |
*/ |
function nextResult() |
{ |
return $this->dbh->nextResult($this->result); |
} |
// }}} |
// {{{ free() |
/** |
* Frees the resources allocated for this result set |
* |
* @return bool true on success. A DB_Error object on failure. |
*/ |
function free() |
{ |
$err = $this->dbh->freeResult($this->result); |
if (DB::isError($err)) { |
return $err; |
} |
$this->result = false; |
$this->statement = false; |
return true; |
} |
// }}} |
// {{{ tableInfo() |
/** |
* @see DB_common::tableInfo() |
* @deprecated Method deprecated some time before Release 1.2 |
*/ |
function tableInfo($mode = null) |
{ |
if (is_string($mode)) { |
return $this->dbh->raiseError(DB_ERROR_NEED_MORE_DATA); |
} |
return $this->dbh->tableInfo($this, $mode); |
} |
// }}} |
// {{{ getQuery() |
/** |
* Determine the query string that created this result |
* |
* @return string the query string |
* |
* @since Method available since Release 1.7.0 |
*/ |
function getQuery() |
{ |
return $this->query; |
} |
// }}} |
// {{{ getRowCounter() |
/** |
* Tells which row number is currently being processed |
* |
* @return integer the current row being looked at. Starts at 1. |
*/ |
function getRowCounter() |
{ |
return $this->row_counter; |
} |
// }}} |
} |
// }}} |
// {{{ class DB_row |
/** |
* PEAR DB Row Object |
* |
* The object contains a row of data from a result set. Each column's data |
* is placed in a property named for the column. |
* |
* @category Database |
* @package DB |
* @author Stig Bakken <ssb@php.net> |
* @copyright 1997-2007 The PHP Group |
* @license http://www.php.net/license/3_0.txt PHP License 3.0 |
* @version Release: 1.9.2 |
* @link http://pear.php.net/package/DB |
* @see DB_common::setFetchMode() |
*/ |
class DB_row |
{ |
// {{{ constructor |
/** |
* The constructor places a row's data into properties of this object |
* |
* @param array the array containing the row's data |
* |
* @return void |
*/ |
function __construct(&$arr) |
{ |
foreach ($arr as $key => $value) { |
$this->$key = &$arr[$key]; |
} |
} |
// }}} |
} |
// }}} |
/* |
* Local variables: |
* tab-width: 4 |
* c-basic-offset: 4 |
* End: |
*/ |
?> |
/branches/v1.3-critias/bibliotheque/pear/PEAR.php |
---|
New file |
0,0 → 1,1112 |
<?php |
/** |
* PEAR, the PHP Extension and Application Repository |
* |
* PEAR class and PEAR_Error class |
* |
* PHP versions 4 and 5 |
* |
* @category pear |
* @package PEAR |
* @author Sterling Hughes <sterling@php.net> |
* @author Stig Bakken <ssb@php.net> |
* @author Tomas V.V.Cox <cox@idecnet.com> |
* @author Greg Beaver <cellog@php.net> |
* @copyright 1997-2010 The Authors |
* @license http://opensource.org/licenses/bsd-license.php New BSD License |
* @link http://pear.php.net/package/PEAR |
* @since File available since Release 0.1 |
*/ |
/**#@+ |
* ERROR constants |
*/ |
define('PEAR_ERROR_RETURN', 1); |
define('PEAR_ERROR_PRINT', 2); |
define('PEAR_ERROR_TRIGGER', 4); |
define('PEAR_ERROR_DIE', 8); |
define('PEAR_ERROR_CALLBACK', 16); |
/** |
* WARNING: obsolete |
* @deprecated |
*/ |
define('PEAR_ERROR_EXCEPTION', 32); |
/**#@-*/ |
if (substr(PHP_OS, 0, 3) == 'WIN') { |
define('OS_WINDOWS', true); |
define('OS_UNIX', false); |
define('PEAR_OS', 'Windows'); |
} else { |
define('OS_WINDOWS', false); |
define('OS_UNIX', true); |
define('PEAR_OS', 'Unix'); // blatant assumption |
} |
$GLOBALS['_PEAR_default_error_mode'] = PEAR_ERROR_RETURN; |
$GLOBALS['_PEAR_default_error_options'] = E_USER_NOTICE; |
$GLOBALS['_PEAR_destructor_object_list'] = array(); |
$GLOBALS['_PEAR_shutdown_funcs'] = array(); |
$GLOBALS['_PEAR_error_handler_stack'] = array(); |
@ini_set('track_errors', true); |
/** |
* Base class for other PEAR classes. Provides rudimentary |
* emulation of destructors. |
* |
* If you want a destructor in your class, inherit PEAR and make a |
* destructor method called _yourclassname (same name as the |
* constructor, but with a "_" prefix). Also, in your constructor you |
* have to call the PEAR constructor: $this->PEAR();. |
* The destructor method will be called without parameters. Note that |
* at in some SAPI implementations (such as Apache), any output during |
* the request shutdown (in which destructors are called) seems to be |
* discarded. If you need to get any debug information from your |
* destructor, use error_log(), syslog() or something similar. |
* |
* IMPORTANT! To use the emulated destructors you need to create the |
* objects by reference: $obj =& new PEAR_child; |
* |
* @category pear |
* @package PEAR |
* @author Stig Bakken <ssb@php.net> |
* @author Tomas V.V. Cox <cox@idecnet.com> |
* @author Greg Beaver <cellog@php.net> |
* @copyright 1997-2006 The PHP Group |
* @license http://opensource.org/licenses/bsd-license.php New BSD License |
* @version Release: 1.10.1 |
* @link http://pear.php.net/package/PEAR |
* @see PEAR_Error |
* @since Class available since PHP 4.0.2 |
* @link http://pear.php.net/manual/en/core.pear.php#core.pear.pear |
*/ |
class PEAR |
{ |
/** |
* Whether to enable internal debug messages. |
* |
* @var bool |
* @access private |
*/ |
var $_debug = false; |
/** |
* Default error mode for this object. |
* |
* @var int |
* @access private |
*/ |
var $_default_error_mode = null; |
/** |
* Default error options used for this object when error mode |
* is PEAR_ERROR_TRIGGER. |
* |
* @var int |
* @access private |
*/ |
var $_default_error_options = null; |
/** |
* Default error handler (callback) for this object, if error mode is |
* PEAR_ERROR_CALLBACK. |
* |
* @var string |
* @access private |
*/ |
var $_default_error_handler = ''; |
/** |
* Which class to use for error objects. |
* |
* @var string |
* @access private |
*/ |
var $_error_class = 'PEAR_Error'; |
/** |
* An array of expected errors. |
* |
* @var array |
* @access private |
*/ |
var $_expected_errors = array(); |
/** |
* List of methods that can be called both statically and non-statically. |
* @var array |
*/ |
protected static $bivalentMethods = array( |
'setErrorHandling' => true, |
'raiseError' => true, |
'throwError' => true, |
'pushErrorHandling' => true, |
'popErrorHandling' => true, |
); |
/** |
* Constructor. Registers this object in |
* $_PEAR_destructor_object_list for destructor emulation if a |
* destructor object exists. |
* |
* @param string $error_class (optional) which class to use for |
* error objects, defaults to PEAR_Error. |
* @access public |
* @return void |
*/ |
function __construct($error_class = null) |
{ |
$classname = strtolower(get_class($this)); |
if ($this->_debug) { |
print "PEAR constructor called, class=$classname\n"; |
} |
if ($error_class !== null) { |
$this->_error_class = $error_class; |
} |
while ($classname && strcasecmp($classname, "pear")) { |
$destructor = "_$classname"; |
if (method_exists($this, $destructor)) { |
global $_PEAR_destructor_object_list; |
$_PEAR_destructor_object_list[] = &$this; |
if (!isset($GLOBALS['_PEAR_SHUTDOWN_REGISTERED'])) { |
register_shutdown_function("_PEAR_call_destructors"); |
$GLOBALS['_PEAR_SHUTDOWN_REGISTERED'] = true; |
} |
break; |
} else { |
$classname = get_parent_class($classname); |
} |
} |
} |
/** |
* Only here for backwards compatibility. |
* E.g. Archive_Tar calls $this->PEAR() in its constructor. |
* |
* @param string $error_class Which class to use for error objects, |
* defaults to PEAR_Error. |
*/ |
public function PEAR($error_class = null) |
{ |
self::__construct($error_class); |
} |
/** |
* Destructor (the emulated type of...). Does nothing right now, |
* but is included for forward compatibility, so subclass |
* destructors should always call it. |
* |
* See the note in the class desciption about output from |
* destructors. |
* |
* @access public |
* @return void |
*/ |
function _PEAR() { |
if ($this->_debug) { |
printf("PEAR destructor called, class=%s\n", strtolower(get_class($this))); |
} |
} |
public function __call($method, $arguments) |
{ |
if (!isset(self::$bivalentMethods[$method])) { |
trigger_error( |
'Call to undefined method PEAR::' . $method . '()', E_USER_ERROR |
); |
} |
return call_user_func_array( |
array(get_class(), '_' . $method), |
array_merge(array($this), $arguments) |
); |
} |
public static function __callStatic($method, $arguments) |
{ |
if (!isset(self::$bivalentMethods[$method])) { |
trigger_error( |
'Call to undefined method PEAR::' . $method . '()', E_USER_ERROR |
); |
} |
return call_user_func_array( |
array(get_class(), '_' . $method), |
array_merge(array(null), $arguments) |
); |
} |
/** |
* If you have a class that's mostly/entirely static, and you need static |
* properties, you can use this method to simulate them. Eg. in your method(s) |
* do this: $myVar = &PEAR::getStaticProperty('myclass', 'myVar'); |
* You MUST use a reference, or they will not persist! |
* |
* @param string $class The calling classname, to prevent clashes |
* @param string $var The variable to retrieve. |
* @return mixed A reference to the variable. If not set it will be |
* auto initialised to NULL. |
*/ |
public static function &getStaticProperty($class, $var) |
{ |
static $properties; |
if (!isset($properties[$class])) { |
$properties[$class] = array(); |
} |
if (!array_key_exists($var, $properties[$class])) { |
$properties[$class][$var] = null; |
} |
return $properties[$class][$var]; |
} |
/** |
* Use this function to register a shutdown method for static |
* classes. |
* |
* @param mixed $func The function name (or array of class/method) to call |
* @param mixed $args The arguments to pass to the function |
* |
* @return void |
*/ |
public static function registerShutdownFunc($func, $args = array()) |
{ |
// if we are called statically, there is a potential |
// that no shutdown func is registered. Bug #6445 |
if (!isset($GLOBALS['_PEAR_SHUTDOWN_REGISTERED'])) { |
register_shutdown_function("_PEAR_call_destructors"); |
$GLOBALS['_PEAR_SHUTDOWN_REGISTERED'] = true; |
} |
$GLOBALS['_PEAR_shutdown_funcs'][] = array($func, $args); |
} |
/** |
* Tell whether a value is a PEAR error. |
* |
* @param mixed $data the value to test |
* @param int $code if $data is an error object, return true |
* only if $code is a string and |
* $obj->getMessage() == $code or |
* $code is an integer and $obj->getCode() == $code |
* |
* @return bool true if parameter is an error |
*/ |
public static function isError($data, $code = null) |
{ |
if (!is_a($data, 'PEAR_Error')) { |
return false; |
} |
if (is_null($code)) { |
return true; |
} elseif (is_string($code)) { |
return $data->getMessage() == $code; |
} |
return $data->getCode() == $code; |
} |
/** |
* Sets how errors generated by this object should be handled. |
* Can be invoked both in objects and statically. If called |
* statically, setErrorHandling sets the default behaviour for all |
* PEAR objects. If called in an object, setErrorHandling sets |
* the default behaviour for that object. |
* |
* @param object $object |
* Object the method was called on (non-static mode) |
* |
* @param int $mode |
* One of PEAR_ERROR_RETURN, PEAR_ERROR_PRINT, |
* PEAR_ERROR_TRIGGER, PEAR_ERROR_DIE, |
* PEAR_ERROR_CALLBACK or PEAR_ERROR_EXCEPTION. |
* |
* @param mixed $options |
* When $mode is PEAR_ERROR_TRIGGER, this is the error level (one |
* of E_USER_NOTICE, E_USER_WARNING or E_USER_ERROR). |
* |
* When $mode is PEAR_ERROR_CALLBACK, this parameter is expected |
* to be the callback function or method. A callback |
* function is a string with the name of the function, a |
* callback method is an array of two elements: the element |
* at index 0 is the object, and the element at index 1 is |
* the name of the method to call in the object. |
* |
* When $mode is PEAR_ERROR_PRINT or PEAR_ERROR_DIE, this is |
* a printf format string used when printing the error |
* message. |
* |
* @access public |
* @return void |
* @see PEAR_ERROR_RETURN |
* @see PEAR_ERROR_PRINT |
* @see PEAR_ERROR_TRIGGER |
* @see PEAR_ERROR_DIE |
* @see PEAR_ERROR_CALLBACK |
* @see PEAR_ERROR_EXCEPTION |
* |
* @since PHP 4.0.5 |
*/ |
protected static function _setErrorHandling( |
$object, $mode = null, $options = null |
) { |
if ($object !== null) { |
$setmode = &$object->_default_error_mode; |
$setoptions = &$object->_default_error_options; |
} else { |
$setmode = &$GLOBALS['_PEAR_default_error_mode']; |
$setoptions = &$GLOBALS['_PEAR_default_error_options']; |
} |
switch ($mode) { |
case PEAR_ERROR_EXCEPTION: |
case PEAR_ERROR_RETURN: |
case PEAR_ERROR_PRINT: |
case PEAR_ERROR_TRIGGER: |
case PEAR_ERROR_DIE: |
case null: |
$setmode = $mode; |
$setoptions = $options; |
break; |
case PEAR_ERROR_CALLBACK: |
$setmode = $mode; |
// class/object method callback |
if (is_callable($options)) { |
$setoptions = $options; |
} else { |
trigger_error("invalid error callback", E_USER_WARNING); |
} |
break; |
default: |
trigger_error("invalid error mode", E_USER_WARNING); |
break; |
} |
} |
/** |
* This method is used to tell which errors you expect to get. |
* Expected errors are always returned with error mode |
* PEAR_ERROR_RETURN. Expected error codes are stored in a stack, |
* and this method pushes a new element onto it. The list of |
* expected errors are in effect until they are popped off the |
* stack with the popExpect() method. |
* |
* Note that this method can not be called statically |
* |
* @param mixed $code a single error code or an array of error codes to expect |
* |
* @return int the new depth of the "expected errors" stack |
* @access public |
*/ |
function expectError($code = '*') |
{ |
if (is_array($code)) { |
array_push($this->_expected_errors, $code); |
} else { |
array_push($this->_expected_errors, array($code)); |
} |
return count($this->_expected_errors); |
} |
/** |
* This method pops one element off the expected error codes |
* stack. |
* |
* @return array the list of error codes that were popped |
*/ |
function popExpect() |
{ |
return array_pop($this->_expected_errors); |
} |
/** |
* This method checks unsets an error code if available |
* |
* @param mixed error code |
* @return bool true if the error code was unset, false otherwise |
* @access private |
* @since PHP 4.3.0 |
*/ |
function _checkDelExpect($error_code) |
{ |
$deleted = false; |
foreach ($this->_expected_errors as $key => $error_array) { |
if (in_array($error_code, $error_array)) { |
unset($this->_expected_errors[$key][array_search($error_code, $error_array)]); |
$deleted = true; |
} |
// clean up empty arrays |
if (0 == count($this->_expected_errors[$key])) { |
unset($this->_expected_errors[$key]); |
} |
} |
return $deleted; |
} |
/** |
* This method deletes all occurences of the specified element from |
* the expected error codes stack. |
* |
* @param mixed $error_code error code that should be deleted |
* @return mixed list of error codes that were deleted or error |
* @access public |
* @since PHP 4.3.0 |
*/ |
function delExpect($error_code) |
{ |
$deleted = false; |
if ((is_array($error_code) && (0 != count($error_code)))) { |
// $error_code is a non-empty array here; we walk through it trying |
// to unset all values |
foreach ($error_code as $key => $error) { |
$deleted = $this->_checkDelExpect($error) ? true : false; |
} |
return $deleted ? true : PEAR::raiseError("The expected error you submitted does not exist"); // IMPROVE ME |
} elseif (!empty($error_code)) { |
// $error_code comes alone, trying to unset it |
if ($this->_checkDelExpect($error_code)) { |
return true; |
} |
return PEAR::raiseError("The expected error you submitted does not exist"); // IMPROVE ME |
} |
// $error_code is empty |
return PEAR::raiseError("The expected error you submitted is empty"); // IMPROVE ME |
} |
/** |
* This method is a wrapper that returns an instance of the |
* configured error class with this object's default error |
* handling applied. If the $mode and $options parameters are not |
* specified, the object's defaults are used. |
* |
* @param mixed $message a text error message or a PEAR error object |
* |
* @param int $code a numeric error code (it is up to your class |
* to define these if you want to use codes) |
* |
* @param int $mode One of PEAR_ERROR_RETURN, PEAR_ERROR_PRINT, |
* PEAR_ERROR_TRIGGER, PEAR_ERROR_DIE, |
* PEAR_ERROR_CALLBACK, PEAR_ERROR_EXCEPTION. |
* |
* @param mixed $options If $mode is PEAR_ERROR_TRIGGER, this parameter |
* specifies the PHP-internal error level (one of |
* E_USER_NOTICE, E_USER_WARNING or E_USER_ERROR). |
* If $mode is PEAR_ERROR_CALLBACK, this |
* parameter specifies the callback function or |
* method. In other error modes this parameter |
* is ignored. |
* |
* @param string $userinfo If you need to pass along for example debug |
* information, this parameter is meant for that. |
* |
* @param string $error_class The returned error object will be |
* instantiated from this class, if specified. |
* |
* @param bool $skipmsg If true, raiseError will only pass error codes, |
* the error message parameter will be dropped. |
* |
* @return object a PEAR error object |
* @see PEAR::setErrorHandling |
* @since PHP 4.0.5 |
*/ |
protected static function _raiseError($object, |
$message = null, |
$code = null, |
$mode = null, |
$options = null, |
$userinfo = null, |
$error_class = null, |
$skipmsg = false) |
{ |
// The error is yet a PEAR error object |
if (is_object($message)) { |
$code = $message->getCode(); |
$userinfo = $message->getUserInfo(); |
$error_class = $message->getType(); |
$message->error_message_prefix = ''; |
$message = $message->getMessage(); |
} |
if ( |
$object !== null && |
isset($object->_expected_errors) && |
count($object->_expected_errors) > 0 && |
count($exp = end($object->_expected_errors)) |
) { |
if ($exp[0] == "*" || |
(is_int(reset($exp)) && in_array($code, $exp)) || |
(is_string(reset($exp)) && in_array($message, $exp)) |
) { |
$mode = PEAR_ERROR_RETURN; |
} |
} |
// No mode given, try global ones |
if ($mode === null) { |
// Class error handler |
if ($object !== null && isset($object->_default_error_mode)) { |
$mode = $object->_default_error_mode; |
$options = $object->_default_error_options; |
// Global error handler |
} elseif (isset($GLOBALS['_PEAR_default_error_mode'])) { |
$mode = $GLOBALS['_PEAR_default_error_mode']; |
$options = $GLOBALS['_PEAR_default_error_options']; |
} |
} |
if ($error_class !== null) { |
$ec = $error_class; |
} elseif ($object !== null && isset($object->_error_class)) { |
$ec = $object->_error_class; |
} else { |
$ec = 'PEAR_Error'; |
} |
if ($skipmsg) { |
$a = new $ec($code, $mode, $options, $userinfo); |
} else { |
$a = new $ec($message, $code, $mode, $options, $userinfo); |
} |
return $a; |
} |
/** |
* Simpler form of raiseError with fewer options. In most cases |
* message, code and userinfo are enough. |
* |
* @param mixed $message a text error message or a PEAR error object |
* |
* @param int $code a numeric error code (it is up to your class |
* to define these if you want to use codes) |
* |
* @param string $userinfo If you need to pass along for example debug |
* information, this parameter is meant for that. |
* |
* @return object a PEAR error object |
* @see PEAR::raiseError |
*/ |
protected static function _throwError($object, $message = null, $code = null, $userinfo = null) |
{ |
if ($object !== null) { |
$a = &$object->raiseError($message, $code, null, null, $userinfo); |
return $a; |
} |
$a = &PEAR::raiseError($message, $code, null, null, $userinfo); |
return $a; |
} |
public static function staticPushErrorHandling($mode, $options = null) |
{ |
$stack = &$GLOBALS['_PEAR_error_handler_stack']; |
$def_mode = &$GLOBALS['_PEAR_default_error_mode']; |
$def_options = &$GLOBALS['_PEAR_default_error_options']; |
$stack[] = array($def_mode, $def_options); |
switch ($mode) { |
case PEAR_ERROR_EXCEPTION: |
case PEAR_ERROR_RETURN: |
case PEAR_ERROR_PRINT: |
case PEAR_ERROR_TRIGGER: |
case PEAR_ERROR_DIE: |
case null: |
$def_mode = $mode; |
$def_options = $options; |
break; |
case PEAR_ERROR_CALLBACK: |
$def_mode = $mode; |
// class/object method callback |
if (is_callable($options)) { |
$def_options = $options; |
} else { |
trigger_error("invalid error callback", E_USER_WARNING); |
} |
break; |
default: |
trigger_error("invalid error mode", E_USER_WARNING); |
break; |
} |
$stack[] = array($mode, $options); |
return true; |
} |
public static function staticPopErrorHandling() |
{ |
$stack = &$GLOBALS['_PEAR_error_handler_stack']; |
$setmode = &$GLOBALS['_PEAR_default_error_mode']; |
$setoptions = &$GLOBALS['_PEAR_default_error_options']; |
array_pop($stack); |
list($mode, $options) = $stack[sizeof($stack) - 1]; |
array_pop($stack); |
switch ($mode) { |
case PEAR_ERROR_EXCEPTION: |
case PEAR_ERROR_RETURN: |
case PEAR_ERROR_PRINT: |
case PEAR_ERROR_TRIGGER: |
case PEAR_ERROR_DIE: |
case null: |
$setmode = $mode; |
$setoptions = $options; |
break; |
case PEAR_ERROR_CALLBACK: |
$setmode = $mode; |
// class/object method callback |
if (is_callable($options)) { |
$setoptions = $options; |
} else { |
trigger_error("invalid error callback", E_USER_WARNING); |
} |
break; |
default: |
trigger_error("invalid error mode", E_USER_WARNING); |
break; |
} |
return true; |
} |
/** |
* Push a new error handler on top of the error handler options stack. With this |
* you can easily override the actual error handler for some code and restore |
* it later with popErrorHandling. |
* |
* @param mixed $mode (same as setErrorHandling) |
* @param mixed $options (same as setErrorHandling) |
* |
* @return bool Always true |
* |
* @see PEAR::setErrorHandling |
*/ |
protected static function _pushErrorHandling($object, $mode, $options = null) |
{ |
$stack = &$GLOBALS['_PEAR_error_handler_stack']; |
if ($object !== null) { |
$def_mode = &$object->_default_error_mode; |
$def_options = &$object->_default_error_options; |
} else { |
$def_mode = &$GLOBALS['_PEAR_default_error_mode']; |
$def_options = &$GLOBALS['_PEAR_default_error_options']; |
} |
$stack[] = array($def_mode, $def_options); |
if ($object !== null) { |
$object->setErrorHandling($mode, $options); |
} else { |
PEAR::setErrorHandling($mode, $options); |
} |
$stack[] = array($mode, $options); |
return true; |
} |
/** |
* Pop the last error handler used |
* |
* @return bool Always true |
* |
* @see PEAR::pushErrorHandling |
*/ |
protected static function _popErrorHandling($object) |
{ |
$stack = &$GLOBALS['_PEAR_error_handler_stack']; |
array_pop($stack); |
list($mode, $options) = $stack[sizeof($stack) - 1]; |
array_pop($stack); |
if ($object !== null) { |
$object->setErrorHandling($mode, $options); |
} else { |
PEAR::setErrorHandling($mode, $options); |
} |
return true; |
} |
/** |
* OS independent PHP extension load. Remember to take care |
* on the correct extension name for case sensitive OSes. |
* |
* @param string $ext The extension name |
* @return bool Success or not on the dl() call |
*/ |
public static function loadExtension($ext) |
{ |
if (extension_loaded($ext)) { |
return true; |
} |
// if either returns true dl() will produce a FATAL error, stop that |
if ( |
function_exists('dl') === false || |
ini_get('enable_dl') != 1 |
) { |
return false; |
} |
if (OS_WINDOWS) { |
$suffix = '.dll'; |
} elseif (PHP_OS == 'HP-UX') { |
$suffix = '.sl'; |
} elseif (PHP_OS == 'AIX') { |
$suffix = '.a'; |
} elseif (PHP_OS == 'OSX') { |
$suffix = '.bundle'; |
} else { |
$suffix = '.so'; |
} |
return @dl('php_'.$ext.$suffix) || @dl($ext.$suffix); |
} |
} |
function _PEAR_call_destructors() |
{ |
global $_PEAR_destructor_object_list; |
if (is_array($_PEAR_destructor_object_list) && |
sizeof($_PEAR_destructor_object_list)) |
{ |
reset($_PEAR_destructor_object_list); |
$destructLifoExists = PEAR::getStaticProperty('PEAR', 'destructlifo'); |
if ($destructLifoExists) { |
$_PEAR_destructor_object_list = array_reverse($_PEAR_destructor_object_list); |
} |
while (list($k, $objref) = each($_PEAR_destructor_object_list)) { |
$classname = get_class($objref); |
while ($classname) { |
$destructor = "_$classname"; |
if (method_exists($objref, $destructor)) { |
$objref->$destructor(); |
break; |
} else { |
$classname = get_parent_class($classname); |
} |
} |
} |
// Empty the object list to ensure that destructors are |
// not called more than once. |
$_PEAR_destructor_object_list = array(); |
} |
// Now call the shutdown functions |
if ( |
isset($GLOBALS['_PEAR_shutdown_funcs']) && |
is_array($GLOBALS['_PEAR_shutdown_funcs']) && |
!empty($GLOBALS['_PEAR_shutdown_funcs']) |
) { |
foreach ($GLOBALS['_PEAR_shutdown_funcs'] as $value) { |
call_user_func_array($value[0], $value[1]); |
} |
} |
} |
/** |
* Standard PEAR error class for PHP 4 |
* |
* This class is supserseded by {@link PEAR_Exception} in PHP 5 |
* |
* @category pear |
* @package PEAR |
* @author Stig Bakken <ssb@php.net> |
* @author Tomas V.V. Cox <cox@idecnet.com> |
* @author Gregory Beaver <cellog@php.net> |
* @copyright 1997-2006 The PHP Group |
* @license http://opensource.org/licenses/bsd-license.php New BSD License |
* @version Release: 1.10.1 |
* @link http://pear.php.net/manual/en/core.pear.pear-error.php |
* @see PEAR::raiseError(), PEAR::throwError() |
* @since Class available since PHP 4.0.2 |
*/ |
class PEAR_Error |
{ |
var $error_message_prefix = ''; |
var $mode = PEAR_ERROR_RETURN; |
var $level = E_USER_NOTICE; |
var $code = -1; |
var $message = ''; |
var $userinfo = ''; |
var $backtrace = null; |
/** |
* PEAR_Error constructor |
* |
* @param string $message message |
* |
* @param int $code (optional) error code |
* |
* @param int $mode (optional) error mode, one of: PEAR_ERROR_RETURN, |
* PEAR_ERROR_PRINT, PEAR_ERROR_DIE, PEAR_ERROR_TRIGGER, |
* PEAR_ERROR_CALLBACK or PEAR_ERROR_EXCEPTION |
* |
* @param mixed $options (optional) error level, _OR_ in the case of |
* PEAR_ERROR_CALLBACK, the callback function or object/method |
* tuple. |
* |
* @param string $userinfo (optional) additional user/debug info |
* |
* @access public |
* |
*/ |
function __construct($message = 'unknown error', $code = null, |
$mode = null, $options = null, $userinfo = null) |
{ |
if ($mode === null) { |
$mode = PEAR_ERROR_RETURN; |
} |
$this->message = $message; |
$this->code = $code; |
$this->mode = $mode; |
$this->userinfo = $userinfo; |
$skiptrace = PEAR::getStaticProperty('PEAR_Error', 'skiptrace'); |
if (!$skiptrace) { |
$this->backtrace = debug_backtrace(); |
if (isset($this->backtrace[0]) && isset($this->backtrace[0]['object'])) { |
unset($this->backtrace[0]['object']); |
} |
} |
if ($mode & PEAR_ERROR_CALLBACK) { |
$this->level = E_USER_NOTICE; |
$this->callback = $options; |
} else { |
if ($options === null) { |
$options = E_USER_NOTICE; |
} |
$this->level = $options; |
$this->callback = null; |
} |
if ($this->mode & PEAR_ERROR_PRINT) { |
if (is_null($options) || is_int($options)) { |
$format = "%s"; |
} else { |
$format = $options; |
} |
printf($format, $this->getMessage()); |
} |
if ($this->mode & PEAR_ERROR_TRIGGER) { |
trigger_error($this->getMessage(), $this->level); |
} |
if ($this->mode & PEAR_ERROR_DIE) { |
$msg = $this->getMessage(); |
if (is_null($options) || is_int($options)) { |
$format = "%s"; |
if (substr($msg, -1) != "\n") { |
$msg .= "\n"; |
} |
} else { |
$format = $options; |
} |
die(sprintf($format, $msg)); |
} |
if ($this->mode & PEAR_ERROR_CALLBACK && is_callable($this->callback)) { |
call_user_func($this->callback, $this); |
} |
if ($this->mode & PEAR_ERROR_EXCEPTION) { |
trigger_error("PEAR_ERROR_EXCEPTION is obsolete, use class PEAR_Exception for exceptions", E_USER_WARNING); |
eval('$e = new Exception($this->message, $this->code);throw($e);'); |
} |
} |
/** |
* Only here for backwards compatibility. |
* |
* Class "Cache_Error" still uses it, among others. |
* |
* @param string $message Message |
* @param int $code Error code |
* @param int $mode Error mode |
* @param mixed $options See __construct() |
* @param string $userinfo Additional user/debug info |
*/ |
public function PEAR_Error( |
$message = 'unknown error', $code = null, $mode = null, |
$options = null, $userinfo = null |
) { |
self::__construct($message, $code, $mode, $options, $userinfo); |
} |
/** |
* Get the error mode from an error object. |
* |
* @return int error mode |
* @access public |
*/ |
function getMode() |
{ |
return $this->mode; |
} |
/** |
* Get the callback function/method from an error object. |
* |
* @return mixed callback function or object/method array |
* @access public |
*/ |
function getCallback() |
{ |
return $this->callback; |
} |
/** |
* Get the error message from an error object. |
* |
* @return string full error message |
* @access public |
*/ |
function getMessage() |
{ |
return ($this->error_message_prefix . $this->message); |
} |
/** |
* Get error code from an error object |
* |
* @return int error code |
* @access public |
*/ |
function getCode() |
{ |
return $this->code; |
} |
/** |
* Get the name of this error/exception. |
* |
* @return string error/exception name (type) |
* @access public |
*/ |
function getType() |
{ |
return get_class($this); |
} |
/** |
* Get additional user-supplied information. |
* |
* @return string user-supplied information |
* @access public |
*/ |
function getUserInfo() |
{ |
return $this->userinfo; |
} |
/** |
* Get additional debug information supplied by the application. |
* |
* @return string debug information |
* @access public |
*/ |
function getDebugInfo() |
{ |
return $this->getUserInfo(); |
} |
/** |
* Get the call backtrace from where the error was generated. |
* Supported with PHP 4.3.0 or newer. |
* |
* @param int $frame (optional) what frame to fetch |
* @return array Backtrace, or NULL if not available. |
* @access public |
*/ |
function getBacktrace($frame = null) |
{ |
if (defined('PEAR_IGNORE_BACKTRACE')) { |
return null; |
} |
if ($frame === null) { |
return $this->backtrace; |
} |
return $this->backtrace[$frame]; |
} |
function addUserInfo($info) |
{ |
if (empty($this->userinfo)) { |
$this->userinfo = $info; |
} else { |
$this->userinfo .= " ** $info"; |
} |
} |
function __toString() |
{ |
return $this->getMessage(); |
} |
/** |
* Make a string representation of this object. |
* |
* @return string a string with an object summary |
* @access public |
*/ |
function toString() |
{ |
$modes = array(); |
$levels = array(E_USER_NOTICE => 'notice', |
E_USER_WARNING => 'warning', |
E_USER_ERROR => 'error'); |
if ($this->mode & PEAR_ERROR_CALLBACK) { |
if (is_array($this->callback)) { |
$callback = (is_object($this->callback[0]) ? |
strtolower(get_class($this->callback[0])) : |
$this->callback[0]) . '::' . |
$this->callback[1]; |
} else { |
$callback = $this->callback; |
} |
return sprintf('[%s: message="%s" code=%d mode=callback '. |
'callback=%s prefix="%s" info="%s"]', |
strtolower(get_class($this)), $this->message, $this->code, |
$callback, $this->error_message_prefix, |
$this->userinfo); |
} |
if ($this->mode & PEAR_ERROR_PRINT) { |
$modes[] = 'print'; |
} |
if ($this->mode & PEAR_ERROR_TRIGGER) { |
$modes[] = 'trigger'; |
} |
if ($this->mode & PEAR_ERROR_DIE) { |
$modes[] = 'die'; |
} |
if ($this->mode & PEAR_ERROR_RETURN) { |
$modes[] = 'return'; |
} |
return sprintf('[%s: message="%s" code=%d mode=%s level=%s '. |
'prefix="%s" info="%s"]', |
strtolower(get_class($this)), $this->message, $this->code, |
implode("|", $modes), $levels[$this->level], |
$this->error_message_prefix, |
$this->userinfo); |
} |
} |
/* |
* Local Variables: |
* mode: php |
* tab-width: 4 |
* c-basic-offset: 4 |
* End: |
*/ |