PEAR_PackageFileManager : The Definitive Guide

PEAR_PackageFileManager Manual
Next

PEAR_PackageFileManager Manual

First Edition

Edited by

Laurent Laville

Copyright © 2006 Gregory Beaver, Laurent Laville

This work is licensed under the Creative Commons Attribution License. To view a copy of this license, visit http://creativecommons.org/licenses/by/2.0/.

Revision History
Revision 1.6.0 November 17, 2006
The first edition of this Guide is now completed. It cover version 1.6.0 (stable) of PEAR_PackageFileManager.

Table of Contents

Preface
Organization of This Book
Pre-requisites
I. Introduction
1. About PEAR_PackageFileManager
2. FAQ - Frequently Asked Questions
II. Getting Started
3. package.xml 2.0
III. Tutorial
4. Introduction
5. Introducing PEAR_PackageFileManager
6. Setting options
7. Creating a new package
8. Maintaining users list
9. Using tasks to customize file installation
10. Maintaining dependencies list
11. Using custom file roles
12. Using custom file tasks
13. Handling Changelog
IV. Reference Guide
<channel> - What is a channel?
<uri> - When should I use <uri>?
<lead>, <developer>, <contributor>, and <helper> - Developer documentation for a release
<version> - versioning in package.xml 2.0
<stability> - specifying release and API stability
<license> - specifying software license and optional reference to license text
<notes> - about release changes
<contents> - specifying the contents of a release
<dir> - documenting a directory in the <contents> tag
<file> - documenting a file in the <contents> tag
tasks for <file>s - specialized file installation and manipulation
<compatible> - Alleviating strict versioning with <compatible>
<dependencies> - Dependency Specification in package.xml 2.0
<usesrole> - documenting custom file roles used in <contents>
<usestask> - documenting custom tasks used in <contents>
<phprelease>, <extbinrelease>, <extsrcrelease>, <bundle> - specifying the content type of a release

List of Tables

6.1. Reference of generation options for package.xml 2.0
7.1. First package/release with package.xml 1.0 and package.xml 2.0
10.1. setting PHP versions dependencies
10.2. setting PEAR installer dependencies
10.3. package.xml 1.0 dependencies
10.4. package.xml 2.0 dependencies
10.5. php extension dependencies version 1.0
10.6. php extension dependencies version 2.0
10.7. OS installation condition
10.8. Arch installation condition
11.1. extension role mapping reference
11.2. install custom file role handler
12.1. install custom file task handler
14. Converting package.xml 1.0 package dependencies to package.xml 2.0

List of Examples

13.1. create a RSS newsfeed
PEAR_PackageFileManager : The Definitive Guide v 1.6.0 : November 17, 2006
Next
Preface


Preface
Prev Next

Preface

Table of Contents

Organization of This Book
Pre-requisites

Organization of This Book

This book is divided into three main parts, they are:

  • Introduction

    This section contains a gentle introduction to what PEAR_PackageFileManager is and has to offer. Included is general information about installing and using this PEAR package, and answers to frequently asked questions.

  • Getting Started

    This section is intended to provide a quick introduction to get started understanding, installing, and running the bundle examples.

  • Reference Guide

    This section describes every API in the PEAR_PackageFileManager package. The description of each function may contain some or all of the following parts:

    • Synopsis

      Shows the structure and prototype of the function.

    • Description

      Gives a description about what the function does.

    • Parameter

      Describes each parameter for the function along with the paramater types and names. Both required and optional parameters are listed.

    • Returns

      Describes the returned value, if the function doesn't fail.

    • Throws

      Describes the returned PEAR_Error objects, if the function fails.

    • Note

      Additional notes and information about the function. An example note would be if the function can be called statically.

    • See

      Links to other related functions or manual entries.

    • Example

      An example use of the function or class.

PEAR_PackageFileManager : The Definitive Guide v 1.6.0 : November 17, 2006
Prev |  | Next
PEAR_PackageFileManager Manual | Home | Pre-requisites


Pre-requisites
Prev Preface Next

Pre-requisites

It is assumed that you have installed both PHP and PEAR.

It is also assumed that your PHP scripts are correctly interpreted by your web server. In most case it will be probably Apache, but you may also have IIS. PEAR_PackageFileManager runs both on Windows and *nix.

PEAR_PackageFileManager : The Definitive Guide v 1.6.0 : November 17, 2006
Prev | Up | Next
Preface | Home | Part I. Introduction


Part I. Introduction
Prev Next

Part I. Introduction

Table of Contents

1. About PEAR_PackageFileManager
What is PEAR_PackageFileManager ?
Intended Audience
Why use PEAR_PackageFileManager 1.6.0 or better ?
2. FAQ - Frequently Asked Questions
PEAR_PackageFileManager : The Definitive Guide v 1.6.0 : November 17, 2006
Prev |  | Next
Pre-requisites | Home | Chapter 1. About PEAR_PackageFileManager


Chapter 1. About PEAR_PackageFileManager
Prev Part I. Introduction Next

Chapter 1. About PEAR_PackageFileManager

Table of Contents

What is PEAR_PackageFileManager ?
Intended Audience
Why use PEAR_PackageFileManager 1.6.0 or better ?
Features
System Requirements

What is PEAR_PackageFileManager ?

Basically PEAR_PackageFileManager takes an existing package.xml file and updates it with a new filelist and changelog.

PEAR_PackageFileManager : The Definitive Guide v 1.6.0 : November 17, 2006
Prev | Up | Next
Part I. Introduction | Home | Intended Audience


Intended Audience
Prev Chapter 1. About PEAR_PackageFileManager Next

Intended Audience

This document is written as a guide to and reference for the PEAR_PackageFileManager package, for both beginner and expert users.

PEAR_PackageFileManager : The Definitive Guide v 1.6.0 : November 17, 2006
Prev | Up | Next
Chapter 1. About PEAR_PackageFileManager | Home | Why use PEAR_PackageFileManager 1.6.0 or better ?


Why use PEAR_PackageFileManager 1.6.0 or better ?
Prev Chapter 1. About PEAR_PackageFileManager Next

Why use PEAR_PackageFileManager 1.6.0 or better ?

Features
System Requirements

At the beggining, maintainers should wrote their package xml file by hand. PEAR_PackageFileManager (PFM) revolutionizes the maintenance of PEAR packages. With a few parameters, the entire package.xml is automatically updated with a listing of all files in a package.

Since first alpha release of PFM 1.6.0, this package can manage the new package.xml 2.0 format introduce with PEAR 1.4.0

The most significant change in PEAR 1.4 was addition of channels, a simple and effective method of distributing application development. PFM 1.6.0 help maintainers to build and manage the new package.xml 2.0 format that it is now simpler to distribute any PHP code project using the PEAR installer than it ever was.

Features

  • manages the new package.xml 2.0 format introduce with PEAR 1.4.0
  • can detect PHP and extension dependencies using PHP_CompatInfo.
  • reads in an existing package.xml file, and only changes the release/changelog.
  • a plugin system for retrieving files in a directory.
  • incredibly flexible options for assigning install roles to files/directories
  • ability to ignore any file based on a * ? wildcard-enabled string(s).
  • ability to include only files that match a * ? wildcard-enabled string(s).
  • ability to manage dependencies.
  • ability to manage maintainers.
  • can output the package.xml in any directory, and read in the package.xml file from any directory.
  • can specify a different name for the package.xml file.

System Requirements

Mandatory resources:

  • PHP 4.2.0 or newer.
  • PEAR 1.4.3 or newer.

PEAR_PackageFileManager : The Definitive Guide v 1.6.0 : November 17, 2006
Prev | Up | Next
Intended Audience | Home | Chapter 2. FAQ - Frequently Asked Questions


Chapter 2. FAQ - Frequently Asked Questions
Prev Part I. Introduction Next

Chapter 2. FAQ - Frequently Asked Questions

2.1. General questions
2.1.1. What does it cost ?
2.1.2. Do you offer support ?
2.1.3. I found a bug, what shall i do ?
2.1.4. What is PEAR ?
2.2. How to do
2.2.1. I have a ... How to ?

2.1. General questions

2.1.1. What does it cost ?
2.1.2. Do you offer support ?
2.1.3. I found a bug, what shall i do ?
2.1.4. What is PEAR ?
2.1.1.

What does it cost ?

You can download and use it for free. But don't delete the copyright notice. You can read terms of the license

2.1.2.

Do you offer support ?

YES if there is no answer in this Guide and if you are ready to share some informations such as : your configuration (platform Win *nix mac, PHP version, PEAR packages installed) and perharps your script.

2.1.3.

I found a bug, what shall i do ?

You can report it with the bug tracker at PEAR.

2.1.4.

What is PEAR ?

PEAR (an acronym for PHP Extension and Application Repository) is a framework and distribution system for reusable PHP components.

Don't forget to read also the PEAR Manual and PEAR FAQ.

2.2. How to do

2.2.1. I have a ... How to ?
2.2.1.

I have a ... How to ?

<?php
?>

PEAR_PackageFileManager : The Definitive Guide v 1.6.0 : November 17, 2006
Prev | Up | Next
Why use PEAR_PackageFileManager 1.6.0 or better ? | Home | Part II. Getting Started


Part II. Getting Started
Prev Next

Part II. Getting Started

Table of Contents

3. package.xml 2.0
Introduction
Allowed elements
PEAR_PackageFileManager : The Definitive Guide v 1.6.0 : November 17, 2006
Prev |  | Next
Chapter 2. FAQ - Frequently Asked Questions | Home | Chapter 3. The package definition file package.xml, version 2.0


Chapter 3. The package definition file package.xml, version 2.0
Prev Part II. Getting Started Next

Chapter 3. The package definition file package.xml, version 2.0

Table of Contents

Introduction
Allowed elements

A quick guide to version 2.0 of the package definition file package.xml

The package definition file package.xml is, as the name already implies, a well-formed XML file that contains all information about a PEAR package. Version 2.0 contains several important enhancements over version 1.0, including

  • Channel support

  • Binary PECL packages support (not fully implemented in PEAR 1.4.0)

  • More specific dependency resolution

This chapter will describe the allowed elements of the package definition file.

The PEAR_PackageFileManager package simplifies the creation of package.xml. You can install PEAR_PackageFileManager via the usual command.

$ pear install PEAR_PackageFileManager

[Note] Note
Since version 1.6.0a1, PEAR_PackageFileManager supports package.xml 2.0 with the PEAR_PackageFileManager2 class.

PEAR_PackageFileManager : The Definitive Guide v 1.6.0 : November 17, 2006
Prev | Up | Next
Part II. Getting Started | Home | Allowed elements


Allowed elements
Prev Chapter 3. The package definition file package.xml, version 2.0 Next

Allowed elements

As any other xml file, the package definition file package.xml begin with a standard xml prolog. The toplevel element in package.xml is the element <package version="2.0">.

<?xml version="1.0"?>
<package 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">

The allowed sub elements are (bold entry is mandatory, while normal entry is optional):

<name>

The name of the package

<extends>

Each package with a major version x in x.y.z greater than 1 must superceed a previous package identify by the extends tag.

<channel> | <uri>

Either use the channel tag that should contain the full channel name, not any alias, or use the uri tag that contain a Uniform Resource Identifier (URI) of your package.

<summary>

Short summary of the package's description

[Warning] Warning
A one-line string longer than 25 characters will be truncated after 25th char. and ... will be appended to the string (to indicate a split).

<description>

Any static long description. No size limitation.

[Tip] Tip
This text should not change very much between releases, use instead the "notes" tag for release notes to identify what have changed since the previous version.

<lead>, <developer>, <contributor> and <helper>

These tags documente who develops a package, and who is still active.

<date>

The date when the current release has been rolled.

<time>

The time when the current release has been rolled. Default is current time if not specified.

<version>

Version tag documenting release version and API version.

<stability>

Stability tag documenting release stability and API stability.

<license>

License tag specifying software license and optional reference to license text.

<notes>

Notes tag specifying release changes introduced since previous version.

<contents>

Contents tag specifying the contents of a release.

<compatible>

compatible tag allow to work with recommended dependency and installed versions.

<dependencies>

dependencies tag specifying the dependencies of a release.

<usesrole>

Usesrole tag documenting custom file roles used in <contents>

<usestask>

Usestask tag documenting custom tasks used in <contents>

<phprelease> | <extsrcrelease> | <extbinrelease> | <bundle>

These tags specifying the content type of a release.

<changelog>

Changelog-like information about the package.

PEAR_PackageFileManager : The Definitive Guide v 1.6.0 : November 17, 2006
Prev | Up | Next
Chapter 3. The package definition file package.xml, version 2.0 | Home | Part III. Tutorial


Part III. Tutorial
Prev Next

Part III. Tutorial

Table of Contents

4. Introduction
Using this tutorial
5. Introducing PEAR_PackageFileManager
The benefits of automated building
API short tour
6. Setting options
List of options
7. Creating a new package
From scratch
Add a new release
Resume
8. Maintaining users list
Add a new user on maintainers list
Remove a user on maintainers list
Change full name, email address, role or status of a maintainer
Getting list of maintainer
9. Using tasks to customize file installation
Search and Replace file contents
Converting file line endings
Advanced installation with post install script
10. Maintaining dependencies list
Add a new dependency to PHP and PEAR installer version
Add a new dependency to another package
Add a new dependency to a php extension
Operating System dependency
Architecture dependency
11. Using custom file roles
Add a new extension role mapping
Improve warning message requiring custom file role handler
12. Using custom file tasks
Add a new custom file task
Improve warning message requiring custom file task handler
13. Handling Changelog
Reading full changelog history
Removing full changelog
PEAR_PackageFileManager : The Definitive Guide v 1.6.0 : November 17, 2006
Prev |  | Next
Allowed elements | Home | Chapter 4. Welcome to the PEAR_PackageFileManager tutorial


Chapter 4. Welcome to the PEAR_PackageFileManager tutorial
Prev Part III. Tutorial Next

Chapter 4. Welcome to the PEAR_PackageFileManager tutorial

Table of Contents

Using this tutorial

Welcome to the PEAR_PackageFileManager tutorial, a self-paced guide that teaches you the basics of building your package with PEAR_PackageFileManager. This tutorial will familiarize you with the process of creating and updating package xml version 2.0

Using this tutorial

The tutorial is divided into 9 short lessons. In each lesson, you will learn how to create a new release, manage developers, files list, dependencies, perform complex installation tasks, and much more.

After you complete the tutorial, you can apply the skills you learn to your own packager copy.

Lesson 1, introducing PEAR_PackageFileManager compares automated and manual building methods.

Lesson 2, setting options defines types and values, and tells when and why you should use an option rather than an other.

Lesson 3, creating a new package teaches you how to build your first package from scratch.

Lesson 4, maintaining users list teaches you how to update the maintainers list. Add a new one, make one inactive, or definitively remove him.

Lesson 5, using tasks to customize file installation teaches you how to perform a custom installation with 3 basic tasks (replace, windowseol, unixeol) and 1 complex (postinstallscript).

