Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
branch: master
Fetching contributors…

Cannot retrieve contributors at this time

641 lines (581 sloc) 22.904 kb
<?php
/*
+----------------------------------------------------------------------+
| PEAR Web site version 1.0 |
+----------------------------------------------------------------------+
| Copyright (c) 2001-2005 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: Stig S. Bakken <ssb@fast.no> |
| Tomas V.V. Cox <cox@php.net> |
| Martin Jansen <mj@php.net> |
+----------------------------------------------------------------------+
$Id$
*/
/**
* Class to handle packages
*
* @class package
* @package pearweb
* @author Stig S. Bakken <ssb@fast.no>
* @author Tomas V.V. Cox <cox@php.net>
* @author Martin Jansen <mj@php.net>
*/
class package
{
/**
* Add new package
*
* @param array
* @return mixed ID of new package or PEAR error object
*/
static function add($data)
{
global $dbh, $auth_user;
// name, category
// license, summary, description
// lead
extract($data);
if (empty($license)) {
$license = 'BSD License';
}
if (!empty($category) && (int)$category == 0) {
$sql = 'SELECT id FROM categories WHERE name = ?';
$category = $dbh->getOne($sql, array($category));
}
if (empty($category)) {
return PEAR::raiseError("package::add: invalid `category' field");
}
if (empty($name)) {
return PEAR::raiseError("package::add: invalid `name' field");
}
$query = '
INSERT INTO packages
(id, name, package_type, category, license, summary, description, homepage, cvs_link)
VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?)';
$id = $dbh->nextId('packages');
$err = $dbh->query($query, array($id, $name, $type, $category, $license, $summary, $description, $homepage, $cvs_link));
if (DB::isError($err)) {
return $err;
}
$sql = 'UPDATE categories SET npackages = npackages + 1 WHERE id = ?';
$err = $dbh->query($sql, array($category));
if (DB::isError($err)) {
return $err;
}
include_once 'pear-database-maintainer.php';
$err = maintainer::add($id, $lead, 'lead');
if (isset($lead) && DB::isError($err)) {
return $err;
}
$event = $auth_user->handle . " (" . $auth_user->name . ") has added a new package " . $name;
$mailtext = $event . "\n\nApprove: http://" . PEAR_CHANNELNAME . "/admin/package-approval.php?approve=" . $id;
$mailtext .= "\nReject: http://" . PEAR_CHANNELNAME . "/admin/package-approval.php?reject=" . $id;
// {{{ Logging mechanism
require_once "Damblan/Log.php";
require_once "Damblan/Log/Mail.php";
// Syslog
$logger = new Damblan_Log;
$logger->log($event);
// Logging via email
$logger = new Damblan_Log_Mail;
$logger->setRecipients("pear-group@php.net");
$logger->setHeader("From", $auth_user->email);
$logger->setHeader("Message-Id", "<approve-request-" . $id . "@" . PEAR_CHANNELNAME . ">");
$logger->setHeader("Subject", "New package");
$logger->log($mailtext);
// }}}
return $id;
}
/**
* Get package information
*
* @static
* @param mixed Name of the package or it's ID
* @param string Single field to fetch
* @param boolean Look in all channels
* @return mixed
*/
static function info($pkg, $field = null, $show_all = false)
{
global $dbh;
$what = is_numeric($pkg) ? 'id' : 'name';
$package_type = '';
if ($show_all === false) {
$package_type = "p.package_type = '" . SITE . "' AND";
}
$pkg_sql = "SELECT
p.id AS packageid,
p.name AS name,
p.package_type AS type,
c.id AS categoryid,
c.name AS category,
p.stablerelease AS stable,
p.license AS license,
p.summary AS summary,
p.homepage AS homepage,
p.description AS description,
p.cvs_link AS cvs_link,
p.doc_link as doc_link,
p.bug_link as bug_link,
p.unmaintained AS unmaintained,
p.newpk_id AS newpk_id,
p.newpackagename as new_package,
p.newchannel as new_channel,
p.blocktrackbacks
FROM packages p, categories c
WHERE " . $package_type . " p.approved = 1 AND c.id = p.category AND p.{$what} = ?";
$rel_sql = '
SELECT
version, id, doneby, license, summary,
description, releasedate, releasenotes, state
FROM releases
WHERE package = ?
ORDER BY releasedate DESC';
$notes_sql = 'SELECT id, nby, ntime, note FROM notes WHERE pid = ?';
$deps_sql = '
SELECT type, relation, version, name, `release` as `release`, optional
FROM deps
WHERE package = ? ORDER BY optional ASC';
if ($field === null) {
$info = $dbh->getRow($pkg_sql, array($pkg), DB_FETCHMODE_ASSOC);
$info['releases'] = $dbh->getAssoc($rel_sql, false, array(@$info['packageid']), DB_FETCHMODE_ASSOC);
$rels = count($info['releases']) ? array_keys($info['releases']) : array('');
$info['stable'] = $rels[0];
$info['notes'] = $dbh->getAssoc($notes_sql, false, array(@$info['packageid']), DB_FETCHMODE_ASSOC);
$deps = $dbh->getAll($deps_sql, array(@$info['packageid']), DB_FETCHMODE_ASSOC);
foreach ($deps as $dep) {
$rel_version = null;
foreach ($info['releases'] as $version => $rel) {
if ($rel['id'] == $dep['release']) {
$rel_version = $version;
break;
}
}
if ($rel_version !== null) {
unset($dep['release']);
$info['releases'][$rel_version]['deps'][] = $dep;
}
}
return $info;
}
// get a single field
if ($field == 'releases' || $field == 'notes') {
if ($what == 'name') {
$sql = 'SELECT p.id FROM packages p WHERE ' . $package_type . ' p.approved = 1 AND p.name = ?';
$pid = $dbh->getOne($sql, array($pkg));
} else {
$pid = $pkg;
}
if ($field == 'releases') {
$info = $dbh->getAssoc($rel_sql, false, array($pid), DB_FETCHMODE_ASSOC);
} elseif ($field == 'notes') {
$info = $dbh->getAssoc($notes_sql, false, array($pid), DB_FETCHMODE_ASSOC);
}
} elseif ($field == 'category') {
$sql = "SELECT c.name FROM categories c, packages p ".
"WHERE c.id = p.category AND " . $package_type . " p.approved = 1 AND p.{$what} = ?";
$info = $dbh->getOne($sql, array($pkg));
} elseif ($field == 'description') {
$sql = "SELECT description FROM packages p WHERE " . $package_type . " p.approved = 1 AND p.{$what} = ?";
$info = $dbh->query($sql, array($pkg));
} elseif ($field == 'authors') {
$sql = "SELECT u.handle, u.name, u.email, u.showemail, m.active, m.role
FROM maintains m, users u, packages p
WHERE " . $package_type ." p.approved = 1 AND m.package = p.id
AND p.$what = ?
AND m.handle = u.handle";
$info = $dbh->getAll($sql, array($pkg), DB_FETCHMODE_ASSOC);
} else {
if ($field == 'categoryid') {
$dbfield = 'category';
} elseif ($field == 'packageid') {
$dbfield = 'id';
} else {
$dbfield = $field;
}
$sql = "SELECT $dbfield FROM packages p WHERE " . $package_type ." p.approved = 1 AND p.{$what} = ?";
$info = $dbh->getOne($sql, array($pkg));
}
return $info;
}
/**
* Lists the IDs and names of all approved PEAR packages
*
* Returns an associative array where the key of each element is
* a package ID, while the value is the name of the corresponding
* package.
*
* @static
* @return array
*/
static function listAllNames()
{
global $dbh;
$sql = 'SELECT id, name FROM packages WHERE package_type = ? AND approved = 1 ORDER BY name';
return $dbh->getAssoc($sql, false, array(SITE));
}
/**
* List all packages
*
* @static
* @param boolean Only list released packages?
* @param boolean If listing released packages only, only list stable releases?
* @param boolean List also PECL packages
* @return array
*/
static function listAll($released_only = true, $stable_only = true)
{
global $dbh;
$sql = '
SELECT
p.name,
p.id AS packageid,
c.id AS categoryid,
c.name AS category,
p.license AS license,
p.summary AS summary,
p.description AS description,
m.handle AS lead
FROM packages p, categories c, maintains m
WHERE
p.package_type = ? AND
p.approved = 1 AND
c.id = p.category AND
p.id = m.package AND
m.role = ?
ORDER BY p.name';
$packageinfo = $dbh->getAssoc($sql, false, array(SITE, 'lead'), DB_FETCHMODE_ASSOC);
$allreleases = $dbh->getAssoc(
"SELECT p.name, r.id AS rid, r.version AS stable, r.state AS state ".
"FROM packages p, releases r ".
"WHERE p.package_type = ? AND " .
' p.id = r.package ' .
"ORDER BY r.releasedate ASC ", false, array(SITE), DB_FETCHMODE_ASSOC);
if ($released_only) {
$stablereleases = $dbh->getAssoc(
"SELECT p.name, r.id AS rid, r.version AS stable, r.state AS state ".
"FROM packages p, releases r ".
"WHERE p.package_type = ? AND " .
"p.id = r.package ".
"AND r.state = 'stable' " .
"ORDER BY r.releasedate ASC ", false, array(SITE), DB_FETCHMODE_ASSOC);
} else {
$stablereleases = $allreleases;
}
$sql = 'SELECT package, `release` , type, relation, `version`, name FROM deps';
$deps = $dbh->getAll($sql, null, DB_FETCHMODE_ASSOC);
foreach ($packageinfo as $pkg => $info) {
$packageinfo[$pkg]['stable'] = false;
}
foreach ($stablereleases as $pkg => $stable) {
$packageinfo[$pkg]['stable'] = $stable['stable'];
$packageinfo[$pkg]['unstable'] = false;
$packageinfo[$pkg]['state'] = $stable['state'];
}
if (!$stable_only) {
foreach ($allreleases as $pkg => $stable) {
if ($stable['state'] == 'stable') {
if (version_compare($packageinfo[$pkg]['stable'], $stable['stable'], '<')) {
// only change it if the version number is newer
$packageinfo[$pkg]['stable'] = $stable['stable'];
}
} else {
if (!isset($packageinfo[$pkg]['unstable']) ||
version_compare($packageinfo[$pkg]['unstable'], $stable['stable'], '<')) {
// only change it if the version number is newer
$packageinfo[$pkg]['unstable'] = $stable['stable'];
}
}
$packageinfo[$pkg]['state'] = $stable['state'];
if (isset($packageinfo[$pkg]['unstable']) && !$packageinfo[$pkg]['stable']) {
$packageinfo[$pkg]['stable'] = $packageinfo[$pkg]['unstable'];
}
}
}
$var = !$stable_only ? 'allreleases' : 'stablereleases';
foreach (array_keys($packageinfo) as $pkg) {
$_deps = array();
foreach ($deps as $dep) {
if ($dep['package'] == $packageinfo[$pkg]['packageid']
&& isset($$var[$pkg])
&& $dep['release'] == $$var[$pkg]['rid'])
{
unset($dep['rid']);
unset($dep['release']);
if ($dep['type'] == 'pkg' && isset($packageinfo[$dep['name']])) {
$dep['package'] = $packageinfo[$dep['name']]['packageid'];
} else {
$dep['package'] = 0;
}
$_deps[] = $dep;
};
};
$packageinfo[$pkg]['deps'] = $_deps;
};
if ($released_only) {
if (!$stable_only) {
foreach ($packageinfo as $pkg => $info) {
if (!isset($allreleases[$pkg]) && !isset($stablereleases[$pkg])) {
unset($packageinfo[$pkg]);
}
}
} else {
foreach ($packageinfo as $pkg => $info) {
if (!isset($stablereleases[$pkg])) {
unset($packageinfo[$pkg]);
}
}
}
}
return $packageinfo;
}
/**
* Get list of packages and their releases
*
* @access public
* @return array
* @static
*/
static function listAllwithReleases()
{
global $dbh;
$query = '
SELECT
p.id AS pid, p.name, r.id AS rid, r.version, r.state
FROM packages p, releases r
WHERE p.package_type = ? AND p.approved = 1 AND p.id = r.package
ORDER BY p.name, r.version DESC';
$sth = $dbh->getAll($query, array(SITE), DB_FETCHMODE_ASSOC);
if (DB::isError($sth)) {
return $sth;
}
$packages = array();
foreach ($sth as $row) {
$packages[$row['pid']]['name'] = $row['name'];
$packages[$row['pid']]['releases'][] = array(
'id' => $row['rid'],
'version' => $row['version'],
'state' => $row['state']
);
}
return $packages;
}
/**
* Updates fields of an existant package
*
* @param int $pkgid The package ID to update
* @param array $data Assoc in the form 'field' => 'value'.
* @return mixed True or PEAR_Error
*/
static function updateInfo($pkgid, $data)
{
global $dbh, $auth_user;
$package_id = package::info($pkgid, 'id');
if (PEAR::isError($package_id) || empty($package_id)) {
return PEAR::raiseError('Package not registered or not approved. Please register it first with "New Package" or wait until it gets approved.');
}
if ($auth_user->isAdmin() === false && $auth_user->isQA() === false) {
include_once 'pear-database-user.php';
$role = user::maintains($auth_user->handle, $package_id);
if ($role != 'lead' && $role != 'developer') {
return PEAR::raiseError('package::updateInfo: insufficient privileges');
}
}
// XXX (cox) what about 'name'?
$allowed = array('license', 'summary', 'description', 'category');
$fields = $prep = array();
foreach ($allowed as $a) {
if (isset($data[$a])) {
$fields[] = "$a = ?";
$prep[] = $data[$a];
}
}
if (!count($fields)) {
return;
}
$sql = 'UPDATE packages SET ' . implode(', ', $fields) . " WHERE id = $package_id";
$row = package::info($pkgid, 'name');
include_once 'pear-rest.php';
$pear_rest = new pearweb_Channel_REST_Generator(PEAR_REST_PATH, $dbh);
$pear_rest->saveAllPackagesREST();
$pear_rest->savePackageREST($row);
$pear_rest->savePackagesCategoryREST(package::info($pkgid, 'category'));
return $dbh->query($sql, $prep);
}
/**
* Get packages that depend on the given package
*
* @param string Name of the package
* @return array List of package that depend on $package
*/
static function getDependants($package)
{
global $dbh;
$query = '
SELECT
p.name AS p_name,
MAX(r.version) AS max_dep,
MAX(rm.version) as max_pkg
FROM packages p, deps AS d
LEFT JOIN releases AS r ON r.id = d.release
LEFT JOIN releases AS rm ON rm.package = d.package
WHERE d.package = p.id AND d.type = ? AND d.name = ?
GROUP BY d.package
ORDER BY p.name';
return $dbh->getAll($query, array('pkg', $package), DB_FETCHMODE_ASSOC);
}
/**
* Get dependencies for the given package
*
* @param string Name of the package
* @return array List of packages that $package requires
*/
static function getDependencies($package, $release = null)
{
global $dbh;
if (empty($release)) {
// Get the most recent version with a given state
$release = $dbh->getOne("SELECT r.id FROM releases r JOIN packages p ON p.id = r.package ".
"WHERE name = ?".
"ORDER BY releasedate DESC",
array($package)); }
$query = '
SELECT d.*
FROM packages p
JOIN deps d ON p.id = d.package
WHERE p.name = ? AND d.release = ?';
return $dbh->getAll($query, array($package, $release), DB_FETCHMODE_ASSOC);
}
/**
* Get list of recent releases for the given package
*
* @param int Number of releases to return
* @param string Name of the package
* @return array
*/
static function getRecent($n, $package)
{
global $dbh;
$recent = array();
$query = '
SELECT
p.id AS id,
p.name AS name,
p.summary AS summary,
r.version AS version,
r.releasedate AS releasedate,
r.releasenotes AS releasenotes,
r.doneby AS doneby,
r.state AS state
FROM packages p, releases r
WHERE
p.package_type = ?
AND p.approved = 1
AND p.id = r.package
AND p.name = ?
ORDER BY r.releasedate DESC';
$sth = $dbh->limitQuery($query, 0, $n, array(SITE, $package));
while ($sth->fetchInto($row, DB_FETCHMODE_ASSOC)) {
$recent[] = $row;
}
return $recent;
}
/**
* Determines if the given package is valid
*
* @access public
* @param string Name of the package
* @return boolean
*/
static function isValid($package)
{
global $dbh;
$query = 'SELECT id FROM packages WHERE package_type = ? AND approved = 1 AND name = ?';
$sth = $dbh->query($query, array(SITE, $package));
return ($sth->numRows() > 0);
}
/**
* Enable or disable trackbacks for a package
*
* @access public
* @param int ID of the package
* @return void
*/
static function allowTrackbacks($name, $allow)
{
global $dbh;
$query = 'UPDATE packages
SET blocktrackbacks = ' . ((int) !$allow) . '
WHERE name = ' . $dbh->quoteSmart($name);
$res = $dbh->query($query);
}
/**
* Generate link for package
*
* Returns HTML-code that creates a link to /package/<package>
*
* @access public
* @return string
*/
function makeLink($name)
{
if ($name == "PEAR Installer") {
return make_link('/package/PEAR', $name);
}
return make_link('/package/' . $name . '/', $name);
}
/**
* Get URL to license text
*
* @todo Add more licenses here
* @param string Name of the license
* @param boolean Direct link or htmled one
* @return string Link to license URL
*/
static function get_license_link($license = '', $plain = false)
{
switch ($license) {
case 'PHP License 3.01' :
case 'PHP License' :
case 'PHP 3.01' :
$link = 'http://www.php.net/license/3_01.txt';
break;
case 'PHP 2.02' :
$link = 'http://www.php.net/license/2_02.txt';
break;
case 'GPL' :
case 'GNU General Public License' :
$link = 'http://www.gnu.org/licenses/gpl.html';
break;
case 'LGPL' :
case 'GNU Lesser General Public License' :
$link = 'http://www.gnu.org/licenses/lgpl.html';
break;
case 'BSD' :
case 'BSD License' :
case 'New BSD License' :
case 'New BSD' :
$link = 'http://www.opensource.org/licenses/bsd-license.php';
break;
case 'MIT' :
case 'MIT License' :
$link = 'http://www.opensource.org/licenses/mit-license.php';
break;
default :
$link = '';
break;
}
if ($plain && $link != '') {
return $link;
}
return ($link != '' ? '<a class="license" href="' . $link . '" rel="license">' . $license . "</a>\n" : $license);
}
}
Jump to Line
Something went wrong with that request. Please try again.