Lesson 6, maintaining dependencies list teaches you how to update the dependencies list. Add a new one, remove one or just change its content.

Lesson 7, using custom file roles teaches you how to customize installation locations for each file rather than use standard categories (php, data, doc, test, script, src, ext).

Lesson 8, using custom file tasks teaches you how to customize installation with a third party task file, rather than using standard basic tasks: replace, eol, postinstall script.

Lesson 9, handling changelog teaches you how to read, remove, modify a changelog entry.

PEAR_PackageFileManager : The Definitive Guide v 1.6.0 : November 17, 2006
Prev | Up | Next
Part III. Tutorial | Home | Chapter 5. Introducing PEAR_PackageFileManager


Chapter 5. Introducing PEAR_PackageFileManager
Prev Part III. Tutorial Next

Chapter 5. Introducing PEAR_PackageFileManager

Table of Contents

The benefits of automated building
API short tour
General information about a package

This lesson :

  • describes the benefits of automated building

  • takes you on a short tour of the methods list

The benefits of automated building

If you have ever created package xml manually, you are aware of its drawbacks. Manual building is time-consuming and tedious, giving sometime typo errors or xml grammar validation errors.

Automated building package.xml with PEAR_PackageFileManager addresses these problems by dramatically speeding up the building/validating process. You can create package scripts that check all aspects of your application distribution.

PEAR_PackageFileManager : The Definitive Guide v 1.6.0 : November 17, 2006
Prev | Up | Next
Chapter 4. Welcome to the PEAR_PackageFileManager tutorial | Home | API short tour


API short tour
Prev Chapter 5. Introducing PEAR_PackageFileManager Next

API short tour

General information about a package

General information about a package

Describing a package xml version 1.0 or 2.0 requires four mandatory properties (xml tag): name, channel (or uri), summary, description, and one optional property: extends.

Methods (setters) that should be called only once (at first package xml build-time), are listed below:

name

PEAR_PackageFile_v2::getPackage(), PEAR_PackageFile_v2_rw::setPackage()

extends

PEAR_PackageFile_v2::getExtends(), PEAR_PackageFile_v2_rw::setExtends()

channel

PEAR_PackageFile_v2::getChannel(), PEAR_PackageFile_v2_rw::setChannel()

uri

PEAR_PackageFile_v2::getUri(), PEAR_PackageFile_v2_rw::setUri()

summary

PEAR_PackageFile_v2::getSummary(), PEAR_PackageFile_v2_rw::setSummary()

description

PEAR_PackageFile_v2::getDescription(), PEAR_PackageFile_v2_rw::setDescription()

PEAR_PackageFileManager : The Definitive Guide v 1.6.0 : November 17, 2006
Prev | Up | Next
Chapter 5. Introducing PEAR_PackageFileManager | Home | Chapter 6. Setting options


Chapter 6. Setting options
Prev Part III. Tutorial Next

Chapter 6. Setting options

Table of Contents

List of options

This lesson :

  • describes exhaustive list of options to configure PEAR_PackageFileManager

List of options

Default behavior may be changed in many way. First one is to define options with the setOptions() method. Here are the list of all available options, with their default values:

Table 6.1. Reference of generation options for package.xml 2.0

Name | Type | Default
packagefile | string | package.xml
filelistgenerator | string | file
license | string | PHP License
baseinstalldir | string | null
changelogoldtonew | boolean | true
roles array

array(
   'h' => 'src',
   'c' => 'src',
   'm4' => 'src',
   'w32' => 'src',
   'dll' => 'ext',
   'php' => 'php',
   'html' => 'doc',
   '*' => 'data',
)
dir_roles array

array(
   'docs' => 'doc',
   'examples' => 'doc',
   'tests' => 'test',
)
exceptions | array | array()
installexceptions | array | array()
ignore | array | array()
include | array | array()
notes | string | null
changelognotes | mixed (string | boolean) | false
outputdirectory | mixed (string | boolean) | false
pathtopackagefile | mixed (string | boolean) | false
lang | string | en
replacements | array | array()
globalreplacements | array | array()
globalreplaceexceptions | array | array()
simpleoutput | boolean | false
addhiddenfiles | boolean | false
cleardependencies | boolean | false
clearcontents | boolean | true
clearchangelog | boolean | false

PEAR_PackageFileManager : The Definitive Guide v 1.6.0 : November 17, 2006
Prev | Up | Next
API short tour | Home | Chapter 7. Creating a new package


Chapter 7. Creating a new package
Prev Part III. Tutorial Next

Chapter 7. Creating a new package

Table of Contents

From scratch
Add a new release
Resume

This lesson :

  • teachs you how to build your first package from scratch.

  • teachs you to distinct usage of setOptions() and importOptions() methods.

From scratch

While in reality, we could find the same generator script to build a package.xml on first time, and update it later, both classes PEAR_PackageFileManager and PEAR_PackageFileManager2 provides two distinct ways of generation, using : setOptions() and importOptions(). We will focus only, in this chapter, on the first method. Later we will see usage of second method when we will talk how to update an existing package.

Lets see step by step how to define a new package with the two versions of PEAR_PackageFileManager.

To define a new package we will need to know some informations, such as : its name, a little summary, and a longer description. But we need also to know where package sources resides, and where it should be installed (on PEAR infrastructure).

With package.xml version 1.0, almost all properties were set with the setOptions() method. With package.xml version 2.0, there are new functions to get/set property individually. Among these ones, there is :

name

getPackage(), setPackage()

extends

getExtends(), setExtends()

channel

getChannel(), setChannel()

uri

getUri(), setUri()

summary

getSummary(), setSummary()

description

getDescription(), setDescription()

To produce a package.xml version 1.0, here is the basic sheme

  1. <?php
  2. require_once 'PEAR/PackageFileManager.php';
  3.
  4. PEAR::setErrorHandling(PEAR_ERROR_DIE);
  5.
  6. $p1 = new PEAR_PackageFileManager();
  7.
  8. $name        = 'MDB2';
  9. $summary     = 'database abstraction layer';
  10. $description = 'PEAR MDB2 is a merge of the PEAR DB and ...';
  11.
  12. $p1->setOptions(array(
  13.     'package'           => $name,
  14.     'summary'           => $summary,
  15.     'description'       => $description,
  16.     'packagedirectory'  => 'C:/php/pear/MDB2',
  17.     'baseinstalldir'    => '/'
  18. ));
  19. //...
  20.
  21. if (isset($_GET['make'])) {
  22.     $p1->writePackageFile();
  23. } else {
  24.     $p1->debugPackageFile();
  25. }
  26. ?>

To produce a package.xml version 2.0

  1. <?php
  2. require_once 'PEAR/PackageFileManager2.php';
  3.
  4. PEAR::setErrorHandling(PEAR_ERROR_DIE);
  5.
  6. $p2 = new PEAR_PackageFileManager2();
  7.
  8. $name        = 'MDB2';
  9. $summary     = 'database abstraction layer';
  10. $description = 'PEAR MDB2 is a merge of the PEAR DB and ...';
  11. $extend      = 'MDB';
  12. $channel     = 'pear.php.net';
  13.
  14. $p2->setOptions(array(
  15.     'packagedirectory'  => 'C:/php/pear/MDB2',
  16.     'baseinstalldir'    => '/'
  17. ));
  18.
  19. $p2->setPackage($name);
  20.
  21. // only necessary when a new major version supperceed to a package
  22. // examples are : MDB -> MDB2, HTML_Progress -> HTML_Progress2, ...
  23. $p2->setExtends($extend);
  24.
  25. $p2->setChannel($channel);
  26. $p2->setSummary($summary);
  27. $p2->setDescription($description);
  28.
  29. //...
  30.
  31. if (isset($_GET['make']) || (isset($_SERVER['argv']) && @$_SERVER['argv'][1] == 'make')) {
  32.     $p2->writePackageFile();
  33. } else {
  34.     $p2->debugPackageFile();
  35. }
  36. ?>

PEAR_PackageFileManager : The Definitive Guide v 1.6.0 : November 17, 2006
Prev | Up | Next
Chapter 6. Setting options | Home | Add a new release


Add a new release
Prev Chapter 7. Creating a new package Next

Add a new release

A new release, depends in part of package type, but as common properties, you should at least read/set :

  • date (optional, current date will be used)

    getDate(), setDate()

  • time (optional, current time will be used; Only available for package.xml 2.0)

    getTime(), setTime()

  • version

    getVersion(),
setReleaseVersion(),
setAPIVersion()

  • stability

    getState(),
getStability(),
setReleaseStability(),
setAPIStability()

  • license

    getLicense(), setLicense()

  • notes

    getNotes(), setNotes()

To produce a package.xml version 1.0

  1. <?php
  2. require_once 'PEAR/PackageFileManager.php';
  3.
  4. PEAR::setErrorHandling(PEAR_ERROR_DIE);
  5.
  6. $p1 = new PEAR_PackageFileManager();
  7.
  8. $name        = 'MDB2';
  9. $summary     = 'database abstraction layer';
  10. $description = 'PEAR MDB2 is a merge of the PEAR DB and ...';
  11. $release_state   = 'stable';
  12. $release_version = '2.3.0';
  13. $release_notes   = 'open TODO list ...';
  14. $license = 'BSD License';
  15.
  16. $p1->setOptions(array(
  17.     'package'           => $name,
  18.     'summary'           => $summary,
  19.     'description'       => $description,
  20.     'state'             => $release_state,
  21.     'version'           => $release_version,
  22.     'notes'             => $release_notes,
  23.     'license'           => $license,
  24.     'ignore'            => array('Iterator.php'),
  25.     'packagedirectory'  => 'C:/php/pear/MDB2',
  26.     'baseinstalldir'    => '/'
  27. ));
  28. //...
  29. $p1->addMaintainer('lsmith', 'lead', 'Lukas Kahwe Smith', 'smith@pooteeweet.org');
  30.
  31. if (isset($_GET['make']) || (isset($_SERVER['argv']) && @$_SERVER['argv'][1] == 'make')) {
  32.     $p1->writePackageFile();
  33. } else {
  34.     $p1->debugPackageFile();
  35. }
  36. ?>

To produce a package.xml version 2.0

  1. <?php
  2. require_once 'PEAR/PackageFileManager2.php';
  3.
  4. PEAR::setErrorHandling(PEAR_ERROR_DIE);
  5.
  6. $p2 = new PEAR_PackageFileManager2();
  7.
  8. $name        = 'MDB2';
  9. $summary     = 'database abstraction layer';
  10. $description = 'PEAR MDB2 is a merge of the PEAR DB and ...';
  11. $channel     = 'pear.php.net';
  12. $extends     = 'MDB';
  13. $release_state   = 'stable';
  14. $release_version = '2.3.0';
  15. $api_state       = 'stable';
  16. $api_version     = '2.3.0';
  17. $release_notes   = 'open TODO list ...';
  18.
  19. $p2->setOptions(array(
  20.     'packagedirectory'  => 'C:/php/pear/MDB2',
  21.     'baseinstalldir'    => '/'
  22. ));
  23.
  24. //...
  25. $p2->setPackageType('php');
  26. $p2->generateContents();
  27. $p2->setPackage($name);
  28. $p2->setChannel($channel);
  29. $p2->setExtends($extends);
  30. $p2->setSummary($summary);
  31. $p2->setDescription($description);
  32. $p2->setReleaseVersion($release_version);
  33. $p2->setReleaseStability($release_state);
  34. $p2->setAPIVersion($api_version);
  35. $p2->setAPIStability($api_state);
  36. $p2->setNotes($release_notes);
  37. $p2->setLicense('BSD License', 'http://www.opensource.org/licenses/bsd-license.php');
  38.
  39. $p2->setPhpDep('4.2.0');
  40. $p2->setPearinstallerDep('1.4.3');
  41.
  42. $p2->addMaintainer('lead', 'lsmith', 'Lukas Kahwe Smith', 'smith@pooteeweet.org');
  43.
  44. if (isset($_GET['make']) || (isset($_SERVER['argv']) && @$_SERVER['argv'][1] == 'make')) {
  45.     $p2->writePackageFile();
  46. } else {
  47.     $p2->debugPackageFile();
  48. }
  49. ?>

Even, if its not yet perfect, we have built our first package.xml.

[Important] Important
A point in favor of PEAR_PackageFileManager2. It may generates package with PHP4 even if PHP5 tokens are detected in source code, while PEAR_PackageFileManager cannot.

PEAR_PackageFileManager : The Definitive Guide v 1.6.0 : November 17, 2006
Prev | Up | Next
Chapter 7. Creating a new package | Home | Resume


Resume
Prev Chapter 7. Creating a new package Next

Resume

  • Defines where source files resides with option directive packagedirectory

  • Defines where source files should be installed (on PEAR infrastructure) with option directive baseinstalldir

  • Defines a name for your package, with a summary, and a long description.

  • Defines a release version number with a state under term of a license. API info are only available for package.xml 2.0, and package.xml 1.0 accept only a license name (without URI).

  • Defines at least one leader for the package maintainers list.

  • package.xml 2.0 dependencies require at least definition of PHP and PEAR installer minimum version to use, while dependencies are optional for package.xml 1.0

  • Gets a fresh package files list depending of plugin used. See option directive filelistgenerator

Table 7.1. First package/release with package.xml 1.0 and package.xml 2.0

1.0 2.0 equivalent

require_once 'PEAR/PackageFileManager.php';

PEAR::setErrorHandling(PEAR_ERROR_DIE);

$p1 = new PEAR_PackageFileManager();

require_once 'PEAR/PackageFileManager2.php';

PEAR::setErrorHandling(PEAR_ERROR_DIE);

$p2 = new PEAR_PackageFileManager2();

$p1->setOptions(array(
    'packagedirectory'  => 'C:\php\pear\MDB2',
    'baseinstalldir'    => '/'
));

$p2->setOptions(array(
    'packagedirectory'  => 'C:\php\pear\MDB2',
    'baseinstalldir'    => '/'
));

$name        = 'MDB2';
$summary     = 'database abstraction layer';
$description = 'PEAR MDB2 is a merge of the PEAR DB ...';

$p1->setOptions(array(
    'package'           => $name,
    'summary'           => $summary,
    'description'       => $description,
    //...
));

$name        = 'MDB2';
$summary     = 'database abstraction layer';
$description = 'PEAR MDB2 is a merge of the PEAR DB ...';

$p2->setPackage($name);
$p2->setSummary($summary);
$p2->setDescription($description);

$release_notes   = 'open TODO list ...';
$release_state   = 'beta';
$release_version = '2.3.0';
$license = array(
    'BSD License',
    'http://www.opensource.org/licenses/bsd-license.php'
    );

$p1->setOptions(array(
    'state'             => $release_state,
    'version'           => $release_version,
    'notes'             => $release_notes,
    'license'           => $license[0],
    //...
));

$release_notes   = 'open TODO list ...';
$release_state   = 'beta';
$release_version = '2.3.0';
$api_state   = 'stable';
$api_version = '2.0.0';
$license = array(
    'BSD License',
    'http://www.opensource.org/licenses/bsd-license.php'
    );

$p2->setReleaseVersion($release_version);
$p2->setReleaseStability($release_state);

$p2->setAPIVersion($api_version);
$p2->setAPIStability($api_state);

$p2->setNotes($release_notes);

$p2->setLicense($license[0], $license[1]);

$p1->addMaintainer('lsmith', 'lead',
    'Lukas Kahwe Smith', 'smith@pooteeweet.org');

$p2->addMaintainer('lead', 'lsmith',
    'Lukas Kahwe Smith', 'smith@pooteeweet.org');

// No need to define PHP and PEAR dependency

$p2->setPhpDep('4.2.0');
$p2->setPearinstallerDep('1.4.3');

// No need to ask for file list contents generation

$p2->generateContents();

[Warning] Warning
Role and Handle parameter order of Maintainer are swapped between package.xml version 1.0 and 2.0

PEAR_PackageFileManager : The Definitive Guide v 1.6.0 : November 17, 2006
Prev | Up | Next
Add a new release | Home | Chapter 8. Maintaining users list


Chapter 8. Maintaining users list
Prev Part III. Tutorial Next

Chapter 8. Maintaining users list

Table of Contents

Add a new user on maintainers list
Remove a user on maintainers list
Change full name, email address, role or status of a maintainer
Getting list of maintainer

This lesson :

  • teachs you how to add a new user or remove him definitively

  • teachs you how to make a user inactive

  • teachs you how to change e-mail address, full name or role of a user

  • helps you get list of user (global, or by role)

Add a new user on maintainers list

No big change since API 1.5.x that manage package.xml 1.0; We use the same method name addMaintainer() with parameters :

role

role of maintainer

Every maintainer has one of four possible roles:

  • lead: the primary maintainer
  • developer: an important developer on the project
  • contributor: self-explanatory
  • helper: ditto

handle

username on pear.php.net of maintainer

name

full name of maintainer

email

email address of maintainer

active

status of maintainer (active = 'yes', inactive = 'no')

[Important] Important
No checking of duplicates is performed, use updateMaintainer() for that purpose.

[Warning] Warning
Role, and Handle parameters are not given in same order. See example below:

To produce a package.xml version 1.0

  1. <?php
  2. require_once 'PEAR/PackageFileManager.php';
  3.
  4. PEAR::setErrorHandling(PEAR_ERROR_DIE);
  5.
  6. $p1 = new PEAR_PackageFileManager();
  7. //...
  8. $p1->addMaintainer('jeichorn', 'lead', 'Joshua Eichorn', 'josh@bluga.net');
  9. $p1->addMaintainer('davidc', 'lead', 'David Coallier', 'davidc@php.net');
  10. ?>

To produce a package.xml version 2.0

  1. <?php
  2. require_once 'PEAR/PackageFileManager2.php';
  3.
  4. PEAR::setErrorHandling(PEAR_ERROR_DIE);
  5.
  6. $p2 = new PEAR_PackageFileManager2();
  7. //...
  8. $p2->addMaintainer('lead', 'jeichorn', 'Joshua Eichorn', 'josh@bluga.net');
  9. $p2->addMaintainer('lead', 'davidc', 'David Coallier', 'davidc@php.net', 'no');
  10. ?>

[Tip] Tip
You may now with PEAR_PackageFileManager 1.6.0+ add a new user with a default inactive status. It was not possible with package xml 1.0; When a user was added as maintainer, it was considered as active. No way to made him inactive, except to remove him definitively.

See previous example with "davidc", added as inactive.

PEAR_PackageFileManager : The Definitive Guide v 1.6.0 : November 17, 2006
Prev | Up | Next
Resume | Home | Remove a user on maintainers list


Remove a user on maintainers list
Prev Chapter 8. Maintaining users list Next

Remove a user on maintainers list

If you think this function is useless, you may consider that the package script generator could use data coming from another source (such as a database, a flat file, ...) rather than just hard-coded.

[Important] Important
This feature is only available for PEAR_PackageFileManager 1.6.0 or better. To do the same thing, by programming, with package.xml version 1.0, you should set options with an empty "maintainers" array first, before apply the addMaintainer() method.

To produce a package.xml version 1.0

  1. <?php
  2. require_once 'PEAR/PackageFileManager.php';
  3. require_once 'MDB2.php';
  4.
  5. PEAR::setErrorHandling(PEAR_ERROR_DIE);
  6.
  7. // ...
  8.
  9. $p1 = new PEAR_PackageFileManager();
  10. $p1->setOptions(array(
  11.     'maintainers' => array(),
  12.     // any other option ...
  13. ));
  14. //...
  15. $res =& $mdb2->query('SELECT * FROM maintainers');
  16.
  17. while (($m = $res->fetchRow())) {
  18.
  19.     if ($m->active) {
  20.         $p1->addMaintainer($m->handle, $m->role, $m->name, $m->email);
  21.     }
  22. }
  23. ?>

To produce a package.xml version 2.0

  1. <?php
  2. require_once 'PEAR/PackageFileManager2.php';
  3. require_once 'MDB2.php';
  4.
  5. PEAR::setErrorHandling(PEAR_ERROR_DIE);
  6.
  7. // ...
  8.
  9. $packagefile = 'c:/php/pear/HTML_AJAX/package2.xml';
  10. // $options = array();
  11.
  12. $p2 = &PEAR_PackageFileManager2::importOptions($packagefile, $options);
  13. //...
  14. $res =& $mdb2->query('SELECT * FROM maintainers');
  15.
  16. while (($m = $res->fetchRow())) {
  17.
  18.     if ($m->exists) {
  19.         $p2->addMaintainer($m->role, $m->handle, $m->name, $m->email, $m->active);
  20.     } else {
  21.         $p2->deleteMaintainer($m->handle);
  22.     }
  23. }
  24. ?>

PEAR_PackageFileManager : The Definitive Guide v 1.6.0 : November 17, 2006
Prev | Up | Next
Chapter 8. Maintaining users list | Home | Change full name, email address, role or status of a maintainer


Change full name, email address, role or status of a maintainer
Prev Chapter 8. Maintaining users list Next

Change full name, email address, role or status of a maintainer

Once again, if you think this function is useless, you may consider that the package script generator could use data coming from another source (such as a database, a flat file, ...) rather than just hard-coded.

Checking of duplicates is performed by usage of updateMaintainer(), and even allow adding a new user if he did not exists.

[Important] Important
This feature is only available for PEAR_PackageFileManager 1.6.0 or better. To do the same thing, by programming, with package.xml version 1.0, you should set options with an empty "maintainers" array first, before apply the addMaintainer() method.

To produce a package.xml version 1.0

  1. <?php
  2. require_once 'PEAR/PackageFileManager.php';
  3. require_once 'MDB2.php';
  4.
  5. PEAR::setErrorHandling(PEAR_ERROR_DIE);
  6.
  7. // ...
  8.
  9. $p1 = new PEAR_PackageFileManager();
  10. $p1->setOptions(array(
  11.     'maintainers' => array(),
  12.     // any other option ...
  13. ));
  14. //...
  15. $res =& $mdb2->query('SELECT * FROM maintainers');
  16.
  17. while (($m = $res->fetchRow())) {
  18.
  19.     $p1->addMaintainer($m->handle, $m->newrole, $m->newname, $m->newemail);
  20. }
  21. ?>

To produce a package.xml version 2.0

  1. <?php
  2. require_once 'PEAR/PackageFileManager2.php';
  3. require_once 'MDB2.php';
  4.
  5. PEAR::setErrorHandling(PEAR_ERROR_DIE);
  6.
  7. // ...
  8.
  9. $packagefile = 'c:/php/pear/HTML_AJAX/package2.xml';
  10. // $options = array();
  11.
  12. $p2 = &PEAR_PackageFileManager2::importOptions($packagefile, $options);
  13. //...
  14. $res =& $mdb2->query('SELECT * FROM maintainers');
  15.
  16. while (($m = $res->fetchRow())) {
  17.
  18.     if ($m->exists) {
  19.         $p2->updateMaintainer($m->newrole, $m->handle, $m->newname, $m->newemail, $m->newstatus);
  20.     } else {
  21.         $p2->deleteMaintainer($m->handle);
  22.     }
  23. }
  24. ?>

PEAR_PackageFileManager : The Definitive Guide v 1.6.0 : November 17, 2006
Prev | Up | Next
Remove a user on maintainers list | Home | Getting list of maintainer


Getting list of maintainer
Prev Chapter 8. Maintaining users list Next

Getting list of maintainer

While API 1.5.x did not provides any way to retrieve user data of a maintainer.
PEAR_PackageFileManager 1.6.0+ allow to get a full list organized by role or not, or
a restricted list to a specific role. These methods to get data are :
getMaintainers(),
getLeads(),
getDevelopers(),
getContributors() and
getHelpers().

Here are the 5 methods in action :

  1. <?php
  2. require_once 'PEAR/PackageFileManager2.php';
  3.
  4. PEAR::setErrorHandling(PEAR_ERROR_DIE);
  5.
  6. $packagefile = 'C:/PEAR/Database/MDB2-2.2.2/package.xml';
  7. $options = array(
  8.     'baseinstalldir' => '/',
  9.     'simpleoutput' => true,
  10.     'clearcontents' => false,
  11.     'changelogoldtonew' => false
  12.     );
  13.
  14. // package.xml could be either version 1.0 or version 2.0
  15. $p2 = &PEAR_PackageFileManager2::importFromPackageFile1($packagefile, $options);
  16.
  17. // all maintainers
  18. $m1 = $p2->getMaintainers();
  19.
  20. // all maintainers group by role
  21. $m2 = $p2->getMaintainers(true);
  22.
  23. // all maintainers that have the 'lead' role
  24. $m3 = $p2->getLeads();
  25.
  26. // all maintainers that have the 'developer' role
  27. $m4 = $p2->getDevelopers();
  28.
  29. // all maintainers that have the 'contributor' role
  30. $m5 = $p2->getContributors();
  31.
  32. // all maintainers that have the 'helper' role
  33. $m6 = $p2->getHelpers();
  34.
  35.
  36. echo '<pre>';
  37. echo '<h1>all maintainers</h1>';
  38. var_dump($m1);
  39. echo '<h1>all maintainers group by role</h1>';
  40. var_dump($m2);
  41. echo '<h1>all maintainers that have the "lead" role</h1>';
  42. var_dump($m3);
  43. echo '<h1>all maintainers that have the "developer" role</h1>';
  44. var_dump($m4);
  45. echo '<h1>all maintainers that have the "contributor" role</h1>';
  46. var_dump($m5);
  47. echo '<h1>all maintainers that have the "helper" role</h1>';
  48. var_dump($m6);
  49. echo '</pre>';
  50. ?>

With such functions, we can retrieve easily a specific user and change its properties. For example, suppose an helper become a new lead on the next stable release.

We could write something like :

  1. <?php
  2. require_once 'PEAR/PackageFileManager2.php';
  3.
  4. PEAR::setErrorHandling(PEAR_ERROR_DIE);
  5.
  6. $version = '0.0.0';
  7. $userid  = 'davidc';
  8. $newrole = 'lead';
  9.
  10. $packagefile = 'C:/PEAR/Database/MDB2-2.2.2/package.xml';
  11. // $options = array();
  12.
  13. // package.xml could be either version 1.0 or version 2.0
  14. $p2 = &PEAR_PackageFileManager2::importFromPackageFile1($packagefile, $options);
  15.
  16. if ($p2->getState('release') == 'stable'
  17.     && version_compare($p2->getVersion('release'), $version) < 0) {
  18.
  19.     $m6 = $p2->getHelpers();
  20.     foreach ($m6 as $id => $user) {
  21.         if ($user['user'] === $userid) {
  22.             list($name, $handle, $email, $active) = $user;
  23.             $p2->updateMaintainer($newrole, $handle, $name, $email, $active);
  24.             break;
  25.         }
  26. }
  27. ?>

PEAR_PackageFileManager : The Definitive Guide v 1.6.0 : November 17, 2006
Prev | Up | Next
Change full name, email address, role or status of a maintainer | Home | Chapter 9. Using tasks to customize file installation


Chapter 9. Using tasks to customize file installation
Prev Part III. Tutorial Next

Chapter 9. Using tasks to customize file installation

Table of Contents

Search and Replace file contents
Converting file line endings
Advanced installation with post install script
Giving parameters for PEAR installer
Scripting actions proceed after files copy

This lesson :

  • teachs you how to manipulate file content with 3 basic tasks

  • teachs you how to perform complex installation with a post install script

Search and Replace file contents

The replace task is nearly identical to the old <replace> tag from package.xml 1.0, and does a text search-and-replace of a file's contents.

In this example we will specialize file pear-phpdoc contents on installation, with the most common and used basic task : <tasks:replace>.

Search all @PHP-BIN@ occurences in source file pear-phpdoc, and replace them by value of option php_bin (PHP CLI/CGI binary location).

To produce a package.xml version 1.0

  1. <?php
  2. require_once 'PEAR/PackageFileManager.php';
  3.
  4. PEAR::setErrorHandling(PEAR_ERROR_DIE);
  5.
  6. $p1 = new PEAR_PackageFileManager();
  7. //...
  8. $p1->addReplacement('pear-phpdoc', 'pear-config', '@PHP-BIN@', 'php_bin');
  9. ?>

To produce a package.xml version 2.0

  1. <?php
  2. require_once 'PEAR/PackageFileManager2.php';
  3.
  4. PEAR::setErrorHandling(PEAR_ERROR_DIE);
  5.
  6. $p2 = new PEAR_PackageFileManager2();
  7. //...
  8. $p2->addReplacement('pear-phpdoc', 'pear-config', '@PHP-BIN@', 'php_bin');
  9. ?>

[Tip] Tip
If all your files, or almost all of them as the same task replacement to do, you can use the addGlobalReplacement() function that accept same $type, $from, $to parameters (#2, #3, #4) of addReplacement().

  1. <?php
  2. require_once 'PEAR/PackageFileManager2.php';
  3.
  4. PEAR::setErrorHandling(PEAR_ERROR_DIE);
  5.
  6. $p2 = new PEAR_PackageFileManager2();
  7. //...
  8. $p2->addGlobalReplacement('pear-config', '@PHP-BIN@', 'php_bin');
  9. ?>

PEAR_PackageFileManager : The Definitive Guide v 1.6.0 : November 17, 2006
Prev | Up | Next
Getting list of maintainer | Home | Converting file line endings


Converting file line endings
Prev Chapter 9. Using tasks to customize file installation Next

Converting file line endings

Windows and Unix platform handle end-of-line in a specific way that you should take care if you don't want to have surprise at run-time.

Windows convert line endings to \r\n, while Unix convert line endings to \n. You may decides to prevent problem at package-time, as well as at install-time, and adding two basic tasks : <tasks:windowseol>, and <tasks:unixeol>.

[Note] Note
This feature is only available for package.xml, version 2.0

In this example we have two files pear-phpdoc and pear-phpdoc.bat that only one version should be installed at run-time. We will see later how to specify this condition.

  1. <?php
  2. require_once 'PEAR/PackageFileManager2.php';
  3.
  4. PEAR::setErrorHandling(PEAR_ERROR_DIE);
  5.
  6. $p2 = new PEAR_PackageFileManager2();
  7. //...
  8. $p2->addUnixEol('pear-phpdoc');
  9. $p2->addWindowsEol('pear-phpdoc.bat');
  10. ?>

PEAR_PackageFileManager : The Definitive Guide v 1.6.0 : November 17, 2006
Prev | Up | Next
Chapter 9. Using tasks to customize file installation | Home | Advanced installation with post install script


Advanced installation with post install script
Prev Chapter 9. Using tasks to customize file installation Next

Advanced installation with post install script

Giving parameters for PEAR installer
Scripting actions proceed after files copy
Introduction to a class pattern
Initializing environment
Proceeding post install task

If you want to do something else than just basic tasks (search and replace string, converting line ending), extreme customization is possible with <postinstallscript> tag. This tag define parameters that are used by PEAR installer to retrieve user input, while running a post-install script.

[Note] Note
This feature is only available for package.xml, version 2.0

Distribution of full web application, including a database, is one of common problem that <tasks:postinstallscript> may solve.

Giving parameters for PEAR installer

In this example we will install a MySQL database with the mysqlinstall script that resides in server sub-directory of target directory installation (see attribute baseinstalldir).

In package.xml, between <contents> tag we will find something like :

  1. <file baseinstalldir="HTML" name="server/mysqlinstall.php" role="php">
  2.  <tasks:postinstallscript>
  3.   <tasks:paramgroup>
  4.    <tasks:id>databaseSetup</tasks:id>
  5.    <tasks:param>
  6.     <tasks:name>database</tasks:name>
  7.     <tasks:prompt>Mysql database</tasks:prompt>
  8.     <tasks:type>string</tasks:type>
  9.     <tasks:default>peartest</tasks:default>
  10.    </tasks:param>
  11.    <tasks:param>
  12.     <tasks:name>user</tasks:name>
  13.     <tasks:prompt>Mysql Username (must have create permision)</tasks:prompt>
  14.     <tasks:type>string</tasks:type>
  15.     <tasks:default>root</tasks:default>
  16.    </tasks:param>
  17.    <tasks:param>
  18.     <tasks:name>password</tasks:name>
  19.     <tasks:prompt>Mysql password</tasks:prompt>
  20.     <tasks:type>string</tasks:type>
  21.     <tasks:default />
  22.    </tasks:param>
  23.    <tasks:param>
  24.     <tasks:name>dbhost</tasks:name>
  25.     <tasks:prompt>Database Host</tasks:prompt>
  26.     <tasks:type>string</tasks:type>
  27.     <tasks:default>localhost</tasks:default>
  28.    </tasks:param>
  29.   </tasks:paramgroup>
  30.  </tasks:postinstallscript>
  31. </file>

Generated by a script like this:

  1. <?php
  2. require_once 'PEAR/PackageFileManager2.php';
  3.
  4. PEAR::setErrorHandling(PEAR_ERROR_DIE);
  5.
  6. $p2 = new PEAR_PackageFileManager2();
  7. //...
  8. $task = & $p2->initPostinstallScript('server/mysqlinstall.php');
  9. $task->addParamGroup('databaseSetup', array(
  10.     $task->getParam('database', 'Mysql database', 'string', 'peartest'),
  11.     $task->getParam('user', 'Mysql Username (must have create permision)', 'string', 'root'),
  12.     $task->getParam('password', 'Mysql password', 'string', ''),
  13.     $task->getParam('dbhost', 'Database Host', 'string', 'localhost'),
  14.     ));
  15. $p2->addPostinstallTask($task, 'server/mysqlinstall.php');
  16. $p2->generateContents();
  17.
  18. if (isset($_GET['make']) || (isset($_SERVER['argv']) && @$_SERVER['argv'][1] == 'make')) {
  19.     $p2->writePackageFile();
  20. } else {
  21.     $p2->debugPackageFile();
  22. }
  23. ?>

Adding a post install task <tasks:postinstallscript> requires to build a PEAR_Task_Postinstallscript_rw instance for the post install script ($task). This is made by PEAR_PackageFileManager::initPostinstallScript() method.

Next we can add as much as we want any paramgroup id, such as : <tasks:paramgroup><tasks:id>databaseSetup</tasks:id>. This is made by PEAR_Task_Postinstallscript_rw::addParamGroup() method.

Each paramgroup may have zero, one or more param. These params are added by an array of PEAR_Task_Postinstallscript_rw::getParam(), or false if there is no param.

Finally, post install script task is added to package xml by a call to PEAR_PackageFileManager::addPostinstallTask() method.

Scripting actions proceed after files copy

Introduction to a class pattern
Initializing environment
Proceeding post install task

Introduction to a class pattern

Post-install script files can be named anything one desires, but the class within the file must be the same name as the file with all path separators replaced by underscores, and a fixed postfix "_postinstall". In other words, this postinstall script: server/mysqlinstall.php, must contain a class named server_mysqlinstall_postinstall.

API of a post install script always match, at least 2 functions :

init()

that initialize script environment with :

  • parameter #1 a reference to a PEAR_Config instance (current configuration used for installation).

  • parameter #2 a reference to the current PEAR_PackageFileManager instance.

  • parameter #3 the last version of this package that was installed. This is a very important parameter, as it is the only way to determine whether a package is being installed from scratch, or upgraded from a previous version. Using this parameter, it is possible to determine what incremental changes, if any, need to be performed.

run()

is called at the conclusion of each parameter group in order to process the user's responses to queries. This method carry two parameters :

  • parameter #1 is an array that will contain a list of successfully completed parameter group sections. This can be used to restore any system changes made by the installation script.

  • parameter #2 identify the most recent paramgroup or contains _undoOnError only triggered by the PEAR installer on rollback process.

In our example, we should have a class pattern as this one :

  1. <?php
  2. class server_mysqlinstall_postinstall
  3. {
  4.     var $_config;
  5.     var $_ui;
  6.     var $_pkg;
  7.     var $lastversion;
  8.
  9.     function init(&$config, &$pkg, $lastversion)
  10.     {
  11.         $this->_config = &$config;
  12.         $this->_ui = &PEAR_Frontend::singleton();
  13.         $this->_pkg = &$pkg;
  14.         $this->lastversion = $lastversion;
  15.         return true;
  16.     }
  17.
  18.     function run($answers, $phase)
  19.     {
  20.     }
  21. }
  22. ?>

Initializing environment

This phase is important and allow script to communicate with a backend logger ($this->_ui), get information from your PEAR installation copy ($this->_config), get information on package release you are trying to install/upgrade ($this->_pkg) and the previous version installed (if any).

You may also add other data you think it's necessary to task proceed. For example a database existence indicator ($this->databaseExists), and what kind of driver we could use: either mysql or mysqli ($this->mysqliAvailable).

  1. <?php
  2. class server_mysqlinstall_postinstall
  3. {
  4. //...
  5.     var $databaseExists;
  6.     var $mysqliAvailable;
  7.
  8.     function init(&$config, &$pkg, $lastversion)
  9.     {
  10.         //...
  11.         $this->databaseExists  = false;
  12.         $this->mysqliAvailable = extension_loaded('mysqli');
  13.
  14.     }
  15. //...
  16. }
  17. ?>

Proceeding post install task

Deeper inside class server_mysqlinstall_postfix and run() method, we find :

  • a way to commit action (each paramgroup id).

  • and another to revert action : _undoOnError

  1. <?php
  2. class server_mysqlinstall_postinstall
  3. {
  4. //...
  5.
  6.     function run($answers, $phase)
  7.     {
  8.         switch ($phase) {
  9.             case 'databaseSetup' :
  10.                 return $this->createDatabase($answers);
  11.                 break;
  12.             case '_undoOnError' :
  13.                 // answers contains paramgroups that succeeded in reverse order
  14.                 foreach ($answers as $group) {
  15.                     switch ($group) {
  16.                         case 'databaseCreate' :
  17.                             if ($this->lastversion || $this->databaseExists) {
  18.                                 // don't uninstall the database
  19.                                 break;
  20.                             }
  21.                             // code to drop the database
  22.                         // ... other case ...
  23.                     }
  24.                 }
  25.                 // ...
  26.                 break;
  27.         }
  28.     }
  29. }
  30. ?>

Explore in details one action (paramgroup id): databaseCreate specialized to creating new database (default is peartest) given by param name database of this paramgroup.

  1. <?php
  2. class server_mysqlinstall_postinstall
  3. {
  4.     var $dbhost;
  5.     var $db;
  6.     var $user;
  7.     var $password;
  8. //...
  9.
  10.     function createDatabase($answers)
  11.     {
  12.         $this->dbhost   = $answers['dbhost'];
  13.         $this->db       = $answers['database'];
  14.         $this->user     = $answers['user'];
  15.         $this->password = $answers['password'];
  16.
  17.         // Try to connect to database
  18.         $conn = $this->getDBConnection();
  19.         if (!$conn) {
  20.             return false;
  21.         }
  22.
  23.         if ($this->mysqliAvailable) {
  24.             $query = mysqli_select_db($conn, $this->db);
  25.         } else {
  26.             $query = mysql_select_db($this->db, $conn);
  27.         }
  28.         if ($query) {
  29.             // upgrading database schema/data ?
  30.             $this->databaseExists = true;
  31.             // ...
  32.         } else {
  33.             // create database
  34.             $this->databaseExists = false;
  35.
  36.             if ($this->mysqliAvailable) {
  37.                 $query = mysqli_query($conn, 'CREATE DATABASE ' . $this->db);
  38.                 if ($query) {
  39.                     $query = mysqli_select_db($conn, $this->db);
  40.                 }
  41.             } else {
  42.                 $query = mysql_query('CREATE DATABASE ' . $this->db, $conn);
  43.                 if ($query) {
  44.                     $query = mysql_select_db($this->db, $conn);
  45.                 }
  46.             }
  47.
  48.             if (!$query) {
  49.                 if ($this->mysqliAvailable) {
  50.                     $err = mysqli_error($conn);
  51.                 } else {
  52.                     $err = mysql_error();
  53.                 }
  54.                 $this->_ui->outputData('Database creation failed: ' . $err);
  55.                 $this->closeDB($conn);
  56.                 return false;
  57.             }
  58.         }
  59.         $this->closeDB($conn);
  60.         return true;
  61.     }
  62.
  63.     function getDBConnection()
  64.     {
  65.         if ($this->mysqliAvailable) {
  66.             $conn = mysqli_connect($this->dbhost, $this->user, $this->password);
  67.         } else {
  68.             $conn = mysql_connect($this->dbhost, $this->user, $this->password);
  69.         }
  70.         if (!$conn) {
  71.             $this->_ui->outputData('Connection to mysql server failed');
  72.             return false;
  73.         }
  74.         return $conn;
  75.     }
  76.
  77.     function closeDB($conn)
  78.     {
  79.         if ($this->mysqliAvailable) {
  80.             mysqli_close($conn);
  81.         } else {
  82.             mysql_close($conn);
  83.         }
  84.     }
  85. }
  86. ?>

[Important] Important
In case of problem, don't forget to provide a way to revert action already applied. PEAR installer will then trigger _undoOnError phase run.

PEAR_PackageFileManager : The Definitive Guide v 1.6.0 : November 17, 2006
Prev | Up | Next
Converting file line endings | Home | Chapter 10. Maintaining dependencies list


Chapter 10. Maintaining dependencies list
Prev Part III. Tutorial Next

Chapter 10. Maintaining dependencies list

Table of Contents

Add a new dependency to PHP and PEAR installer version
PHP version dependencies
PEAR installer dependencies
Add a new dependency to another package
With package.xml 1.0, channel-based like
With package.xml 2.0, channel-based
With package.xml 2.0, uri-based
Add a new dependency to a php extension
With package.xml 1.0
With package.xml 2.0
Operating System dependency
Architecture dependency

This lesson :

  • teachs you how to add a simple PHP and PEAR version dependency

  • teachs you how to add a package version dependency

  • teachs you how to add a php extension dependency

  • teachs you how to restrict installation on specifics Operating System and process architecture

Add a new dependency to PHP and PEAR installer version

PHP version dependencies
PEAR installer dependencies

PHP and PEAR installer dependencies are required in all package.xml with at least the minimum version property set.

PHP version dependencies

PHP versioning requires at least the minimum version to install this package.xml Its made by setPhpDep() method.

In table below, consider we have each time $p2 produced by code :

  1. <?php
  2. require_once 'PEAR/PackageFileManager2.php';
  3.
  4. PEAR::setErrorHandling(PEAR_ERROR_DIE);
  5.
  6. $p2 = new PEAR_PackageFileManager2();
  7. ?>

Table 10.1. setting PHP versions dependencies

PHP code XML equivalent

$p2->setPhpDep('4.2.0');

 <dependencies>
  <required>
   <php>
    <min>4.2.0</min>
   </php>
  </required>
 </dependencies>

$p2->setPhpDep('4.2.0', '5.0.0');

 <dependencies>
  <required>
   <php>
    <min>4.2.0</min>
    <max>5.0.0</max>
   </php>
  </required>
 </dependencies>

$p2->setPhpDep('4.2.0', '5.0.0', array('5.0.0'));

 <dependencies>
  <required>
   <php>
    <min>4.2.0</min>
    <max>5.0.0</max>
    <exclude>5.0.0</exclude>
   </php>
  </required>
 </dependencies>

$p2->setPhpDep('4.2.0', '5.1.0', array('5.0.0', '5.0.1'));

 <dependencies>
  <required>
   <php>
    <min>4.2.0</min>
    <max>5.1.0</max>
    <exclude>5.0.0</exclude>
    <exclude>5.0.1</exclude>
   </php>
  </required>
 </dependencies>

PEAR installer dependencies

PEAR installer versioning requires at least the minimum version of PEAR that can properly parse and install the package.xml containing it. Its made by setPearinstallerDep() method.

In table below, consider we have each time $p2 produced by code :

  1. <?php
  2. require_once 'PEAR/PackageFileManager2.php';
  3.
  4. PEAR::setErrorHandling(PEAR_ERROR_DIE);
  5.
  6. $p2 = new PEAR_PackageFileManager2();
  7. ?>

Table 10.2. setting PEAR installer dependencies

PHP code XML equivalent

$p2->setPearinstallerDep('1.4.3');

 <dependencies>
  <required>
   <pearinstaller>
    <min>1.4.3</min>
   </pearinstaller>
  </required>
 </dependencies>

$p2->setPearinstallerDep('1.4.3', '1.4.11');

 <dependencies>
  <required>
   <pearinstaller>
    <min>1.4.3</min>
    <max>1.4.11</max>
   </pearinstaller>
  </required>
 </dependencies>

$p2->setPearinstallerDep('1.4.0', false, '1.4.3');

 <dependencies>
  <required>
   <pearinstaller>
    <min>1.4.0</min>
    <recommended>1.4.3</recommended>
   </pearinstaller>
  </required>
 </dependencies>

$p2->setPearinstallerDep('1.4.0', false, false,
    array('1.4.1', '1.4.2'));

 <dependencies>
  <required>
   <pearinstaller>
    <min>1.4.0</min>
    <exclude>1.4.1</exclude>
    <exclude>1.4.2</exclude>
   </pearinstaller>
  </required>
 </dependencies>

PEAR_PackageFileManager : The Definitive Guide v 1.6.0 : November 17, 2006
Prev | Up | Next
Advanced installation with post install script | Home | Add a new dependency to another package


Add a new dependency to another package
Prev Chapter 10. Maintaining dependencies list Next

Add a new dependency to another package

With package.xml 1.0, channel-based like
With package.xml 2.0, channel-based
With package.xml 2.0, uri-based

PEAR 1.4.0 and package.xml 2.0 supports more package dependencies than package.xml 1.0, but we will see in details what are differences and how we can do (try to do) the same job.

With package.xml 1.0, channel-based like

In table below, consider we have each time $p1 produced by code :

  1. <?php
  2. require_once 'PEAR/PackageFileManager.php';
  3.
  4. PEAR::setErrorHandling(PEAR_ERROR_DIE);
  5.
  6. $p1 = new PEAR_PackageFileManager();
  7. ?>

Table 10.3. package.xml 1.0 dependencies

PHP code XML equivalent

// 'has' relation
$p1->addDependency('PEAR',
    false, 'has', 'pkg', false);

<deps>
 <dep type="pkg" rel="has"
      optional="no">
      PEAR
 </dep>
</deps>

// 'greater or equal' relation
$p1->addDependency('Archive_Tar',
    '1.0.0', 'ge', 'pkg', false);

<deps>
 <dep type="pkg"
      rel="ge" version="1.0.0"
      optional="no">
      Archive_Tar
 </dep>
</deps>

// 'greater than' relation
$p1->addDependency('MDB2',
    '2.1.0', 'gt', 'pkg', true);

<deps>
 <dep type="pkg"
      rel="gt" version="2.1.0"
      optional="yes">
      MDB2
 </dep>
</deps>

// 'less or equal' relation
$p1->addDependency('Console_Getopt',
    '1.2', 'le', 'pkg');

<deps>
 <dep type="pkg"
      rel="le" version="1.2"
      optional="no">
      Console_Getopt
 </dep>
</deps>

// 'less than' relation
$p1->addDependency('Text_Highlighter',
    '0.7.0', 'lt', 'pkg', true);

<deps>
 <dep type="pkg"
      rel="lt" version="0.7.0"
      optional="yes">
      Text_Highlighter
 </dep>
</deps>

// 'between' relation
$p1->addDependency('PEAR_PackageFileManager',
    '1.6.0a1', 'ge');
$p1->addDependency('PEAR_PackageFileManager',
    '1.6.0b5', 'le');

<deps>
 <dep type="pkg"
      rel="ge" version="1.6.0a1"
      optional="no">
      PEAR_PackageFileManager
 </dep>
 <dep type="pkg"
      rel="le" version="1.6.0b5"
      optional="no">
      PEAR_PackageFileManager
 </dep>
</deps>

// 'conflicting' dependency
$p1->addDependency('DB',
    false, 'not', 'pkg');

<deps>
 <dep type="pkg" rel="not">DB</dep>
</deps>

With package.xml 2.0, channel-based

In table below, consider we have each time $p2 produced by code :

  1. <?php
  2. require_once 'PEAR/PackageFileManager2.php';
  3.
  4. PEAR::setErrorHandling(PEAR_ERROR_DIE);
  5.
  6. $p2 = new PEAR_PackageFileManager2();
  7. ?>

Table 10.4. package.xml 2.0 dependencies

PHP code XML equivalent

// 'has' relation
$p2->addPackageDepWithChannel('required',
    'PEAR', 'pear.php.net');

<dependencies>
 <required>
<!-- ... -->
  <package>
   <name>PEAR</name>
   <channel>pear.php.net</channel>
  </package>
 </required>
</dependencies>

// 'greater or equal' relation
$p2->addPackageDepWithChannel('required',
    'Archive_Tar', 'pear.php.net',
    '1.0.0');

<dependencies>
 <required>
<!-- ... -->
  <package>
   <name>Archive_Tar</name>
   <channel>pear.php.net</channel>
   <min>1.0.0</min>
  </package>
 </required>
</dependencies>

// 'greater than' relation
$p2->addPackageDepWithChannel('optional',
    'MDB2', 'pear.php.net',
    '2.1.0', false, false, '2.1.0');

<dependencies>
 <required>
<!-- ... -->
 </required>
 <optional>
  <package>
   <name>MDB2</name>
   <channel>pear.php.net</channel>
   <min>2.1.0</min>
   <exclude>2.1.0</exclude>
  </package>
 </optional>
</dependencies>

// 'less or equal' relation
$p2->addPackageDepWithChannel('required',
    'Console_Getopt', 'pear.php.net',
    false, '1.3.0');

<dependencies>
 <required>
<!-- ... -->
  <package>
   <name>Console_Getopt</name>
   <channel>pear.php.net</channel>
   <max>1.3.0</max>
  </package>
 </required>
</dependencies>

// 'less than' relation
$p2->addPackageDepWithChannel('optional',
    'Text_Highlighter', 'pear.php.net',
    false, '0.7.0', false, '0.7.0');

<dependencies>
 <required>
<!-- ... -->
 </required>
 <optional>
  <package>
   <name>Text_Highlighter</name>
   <channel>pear.php.net</channel>
   <max>0.7.0</min>
   <exclude>0.7.0</exclude>
  </package>
 </optional>
</dependencies>

// 'between' relation
$p2->addPackageDepWithChannel('required',
    'PEAR_PackageFileManager', 'pear.php.net',
    '1.6.0a1', '1.6.0b5');

<dependencies>
 <required>
<!-- ... -->
  <package>
   <name>PEAR_PackageFileManager</name>
   <channel>pear.php.net</channel>
   <min>1.6.0a1</min>
   <max>1.6.0b5</max>
  </package>
 </required>
</dependencies>

// 'conflicting' dependency
$p2->addConflictingPackageDepWithChannel('DB',
    'pear.php.net');

<dependencies>
 <required>
<!-- ... -->
  <package>
   <name>DB</name>
   <channel>pear.php.net</channel>
   <conflicts/>
  </package>
 </required>
</dependencies>

With package.xml 2.0, uri-based

When you use uri-based package dependencies rather than channel-based package dependencies (see previously), you have to use: addPackageDepWithUri() method instead of addPackageDepWithChannel().

Here is a simple example to produce:

  1. <require>
  2.  <package>
  3.   <name>Foo<name>
  4.   <uri>http://www.example.com/Foo-1.3.0</uri>
  5.  </package>
  6. </require>

you should write:

  1. $p2->addPackageDepWithUri('required', 'Foo', 'http://www.example.com/Foo-1.3.0');

[Important] Important
Do not append tgz or tar extension, when you give the uri. PEAR installer will try to fetch http://www.example.com/Foo-1.3.0.tgz or http://www.example.com/Foo-1.3.0.tar

[Note] Note
List of package installed through pseudo channel __uri may be displayed, on command line, with :
      pear list -a

PEAR_PackageFileManager : The Definitive Guide v 1.6.0 : November 17, 2006
Prev | Up | Next
Chapter 10. Maintaining dependencies list | Home | Add a new dependency to a php extension


Add a new dependency to a php extension
Prev Chapter 10. Maintaining dependencies list Next

Add a new dependency to a php extension

With package.xml 1.0
With package.xml 2.0

As with all dependencies that support versioning, all standard versioning tags are supported (min, max, recommended, exclude). In addition, the <conflicts> tag is supported to create a negative dependency.

With package.xml 1.0

Table 10.5. php extension dependencies version 1.0

PHP code XML equivalent

// 'has' relation
$p1->addDependency('gettext', false, 'has', 'ext');

<deps>
 <dep type="ext" rel="has"
      optional="no">
      gettext
 </dep>
</deps>

[Caution] Caution
Do not use comparaison operator with version, on php extension dependency, it won't work as you would expected.

With package.xml 2.0

Table 10.6. php extension dependencies version 2.0

PHP code XML equivalent

// 'has' relation
$p2->addExtensionDep('required', 'gettext');

<dependencies>
 <required>
<!-- ... -->
  <extension>
   <name>gettext</name>
  </extension>
 </required>
</dependencies>

// 'greater or equal' relation
$p2->addExtensionDep('optional', 'gd', '2.0.0');

<dependencies>
 <optional>
<!-- ... -->
  <extension>
   <name>gd</name>
   <min>2.0.0</min>
  </extension>
 </optional>
</dependencies>

PEAR_PackageFileManager : The Definitive Guide v 1.6.0 : November 17, 2006
Prev | Up | Next
Add a new dependency to another package | Home | Operating System dependency


Operating System dependency
Prev Chapter 10. Maintaining dependencies list Next

Operating System dependency

Dealing with OS dependency to restrict a package installation is made with call to addOsDep() method.

For example, if we want to restrict a package installation on linux OS, or on every OS except windows, we should write :

Table 10.7. OS installation condition

PHP code XML equivalent

$p2->addOsDep('linux');

<dependencies>
 <required>
<!-- ... -->
  <os>
   <name>linux</name>
  </os>
 </required>
</dependencies>

$p2->addOsDep('windows', true);

<dependencies>
 <required>
<!-- ... -->
  <os>
   <name>windows</name>
   <conflicts />
  </os>
 </required>
</dependencies>

PEAR_PackageFileManager : The Definitive Guide v 1.6.0 : November 17, 2006
Prev | Up | Next
Add a new dependency to a php extension | Home | Architecture dependency


Architecture dependency
Prev Chapter 10. Maintaining dependencies list Next

Architecture dependency

Dealing with Architecture dependency to restrict a package installation to a specific OS and processor architecture is made with call to addArchDep() method.

For example, if we want to restrict a package installation on linux OS, and intel 8086 family processor, or on every architecture except Mac OS X (darwin), we should write :

Table 10.8. Arch installation condition

PHP code XML equivalent

$p2->addArchDep('linux-*-i?86-*');

<dependencies>
 <required>
<!-- ... -->
  <arch>
   <pattern>linux-*-i?86-*</pattern>
  </arch>
 </required>
</dependencies>

$p2->addArchDep('darwin', true);

<dependencies>
 <required>
<!-- ... -->
  <arch>
   <pattern>darwin</pattern>
   <conflicts />
  </arch>
 </required>
</dependencies>

PEAR_PackageFileManager : The Definitive Guide v 1.6.0 : November 17, 2006
Prev | Up | Next
Operating System dependency | Home | Chapter 11. Using custom file roles


Chapter 11. Using custom file roles
Prev Part III. Tutorial Next

Chapter 11. Using custom file roles

Table of Contents

Add a new extension role mapping
Improve warning message requiring custom file role handler

This lesson :

  • teachs you how to add a new extension role mapping to default role influences array.

  • teachs you how to improve message when dealing with package role handler not installed on your system.

Add a new extension role mapping

Default role mapping array separates extension into seven categories.

Table 11.1. extension role mapping reference

Role | Extension
php | php
data | all other extension
doc | html
test | none
script | none
src | h, c, m4, w32
ext | dll

Once a package that reference, manage, the new role is properly installed in your system, you can use it, and add it to the default role mapping array.

We suppose to have previously installed a package that manage the new role web. Here we will assume that all log files (*.log) will be copied into directory declared by <locationconfig> tag of xml web file role (see PEAR/Installer/Role/Web.xml).

  1. $p2->addRole('log', 'web');

However, if a user does not have the package installed that provides the custom role web, then the error message on installation will simply say File ... has invalid role "web" should be one of data, doc, php, script, test which is not very helpful.

If you don't want to give the same behavior to all file with same extension, but only to one or a set of them, then use option directive exceptions.

  1. $p2->setOptions(array(
  2.     // ...
  3.     'exceptions' => array('index.php' => 'web'),
  4.     );

PEAR_PackageFileManager : The Definitive Guide v 1.6.0 : November 17, 2006
Prev | Up | Next
Architecture dependency | Home | Improve warning message requiring custom file role handler


Improve warning message requiring custom file role handler
Prev Chapter 11. Using custom file roles Next

Improve warning message requiring custom file role handler

This problem may be solve easily by adding a <usersrole> tag documenting package to install that will handle the new role. Uses methods : addUsesrole() with (replace role) or without (append role) its resetUsesrole() companion.

Table 11.2. install custom file role handler

PHP code XML equivalent

$p2->resetUsesrole();
// use channel-based package
$p2->addUsesrole('web', 'Role_Web', 'pearified.com');

<usesrole>
 <role>web</role>
 <package>Role_Web</package>
 <channel>pearified.com</channel>
</usesrole>

$p2->resetUsesrole();
// use uri-based package
$p2->addUsesrole('web',
    'http://pearified.com/Role-1.1.1');

<usesrole>
 <role>web</role>
 <uri>http://pearified.com/Role-1.1.1</uri>
</usesrole>

[Tip] Tip
If Role_Web package is not installed, then PEAR installer take aware user with a message like This package contains role "web" and requires package "channel://pearified.com/Role_Web" to be used.

PEAR_PackageFileManager : The Definitive Guide v 1.6.0 : November 17, 2006
Prev | Up | Next
Chapter 11. Using custom file roles | Home | Chapter 12. Using custom file tasks


Chapter 12. Using custom file tasks
Prev Part III. Tutorial Next

Chapter 12. Using custom file tasks

Table of Contents

Add a new custom file task
Improve warning message requiring custom file task handler

This lesson :

  • teachs you how to add a new task file provide by a third party to default tasks array.

  • teachs you how to improve message when dealing with package task handler not installed on your system.

Add a new custom file task

Standard file tasks provided by default, allow to : search-and-replace string into file contents, change line-ending, and add a complex postinstall script.

If you want to specialize your installation with a complex task, you will need first to learn how to create customized task in PHP .

Once a package that reference, manage, the new task file is properly installed in your system (into directory PEAR/Task/), you can use it with a call to addTaskToFile().

We suppose to have previously installed a package that manage the new task stripwhitespace.

[Note] Note
Install the PEAR_Task_Stripwhitespace package version 0.1.0 on __URI channel.
      pear install http://pear.laurent-laville.org/get/PEAR_Task_Stripwhitespace-0.1.0.tgz

  1. <?php
  2. require_once 'PEAR/PackageFileManager2.php';
  3. require_once 'PEAR/Task/Stripwhitespace/rw.php';
  4. require_once 'PEAR/Config.php';
  5. require_once 'PEAR/Frontend.php';
  6.
  7. PEAR::setErrorHandling(PEAR_ERROR_DIE);
  8.
  9. $p2 = new PEAR_PackageFileManager2();
  10. //...
  11.
  12. $p2->generateContents();
  13.
  14. $config = PEAR_Config::singleton();
  15. $log = PEAR_Frontend::singleton();
  16. $xml = $p2->getArray();
  17.
  18. $task = new PEAR_Task_Stripwhitespace_rw($p2, $config, $log, $xml);
  19. $p2->addTaskToFile('index.php', $task);
  20. //...
  21.
  22. $p2->resetUsestask();
  23. $p2->addUsestask($task->getName(),
  24.     'http://pear.laurent-laville.org/get/PEAR_Task_Stripwhitespace-0.1.0');
  25.
  26. if (isset($_GET['make']) || (isset($_SERVER['argv']) && @$_SERVER['argv'][1] == 'make')) {
  27.     $p2->writePackageFile();
  28. } else {
  29.     $p2->debugPackageFile();
  30. }
  31. ?>

This script will generate something like :

  1. <contents>
  2.   <dir baseinstalldir="HTML" name="/">
  3.    <file baseinstalldir="HTML" name="server/mysqlinstall.php" role="php" />
  4.    <file baseinstalldir="HTML" name="index.php" role="php">
  5.     <tasks:stripwhitespace />
  6.    </file>
  7.   </dir>
  8.  </contents>

[Important] Important
Allways generate file list contents with generateContents() before trying to add a task to one of file with addTaskToFile().

However, if a user does not have the package installed that provides the custom task stripwhitespace, then the error message on installation will simply say Unknown task "stripwhitespace" which is not very helpful.

PEAR_PackageFileManager : The Definitive Guide v 1.6.0 : November 17, 2006
Prev | Up | Next
Improve warning message requiring custom file role handler | Home | Improve warning message requiring custom file task handler


Improve warning message requiring custom file task handler
Prev Chapter 12. Using custom file tasks Next

Improve warning message requiring custom file task handler

This problem may be solve easily by adding a <userstask> tag documenting package to install that will handle the new task. Uses methods : addUsestask() with (replace task) or without (append task) its resetUsestask() companion.

Table 12.1. install custom file task handler

PHP code XML equivalent

$p2->resetUsestask();
// use channel-based package
$p2->addUsestask('foo',
    'Task_Foo', 'pear.example.com');

<usestask>
 <task>foo</task>
 <package>Task_Foo</package>
 <channel>pear.example.com</channel>
</usestask>

$p2->resetUsestask();
// use uri-based package
$p2->addUsestask('foo',
    'http://pear.example.com/Task_Foo-0.1.0');

<usestask>
 <task>foo</task>
 <package>Task_Foo</package>
 <uri>http://pear.example.com/Task_Foo-0.1.0</uri>
</usestask>

[Tip] Tip
If Task_Foo package is not installed, then PEAR installer take aware user with a message like This package contains task "foo" and requires package "http://pear.example.com/Task_Foo-0.1.0.tgz" to be used.

PEAR_PackageFileManager : The Definitive Guide v 1.6.0 : November 17, 2006
Prev | Up | Next
Chapter 12. Using custom file tasks | Home | Chapter 13. Handling Changelog


Chapter 13. Handling Changelog
Prev Part III. Tutorial Next

Chapter 13. Handling Changelog

Table of Contents

Reading full changelog history
Removing full changelog

This lesson :

  • teachs you how to read full changelog history.

  • teachs you how to remove definitively full changelog section from package.xml

Reading full changelog history

If you want to retrieve information from an old version, or just count releases, you have only to use one method: getChangelog().

We will create a RSS newsfeed with result of getChangelog() assisted by PEAR package XML_Serializer .

[Note] Note
Original article create a RSS newsfeed is locate at http://freedomink.org/node/62

Example 13.1. create a RSS newsfeed

  1. <?php
  2. require_once 'PEAR/PackageFileManager2.php';
  3. require_once 'XML/Serializer.php';
  4.
  5. PEAR::setErrorHandling(PEAR_ERROR_DIE);
  6.
  7. $packagefile = 'C:/php/pear/PEAR_PackageFileManager/package2.xml';
  8.
  9. $options = array('filelistgenerator' => 'cvs',
  10.     'packagedirectory' => dirname($packagefile),
  11.     'baseinstalldir' => 'PEAR',
  12.     );
  13.
  14. $p2 = &PEAR_PackageFileManager2::importOptions($packagefile, $options);
  15.
  16. $changelog = $p2->getChangelog();
  17.
  18. $options = array(
  19.     'indent'    => '    ',
  20.     'linebreak' => "\n",
  21.     'typeHints' => false,
  22.     'addDecl'   => true,
  23.     'encoding'  => 'UTF-8',
  24.     'rootName'  => 'rdf:RDF',
  25.     'defaultTagName' => 'item'
  26.     );
  27.
  28. $stories = array();
  29.
  30. foreach ($changelog['release'] as $log) {
  31.     $stories[] = array(
  32.         'title'       => $p2->getPackage() . ' ' . $log['version']['release'],
  33.         'link'        => 'http://pear.php.net/package/' . $p2->getPackage()
  34.                        . '/download/' . $log['version']['release'],
  35.         'description' => $log['notes']
  36.     );
  37. }
  38.
  39. $data['channel'] = array(
  40.     'title' => 'Latest releases',
  41.     'link'  => 'http://pear.php.net/package/' . $p2->getPackage(),
  42.     $stories
  43. );
  44.
  45. $serializer = new XML_Serializer($options);
  46.
  47. if ($serializer->serialize($data)) {
  48.     echo '<pre>';
  49.     echo htmlentities($serializer->getSerializedData());
  50.     echo '</pre>';
  51. }
  52. ?>

PEAR_PackageFileManager : The Definitive Guide v 1.6.0 : November 17, 2006
Prev | Up | Next
Improve warning message requiring custom file task handler | Home | Removing full changelog


Removing full changelog
Prev Chapter 13. Handling Changelog Next

Removing full changelog

If you don't want to keep history of changes when you generate a new release, then you have only to set option clearchangelog to true.

[Warning] Warning
This option is only available since stable release 1.6.0

  1. <?php
  2. require_once 'PEAR/PackageFileManager2.php';
  3.
  4. PEAR::setErrorHandling(PEAR_ERROR_DIE);
  5.
  6. $packagefile = 'C:/php/pear/PEAR_PackageFileManager/package2.xml';
  7.
  8. $options = array('filelistgenerator' => 'cvs',
  9.     'packagedirectory' => dirname($packagefile),
  10.     'baseinstalldir' => 'PEAR',
  11.     'clearchangelog' => true
  12.     );
  13.
  14. $p2 = &PEAR_PackageFileManager2::importOptions($packagefile, $options);
  15.
  16. $p2->generateContents();
  17.
  18. if (isset($_GET['make']) || (isset($_SERVER['argv']) && @$_SERVER['argv'][1] == 'make')) {
  19.     $p2->writePackageFile();
  20. } else {
  21.     $p2->debugPackageFile();
  22. }
  23. ?>

PEAR_PackageFileManager : The Definitive Guide v 1.6.0 : November 17, 2006
Prev | Up | Next
Chapter 13. Handling Changelog | Home | Part IV. Reference Guide


Part IV. Reference Guide
Prev Next

Part IV. Reference Guide

Table of Contents

<channel> - What is a channel?
<uri> - When should I use <uri>?
<lead>, <developer>, <contributor>, and <helper> - Developer documentation for a release
<version> - versioning in package.xml 2.0
<stability> - specifying release and API stability
<license> - specifying software license and optional reference to license text
<notes> - about release changes
<contents> - specifying the contents of a release
<dir> - documenting a directory in the <contents> tag
<file> - documenting a file in the <contents> tag
tasks for <file>s - specialized file installation and manipulation
<compatible> - Alleviating strict versioning with <compatible>
<dependencies> - Dependency Specification in package.xml 2.0
<usesrole> - documenting custom file roles used in <contents>
<usestask> - documenting custom tasks used in <contents>
<phprelease>, <extbinrelease>, <extsrcrelease>, <bundle> - specifying the content type of a release
PEAR_PackageFileManager : The Definitive Guide v 1.6.0 : November 17, 2006
Prev |  | Next
Removing full changelog | Home | <channel>


<channel>

<channel>
Prev Part IV. Reference Guide Next

Name

<channel> — What is a channel?

Quick introduction to channels

Channels are new in PEAR 1.4.0. Channels are a systemized way of differentiating between different download sources. One such download source is pear.php.net, another is pecl.php.net, and there are several third party channels slowly springing up around the net.

The <channel> tag should contain the full channel name, not any alias (don't use "pear", use "pear.php.net".

A good rule of thumb to use when determining what channel name to use is "where do I upload my releases to?" If the answer is pear.php.net, that is your package's channel. If the answer is pecl.php.net, then that is your channel.

If you aren't running a channel server and wish to serve your packages as well as allow other packages to remotely depend on your package, the new uri-based package distribution method is the best choice, see the <uri> tag documentation link below.

See also:

<uri>

PEAR_PackageFileManager : The Definitive Guide v 1.6.0 : November 17, 2006
Prev | Up | Next
Part IV. Reference Guide | Home | <uri>


<uri>

<uri>
Prev Part IV. Reference Guide Next

Name

<uri> — When should I use <uri>?

When to use <uri> instead of <channel>

If you do not have a channel server and wish to serve your packages so that others can depend on them, use <uri>. This should contain a static uri that links to a single package version's downloadable .tgz

If you do not need to allow external remote dependencies, then simply use the pear.php.net channel as your package's channel.

For instance, if you wish to serve package Foo version 1.1.0 from www.example.com, use the uri "http://www.example.com/Foo-1.1.0". Note that the uri must contain the full path MINUS THE EXTENSION. Provide both Foo-1.1.0.tgz and Foo-1.1.0.tar for users without gzip.

See also:

<channel>

PEAR_PackageFileManager : The Definitive Guide v 1.6.0 : November 17, 2006
Prev | Up | Next
<channel> | Home | <lead>, <developer>, <contributor>, and <helper>


<lead>, <developer>, <contributor>, and <helper>

<lead>, <developer>, <contributor>, and <helper>
Prev Part IV. Reference Guide Next

Name

<lead>, <developer>, <contributor>, and <helper> — Developer documentation for a release

Documenting who develops a package

In package.xml 1.0, a developer was documented using the <maintainer> tag inside of a redundant <maintainers> container tag. This has been simplified in package.xml 2.0 both to slightly speed parsing and to make validation of the xml simpler. Now, the contents of the <role> tag has been extracted as 4 tags to describe the maintainers of a package.

In addition, a new internal tag <active> has been added, so that you can honor retired developers' work without having to remove them altogether from package.xml.

[Warning] Warning
Tag order is important. List leads followed by developers followed by contributors and finally helpers.

PEAR_PackageFileManager : The Definitive Guide v 1.6.0 : November 17, 2006
Prev | Up | Next
<uri> | Home | <version>


<version>

<version>
Prev Part IV. Reference Guide Next

Name

<version> — versioning in package.xml 2.0

Documenting release version and API version

In package.xml 1.0, the version was simply the version. package.xml 2.0 splits the concept of versioning into two components, release and api.

The release version is the same familiar versioning concept from package.xml 1.0. This version is validated very carefully by the packager.

The API version is informational only - the installer does not use it. It can be used for a package-time replacement by the installer. This can be very useful when implementing a reflective method such as getApiVersion. In addition, the API version is very loosely validated, and only requires a version_compare()-compatible version number.

PEAR_PackageFileManager : The Definitive Guide v 1.6.0 : November 17, 2006
Prev | Up | Next
<lead>, <developer>, <contributor>, and <helper> | Home | <stability>


<stability>

<stability>
Prev Part IV. Reference Guide Next

Name

<stability> — specifying release and API stability

Documenting release stability and API stability

In package.xml 1.0, stability was known as "state" which is not the most accurate description. package.xml 2.0 introduces the term stability and like version splits the concept of stability into two components, release and api.

The release stability is the same familiar state from package.xml 1.0. It can be one of:

  1. snapshot - a frozen picture of development at a particular moment

  2. devel - a very new non-production release. Devel should be used for extremely new, practically untested code.

  3. alpha - a new non-production release. Alpha should be used for new code that has an unstable API or untested code.

  4. beta - a non-production release. Beta should be used for code that has a stable API and is nearing a fully stable release. Regresion tests and documentation should exist or soon follow to qualify as a beta release. Release candidates should use the beta stability.

  5. stable - a production release. Stable releases must have a stable API, and must have regression tests and documentation.

The API stability is informational only - the installer does not use it.

PEAR_PackageFileManager : The Definitive Guide v 1.6.0 : November 17, 2006
Prev | Up | Next
<version> | Home | <license>


<license>

<license>
Prev Part IV. Reference Guide Next

Name

<license> — specifying software license and optional reference to license text

Documenting release license

In package.xml 1.0, the license tag only contained the name of the license. In package.xml 2.0, there are two optional attributes, "uri" and "filesource". "uri" contains a uri that identifies the text of a license, such as "http://www.php.net/license" for the PHP License. "filesource" can be used to specify a LICENSE file within an actual package that contains the text of the license.

PEAR_PackageFileManager : The Definitive Guide v 1.6.0 : November 17, 2006
Prev | Up | Next
<stability> | Home | <notes>


<notes>

<notes>
Prev Part IV. Reference Guide Next

Name

<notes> — about release changes

Documenting release notes

Any long static text that identify what have been changed since previous version. It can be multi-line.

PEAR_PackageFileManager : The Definitive Guide v 1.6.0 : November 17, 2006
Prev | Up | Next
<license> | Home | <contents>


<contents>

<contents>
Prev Part IV. Reference Guide Next

Name

<contents> — specifying the contents of a release

Documenting release contents

In package.xml 1.0, the contents tag was <filelist>. The purpose of the tag changed dramatically in package.xml 2.0, warranting a name change. Now, <filelist> can be found in the release section of the package.xml.

<contents> is used to describe the contents of a tarball. Nothing further. All files in the contents tag will be placed into the tarball regardless of whether they eventually get installed by the PEAR installer. This fact can be used to create a very versatile tarball, one that can be directly unzipped and work out of the box as well as be installed by the PEAR installer and work out of the box.

For most release types, contents contains a single <dir> tag that then either contains nested dir tags and/or <file> tags.

PEAR_PackageFileManager : The Definitive Guide v 1.6.0 : November 17, 2006
Prev | Up | Next
<notes> | Home | <dir>


<dir>

<dir>
Prev Part IV. Reference Guide Next

Name

<dir> — documenting a directory in the <contents> tag

Documenting directories

The <dir> tag is identical to package.xml 1.0. Required attributes are name and optional attributes are baseinstalldir (the relative location where all files and subdirectories will be installed)

Note that all files must be contained in a single top-level <dir> tag. For simple packages, simply use <dir name="/"> as the directory name

PEAR_PackageFileManager : The Definitive Guide v 1.6.0 : November 17, 2006
Prev | Up | Next
<contents> | Home | <file>


<file>

<file>
Prev Part IV. Reference Guide Next

Name

<file> — documenting a file in the <contents> tag

Documenting files

The <file> tag is almost identical to package.xml 1.0. Required attributes are name and role. Optional attributes are baseinstalldir and md5sum. Optional attributes platform and install-as have been replaced by the release tags. Specifically, <install> is used to specify install-as, and the <ignore> tag can be used in conjunction with <installconditions> to exclude packages from being installed on particular platforms.

For those familiar with the platform attribute, the way to handle this example:

<file name="scripts/foo.bat" role="script" install-as="foo.bat" platform="windows">

is to in fact create two release sections. The file tag would then look like:

<file name="scripts/foo.bat" role="script">

and the release section would look like this:

<phprelease> <installconditions> <os>windows</os> </installconditions> <install name="scripts/foo.bat" as="foo.bat"/> </phprelease> <phprelease> <ignore name="scripts/foo.bat"/> </phprelease>

Note that the second <phprelease> tag could just as easily have had an <installconditions> tag containing <os>unix</os>, but this is unnecessary, as the second release will be processed on any system that is not a windows system.

PEAR_PackageFileManager : The Definitive Guide v 1.6.0 : November 17, 2006
Prev | Up | Next
<dir> | Home | tasks for <file>s


tasks for <file>s

tasks for <file>s
Prev Part IV. Reference Guide Next

Name

tasks for <file>s — specialized file installation and manipulation

Using tasks to customize file installation

Tasks provide a flexible and customizable way to manipulate file contents or to perform complex installation tasks (hence the name "tasks"). By default, PEAR comes with 4 tasks, but customized tasks can be added simply by adding a file into the PEAR/Tasks directory that follows the conventions of existing tasks. This page does not describe how to create a custom task, only how to use them in package.xml.

There are 3 basic tasks and 1 complex task distributed with PEAR. The basic tasks are "tasks:replace", "tasks:windowseol", and "tasks:unixeol". The complex task is "tasks:postinstallscript". "tasks:replace" is nearly identical to the old <replace> tag from package.xml 1.0, and does a text search-and-replace of a file's contents. "tasks:windowseol" and "tasks:unixeol" manipulate the line endings of a file to ensure that the correct line endings are in place for critical files like DOS .bat batch files and unix shell scripts. "tasks:postinstallscript" allows users to choose to run a script to perform further installation functions.

<tasks:replace> - customizing file contents

The replace task has 3 required attributes:

  1. type - This must be either package-info or pear-config. package-info replacements extract information from package.xml itself to use as the replacement text. pear-config replacements use the value of a configuration variable (as displayed by

    pear config-show

    ) as the text for replacement.

  2. from - Text to search for in a file. Traditionally, this text is enclosed in "@" to differentiate it from normal text, as in from="@version@"

  3. to - Abstract item to use as a replacement for all occurences of "from". package-info replacements can be one of version, release_date, release_state, release_license, release_notes, apiversion, name, summary, description, notes, time, date, and for some packages extends, srcpackage, srcuri, and providesextension.

Note that package-info replacements are performed at packaging time, so files contain package-info replacements inside a .tgz/.tar release. pear-config replacements can only occur on the installation system, and are performed at install-time.

<tasks:windowseol> - converting line endings to \r\n

This task can be used to enable packaging of windows-specific files (like DOS batch files) on a non-windows system, such as unix systems that convert line endings to \n. Note that this task is performed at package-time, as well as at install-time, so files will contain the correct line endings inside a .tgz/.tar release.

<tasks:unixeol> - converting line endings to \n

This task can be used to enable packaging of unix-specific files (like sh shell scripts) on a non-unix system, such as windows systems that convert line endings to \r\n. Note that this task is performed at package-time, as well as at install-time, so files will contain the correct line endings inside a .tgz/.tar release.

<tasks:postinstallscript> - extreme customization

The postinstallscript task informs the installer that the file it references is a post-installation script.

For security reasons, post-install scripts must be manually executed by the users, and as such the installer has special code that is separate from other tasks.

The <postinstallscript> tag may define parameters that are used by the installer to retrieve user input. In order to support both the web installer and the command-line installer, all processing of input is performed by PEAR and passed to the post-install script in a strict format. All you need to do is define the parameters using xml inside the <postinstallscript> tag.

Here is the xml representing a simple post-install script with parameters:

<tasks:postinstallscript>
 <tasks:paramgroup>
  <tasks:id>first</tasks:id>
  <tasks:param>
   <tasks:name>test</tasks:name>
   <tasks:prompt>Testing Thingy</tasks:prompt>
   <tasks:type>string</tasks:type>
  </tasks:param>
 </tasks:paramgroup>
</tasks:postinstallscript>

Note that the only type recognized at this stage is "string" but others will follow. A more complex example follows:

<tasks:postinstallscript>
 <tasks:paramgroup>
  <tasks:id>first</tasks:id>
  <tasks:instructions>The first group of questions relates
   primarily to your favorite color.  Answer wisely.
  </tasks:instructions>
  <tasks:param>
   <tasks:name>test</tasks:name>
   <tasks:prompt>Testing Thingy</tasks:prompt>
   <tasks:type>string</tasks:type>
   <tasks:default>hi</tasks:default>
  </tasks:param>
  <tasks:param>
   <tasks:name>test2</tasks:name>
   <tasks:prompt>Testing Thingy 2</tasks:prompt>
   <tasks:type>string</tasks:type>
  </tasks:param>
 </tasks:paramgroup>
 <tasks:paramgroup>
  <tasks:id>second</tasks:id>
  <tasks:name>first::test</tasks:name>
  <tasks:conditiontype>preg_match</tasks:conditiontype>
  <tasks:value>g+</tasks:value>
  <tasks:param>
   <tasks:name>test</tasks:name>
   <tasks:prompt>Testing Thingy a</tasks:prompt>
   <tasks:type>string</tasks:type>
   <tasks:default>hi</tasks:default>
  </tasks:param>
  <tasks:param>
   <tasks:name>test2</tasks:name>
   <tasks:prompt>Testing Thingy b</tasks:prompt>
   <tasks:type>string</tasks:type>
  </tasks:param>
 </tasks:paramgroup>
</tasks:postinstallscript>

This post-installation script has two parameter groups. The first parameter group has special instructions that are displayed to the user to assist in answering the required prompts. After the first group is processed, the second group is processed (naturally). However, in this case, the second group is a conditional parameter group. A conditional parameter group examines the user input from previous parameter groups and only displays its parameter prompts if a single parameter fits a test. The condition is defined by three tags, <tasks:name>, <tasks:conditiontype>, and <tasks:value>. Note that all three tags are required or xml validation will fail.

<tasks:name> is the parameter name from a previous parameter group. The format of name is groupID::parameterName, so as you see above, "first::test" refers to the <tasks:param> test from the <tasks:paramgroup> first.

<tasks:conditiontype> determines how the parameter input function will process the value of the parameter specified in <tasks:name>, and can be one of three values, "=" "!=" or "preg_match".

  • =: This (obviously) tests whether the parameters value is equal to the <tasks:value> tag

  • !=: This (obviously) tests whether the parameters value is not equal to the <tasks:value> tag

  • preg_match: This uses the content of the <tasks:value> tag as if it were the stuff between / and / in a preg_match function call. Do NOT include // brackets in the regular expression. In the <tasks:paramgroup> second, the value "g+" will become:

<?php
preg_match('/g+/', first::test value)
?>

PEAR_PackageFileManager : The Definitive Guide v 1.6.0 : November 17, 2006
Prev | Up | Next
<file> | Home | <compatible>


<compatible>

<compatible>
Prev Part IV. Reference Guide Next

Name

<compatible> — Alleviating strict versioning with <compatible>

Working with <recommended> dependency versions and <compatible>

The <compatible> tag is designed to be used with a <package> dependency that contains a <recommended> version tag from package pear.example.com/Bar version 1.3.0 like so:

<package>
 <name>Foo</name>
 <channel>pear.example.com</channel>
 <min>1.0.0</min>
 <recommended>1.5.2</recommended>
</package>

The above dependency can be translated into English as follows: "Use the package pear.example.com/Foo, but only versions 1.0.0 or newer. If pear.example.com/Foo is not installed, install version 1.5.2. If pear.example.com/Foo is installed and is not version 1.5.2, fail unless --force is specified, or pear.example.com/Foo is compatible with me."

That last clause "...or pear.example.com/Foo is compatible with me." is controlled by the <compatible> tag. If package Foo version 1.5.3's package.xml has a <compatible> like so:

<compatible>
 <name>Bar</name>
 <channel>pear.example.com</channel>
 <min>1.2.0</min>
 <max>1.3.0</max>
 <exclude>1.2.9</exclude>
</compatible>

This will instruct the installer that pear.example.com/Foo version 1.5.3 is compatible with pear.example.com/Bar versions 1.2.0 to 1.3.0 inclusive, but is not compatible with 1.2.9.

It is very important to note that only existing versions that have been tested with the package should be mentioned in the <compatible> tag. Future versions of pear.example.com/Bar should simply upgrade the <recommended> tag.

<compatible> may contain three versioning tags. The required <min> and <max> are used to define the range of tested and compatible versions, and <exclude> is used to exclude any versions within the range. In the example above, 1.3.0 and 1.2.0 are the highest and lowest versions that may be excluded. There can be an unlimited number of <compatible> tags inside a package.xml.

See also:

<package> dependencies

PEAR_PackageFileManager : The Definitive Guide v 1.6.0 : November 17, 2006
Prev | Up | Next
tasks for <file>s | Home | <dependencies>


<dependencies>

<dependencies>
Prev Part IV. Reference Guide Next

Name

<dependencies> — Dependency Specification in package.xml 2.0

Introduction to dependencies in package.xml 2.0

Dependencies are the most difficult aspect of programming. Using code written by other people can be a nightmare without simple ways to control bugs and API changes. Arguably, the handling of dependencies is PEAR's greatest strength, although there are many other nice features. Regardless of your personal opinion of the importance of dependencies, it is crucial to understand how to specify a dependency, and the different ways to ensure that your package is only used on systems that support it.

In package.xml 1.0, dependencies were relatively simple, but at the cost of usefulness. Specifying a dependency on a package for applications was actually dangerous. If you wished to limit an installed version of a package to a single version, it would mean preventing upgrade at any cost. package.xml 2.0 provides a simple way to enforce stricter dependency versioning without making upgrades onerous.

In package.xml 1.0, dependencies on PHP extensions like PECL extensions was near to a disaster. Extensions had to be present in the php.ini and loaded in memory in order to validate as being installed. This is often impossible, as a different php.ini is used for a production website versus the php.ini used for the pear installer. With package.xml 2.0, dependencies on a PECL-like extension is simple and straightforward, and only requires that the package be installed, and not that the extension be present in memory, although an older style extension dependency is also supported.

package.xml 1.0 supports two kinds of dependencies, required and optional. package.xml 2.0 also supports these two dependency types, but introduces a new kind of dependency concept: an optional dependency group. Dependency groups define a feature set. Instead of thinking "This package optionally depends on Net_FTP and optionally depends on Log" think "To remotely install packages, I need the remoteinstall feature, which needs Net_FTP and the Log package". This grouping allows defining sets of packages and extensions that comprise a feature and must be installed all at once for the feature to function properly.

package.xml 1.0 only supported php, package, and extension dependencies. package.xml 2.0 supports dependencies on php, package, extension, os, architecture, and PEAR installer. In addition, package.xml 2.0 supports depending on a static package located at a url, and depending on a package that provides an extension to PHP like PECL packages.

The PEAR installer dependency is not a dependency on the PEAR package, but a dependency on the currently running PEAR installer, and is more similar to a PHP dependency in that it requires the specified version to be running in memory. This is very useful for circumventing difficult bugs in the PEAR installer that render a package install useless.

Structure of <dependencies>

The <dependencies> tag re-organizes dependencies into groups and "extracts" attributes into tags. It also un-abbreviates words for clarity and human-readability. The following excerpt of a package.xml version 1.0:

<deps>
 <dep type="pkg" rel="ge" version="1.3.1">Archive_Tar</dep>
 <dep type="php" rel="ge" version="4.2.0"/>
 <dep type="pkg" rel="has" optional="yes">PEAR_Frontend_Web</dep>
</deps>

Approximately translates into this format in package.xml 2.0:

<dependencies>
 <required>
  <pearinstaller>
   <min>1.4.0a7</min>
  </pearinstaller>
  <php>
   <min>4.2.0</min>
   <max>6.0.0</max>
  </php>
  <package>
   <name>Archive_Tar</name>
   <channel>pear.php.net</channel>
   <min>1.3.1</min>
  </package>
 </required>
 <optional>
  <package>
   <name>PEAR_Frontend_Web</name>
   <channel>pear.php.net</channel>
  </package>
 </optional>
</dependencies>

These changes were made to simplify xml validation and parsing. Note that unlike package.xml 1.0, the <pearinstaller> and <php> dependencies are required in all package.xml. In addition the <min> tag is required in both <pearinstaller> and <php> dependencies.

<pearinstaller> dependencies

The <pearinstaller> dependency defines the minimum version of PEAR that can properly parse and install the package.xml containing it. As with all dependency tags that support versioning, these 4 tags are supported to define versioning:

  • <min> - minimum version of PEAR required to install this package.xml. This tag is required in all package.xml <pearinstaller> dependencies.

  • <max> - maximum version of PEAR installer supported. Use with caution! This tag will prevent the package from being installed by anyone with a newer version of PEAR!

  • <recommended> - recommended version of PEAR installer. This tag is used for strict version control. The installer will refuse to install a package without the --force option unless the version exactly matches recommended. This can be used to provide a level of extra security, as a package can be set to install using a version that is known to work without limiting future upgrades.

  • <exclude> - incompatible versions of PEAR installer. Use this to prevent the package from being installed by any PEAR version that cannot properly install the package. Multiple <exclude> tags may be used to exclude more than one version.

<php> dependencies

As with all dependency tags that support versioning, these 3 tags are supported to define versioning:

  • <min> - minimum version of PHP required to install this package.xml. This tag is required in all package.xml <php> dependencies.

  • <max> - maximum version of PHP supported.

  • <exclude> - incompatible versions of PHP. Use this to prevent the package from being installed by any PHP version that cannot properly work with the package. Multiple <exclude> tags may be used to exclude more than one version.

<subpackage> dependencies

Subpackage dependencies share the same xml format as package dependencies. The subpackage dependency should only be used if a package is split into more than one package. In other words, if the child package contains the same files as any earlier version of the parent package, the child package would normally conflict with the parent package because it would be attempting to overwrite the parent package's files with its own files.

A simple example should make this clear. Package Foo 1.0.0 contains Foo.php and Foo/Bar.php. Package Foo's developers decide to split Foo into two packages: Foo and Foo_Bar. Foo 1.1.0 contains foo.php, and Foo_Bar 0.1.0 contains Foo/Bar.php. Foo_Bar 0.1.0 conflicts directly with Foo 1.0.0, as both contain the file Foo/Bar.php.

If Foo has a subpackage dependency on Foo_Bar, then the installer will ignore the conflict between Foo 1.0.0's Foo/Bar.php and Foo_Bar 0.1.0's Foo/Bar.php just as it ignores the conflict between Foo 1.0.0's Foo.php and Foo 1.1.0's Foo.php.

<package> dependencies

Understandably, the <package> dependency is PEAR's most complex dependency. PEAR 1.4.0 supports 3 different kinds of package dependencies:

  1. Normal, traditional channel server-based package dependencies (same idea as package.xml 1.0).

  2. Dependencies on packages that provide PHP extensions (like PECL packages). (These can be both server-based and uri-based dependencies)

  3. Static, non-traditional uri-based package dependencies.

channel-based <package> depedendencies

The most common kind of package dependency is a channel-based dependency. This dependency from package.xml version 1.0:

<deps>
 <dep type="pkg" rel="has">PEAR</dep>
</deps>

translates to this dependency in package.xml version 2.0:

<dependencies>
 <required>
<!-- ... -->
  <package>
   <name>PEAR</name>
   <channel>pear.php.net</channel>
  </package>
 </required>
</dependencies>

Note that <channel> is a required tag for all typical package dependencies. Use pear.php.net for all packages that were packaged using package.xml 1.0, regardless of where they are downloaded from.

As with all dependency tags that support versioning, all standard versioning tags are supported (min, max, recommended, exclude). In addition, the <conflicts> tag is supported to create a negative dependency.

  • <min> - minimum version of a dependency. If the dependency package is installed, and is older than this version, installation will fail.

  • <max> - maximum version of a dependency. If the dependency package is installed, and is newer than this version, installation will fail.

  • <recommended> - recommended version of a dependency. This tag is used for strict version control. The installer will refuse to install a package without the --force option unless the version exactly matches recommended. This can be used to provide a level of extra security, as a package can be set to install using a version that is known to work without limiting future upgrades.

    Note that use of the <compatible> tag in the dependency's package.xml can be used to circumvent the installer's strictness. In essence, the <compatible> tag tells the installer that a dependent package is compatible with the current package, even though it is not the recommended version.

  • <exclude> - incompatible versions of a package. Multiple <exclude> tags may be used to exclude more than one version of a dependency.

  • <conflicts> - Negates the dependency. If the package is installed, it cannot satisfy the requirements of the dependency or installation will fail.

Here is a rough chart describing how to convert from package.xml 1.0 "rel" attributes to a package.xml 2.0 equivalent.

Table 14. Converting package.xml 1.0 package dependencies to package.xml 2.0

1.0 2.0 equivalent
           <dep type="pkg" rel="has">Foo</dep>

<package>
 <name>Foo</name>
 <channel>pear.php.net</channel>
</package>

           <dep type="pkg" rel="ge" version="1.0.0">Foo</dep>

<package>
 <name>Foo</name>
 <channel>pear.php.net</channel>
 <min>1.0.0</min>
</package>

           <dep type="pkg" rel="gt" version="1.0.0">Foo</dep>

<package>
 <name>Foo</name>
 <channel>pear.php.net</channel>
 <min>1.0.0</min>
 <exclude>1.0.0</exclude>
</package>

           <dep type="pkg" rel="le" version="1.0.0">Foo</dep>

<package>
 <name>Foo</name>
 <channel>pear.php.net</channel>
 <max>1.0.0</max>
</package>

           <dep type="pkg" rel="lt" version="1.0.0">Foo</dep>

<package>
 <name>Foo</name>
 <channel>pear.php.net</channel>
 <max>1.0.0</max>
 <exclude>1.0.0</exclude>
</package>

<dep type="pkg" rel="ge" version="1.0.0">Foo</dep>
<dep type="pkg" rel="le" version="1.9.0">Foo</dep>

<package>
 <name>Foo</name>
 <channel>pear.php.net</channel>
 <min>1.0.0</min>
 <max>1.9.0</max>
</package>

<dep type="pkg" rel="not">Foo</dep>

<package>
 <name>Foo</name>
 <channel>pear.php.net</channel>
 <conflicts/>
</package>

uri-based <package> dependencies

Let's look at uri-based package dependencies. Here is a simple example:

<package>
 <name>Foo<name>
 <uri>http://www.example.com/Foo-1.3.0</uri>
</package>

This dependency tells the installer to fetch http://www.example.com/Foo-1.3.0.tgz or http://www.example.com/Foo-1.3.0.tar (both must be available!) if the package Foo is not installed. All uri packages must contain a <uri> tag rather than a <channel> tag and will automatically belong to the pseudo-channel "__uri", but that is not important to the discussion of how to format the xml to create the uri-based package dependency.

uri-based package dependencies cannot contain any versioning information, as this is irrelevant: there is only one version possible with a static uri. uri-based dependencies can contain the <conflicts/> tag to specify an absolute conflict with the package, and the <providesextension> tag to specify an extension provided by the static package.

PEAR-style <package> dependencies vs. PECL-style <package> dependencies

package.xml 2.0 supports differentiating release types, and as such also supports dependencies on PECL-style packages that use the extbinrelease or extsrcrelease type.

To specify a dependency on a PHP extension that can be distributed as a PECL package, but could also be bundled with PHP by default, such as the PDO extension, use this dependency style:

<package>
 <name>PDO</name>
 <channel>pecl.php.net</channel>
 <min>0.3.1</min>
 <providesextension>PDO</providesextension>
</package>

The magic is in the <providesextension> tag. This tag tells the installer to take this process when validating the dependency:

  1. Is the extension "PDO" present in memory? If so, is it version 0.3.1 or higher?

  2. If not, is the user also installing pecl.php.net/PDO at the same time as this package? If so, is it version 0.3.1 or higher?

  3. If not, is pecl.php.net/PDO installed, and is the version 0.3.1 or higher?

If any of the three conditions above validate in the order specified, the dependency will be satisfied and installation will continue. This system allows users to use a different php.ini to install PHP extensions and also provides a fail-safe system to depend on extensions.

[Warning] Warning

<providesextension>, like all other extension-related functions in PHP, is case-sensitive. Do not use "pdo" for the "PDO" extension, or your dependency will always fail.

<extension> dependencies

As with all dependency tags that support versioning, all standard versioning tags are supported (min, max, recommended, exclude). In addition, the <conflicts> tag is supported to create a negative dependency.

  • <min> - minimum version of PHP extension to install this package.xml.

  • <max> - maximum version of PHP extension supported.

  • <recommended> - recommended version of PHP extension. This tag is used for strict version control. The installer will refuse to install a package without the --force option unless the version exactly matches recommended. This can be used to provide a level of extra security, as a package can be set to install using a version that is known to work without limiting future upgrades.

  • <exclude> - incompatible versions of PHP extension. Multiple <exclude> tags may be used to exclude more than one version.

  • <conflicts> - Negates the dependency. If the extension is present, it cannot satisfy the requirements of the dependency or installation will fail.

<os> dependencies

The OS dependency is used to restrict a package to both a particular class of OSes (like unix) and to a specific OS (like darwin, or freebsd). Here is an example:

<os>
 <name>linux</name>
</os>

To specify that a package can be installed on every OS except the one specified, use the <conflicts/> tag:

<os>
 <name>windows</name>
 <conflicts/>
</os>

Possible OS values are:

  • windows
  • unix
  • linux
  • freebsd
  • darwin (use for Mac OS X)
  • sunos
  • irix
  • hpux
  • aix

In addition, any esoteric OS that supports the php_uname function can be used. Note that the "unix" OS is defined as any of linux, freebsd, darwin, sunos, irix, hpux, or aix.

<arch> dependencies

The arch dependency is used to restrict a package to a specific os and processor architecture. Here is an example:

<arch>
 <pattern>linux-*-i386-*</pattern>
</arch>

To specify that a package can be installed on every architecture except the one specified, use the <conflicts/> tag:

<arch>
 <pattern>linux-*-i?86-*</pattern>
 <conflicts/>
</arch>

The arch pattern is defined by the OS_Guess->matchSignature method, and is as follows: sysname[-release[-cpu[-extra]]]. All segments within [] are optional, and the wildcard "*" can be used in all segments instead of a value. In addition, the "?" wildcard can be used to specify a single character that can match any value. i?86 will match i386, i686, i586 and so on.

sysname is the same as the os dependency, except unix is not supported.

release is the version of the operating system.

cpu is the specific cpu, and is typically i?86, sparc, powerpc.

extra is any other stuff on the end of php_uname, including the glibc version

PEAR_PackageFileManager : The Definitive Guide v 1.6.0 : November 17, 2006
Prev | Up | Next
<compatible> | Home | <usesrole>


<usesrole>

<usesrole>
Prev Part IV. Reference Guide Next

Name

<usesrole> — documenting custom file roles used in <contents>

Documenting custom file roles

Standard file roles provided by default with PEAR are:

  • php

  • data

  • doc

  • test

  • script

  • src

  • ext

If your package chooses to use a role provided by a third party that implements some more advanced file installation handling, all you need to do is specify the role in the xml for the <file> tag that contains it like so:

<file role="foo"/>

However, if a user does not have the package installed that provides the custom role "foo", then the error message on installation will simply say "unknown role 'foo'", which is not very helpful.

The <usesrole> tag instead prompts the installer to tell the user "this package uses the custom role 'foo', install package pear.example.com/Foo to use"

<usesrole>
 <role>foo</role>
 <package>Foo</package>
 <channel>pear.example.com</channel>
</usesrole>

Note that static URI packages (channel-less packages) are also supported:

<usesrole>
 <role>foo</role>
 <uri>http://pear.example.com/Foo-1.2.0</uri>
</usesrole>

PEAR_PackageFileManager : The Definitive Guide v 1.6.0 : November 17, 2006
Prev | Up | Next
<dependencies> | Home | <usestask>


<usestask>

<usestask>
Prev Part IV. Reference Guide Next

Name

<usestask> — documenting custom tasks used in <contents>

Documenting custom file tasks

Standard file tasks provided by default with PEAR are documented in this location.

If your package chooses to use a task provided by a third party, all you need to do is specify the task as part of the xml for the <file> tag that contains it like so:

<file role="php">
 <tasks:foo/>
</file>

However, if a user does not have the package installed that provides the custom task "foo", then the error message on installation will simply say "unknown task 'foo'", which is not very helpful.

The <usestask> tag instead prompts the installer to tell the user "this package uses the custom task 'foo', install package pear.example.com/Foo to use"

<usestask>
 <task>foo</task>
 <package>Foo</package>
 <channel>pear.example.com</channel>
</usestask>

Note that static URI packages (channel-less packages) are also supported:

<usestask>
 <task>foo</task>
 <uri>http://pear.example.com/Foo-1.2.0</uri>
</usesrole>

PEAR_PackageFileManager : The Definitive Guide v 1.6.0 : November 17, 2006
Prev | Up | Next
<usesrole> | Home | <phprelease>, <extbinrelease>, <extsrcrelease>, <bundle>


<phprelease>, <extbinrelease>, <extsrcrelease>, <bundle>

<phprelease>, <extbinrelease>, <extsrcrelease>, <bundle>
Prev Part IV. Reference Guide

Name

<phprelease>, <extbinrelease>, <extsrcrelease>, <bundle> — specifying the content type of a release

Documenting release type

In package.xml 1.0, there was one release type. package.xml 2.0 provides much finer control over the kind of release in order to provide three new release types: extension binary release, extension source release, and package bundle release.

All of the normal release tags (phprelease, extsrcrelease, extbinrelease) may contain two optional sections, <installconditions> and <filelist>. The purpose of these sections is to allow specification of different file install groups based on the target OS for installation, or other common install conditions.

To be clear: in package.xml, there was 1 <release> tag. package.xml 2.0 allows several adjacent release tags, each specifying a different install set. This actually simplifies complex installation filesets by separating the contents listing of the tarball from how the installer should manipulate this listing. Debugging installation file sets should be much simpler with this change.

The <filelist> tag can contain only two possible tags, <install> and <ignore>. install has two required attributes, "name" and "as". The install tag is used in the same manner as package.xml's install-as attribute for the <file>, to specify a new installation location for a file in the contents list. The ignore tag is used to completely ignore a file.

The <installconditions> tag can contain 4 tags whose format can be found in the <dependencies> section: <php>, <extension>, <os>, and <arch>. Each tag can appear exactly once except for the extension tag, which can appear limitless times.

The php tag is used to specify a php version or range of versions that an install set should be valid with.

The extension tag is used to specify extensions that must be present for an install set to be valid.

The os tag is used to specify an OS that must be present for an install set to be valid. Note that unix can be used to match all flavors, and linux can be used to match all linux-based OSes. Darwin should be used for Mac OS X, and * can be used to match all operating systems.

The arch tag is used to specify a uname string or portion of a uname string that must match in order for the install set to be valid.

<phprelease>

The phprelease release type is designed for PEAR-style PHP script package releases. It causes a few specific validation changes. First of all, the <contents> tag must contain <file> and <dir> tags. The only valid roles for files are role="php", role="data", role="doc", and role="test" plus any custom roles that the user has installed for use in php releases.

<extsrcrelease>

The extsrcrelease release type is for PECL-style PHP extension releases that must be compiled in order to be useable. It causes a few specific validation changes. First of all, the <contents> tag must contain <file> and <dir> tags. The only valid roles for files are role="src", role="data", role="doc", and role="test" plus any custom roles that the user has installed for use in extension source releases.

In addition, the <providesextension> tag must be present in order to document the name of the extension this package provides must be in the package.xml as well.

<extbinrelease>

The extbinrelease release type is for PECL-style PHP Extension binary releases that are pre-compiled. It causes a few specific validation changes. First of all, the <contents> tag must contain <file> and <dir> tags. The only valid roles for files are role="ext", role="data", role="doc", and role="test" plus any custom roles that the user has installed for use in extension binary releases.

In addition, the <srcpackage> or <srcuri> and the <providesextension> tags must be present in order to document the package that provides extension source for this binary release, and the name of the extension this package provides must be in the package.xml as well.

<bundle>

The bundle release type is designed to allow packaging several other package releases into a single bundle of packages that will all be installed at the same time. This can be used to distribute a complete application as one tarball, or to distribute a library of packages in a single tarball.

Unlike the other release types, a bundle release's <contents> tag must contain only the <bundledpackage> tag. The contents of the bundledpackage should be release names like "Foo-1.2.3.tgz"

In addition, the <bundle/> tag must be empty.

PEAR_PackageFileManager : The Definitive Guide v 1.6.0 : November 17, 2006
Prev | Up
<usestask> | Home