/trunk/jrest/lib/Log.php |
---|
New file |
0,0 → 1,196 |
<?php |
//declare(encoding='UTF-8'); |
/** |
* Classe permettant de logger des messages dans les fichier situés dans le dossier de log |
* |
* PHP Version 5 |
* |
* @category PHP |
* @package Framework |
* @author aurelien <aurelien@tela-botanica.org> |
* @copyright 2009 Tela-Botanica |
* @license http://www.cecill.info/licences/Licence_CeCILL_V2-fr.txt Licence CECILL |
* @version SVN: <svn_id> |
* @link /doc/framework/ |
*/ |
class Log { |
/** |
* Tableau associatif stockant les descripteurs de fichiers |
*/ |
private static $fichiersLog = array(); |
/** |
* Chemin de base du dossier log de l'application |
*/ |
private static $cheminLogs = '/home/aurelien/Logs/'; |
/** |
* Booleen indiquant si l'on peut correctement écrire dans les fichiers de logs |
*/ |
private static $droitLogger = true; |
/** |
* Zone horaire (pour éviter des avertissements dans les dates) |
*/ |
private static $timeZone = ''; |
/** |
* Taille maximum d'un fichier de log avant que celui ne soit archivé (en octets) |
*/ |
private static $tailleMax = 10000; |
/** |
* séparateur de chemin |
*/ |
private static $sd = DIRECTORY_SEPARATOR; |
/** |
* Extension des fichiers de log |
*/ |
private static $ext = '.log'; |
/** |
* La classe registre se contient elle-même, (pour le pattern singleton) |
*/ |
private static $log; |
/** |
* Constructeur par défaut, privé, car on accède à la classe par le getInstance |
*/ |
private function __construct() { |
self::$sd = $sd; |
// gestion de la timezone pour éviter des erreurs |
if(function_exists("date_default_timezone_set") and function_exists("date_default_timezone_get")) { |
date_default_timezone_set(self::$timeZone); |
} |
if(!is_dir(self::$cheminLogs) || !is_writable(self::$cheminLogs)) { |
self::desactiverEcriture(); |
} |
} |
public static function setCheminLog($nouveauCheminLogs) { |
self::$cheminLogs = $nouveauCheminLogs; |
} |
public static function getCheminLog() { |
return self::$cheminLogs; |
} |
public static function setTimeZone($NouvelleTimeZone) { |
self::$timeZone = $NouvelleTimeZone; |
} |
public static function setTailleMax($nouvelleTailleMax) { |
self::$tailleMax = $nouvelleTailleMax; |
} |
/** |
* Fonction qui renvoie l'instance de classe en assurant son unicité, c'est l'unique méthode qui doit être |
* utilisée pour récupérer l'objet Registre |
* @return Log le gestionnaire de log en cours |
*/ |
public static function getInstance() { |
if (self::$log instanceof Log) { |
return self::$log; |
} |
self::$log = new Log(); |
return self::$log; |
} |
/** |
* Ajoute une entrée au log spécifié par le paramètre $nomFichier |
* @param string $nomFichier le nom du fichier dans lequel écrire |
*/ |
public static function ajouterEntree($nomFichier,$entree,$mode='a+') { |
if(self::$droitLogger) { |
$date = "\n"."\n".date('d m Y H:i')."\n" ; |
// si le fichier est déjà dans le tableau et qu'on peut y écrire |
if(self::verifierOuvrirFichier($nomFichier,$mode)) { |
// on y écrit le message de log |
fwrite(self::$fichiersLog[$nomFichier],$date.$entree); |
// on vérifie si le fichier ne dépasse pas la taille maximale |
self::verifierTailleFichierOuArchiver($nomFichier); |
} else { |
// sinon on interdit l'écriture |
self::desactiverEcriture($nomFichier); |
} |
} |
} |
/** |
* Vide un fichier log indiqué |
* @param string $nomFichier le nom du fichier à vider |
*/ |
public static function viderLog($nomFichier) { |
ajouterEntree($nomFichier,'','w'); |
} |
/** |
* Vérifie la présence d'un fichier dans le tableau, ses droits d'écriture, |
* l'ouvre si nécessaire |
* @param string $nomFichier le nom du fichier dont on doit vérifier la présence |
* @return boolean true si le fichier est ouvert ou maintenant accessible, false sinon |
*/ |
public static function verifierOuvrirFichier($nomFichier,$mode) { |
// le fichier est il déjà ouvert ? |
if(in_array($nomFichier,self::$fichiersLog)) { |
// si oui peut on y écrire ? |
if(is_writable(self::$cheminLogs.$nomFichier.self::$ext)) { |
// si oui on renvoie le descripteur |
return true; |
} |
return false; |
} else { |
// sinon on l'ouvre |
$fp = @fopen(self::$cheminLogs.$nomFichier.self::$ext,$mode); |
// si l'ouverture a réussi et si le fichier a les droits d'écriture |
if($fp && is_writable(self::$cheminLogs.$nomFichier.self::$ext)) { |
// si oui on renvoie le descripteur qu'on ajoute au tableau |
self::$fichiersLog[$nomFichier] = $fp; |
return true; |
} |
return false; |
} |
} |
/** |
* Vérifie la taille d'un fichier donné et si celle ci est trop importante |
* archive le fichier de log |
* @param string $nomFichier nom du fichier à vérifier |
*/ |
private static function verifierTailleFichierOuArchiver($nomFichier) { |
if(filesize(self::$cheminLogs.$nomFichier.self::$ext) > self::$tailleMax) { |
rename(self::$cheminLogs.$nomFichier.self::$ext,self::$cheminLogs.$nomFichier.date('d_m_Y_H:i').self::$ext); |
self::ajouterEntree($nomFichier,''); |
} |
} |
/** |
* Désactive l'écriture du log et envoie un message au gestionnaire d'erreurs |
* @param string $nomFichier le nom du fichier qui a causé l'erreur |
*/ |
private static function desactiverEcriture($nomFichier = '') { |
self::$droitLogger = false; |
if($nomFichier != '') { |
$fichierDossier = 'fichier '.$nomFichier ; |
} else { |
$fichierDossier = 'dossier des logs'; |
} |
} |
/** |
* destructeur de classe, ferme les descripteurs ouverts |
*/ |
public function __destruct() { |
foreach(self::$fichiersLog as $nomFichier => $fp) { |
fclose($fp); |
} |
} |
} |
?> |
/trunk/jrest/lib/Spreadsheet/Excel/Writer/Format.php |
---|
New file |
0,0 → 1,940 |
<?php |
/* |
* Module written/ported by Xavier Noguer <xnoguer@rezebra.com> |
* |
* The majority of this is _NOT_ my code. I simply ported it from the |
* PERL Spreadsheet::WriteExcel module. |
* |
* The author of the Spreadsheet::WriteExcel module is John McNamara |
* <jmcnamara@cpan.org> |
* |
* I _DO_ maintain this code, and John McNamara has nothing to do with the |
* porting of this code to PHP. Any questions directly related to this |
* class library should be directed to me. |
* |
* License Information: |
* |
* Spreadsheet_Excel_Writer: A library for generating Excel Spreadsheets |
* Copyright (c) 2002-2003 Xavier Noguer xnoguer@rezebra.com |
* |
* This library is free software; you can redistribute it and/or |
* modify it under the terms of the GNU Lesser General Public |
* License as published by the Free Software Foundation; either |
* version 2.1 of the License, or (at your option) any later version. |
* |
* This library is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
* Lesser General Public License for more details. |
* |
* You should have received a copy of the GNU Lesser General Public |
* License along with this library; if not, write to the Free Software |
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
*/ |
require_once('PEAR.php'); |
/** |
* Class for generating Excel XF records (formats) |
* |
* @author Xavier Noguer <xnoguer@rezebra.com> |
* @category FileFormats |
* @package Spreadsheet_Excel_Writer |
*/ |
class Spreadsheet_Excel_Writer_Format extends PEAR |
{ |
/** |
* The index given by the workbook when creating a new format. |
* @var integer |
*/ |
var $_xf_index; |
/** |
* Index to the FONT record. |
* @var integer |
*/ |
var $font_index; |
/** |
* The font name (ASCII). |
* @var string |
*/ |
var $_font_name; |
/** |
* Height of font (1/20 of a point) |
* @var integer |
*/ |
var $_size; |
/** |
* Bold style |
* @var integer |
*/ |
var $_bold; |
/** |
* Bit specifiying if the font is italic. |
* @var integer |
*/ |
var $_italic; |
/** |
* Index to the cell's color |
* @var integer |
*/ |
var $_color; |
/** |
* The text underline property |
* @var integer |
*/ |
var $_underline; |
/** |
* Bit specifiying if the font has strikeout. |
* @var integer |
*/ |
var $_font_strikeout; |
/** |
* Bit specifiying if the font has outline. |
* @var integer |
*/ |
var $_font_outline; |
/** |
* Bit specifiying if the font has shadow. |
* @var integer |
*/ |
var $_font_shadow; |
/** |
* 2 bytes specifiying the script type for the font. |
* @var integer |
*/ |
var $_font_script; |
/** |
* Byte specifiying the font family. |
* @var integer |
*/ |
var $_font_family; |
/** |
* Byte specifiying the font charset. |
* @var integer |
*/ |
var $_font_charset; |
/** |
* An index (2 bytes) to a FORMAT record (number format). |
* @var integer |
*/ |
var $_num_format; |
/** |
* Bit specifying if formulas are hidden. |
* @var integer |
*/ |
var $_hidden; |
/** |
* Bit specifying if the cell is locked. |
* @var integer |
*/ |
var $_locked; |
/** |
* The three bits specifying the text horizontal alignment. |
* @var integer |
*/ |
var $_text_h_align; |
/** |
* Bit specifying if the text is wrapped at the right border. |
* @var integer |
*/ |
var $_text_wrap; |
/** |
* The three bits specifying the text vertical alignment. |
* @var integer |
*/ |
var $_text_v_align; |
/** |
* 1 bit, apparently not used. |
* @var integer |
*/ |
var $_text_justlast; |
/** |
* The two bits specifying the text rotation. |
* @var integer |
*/ |
var $_rotation; |
/** |
* The cell's foreground color. |
* @var integer |
*/ |
var $_fg_color; |
/** |
* The cell's background color. |
* @var integer |
*/ |
var $_bg_color; |
/** |
* The cell's background fill pattern. |
* @var integer |
*/ |
var $_pattern; |
/** |
* Style of the bottom border of the cell |
* @var integer |
*/ |
var $_bottom; |
/** |
* Color of the bottom border of the cell. |
* @var integer |
*/ |
var $_bottom_color; |
/** |
* Style of the top border of the cell |
* @var integer |
*/ |
var $_top; |
/** |
* Color of the top border of the cell. |
* @var integer |
*/ |
var $_top_color; |
/** |
* Style of the left border of the cell |
* @var integer |
*/ |
var $_left; |
/** |
* Color of the left border of the cell. |
* @var integer |
*/ |
var $_left_color; |
/** |
* Style of the right border of the cell |
* @var integer |
*/ |
var $_right; |
/** |
* Color of the right border of the cell. |
* @var integer |
*/ |
var $_right_color; |
/** |
* Constructor |
* |
* @access public |
* @param integer $index the XF index for the format. |
* @param array $properties array with properties to be set on initialization. |
*/ |
function Spreadsheet_Excel_Writer_Format($index = 0,$properties = array()) |
{ |
$this->_xf_index = $index; |
$this->font_index = 0; |
$this->_font_name = 'Arial'; |
$this->_size = 10; |
$this->_bold = 0x0190; |
$this->_italic = 0; |
$this->_color = 0x7FFF; |
$this->_underline = 0; |
$this->_font_strikeout = 0; |
$this->_font_outline = 0; |
$this->_font_shadow = 0; |
$this->_font_script = 0; |
$this->_font_family = 0; |
$this->_font_charset = 0; |
$this->_num_format = 0; |
$this->_hidden = 0; |
$this->_locked = 1; |
$this->_text_h_align = 0; |
$this->_text_wrap = 0; |
$this->_text_v_align = 2; |
$this->_text_justlast = 0; |
$this->_rotation = 0; |
$this->_fg_color = 0x40; |
$this->_bg_color = 0x41; |
$this->_pattern = 0; |
$this->_bottom = 0; |
$this->_top = 0; |
$this->_left = 0; |
$this->_right = 0; |
$this->_bottom_color = 0x40; |
$this->_top_color = 0x40; |
$this->_left_color = 0x40; |
$this->_right_color = 0x40; |
// Set properties passed to Spreadsheet_Excel_Writer_Workbook::addFormat() |
foreach($properties as $property => $value) |
{ |
if(method_exists($this,'set'.ucwords($property))) |
{ |
$method_name = 'set'.ucwords($property); |
$this->$method_name($value); |
} |
} |
} |
/** |
* Generate an Excel BIFF XF record (style or cell). |
* |
* @param string $style The type of the XF record ('style' or 'cell'). |
* @return string The XF record |
*/ |
function getXf($style) |
{ |
// Set the type of the XF record and some of the attributes. |
if ($style == "style") { |
$style = 0xFFF5; |
} |
else { |
$style = $this->_locked; |
$style |= $this->_hidden << 1; |
} |
// Flags to indicate if attributes have been set. |
$atr_num = ($this->_num_format != 0)?1:0; |
$atr_fnt = ($this->font_index != 0)?1:0; |
$atr_alc = ($this->_text_wrap)?1:0; |
$atr_bdr = ($this->_bottom || |
$this->_top || |
$this->_left || |
$this->_right)?1:0; |
$atr_pat = (($this->_fg_color != 0x40) || |
($this->_bg_color != 0x41) || |
$this->_pattern)?1:0; |
$atr_prot = 0; |
// Zero the default border colour if the border has not been set. |
if ($this->_bottom == 0) { |
$this->_bottom_color = 0; |
} |
if ($this->_top == 0) { |
$this->_top_color = 0; |
} |
if ($this->_right == 0) { |
$this->_right_color = 0; |
} |
if ($this->_left == 0) { |
$this->_left_color = 0; |
} |
$record = 0x00E0; // Record identifier |
$length = 0x0010; // Number of bytes to follow |
$ifnt = $this->font_index; // Index to FONT record |
$ifmt = $this->_num_format; // Index to FORMAT record |
$align = $this->_text_h_align; // Alignment |
$align |= $this->_text_wrap << 3; |
$align |= $this->_text_v_align << 4; |
$align |= $this->_text_justlast << 7; |
$align |= $this->_rotation << 8; |
$align |= $atr_num << 10; |
$align |= $atr_fnt << 11; |
$align |= $atr_alc << 12; |
$align |= $atr_bdr << 13; |
$align |= $atr_pat << 14; |
$align |= $atr_prot << 15; |
$icv = $this->_fg_color; // fg and bg pattern colors |
$icv |= $this->_bg_color << 7; |
$fill = $this->_pattern; // Fill and border line style |
$fill |= $this->_bottom << 6; |
$fill |= $this->_bottom_color << 9; |
$border1 = $this->_top; // Border line style and color |
$border1 |= $this->_left << 3; |
$border1 |= $this->_right << 6; |
$border1 |= $this->_top_color << 9; |
$border2 = $this->_left_color; // Border color |
$border2 |= $this->_right_color << 7; |
$header = pack("vv", $record, $length); |
$data = pack("vvvvvvvv", $ifnt, $ifmt, $style, $align, |
$icv, $fill, |
$border1, $border2); |
return($header.$data); |
} |
/** |
* Generate an Excel BIFF FONT record. |
* |
* @return string The FONT record |
*/ |
function getFont() |
{ |
$dyHeight = $this->_size * 20; // Height of font (1/20 of a point) |
$icv = $this->_color; // Index to color palette |
$bls = $this->_bold; // Bold style |
$sss = $this->_font_script; // Superscript/subscript |
$uls = $this->_underline; // Underline |
$bFamily = $this->_font_family; // Font family |
$bCharSet = $this->_font_charset; // Character set |
$rgch = $this->_font_name; // Font name |
$cch = strlen($rgch); // Length of font name |
$record = 0x31; // Record identifier |
$length = 0x0F + $cch; // Record length |
$reserved = 0x00; // Reserved |
$grbit = 0x00; // Font attributes |
if ($this->_italic) { |
$grbit |= 0x02; |
} |
if ($this->_font_strikeout) { |
$grbit |= 0x08; |
} |
if ($this->_font_outline) { |
$grbit |= 0x10; |
} |
if ($this->_font_shadow) { |
$grbit |= 0x20; |
} |
$header = pack("vv", $record, $length); |
$data = pack("vvvvvCCCCC", $dyHeight, $grbit, $icv, $bls, |
$sss, $uls, $bFamily, |
$bCharSet, $reserved, $cch); |
return($header . $data. $this->_font_name); |
} |
/** |
* Returns a unique hash key for a font. |
* Used by Spreadsheet_Excel_Writer_Workbook::_storeAllFonts() |
* |
* The elements that form the key are arranged to increase the probability of |
* generating a unique key. Elements that hold a large range of numbers |
* (eg. _color) are placed between two binary elements such as _italic |
* |
* @return string A key for this font |
*/ |
function getFontKey() |
{ |
$key = "$this->_font_name$this->_size"; |
$key .= "$this->_font_script$this->_underline"; |
$key .= "$this->_font_strikeout$this->_bold$this->_font_outline"; |
$key .= "$this->_font_family$this->_font_charset"; |
$key .= "$this->_font_shadow$this->_color$this->_italic"; |
$key = str_replace(" ","_",$key); |
return ($key); |
} |
/** |
* Returns the index used by Spreadsheet_Excel_Writer_Worksheet::_XF() |
* |
* @return integer The index for the XF record |
*/ |
function getXfIndex() |
{ |
return($this->_xf_index); |
} |
/** |
* Used in conjunction with the set_xxx_color methods to convert a color |
* string into a number. Color range is 0..63 but we will restrict it |
* to 8..63 to comply with Gnumeric. Colors 0..7 are repeated in 8..15. |
* |
* @access private |
* @param string $name_color name of the color (i.e.: 'blue', 'red', etc..). Optional. |
* @return integer The color index |
*/ |
function _getColor($name_color = '') |
{ |
$colors = array( |
'aqua' => 0x0F, |
'cyan' => 0x0F, |
'black' => 0x08, |
'blue' => 0x0C, |
'brown' => 0x10, |
'magenta' => 0x0E, |
'fuchsia' => 0x0E, |
'gray' => 0x17, |
'grey' => 0x17, |
'green' => 0x11, |
'lime' => 0x0B, |
'navy' => 0x12, |
'orange' => 0x35, |
'purple' => 0x14, |
'red' => 0x0A, |
'silver' => 0x16, |
'white' => 0x09, |
'yellow' => 0x0D |
); |
// Return the default color, 0x7FFF, if undef, |
if($name_color == '') { |
return(0x7FFF); |
} |
// or the color string converted to an integer, |
if(isset($colors[$name_color])) { |
return($colors[$name_color]); |
} |
// or the default color if string is unrecognised, |
if(preg_match("/\D/",$name_color)) { |
return(0x7FFF); |
} |
// or an index < 8 mapped into the correct range, |
if($name_color < 8) { |
return($name_color + 8); |
} |
// or the default color if arg is outside range, |
if($name_color > 63) { |
return(0x7FFF); |
} |
// or an integer in the valid range |
return($name_color); |
} |
/** |
* Set cell alignment. |
* |
* @access public |
* @param string $location alignment for the cell ('left', 'right', etc...). |
*/ |
function setAlign($location) |
{ |
if (preg_match("/\d/",$location)) { |
return; // Ignore numbers |
} |
$location = strtolower($location); |
if ($location == 'left') { |
$this->_text_h_align = 1; |
} |
if ($location == 'centre') { |
$this->_text_h_align = 2; |
} |
if ($location == 'center') { |
$this->_text_h_align = 2; |
} |
if ($location == 'right') { |
$this->_text_h_align = 3; |
} |
if ($location == 'fill') { |
$this->_text_h_align = 4; |
} |
if ($location == 'justify') { |
$this->_text_h_align = 5; |
} |
if ($location == 'merge') { |
$this->_text_h_align = 6; |
} |
if ($location == 'equal_space') { // For T.K. |
$this->_text_h_align = 7; |
} |
if ($location == 'top') { |
$this->_text_v_align = 0; |
} |
if ($location == 'vcentre') { |
$this->_text_v_align = 1; |
} |
if ($location == 'vcenter') { |
$this->_text_v_align = 1; |
} |
if ($location == 'bottom') { |
$this->_text_v_align = 2; |
} |
if ($location == 'vjustify') { |
$this->_text_v_align = 3; |
} |
if ($location == 'vequal_space') { // For T.K. |
$this->_text_v_align = 4; |
} |
} |
/** |
* This is an alias for the unintuitive setAlign('merge') |
* |
* @access public |
*/ |
function setMerge() |
{ |
$this->setAlign('merge'); |
} |
/** |
* Sets the boldness of the text. |
* Bold has a range 100..1000. |
* 0 (400) is normal. 1 (700) is bold. |
* |
* @access public |
* @param integer $weight Weight for the text, 0 maps to 400 (normal text), |
1 maps to 700 (bold text). Valid range is: 100-1000. |
It's Optional, default is 1 (bold). |
*/ |
function setBold($weight = 1) |
{ |
if($weight == 1) { |
$weight = 0x2BC; // Bold text |
} |
if($weight == 0) { |
$weight = 0x190; // Normal text |
} |
if($weight < 0x064) { |
$weight = 0x190; // Lower bound |
} |
if($weight > 0x3E8) { |
$weight = 0x190; // Upper bound |
} |
$this->_bold = $weight; |
} |
/************************************ |
* FUNCTIONS FOR SETTING CELLS BORDERS |
*/ |
/** |
* Sets the width for the bottom border of the cell |
* |
* @access public |
* @param integer $style style of the cell border. 1 => thin, 2 => thick. |
*/ |
function setBottom($style) |
{ |
$this->_bottom = $style; |
} |
/** |
* Sets the width for the top border of the cell |
* |
* @access public |
* @param integer $style style of the cell top border. 1 => thin, 2 => thick. |
*/ |
function setTop($style) |
{ |
$this->_top = $style; |
} |
/** |
* Sets the width for the left border of the cell |
* |
* @access public |
* @param integer $style style of the cell left border. 1 => thin, 2 => thick. |
*/ |
function setLeft($style) |
{ |
$this->_left = $style; |
} |
/** |
* Sets the width for the right border of the cell |
* |
* @access public |
* @param integer $style style of the cell right border. 1 => thin, 2 => thick. |
*/ |
function setRight($style) |
{ |
$this->_right = $style; |
} |
/** |
* Set cells borders to the same style |
* |
* @access public |
* @param integer $style style to apply for all cell borders. 1 => thin, 2 => thick. |
*/ |
function setBorder($style) |
{ |
$this->setBottom($style); |
$this->setTop($style); |
$this->setLeft($style); |
$this->setRight($style); |
} |
/******************************************* |
* FUNCTIONS FOR SETTING CELLS BORDERS COLORS |
*/ |
/** |
* Sets all the cell's borders to the same color |
* |
* @access public |
* @param mixed $color The color we are setting. Either a string (like 'blue'), |
* or an integer (range is [8...63]). |
*/ |
function setBorderColor($color) |
{ |
$this->setBottomColor($color); |
$this->setTopColor($color); |
$this->setLeftColor($color); |
$this->setRightColor($color); |
} |
/** |
* Sets the cell's bottom border color |
* |
* @access public |
* @param mixed $color either a string (like 'blue'), or an integer (range is [8...63]). |
*/ |
function setBottomColor($color) |
{ |
$value = $this->_getColor($color); |
$this->_bottom_color = $value; |
} |
/** |
* Sets the cell's top border color |
* |
* @access public |
* @param mixed $color either a string (like 'blue'), or an integer (range is [8...63]). |
*/ |
function setTopColor($color) |
{ |
$value = $this->_getColor($color); |
$this->_top_color = $value; |
} |
/** |
* Sets the cell's left border color |
* |
* @access public |
* @param mixed $color either a string (like 'blue'), or an integer (range is [8...63]). |
*/ |
function setLeftColor($color) |
{ |
$value = $this->_getColor($color); |
$this->_left_color = $value; |
} |
/** |
* Sets the cell's right border color |
* |
* @access public |
* @param mixed $color either a string (like 'blue'), or an integer (range is [8...63]). |
*/ |
function setRightColor($color) |
{ |
$value = $this->_getColor($color); |
$this->_right_color = $value; |
} |
/** |
* Sets the cell's foreground color |
* |
* @access public |
* @param mixed $color either a string (like 'blue'), or an integer (range is [8...63]). |
*/ |
function setFgColor($color) |
{ |
$value = $this->_getColor($color); |
$this->_fg_color = $value; |
} |
/** |
* Sets the cell's background color |
* |
* @access public |
* @param mixed $color either a string (like 'blue'), or an integer (range is [8...63]). |
*/ |
function setBgColor($color) |
{ |
$value = $this->_getColor($color); |
$this->_bg_color = $value; |
} |
/** |
* Sets the cell's color |
* |
* @access public |
* @param mixed $color either a string (like 'blue'), or an integer (range is [8...63]). |
*/ |
function setColor($color) |
{ |
$value = $this->_getColor($color); |
$this->_color = $value; |
} |
/** |
* Sets the fill pattern attribute of a cell |
* |
* @access public |
* @param integer $arg Optional. Defaults to 1. Meaningful values are: 0-18, |
* 0 meaning no background. |
*/ |
function setPattern($arg = 1) |
{ |
$this->_pattern = $arg; |
} |
/** |
* Sets the underline of the text |
* |
* @access public |
* @param integer $underline The value for underline. Possible values are: |
* 1 => underline, 2 => double underline. |
*/ |
function setUnderline($underline) |
{ |
$this->_underline = $underline; |
} |
/** |
* Sets the font style as italic |
* |
* @access public |
*/ |
function setItalic() |
{ |
$this->_italic = 1; |
} |
/** |
* Sets the font size |
* |
* @access public |
* @param integer $size The font size (in pixels I think). |
*/ |
function setSize($size) |
{ |
$this->_size = $size; |
} |
/** |
* Sets text wrapping |
* |
* @access public |
*/ |
function setTextWrap() |
{ |
$this->_text_wrap = 1; |
} |
/** |
* Sets the orientation of the text |
* |
* @access public |
* @param integer $angle The rotation angle for the text (clockwise). Possible |
values are: 0, 90, 270 and -1 for stacking top-to-bottom. |
*/ |
function setTextRotation($angle) |
{ |
switch ($angle) |
{ |
case 0: |
$this->_rotation = 0; |
break; |
case 90: |
$this->_rotation = 3; |
break; |
case 270: |
$this->_rotation = 2; |
break; |
case -1: |
$this->_rotation = 1; |
break; |
default : |
$this->raiseError("Invalid value for angle.". |
" Possible values are: 0, 90, 270 and -1 ". |
"for stacking top-to-bottom."); |
$this->_rotation = 0; |
break; |
} |
} |
/** |
* Sets the numeric format. |
* It can be date, time, currency, etc... |
* |
* @access public |
* @param integer $num_format The numeric format. |
*/ |
function setNumFormat($num_format) |
{ |
$this->_num_format = $num_format; |
} |
/** |
* Sets font as strikeout. |
* |
* @access public |
*/ |
function setStrikeOut() |
{ |
$this->_font_strikeout = 1; |
} |
/** |
* Sets outlining for a font. |
* |
* @access public |
*/ |
function setOutLine() |
{ |
$this->_font_outline = 1; |
} |
/** |
* Sets font as shadow. |
* |
* @access public |
*/ |
function setShadow() |
{ |
$this->_font_shadow = 1; |
} |
/** |
* Sets the script type of the text |
* |
* @access public |
* @param integer $script The value for script type. Possible values are: |
* 1 => superscript, 2 => subscript. |
*/ |
function setScript($script) |
{ |
$this->_font_script = $script; |
} |
/** |
* Unlocks a cell. Useful for unprotecting particular cells of a protected sheet. |
* |
* @access public |
*/ |
function setUnLocked() |
{ |
$this->_locked = 0; |
} |
} |
?> |
/trunk/jrest/lib/Spreadsheet/Excel/Writer/Worksheet.php |
---|
New file |
0,0 → 1,3095 |
<?php |
/* |
* Module written/ported by Xavier Noguer <xnoguer@rezebra.com> |
* |
* The majority of this is _NOT_ my code. I simply ported it from the |
* PERL Spreadsheet::WriteExcel module. |
* |
* The author of the Spreadsheet::WriteExcel module is John McNamara |
* <jmcnamara@cpan.org> |
* |
* I _DO_ maintain this code, and John McNamara has nothing to do with the |
* porting of this code to PHP. Any questions directly related to this |
* class library should be directed to me. |
* |
* License Information: |
* |
* Spreadsheet_Excel_Writer: A library for generating Excel Spreadsheets |
* Copyright (c) 2002-2003 Xavier Noguer xnoguer@rezebra.com |
* |
* This library is free software; you can redistribute it and/or |
* modify it under the terms of the GNU Lesser General Public |
* License as published by the Free Software Foundation; either |
* version 2.1 of the License, or (at your option) any later version. |
* |
* This library is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
* Lesser General Public License for more details. |
* |
* You should have received a copy of the GNU Lesser General Public |
* License along with this library; if not, write to the Free Software |
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
*/ |
require_once('Parser.php'); |
require_once('BIFFwriter.php'); |
/** |
* Class for generating Excel Spreadsheets |
* |
* @author Xavier Noguer <xnoguer@rezebra.com> |
* @category FileFormats |
* @package Spreadsheet_Excel_Writer |
*/ |
class Spreadsheet_Excel_Writer_Worksheet extends Spreadsheet_Excel_Writer_BIFFwriter |
{ |
/** |
* Name of the Worksheet |
* @var string |
*/ |
var $name; |
/** |
* Index for the Worksheet |
* @var integer |
*/ |
var $index; |
/** |
* Reference to the (default) Format object for URLs |
* @var object Format |
*/ |
var $_url_format; |
/** |
* Reference to the parser used for parsing formulas |
* @var object Format |
*/ |
var $_parser; |
/** |
* Filehandle to the temporary file for storing data |
* @var resource |
*/ |
var $_filehandle; |
/** |
* Boolean indicating if we are using a temporary file for storing data |
* @var bool |
*/ |
var $_using_tmpfile; |
/** |
* Maximum number of rows for an Excel spreadsheet (BIFF5) |
* @var integer |
*/ |
var $_xls_rowmax; |
/** |
* Maximum number of columns for an Excel spreadsheet (BIFF5) |
* @var integer |
*/ |
var $_xls_colmax; |
/** |
* Maximum number of characters for a string (LABEL record in BIFF5) |
* @var integer |
*/ |
var $_xls_strmax; |
/** |
* First row for the DIMENSIONS record |
* @var integer |
* @see storeDimensions() |
*/ |
var $_dim_rowmin; |
/** |
* Last row for the DIMENSIONS record |
* @var integer |
* @see storeDimensions() |
*/ |
var $_dim_rowmax; |
/** |
* First column for the DIMENSIONS record |
* @var integer |
* @see storeDimensions() |
*/ |
var $_dim_colmin; |
/** |
* Last column for the DIMENSIONS record |
* @var integer |
* @see storeDimensions() |
*/ |
var $_dim_colmax; |
/** |
* Array containing format information for columns |
* @var array |
*/ |
var $_colinfo; |
/** |
* Array containing the selected area for the worksheet |
* @var array |
*/ |
var $_selection; |
/** |
* Array containing the panes for the worksheet |
* @var array |
*/ |
var $_panes; |
/** |
* The active pane for the worksheet |
* @var integer |
*/ |
var $_active_pane; |
/** |
* Bit specifying if panes are frozen |
* @var integer |
*/ |
var $_frozen; |
/** |
* Bit specifying if the worksheet is selected |
* @var integer |
*/ |
var $selected; |
/** |
* The paper size (for printing) (DOCUMENT!!!) |
* @var integer |
*/ |
var $_paper_size; |
/** |
* Bit specifying paper orientation (for printing). 0 => landscape, 1 => portrait |
* @var integer |
*/ |
var $_orientation; |
/** |
* The page header caption |
* @var string |
*/ |
var $_header; |
/** |
* The page footer caption |
* @var string |
*/ |
var $_footer; |
/** |
* The horizontal centering value for the page |
* @var integer |
*/ |
var $_hcenter; |
/** |
* The vertical centering value for the page |
* @var integer |
*/ |
var $_vcenter; |
/** |
* The margin for the header |
* @var float |
*/ |
var $_margin_head; |
/** |
* The margin for the footer |
* @var float |
*/ |
var $_margin_foot; |
/** |
* The left margin for the worksheet in inches |
* @var float |
*/ |
var $_margin_left; |
/** |
* The right margin for the worksheet in inches |
* @var float |
*/ |
var $_margin_right; |
/** |
* The top margin for the worksheet in inches |
* @var float |
*/ |
var $_margin_top; |
/** |
* The bottom margin for the worksheet in inches |
* @var float |
*/ |
var $_margin_bottom; |
/** |
* First row to reapeat on each printed page |
* @var integer |
*/ |
var $title_rowmin; |
/** |
* Last row to reapeat on each printed page |
* @var integer |
*/ |
var $title_rowmax; |
/** |
* First column to reapeat on each printed page |
* @var integer |
*/ |
var $title_colmin; |
/** |
* First row of the area to print |
* @var integer |
*/ |
var $print_rowmin; |
/** |
* Last row to of the area to print |
* @var integer |
*/ |
var $print_rowmax; |
/** |
* First column of the area to print |
* @var integer |
*/ |
var $print_colmin; |
/** |
* Last column of the area to print |
* @var integer |
*/ |
var $print_colmax; |
/** |
* Constructor |
* |
* @param string $name The name of the new worksheet |
* @param integer $index The index of the new worksheet |
* @param mixed &$activesheet The current activesheet of the workbook we belong to |
* @param mixed &$firstsheet The first worksheet in the workbook we belong to |
* @param mixed &$url_format The default format for hyperlinks |
* @param mixed &$parser The formula parser created for the Workbook |
*/ |
function Spreadsheet_Excel_Writer_Worksheet($name, $index, &$activesheet, |
&$firstsheet, &$url_format, |
&$parser) |
{ |
// It needs to call its parent's constructor explicitly |
$this->Spreadsheet_Excel_Writer_BIFFwriter(); |
$rowmax = 65536; // 16384 in Excel 5 |
$colmax = 256; |
$this->name = $name; |
$this->index = $index; |
$this->activesheet = &$activesheet; |
$this->firstsheet = &$firstsheet; |
$this->_url_format = &$url_format; |
$this->_parser = &$parser; |
//$this->ext_sheets = array(); |
$this->_filehandle = ""; |
$this->_using_tmpfile = true; |
//$this->fileclosed = 0; |
//$this->offset = 0; |
$this->_xls_rowmax = $rowmax; |
$this->_xls_colmax = $colmax; |
$this->_xls_strmax = 255; |
$this->_dim_rowmin = $rowmax + 1; |
$this->_dim_rowmax = 0; |
$this->_dim_colmin = $colmax + 1; |
$this->_dim_colmax = 0; |
$this->_colinfo = array(); |
$this->_selection = array(0,0,0,0); |
$this->_panes = array(); |
$this->_active_pane = 3; |
$this->_frozen = 0; |
$this->selected = 0; |
$this->_paper_size = 0x0; |
$this->_orientation = 0x1; |
$this->_header = ''; |
$this->_footer = ''; |
$this->_hcenter = 0; |
$this->_vcenter = 0; |
$this->_margin_head = 0.50; |
$this->_margin_foot = 0.50; |
$this->_margin_left = 0.75; |
$this->_margin_right = 0.75; |
$this->_margin_top = 1.00; |
$this->_margin_bottom = 1.00; |
$this->title_rowmin = NULL; |
$this->title_rowmax = NULL; |
$this->title_colmin = NULL; |
$this->title_colmax = NULL; |
$this->print_rowmin = NULL; |
$this->print_rowmax = NULL; |
$this->print_colmin = NULL; |
$this->print_colmax = NULL; |
$this->_print_gridlines = 1; |
$this->_print_headers = 0; |
$this->_fit_page = 0; |
$this->_fit_width = 0; |
$this->_fit_height = 0; |
$this->_hbreaks = array(); |
$this->_vbreaks = array(); |
$this->_protect = 0; |
$this->_password = NULL; |
$this->col_sizes = array(); |
$this->row_sizes = array(); |
$this->_zoom = 100; |
$this->_print_scale = 100; |
$this->_initialize(); |
} |
/** |
* Open a tmp file to store the majority of the Worksheet data. If this fails, |
* for example due to write permissions, store the data in memory. This can be |
* slow for large files. |
* |
* @access private |
*/ |
function _initialize() |
{ |
// Open tmp file for storing Worksheet data |
$fh = tmpfile(); |
if ( $fh) { |
// Store filehandle |
$this->_filehandle = $fh; |
} |
else { |
// If tmpfile() fails store data in memory |
$this->_using_tmpfile = false; |
} |
} |
/** |
* Add data to the beginning of the workbook (note the reverse order) |
* and to the end of the workbook. |
* |
* @access public |
* @see Spreadsheet_Excel_Writer_Workbook::storeWorkbook() |
* @param array $sheetnames The array of sheetnames from the Workbook this |
* worksheet belongs to |
*/ |
function close($sheetnames) |
{ |
$num_sheets = count($sheetnames); |
/*********************************************** |
* Prepend in reverse order!! |
*/ |
// Prepend the sheet dimensions |
$this->storeDimensions(); |
// Prepend the sheet password |
$this->_storePassword(); |
// Prepend the sheet protection |
$this->_storeProtect(); |
// Prepend the page setup |
$this->_storeSetup(); |
// Prepend the bottom margin |
$this->_storeMarginBottom(); |
// Prepend the top margin |
$this->_storeMarginTop(); |
// Prepend the right margin |
$this->_storeMarginRight(); |
// Prepend the left margin |
$this->_storeMarginLeft(); |
// Prepend the page vertical centering |
$this->_storeVcenter(); |
// Prepend the page horizontal centering |
$this->_storeHcenter(); |
// Prepend the page footer |
$this->_storeFooter(); |
// Prepend the page header |
$this->_storeHeader(); |
// Prepend the vertical page breaks |
$this->_storeVbreak(); |
// Prepend the horizontal page breaks |
$this->_storeHbreak(); |
// Prepend WSBOOL |
$this->_storeWsbool(); |
// Prepend GRIDSET |
$this->_storeGridset(); |
// Prepend PRINTGRIDLINES |
$this->_storePrintGridlines(); |
// Prepend PRINTHEADERS |
$this->_storePrintHeaders(); |
// Prepend EXTERNSHEET references |
for ($i = $num_sheets; $i > 0; $i--) |
{ |
$sheetname = $sheetnames[$i-1]; |
$this->_storeExternsheet($sheetname); |
} |
// Prepend the EXTERNCOUNT of external references. |
$this->_storeExterncount($num_sheets); |
// Prepend the COLINFO records if they exist |
if (!empty($this->_colinfo)) |
{ |
for($i=0; $i < count($this->_colinfo); $i++) { |
$this->_storeColinfo($this->_colinfo[$i]); |
} |
$this->_storeDefcol(); |
} |
// Prepend the BOF record |
$this->_storeBof(0x0010); |
/* |
* End of prepend. Read upwards from here. |
***********************************************/ |
// Append |
$this->_storeWindow2(); |
$this->_storeZoom(); |
if (!empty($this->_panes)) { |
$this->_storePanes($this->_panes); |
} |
$this->_storeSelection($this->_selection); |
$this->_storeEof(); |
} |
/** |
* Retrieve the worksheet name. |
* This is usefull when creating worksheets without a name. |
* |
* @access public |
* @return string The worksheet's name |
*/ |
function getName() |
{ |
return $this->name; |
} |
/** |
* Retrieves data from memory in one chunk, or from disk in $buffer |
* sized chunks. |
* |
* @return string The data |
*/ |
function getData() |
{ |
$buffer = 4096; |
// Return data stored in memory |
if (isset($this->_data)) |
{ |
$tmp = $this->_data; |
unset($this->_data); |
$fh = $this->_filehandle; |
if ($this->_using_tmpfile) { |
fseek($fh, 0); |
} |
return($tmp); |
} |
// Return data stored on disk |
if ($this->_using_tmpfile) |
{ |
if ($tmp = fread($this->_filehandle, $buffer)) { |
return($tmp); |
} |
} |
// No data to return |
return(''); |
} |
/** |
* Set this worksheet as a selected worksheet, |
* i.e. the worksheet has its tab highlighted. |
* |
* @access public |
*/ |
function select() |
{ |
$this->selected = 1; |
} |
/** |
* Set this worksheet as the active worksheet, |
* i.e. the worksheet that is displayed when the workbook is opened. |
* Also set it as selected. |
* |
* @access public |
*/ |
function activate() |
{ |
$this->selected = 1; |
$this->activesheet = $this->index; |
} |
/** |
* Set this worksheet as the first visible sheet. |
* This is necessary when there are a large number of worksheets and the |
* activated worksheet is not visible on the screen. |
* |
* @access public |
*/ |
function setFirstSheet() |
{ |
$this->firstsheet = $this->index; |
} |
/** |
* Set the worksheet protection flag |
* to prevent accidental modification and to |
* hide formulas if the locked and hidden format properties have been set. |
* |
* @access public |
* @param string $password The password to use for protecting the sheet. |
*/ |
function protect($password) |
{ |
$this->_protect = 1; |
$this->_password = $this->_encodePassword($password); |
} |
/** |
* Set the width of a single column or a range of columns. |
* |
* @access public |
* @param integer $firstcol first column on the range |
* @param integer $lastcol last column on the range |
* @param integer $width width to set |
* @param mixed $format The optional XF format to apply to the columns |
* @param integer $hidden The optional hidden atribute |
*/ |
function setColumn($firstcol, $lastcol, $width, $format = 0, $hidden = 0) |
{ |
$this->_colinfo[] = array($firstcol, $lastcol, $width, &$format, $hidden); |
// Set width to zero if column is hidden |
$width = ($hidden) ? 0 : $width; |
for($col = $firstcol; $col <= $lastcol; $col++) { |
$this->col_sizes[$col] = $width; |
} |
} |
/** |
* Set which cell or cells are selected in a worksheet |
* |
* @access public |
* @param integer $first_row first row in the selected quadrant |
* @param integer $first_column first column in the selected quadrant |
* @param integer $last_row last row in the selected quadrant |
* @param integer $last_column last column in the selected quadrant |
*/ |
function setSelection($first_row,$first_column,$last_row,$last_column) |
{ |
$this->_selection = array($first_row,$first_column,$last_row,$last_column); |
} |
/** |
* Set panes and mark them as frozen. |
* |
* @access public |
* @param array $panes This is the only parameter received and is composed of the following: |
* 0 => Vertical split position, |
* 1 => Horizontal split position |
* 2 => Top row visible |
* 3 => Leftmost column visible |
* 4 => Active pane |
*/ |
function freezePanes($panes) |
{ |
$this->_frozen = 1; |
$this->_panes = $panes; |
} |
/** |
* Set panes and mark them as unfrozen. |
* |
* @access public |
* @param array $panes This is the only parameter received and is composed of the following: |
* 0 => Vertical split position, |
* 1 => Horizontal split position |
* 2 => Top row visible |
* 3 => Leftmost column visible |
* 4 => Active pane |
*/ |
function thawPanes($panes) |
{ |
$this->_frozen = 0; |
$this->_panes = $panes; |
} |
/** |
* Set the page orientation as portrait. |
* |
* @access public |
*/ |
function setPortrait() |
{ |
$this->_orientation = 1; |
} |
/** |
* Set the page orientation as landscape. |
* |
* @access public |
*/ |
function setLandscape() |
{ |
$this->_orientation = 0; |
} |
/** |
* Set the paper type. Ex. 1 = US Letter, 9 = A4 |
* |
* @access public |
* @param integer $size The type of paper size to use |
*/ |
function setPaper($size = 0) |
{ |
$this->_paper_size = $size; |
} |
/** |
* Set the page header caption and optional margin. |
* |
* @access public |
* @param string $string The header text |
* @param float $margin optional head margin in inches. |
*/ |
function setHeader($string,$margin = 0.50) |
{ |
if (strlen($string) >= 255) { |
//carp 'Header string must be less than 255 characters'; |
return; |
} |
$this->_header = $string; |
$this->_margin_head = $margin; |
} |
/** |
* Set the page footer caption and optional margin. |
* |
* @access public |
* @param string $string The footer text |
* @param float $margin optional foot margin in inches. |
*/ |
function setFooter($string,$margin = 0.50) |
{ |
if (strlen($string) >= 255) { |
//carp 'Footer string must be less than 255 characters'; |
return; |
} |
$this->_footer = $string; |
$this->_margin_foot = $margin; |
} |
/** |
* Center the page horinzontally. |
* |
* @access public |
* @param integer $center the optional value for centering. Defaults to 1 (center). |
*/ |
function centerHorizontally($center = 1) |
{ |
$this->_hcenter = $center; |
} |
/** |
* Center the page vertically. |
* |
* @access public |
* @param integer $center the optional value for centering. Defaults to 1 (center). |
*/ |
function centerVertically($center = 1) |
{ |
$this->_vcenter = $center; |
} |
/** |
* Set all the page margins to the same value in inches. |
* |
* @access public |
* @param float $margin The margin to set in inches |
*/ |
function setMargins($margin) |
{ |
$this->setMarginLeft($margin); |
$this->setMarginRight($margin); |
$this->setMarginTop($margin); |
$this->setMarginBottom($margin); |
} |
/** |
* Set the left and right margins to the same value in inches. |
* |
* @access public |
* @param float $margin The margin to set in inches |
*/ |
function setMargins_LR($margin) |
{ |
$this->setMarginLeft($margin); |
$this->setMarginRight($margin); |
} |
/** |
* Set the top and bottom margins to the same value in inches. |
* |
* @access public |
* @param float $margin The margin to set in inches |
*/ |
function setMargins_TB($margin) |
{ |
$this->setMarginTop($margin); |
$this->setMarginBottom($margin); |
} |
/** |
* Set the left margin in inches. |
* |
* @access public |
* @param float $margin The margin to set in inches |
*/ |
function setMarginLeft($margin = 0.75) |
{ |
$this->_margin_left = $margin; |
} |
/** |
* Set the right margin in inches. |
* |
* @access public |
* @param float $margin The margin to set in inches |
*/ |
function setMarginRight($margin = 0.75) |
{ |
$this->_margin_right = $margin; |
} |
/** |
* Set the top margin in inches. |
* |
* @access public |
* @param float $margin The margin to set in inches |
*/ |
function setMarginTop($margin = 1.00) |
{ |
$this->_margin_top = $margin; |
} |
/** |
* Set the bottom margin in inches. |
* |
* @access public |
* @param float $margin The margin to set in inches |
*/ |
function setMarginBottom($margin = 1.00) |
{ |
$this->_margin_bottom = $margin; |
} |
/** |
* Set the rows to repeat at the top of each printed page. |
* |
* @access public |
* @param integer $first_row First row to repeat |
* @param integer $last_row Last row to repeat. Optional. |
*/ |
function repeatRows($first_row, $last_row = NULL) |
{ |
$this->title_rowmin = $first_row; |
if (isset($last_row)) { //Second row is optional |
$this->title_rowmax = $last_row; |
} |
else { |
$this->title_rowmax = $first_row; |
} |
} |
/** |
* Set the columns to repeat at the left hand side of each printed page. |
* |
* @access public |
* @param integer $first_col First column to repeat |
* @param integer $last_col Last column to repeat. Optional. |
*/ |
function repeatColumns($first_col, $last_col = NULL) |
{ |
$this->title_colmin = $first_col; |
if (isset($last_col)) { // Second col is optional |
$this->title_colmax = $last_col; |
} |
else { |
$this->title_colmax = $first_col; |
} |
} |
/** |
* Set the area of each worksheet that will be printed. |
* |
* @access public |
* @param integer $first_row First row of the area to print |
* @param integer $first_col First column of the area to print |
* @param integer $last_row Last row of the area to print |
* @param integer $last_col Last column of the area to print |
*/ |
function printArea($first_row, $first_col, $last_row, $last_col) |
{ |
$this->print_rowmin = $first_row; |
$this->print_colmin = $first_col; |
$this->print_rowmax = $last_row; |
$this->print_colmax = $last_col; |
} |
/** |
* Set the option to hide gridlines on the printed page. |
* |
* @access public |
*/ |
function hideGridlines() |
{ |
$this->_print_gridlines = 0; |
} |
/** |
* Set the option to print the row and column headers on the printed page. |
* |
* @access public |
* @param integer $print Whether to print the headers or not. Defaults to 1 (print). |
*/ |
function printRowColHeaders($print = 1) |
{ |
$this->_print_headers = $print; |
} |
/** |
* Set the vertical and horizontal number of pages that will define the maximum area printed. |
* It doesn't seem to work with OpenOffice. |
* |
* @access public |
* @param integer $width Maximun width of printed area in pages |
* @param integer $height Maximun heigth of printed area in pages |
* @see setPrintScale() |
*/ |
function fitToPages($width, $height) |
{ |
$this->_fit_page = 1; |
$this->_fit_width = $width; |
$this->_fit_height = $height; |
} |
/** |
* Store the horizontal page breaks on a worksheet (for printing). |
* The breaks represent the row after which the break is inserted. |
* |
* @access public |
* @param array $breaks Array containing the horizontal page breaks |
*/ |
function setHPagebreaks($breaks) |
{ |
foreach($breaks as $break) { |
array_push($this->_hbreaks,$break); |
} |
} |
/** |
* Store the vertical page breaks on a worksheet (for printing). |
* The breaks represent the column after which the break is inserted. |
* |
* @access public |
* @param array $breaks Array containing the vertical page breaks |
*/ |
function setVPagebreaks($breaks) |
{ |
foreach($breaks as $break) { |
array_push($this->_vbreaks,$break); |
} |
} |
/** |
* Set the worksheet zoom factor. |
* |
* @access public |
* @param integer $scale The zoom factor |
*/ |
function setZoom($scale = 100) |
{ |
// Confine the scale to Excel's range |
if ($scale < 10 or $scale > 400) |
{ |
$this->raiseError("Zoom factor $scale outside range: 10 <= zoom <= 400"); |
$scale = 100; |
} |
$this->_zoom = floor($scale); |
} |
/** |
* Set the scale factor for the printed page. |
* It turns off the "fit to page" option |
* |
* @access public |
* @param integer $scale The optional scale factor. Defaults to 100 |
*/ |
function setPrintScale($scale = 100) |
{ |
// Confine the scale to Excel's range |
if ($scale < 10 or $scale > 400) |
{ |
$this->raiseError("Print scale $scale outside range: 10 <= zoom <= 400"); |
$scale = 100; |
} |
// Turn off "fit to page" option |
$this->_fit_page = 0; |
$this->_print_scale = floor($scale); |
} |
/** |
* Map to the appropriate write method acording to the token recieved. |
* |
* @access public |
* @param integer $row The row of the cell we are writing to |
* @param integer $col The column of the cell we are writing to |
* @param mixed $token What we are writing |
* @param mixed $format The optional format to apply to the cell |
*/ |
function write($row, $col, $token, $format = 0) |
{ |
// Check for a cell reference in A1 notation and substitute row and column |
/*if ($_[0] =~ /^\D/) { |
@_ = $this->_substituteCellref(@_); |
}*/ |
// Match number |
if (preg_match("/^([+-]?)(?=\d|\.\d)\d*(\.\d*)?([Ee]([+-]?\d+))?$/",$token)) { |
return $this->writeNumber($row,$col,$token,$format); |
} |
// Match http or ftp URL |
elseif (preg_match("/^[fh]tt?p:\/\//",$token)) { |
return $this->writeUrl($row, $col, $token, $format); |
} |
// Match mailto: |
elseif (preg_match("/^mailto:/",$token)) { |
return $this->writeUrl($row, $col, $token, $format); |
} |
// Match internal or external sheet link |
elseif (preg_match("/^(?:in|ex)ternal:/",$token)) { |
return $this->writeUrl($row, $col, $token, $format); |
} |
// Match formula |
elseif (preg_match("/^=/",$token)) { |
return $this->writeFormula($row, $col, $token, $format); |
} |
// Match formula |
elseif (preg_match("/^@/",$token)) { |
return $this->writeFormula($row, $col, $token, $format); |
} |
// Match blank |
elseif ($token == '') { |
return $this->writeBlank($row,$col,$format); |
} |
// Default: match string |
else { |
return $this->writeString($row,$col,$token,$format); |
} |
} |
/** |
* Write an array of values as a row |
* |
* @access public |
* @param |
* @return |
*/ |
function writeRow($row, $col, $val, $format=0) |
{ |
if (is_array($val)) { |
foreach($val as $v) { |
if (is_array($v)) { |
$this->writeCol($row, $col, $v, $format); |
} else { |
$this->write($row, $col, $v, $format); |
} |
$col++; |
} |
} else { |
$retval = new PEAR_Error('$val needs to be an array'); |
} |
return($retval); |
} |
/** |
* Write an array of values as a column |
* |
* @access public |
* @param |
* @return |
*/ |
function writeCol($row, $col, $val, $format=0) |
{ |
if (is_array($val)) { |
foreach($val as $v) { |
$this->write($row, $col, $v, $format); |
$row++; |
} |
} else { |
$retval = new PEAR_Error('$val needs to be an array'); |
} |
return($retval); |
} |
/** |
* Returns an index to the XF record in the workbook |
* |
* @access private |
* @param mixed &$format The optional XF format |
* @return integer The XF record index |
*/ |
function _XF(&$format) |
{ |
if ($format != 0) { |
return($format->getXfIndex()); |
} |
else { |
return(0x0F); |
} |
} |
/****************************************************************************** |
******************************************************************************* |
* |
* Internal methods |
*/ |
/** |
* Store Worksheet data in memory using the parent's class append() or to a |
* temporary file, the default. |
* |
* @access private |
* @param string $data The binary data to append |
*/ |
function _append($data) |
{ |
if ($this->_using_tmpfile) |
{ |
// Add CONTINUE records if necessary |
if (strlen($data) > $this->_limit) { |
$data = $this->_addContinue($data); |
} |
fwrite($this->_filehandle,$data); |
$this->_datasize += strlen($data); |
} |
else { |
parent::_append($data); |
} |
} |
/** |
* Substitute an Excel cell reference in A1 notation for zero based row and |
* column values in an argument list. |
* |
* Ex: ("A4", "Hello") is converted to (3, 0, "Hello"). |
* |
* @access private |
* @param string $cell The cell reference. Or range of cells. |
* @return array |
*/ |
function _substituteCellref($cell) |
{ |
$cell = strtoupper($cell); |
// Convert a column range: 'A:A' or 'B:G' |
if (preg_match("/([A-I]?[A-Z]):([A-I]?[A-Z])/",$cell,$match)) { |
list($no_use, $col1) = $this->_cellToRowcol($match[1] .'1'); // Add a dummy row |
list($no_use, $col2) = $this->_cellToRowcol($match[2] .'1'); // Add a dummy row |
return(array($col1, $col2)); |
} |
// Convert a cell range: 'A1:B7' |
if (preg_match("/\$?([A-I]?[A-Z]\$?\d+):\$?([A-I]?[A-Z]\$?\d+)/",$cell,$match)) { |
list($row1, $col1) = $this->_cellToRowcol($match[1]); |
list($row2, $col2) = $this->_cellToRowcol($match[2]); |
return(array($row1, $col1, $row2, $col2)); |
} |
// Convert a cell reference: 'A1' or 'AD2000' |
if (preg_match("/\$?([A-I]?[A-Z]\$?\d+)/",$cell)) { |
list($row1, $col1) = $this->_cellToRowcol($match[1]); |
return(array($row1, $col1)); |
} |
// TODO use real error codes |
$this->raiseError("Unknown cell reference $cell", 0, PEAR_ERROR_DIE); |
} |
/** |
* Convert an Excel cell reference in A1 notation to a zero based row and column |
* reference; converts C1 to (0, 2). |
* |
* @access private |
* @param string $cell The cell reference. |
* @return array containing (row, column) |
*/ |
function _cellToRowcol($cell) |
{ |
preg_match("/\$?([A-I]?[A-Z])\$?(\d+)/",$cell,$match); |
$col = $match[1]; |
$row = $match[2]; |
// Convert base26 column string to number |
$chars = split('', $col); |
$expn = 0; |
$col = 0; |
while ($chars) { |
$char = array_pop($chars); // LS char first |
$col += (ord($char) -ord('A') +1) * pow(26,$expn); |
$expn++; |
} |
// Convert 1-index to zero-index |
$row--; |
$col--; |
return(array($row, $col)); |
} |
/** |
* Based on the algorithm provided by Daniel Rentz of OpenOffice. |
* |
* @access private |
* @param string $plaintext The password to be encoded in plaintext. |
* @return string The encoded password |
*/ |
function _encodePassword($plaintext) |
{ |
$password = 0x0000; |
$i = 1; // char position |
// split the plain text password in its component characters |
$chars = preg_split('//', $plaintext, -1, PREG_SPLIT_NO_EMPTY); |
foreach($chars as $char) |
{ |
$value = ord($char) << $i; // shifted ASCII value |
$rotated_bits = $value >> 15; // rotated bits beyond bit 15 |
$value &= 0x7fff; // first 15 bits |
$password ^= ($value | $rotated_bits); |
$i++; |
} |
$password ^= strlen($plaintext); |
$password ^= 0xCE4B; |
return($password); |
} |
/****************************************************************************** |
******************************************************************************* |
* |
* BIFF RECORDS |
*/ |
/** |
* Write a double to the specified row and column (zero indexed). |
* An integer can be written as a double. Excel will display an |
* integer. $format is optional. |
* |
* Returns 0 : normal termination |
* -2 : row or column out of range |
* |
* @access public |
* @param integer $row Zero indexed row |
* @param integer $col Zero indexed column |
* @param float $num The number to write |
* @param mixed $format The optional XF format |
* @return integer |
*/ |
function writeNumber($row, $col, $num, $format = 0) |
{ |
$record = 0x0203; // Record identifier |
$length = 0x000E; // Number of bytes to follow |
$xf = $this->_XF($format); // The cell format |
// Check that row and col are valid and store max and min values |
if ($row >= $this->_xls_rowmax) |
{ |
return(-2); |
} |
if ($col >= $this->_xls_colmax) |
{ |
return(-2); |
} |
if ($row < $this->_dim_rowmin) |
{ |
$this->_dim_rowmin = $row; |
} |
if ($row > $this->_dim_rowmax) |
{ |
$this->_dim_rowmax = $row; |
} |
if ($col < $this->_dim_colmin) |
{ |
$this->_dim_colmin = $col; |
} |
if ($col > $this->_dim_colmax) |
{ |
$this->_dim_colmax = $col; |
} |
$header = pack("vv", $record, $length); |
$data = pack("vvv", $row, $col, $xf); |
$xl_double = pack("d", $num); |
if ($this->_byte_order) // if it's Big Endian |
{ |
$xl_double = strrev($xl_double); |
} |
$this->_append($header.$data.$xl_double); |
return(0); |
} |
/** |
* Write a string to the specified row and column (zero indexed). |
* NOTE: there is an Excel 5 defined limit of 255 characters. |
* $format is optional. |
* Returns 0 : normal termination |
* -2 : row or column out of range |
* -3 : long string truncated to 255 chars |
* |
* @access public |
* @param integer $row Zero indexed row |
* @param integer $col Zero indexed column |
* @param string $str The string to write |
* @param mixed $format The XF format for the cell |
* @return integer |
*/ |
function writeString($row, $col, $str, $format = 0) |
{ |
$strlen = strlen($str); |
$record = 0x0204; // Record identifier |
$length = 0x0008 + $strlen; // Bytes to follow |
$xf = $this->_XF($format); // The cell format |
$str_error = 0; |
// Check that row and col are valid and store max and min values |
if ($row >= $this->_xls_rowmax) |
{ |
return(-2); |
} |
if ($col >= $this->_xls_colmax) |
{ |
return(-2); |
} |
if ($row < $this->_dim_rowmin) |
{ |
$this->_dim_rowmin = $row; |
} |
if ($row > $this->_dim_rowmax) |
{ |
$this->_dim_rowmax = $row; |
} |
if ($col < $this->_dim_colmin) |
{ |
$this->_dim_colmin = $col; |
} |
if ($col > $this->_dim_colmax) |
{ |
$this->_dim_colmax = $col; |
} |
if ($strlen > $this->_xls_strmax) // LABEL must be < 255 chars |
{ |
$str = substr($str, 0, $this->_xls_strmax); |
$length = 0x0008 + $this->_xls_strmax; |
$strlen = $this->_xls_strmax; |
$str_error = -3; |
} |
$header = pack("vv", $record, $length); |
$data = pack("vvvv", $row, $col, $xf, $strlen); |
$this->_append($header.$data.$str); |
return($str_error); |
} |
/** |
* Writes a note associated with the cell given by the row and column. |
* NOTE records don't have a length limit. |
* |
* @access public |
* @param integer $row Zero indexed row |
* @param integer $col Zero indexed column |
* @param string $note The note to write |
*/ |
function writeNote($row, $col, $note) |
{ |
$note_length = strlen($note); |
$record = 0x001C; // Record identifier |
$max_length = 2048; // Maximun length for a NOTE record |
//$length = 0x0006 + $note_length; // Bytes to follow |
// Check that row and col are valid and store max and min values |
if ($row >= $this->_xls_rowmax) |
{ |
return(-2); |
} |
if ($col >= $this->_xls_colmax) |
{ |
return(-2); |
} |
if ($row < $this->_dim_rowmin) |
{ |
$this->_dim_rowmin = $row; |
} |
if ($row > $this->_dim_rowmax) |
{ |
$this->_dim_rowmax = $row; |
} |
if ($col < $this->_dim_colmin) |
{ |
$this->_dim_colmin = $col; |
} |
if ($col > $this->_dim_colmax) |
{ |
$this->_dim_colmax = $col; |
} |
// Length for this record is no more than 2048 + 6 |
$length = 0x0006 + min($note_length, 2048); |
$header = pack("vv", $record, $length); |
$data = pack("vvv", $row, $col, $note_length); |
$this->_append($header.$data.substr($note, 0, 2048)); |
for($i = $max_length; $i < $note_length; $i += $max_length) |
{ |
$chunk = substr($note, $i, $max_length); |
$length = 0x0006 + strlen($chunk); |
$header = pack("vv", $record, $length); |
$data = pack("vvv", -1, 0, strlen($chunk)); |
$this->_append($header.$data.$chunk); |
} |
return(0); |
} |
/** |
* Write a blank cell to the specified row and column (zero indexed). |
* A blank cell is used to specify formatting without adding a string |
* or a number. |
* |
* A blank cell without a format serves no purpose. Therefore, we don't write |
* a BLANK record unless a format is specified. |
* |
* Returns 0 : normal termination (including no format) |
* -1 : insufficient number of arguments |
* -2 : row or column out of range |
* |
* @access public |
* @param integer $row Zero indexed row |
* @param integer $col Zero indexed column |
* @param mixed $format The XF format |
*/ |
function writeBlank($row, $col, $format) |
{ |
// Don't write a blank cell unless it has a format |
if ($format == 0) |
{ |
return(0); |
} |
$record = 0x0201; // Record identifier |
$length = 0x0006; // Number of bytes to follow |
$xf = $this->_XF($format); // The cell format |
// Check that row and col are valid and store max and min values |
if ($row >= $this->_xls_rowmax) |
{ |
return(-2); |
} |
if ($col >= $this->_xls_colmax) |
{ |
return(-2); |
} |
if ($row < $this->_dim_rowmin) |
{ |
$this->_dim_rowmin = $row; |
} |
if ($row > $this->_dim_rowmax) |
{ |
$this->_dim_rowmax = $row; |
} |
if ($col < $this->_dim_colmin) |
{ |
$this->_dim_colmin = $col; |
} |
if ($col > $this->_dim_colmax) |
{ |
$this->_dim_colmax = $col; |
} |
$header = pack("vv", $record, $length); |
$data = pack("vvv", $row, $col, $xf); |
$this->_append($header.$data); |
return 0; |
} |
/** |
* Write a formula to the specified row and column (zero indexed). |
* The textual representation of the formula is passed to the parser in |
* Parser.php which returns a packed binary string. |
* |
* Returns 0 : normal termination |
* -1 : formula errors (bad formula) |
* -2 : row or column out of range |
* |
* @access public |
* @param integer $row Zero indexed row |
* @param integer $col Zero indexed column |
* @param string $formula The formula text string |
* @param mixed $format The optional XF format |
* @return integer |
*/ |
function writeFormula($row, $col, $formula, $format = 0) |
{ |
$record = 0x0006; // Record identifier |
// Excel normally stores the last calculated value of the formula in $num. |
// Clearly we are not in a position to calculate this a priori. Instead |
// we set $num to zero and set the option flags in $grbit to ensure |
// automatic calculation of the formula when the file is opened. |
// |
$xf = $this->_XF($format); // The cell format |
$num = 0x00; // Current value of formula |
$grbit = 0x03; // Option flags |
$chn = 0x0000; // Must be zero |
// Check that row and col are valid and store max and min values |
if ($row >= $this->_xls_rowmax) |
{ |
return(-2); |
} |
if ($col >= $this->_xls_colmax) |
{ |
return(-2); |
} |
if ($row < $this->_dim_rowmin) |
{ |
$this->_dim_rowmin = $row; |
} |
if ($row > $this->_dim_rowmax) |
{ |
$this->_dim_rowmax = $row; |
} |
if ($col < $this->_dim_colmin) |
{ |
$this->_dim_colmin = $col; |
} |
if ($col > $this->_dim_colmax) |
{ |
$this->_dim_colmax = $col; |
} |
// Strip the '=' or '@' sign at the beginning of the formula string |
if (preg_match("/^=/",$formula)) { |
$formula = preg_replace("/(^=)/","",$formula); |
} |
elseif (preg_match("/^@/",$formula)) { |
$formula = preg_replace("/(^@)/","",$formula); |
} |
else |
{ |
// Error handling |
$this->writeString($row, $col, 'Unrecognised character for formula'); |
return -1; |
} |
// Parse the formula using the parser in Parser.php |
$error = $this->_parser->parse($formula); |
if ($this->isError($error)) |
{ |
$this->writeString($row, $col, $error->getMessage()); |
return -1; |
} |
$formula = $this->_parser->toReversePolish(); |
if ($this->isError($formula)) |
{ |
$this->writeString($row, $col, $formula->getMessage()); |
return -1; |
} |
$formlen = strlen($formula); // Length of the binary string |
$length = 0x16 + $formlen; // Length of the record data |
$header = pack("vv", $record, $length); |
$data = pack("vvvdvVv", $row, $col, $xf, $num, |
$grbit, $chn, $formlen); |
$this->_append($header.$data.$formula); |
return 0; |
} |
/** |
* Write a hyperlink. |
* This is comprised of two elements: the visible label and |
* the invisible link. The visible label is the same as the link unless an |
* alternative string is specified. The label is written using the |
* writeString() method. Therefore the 255 characters string limit applies. |
* $string and $format are optional. |
* |
* The hyperlink can be to a http, ftp, mail, internal sheet (not yet), or external |
* directory url. |
* |
* Returns 0 : normal termination |
* -2 : row or column out of range |
* -3 : long string truncated to 255 chars |
* |
* @access public |
* @param integer $row Row |
* @param integer $col Column |
* @param string $url URL string |
* @param string $string Alternative label |
* @param mixed $format The cell format |
* @return integer |
*/ |
function writeUrl($row, $col, $url, $string = '', $format = 0) |
{ |
// Add start row and col to arg list |
return($this->_writeUrl_range($row, $col, $row, $col, $url, $string, $format)); |
} |
/** |
* This is the more general form of writeUrl(). It allows a hyperlink to be |
* written to a range of cells. This function also decides the type of hyperlink |
* to be written. These are either, Web (http, ftp, mailto), Internal |
* (Sheet1!A1) or external ('c:\temp\foo.xls#Sheet1!A1'). |
* |
* @access private |
* @see writeUrl() |
* @param integer $row1 Start row |
* @param integer $col1 Start column |
* @param integer $row2 End row |
* @param integer $col2 End column |
* @param string $url URL string |
* @param string $string Alternative label |
* @param mixed $format The cell format |
* @return integer |
*/ |
function _writeUrl_range($row1, $col1, $row2, $col2, $url, $string = '', $format = 0) |
{ |
// Check for internal/external sheet links or default to web link |
if (preg_match('[^internal:]', $url)) { |
return($this->_writeUrlInternal($row1, $col1, $row2, $col2, $url, $string, $format)); |
} |
if (preg_match('[^external:]', $url)) { |
return($this->_writeUrlExternal($row1, $col1, $row2, $col2, $url, $string, $format)); |
} |
return($this->_writeUrlWeb($row1, $col1, $row2, $col2, $url, $string, $format)); |
} |
/** |
* Used to write http, ftp and mailto hyperlinks. |
* The link type ($options) is 0x03 is the same as absolute dir ref without |
* sheet. However it is differentiated by the $unknown2 data stream. |
* |
* @access private |
* @see writeUrl() |
* @param integer $row1 Start row |
* @param integer $col1 Start column |
* @param integer $row2 End row |
* @param integer $col2 End column |
* @param string $url URL string |
* @param string $str Alternative label |
* @param mixed $format The cell format |
* @return integer |
*/ |
function _writeUrlWeb($row1, $col1, $row2, $col2, $url, $str, $format = 0) |
{ |
$record = 0x01B8; // Record identifier |
$length = 0x00000; // Bytes to follow |
if ($format == 0) { |
$format = $this->_url_format; |
} |
// Write the visible label using the writeString() method. |
if ($str == '') { |
$str = $url; |
} |
$str_error = $this->writeString($row1, $col1, $str, $format); |
if (($str_error == -2) or ($str_error == -3)) { |
return $str_error; |
} |
// Pack the undocumented parts of the hyperlink stream |
$unknown1 = pack("H*", "D0C9EA79F9BACE118C8200AA004BA90B02000000"); |
$unknown2 = pack("H*", "E0C9EA79F9BACE118C8200AA004BA90B"); |
// Pack the option flags |
$options = pack("V", 0x03); |
// Convert URL to a null terminated wchar string |
$url = join("\0", preg_split("''", $url, -1, PREG_SPLIT_NO_EMPTY)); |
$url = $url . "\0\0\0"; |
// Pack the length of the URL |
$url_len = pack("V", strlen($url)); |
// Calculate the data length |
$length = 0x34 + strlen($url); |
// Pack the header data |
$header = pack("vv", $record, $length); |
$data = pack("vvvv", $row1, $row2, $col1, $col2); |
// Write the packed data |
$this->_append( $header. $data. |
$unknown1. $options. |
$unknown2. $url_len. $url); |
return($str_error); |
} |
/** |
* Used to write internal reference hyperlinks such as "Sheet1!A1". |
* |
* @access private |
* @see writeUrl() |
* @param integer $row1 Start row |
* @param integer $col1 Start column |
* @param integer $row2 End row |
* @param integer $col2 End column |
* @param string $url URL string |
* @param string $str Alternative label |
* @param mixed $format The cell format |
* @return integer |
*/ |
function _writeUrlInternal($row1, $col1, $row2, $col2, $url, $str, $format = 0) |
{ |
$record = 0x01B8; // Record identifier |
$length = 0x00000; // Bytes to follow |
if ($format == 0) { |
$format = $this->_url_format; |
} |
// Strip URL type |
$url = preg_replace('s[^internal:]', '', $url); |
// Write the visible label |
if ($str == '') { |
$str = $url; |
} |
$str_error = $this->writeString($row1, $col1, $str, $format); |
if (($str_error == -2) or ($str_error == -3)) { |
return $str_error; |
} |
// Pack the undocumented parts of the hyperlink stream |
$unknown1 = pack("H*", "D0C9EA79F9BACE118C8200AA004BA90B02000000"); |
// Pack the option flags |
$options = pack("V", 0x08); |
// Convert the URL type and to a null terminated wchar string |
$url = join("\0", preg_split("''", $url, -1, PREG_SPLIT_NO_EMPTY)); |
$url = $url . "\0\0\0"; |
// Pack the length of the URL as chars (not wchars) |
$url_len = pack("V", floor(strlen($url)/2)); |
// Calculate the data length |
$length = 0x24 + strlen($url); |
// Pack the header data |
$header = pack("vv", $record, $length); |
$data = pack("vvvv", $row1, $row2, $col1, $col2); |
// Write the packed data |
$this->_append($header. $data. |
$unknown1. $options. |
$url_len. $url); |
return($str_error); |
} |
/** |
* Write links to external directory names such as 'c:\foo.xls', |
* c:\foo.xls#Sheet1!A1', '../../foo.xls'. and '../../foo.xls#Sheet1!A1'. |
* |
* Note: Excel writes some relative links with the $dir_long string. We ignore |
* these cases for the sake of simpler code. |
* |
* @access private |
* @see writeUrl() |
* @param integer $row1 Start row |
* @param integer $col1 Start column |
* @param integer $row2 End row |
* @param integer $col2 End column |
* @param string $url URL string |
* @param string $str Alternative label |
* @param mixed $format The cell format |
* @return integer |
*/ |
function _writeUrlExternal($row1, $col1, $row2, $col2, $url, $str, $format = 0) |
{ |
// Network drives are different. We will handle them separately |
// MS/Novell network drives and shares start with \\ |
if (preg_match('[^external:\\\\]', $url)) { |
return; //($this->_writeUrlExternal_net($row1, $col1, $row2, $col2, $url, $str, $format)); |
} |
$record = 0x01B8; // Record identifier |
$length = 0x00000; // Bytes to follow |
if ($format == 0) { |
$format = $this->_url_format; |
} |
// Strip URL type and change Unix dir separator to Dos style (if needed) |
// |
$url = preg_replace('[^external:]', '', $url); |
$url = preg_replace('[/]', "\\", $url); |
// Write the visible label |
if ($str == '') { |
$str = preg_replace('[\#]', ' - ', $url); |
} |
$str_error = $this->writeString($row1, $col1, $str, $format); |
if (($str_error == -2) or ($str_error == -3)) { |
return $str_error; |
} |
// Determine if the link is relative or absolute: |
// relative if link contains no dir separator, "somefile.xls" |
// relative if link starts with up-dir, "..\..\somefile.xls" |
// otherwise, absolute |
$absolute = 0x02; // Bit mask |
if (!preg_match('[\\]', $url)) { |
$absolute = 0x00; |
} |
if (preg_match('[^\.\.\\]', $url)) { |
$absolute = 0x00; |
} |
// Determine if the link contains a sheet reference and change some of the |
// parameters accordingly. |
// Split the dir name and sheet name (if it exists) |
list($dir_long , $sheet) = split('/\#/', $url); |
$link_type = 0x01 | $absolute; |
if (isset($sheet)) { |
$link_type |= 0x08; |
$sheet_len = pack("V", strlen($sheet) + 0x01); |
$sheet = join("\0", split('', $sheet)); |
$sheet .= "\0\0\0"; |
} |
else { |
$sheet_len = ''; |
$sheet = ''; |
} |
// Pack the link type |
$link_type = pack("V", $link_type); |
// Calculate the up-level dir count e.g.. (..\..\..\ == 3) |
$up_count = preg_match_all("/\.\.\\/", $dir_long, $useless); |
$up_count = pack("v", $up_count); |
// Store the short dos dir name (null terminated) |
$dir_short = preg_replace('/\.\.\\/', '', $dir_long) . "\0"; |
// Store the long dir name as a wchar string (non-null terminated) |
$dir_long = join("\0", split('', $dir_long)); |
$dir_long = $dir_long . "\0"; |
// Pack the lengths of the dir strings |
$dir_short_len = pack("V", strlen($dir_short) ); |
$dir_long_len = pack("V", strlen($dir_long) ); |
$stream_len = pack("V", strlen($dir_long) + 0x06); |
// Pack the undocumented parts of the hyperlink stream |
$unknown1 = pack("H*",'D0C9EA79F9BACE118C8200AA004BA90B02000000' ); |
$unknown2 = pack("H*",'0303000000000000C000000000000046' ); |
$unknown3 = pack("H*",'FFFFADDE000000000000000000000000000000000000000'); |
$unknown4 = pack("v", 0x03 ); |
// Pack the main data stream |
$data = pack("vvvv", $row1, $row2, $col1, $col2) . |
$unknown1 . |
$link_type . |
$unknown2 . |
$up_count . |
$dir_short_len. |
$dir_short . |
$unknown3 . |
$stream_len . |
$dir_long_len . |
$unknown4 . |
$dir_long . |
$sheet_len . |
$sheet ; |
// Pack the header data |
$length = strlen($data); |
$header = pack("vv", $record, $length); |
// Write the packed data |
$this->_append($header. $data); |
return($str_error); |
} |
/** |
* This method is used to set the height and format for a row. |
* |
* @access public |
* @param integer $row The row to set |
* @param integer $height Height we are giving to the row. |
* Use NULL to set XF without setting height |
* @param mixed $format XF format we are giving to the row |
*/ |
function setRow($row, $height, $format = 0) |
{ |
$record = 0x0208; // Record identifier |
$length = 0x0010; // Number of bytes to follow |
$colMic = 0x0000; // First defined column |
$colMac = 0x0000; // Last defined column |
$irwMac = 0x0000; // Used by Excel to optimise loading |
$reserved = 0x0000; // Reserved |
$grbit = 0x01C0; // Option flags. (monkey) see $1 do |
$ixfe = $this->_XF($format); // XF index |
// Use setRow($row, NULL, $XF) to set XF format without setting height |
if ($height != NULL) { |
$miyRw = $height * 20; // row height |
} |
else { |
$miyRw = 0xff; // default row height is 256 |
} |
$header = pack("vv", $record, $length); |
$data = pack("vvvvvvvv", $row, $colMic, $colMac, $miyRw, |
$irwMac,$reserved, $grbit, $ixfe); |
$this->_append($header.$data); |
} |
/** |
* Writes Excel DIMENSIONS to define the area in which there is data. |
* |
* @access private |
*/ |
function storeDimensions() |
{ |
$record = 0x0000; // Record identifier |
$length = 0x000A; // Number of bytes to follow |
$row_min = $this->_dim_rowmin; // First row |
$row_max = $this->_dim_rowmax; // Last row plus 1 |
$col_min = $this->_dim_colmin; // First column |
$col_max = $this->_dim_colmax; // Last column plus 1 |
$reserved = 0x0000; // Reserved by Excel |
$header = pack("vv", $record, $length); |
$data = pack("vvvvv", $row_min, $row_max, |
$col_min, $col_max, $reserved); |
$this->_prepend($header.$data); |
} |
/** |
* Write BIFF record Window2. |
* |
* @access private |
*/ |
function _storeWindow2() |
{ |
$record = 0x023E; // Record identifier |
$length = 0x000A; // Number of bytes to follow |
$grbit = 0x00B6; // Option flags |
$rwTop = 0x0000; // Top row visible in window |
$colLeft = 0x0000; // Leftmost column visible in window |
$rgbHdr = 0x00000000; // Row/column heading and gridline color |
// The options flags that comprise $grbit |
$fDspFmla = 0; // 0 - bit |
$fDspGrid = 1; // 1 |
$fDspRwCol = 1; // 2 |
$fFrozen = $this->_frozen; // 3 |
$fDspZeros = 1; // 4 |
$fDefaultHdr = 1; // 5 |
$fArabic = 0; // 6 |
$fDspGuts = 1; // 7 |
$fFrozenNoSplit = 0; // 0 - bit |
$fSelected = $this->selected; // 1 |
$fPaged = 1; // 2 |
$grbit = $fDspFmla; |
$grbit |= $fDspGrid << 1; |
$grbit |= $fDspRwCol << 2; |
$grbit |= $fFrozen << 3; |
$grbit |= $fDspZeros << 4; |
$grbit |= $fDefaultHdr << 5; |
$grbit |= $fArabic << 6; |
$grbit |= $fDspGuts << 7; |
$grbit |= $fFrozenNoSplit << 8; |
$grbit |= $fSelected << 9; |
$grbit |= $fPaged << 10; |
$header = pack("vv", $record, $length); |
$data = pack("vvvV", $grbit, $rwTop, $colLeft, $rgbHdr); |
$this->_append($header.$data); |
} |
/** |
* Write BIFF record DEFCOLWIDTH if COLINFO records are in use. |
* |
* @access private |
*/ |
function _storeDefcol() |
{ |
$record = 0x0055; // Record identifier |
$length = 0x0002; // Number of bytes to follow |
$colwidth = 0x0008; // Default column width |
$header = pack("vv", $record, $length); |
$data = pack("v", $colwidth); |
$this->_prepend($header.$data); |
} |
/** |
* Write BIFF record COLINFO to define column widths |
* |
* Note: The SDK says the record length is 0x0B but Excel writes a 0x0C |
* length record. |
* |
* @access private |
* @param array $col_array This is the only parameter received and is composed of the following: |
* 0 => First formatted column, |
* 1 => Last formatted column, |
* 2 => Col width (8.43 is Excel default), |
* 3 => The optional XF format of the column, |
* 4 => Option flags. |
*/ |
function _storeColinfo($col_array) |
{ |
if (isset($col_array[0])) { |
$colFirst = $col_array[0]; |
} |
if (isset($col_array[1])) { |
$colLast = $col_array[1]; |
} |
if (isset($col_array[2])) { |
$coldx = $col_array[2]; |
} |
else { |
$coldx = 8.43; |
} |
if (isset($col_array[3])) { |
$format = $col_array[3]; |
} |
else { |
$format = 0; |
} |
if (isset($col_array[4])) { |
$grbit = $col_array[4]; |
} |
else { |
$grbit = 0; |
} |
$record = 0x007D; // Record identifier |
$length = 0x000B; // Number of bytes to follow |
$coldx += 0.72; // Fudge. Excel subtracts 0.72 !? |
$coldx *= 256; // Convert to units of 1/256 of a char |
$ixfe = $this->_XF($format); |
$reserved = 0x00; // Reserved |
$header = pack("vv", $record, $length); |
$data = pack("vvvvvC", $colFirst, $colLast, $coldx, |
$ixfe, $grbit, $reserved); |
$this->_prepend($header.$data); |
} |
/** |
* Write BIFF record SELECTION. |
* |
* @access private |
* @param array $array array containing ($rwFirst,$colFirst,$rwLast,$colLast) |
* @see setSelection() |
*/ |
function _storeSelection($array) |
{ |
list($rwFirst,$colFirst,$rwLast,$colLast) = $array; |
$record = 0x001D; // Record identifier |
$length = 0x000F; // Number of bytes to follow |
$pnn = $this->_active_pane; // Pane position |
$rwAct = $rwFirst; // Active row |
$colAct = $colFirst; // Active column |
$irefAct = 0; // Active cell ref |
$cref = 1; // Number of refs |
if (!isset($rwLast)) { |
$rwLast = $rwFirst; // Last row in reference |
} |
if (!isset($colLast)) { |
$colLast = $colFirst; // Last col in reference |
} |
// Swap last row/col for first row/col as necessary |
if ($rwFirst > $rwLast) |
{ |
list($rwFirst, $rwLast) = array($rwLast, $rwFirst); |
} |
if ($colFirst > $colLast) |
{ |
list($colFirst, $colLast) = array($colLast, $colFirst); |
} |
$header = pack("vv", $record, $length); |
$data = pack("CvvvvvvCC", $pnn, $rwAct, $colAct, |
$irefAct, $cref, |
$rwFirst, $rwLast, |
$colFirst, $colLast); |
$this->_append($header.$data); |
} |
/** |
* Write BIFF record EXTERNCOUNT to indicate the number of external sheet |
* references in a worksheet. |
* |
* Excel only stores references to external sheets that are used in formulas. |
* For simplicity we store references to all the sheets in the workbook |
* regardless of whether they are used or not. This reduces the overall |
* complexity and eliminates the need for a two way dialogue between the formula |
* parser the worksheet objects. |
* |
* @access private |
* @param integer $count The number of external sheet references in this worksheet |
*/ |
function _storeExterncount($count) |
{ |
$record = 0x0016; // Record identifier |
$length = 0x0002; // Number of bytes to follow |
$header = pack("vv", $record, $length); |
$data = pack("v", $count); |
$this->_prepend($header.$data); |
} |
/** |
* Writes the Excel BIFF EXTERNSHEET record. These references are used by |
* formulas. A formula references a sheet name via an index. Since we store a |
* reference to all of the external worksheets the EXTERNSHEET index is the same |
* as the worksheet index. |
* |
* @access private |
* @param string $sheetname The name of a external worksheet |
*/ |
function _storeExternsheet($sheetname) |
{ |
$record = 0x0017; // Record identifier |
// References to the current sheet are encoded differently to references to |
// external sheets. |
// |
if ($this->name == $sheetname) { |
$sheetname = ''; |
$length = 0x02; // The following 2 bytes |
$cch = 1; // The following byte |
$rgch = 0x02; // Self reference |
} |
else { |
$length = 0x02 + strlen($sheetname); |
$cch = strlen($sheetname); |
$rgch = 0x03; // Reference to a sheet in the current workbook |
} |
$header = pack("vv", $record, $length); |
$data = pack("CC", $cch, $rgch); |
$this->_prepend($header.$data.$sheetname); |
} |
/** |
* Writes the Excel BIFF PANE record. |
* The panes can either be frozen or thawed (unfrozen). |
* Frozen panes are specified in terms of an integer number of rows and columns. |
* Thawed panes are specified in terms of Excel's units for rows and columns. |
* |
* @access private |
* @param array $panes This is the only parameter received and is composed of the following: |
* 0 => Vertical split position, |
* 1 => Horizontal split position |
* 2 => Top row visible |
* 3 => Leftmost column visible |
* 4 => Active pane |
*/ |
function _storePanes($panes) |
{ |
$y = $panes[0]; |
$x = $panes[1]; |
$rwTop = $panes[2]; |
$colLeft = $panes[3]; |
if (count($panes) > 4) { // if Active pane was received |
$pnnAct = $panes[4]; |
} |
else { |
$pnnAct = NULL; |
} |
$record = 0x0041; // Record identifier |
$length = 0x000A; // Number of bytes to follow |
// Code specific to frozen or thawed panes. |
if ($this->_frozen) |
{ |
// Set default values for $rwTop and $colLeft |
if (!isset($rwTop)) { |
$rwTop = $y; |
} |
if (!isset($colLeft)) { |
$colLeft = $x; |
} |
} |
else |
{ |
// Set default values for $rwTop and $colLeft |
if (!isset($rwTop)) { |
$rwTop = 0; |
} |
if (!isset($colLeft)) { |
$colLeft = 0; |
} |
// Convert Excel's row and column units to the internal units. |
// The default row height is 12.75 |
// The default column width is 8.43 |
// The following slope and intersection values were interpolated. |
// |
$y = 20*$y + 255; |
$x = 113.879*$x + 390; |
} |
// Determine which pane should be active. There is also the undocumented |
// option to override this should it be necessary: may be removed later. |
// |
if (!isset($pnnAct)) |
{ |
if ($x != 0 and $y != 0) |
$pnnAct = 0; // Bottom right |
if ($x != 0 and $y == 0) |
$pnnAct = 1; // Top right |
if ($x == 0 and $y != 0) |
$pnnAct = 2; // Bottom left |
if ($x == 0 and $y == 0) |
$pnnAct = 3; // Top left |
} |
$this->_active_pane = $pnnAct; // Used in _storeSelection |
$header = pack("vv", $record, $length); |
$data = pack("vvvvv", $x, $y, $rwTop, $colLeft, $pnnAct); |
$this->_append($header.$data); |
} |
/** |
* Store the page setup SETUP BIFF record. |
* |
* @access private |
*/ |
function _storeSetup() |
{ |
$record = 0x00A1; // Record identifier |
$length = 0x0022; // Number of bytes to follow |
$iPaperSize = $this->_paper_size; // Paper size |
$iScale = $this->_print_scale; // Print scaling factor |
$iPageStart = 0x01; // Starting page number |
$iFitWidth = $this->_fit_width; // Fit to number of pages wide |
$iFitHeight = $this->_fit_height; // Fit to number of pages high |
$grbit = 0x00; // Option flags |
$iRes = 0x0258; // Print resolution |
$iVRes = 0x0258; // Vertical print resolution |
$numHdr = $this->_margin_head; // Header Margin |
$numFtr = $this->_margin_foot; // Footer Margin |
$iCopies = 0x01; // Number of copies |
$fLeftToRight = 0x0; // Print over then down |
$fLandscape = $this->_orientation; // Page orientation |
$fNoPls = 0x0; // Setup not read from printer |
$fNoColor = 0x0; // Print black and white |
$fDraft = 0x0; // Print draft quality |
$fNotes = 0x0; // Print notes |
$fNoOrient = 0x0; // Orientation not set |
$fUsePage = 0x0; // Use custom starting page |
$grbit = $fLeftToRight; |
$grbit |= $fLandscape << 1; |
$grbit |= $fNoPls << 2; |
$grbit |= $fNoColor << 3; |
$grbit |= $fDraft << 4; |
$grbit |= $fNotes << 5; |
$grbit |= $fNoOrient << 6; |
$grbit |= $fUsePage << 7; |
$numHdr = pack("d", $numHdr); |
$numFtr = pack("d", $numFtr); |
if ($this->_byte_order) // if it's Big Endian |
{ |
$numHdr = strrev($numHdr); |
$numFtr = strrev($numFtr); |
} |
$header = pack("vv", $record, $length); |
$data1 = pack("vvvvvvvv", $iPaperSize, |
$iScale, |
$iPageStart, |
$iFitWidth, |
$iFitHeight, |
$grbit, |
$iRes, |
$iVRes); |
$data2 = $numHdr.$numFtr; |
$data3 = pack("v", $iCopies); |
$this->_prepend($header.$data1.$data2.$data3); |
} |
/** |
* Store the header caption BIFF record. |
* |
* @access private |
*/ |
function _storeHeader() |
{ |
$record = 0x0014; // Record identifier |
$str = $this->_header; // header string |
$cch = strlen($str); // Length of header string |
$length = 1 + $cch; // Bytes to follow |
$header = pack("vv", $record, $length); |
$data = pack("C", $cch); |
$this->_append($header.$data.$str); |
} |
/** |
* Store the footer caption BIFF record. |
* |
* @access private |
*/ |
function _storeFooter() |
{ |
$record = 0x0015; // Record identifier |
$str = $this->_footer; // Footer string |
$cch = strlen($str); // Length of footer string |
$length = 1 + $cch; // Bytes to follow |
$header = pack("vv", $record, $length); |
$data = pack("C", $cch); |
$this->_append($header.$data.$str); |
} |
/** |
* Store the horizontal centering HCENTER BIFF record. |
* |
* @access private |
*/ |
function _storeHcenter() |
{ |
$record = 0x0083; // Record identifier |
$length = 0x0002; // Bytes to follow |
$fHCenter = $this->_hcenter; // Horizontal centering |
$header = pack("vv", $record, $length); |
$data = pack("v", $fHCenter); |
$this->_append($header.$data); |
} |
/** |
* Store the vertical centering VCENTER BIFF record. |
* |
* @access private |
*/ |
function _storeVcenter() |
{ |
$record = 0x0084; // Record identifier |
$length = 0x0002; // Bytes to follow |
$fVCenter = $this->_vcenter; // Horizontal centering |
$header = pack("vv", $record, $length); |
$data = pack("v", $fVCenter); |
$this->_append($header.$data); |
} |
/** |
* Store the LEFTMARGIN BIFF record. |
* |
* @access private |
*/ |
function _storeMarginLeft() |
{ |
$record = 0x0026; // Record identifier |
$length = 0x0008; // Bytes to follow |
$margin = $this->_margin_left; // Margin in inches |
$header = pack("vv", $record, $length); |
$data = pack("d", $margin); |
if ($this->_byte_order) // if it's Big Endian |
{ |
$data = strrev($data); |
} |
$this->_append($header.$data); |
} |
/** |
* Store the RIGHTMARGIN BIFF record. |
* |
* @access private |
*/ |
function _storeMarginRight() |
{ |
$record = 0x0027; // Record identifier |
$length = 0x0008; // Bytes to follow |
$margin = $this->_margin_right; // Margin in inches |
$header = pack("vv", $record, $length); |
$data = pack("d", $margin); |
if ($this->_byte_order) // if it's Big Endian |
{ |
$data = strrev($data); |
} |
$this->_append($header.$data); |
} |
/** |
* Store the TOPMARGIN BIFF record. |
* |
* @access private |
*/ |
function _storeMarginTop() |
{ |
$record = 0x0028; // Record identifier |
$length = 0x0008; // Bytes to follow |
$margin = $this->_margin_top; // Margin in inches |
$header = pack("vv", $record, $length); |
$data = pack("d", $margin); |
if ($this->_byte_order) // if it's Big Endian |
{ |
$data = strrev($data); |
} |
$this->_append($header.$data); |
} |
/** |
* Store the BOTTOMMARGIN BIFF record. |
* |
* @access private |
*/ |
function _storeMarginBottom() |
{ |
$record = 0x0029; // Record identifier |
$length = 0x0008; // Bytes to follow |
$margin = $this->_margin_bottom; // Margin in inches |
$header = pack("vv", $record, $length); |
$data = pack("d", $margin); |
if ($this->_byte_order) // if it's Big Endian |
{ |
$data = strrev($data); |
} |
$this->_append($header.$data); |
} |
/** |
* Merges the area given by its arguments. |
* This is an Excel97/2000 method. It is required to perform more complicated |
* merging than the normal setAlign('merge'). |
* |
* @access public |
* @param integer $first_row First row of the area to merge |
* @param integer $first_col First column of the area to merge |
* @param integer $last_row Last row of the area to merge |
* @param integer $last_col Last column of the area to merge |
*/ |
function mergeCells($first_row, $first_col, $last_row, $last_col) |
{ |
$record = 0x00E5; // Record identifier |
$length = 0x000A; // Bytes to follow |
$cref = 1; // Number of refs |
// Swap last row/col for first row/col as necessary |
if ($first_row > $last_row) { |
list($first_row, $last_row) = array($last_row, $first_row); |
} |
if ($first_col > $last_col) { |
list($first_col, $last_col) = array($last_col, $first_col); |
} |
$header = pack("vv", $record, $length); |
$data = pack("vvvvv", $cref, $first_row, $last_row, |
$first_col, $last_col); |
$this->_append($header.$data); |
} |
/** |
* Write the PRINTHEADERS BIFF record. |
* |
* @access private |
*/ |
function _storePrintHeaders() |
{ |
$record = 0x002a; // Record identifier |
$length = 0x0002; // Bytes to follow |
$fPrintRwCol = $this->_print_headers; // Boolean flag |
$header = pack("vv", $record, $length); |
$data = pack("v", $fPrintRwCol); |
$this->_prepend($header.$data); |
} |
/** |
* Write the PRINTGRIDLINES BIFF record. Must be used in conjunction with the |
* GRIDSET record. |
* |
* @access private |
*/ |
function _storePrintGridlines() |
{ |
$record = 0x002b; // Record identifier |
$length = 0x0002; // Bytes to follow |
$fPrintGrid = $this->_print_gridlines; // Boolean flag |
$header = pack("vv", $record, $length); |
$data = pack("v", $fPrintGrid); |
$this->_prepend($header.$data); |
} |
/** |
* Write the GRIDSET BIFF record. Must be used in conjunction with the |
* PRINTGRIDLINES record. |
* |
* @access private |
*/ |
function _storeGridset() |
{ |
$record = 0x0082; // Record identifier |
$length = 0x0002; // Bytes to follow |
$fGridSet = !($this->_print_gridlines); // Boolean flag |
$header = pack("vv", $record, $length); |
$data = pack("v", $fGridSet); |
$this->_prepend($header.$data); |
} |
/** |
* Write the WSBOOL BIFF record, mainly for fit-to-page. Used in conjunction |
* with the SETUP record. |
* |
* @access private |
*/ |
function _storeWsbool() |
{ |
$record = 0x0081; // Record identifier |
$length = 0x0002; // Bytes to follow |
// The only option that is of interest is the flag for fit to page. So we |
// set all the options in one go. |
// |
if ($this->_fit_page) { |
$grbit = 0x05c1; |
} |
else { |
$grbit = 0x04c1; |
} |
$header = pack("vv", $record, $length); |
$data = pack("v", $grbit); |
$this->_prepend($header.$data); |
} |
/** |
* Write the HORIZONTALPAGEBREAKS BIFF record. |
* |
* @access private |
*/ |
function _storeHbreak() |
{ |
// Return if the user hasn't specified pagebreaks |
if (empty($this->_hbreaks)) { |
return; |
} |
// Sort and filter array of page breaks |
$breaks = $this->_hbreaks; |
sort($breaks,SORT_NUMERIC); |
if ($breaks[0] == 0) { // don't use first break if it's 0 |
array_shift($breaks); |
} |
$record = 0x001b; // Record identifier |
$cbrk = count($breaks); // Number of page breaks |
$length = ($cbrk + 1) * 2; // Bytes to follow |
$header = pack("vv", $record, $length); |
$data = pack("v", $cbrk); |
// Append each page break |
foreach($breaks as $break) { |
$data .= pack("v", $break); |
} |
$this->_prepend($header.$data); |
} |
/** |
* Write the VERTICALPAGEBREAKS BIFF record. |
* |
* @access private |
*/ |
function _storeVbreak() |
{ |
// Return if the user hasn't specified pagebreaks |
if (empty($this->_vbreaks)) { |
return; |
} |
// 1000 vertical pagebreaks appears to be an internal Excel 5 limit. |
// It is slightly higher in Excel 97/200, approx. 1026 |
$breaks = array_slice($this->_vbreaks,0,1000); |
// Sort and filter array of page breaks |
sort($breaks,SORT_NUMERIC); |
if ($breaks[0] == 0) { // don't use first break if it's 0 |
array_shift($breaks); |
} |
$record = 0x001a; // Record identifier |
$cbrk = count($breaks); // Number of page breaks |
$length = ($cbrk + 1) * 2; // Bytes to follow |
$header = pack("vv", $record, $length); |
$data = pack("v", $cbrk); |
// Append each page break |
foreach ($breaks as $break) { |
$data .= pack("v", $break); |
} |
$this->_prepend($header.$data); |
} |
/** |
* Set the Biff PROTECT record to indicate that the worksheet is protected. |
* |
* @access private |
*/ |
function _storeProtect() |
{ |
// Exit unless sheet protection has been specified |
if ($this->_protect == 0) { |
return; |
} |
$record = 0x0012; // Record identifier |
$length = 0x0002; // Bytes to follow |
$fLock = $this->_protect; // Worksheet is protected |
$header = pack("vv", $record, $length); |
$data = pack("v", $fLock); |
$this->_prepend($header.$data); |
} |
/** |
* Write the worksheet PASSWORD record. |
* |
* @access private |
*/ |
function _storePassword() |
{ |
// Exit unless sheet protection and password have been specified |
if (($this->_protect == 0) or (!isset($this->_password))) { |
return; |
} |
$record = 0x0013; // Record identifier |
$length = 0x0002; // Bytes to follow |
$wPassword = $this->_password; // Encoded password |
$header = pack("vv", $record, $length); |
$data = pack("v", $wPassword); |
$this->_prepend($header.$data); |
} |
/** |
* Insert a 24bit bitmap image in a worksheet. |
* |
* @access public |
* @param integer $row The row we are going to insert the bitmap into |
* @param integer $col The column we are going to insert the bitmap into |
* @param string $bitmap The bitmap filename |
* @param integer $x The horizontal position (offset) of the image inside the cell. |
* @param integer $y The vertical position (offset) of the image inside the cell. |
* @param integer $scale_x The horizontal scale |
* @param integer $scale_y The vertical scale |
*/ |
function insertBitmap($row, $col, $bitmap, $x = 0, $y = 0, $scale_x = 1, $scale_y = 1) |
{ |
$bitmap_array = $this->_processBitmap($bitmap); |
if ($this->isError($bitmap_array)) |
{ |
$this->writeString($row, $col, $bitmap_array->getMessage()); |
return; |
} |
list($width, $height, $size, $data) = $bitmap_array; //$this->_processBitmap($bitmap); |
// Scale the frame of the image. |
$width *= $scale_x; |
$height *= $scale_y; |
// Calculate the vertices of the image and write the OBJ record |
$this->_positionImage($col, $row, $x, $y, $width, $height); |
// Write the IMDATA record to store the bitmap data |
$record = 0x007f; |
$length = 8 + $size; |
$cf = 0x09; |
$env = 0x01; |
$lcb = $size; |
$header = pack("vvvvV", $record, $length, $cf, $env, $lcb); |
$this->_append($header.$data); |
} |
/** |
* Calculate the vertices that define the position of the image as required by |
* the OBJ record. |
* |
* +------------+------------+ |
* | A | B | |
* +-----+------------+------------+ |
* | |(x1,y1) | | |
* | 1 |(A1)._______|______ | |
* | | | | | |
* | | | | | |
* +-----+----| BITMAP |-----+ |
* | | | | | |
* | 2 | |______________. | |
* | | | (B2)| |
* | | | (x2,y2)| |
* +---- +------------+------------+ |
* |
* Example of a bitmap that covers some of the area from cell A1 to cell B2. |
* |
* Based on the width and height of the bitmap we need to calculate 8 vars: |
* $col_start, $row_start, $col_end, $row_end, $x1, $y1, $x2, $y2. |
* The width and height of the cells are also variable and have to be taken into |
* account. |
* The values of $col_start and $row_start are passed in from the calling |
* function. The values of $col_end and $row_end are calculated by subtracting |
* the width and height of the bitmap from the width and height of the |
* underlying cells. |
* The vertices are expressed as a percentage of the underlying cell width as |
* follows (rhs values are in pixels): |
* |
* x1 = X / W *1024 |
* y1 = Y / H *256 |
* x2 = (X-1) / W *1024 |
* y2 = (Y-1) / H *256 |
* |
* Where: X is distance from the left side of the underlying cell |
* Y is distance from the top of the underlying cell |
* W is the width of the cell |
* H is the height of the cell |
* |
* @access private |
* @note the SDK incorrectly states that the height should be expressed as a |
* percentage of 1024. |
* @param integer $col_start Col containing upper left corner of object |
* @param integer $row_start Row containing top left corner of object |
* @param integer $x1 Distance to left side of object |
* @param integer $y1 Distance to top of object |
* @param integer $width Width of image frame |
* @param integer $height Height of image frame |
*/ |
function _positionImage($col_start, $row_start, $x1, $y1, $width, $height) |
{ |
// Initialise end cell to the same as the start cell |
$col_end = $col_start; // Col containing lower right corner of object |
$row_end = $row_start; // Row containing bottom right corner of object |
// Zero the specified offset if greater than the cell dimensions |
if ($x1 >= $this->_sizeCol($col_start)) |
{ |
$x1 = 0; |
} |
if ($y1 >= $this->_sizeRow($row_start)) |
{ |
$y1 = 0; |
} |
$width = $width + $x1 -1; |
$height = $height + $y1 -1; |
// Subtract the underlying cell widths to find the end cell of the image |
while ($width >= $this->_sizeCol($col_end)) { |
$width -= $this->_sizeCol($col_end); |
$col_end++; |
} |
// Subtract the underlying cell heights to find the end cell of the image |
while ($height >= $this->_sizeRow($row_end)) { |
$height -= $this->_sizeRow($row_end); |
$row_end++; |
} |
// Bitmap isn't allowed to start or finish in a hidden cell, i.e. a cell |
// with zero eight or width. |
// |
if ($this->_sizeCol($col_start) == 0) |
return; |
if ($this->_sizeCol($col_end) == 0) |
return; |
if ($this->_sizeRow($row_start) == 0) |
return; |
if ($this->_sizeRow($row_end) == 0) |
return; |
// Convert the pixel values to the percentage value expected by Excel |
$x1 = $x1 / $this->_sizeCol($col_start) * 1024; |
$y1 = $y1 / $this->_sizeRow($row_start) * 256; |
$x2 = $width / $this->_sizeCol($col_end) * 1024; // Distance to right side of object |
$y2 = $height / $this->_sizeRow($row_end) * 256; // Distance to bottom of object |
$this->_storeObjPicture( $col_start, $x1, |
$row_start, $y1, |
$col_end, $x2, |
$row_end, $y2 |
); |
} |
/** |
* Convert the width of a cell from user's units to pixels. By interpolation |
* the relationship is: y = 7x +5. If the width hasn't been set by the user we |
* use the default value. If the col is hidden we use a value of zero. |
* |
* @access private |
* @param integer $col The column |
* @return integer The width in pixels |
*/ |
function _sizeCol($col) |
{ |
// Look up the cell value to see if it has been changed |
if (isset($this->col_sizes[$col])) { |
if ($this->col_sizes[$col] == 0) { |
return(0); |
} |
else { |
return(floor(7 * $this->col_sizes[$col] + 5)); |
} |
} |
else { |
return(64); |
} |
} |
/** |
* Convert the height of a cell from user's units to pixels. By interpolation |
* the relationship is: y = 4/3x. If the height hasn't been set by the user we |
* use the default value. If the row is hidden we use a value of zero. (Not |
* possible to hide row yet). |
* |
* @access private |
* @param integer $row The row |
* @return integer The width in pixels |
*/ |
function _sizeRow($row) |
{ |
// Look up the cell value to see if it has been changed |
if (isset($this->row_sizes[$row])) { |
if ($this->row_sizes[$row] == 0) { |
return(0); |
} |
else { |
return(floor(4/3 * $this->row_sizes[$row])); |
} |
} |
else { |
return(17); |
} |
} |
/** |
* Store the OBJ record that precedes an IMDATA record. This could be generalise |
* to support other Excel objects. |
* |
* @access private |
* @param integer $colL Column containing upper left corner of object |
* @param integer $dxL Distance from left side of cell |
* @param integer $rwT Row containing top left corner of object |
* @param integer $dyT Distance from top of cell |
* @param integer $colR Column containing lower right corner of object |
* @param integer $dxR Distance from right of cell |
* @param integer $rwB Row containing bottom right corner of object |
* @param integer $dyB Distance from bottom of cell |
*/ |
function _storeObjPicture($colL,$dxL,$rwT,$dyT,$colR,$dxR,$rwB,$dyB) |
{ |
$record = 0x005d; // Record identifier |
$length = 0x003c; // Bytes to follow |
$cObj = 0x0001; // Count of objects in file (set to 1) |
$OT = 0x0008; // Object type. 8 = Picture |
$id = 0x0001; // Object ID |
$grbit = 0x0614; // Option flags |
$cbMacro = 0x0000; // Length of FMLA structure |
$Reserved1 = 0x0000; // Reserved |
$Reserved2 = 0x0000; // Reserved |
$icvBack = 0x09; // Background colour |
$icvFore = 0x09; // Foreground colour |
$fls = 0x00; // Fill pattern |
$fAuto = 0x00; // Automatic fill |
$icv = 0x08; // Line colour |
$lns = 0xff; // Line style |
$lnw = 0x01; // Line weight |
$fAutoB = 0x00; // Automatic border |
$frs = 0x0000; // Frame style |
$cf = 0x0009; // Image format, 9 = bitmap |
$Reserved3 = 0x0000; // Reserved |
$cbPictFmla = 0x0000; // Length of FMLA structure |
$Reserved4 = 0x0000; // Reserved |
$grbit2 = 0x0001; // Option flags |
$Reserved5 = 0x0000; // Reserved |
$header = pack("vv", $record, $length); |
$data = pack("V", $cObj); |
$data .= pack("v", $OT); |
$data .= pack("v", $id); |
$data .= pack("v", $grbit); |
$data .= pack("v", $colL); |
$data .= pack("v", $dxL); |
$data .= pack("v", $rwT); |
$data .= pack("v", $dyT); |
$data .= pack("v", $colR); |
$data .= pack("v", $dxR); |
$data .= pack("v", $rwB); |
$data .= pack("v", $dyB); |
$data .= pack("v", $cbMacro); |
$data .= pack("V", $Reserved1); |
$data .= pack("v", $Reserved2); |
$data .= pack("C", $icvBack); |
$data .= pack("C", $icvFore); |
$data .= pack("C", $fls); |
$data .= pack("C", $fAuto); |
$data .= pack("C", $icv); |
$data .= pack("C", $lns); |
$data .= pack("C", $lnw); |
$data .= pack("C", $fAutoB); |
$data .= pack("v", $frs); |
$data .= pack("V", $cf); |
$data .= pack("v", $Reserved3); |
$data .= pack("v", $cbPictFmla); |
$data .= pack("v", $Reserved4); |
$data .= pack("v", $grbit2); |
$data .= pack("V", $Reserved5); |
$this->_append($header.$data); |
} |
/** |
* Convert a 24 bit bitmap into the modified internal format used by Windows. |
* This is described in BITMAPCOREHEADER and BITMAPCOREINFO structures in the |
* MSDN library. |
* |
* @access private |
* @param string $bitmap The bitmap to process |
* @return array Array with data and properties of the bitmap |
*/ |
function _processBitmap($bitmap) |
{ |
// Open file. |
$bmp_fd = @fopen($bitmap,"rb"); |
if (!$bmp_fd) { |
return($this->raiseError("Couldn't import $bitmap")); |
} |
// Slurp the file into a string. |
$data = fread($bmp_fd, filesize($bitmap)); |
// Check that the file is big enough to be a bitmap. |
if (strlen($data) <= 0x36) { |
return($this->raiseError("$bitmap doesn't contain enough data.\n")); |
} |
// The first 2 bytes are used to identify the bitmap. |
$identity = unpack("A2", $data); |
if ($identity[''] != "BM") { |
return($this->raiseError("$bitmap doesn't appear to be a valid bitmap image.\n")); |
} |
// Remove bitmap data: ID. |
$data = substr($data, 2); |
// Read and remove the bitmap size. This is more reliable than reading |
// the data size at offset 0x22. |
// |
$size_array = unpack("V", substr($data, 0, 4)); |
$size = $size_array['']; |
$data = substr($data, 4); |
$size -= 0x36; // Subtract size of bitmap header. |
$size += 0x0C; // Add size of BIFF header. |
// Remove bitmap data: reserved, offset, header length. |
$data = substr($data, 12); |
// Read and remove the bitmap width and height. Verify the sizes. |
$width_and_height = unpack("V2", substr($data, 0, 8)); |
$width = $width_and_height[1]; |
$height = $width_and_height[2]; |
$data = substr($data, 8); |
if ($width > 0xFFFF) { |
return($this->raiseError("$bitmap: largest image width supported is 65k.\n")); |
} |
if ($height > 0xFFFF) { |
return($this->raiseError("$bitmap: largest image height supported is 65k.\n")); |
} |
// Read and remove the bitmap planes and bpp data. Verify them. |
$planes_and_bitcount = unpack("v2", substr($data, 0, 4)); |
$data = substr($data, 4); |
if ($planes_and_bitcount[2] != 24) { // Bitcount |
return($this->raiseError("$bitmap isn't a 24bit true color bitmap.\n")); |
} |
if ($planes_and_bitcount[1] != 1) { |
return($this->raiseError("$bitmap: only 1 plane nupported in bitmap image.\n")); |
} |
// Read and remove the bitmap compression. Verify compression. |
$compression = unpack("V", substr($data, 0, 4)); |
$data = substr($data, 4); |
//$compression = 0; |
if ($compression[""] != 0) { |
return($this->raiseError("$bitmap: compression not supported in bitmap image.\n")); |
} |
// Remove bitmap data: data size, hres, vres, colours, imp. colours. |
$data = substr($data, 20); |
// Add the BITMAPCOREHEADER data |
$header = pack("Vvvvv", 0x000c, $width, $height, 0x01, 0x18); |
$data = $header . $data; |
return (array($width, $height, $size, $data)); |
} |
/** |
* Store the window zoom factor. This should be a reduced fraction but for |
* simplicity we will store all fractions with a numerator of 100. |
* |
* @access private |
*/ |
function _storeZoom() |
{ |
// If scale is 100 we don't need to write a record |
if ($this->_zoom == 100) { |
return; |
} |
$record = 0x00A0; // Record identifier |
$length = 0x0004; // Bytes to follow |
$header = pack("vv", $record, $length); |
$data = pack("vv", $this->_zoom, 100); |
$this->_append($header.$data); |
} |
} |
?> |
/trunk/jrest/lib/Spreadsheet/Excel/Writer/OLEwriter.php |
---|
New file |
0,0 → 1,428 |
<?php |
/* |
* Module written/ported by Xavier Noguer <xnoguer@rezebra.com> |
* |
* The majority of this is _NOT_ my code. I simply ported it from the |
* PERL Spreadsheet::WriteExcel module. |
* |
* The author of the Spreadsheet::WriteExcel module is John McNamara |
* <jmcnamara@cpan.org> |
* |
* I _DO_ maintain this code, and John McNamara has nothing to do with the |
* porting of this code to PHP. Any questions directly related to this |
* class library should be directed to me. |
* |
* License Information: |
* |
* Spreadsheet_Excel_Writer: A library for generating Excel Spreadsheets |
* Copyright (c) 2002-2003 Xavier Noguer xnoguer@rezebra.com |
* |
* This library is free software; you can redistribute it and/or |
* modify it under the terms of the GNU Lesser General Public |
* License as published by the Free Software Foundation; either |
* version 2.1 of the License, or (at your option) any later version. |
* |
* This library is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
* Lesser General Public License for more details. |
* |
* You should have received a copy of the GNU Lesser General Public |
* License along with this library; if not, write to the Free Software |
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
*/ |
require_once('PEAR.php'); |
/** |
* Class for creating OLE streams for Excel Spreadsheets |
* |
* @author Xavier Noguer <xnoguer@rezebra.com> |
* @category FileFormats |
* @package Spreadsheet_Excel_Writer |
*/ |
class Spreadsheet_Excel_Writer_OLEwriter extends PEAR |
{ |
/** |
* Filename for the OLE stream |
* @var string |
* @see _initialize() |
*/ |
var $_OLEfilename; |
/** |
* Filehandle for the OLE stream |
* @var resource |
*/ |
var $_filehandle; |
/** |
* Name of the temporal file in case OLE stream goes to stdout |
* @var string |
*/ |
var $_tmp_filename; |
/** |
* Variable for preventing closing two times |
* @var integer |
*/ |
var $_fileclosed; |
/** |
* Size of the data to be written to the OLE stream |
* @var integer |
*/ |
var $_biffsize; |
/** |
* Real data size to be written to the OLE stream |
* @var integer |
*/ |
var $_booksize; |
/** |
* Number of big blocks in the OLE stream |
* @var integer |
*/ |
var $_big_blocks; |
/** |
* Number of list blocks in the OLE stream |
* @var integer |
*/ |
var $_list_blocks; |
/** |
* Number of big blocks in the OLE stream |
* @var integer |
*/ |
var $_root_start; |
/** |
* Constructor for the OLEwriter class |
* |
* @param string $OLEfilename the name of the file for the OLE stream |
*/ |
function Spreadsheet_Excel_Writer_OLEwriter($OLEfilename) |
{ |
$this->_OLEfilename = $OLEfilename; |
$this->_filehandle = ""; |
$this->_tmp_filename = ""; |
$this->_fileclosed = 0; |
$this->_biff_only = 0; |
//$this->_size_allowed = 0; |
$this->_biffsize = 0; |
$this->_booksize = 0; |
$this->_big_blocks = 0; |
$this->_list_blocks = 0; |
$this->_root_start = 0; |
//$this->_block_count = 4; |
$this->_initialize(); |
} |
/** |
* Check for a valid filename and store the filehandle. |
* Filehandle "-" writes to STDOUT |
* |
* @access private |
*/ |
function _initialize() |
{ |
$OLEfile = $this->_OLEfilename; |
if(($OLEfile == '-') or ($OLEfile == '')) |
{ |
$this->_tmp_filename = tempnam("/tmp", "OLEwriter"); |
$fh = fopen($this->_tmp_filename,"wb"); |
if ($fh == false) { |
$this->raiseError("Can't create temporary file."); |
} |
} |
else |
{ |
// Create a new file, open for writing (in binmode) |
$fh = fopen($OLEfile,"wb"); |
if ($fh == false) { |
$this->raiseError("Can't open $OLEfile. It may be in use or protected."); |
} |
} |
// Store filehandle |
$this->_filehandle = $fh; |
} |
/** |
* Set the size of the data to be written to the OLE stream. |
* The maximun size comes from this: |
* $big_blocks = (109 depot block x (128 -1 marker word) |
* - (1 x end words)) = 13842 |
* $maxsize = $big_blocks * 512 bytes = 7087104 |
* |
* @access public |
* @see Spreadsheet_Excel_Writer_Workbook::store_OLE_file() |
* @param integer $biffsize The size of the data to be written to the OLE stream |
* @return integer 1 for success |
*/ |
function setSize($biffsize) |
{ |
$maxsize = 7087104; // TODO: extend max size |
if ($biffsize > $maxsize) { |
$this->raiseError("Maximum file size, $maxsize, exceeded."); |
} |
$this->_biffsize = $biffsize; |
// Set the min file size to 4k to avoid having to use small blocks |
if ($biffsize > 4096) { |
$this->_booksize = $biffsize; |
} |
else { |
$this->_booksize = 4096; |
} |
//$this->_size_allowed = 1; |
return(1); |
} |
/** |
* Calculate various sizes needed for the OLE stream |
* |
* @access private |
*/ |
function _calculateSizes() |
{ |
$datasize = $this->_booksize; |
if ($datasize % 512 == 0) { |
$this->_big_blocks = $datasize/512; |
} |
else { |
$this->_big_blocks = floor($datasize/512) + 1; |
} |
// There are 127 list blocks and 1 marker blocks for each big block |
// depot + 1 end of chain block |
$this->_list_blocks = floor(($this->_big_blocks)/127) + 1; |
$this->_root_start = $this->_big_blocks; |
} |
/** |
* Write root entry, big block list and close the filehandle. |
* This routine is used to explicitly close the open filehandle without |
* having to wait for DESTROY. |
* |
* @access public |
* @see Spreadsheet_Excel_Writer_Workbook::store_OLE_file() |
*/ |
function close() |
{ |
//return if not $this->{_size_allowed}; |
$this->_writePadding(); |
$this->_writePropertyStorage(); |
$this->_writeBigBlockDepot(); |
// Close the filehandle |
fclose($this->_filehandle); |
if(($this->_OLEfilename == '-') or ($this->_OLEfilename == '')) |
{ |
$fh = fopen($this->_tmp_filename, "rb"); |
if ($fh == false) { |
$this->raiseError("Can't read temporary file."); |
} |
fpassthru($fh); |
@unlink($this->_tmp_filename); |
} |
$this->_fileclosed = 1; |
} |
/** |
* Write BIFF data to OLE file. |
* |
* @param string $data string of bytes to be written |
*/ |
function write($data) |
{ |
fwrite($this->_filehandle,$data,strlen($data)); |
} |
/** |
* Write OLE header block. |
*/ |
function writeHeader() |
{ |
$this->_calculateSizes(); |
$root_start = $this->_root_start; |
$num_lists = $this->_list_blocks; |
$id = pack("nnnn", 0xD0CF, 0x11E0, 0xA1B1, 0x1AE1); |
$unknown1 = pack("VVVV", 0x00, 0x00, 0x00, 0x00); |
$unknown2 = pack("vv", 0x3E, 0x03); |
$unknown3 = pack("v", -2); |
$unknown4 = pack("v", 0x09); |
$unknown5 = pack("VVV", 0x06, 0x00, 0x00); |
$num_bbd_blocks = pack("V", $num_lists); |
$root_startblock = pack("V", $root_start); |
$unknown6 = pack("VV", 0x00, 0x1000); |
$sbd_startblock = pack("V", -2); |
$unknown7 = pack("VVV", 0x00, -2 ,0x00); |
$unused = pack("V", -1); |
fwrite($this->_filehandle,$id); |
fwrite($this->_filehandle,$unknown1); |
fwrite($this->_filehandle,$unknown2); |
fwrite($this->_filehandle,$unknown3); |
fwrite($this->_filehandle,$unknown4); |
fwrite($this->_filehandle,$unknown5); |
fwrite($this->_filehandle,$num_bbd_blocks); |
fwrite($this->_filehandle,$root_startblock); |
fwrite($this->_filehandle,$unknown6); |
fwrite($this->_filehandle,$sbd_startblock); |
fwrite($this->_filehandle,$unknown7); |
for($i=1; $i <= $num_lists; $i++) |
{ |
$root_start++; |
fwrite($this->_filehandle,pack("V",$root_start)); |
} |
for($i = $num_lists; $i <=108; $i++) |
{ |
fwrite($this->_filehandle,$unused); |
} |
} |
/** |
* Write big block depot. |
* |
* @access private |
*/ |
function _writeBigBlockDepot() |
{ |
$num_blocks = $this->_big_blocks; |
$num_lists = $this->_list_blocks; |
$total_blocks = $num_lists *128; |
$used_blocks = $num_blocks + $num_lists +2; |
$marker = pack("V", -3); |
$end_of_chain = pack("V", -2); |
$unused = pack("V", -1); |
for($i=1; $i < $num_blocks; $i++) |
{ |
fwrite($this->_filehandle,pack("V",$i)); |
} |
fwrite($this->_filehandle,$end_of_chain); |
fwrite($this->_filehandle,$end_of_chain); |
for($i=0; $i < $num_lists; $i++) |
{ |
fwrite($this->_filehandle,$marker); |
} |
for($i=$used_blocks; $i <= $total_blocks; $i++) |
{ |
fwrite($this->_filehandle,$unused); |
} |
} |
/** |
* Write property storage. TODO: add summary sheets |
* |
* @access private |
*/ |
function _writePropertyStorage() |
{ |
//$rootsize = -2; |
/*************** name type dir start size */ |
$this->_writePps("Root Entry", 0x05, 1, -2, 0x00); |
$this->_writePps("Book", 0x02, -1, 0x00, $this->_booksize); |
$this->_writePps('', 0x00, -1, 0x00, 0x0000); |
$this->_writePps('', 0x00, -1, 0x00, 0x0000); |
} |
/** |
* Write property sheet in property storage |
* |
* @param string $name name of the property storage. |
* @param integer $type type of the property storage. |
* @param integer $dir dir of the property storage. |
* @param integer $start start of the property storage. |
* @param integer $size size of the property storage. |
* @access private |
*/ |
function _writePps($name,$type,$dir,$start,$size) |
{ |
$length = 0; |
$rawname = ''; |
if ($name != '') |
{ |
$name = $name . "\0"; |
for($i=0;$i<strlen($name);$i++) |
{ |
// Simulate a Unicode string |
$rawname .= pack("H*",dechex(ord($name{$i}))).pack("C",0); |
} |
$length = strlen($name) * 2; |
} |
$zero = pack("C", 0); |
$pps_sizeofname = pack("v", $length); // 0x40 |
$pps_type = pack("v", $type); // 0x42 |
$pps_prev = pack("V", -1); // 0x44 |
$pps_next = pack("V", -1); // 0x48 |
$pps_dir = pack("V", $dir); // 0x4c |
$unknown1 = pack("V", 0); |
$pps_ts1s = pack("V", 0); // 0x64 |
$pps_ts1d = pack("V", 0); // 0x68 |
$pps_ts2s = pack("V", 0); // 0x6c |
$pps_ts2d = pack("V", 0); // 0x70 |
$pps_sb = pack("V", $start); // 0x74 |
$pps_size = pack("V", $size); // 0x78 |
fwrite($this->_filehandle,$rawname); |
for($i=0; $i < (64 -$length); $i++) { |
fwrite($this->_filehandle,$zero); |
} |
fwrite($this->_filehandle,$pps_sizeofname); |
fwrite($this->_filehandle,$pps_type); |
fwrite($this->_filehandle,$pps_prev); |
fwrite($this->_filehandle,$pps_next); |
fwrite($this->_filehandle,$pps_dir); |
for($i=0; $i < 5; $i++) { |
fwrite($this->_filehandle,$unknown1); |
} |
fwrite($this->_filehandle,$pps_ts1s); |
fwrite($this->_filehandle,$pps_ts1d); |
fwrite($this->_filehandle,$pps_ts2d); |
fwrite($this->_filehandle,$pps_ts2d); |
fwrite($this->_filehandle,$pps_sb); |
fwrite($this->_filehandle,$pps_size); |
fwrite($this->_filehandle,$unknown1); |
} |
/** |
* Pad the end of the file |
* |
* @access private |
*/ |
function _writePadding() |
{ |
$biffsize = $this->_biffsize; |
if ($biffsize < 4096) { |
$min_size = 4096; |
} |
else { |
$min_size = 512; |
} |
if ($biffsize % $min_size != 0) |
{ |
$padding = $min_size - ($biffsize % $min_size); |
for($i=0; $i < $padding; $i++) { |
fwrite($this->_filehandle,"\0"); |
} |
} |
} |
} |
?> |
/trunk/jrest/lib/Spreadsheet/Excel/Writer/Parser.php |
---|
New file |
0,0 → 1,1551 |
<?php |
/** |
* Class for parsing Excel formulas |
* |
* License Information: |
* |
* Spreadsheet_Excel_Writer: A library for generating Excel Spreadsheets |
* Copyright (c) 2002-2003 Xavier Noguer xnoguer@rezebra.com |
* |
* This library is free software; you can redistribute it and/or |
* modify it under the terms of the GNU Lesser General Public |
* License as published by the Free Software Foundation; either |
* version 2.1 of the License, or (at your option) any later version. |
* |
* This library is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
* Lesser General Public License for more details. |
* |
* You should have received a copy of the GNU Lesser General Public |
* License along with this library; if not, write to the Free Software |
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
*/ |
/** |
* @const SPREADSHEET_EXCEL_WRITER_ADD token identifier for character "+" |
*/ |
define('SPREADSHEET_EXCEL_WRITER_ADD',"+"); |
/** |
* @const SPREADSHEET_EXCEL_WRITER_SUB token identifier for character "-" |
*/ |
define('SPREADSHEET_EXCEL_WRITER_SUB',"-"); |
/** |
* @const SPREADSHEET_EXCEL_WRITER_MUL token identifier for character "*" |
*/ |
define('SPREADSHEET_EXCEL_WRITER_MUL',"*"); |
/** |
* @const SPREADSHEET_EXCEL_WRITER_DIV token identifier for character "/" |
*/ |
define('SPREADSHEET_EXCEL_WRITER_DIV',"/"); |
/** |
* @const SPREADSHEET_EXCEL_WRITER_OPEN token identifier for character "(" |
*/ |
define('SPREADSHEET_EXCEL_WRITER_OPEN',"("); |
/** |
* @const SPREADSHEET_EXCEL_WRITER_CLOSE token identifier for character ")" |
*/ |
define('SPREADSHEET_EXCEL_WRITER_CLOSE',")"); |
/** |
* @const SPREADSHEET_EXCEL_WRITER_COMA token identifier for character "," |
*/ |
define('SPREADSHEET_EXCEL_WRITER_COMA',","); |
/** |
* @const SPREADSHEET_EXCEL_WRITER_GT token identifier for character ">" |
*/ |
define('SPREADSHEET_EXCEL_WRITER_GT',">"); |
/** |
* @const SPREADSHEET_EXCEL_WRITER_LT token identifier for character "<" |
*/ |
define('SPREADSHEET_EXCEL_WRITER_LT',"<"); |
/** |
* @const SPREADSHEET_EXCEL_WRITER_LE token identifier for character "<=" |
*/ |
define('SPREADSHEET_EXCEL_WRITER_LE',"<="); |
/** |
* @const SPREADSHEET_EXCEL_WRITER_GE token identifier for character ">=" |
*/ |
define('SPREADSHEET_EXCEL_WRITER_GE',">="); |
/** |
* @const SPREADSHEET_EXCEL_WRITER_EQ token identifier for character "=" |
*/ |
define('SPREADSHEET_EXCEL_WRITER_EQ',"="); |
/** |
* @const SPREADSHEET_EXCEL_WRITER_NE token identifier for character "<>" |
*/ |
define('SPREADSHEET_EXCEL_WRITER_NE',"<>"); |
require_once('PEAR.php'); |
/** |
* Class for parsing Excel formulas |
* |
* @author Xavier Noguer <xnoguer@rezebra.com> |
* @category FileFormats |
* @package Spreadsheet_Excel_Writer |
*/ |
class Spreadsheet_Excel_Writer_Parser extends PEAR |
{ |
/** |
* The index of the character we are currently looking at |
* @var integer |
*/ |
var $_current_char; |
/** |
* The token we are working on. |
* @var string |
*/ |
var $_current_token; |
/** |
* The formula to parse |
* @var string |
*/ |
var $_formula; |
/** |
* The character ahead of the current char |
* @var string |
*/ |
var $_lookahead; |
/** |
* The parse tree to be generated |
* @var string |
*/ |
var $_parse_tree; |
/** |
* The byte order. 1 => big endian, 0 => little endian. |
* @var integer |
*/ |
var $_byte_order; |
/** |
* Number of arguments for the current function |
* @var integer |
*/ |
var $_func_args; |
/** |
* Array of external sheets |
* @var array |
*/ |
var $_ext_sheets; |
/** |
* The class constructor |
* |
* @param integer $byte_order The byte order (Little endian or Big endian) of the architecture |
(optional). 1 => big endian, 0 (default) => little endian. |
*/ |
function Spreadsheet_Excel_Writer_Parser($byte_order = 0) |
{ |
$this->_current_char = 0; |
$this->_current_token = ''; // The token we are working on. |
$this->_formula = ""; // The formula to parse. |
$this->_lookahead = ''; // The character ahead of the current char. |
$this->_parse_tree = ''; // The parse tree to be generated. |
$this->_initializeHashes(); // Initialize the hashes: ptg's and function's ptg's |
$this->_byte_order = $byte_order; // Little Endian or Big Endian |
$this->_func_args = 0; // Number of arguments for the current function |
$this->_ext_sheets = array(); |
} |
/** |
* Initialize the ptg and function hashes. |
* |
* @access private |
*/ |
function _initializeHashes() |
{ |
// The Excel ptg indices |
$this->ptg = array( |
'ptgExp' => 0x01, |
'ptgTbl' => 0x02, |
'ptgAdd' => 0x03, |
'ptgSub' => 0x04, |
'ptgMul' => 0x05, |
'ptgDiv' => 0x06, |
'ptgPower' => 0x07, |
'ptgConcat' => 0x08, |
'ptgLT' => 0x09, |
'ptgLE' => 0x0A, |
'ptgEQ' => 0x0B, |
'ptgGE' => 0x0C, |
'ptgGT' => 0x0D, |
'ptgNE' => 0x0E, |
'ptgIsect' => 0x0F, |
'ptgUnion' => 0x10, |
'ptgRange' => 0x11, |
'ptgUplus' => 0x12, |
'ptgUminus' => 0x13, |
'ptgPercent' => 0x14, |
'ptgParen' => 0x15, |
'ptgMissArg' => 0x16, |
'ptgStr' => 0x17, |
'ptgAttr' => 0x19, |
'ptgSheet' => 0x1A, |
'ptgEndSheet' => 0x1B, |
'ptgErr' => 0x1C, |
'ptgBool' => 0x1D, |
'ptgInt' => 0x1E, |
'ptgNum' => 0x1F, |
'ptgArray' => 0x20, |
'ptgFunc' => 0x21, |
'ptgFuncVar' => 0x22, |
'ptgName' => 0x23, |
'ptgRef' => 0x24, |
'ptgArea' => 0x25, |
'ptgMemArea' => 0x26, |
'ptgMemErr' => 0x27, |
'ptgMemNoMem' => 0x28, |
'ptgMemFunc' => 0x29, |
'ptgRefErr' => 0x2A, |
'ptgAreaErr' => 0x2B, |
'ptgRefN' => 0x2C, |
'ptgAreaN' => 0x2D, |
'ptgMemAreaN' => 0x2E, |
'ptgMemNoMemN' => 0x2F, |
'ptgNameX' => 0x39, |
'ptgRef3d' => 0x3A, |
'ptgArea3d' => 0x3B, |
'ptgRefErr3d' => 0x3C, |
'ptgAreaErr3d' => 0x3D, |
'ptgArrayV' => 0x40, |
'ptgFuncV' => 0x41, |
'ptgFuncVarV' => 0x42, |
'ptgNameV' => 0x43, |
'ptgRefV' => 0x44, |
'ptgAreaV' => 0x45, |
'ptgMemAreaV' => 0x46, |
'ptgMemErrV' => 0x47, |
'ptgMemNoMemV' => 0x48, |
'ptgMemFuncV' => 0x49, |
'ptgRefErrV' => 0x4A, |
'ptgAreaErrV' => 0x4B, |
'ptgRefNV' => 0x4C, |
'ptgAreaNV' => 0x4D, |
'ptgMemAreaNV' => 0x4E, |
'ptgMemNoMemN' => 0x4F, |
'ptgFuncCEV' => 0x58, |
'ptgNameXV' => 0x59, |
'ptgRef3dV' => 0x5A, |
'ptgArea3dV' => 0x5B, |
'ptgRefErr3dV' => 0x5C, |
'ptgAreaErr3d' => 0x5D, |
'ptgArrayA' => 0x60, |
'ptgFuncA' => 0x61, |
'ptgFuncVarA' => 0x62, |
'ptgNameA' => 0x63, |
'ptgRefA' => 0x64, |
'ptgAreaA' => 0x65, |
'ptgMemAreaA' => 0x66, |
'ptgMemErrA' => 0x67, |
'ptgMemNoMemA' => 0x68, |
'ptgMemFuncA' => 0x69, |
'ptgRefErrA' => 0x6A, |
'ptgAreaErrA' => 0x6B, |
'ptgRefNA' => 0x6C, |
'ptgAreaNA' => 0x6D, |
'ptgMemAreaNA' => 0x6E, |
'ptgMemNoMemN' => 0x6F, |
'ptgFuncCEA' => 0x78, |
'ptgNameXA' => 0x79, |
'ptgRef3dA' => 0x7A, |
'ptgArea3dA' => 0x7B, |
'ptgRefErr3dA' => 0x7C, |
'ptgAreaErr3d' => 0x7D |
); |
// Thanks to Michael Meeks and Gnumeric for the initial arg values. |
// |
// The following hash was generated by "function_locale.pl" in the distro. |
// Refer to function_locale.pl for non-English function names. |
// |
// The array elements are as follow: |
// ptg: The Excel function ptg code. |
// args: The number of arguments that the function takes: |
// >=0 is a fixed number of arguments. |
// -1 is a variable number of arguments. |
// class: The reference, value or array class of the function args. |
// vol: The function is volatile. |
// |
$this->_functions = array( |
// function ptg args class vol |
'COUNT' => array( 0, -1, 0, 0 ), |
'IF' => array( 1, -1, 1, 0 ), |
'ISNA' => array( 2, 1, 1, 0 ), |
'ISERROR' => array( 3, 1, 1, 0 ), |
'SUM' => array( 4, -1, 0, 0 ), |
'AVERAGE' => array( 5, -1, 0, 0 ), |
'MIN' => array( 6, -1, 0, 0 ), |
'MAX' => array( 7, -1, 0, 0 ), |
'ROW' => array( 8, -1, 0, 0 ), |
'COLUMN' => array( 9, -1, 0, 0 ), |
'NA' => array( 10, 0, 0, 0 ), |
'NPV' => array( 11, -1, 1, 0 ), |
'STDEV' => array( 12, -1, 0, 0 ), |
'DOLLAR' => array( 13, -1, 1, 0 ), |
'FIXED' => array( 14, -1, 1, 0 ), |
'SIN' => array( 15, 1, 1, 0 ), |
'COS' => array( 16, 1, 1, 0 ), |
'TAN' => array( 17, 1, 1, 0 ), |
'ATAN' => array( 18, 1, 1, 0 ), |
'PI' => array( 19, 0, 1, 0 ), |
'SQRT' => array( 20, 1, 1, 0 ), |
'EXP' => array( 21, 1, 1, 0 ), |
'LN' => array( 22, 1, 1, 0 ), |
'LOG10' => array( 23, 1, 1, 0 ), |
'ABS' => array( 24, 1, 1, 0 ), |
'INT' => array( 25, 1, 1, 0 ), |
'SIGN' => array( 26, 1, 1, 0 ), |
'ROUND' => array( 27, 2, 1, 0 ), |
'LOOKUP' => array( 28, -1, 0, 0 ), |
'INDEX' => array( 29, -1, 0, 1 ), |
'REPT' => array( 30, 2, 1, 0 ), |
'MID' => array( 31, 3, 1, 0 ), |
'LEN' => array( 32, 1, 1, 0 ), |
'VALUE' => array( 33, 1, 1, 0 ), |
'TRUE' => array( 34, 0, 1, 0 ), |
'FALSE' => array( 35, 0, 1, 0 ), |
'AND' => array( 36, -1, 0, 0 ), |
'OR' => array( 37, -1, 0, 0 ), |
'NOT' => array( 38, 1, 1, 0 ), |
'MOD' => array( 39, 2, 1, 0 ), |
'DCOUNT' => array( 40, 3, 0, 0 ), |
'DSUM' => array( 41, 3, 0, 0 ), |
'DAVERAGE' => array( 42, 3, 0, 0 ), |
'DMIN' => array( 43, 3, 0, 0 ), |
'DMAX' => array( 44, 3, 0, 0 ), |
'DSTDEV' => array( 45, 3, 0, 0 ), |
'VAR' => array( 46, -1, 0, 0 ), |
'DVAR' => array( 47, 3, 0, 0 ), |
'TEXT' => array( 48, 2, 1, 0 ), |
'LINEST' => array( 49, -1, 0, 0 ), |
'TREND' => array( 50, -1, 0, 0 ), |
'LOGEST' => array( 51, -1, 0, 0 ), |
'GROWTH' => array( 52, -1, 0, 0 ), |
'PV' => array( 56, -1, 1, 0 ), |
'FV' => array( 57, -1, 1, 0 ), |
'NPER' => array( 58, -1, 1, 0 ), |
'PMT' => array( 59, -1, 1, 0 ), |
'RATE' => array( 60, -1, 1, 0 ), |
'MIRR' => array( 61, 3, 0, 0 ), |
'IRR' => array( 62, -1, 0, 0 ), |
'RAND' => array( 63, 0, 1, 1 ), |
'MATCH' => array( 64, -1, 0, 0 ), |
'DATE' => array( 65, 3, 1, 0 ), |
'TIME' => array( 66, 3, 1, 0 ), |
'DAY' => array( 67, 1, 1, 0 ), |
'MONTH' => array( 68, 1, 1, 0 ), |
'YEAR' => array( 69, 1, 1, 0 ), |
'WEEKDAY' => array( 70, -1, 1, 0 ), |
'HOUR' => array( 71, 1, 1, 0 ), |
'MINUTE' => array( 72, 1, 1, 0 ), |
'SECOND' => array( 73, 1, 1, 0 ), |
'NOW' => array( 74, 0, 1, 1 ), |
'AREAS' => array( 75, 1, 0, 1 ), |
'ROWS' => array( 76, 1, 0, 1 ), |
'COLUMNS' => array( 77, 1, 0, 1 ), |
'OFFSET' => array( 78, -1, 0, 1 ), |
'SEARCH' => array( 82, -1, 1, 0 ), |
'TRANSPOSE' => array( 83, 1, 1, 0 ), |
'TYPE' => array( 86, 1, 1, 0 ), |
'ATAN2' => array( 97, 2, 1, 0 ), |
'ASIN' => array( 98, 1, 1, 0 ), |
'ACOS' => array( 99, 1, 1, 0 ), |
'CHOOSE' => array( 100, -1, 1, 0 ), |
'HLOOKUP' => array( 101, -1, 0, 0 ), |
'VLOOKUP' => array( 102, -1, 0, 0 ), |
'ISREF' => array( 105, 1, 0, 0 ), |
'LOG' => array( 109, -1, 1, 0 ), |
'CHAR' => array( 111, 1, 1, 0 ), |
'LOWER' => array( 112, 1, 1, 0 ), |
'UPPER' => array( 113, 1, 1, 0 ), |
'PROPER' => array( 114, 1, 1, 0 ), |
'LEFT' => array( 115, -1, 1, 0 ), |
'RIGHT' => array( 116, -1, 1, 0 ), |
'EXACT' => array( 117, 2, 1, 0 ), |
'TRIM' => array( 118, 1, 1, 0 ), |
'REPLACE' => array( 119, 4, 1, 0 ), |
'SUBSTITUTE' => array( 120, -1, 1, 0 ), |
'CODE' => array( 121, 1, 1, 0 ), |
'FIND' => array( 124, -1, 1, 0 ), |
'CELL' => array( 125, -1, 0, 1 ), |
'ISERR' => array( 126, 1, 1, 0 ), |
'ISTEXT' => array( 127, 1, 1, 0 ), |
'ISNUMBER' => array( 128, 1, 1, 0 ), |
'ISBLANK' => array( 129, 1, 1, 0 ), |
'T' => array( 130, 1, 0, 0 ), |
'N' => array( 131, 1, 0, 0 ), |
'DATEVALUE' => array( 140, 1, 1, 0 ), |
'TIMEVALUE' => array( 141, 1, 1, 0 ), |
'SLN' => array( 142, 3, 1, 0 ), |
'SYD' => array( 143, 4, 1, 0 ), |
'DDB' => array( 144, -1, 1, 0 ), |
'INDIRECT' => array( 148, -1, 1, 1 ), |
'CALL' => array( 150, -1, 1, 0 ), |
'CLEAN' => array( 162, 1, 1, 0 ), |
'MDETERM' => array( 163, 1, 2, 0 ), |
'MINVERSE' => array( 164, 1, 2, 0 ), |
'MMULT' => array( 165, 2, 2, 0 ), |
'IPMT' => array( 167, -1, 1, 0 ), |
'PPMT' => array( 168, -1, 1, 0 ), |
'COUNTA' => array( 169, -1, 0, 0 ), |
'PRODUCT' => array( 183, -1, 0, 0 ), |
'FACT' => array( 184, 1, 1, 0 ), |
'DPRODUCT' => array( 189, 3, 0, 0 ), |
'ISNONTEXT' => array( 190, 1, 1, 0 ), |
'STDEVP' => array( 193, -1, 0, 0 ), |
'VARP' => array( 194, -1, 0, 0 ), |
'DSTDEVP' => array( 195, 3, 0, 0 ), |
'DVARP' => array( 196, 3, 0, 0 ), |
'TRUNC' => array( 197, -1, 1, 0 ), |
'ISLOGICAL' => array( 198, 1, 1, 0 ), |
'DCOUNTA' => array( 199, 3, 0, 0 ), |
'ROUNDUP' => array( 212, 2, 1, 0 ), |
'ROUNDDOWN' => array( 213, 2, 1, 0 ), |
'RANK' => array( 216, -1, 0, 0 ), |
'ADDRESS' => array( 219, -1, 1, 0 ), |
'DAYS360' => array( 220, -1, 1, 0 ), |
'TODAY' => array( 221, 0, 1, 1 ), |
'VDB' => array( 222, -1, 1, 0 ), |
'MEDIAN' => array( 227, -1, 0, 0 ), |
'SUMPRODUCT' => array( 228, -1, 2, 0 ), |
'SINH' => array( 229, 1, 1, 0 ), |
'COSH' => array( 230, 1, 1, 0 ), |
'TANH' => array( 231, 1, 1, 0 ), |
'ASINH' => array( 232, 1, 1, 0 ), |
'ACOSH' => array( 233, 1, 1, 0 ), |
'ATANH' => array( 234, 1, 1, 0 ), |
'DGET' => array( 235, 3, 0, 0 ), |
'INFO' => array( 244, 1, 1, 1 ), |
'DB' => array( 247, -1, 1, 0 ), |
'FREQUENCY' => array( 252, 2, 0, 0 ), |
'ERROR.TYPE' => array( 261, 1, 1, 0 ), |
'REGISTER.ID' => array( 267, -1, 1, 0 ), |
'AVEDEV' => array( 269, -1, 0, 0 ), |
'BETADIST' => array( 270, -1, 1, 0 ), |
'GAMMALN' => array( 271, 1, 1, 0 ), |
'BETAINV' => array( 272, -1, 1, 0 ), |
'BINOMDIST' => array( 273, 4, 1, 0 ), |
'CHIDIST' => array( 274, 2, 1, 0 ), |
'CHIINV' => array( 275, 2, 1, 0 ), |
'COMBIN' => array( 276, 2, 1, 0 ), |
'CONFIDENCE' => array( 277, 3, 1, 0 ), |
'CRITBINOM' => array( 278, 3, 1, 0 ), |
'EVEN' => array( 279, 1, 1, 0 ), |
'EXPONDIST' => array( 280, 3, 1, 0 ), |
'FDIST' => array( 281, 3, 1, 0 ), |
'FINV' => array( 282, 3, 1, 0 ), |
'FISHER' => array( 283, 1, 1, 0 ), |
'FISHERINV' => array( 284, 1, 1, 0 ), |
'FLOOR' => array( 285, 2, 1, 0 ), |
'GAMMADIST' => array( 286, 4, 1, 0 ), |
'GAMMAINV' => array( 287, 3, 1, 0 ), |
'CEILING' => array( 288, 2, 1, 0 ), |
'HYPGEOMDIST' => array( 289, 4, 1, 0 ), |
'LOGNORMDIST' => array( 290, 3, 1, 0 ), |
'LOGINV' => array( 291, 3, 1, 0 ), |
'NEGBINOMDIST' => array( 292, 3, 1, 0 ), |
'NORMDIST' => array( 293, 4, 1, 0 ), |
'NORMSDIST' => array( 294, 1, 1, 0 ), |
'NORMINV' => array( 295, 3, 1, 0 ), |
'NORMSINV' => array( 296, 1, 1, 0 ), |
'STANDARDIZE' => array( 297, 3, 1, 0 ), |
'ODD' => array( 298, 1, 1, 0 ), |
'PERMUT' => array( 299, 2, 1, 0 ), |
'POISSON' => array( 300, 3, 1, 0 ), |
'TDIST' => array( 301, 3, 1, 0 ), |
'WEIBULL' => array( 302, 4, 1, 0 ), |
'SUMXMY2' => array( 303, 2, 2, 0 ), |
'SUMX2MY2' => array( 304, 2, 2, 0 ), |
'SUMX2PY2' => array( 305, 2, 2, 0 ), |
'CHITEST' => array( 306, 2, 2, 0 ), |
'CORREL' => array( 307, 2, 2, 0 ), |
'COVAR' => array( 308, 2, 2, 0 ), |
'FORECAST' => array( 309, 3, 2, 0 ), |
'FTEST' => array( 310, 2, 2, 0 ), |
'INTERCEPT' => array( 311, 2, 2, 0 ), |
'PEARSON' => array( 312, 2, 2, 0 ), |
'RSQ' => array( 313, 2, 2, 0 ), |
'STEYX' => array( 314, 2, 2, 0 ), |
'SLOPE' => array( 315, 2, 2, 0 ), |
'TTEST' => array( 316, 4, 2, 0 ), |
'PROB' => array( 317, -1, 2, 0 ), |
'DEVSQ' => array( 318, -1, 0, 0 ), |
'GEOMEAN' => array( 319, -1, 0, 0 ), |
'HARMEAN' => array( 320, -1, 0, 0 ), |
'SUMSQ' => array( 321, -1, 0, 0 ), |
'KURT' => array( 322, -1, 0, 0 ), |
'SKEW' => array( 323, -1, 0, 0 ), |
'ZTEST' => array( 324, -1, 0, 0 ), |
'LARGE' => array( 325, 2, 0, 0 ), |
'SMALL' => array( 326, 2, 0, 0 ), |
'QUARTILE' => array( 327, 2, 0, 0 ), |
'PERCENTILE' => array( 328, 2, 0, 0 ), |
'PERCENTRANK' => array( 329, -1, 0, 0 ), |
'MODE' => array( 330, -1, 2, 0 ), |
'TRIMMEAN' => array( 331, 2, 0, 0 ), |
'TINV' => array( 332, 2, 1, 0 ), |
'CONCATENATE' => array( 336, -1, 1, 0 ), |
'POWER' => array( 337, 2, 1, 0 ), |
'RADIANS' => array( 342, 1, 1, 0 ), |
'DEGREES' => array( 343, 1, 1, 0 ), |
'SUBTOTAL' => array( 344, -1, 0, 0 ), |
'SUMIF' => array( 345, -1, 0, 0 ), |
'COUNTIF' => array( 346, 2, 0, 0 ), |
'COUNTBLANK' => array( 347, 1, 0, 0 ), |
'ROMAN' => array( 354, -1, 1, 0 ) |
); |
} |
/** |
* Convert a token to the proper ptg value. |
* |
* @access private |
* @param mixed $token The token to convert. |
*/ |
function _convert($token) |
{ |
if (preg_match("/^\"[^\"]{0,255}\"$/", $token)) |
{ |
return $this->_convertString($token); |
} |
elseif (is_numeric($token)) |
{ |
return $this->_convertNumber($token); |
} |
// match references like A1 or $A$1 |
elseif(preg_match('/^\$?([A-I]?[A-Z])\$?(\d+)$/',$token)) |
{ |
return($this->_convertRef2d($token)); |
} |
// match external references like Sheet1:Sheet2!A1 |
elseif (preg_match("/^[A-Za-z0-9_]+(\:[A-Za-z0-9_]+)?\![A-I]?[A-Z](\d+)$/",$token)) |
{ |
return $this->_convertRef3d($token); |
} |
// match ranges like A1:B2 |
elseif(preg_match("/^(\$)?[A-I]?[A-Z](\$)?(\d+)\:(\$)?[A-I]?[A-Z](\$)?(\d+)$/",$token)) |
{ |
return($this->_convertRange2d($token)); |
} |
// match ranges like A1..B2 |
elseif(preg_match("/^(\$)?[A-I]?[A-Z](\$)?(\d+)\.\.(\$)?[A-I]?[A-Z](\$)?(\d+)$/",$token)) |
{ |
return($this->_convertRange2d($token)); |
} |
// match external ranges like Sheet1:Sheet2!A1:B2 |
elseif (preg_match("/^[A-Za-z0-9_]+(\:[A-Za-z0-9_]+)?\!([A-I]?[A-Z])?(\d+)\:([A-I]?[A-Z])?(\d+)$/",$token)) |
{ |
return $this->_convertRange3d($token); |
} |
elseif(isset($this->ptg[$token])) // operators (including parentheses) |
{ |
return(pack("C", $this->ptg[$token])); |
} |
elseif(preg_match("/[A-Z0-9\xc0-\xdc\.]+/",$token)) |
{ |
return($this->_convertFunction($token,$this->_func_args)); |
} |
// if it's an argument, ignore the token (the argument remains) |
elseif($token == 'arg') |
{ |
$this->_func_args++; |
return(''); |
} |
// TODO: use real error codes |
$this->raiseError("Unknown token $token", 0, PEAR_ERROR_DIE); |
} |
/** |
* Convert a number token to ptgInt or ptgNum |
* |
* @access private |
* @param mixed $num an integer or double for conversion to its ptg value |
*/ |
function _convertNumber($num) |
{ |
// Integer in the range 0..2**16-1 |
if ((preg_match("/^\d+$/",$num)) and ($num <= 65535)) { |
return(pack("Cv", $this->ptg['ptgInt'], $num)); |
} |
else // A float |
{ |
if($this->_byte_order) // if it's Big Endian |
{ |
$num = strrev($num); |
} |
return(pack("Cd", $this->ptg['ptgNum'], $num)); |
} |
} |
/** |
* Convert a string token to ptgStr |
* |
* @access private |
* @param string $string A string for conversion to its ptg value |
*/ |
function _convertString($string) |
{ |
// chop away beggining and ending quotes |
$string = substr($string, 1, strlen($string) - 2); |
return pack("CC", $this->ptg['ptgStr'], strlen($string)).$string; |
} |
/** |
* Convert a function to a ptgFunc or ptgFuncVarV depending on the number of |
* args that it takes. |
* |
* @access private |
* @param string $token The name of the function for convertion to ptg value. |
* @param integer $num_args The number of arguments the function recieves. |
*/ |
function _convertFunction($token, $num_args) |
{ |
$this->_func_args = 0; // re initialize the number of arguments |
$args = $this->_functions[$token][1]; |
$volatile = $this->_functions[$token][3]; |
// Fixed number of args eg. TIME($i,$j,$k). |
if ($args >= 0) { |
return(pack("Cv", $this->ptg['ptgFuncV'], $this->_functions[$token][0])); |
} |
// Variable number of args eg. SUM($i,$j,$k, ..). |
if ($args == -1) { |
return(pack("CCv", $this->ptg['ptgFuncVarV'], $num_args, $this->_functions[$token][0])); |
} |
} |
/** |
* Convert an Excel range such as A1:D4 to a ptgRefV. |
* |
* @access private |
* @param string $range An Excel range in the A1:A2 or A1..A2 format. |
*/ |
function _convertRange2d($range) |
{ |
$class = 2; // as far as I know, this is magick. |
// Split the range into 2 cell refs |
if(preg_match("/^([A-I]?[A-Z])(\d+)\:([A-I]?[A-Z])(\d+)$/",$range)) { |
list($cell1, $cell2) = split(':', $range); |
} |
elseif(preg_match("/^([A-I]?[A-Z])(\d+)\.\.([A-I]?[A-Z])(\d+)$/",$range)) { |
list($cell1, $cell2) = split('\.\.', $range); |
} |
else { |
// TODO: use real error codes |
$this->raiseError("Unknown range separator", 0, PEAR_ERROR_DIE); |
} |
// Convert the cell references |
$cell_array1 = $this->_cellToPackedRowcol($cell1); |
if($this->isError($cell_array1)) { |
return($cell_array1); |
} |
list($row1, $col1) = $cell_array1; //$this->_cellToPackedRowcol($cell1); |
$cell_array2 = $this->_cellToPackedRowcol($cell2); |
if($this->isError($cell_array2)) { |
return($cell_array2); |
} |
list($row2, $col2) = $cell_array2; //$this->_cellToPackedRowcol($cell2); |
// The ptg value depends on the class of the ptg. |
if ($class == 0) { |
$ptgArea = pack("C", $this->ptg['ptgArea']); |
} |
elseif ($class == 1) { |
$ptgArea = pack("C", $this->ptg['ptgAreaV']); |
} |
elseif ($class == 2) { |
$ptgArea = pack("C", $this->ptg['ptgAreaA']); |
} |
else { |
// TODO: use real error codes |
$this->raiseError("Unknown class $class", 0, PEAR_ERROR_DIE); |
} |
return($ptgArea . $row1 . $row2 . $col1. $col2); |
} |
/** |
* Convert an Excel 3d range such as "Sheet1!A1:D4" or "Sheet1:Sheet2!A1:D4" to |
* a ptgArea3dV. |
* |
* @access private |
* @param string $token An Excel range in the Sheet1!A1:A2 format. |
*/ |
function _convertRange3d($token) |
{ |
$class = 2; // as far as I know, this is magick. |
// Split the ref at the ! symbol |
list($ext_ref, $range) = split('!', $token); |
// Convert the external reference part |
$ext_ref = $this->_packExtRef($ext_ref); |
if ($this->isError($ext_ref)) { |
return $ext_ref; |
} |
// Split the range into 2 cell refs |
list($cell1, $cell2) = split(':', $range); |
// Convert the cell references |
if (preg_match("/^(\$)?[A-I]?[A-Z](\$)?(\d+)$/", $cell1)) |
{ |
$cell_array1 = $this->_cellToPackedRowcol($cell1); |
if (PEAR::isError($cell_array1)) { |
return $cell_array1; |
} |
list($row1, $col1) = $cell_array1; |
$cell_array2 = $this->_cellToPackedRowcol($cell2); |
if (PEAR::isError($cell_array2)) { |
return $cell_array2; |
} |
list($row2, $col2) = $cell_array2; |
} |
else { // It's a columns range (like 26:27) |
$cells_array = $this->_rangeToPackedRange($cell1.':'.$cell2); |
if (PEAR::isError($cells_array)) { |
return $cells_array; |
} |
list($row1, $col1, $row2, $col2) = $cells_array; |
} |
// The ptg value depends on the class of the ptg. |
if ($class == 0) { |
$ptgArea = pack("C", $this->ptg['ptgArea3d']); |
} |
elseif ($class == 1) { |
$ptgArea = pack("C", $this->ptg['ptgArea3dV']); |
} |
elseif ($class == 2) { |
$ptgArea = pack("C", $this->ptg['ptgArea3dA']); |
} |
else { |
$this->raiseError("Unknown class $class", 0, PEAR_ERROR_DIE); |
} |
return $ptgArea . $ext_ref . $row1 . $row2 . $col1. $col2; |
} |
/** |
* Convert an Excel reference such as A1, $B2, C$3 or $D$4 to a ptgRefV. |
* |
* @access private |
* @param string $cell An Excel cell reference |
* @return string The cell in packed() format with the corresponding ptg |
*/ |
function _convertRef2d($cell) |
{ |
$class = 2; // as far as I know, this is magick. |
// Convert the cell reference |
$cell_array = $this->_cellToPackedRowcol($cell); |
if($this->isError($cell_array)) { |
return($cell_array); |
} |
list($row, $col) = $cell_array; |
// The ptg value depends on the class of the ptg. |
if ($class == 0) { |
$ptgRef = pack("C", $this->ptg['ptgRef']); |
} |
elseif ($class == 1) { |
$ptgRef = pack("C", $this->ptg['ptgRefV']); |
} |
elseif ($class == 2) { |
$ptgRef = pack("C", $this->ptg['ptgRefA']); |
} |
else { |
// TODO: use real error codes |
$this->raiseError("Unknown class $class", 0, PEAR_ERROR_DIE); |
} |
return($ptgRef.$row.$col); |
} |
/** |
* Convert an Excel 3d reference such as "Sheet1!A1" or "Sheet1:Sheet2!A1" to a |
* ptgRef3dV. |
* |
* @access private |
* @param string $cell An Excel cell reference |
* @return string The cell in packed() format with the corresponding ptg |
*/ |
function _convertRef3d($cell) |
{ |
$class = 2; // as far as I know, this is magick. |
// Split the ref at the ! symbol |
list($ext_ref, $cell) = split('!', $cell); |
// Convert the external reference part |
$ext_ref = $this->_packExtRef($ext_ref); |
if ($this->isError($ext_ref)) { |
return $ext_ref; |
} |
// Convert the cell reference part |
list($row, $col) = $this->_cellToPackedRowcol($cell); |
// The ptg value depends on the class of the ptg. |
if ($class == 0) { |
$ptgRef = pack("C", $this->ptg['ptgRef3d']); |
} |
elseif ($class == 1) { |
$ptgRef = pack("C", $this->ptg['ptgRef3dV']); |
} |
elseif ($class == 2) { |
$ptgRef = pack("C", $this->ptg['ptgRef3dA']); |
} |
else { |
$this->raiseError("Unknown class $class", 0, PEAR_ERROR_DIE); |
} |
return $ptgRef . $ext_ref. $row . $col; |
} |
/** |
* Convert the sheet name part of an external reference, for example "Sheet1" or |
* "Sheet1:Sheet2", to a packed structure. |
* |
* @access private |
* @param string $ext_ref The name of the external reference |
* @return string The reference index in packed() format |
*/ |
function _packExtRef($ext_ref) |
{ |
$ext_ref = preg_replace("/^'/", '', $ext_ref); // Remove leading ' if any. |
$ext_ref = preg_replace("/'$/", '', $ext_ref); // Remove trailing ' if any. |
// Check if there is a sheet range eg., Sheet1:Sheet2. |
if (preg_match("/:/", $ext_ref)) |
{ |
list($sheet_name1, $sheet_name2) = split(':', $ext_ref); |
$sheet1 = $this->_getSheetIndex($sheet_name1); |
if ($sheet1 == -1) { |
return $this->raiseError("Unknown sheet name $sheet_name1 in formula"); |
} |
$sheet2 = $this->_getSheetIndex($sheet_name2); |
if ($sheet2 == -1) { |
return $this->raiseError("Unknown sheet name $sheet_name2 in formula"); |
} |
// Reverse max and min sheet numbers if necessary |
if ($sheet1 > $sheet2) { |
list($sheet1, $sheet2) = array($sheet2, $sheet1); |
} |
} |
else // Single sheet name only. |
{ |
$sheet1 = $this->_getSheetIndex($ext_ref); |
if ($sheet1 == -1) { |
return $this->raiseError("Unknown sheet name $ext_ref in formula"); |
} |
$sheet2 = $sheet1; |
} |
// References are stored relative to 0xFFFF. |
$offset = -1 - $sheet1; |
return pack('vdvv', $offset, 0x00, $sheet1, $sheet2); |
} |
/** |
* Look up the index that corresponds to an external sheet name. The hash of |
* sheet names is updated by the addworksheet() method of the |
* Spreadsheet_Excel_Writer_Workbook class. |
* |
* @access private |
* @return integer |
*/ |
function _getSheetIndex($sheet_name) |
{ |
if (!isset($this->_ext_sheets[$sheet_name])) { |
return -1; |
} |
else { |
return $this->_ext_sheets[$sheet_name]; |
} |
} |
/** |
* This method is used to update the array of sheet names. It is |
* called by the addWorksheet() method of the Spreadsheet_Excel_Writer_Workbook class. |
* |
* @access private |
* @param string $name The name of the worksheet being added |
* @param integer $index The index of the worksheet being added |
*/ |
function setExtSheet($name, $index) |
{ |
$this->_ext_sheets[$name] = $index; |
} |
/** |
* pack() row and column into the required 3 byte format. |
* |
* @access private |
* @param string $cell The Excel cell reference to be packed |
* @return array Array containing the row and column in packed() format |
*/ |
function _cellToPackedRowcol($cell) |
{ |
list($row, $col, $row_rel, $col_rel) = $this->_cellToRowcol($cell); |
if ($col >= 256) { |
return($this->raiseError("Column in: $cell greater than 255")); |
} |
if ($row >= 16384) { |
return($this->raiseError("Row in: $cell greater than 16384 ")); |
} |
// Set the high bits to indicate if row or col are relative. |
$row |= $col_rel << 14; |
$row |= $row_rel << 15; |
$row = pack('v', $row); |
$col = pack('C', $col); |
return(array($row, $col)); |
} |
/** |
* pack() row range into the required 3 byte format. |
* Just using maximun col/rows, which is probably not the correct solution |
* |
* @access private |
* @param string $range The Excel range to be packed |
* @return array Array containing (row1,col1,row2,col2) in packed() format |
*/ |
function _rangeToPackedRange($range) |
{ |
preg_match('/(\$)?(\d+)\:(\$)?(\d+)/', $range, $match); |
// return absolute rows if there is a $ in the ref |
$row1_rel = empty($match[1]) ? 1 : 0; |
$row1 = $match[2]; |
$row2_rel = empty($match[3]) ? 1 : 0; |
$row2 = $match[4]; |
// Convert 1-index to zero-index |
$row1--; |
$row2--; |
// Trick poor inocent Excel |
$col1 = 0; |
$col2 = 16383; // maximum possible value for Excel 5 (change this!!!) |
//list($row, $col, $row_rel, $col_rel) = $this->_cellToRowcol($cell); |
if (($row1 >= 16384) or ($row2 >= 16384)) { |
return new PEAR_Error("Row in: $range greater than 16384 "); |
} |
// Set the high bits to indicate if rows are relative. |
$row1 |= $row1_rel << 14; |
$row2 |= $row2_rel << 15; |
$row1 = pack('v', $row1); |
$row2 = pack('v', $row2); |
$col1 = pack('C', $col1); |
$col2 = pack('C', $col2); |
return array($row1, $col1, $row2, $col2); |
} |
/** |
* Convert an Excel cell reference such as A1 or $B2 or C$3 or $D$4 to a zero |
* indexed row and column number. Also returns two (0,1) values to indicate |
* whether the row or column are relative references. |
* |
* @access private |
* @param string $cell The Excel cell reference in A1 format. |
* @return array |
*/ |
function _cellToRowcol($cell) |
{ |
preg_match('/(\$)?([A-I]?[A-Z])(\$)?(\d+)/',$cell,$match); |
// return absolute column if there is a $ in the ref |
$col_rel = empty($match[1]) ? 1 : 0; |
$col_ref = $match[2]; |
$row_rel = empty($match[3]) ? 1 : 0; |
$row = $match[4]; |
// Convert base26 column string to a number. |
$expn = strlen($col_ref) - 1; |
$col = 0; |
for($i=0; $i < strlen($col_ref); $i++) |
{ |
$col += (ord($col_ref{$i}) - ord('A') + 1) * pow(26, $expn); |
$expn--; |
} |
// Convert 1-index to zero-index |
$row--; |
$col--; |
return(array($row, $col, $row_rel, $col_rel)); |
} |
/** |
* Advance to the next valid token. |
* |
* @access private |
*/ |
function _advance() |
{ |
$i = $this->_current_char; |
// eat up white spaces |
if($i < strlen($this->_formula)) |
{ |
while($this->_formula{$i} == " ") { |
$i++; |
} |
if($i < strlen($this->_formula) - 1) { |
$this->_lookahead = $this->_formula{$i+1}; |
} |
$token = ""; |
} |
while($i < strlen($this->_formula)) |
{ |
$token .= $this->_formula{$i}; |
if($this->_match($token) != '') |
{ |
if($i < strlen($this->_formula) - 1) { |
$this->_lookahead = $this->_formula{$i+1}; |
} |
$this->_current_char = $i + 1; |
$this->_current_token = $token; |
return(1); |
} |
if ($i < strlen($this->_formula) - 2) { |
$this->_lookahead = $this->_formula{$i+2}; |
} |
// if we run out of characters _lookahead becomes empty |
else { |
$this->_lookahead = ''; |
} |
$i++; |
} |
//die("Lexical error ".$this->_current_char); |
} |
/** |
* Checks if it's a valid token. |
* |
* @access private |
* @param mixed $token The token to check. |
* @return mixed The checked token or false on failure |
*/ |
function _match($token) |
{ |
switch($token) |
{ |
case SPREADSHEET_EXCEL_WRITER_ADD: |
return($token); |
break; |
case SPREADSHEET_EXCEL_WRITER_SUB: |
return($token); |
break; |
case SPREADSHEET_EXCEL_WRITER_MUL: |
return($token); |
break; |
case SPREADSHEET_EXCEL_WRITER_DIV: |
return($token); |
break; |
case SPREADSHEET_EXCEL_WRITER_OPEN: |
return($token); |
break; |
case SPREADSHEET_EXCEL_WRITER_CLOSE: |
return($token); |
break; |
case SPREADSHEET_EXCEL_WRITER_COMA: |
return($token); |
break; |
case SPREADSHEET_EXCEL_WRITER_GT: |
if ($this->_lookahead == '=') { // it's a GE token |
break; |
} |
return($token); |
break; |
case SPREADSHEET_EXCEL_WRITER_LT: |
// it's a LE or a NE token |
if (($this->_lookahead == '=') or ($this->_lookahead == '>')) { |
break; |
} |
return($token); |
break; |
case SPREADSHEET_EXCEL_WRITER_GE: |
return($token); |
break; |
case SPREADSHEET_EXCEL_WRITER_LE: |
return($token); |
break; |
case SPREADSHEET_EXCEL_WRITER_EQ: |
return($token); |
break; |
case SPREADSHEET_EXCEL_WRITER_NE: |
return($token); |
break; |
default: |
// if it's a reference |
if (preg_match('/^\$?[A-I]?[A-Z]\$?[0-9]+$/',$token) and |
!ereg("[0-9]",$this->_lookahead) and |
($this->_lookahead != ':') and ($this->_lookahead != '.') and |
($this->_lookahead != '!')) |
{ |
return $token; |
} |
// If it's an external reference (Sheet1!A1 or Sheet1:Sheet2!A1) |
elseif (preg_match("/^[A-Za-z0-9_]+(\:[A-Za-z0-9_]+)?\![A-I]?[A-Z][0-9]+$/",$token) and |
!ereg("[0-9]",$this->_lookahead) and |
($this->_lookahead != ':') and ($this->_lookahead != '.')) |
{ |
return $token; |
} |
// if it's a range (A1:A2) |
elseif (preg_match("/^(\$)?[A-I]?[A-Z](\$)?[0-9]+:(\$)?[A-I]?[A-Z](\$)?[0-9]+$/",$token) and |
!ereg("[0-9]",$this->_lookahead)) |
{ |
return $token; |
} |
// if it's a range (A1..A2) |
elseif (preg_match("/^(\$)?[A-I]?[A-Z](\$)?[0-9]+\.\.(\$)?[A-I]?[A-Z](\$)?[0-9]+$/",$token) and |
!ereg("[0-9]",$this->_lookahead)) |
{ |
return $token; |
} |
// If it's an external range |
elseif (preg_match("/^[A-Za-z0-9_]+(\:[A-Za-z0-9_]+)?\!([A-I]?[A-Z])?[0-9]+:([A-I]?[A-Z])?[0-9]+$/",$token) and |
!ereg("[0-9]",$this->_lookahead)) |
{ |
return $token; |
} |
// If it's a number (check that it's not a sheet name or range) |
elseif (is_numeric($token) and !is_numeric($token.$this->_lookahead) and |
($this->_lookahead != '!') and (($this->_lookahead != ':'))) |
{ |
return $token; |
} |
// If it's a string (of maximum 255 characters) |
elseif(ereg("^\"[^\"]{0,255}\"$",$token)) |
{ |
return($token); |
} |
// if it's a function call |
elseif(eregi("^[A-Z0-9\xc0-\xdc\.]+$",$token) and ($this->_lookahead == "(")) |
{ |
return($token); |
} |
return ''; |
} |
} |
/** |
* The parsing method. It parses a formula. |
* |
* @access public |
* @param string $formula The formula to parse, without the initial equal sign (=). |
*/ |
function parse($formula) |
{ |
$this->_current_char = 0; |
$this->_formula = $formula; |
$this->_lookahead = $formula{1}; |
$this->_advance(); |
$this->_parse_tree = $this->_condition(); |
if ($this->isError($this->_parse_tree)) { |
return $this->_parse_tree; |
} |
} |
/** |
* It parses a condition. It assumes the following rule: |
* Cond -> Expr [(">" | "<") Expr] |
* |
* @access private |
* @return mixed The parsed ptg'd tree |
*/ |
function _condition() |
{ |
$result = $this->_expression(); |
if($this->isError($result)) { |
return $result; |
} |
if ($this->_current_token == SPREADSHEET_EXCEL_WRITER_LT) |
{ |
$this->_advance(); |
$result2 = $this->_expression(); |
if($this->isError($result2)) { |
return $result2; |
} |
$result = $this->_createTree('ptgLT', $result, $result2); |
} |
elseif ($this->_current_token == SPREADSHEET_EXCEL_WRITER_GT) |
{ |
$this->_advance(); |
$result2 = $this->_expression(); |
if($this->isError($result2)) { |
return $result2; |
} |
$result = $this->_createTree('ptgGT', $result, $result2); |
} |
elseif ($this->_current_token == SPREADSHEET_EXCEL_WRITER_LE) |
{ |
$this->_advance(); |
$result2 = $this->_expression(); |
if($this->isError($result2)) { |
return $result2; |
} |
$result = $this->_createTree('ptgLE', $result, $result2); |
} |
elseif ($this->_current_token == SPREADSHEET_EXCEL_WRITER_GE) |
{ |
$this->_advance(); |
$result2 = $this->_expression(); |
if($this->isError($result2)) { |
return $result2; |
} |
$result = $this->_createTree('ptgGE', $result, $result2); |
} |
elseif ($this->_current_token == SPREADSHEET_EXCEL_WRITER_EQ) |
{ |
$this->_advance(); |
$result2 = $this->_expression(); |
if($this->isError($result2)) { |
return $result2; |
} |
$result = $this->_createTree('ptgEQ', $result, $result2); |
} |
elseif ($this->_current_token == SPREADSHEET_EXCEL_WRITER_NE) |
{ |
$this->_advance(); |
$result2 = $this->_expression(); |
if($this->isError($result2)) { |
return $result2; |
} |
$result = $this->_createTree('ptgNE', $result, $result2); |
} |
return $result; |
} |
/** |
* It parses a expression. It assumes the following rule: |
* Expr -> Term [("+" | "-") Term] |
* |
* @access private |
* @return mixed The parsed ptg'd tree |
*/ |
function _expression() |
{ |
// If it's a string return a string node |
if (ereg("^\"[^\"]{0,255}\"$", $this->_current_token)) |
{ |
$result = $this->_createTree($this->_current_token, '', ''); |
$this->_advance(); |
return($result); |
} |
$result = $this->_term(); |
if($this->isError($result)) { |
return($result); |
} |
while (($this->_current_token == SPREADSHEET_EXCEL_WRITER_ADD) or |
($this->_current_token == SPREADSHEET_EXCEL_WRITER_SUB)) |
{ |
if ($this->_current_token == SPREADSHEET_EXCEL_WRITER_ADD) |
{ |
$this->_advance(); |
$result2 = $this->_term(); |
if($this->isError($result2)) { |
return($result2); |
} |
$result = $this->_createTree('ptgAdd', $result, $result2); |
} |
else |
{ |
$this->_advance(); |
$result2 = $this->_term(); |
if($this->isError($result2)) { |
return($result2); |
} |
$result = $this->_createTree('ptgSub', $result, $result2); |
} |
} |
return($result); |
} |
/** |
* This function just introduces a ptgParen element in the tree, so that Excel |
* doesn't get confused when working with a parenthesized formula afterwards. |
* |
* @access private |
* @see _fact() |
* @return mixed The parsed ptg'd tree |
*/ |
function _parenthesizedExpression() |
{ |
$result = $this->_createTree('ptgParen', $this->_expression(), ''); |
return($result); |
} |
/** |
* It parses a term. It assumes the following rule: |
* Term -> Fact [("*" | "/") Fact] |
* |
* @access private |
* @return mixed The parsed ptg'd tree |
*/ |
function _term() |
{ |
$result = $this->_fact(); |
if($this->isError($result)) { |
return($result); |
} |
while (($this->_current_token == SPREADSHEET_EXCEL_WRITER_MUL) or |
($this->_current_token == SPREADSHEET_EXCEL_WRITER_DIV)) |
{ |
if ($this->_current_token == SPREADSHEET_EXCEL_WRITER_MUL) |
{ |
$this->_advance(); |
$result2 = $this->_fact(); |
if($this->isError($result2)) { |
return($result2); |
} |
$result = $this->_createTree('ptgMul', $result, $result2); |
} |
else |
{ |
$this->_advance(); |
$result2 = $this->_fact(); |
if($this->isError($result2)) { |
return($result2); |
} |
$result = $this->_createTree('ptgDiv', $result, $result2); |
} |
} |
return($result); |
} |
/** |
* It parses a factor. It assumes the following rule: |
* Fact -> ( Expr ) |
* | CellRef |
* | CellRange |
* | Number |
* | Function |
* |
* @access private |
* @return mixed The parsed ptg'd tree |
*/ |
function _fact() |
{ |
if ($this->_current_token == SPREADSHEET_EXCEL_WRITER_OPEN) |
{ |
$this->_advance(); // eat the "(" |
$result = $this->_parenthesizedExpression(); |
if ($this->_current_token != SPREADSHEET_EXCEL_WRITER_CLOSE) { |
return($this->raiseError("')' token expected.")); |
} |
$this->_advance(); // eat the ")" |
return $result; |
} |
// if it's a reference |
if (preg_match('/^\$?[A-I]?[A-Z]\$?[0-9]+$/',$this->_current_token)) |
{ |
$result = $this->_createTree($this->_current_token, '', ''); |
$this->_advance(); |
return $result; |
} |
// If it's an external reference (Sheet1!A1 or Sheet1:Sheet2!A1) |
elseif (preg_match("/^[A-Za-z0-9_]+(\:[A-Za-z0-9_]+)?\![A-I]?[A-Z][0-9]+$/",$this->_current_token)) |
{ |
$result = $this->_createTree($this->_current_token, '', ''); |
$this->_advance(); |
return $result; |
} |
// if it's a range |
elseif (preg_match("/^(\$)?[A-I]?[A-Z](\$)?[0-9]+:(\$)?[A-I]?[A-Z](\$)?[0-9]+$/",$this->_current_token) or |
preg_match("/^(\$)?[A-I]?[A-Z](\$)?[0-9]+\.\.(\$)?[A-I]?[A-Z](\$)?[0-9]+$/",$this->_current_token)) |
{ |
$result = $this->_current_token; |
$this->_advance(); |
return $result; |
} |
// If it's an external range (Sheet1!A1:B2) |
elseif (preg_match("/^[A-Za-z0-9_]+(\:[A-Za-z0-9_]+)?\!([A-I]?[A-Z])?[0-9]+:([A-I]?[A-Z])?[0-9]+$/",$this->_current_token)) |
{ |
$result = $this->_current_token; |
$this->_advance(); |
return($result); |
} |
elseif (is_numeric($this->_current_token)) |
{ |
$result = $this->_createTree($this->_current_token, '', ''); |
$this->_advance(); |
return($result); |
} |
// if it's a function call |
elseif (eregi("^[A-Z0-9\xc0-\xdc\.]+$",$this->_current_token)) |
{ |
$result = $this->_func(); |
return($result); |
} |
return($this->raiseError("Sintactic error: ".$this->_current_token.", lookahead: ". |
$this->_lookahead.", current char: ".$this->_current_char)); |
} |
/** |
* It parses a function call. It assumes the following rule: |
* Func -> ( Expr [,Expr]* ) |
* |
* @access private |
*/ |
function _func() |
{ |
$num_args = 0; // number of arguments received |
$function = $this->_current_token; |
$this->_advance(); |
$this->_advance(); // eat the "(" |
while($this->_current_token != ')') |
{ |
if($num_args > 0) |
{ |
if($this->_current_token == SPREADSHEET_EXCEL_WRITER_COMA) { |
$this->_advance(); // eat the "," |
} |
else { |
return new PEAR_Error("Sintactic error: coma expected in ". |
"function $function, {$num_args}º arg"); |
} |
$result2 = $this->_condition(); |
if($this->isError($result2)) { |
return($result2); |
} |
$result = $this->_createTree('arg', $result, $result2); |
} |
else // first argument |
{ |
$result2 = $this->_condition(); |
if($this->isError($result2)) { |
return($result2); |
} |
$result = $this->_createTree('arg', '', $result2); |
} |
$num_args++; |
} |
$args = $this->_functions[$function][1]; |
// If fixed number of args eg. TIME($i,$j,$k). Check that the number of args is valid. |
if (($args >= 0) and ($args != $num_args)) |
{ |
return($this->raiseError("Incorrect number of arguments in function $function() ")); |
} |
$result = $this->_createTree($function, $result, ''); |
$this->_advance(); // eat the ")" |
return($result); |
} |
/** |
* Creates a tree. In fact an array which may have one or two arrays (sub-trees) |
* as elements. |
* |
* @access private |
* @param mixed $value The value of this node. |
* @param mixed $left The left array (sub-tree) or a final node. |
* @param mixed $right The right array (sub-tree) or a final node. |
*/ |
function _createTree($value, $left, $right) |
{ |
return(array('value' => $value, 'left' => $left, 'right' => $right)); |
} |
/** |
* Builds a string containing the tree in reverse polish notation (What you |
* would use in a HP calculator stack). |
* The following tree: |
* |
* + |
* / \ |
* 2 3 |
* |
* produces: "23+" |
* |
* The following tree: |
* |
* + |
* / \ |
* 3 * |
* / \ |
* 6 A1 |
* |
* produces: "36A1*+" |
* |
* In fact all operands, functions, references, etc... are written as ptg's |
* |
* @access public |
* @param array $tree The optional tree to convert. |
* @return string The tree in reverse polish notation |
*/ |
function toReversePolish($tree = array()) |
{ |
$polish = ""; // the string we are going to return |
if (empty($tree)) // If it's the first call use _parse_tree |
{ |
$tree = $this->_parse_tree; |
} |
if (is_array($tree['left'])) |
{ |
$converted_tree = $this->toReversePolish($tree['left']); |
if($this->isError($converted_tree)) { |
return($converted_tree); |
} |
$polish .= $converted_tree; |
} |
elseif($tree['left'] != '') // It's a final node |
{ |
$converted_tree = $this->_convert($tree['left']); |
if($this->isError($converted_tree)) { |
return($converted_tree); |
} |
$polish .= $converted_tree; |
} |
if (is_array($tree['right'])) |
{ |
$converted_tree = $this->toReversePolish($tree['right']); |
if($this->isError($converted_tree)) { |
return($converted_tree); |
} |
$polish .= $converted_tree; |
} |
elseif($tree['right'] != '') // It's a final node |
{ |
$converted_tree = $this->_convert($tree['right']); |
if($this->isError($converted_tree)) { |
return($converted_tree); |
} |
$polish .= $converted_tree; |
} |
$converted_tree = $this->_convert($tree['value']); |
if($this->isError($converted_tree)) { |
return($converted_tree); |
} |
$polish .= $converted_tree; |
return($polish); |
} |
} |
?> |
/trunk/jrest/lib/Spreadsheet/Excel/Writer/Workbook.php |
---|
New file |
0,0 → 1,1042 |
<?php |
/* |
* Module written/ported by Xavier Noguer <xnoguer@rezebra.com> |
* |
* The majority of this is _NOT_ my code. I simply ported it from the |
* PERL Spreadsheet::WriteExcel module. |
* |
* The author of the Spreadsheet::WriteExcel module is John McNamara |
* <jmcnamara@cpan.org> |
* |
* I _DO_ maintain this code, and John McNamara has nothing to do with the |
* porting of this code to PHP. Any questions directly related to this |
* class library should be directed to me. |
* |
* License Information: |
* |
* Spreadsheet_Excel_Writer: A library for generating Excel Spreadsheets |
* Copyright (c) 2002-2003 Xavier Noguer xnoguer@rezebra.com |
* |
* This library is free software; you can redistribute it and/or |
* modify it under the terms of the GNU Lesser General Public |
* License as published by the Free Software Foundation; either |
* version 2.1 of the License, or (at your option) any later version. |
* |
* This library is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
* Lesser General Public License for more details. |
* |
* You should have received a copy of the GNU Lesser General Public |
* License along with this library; if not, write to the Free Software |
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
*/ |
require_once('Format.php'); |
require_once('OLEwriter.php'); |
require_once('BIFFwriter.php'); |
require_once('Worksheet.php'); |
require_once('Parser.php'); |
/** |
* Class for generating Excel Spreadsheets |
* |
* @author Xavier Noguer <xnoguer@rezebra.com> |
* @category FileFormats |
* @package Spreadsheet_Excel_Writer |
*/ |
class Spreadsheet_Excel_Writer_Workbook extends Spreadsheet_Excel_Writer_BIFFwriter |
{ |
/** |
* Filename for the Workbook |
* @var string |
*/ |
var $_filename; |
/** |
* Formula parser |
* @var object Parser |
*/ |
var $_parser; |
/** |
* Flag for 1904 date system |
* @var integer |
*/ |
var $_1904; |
/** |
* The active worksheet of the workbook (0 indexed) |
* @var integer |
*/ |
var $_activesheet; |
/** |
* 1st displayed worksheet in the workbook (0 indexed) |
* @var integer |
*/ |
var $_firstsheet; |
/** |
* Number of workbook tabs selected |
* @var integer |
*/ |
var $_selected; |
/** |
* Index for creating adding new formats to the workbook |
* @var integer |
*/ |
var $_xf_index; |
/** |
* Flag for preventing close from being called twice. |
* @var integer |
* @see close() |
*/ |
var $_fileclosed; |
/** |
* The BIFF file size for the workbook. |
* @var integer |
* @see _calcSheetOffsets() |
*/ |
var $_biffsize; |
/** |
* The default sheetname for all sheets created. |
* @var string |
*/ |
var $_sheetname; |
/** |
* The default XF format. |
* @var object Format |
*/ |
var $_tmp_format; |
/** |
* Array containing references to all of this workbook's worksheets |
* @var array |
*/ |
var $_worksheets; |
/** |
* Array of sheetnames for creating the EXTERNSHEET records |
* @var array |
*/ |
var $_sheetnames; |
/** |
* Array containing references to all of this workbook's formats |
* @var array |
*/ |
var $_formats; |
/** |
* Array containing the colour palette |
* @var array |
*/ |
var $_palette; |
/** |
* The default format for URLs. |
* @var object Format |
*/ |
var $_url_format; |
/** |
* Class constructor |
* |
* @param string filename for storing the workbook. "-" for writing to stdout. |
* @access public |
*/ |
function Spreadsheet_Excel_Writer_Workbook($filename) |
{ |
// It needs to call its parent's constructor explicitly |
$this->Spreadsheet_Excel_Writer_BIFFwriter(); |
$this->_filename = $filename; |
$this->_parser =& new Spreadsheet_Excel_Writer_Parser($this->_byte_order); |
$this->_1904 = 0; |
$this->_activesheet = 0; |
$this->_firstsheet = 0; |
$this->_selected = 0; |
$this->_xf_index = 16; // 15 style XF's and 1 cell XF. |
$this->_fileclosed = 0; |
$this->_biffsize = 0; |
$this->_sheetname = "Sheet"; |
$this->_tmp_format =& new Spreadsheet_Excel_Writer_Format(); |
$this->_worksheets = array(); |
$this->_sheetnames = array(); |
$this->_formats = array(); |
$this->_palette = array(); |
// Add the default format for hyperlinks |
$this->_url_format =& $this->addFormat(array('color' => 'blue', 'underline' => 1)); |
$this->_setPaletteXl97(); |
} |
/** |
* Calls finalization methods. |
* This method should always be the last one to be called on every workbook |
* |
* @access public |
*/ |
function close() |
{ |
if ($this->_fileclosed) { // Prevent close() from being called twice. |
return; |
} |
$this->_storeWorkbook(); |
$this->_fileclosed = 1; |
} |
/** |
* An accessor for the _worksheets[] array |
* Returns an array of the worksheet objects in a workbook |
* It actually calls to worksheets() |
* |
* @access public |
* @see worksheets() |
* @return array |
*/ |
function sheets() |
{ |
return $this->worksheets(); |
} |
/** |
* An accessor for the _worksheets[] array. |
* Returns an array of the worksheet objects in a workbook |
* |
* @access public |
* @return array |
*/ |
function worksheets() |
{ |
return($this->_worksheets); |
} |
/** |
* Add a new worksheet to the Excel workbook. |
* If no name is given the name of the worksheet will be Sheeti$i, with |
* $i in [1..]. |
* |
* @access public |
* @param string $name the optional name of the worksheet |
* @return &Spreadsheet_Excel_Writer_Worksheet reference to a worksheet object |
*/ |
function &addWorksheet($name = '') |
{ |
$index = count($this->_worksheets); |
$sheetname = $this->_sheetname; |
if($name == '') { |
$name = $sheetname.($index+1); |
} |
// Check that sheetname is <= 31 chars (Excel limit). |
if(strlen($name) > 31) { |
$this->raiseError("Sheetname $name must be <= 31 chars"); |
} |
// Check that the worksheet name doesn't already exist: a fatal Excel error. |
for($i=0; $i < count($this->_worksheets); $i++) |
{ |
if($name == $this->_worksheets[$i]->getName()) { |
$this->raiseError("Worksheet '$name' already exists"); |
} |
} |
$worksheet = new Spreadsheet_Excel_Writer_Worksheet($name,$index,$this->_activesheet, |
$this->_firstsheet,$this->_url_format, |
$this->_parser); |
$this->_worksheets[$index] = &$worksheet; // Store ref for iterator |
$this->_sheetnames[$index] = $name; // Store EXTERNSHEET names |
$this->_parser->setExtSheet($name, $index); // Register worksheet name with parser |
return($worksheet); |
} |
/** |
* Add a new format to the Excel workbook. |
* Also, pass any properties to the Format constructor. |
* |
* @access public |
* @param array $properties array with properties for initializing the format. |
* @return &Spreadsheet_Excel_Writer_Format reference to an Excel Format |
*/ |
function &addFormat($properties = array()) |
{ |
$format = new Spreadsheet_Excel_Writer_Format($this->_xf_index,$properties); |
$this->_xf_index += 1; |
$this->_formats[] = &$format; |
return($format); |
} |
/** |
* Change the RGB components of the elements in the colour palette. |
* |
* @access public |
* @param integer $index colour index |
* @param integer $red red RGB value [0-255] |
* @param integer $green green RGB value [0-255] |
* @param integer $blue blue RGB value [0-255] |
* @return integer The palette index for the custom color |
*/ |
function setCustomColor($index,$red,$green,$blue) |
{ |
// Match a HTML #xxyyzz style parameter |
/*if (defined $_[1] and $_[1] =~ /^#(\w\w)(\w\w)(\w\w)/ ) { |
@_ = ($_[0], hex $1, hex $2, hex $3); |
}*/ |
// Check that the colour index is the right range |
if ($index < 8 or $index > 64) { |
// TODO: assign real error codes |
$this->raiseError("Color index $index outside range: 8 <= index <= 64",0,PEAR_ERROR_DIE); |
} |
// Check that the colour components are in the right range |
if ( ($red < 0 or $red > 255) or |
($green < 0 or $green > 255) or |
($blue < 0 or $blue > 255) ) |
{ |
$this->raiseError("Color component outside range: 0 <= color <= 255"); |
} |
$index -= 8; // Adjust colour index (wingless dragonfly) |
// Set the RGB value |
$this->_palette[$index] = array($red, $green, $blue, 0); |
return($index + 8); |
} |
/** |
* Sets the colour palette to the Excel 97+ default. |
* |
* @access private |
*/ |
function _setPaletteXl97() |
{ |
$this->_palette = array( |
array(0x00, 0x00, 0x00, 0x00), // 8 |
array(0xff, 0xff, 0xff, 0x00), // 9 |
array(0xff, 0x00, 0x00, 0x00), // 10 |
array(0x00, 0xff, 0x00, 0x00), // 11 |
array(0x00, 0x00, 0xff, 0x00), // 12 |
array(0xff, 0xff, 0x00, 0x00), // 13 |
array(0xff, 0x00, 0xff, 0x00), // 14 |
array(0x00, 0xff, 0xff, 0x00), // 15 |
array(0x80, 0x00, 0x00, 0x00), // 16 |
array(0x00, 0x80, 0x00, 0x00), // 17 |
array(0x00, 0x00, 0x80, 0x00), // 18 |
array(0x80, 0x80, 0x00, 0x00), // 19 |
array(0x80, 0x00, 0x80, 0x00), // 20 |
array(0x00, 0x80, 0x80, 0x00), // 21 |
array(0xc0, 0xc0, 0xc0, 0x00), // 22 |
array(0x80, 0x80, 0x80, 0x00), // 23 |
array(0x99, 0x99, 0xff, 0x00), // 24 |
array(0x99, 0x33, 0x66, 0x00), // 25 |
array(0xff, 0xff, 0xcc, 0x00), // 26 |
array(0xcc, 0xff, 0xff, 0x00), // 27 |
array(0x66, 0x00, 0x66, 0x00), // 28 |
array(0xff, 0x80, 0x80, 0x00), // 29 |
array(0x00, 0x66, 0xcc, 0x00), // 30 |
array(0xcc, 0xcc, 0xff, 0x00), // 31 |
array(0x00, 0x00, 0x80, 0x00), // 32 |
array(0xff, 0x00, 0xff, 0x00), // 33 |
array(0xff, 0xff, 0x00, 0x00), // 34 |
array(0x00, 0xff, 0xff, 0x00), // 35 |
array(0x80, 0x00, 0x80, 0x00), // 36 |
array(0x80, 0x00, 0x00, 0x00), // 37 |
array(0x00, 0x80, 0x80, 0x00), // 38 |
array(0x00, 0x00, 0xff, 0x00), // 39 |
array(0x00, 0xcc, 0xff, 0x00), // 40 |
array(0xcc, 0xff, 0xff, 0x00), // 41 |
array(0xcc, 0xff, 0xcc, 0x00), // 42 |
array(0xff, 0xff, 0x99, 0x00), // 43 |
array(0x99, 0xcc, 0xff, 0x00), // 44 |
array(0xff, 0x99, 0xcc, 0x00), // 45 |
array(0xcc, 0x99, 0xff, 0x00), // 46 |
array(0xff, 0xcc, 0x99, 0x00), // 47 |
array(0x33, 0x66, 0xff, 0x00), // 48 |
array(0x33, 0xcc, 0xcc, 0x00), // 49 |
array(0x99, 0xcc, 0x00, 0x00), // 50 |
array(0xff, 0xcc, 0x00, 0x00), // 51 |
array(0xff, 0x99, 0x00, 0x00), // 52 |
array(0xff, 0x66, 0x00, 0x00), // 53 |
array(0x66, 0x66, 0x99, 0x00), // 54 |
array(0x96, 0x96, 0x96, 0x00), // 55 |
array(0x00, 0x33, 0x66, 0x00), // 56 |
array(0x33, 0x99, 0x66, 0x00), // 57 |
array(0x00, 0x33, 0x00, 0x00), // 58 |
array(0x33, 0x33, 0x00, 0x00), // 59 |
array(0x99, 0x33, 0x00, 0x00), // 60 |
array(0x99, 0x33, 0x66, 0x00), // 61 |
array(0x33, 0x33, 0x99, 0x00), // 62 |
array(0x33, 0x33, 0x33, 0x00), // 63 |
); |
} |
/** |
* Assemble worksheets into a workbook and send the BIFF data to an OLE |
* storage. |
* |
* @access private |
*/ |
function _storeWorkbook() |
{ |
// Ensure that at least one worksheet has been selected. |
if ($this->_activesheet == 0) |
{ |
$this->_worksheets[0]->selected = 1; |
} |
// Calculate the number of selected worksheet tabs and call the finalization |
// methods for each worksheet |
for($i=0; $i < count($this->_worksheets); $i++) |
{ |
if($this->_worksheets[$i]->selected) { |
$this->_selected++; |
} |
$this->_worksheets[$i]->close($this->_sheetnames); |
} |
// Add Workbook globals |
$this->_storeBof(0x0005); |
$this->_storeExterns(); // For print area and repeat rows |
$this->_storeNames(); // For print area and repeat rows |
$this->_storeWindow1(); |
$this->_store1904(); |
$this->_storeAllFonts(); |
$this->_storeAllNumFormats(); |
$this->_storeAllXfs(); |
$this->_storeAllStyles(); |
$this->_storePalette(); |
$this->_calcSheetOffsets(); |
// Add BOUNDSHEET records |
for($i=0; $i < count($this->_worksheets); $i++) { |
$this->_storeBoundsheet($this->_worksheets[$i]->name,$this->_worksheets[$i]->offset); |
} |
// End Workbook globals |
$this->_storeEof(); |
// Store the workbook in an OLE container |
$this->_storeOLEFile(); |
} |
/** |
* Store the workbook in an OLE container if the total size of the workbook data |
* is less than ~ 7MB. |
* |
* @access private |
*/ |
function _storeOLEFile() |
{ |
$OLE = new Spreadsheet_Excel_Writer_OLEwriter($this->_filename); |
$this->_tmp_filename = $OLE->_tmp_filename; |
// Write Worksheet data if data <~ 7MB |
if ($OLE->setSize($this->_biffsize)) |
{ |
$OLE->writeHeader(); |
$OLE->write($this->_data); |
foreach($this->_worksheets as $sheet) |
{ |
while ($tmp = $sheet->getData()) { |
$OLE->write($tmp); |
} |
} |
} |
$OLE->close(); |
} |
/** |
* Calculate offsets for Worksheet BOF records. |
* |
* @access private |
*/ |
function _calcSheetOffsets() |
{ |
$BOF = 11; |
$EOF = 4; |
$offset = $this->_datasize; |
for($i=0; $i < count($this->_worksheets); $i++) { |
$offset += $BOF + strlen($this->_worksheets[$i]->name); |
} |
$offset += $EOF; |
for($i=0; $i < count($this->_worksheets); $i++) { |
$this->_worksheets[$i]->offset = $offset; |
$offset += $this->_worksheets[$i]->_datasize; |
} |
$this->_biffsize = $offset; |
} |
/** |
* Store the Excel FONT records. |
* |
* @access private |
*/ |
function _storeAllFonts() |
{ |
// tmp_format is added by the constructor. We use this to write the default XF's |
$format = $this->_tmp_format; |
$font = $format->getFont(); |
// Note: Fonts are 0-indexed. According to the SDK there is no index 4, |
// so the following fonts are 0, 1, 2, 3, 5 |
// |
for($i=1; $i <= 5; $i++){ |
$this->_append($font); |
} |
// Iterate through the XF objects and write a FONT record if it isn't the |
// same as the default FONT and if it hasn't already been used. |
// |
$fonts = array(); |
$index = 6; // The first user defined FONT |
$key = $format->getFontKey(); // The default font from _tmp_format |
$fonts[$key] = 0; // Index of the default font |
for($i=0; $i < count($this->_formats); $i++) { |
$key = $this->_formats[$i]->getFontKey(); |
if (isset($fonts[$key])) { |
// FONT has already been used |
$this->_formats[$i]->font_index = $fonts[$key]; |
} |
else { |
// Add a new FONT record |
$fonts[$key] = $index; |
$this->_formats[$i]->font_index = $index; |
$index++; |
$font = $this->_formats[$i]->getFont(); |
$this->_append($font); |
} |
} |
} |
/** |
* Store user defined numerical formats i.e. FORMAT records |
* |
* @access private |
*/ |
function _storeAllNumFormats() |
{ |
// Leaning num_format syndrome |
$hash_num_formats = array(); |
$num_formats = array(); |
$index = 164; |
// Iterate through the XF objects and write a FORMAT record if it isn't a |
// built-in format type and if the FORMAT string hasn't already been used. |
// |
for($i=0; $i < count($this->_formats); $i++) |
{ |
$num_format = $this->_formats[$i]->_num_format; |
// Check if $num_format is an index to a built-in format. |
// Also check for a string of zeros, which is a valid format string |
// but would evaluate to zero. |
// |
if (!preg_match("/^0+\d/",$num_format)) |
{ |
if (preg_match("/^\d+$/",$num_format)) { // built-in format |
continue; |
} |
} |
if (isset($hash_num_formats[$num_format])) { |
// FORMAT has already been used |
$this->_formats[$i]->_num_format = $hash_num_formats[$num_format]; |
} |
else{ |
// Add a new FORMAT |
$hash_num_formats[$num_format] = $index; |
$this->_formats[$i]->_num_format = $index; |
array_push($num_formats,$num_format); |
$index++; |
} |
} |
// Write the new FORMAT records starting from 0xA4 |
$index = 164; |
foreach ($num_formats as $num_format) { |
$this->_storeNumFormat($num_format,$index); |
$index++; |
} |
} |
/** |
* Write all XF records. |
* |
* @access private |
*/ |
function _storeAllXfs() |
{ |
// _tmp_format is added by the constructor. We use this to write the default XF's |
// The default font index is 0 |
// |
$format = $this->_tmp_format; |
for ($i=0; $i <= 14; $i++) { |
$xf = $format->getXf('style'); // Style XF |
$this->_append($xf); |
} |
$xf = $format->getXf('cell'); // Cell XF |
$this->_append($xf); |
// User defined XFs |
for($i=0; $i < count($this->_formats); $i++) { |
$xf = $this->_formats[$i]->getXf('cell'); |
$this->_append($xf); |
} |
} |
/** |
* Write all STYLE records. |
* |
* @access private |
*/ |
function _storeAllStyles() |
{ |
$this->_storeStyle(); |
} |
/** |
* Write the EXTERNCOUNT and EXTERNSHEET records. These are used as indexes for |
* the NAME records. |
* |
* @access private |
*/ |
function _storeExterns() |
{ |
// Create EXTERNCOUNT with number of worksheets |
$this->_storeExterncount(count($this->_worksheets)); |
// Create EXTERNSHEET for each worksheet |
foreach ($this->_sheetnames as $sheetname) { |
$this->_storeExternsheet($sheetname); |
} |
} |
/** |
* Write the NAME record to define the print area and the repeat rows and cols. |
* |
* @access private |
*/ |
function _storeNames() |
{ |
// Create the print area NAME records |
foreach ($this->_worksheets as $worksheet) { |
// Write a Name record if the print area has been defined |
if (isset($worksheet->print_rowmin)) |
{ |
$this->_storeNameShort( |
$worksheet->index, |
0x06, // NAME type |
$worksheet->print_rowmin, |
$worksheet->print_rowmax, |
$worksheet->print_colmin, |
$worksheet->print_colmax |
); |
} |
} |
// Create the print title NAME records |
foreach ($this->_worksheets as $worksheet) |
{ |
$rowmin = $worksheet->title_rowmin; |
$rowmax = $worksheet->title_rowmax; |
$colmin = $worksheet->title_colmin; |
$colmax = $worksheet->title_colmax; |
// Determine if row + col, row, col or nothing has been defined |
// and write the appropriate record |
// |
if (isset($rowmin) and isset($colmin)) { |
// Row and column titles have been defined. |
// Row title has been defined. |
$this->_storeNameLong( |
$worksheet->index, |
0x07, // NAME type |
$rowmin, |
$rowmax, |
$colmin, |
$colmax |
); |
} |
elseif (isset($rowmin)) { |
// Row title has been defined. |
$this->_storeNameShort( |
$worksheet->index, |
0x07, // NAME type |
$rowmin, |
$rowmax, |
0x00, |
0xff |
); |
} |
elseif (isset($colmin)) { |
// Column title has been defined. |
$this->_storeNameShort( |
$worksheet->index, |
0x07, // NAME type |
0x0000, |
0x3fff, |
$colmin, |
$colmax |
); |
} |
else { |
// Print title hasn't been defined. |
} |
} |
} |
/****************************************************************************** |
* |
* BIFF RECORDS |
* |
*/ |
/** |
* Write Excel BIFF WINDOW1 record. |
* |
* @access private |
*/ |
function _storeWindow1() |
{ |
$record = 0x003D; // Record identifier |
$length = 0x0012; // Number of bytes to follow |
$xWn = 0x0000; // Horizontal position of window |
$yWn = 0x0000; // Vertical position of window |
$dxWn = 0x25BC; // Width of window |
$dyWn = 0x1572; // Height of window |
$grbit = 0x0038; // Option flags |
$ctabsel = $this->_selected; // Number of workbook tabs selected |
$wTabRatio = 0x0258; // Tab to scrollbar ratio |
$itabFirst = $this->_firstsheet; // 1st displayed worksheet |
$itabCur = $this->_activesheet; // Active worksheet |
$header = pack("vv", $record, $length); |
$data = pack("vvvvvvvvv", $xWn, $yWn, $dxWn, $dyWn, |
$grbit, |
$itabCur, $itabFirst, |
$ctabsel, $wTabRatio); |
$this->_append($header.$data); |
} |
/** |
* Writes Excel BIFF BOUNDSHEET record. |
* |
* @param string $sheetname Worksheet name |
* @param integer $offset Location of worksheet BOF |
* @access private |
*/ |
function _storeBoundsheet($sheetname,$offset) |
{ |
$record = 0x0085; // Record identifier |
$length = 0x07 + strlen($sheetname); // Number of bytes to follow |
$grbit = 0x0000; // Sheet identifier |
$cch = strlen($sheetname); // Length of sheet name |
$header = pack("vv", $record, $length); |
$data = pack("VvC", $offset, $grbit, $cch); |
$this->_append($header.$data.$sheetname); |
} |
/** |
* Write Excel BIFF STYLE records. |
* |
* @access private |
*/ |
function _storeStyle() |
{ |
$record = 0x0293; // Record identifier |
$length = 0x0004; // Bytes to follow |
$ixfe = 0x8000; // Index to style XF |
$BuiltIn = 0x00; // Built-in style |
$iLevel = 0xff; // Outline style level |
$header = pack("vv", $record, $length); |
$data = pack("vCC", $ixfe, $BuiltIn, $iLevel); |
$this->_append($header.$data); |
} |
/** |
* Writes Excel FORMAT record for non "built-in" numerical formats. |
* |
* @param string $format Custom format string |
* @param integer $ifmt Format index code |
* @access private |
*/ |
function _storeNumFormat($format,$ifmt) |
{ |
$record = 0x041E; // Record identifier |
$length = 0x03 + strlen($format); // Number of bytes to follow |
$cch = strlen($format); // Length of format string |
$header = pack("vv", $record, $length); |
$data = pack("vC", $ifmt, $cch); |
$this->_append($header.$data.$format); |
} |
/** |
* Write Excel 1904 record to indicate the date system in use. |
* |
* @access private |
*/ |
function _store1904() |
{ |
$record = 0x0022; // Record identifier |
$length = 0x0002; // Bytes to follow |
$f1904 = $this->_1904; // Flag for 1904 date system |
$header = pack("vv", $record, $length); |
$data = pack("v", $f1904); |
$this->_append($header.$data); |
} |
/** |
* Write BIFF record EXTERNCOUNT to indicate the number of external sheet |
* references in the workbook. |
* |
* Excel only stores references to external sheets that are used in NAME. |
* The workbook NAME record is required to define the print area and the repeat |
* rows and columns. |
* |
* A similar method is used in Worksheet.php for a slightly different purpose. |
* |
* @param integer $cxals Number of external references |
* @access private |
*/ |
function _storeExterncount($cxals) |
{ |
$record = 0x0016; // Record identifier |
$length = 0x0002; // Number of bytes to follow |
$header = pack("vv", $record, $length); |
$data = pack("v", $cxals); |
$this->_append($header.$data); |
} |
/** |
* Writes the Excel BIFF EXTERNSHEET record. These references are used by |
* formulas. NAME record is required to define the print area and the repeat |
* rows and columns. |
* |
* A similar method is used in Worksheet.php for a slightly different purpose. |
* |
* @param string $sheetname Worksheet name |
* @access private |
*/ |
function _storeExternsheet($sheetname) |
{ |
$record = 0x0017; // Record identifier |
$length = 0x02 + strlen($sheetname); // Number of bytes to follow |
$cch = strlen($sheetname); // Length of sheet name |
$rgch = 0x03; // Filename encoding |
$header = pack("vv", $record, $length); |
$data = pack("CC", $cch, $rgch); |
$this->_append($header.$data.$sheetname); |
} |
/** |
* Store the NAME record in the short format that is used for storing the print |
* area, repeat rows only and repeat columns only. |
* |
* @param integer $index Sheet index |
* @param integer $type Built-in name type |
* @param integer $rowmin Start row |
* @param integer $rowmax End row |
* @param integer $colmin Start colum |
* @param integer $colmax End column |
* @access private |
*/ |
function _storeNameShort($index,$type,$rowmin,$rowmax,$colmin,$colmax) |
{ |
$record = 0x0018; // Record identifier |
$length = 0x0024; // Number of bytes to follow |
$grbit = 0x0020; // Option flags |
$chKey = 0x00; // Keyboard shortcut |
$cch = 0x01; // Length of text name |
$cce = 0x0015; // Length of text definition |
$ixals = $index + 1; // Sheet index |
$itab = $ixals; // Equal to ixals |
$cchCustMenu = 0x00; // Length of cust menu text |
$cchDescription = 0x00; // Length of description text |
$cchHelptopic = 0x00; // Length of help topic text |
$cchStatustext = 0x00; // Length of status bar text |
$rgch = $type; // Built-in name type |
$unknown03 = 0x3b; |
$unknown04 = 0xffff-$index; |
$unknown05 = 0x0000; |
$unknown06 = 0x0000; |
$unknown07 = 0x1087; |
$unknown08 = 0x8005; |
$header = pack("vv", $record, $length); |
$data = pack("v", $grbit); |
$data .= pack("C", $chKey); |
$data .= pack("C", $cch); |
$data .= pack("v", $cce); |
$data .= pack("v", $ixals); |
$data .= pack("v", $itab); |
$data .= pack("C", $cchCustMenu); |
$data .= pack("C", $cchDescription); |
$data .= pack("C", $cchHelptopic); |
$data .= pack("C", $cchStatustext); |
$data .= pack("C", $rgch); |
$data .= pack("C", $unknown03); |
$data .= pack("v", $unknown04); |
$data .= pack("v", $unknown05); |
$data .= pack("v", $unknown06); |
$data .= pack("v", $unknown07); |
$data .= pack("v", $unknown08); |
$data .= pack("v", $index); |
$data .= pack("v", $index); |
$data .= pack("v", $rowmin); |
$data .= pack("v", $rowmax); |
$data .= pack("C", $colmin); |
$data .= pack("C", $colmax); |
$this->_append($header.$data); |
} |
/** |
* Store the NAME record in the long format that is used for storing the repeat |
* rows and columns when both are specified. This shares a lot of code with |
* _storeNameShort() but we use a separate method to keep the code clean. |
* Code abstraction for reuse can be carried too far, and I should know. ;-) |
* |
* @param integer $index Sheet index |
* @param integer $type Built-in name type |
* @param integer $rowmin Start row |
* @param integer $rowmax End row |
* @param integer $colmin Start colum |
* @param integer $colmax End column |
* @access private |
*/ |
function _storeNameLong($index,$type,$rowmin,$rowmax,$colmin,$colmax) |
{ |
$record = 0x0018; // Record identifier |
$length = 0x003d; // Number of bytes to follow |
$grbit = 0x0020; // Option flags |
$chKey = 0x00; // Keyboard shortcut |
$cch = 0x01; // Length of text name |
$cce = 0x002e; // Length of text definition |
$ixals = $index + 1; // Sheet index |
$itab = $ixals; // Equal to ixals |
$cchCustMenu = 0x00; // Length of cust menu text |
$cchDescription = 0x00; // Length of description text |
$cchHelptopic = 0x00; // Length of help topic text |
$cchStatustext = 0x00; // Length of status bar text |
$rgch = $type; // Built-in name type |
$unknown01 = 0x29; |
$unknown02 = 0x002b; |
$unknown03 = 0x3b; |
$unknown04 = 0xffff-$index; |
$unknown05 = 0x0000; |
$unknown06 = 0x0000; |
$unknown07 = 0x1087; |
$unknown08 = 0x8008; |
$header = pack("vv", $record, $length); |
$data = pack("v", $grbit); |
$data .= pack("C", $chKey); |
$data .= pack("C", $cch); |
$data .= pack("v", $cce); |
$data .= pack("v", $ixals); |
$data .= pack("v", $itab); |
$data .= pack("C", $cchCustMenu); |
$data .= pack("C", $cchDescription); |
$data .= pack("C", $cchHelptopic); |
$data .= pack("C", $cchStatustext); |
$data .= pack("C", $rgch); |
$data .= pack("C", $unknown01); |
$data .= pack("v", $unknown02); |
// Column definition |
$data .= pack("C", $unknown03); |
$data .= pack("v", $unknown04); |
$data .= pack("v", $unknown05); |
$data .= pack("v", $unknown06); |
$data .= pack("v", $unknown07); |
$data .= pack("v", $unknown08); |
$data .= pack("v", $index); |
$data .= pack("v", $index); |
$data .= pack("v", 0x0000); |
$data .= pack("v", 0x3fff); |
$data .= pack("C", $colmin); |
$data .= pack("C", $colmax); |
// Row definition |
$data .= pack("C", $unknown03); |
$data .= pack("v", $unknown04); |
$data .= pack("v", $unknown05); |
$data .= pack("v", $unknown06); |
$data .= pack("v", $unknown07); |
$data .= pack("v", $unknown08); |
$data .= pack("v", $index); |
$data .= pack("v", $index); |
$data .= pack("v", $rowmin); |
$data .= pack("v", $rowmax); |
$data .= pack("C", 0x00); |
$data .= pack("C", 0xff); |
// End of data |
$data .= pack("C", 0x10); |
$this->_append($header.$data); |
} |
/** |
* Stores the PALETTE biff record. |
* |
* @access private |
*/ |
function _storePalette() |
{ |
$aref = $this->_palette; |
$record = 0x0092; // Record identifier |
$length = 2 + 4 * count($aref); // Number of bytes to follow |
$ccv = count($aref); // Number of RGB values to follow |
$data = ''; // The RGB data |
// Pack the RGB data |
foreach($aref as $color) |
{ |
foreach($color as $byte) { |
$data .= pack("C",$byte); |
} |
} |
$header = pack("vvv", $record, $length, $ccv); |
$this->_append($header.$data); |
} |
} |
?> |
/trunk/jrest/lib/Spreadsheet/Excel/Writer/BIFFwriter.php |
---|
New file |
0,0 → 1,235 |
<?php |
/* |
* Module written/ported by Xavier Noguer <xnoguer@rezebra.com> |
* |
* The majority of this is _NOT_ my code. I simply ported it from the |
* PERL Spreadsheet::WriteExcel module. |
* |
* The author of the Spreadsheet::WriteExcel module is John McNamara |
* <jmcnamara@cpan.org> |
* |
* I _DO_ maintain this code, and John McNamara has nothing to do with the |
* porting of this code to PHP. Any questions directly related to this |
* class library should be directed to me. |
* |
* License Information: |
* |
* Spreadsheet_Excel_Writer: A library for generating Excel Spreadsheets |
* Copyright (c) 2002-2003 Xavier Noguer xnoguer@rezebra.com |
* |
* This library is free software; you can redistribute it and/or |
* modify it under the terms of the GNU Lesser General Public |
* License as published by the Free Software Foundation; either |
* version 2.1 of the License, or (at your option) any later version. |
* |
* This library is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
* Lesser General Public License for more details. |
* |
* You should have received a copy of the GNU Lesser General Public |
* License along with this library; if not, write to the Free Software |
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
*/ |
require_once('PEAR.php'); |
/** |
* Class for writing Excel BIFF records. |
* |
* From "MICROSOFT EXCEL BINARY FILE FORMAT" by Mark O'Brien (Microsoft Corporation): |
* |
* BIFF (BInary File Format) is the file format in which Excel documents are |
* saved on disk. A BIFF file is a complete description of an Excel document. |
* BIFF files consist of sequences of variable-length records. There are many |
* different types of BIFF records. For example, one record type describes a |
* formula entered into a cell; one describes the size and location of a |
* window into a document; another describes a picture format. |
* |
* @author Xavier Noguer <xnoguer@rezebra.com> |
* @category FileFormats |
* @package Spreadsheet_Excel_Writer |
*/ |
class Spreadsheet_Excel_Writer_BIFFwriter extends PEAR |
{ |
/** |
* The BIFF/Excel version (5). |
* @var integer |
*/ |
var $_BIFF_version = 0x0500; |
/** |
* The byte order of this architecture. 0 => little endian, 1 => big endian |
* @var integer |
*/ |
var $_byte_order; |
/** |
* The string containing the data of the BIFF stream |
* @var string |
*/ |
var $_data; |
/** |
* The size of the data in bytes. Should be the same as strlen($this->_data) |
* @var integer |
*/ |
var $_datasize; |
/** |
* The maximun length for a BIFF record. See _addContinue() |
* @var integer |
* @see _addContinue() |
*/ |
var $_limit; |
/** |
* Constructor |
* |
* @access public |
*/ |
function Spreadsheet_Excel_Writer_BIFFwriter() |
{ |
$this->_byte_order = ''; |
$this->_data = ''; |
$this->_datasize = 0; |
$this->_limit = 2080; |
// Set the byte order |
$this->_setByteOrder(); |
} |
/** |
* Determine the byte order and store it as class data to avoid |
* recalculating it for each call to new(). |
* |
* @access private |
*/ |
function _setByteOrder() |
{ |
if ($this->_byte_order == '') |
{ |
// Check if "pack" gives the required IEEE 64bit float |
$teststr = pack("d", 1.2345); |
$number = pack("C8", 0x8D, 0x97, 0x6E, 0x12, 0x83, 0xC0, 0xF3, 0x3F); |
if ($number == $teststr) { |
$byte_order = 0; // Little Endian |
} |
elseif ($number == strrev($teststr)){ |
$byte_order = 1; // Big Endian |
} |
else { |
// Give up. I'll fix this in a later version. |
$this->raiseError("Required floating point format not supported ". |
"on this platform."); |
} |
} |
$this->_byte_order = $byte_order; |
} |
/** |
* General storage function |
* |
* @param string $data binary data to prepend |
* @access private |
*/ |
function _prepend($data) |
{ |
if (strlen($data) > $this->_limit) { |
$data = $this->_addContinue($data); |
} |
$this->_data = $data.$this->_data; |
$this->_datasize += strlen($data); |
} |
/** |
* General storage function |
* |
* @param string $data binary data to append |
* @access private |
*/ |
function _append($data) |
{ |
if (strlen($data) > $this->_limit) { |
$data = $this->_addContinue($data); |
} |
$this->_data = $this->_data.$data; |
$this->_datasize += strlen($data); |
} |
/** |
* Writes Excel BOF record to indicate the beginning of a stream or |
* sub-stream in the BIFF file. |
* |
* @param integer $type type of BIFF file to write: 0x0005 Workbook, 0x0010 Worksheet. |
* @access private |
*/ |
function _storeBof($type) |
{ |
$record = 0x0809; // Record identifier |
$length = 0x0008; // Number of bytes to follow |
$version = $this->_BIFF_version; |
// According to the SDK $build and $year should be set to zero. |
// However, this throws a warning in Excel 5. So, use these |
// magic numbers. |
$build = 0x096C; |
$year = 0x07C9; |
$header = pack("vv", $record, $length); |
$data = pack("vvvv", $version, $type, $build, $year); |
$this->_prepend($header.$data); |
} |
/** |
* Writes Excel EOF record to indicate the end of a BIFF stream. |
* |
* @access private |
*/ |
function _storeEof() |
{ |
$record = 0x000A; // Record identifier |
$length = 0x0000; // Number of bytes to follow |
$header = pack("vv", $record, $length); |
$this->_append($header); |
} |
/** |
* Excel limits the size of BIFF records. In Excel 5 the limit is 2084 bytes. In |
* Excel 97 the limit is 8228 bytes. Records that are longer than these limits |
* must be split up into CONTINUE blocks. |
* |
* This function takes a long BIFF record and inserts CONTINUE records as |
* necessary. |
* |
* @param string $data The original binary data to be written |
* @return string A very convenient string of continue blocks |
* @access private |
*/ |
function _addContinue($data) |
{ |
$limit = $this->_limit; |
$record = 0x003C; // Record identifier |
// The first 2080/8224 bytes remain intact. However, we have to change |
// the length field of the record. |
$tmp = substr($data, 0, 2).pack("v", $limit-4).substr($data, 4, $limit - 4); |
$header = pack("vv", $record, $limit); // Headers for continue records |
// Retrieve chunks of 2080/8224 bytes +4 for the header. |
for($i = $limit; $i < strlen($data) - $limit; $i += $limit) |
{ |
$tmp .= $header; |
$tmp .= substr($data, $i, $limit); |
} |
// Retrieve the last chunk of data |
$header = pack("vv", $record, strlen($data) - $i); |
$tmp .= $header; |
$tmp .= substr($data,$i,strlen($data) - $i); |
return($tmp); |
} |
} |
?> |
/trunk/jrest/lib/Spreadsheet/Excel/Writer.php |
---|
New file |
0,0 → 1,75 |
<?php |
/* |
* Module written/ported by Xavier Noguer <xnoguer@rezebra.com> |
* |
* PERL Spreadsheet::WriteExcel module. |
* |
* The author of the Spreadsheet::WriteExcel module is John McNamara |
* <jmcnamara@cpan.org> |
* |
* I _DO_ maintain this code, and John McNamara has nothing to do with the |
* porting of this code to PHP. Any questions directly related to this |
* class library should be directed to me. |
* |
* License Information: |
* |
* Spreadsheet_Excel_Writer: A library for generating Excel Spreadsheets |
* Copyright (c) 2002-2003 Xavier Noguer xnoguer@rezebra.com |
* |
* This library is free software; you can redistribute it and/or |
* modify it under the terms of the GNU Lesser General Public |
* License as published by the Free Software Foundation; either |
* version 2.1 of the License, or (at your option) any later version. |
* |
* This library is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
* Lesser General Public License for more details. |
* |
* You should have received a copy of the GNU Lesser General Public |
* License along with this library; if not, write to the Free Software |
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
*/ |
require_once('PEAR.php'); |
require_once('Writer/Workbook.php'); |
/** |
* Class for writing Excel Spreadsheets. This class should change COMPLETELY. |
* |
* @author Xavier Noguer <xnoguer@rezebra.com> |
* @category FileFormats |
* @package Spreadsheet_Excel_Writer |
*/ |
class Spreadsheet_Excel_Writer extends Spreadsheet_Excel_Writer_Workbook |
{ |
/** |
* The constructor. It just creates a Workbook |
* |
* @param string $filename The optional filename for the Workbook. |
* @return Spreadsheet_Excel_Writer_Workbook The Workbook created |
*/ |
function Spreadsheet_Excel_Writer($filename = '') |
{ |
$this->_filename = $filename; |
$this->Spreadsheet_Excel_Writer_Workbook($filename); |
} |
/** |
* Send HTTP headers for the Excel file. |
* |
* @param string $filename The filename to use for HTTP headers |
* @access public |
*/ |
function send($filename) |
{ |
header("Content-type: application/vnd.ms-excel"); |
header("Content-Disposition: attachment; filename=$filename"); |
header("Expires: 0"); |
header("Cache-Control: must-revalidate, post-check=0,pre-check=0"); |
header("Pragma: public"); |
} |
} |
?> |
/trunk/jrest/lib/ezmlmAccessObject.class.php |
---|
New file |
0,0 → 1,354 |
<?php |
//vim: set expandtab tabstop=4 shiftwidth=4: |
// Copyright (C) 1999-2006 Tela Botanica (accueil@tela-botanica.org) |
// |
// Ce logiciel est un programme informatique servant à gérer du contenu et des |
// applications web. |
// Ce logiciel est regi par la licence CeCILL soumise au droit francais et |
// respectant les principes de diffusion des logiciels libres. Vous pouvez |
// utiliser, modifier et/ou redistribuer ce programme sous les conditions |
// de la licence CeCILL telle que diffusee par le CEA, le CNRS et l'INRIA |
// sur le site "http://www.cecill.info". |
// En contrepartie de l'accessibilite au code source et des droits de copie, |
// de modification et de redistribution accordes par cette licence, il n'est |
// offert aux utilisateurs qu'une garantie limitee. Pour les memes raisons, |
// seule une responsabilite restreinte pese sur l'auteur du programme, le |
// titulaire des droits patrimoniaux et les concedants successifs. |
// A cet egard l'attention de l'utilisateur est attiree sur les risques |
// associes au chargement, a l'utilisation, a la modification et/ou au |
// developpement et a la reproduction du logiciel par l'utilisateur etant |
// donne sa specificite de logiciel libre, qui peut le rendre complexe a |
// manipuler et qui le reserve donc a des developpeurs et des professionnels |
// avertis possedant des connaissances informatiques approfondies. Les |
// utilisateurs sont donc invites a charger et tester l'adequation du |
// logiciel a leurs besoins dans des conditions permettant d'assurer la |
// securite de leurs systemes et ou de leurs donnees et, plus generalement, |
// a l'utiliser et l'exploiter dans les memes conditions de securite. |
// Le fait que vous puissiez acceder a cet en-tete signifie que vous avez |
// pris connaissance de la licence CeCILL, et que vous en avez accepte les |
// termes. |
// ---- |
// CVS : $Id: ezmlmAccessObject.class.php,v 1.6 2008-08-25 15:16:59 alexandre_tb Exp $ |
/** |
* Application projet |
* |
* La classe ezmlmAccessObject |
* |
*@package projet |
//Auteur original : |
*@author Alexandre Granier <alexandre@tela-botanica.org> |
//Autres auteurs : |
*@author Aucun |
*@copyright Tela-Botanica 2000-2006 |
*@version $Revision: 1.6 $ |
// +------------------------------------------------------------------------------------------------------+ |
*/ |
/** Etend XML_Parser_Simple */ |
require_once 'XML/Parser/Simple.php' ; |
/** |
* Les codes erreurs |
*/ |
define ('EZMLM_ACCESS_OBJECT_ACTION_NON_SUPPORTEE', 206) ; |
/** |
* classe ezmlmAccessObject parse les fichiers XML |
* issue de ezmlm |
* |
* @category XML |
* @package projet |
* @author alex |
*/ |
class ezmlmAccessObject extends XML_Parser_Simple { |
/** |
* Le domaine de la liste |
*/ |
var $domaine ; |
/** |
* Le nom de la liste |
*/ |
var $liste ; |
/** |
* Les actions valides |
*/ |
var $actions_supportees = array ('calendrier_messages', |
'message', |
'derniers_messages', |
'messages_auteur', |
'messages_mois', |
'messages_thread', |
'supprimer', |
'liste_abonnes', |
'nombre_messages'); |
/** |
* l'action selectionnee |
*/ |
var $action ; |
/** |
* La langue 'fr-FR' |
*/ |
var $langue ; |
/** |
* L'url de base |
*/ |
var $url ; |
/** |
* L'identifiant du repertoire |
*/ |
var $identifiant_repertoire ; |
/** |
* Identifiant message |
*/ |
var $identifiant_message; |
/** |
* L'identifiant du repertoire |
*/ |
var $_numeroRepertoireSuivant ; |
/** |
* L'identifiant du repertoire |
*/ |
var $hash_auteur ; |
/** |
* Le mois a afficher |
*/ |
var $mois ; |
var $_numeraRepertoirePrecedent; |
/** |
* Identifiant message |
*/ |
var $_numeroFichierSuivant; |
var $_numeroFichierPrecedent; |
var $chemin_fichier_xml; |
/** |
* Creation de l'objet d'acces |
* |
*/ |
function ezmlmAccessObject ($action, $domaine, $liste, $langue = 'fr', $url = '') { |
$this->XML_Parser_Simple(null, 'func') ; |
$this->action = $action ; |
$this->domaine = $domaine ; |
$this->liste = $liste ; |
$this->langue = $langue ; |
$this->url = $url ; |
} |
/** |
* Gestion des balises |
* |
* Cette methode specifie les balises reconnus par ezmlmAccessObject |
* Elle remplace la methode handleElement de XML_Parser_Simple |
* |
* @access public |
* @param string nom de l'element (Voir la doc de PHP) |
* @param array attributes |
* @param |
* @link http://fr.php.net/manual/fr/ref.xml.php manuel |
*/ |
function handleElement_ezmlm_message ($name, $attribs, $data) { |
echo $data ; |
} |
function handleElement_message_suivant ($name, $attribs, $data) { |
$this->_numeroRepertoireSuivant = $attribs['NUMERO_REPERTOIRE'] ; |
$this->_numeroFichierSuivant = $attribs['NUMERO'] ; |
} |
function handleElement_message_precedent ($name, $attribs, $data) { |
$this->_numeroRepertoirePrecedent = $attribs['NUMERO_REPERTOIRE'] ; |
$this->_numeroFichierPrecedent = $attribs['NUMERO'] ; |
} |
function handleElement_ezmlm_calendrier_messages ($name, $attribs, $data) { echo $data ; } |
function handleElement_ezmlm_derniers_messages ($name, $attribs, $data) { echo $data ; } |
function handleElement_ezmlm_messages_auteur ($name, $attribs, $data) { echo $data ; } |
function handleElement_ezmlm_messages_mois ($name, $attribs, $data) { echo $data ; } |
function handleElement_ezmlm_messages_thread ($name, $attribs, $data) { echo $data ; } |
function handleElement_ezmlm_liste_abonnes ($name, $attribs, $data) { echo $data ; } |
function handleElement_ezmlm_nombre_messages ($name, $attribs, $data) { echo $data ; } |
/** |
* Choix de l'action |
* |
* Liste des actions : |
* 'calendrier_messages' |
* |
* @access public |
* @param string une action qui doit etre supporté |
*/ |
function setAction($action) { |
// verification de l'action |
if (!in_array($action, $this->actions_supportees)) { |
return raiseError(EZMLM_ACCESS_OBJECT_ACTION_NON_SUPPORTEE) ; |
} |
$this->action = $action ; |
// Libere les ressources (XML_Parser::free) |
$this->free(); |
// On vide l url |
//$this->url = ''; |
$this->chemin_fichier_xml = ''; |
// Charge la nouvelle action |
$this->load() ; |
} |
/** |
* Charge une action |
* |
* cad affecte un fichier xml au parser |
* |
* @access public |
*/ |
function load() { |
$this->chemin_fichier_xml = PROJET_SERVEUR_VPOPMAIL.'/'.$this->action.'.php?domaine='. |
$this->domaine.'&liste='.$this->liste.'&langue='. |
$this->langue ; |
if ($this->url != '') $this->chemin_fichier_xml.= '&url='.urlencode($this->url) ; |
if (isset ($this->identifiant_repertoire)) |
$this->chemin_fichier_xml .= '&actionargs[]='.$this->identifiant_repertoire ; |
if (isset ($this->identifiant_message)) |
$this->chemin_fichier_xml .= '&actionargs[]='.$this->identifiant_message ; |
if (isset ($this->hash_auteur)) |
$this->chemin_fichier_xml .= '&actionargs[]='.$this->hash_auteur ; |
if (isset ($this->mois)) |
$this->chemin_fichier_xml .= '&actionargs[]='.$this->mois ; |
$this->setInputFile($this->chemin_fichier_xml) ; |
} |
/** |
* Precise un message a extraire |
* |
* On indique le numero de repertoire ezmlm et le numero du message |
* @param integer le numero du repertoire |
* @param integer le numero du message |
* |
*/ |
function setIdMessage ($identifiant_repertoire, $identifiant_message) { |
$this->identifiant_repertoire = $identifiant_repertoire ; |
$this->identifiant_message = $identifiant_message ; |
} |
/** |
* Precise un auteur |
* |
* On indique le numero de repertoire ezmlm et le numero du message |
* @param string le hash d'un auteur |
* |
*/ |
function setHashAuteur ($hash_auteur) { |
$this->hash_auteur = $hash_auteur; |
} |
/** |
* Precise un mois |
* |
* On indique le numero de repertoire ezmlm et le numéro du message |
* @param string le hash d'un auteur |
* |
*/ |
function setMois ($mois) { |
$this->mois = $mois; |
} |
/** |
* Renvoi le numero du repertoire suivant |
* |
* |
*/ |
function getNumeroRepertoireSuivant() { return $this->_numeroRepertoireSuivant; } |
function getNumeroFichierSuivant () { return $this->_numeroFichierSuivant ; } |
function getNumeroRepertoirePrecedent() { return $this->_numeroRepertoirePrecedent; } |
function getNumeroFichierPrecedent () { return $this->_numeroFichierPrecedent ; } |
function getNumeroMessage () { return $this->_numeroMessage ; } |
function getNombreTotalMessage () { return $this->_nombreTotalMessage ; } |
function parse() |
{ |
if (substr(phpversion(), 0, 1) == '5') { |
try { |
$xml = new SimpleXMLElement($this->chemin_fichier_xml, null, true); |
switch ($this->action) { |
case 'calendrier_messages' :echo utf8_decode($xml); |
echo utf8_decode($xml->ezmlm_calendrier_messages); |
break; |
case 'message': |
echo utf8_decode ($xml); |
$this->_numeroRepertoirePrecedent = $xml->message_precedent['numero_repertoire']; |
$this->_numeroRepertoireSuivant = $xml->message_suivant['numero_repertoire']; |
$this->_numeroFichierSuivant = $xml->message_suivant['numero']; |
$this->_numeroFichierPrecedent = $xml->message_precedent['numero']; |
$this->_numeroMessage = $xml->numero; |
$this->_nombreTotalMessage = $xml->numero['total_message']; |
break; |
case 'nombre_messages': |
echo $xml[0]; |
break; |
case 'liste_abonnes': |
return $xml; |
break; |
default : |
echo utf8_decode($xml); |
} |
$error = 'Erreur dans l\'accès au fichier:<br />'.$this->chemin_fichier_xml.'<br />'; |
$error = ''; |
throw new Exception($error); |
} |
catch (Exception $e) { |
echo $e->getMessage().'<br />'; |
//echo $this->chemin_fichier_xml; |
} |
} else { |
return parent::parse(); |
} |
} |
} |
?> |
/trunk/jrest/lib/zip.php |
---|
New file |
0,0 → 1,190 |
<?php |
/* vim: set expandtab sw=4 ts=4 sts=4: */ |
/** |
* |
* @version $Id: zip.lib.php 10240 2007-04-01 11:02:46Z cybot_tm $ |
*/ |
/** |
* Zip file creation class. |
* Makes zip files. |
* |
* Based on : |
* |
* http://www.zend.com/codex.php?id=535&single=1 |
* By Eric Mueller <eric@themepark.com> |
* |
* http://www.zend.com/codex.php?id=470&single=1 |
* by Denis125 <webmaster@atlant.ru> |
* |
* a patch from Peter Listiak <mlady@users.sourceforge.net> for last modified |
* date and time of the compressed file |
* |
* Official ZIP file format: http://www.pkware.com/appnote.txt |
* |
* @access public |
*/ |
class zipfile |
{ |
/** |
* Array to store compressed data |
* |
* @var array $datasec |
*/ |
var $datasec = array(); |
/** |
* Central directory |
* |
* @var array $ctrl_dir |
*/ |
var $ctrl_dir = array(); |
/** |
* End of central directory record |
* |
* @var string $eof_ctrl_dir |
*/ |
var $eof_ctrl_dir = "\x50\x4b\x05\x06\x00\x00\x00\x00"; |
/** |
* Last offset position |
* |
* @var integer $old_offset |
*/ |
var $old_offset = 0; |
/** |
* Converts an Unix timestamp to a four byte DOS date and time format (date |
* in high two bytes, time in low two bytes allowing magnitude comparison). |
* |
* @param integer the current Unix timestamp |
* |
* @return integer the current date in a four byte DOS format |
* |
* @access private |
*/ |
function unix2DosTime($unixtime = 0) { |
$timearray = ($unixtime == 0) ? getdate() : getdate($unixtime); |
if ($timearray['year'] < 1980) { |
$timearray['year'] = 1980; |
$timearray['mon'] = 1; |
$timearray['mday'] = 1; |
$timearray['hours'] = 0; |
$timearray['minutes'] = 0; |
$timearray['seconds'] = 0; |
} // end if |
return (($timearray['year'] - 1980) << 25) | ($timearray['mon'] << 21) | ($timearray['mday'] << 16) | |
($timearray['hours'] << 11) | ($timearray['minutes'] << 5) | ($timearray['seconds'] >> 1); |
} // end of the 'unix2DosTime()' method |
/** |
* Adds "file" to archive |
* |
* @param string file contents |
* @param string name of the file in the archive (may contains the path) |
* @param integer the current timestamp |
* |
* @access public |
*/ |
function addFile($data, $name, $time = 0) |
{ |
$name = str_replace('\\', '/', $name); |
$dtime = dechex($this->unix2DosTime($time)); |
$hexdtime = '\x' . $dtime[6] . $dtime[7] |
. '\x' . $dtime[4] . $dtime[5] |
. '\x' . $dtime[2] . $dtime[3] |
. '\x' . $dtime[0] . $dtime[1]; |
eval('$hexdtime = "' . $hexdtime . '";'); |
$fr = "\x50\x4b\x03\x04"; |
$fr .= "\x14\x00"; // ver needed to extract |
$fr .= "\x00\x00"; // gen purpose bit flag |
$fr .= "\x08\x00"; // compression method |
$fr .= $hexdtime; // last mod time and date |
// "local file header" segment |
$unc_len = strlen($data); |
$crc = crc32($data); |
$zdata = gzcompress($data); |
$zdata = substr(substr($zdata, 0, strlen($zdata) - 4), 2); // fix crc bug |
$c_len = strlen($zdata); |
$fr .= pack('V', $crc); // crc32 |
$fr .= pack('V', $c_len); // compressed filesize |
$fr .= pack('V', $unc_len); // uncompressed filesize |
$fr .= pack('v', strlen($name)); // length of filename |
$fr .= pack('v', 0); // extra field length |
$fr .= $name; |
// "file data" segment |
$fr .= $zdata; |
// "data descriptor" segment (optional but necessary if archive is not |
// served as file) |
// nijel(2004-10-19): this seems not to be needed at all and causes |
// problems in some cases (bug #1037737) |
//$fr .= pack('V', $crc); // crc32 |
//$fr .= pack('V', $c_len); // compressed filesize |
//$fr .= pack('V', $unc_len); // uncompressed filesize |
// add this entry to array |
$this -> datasec[] = $fr; |
// now add to central directory record |
$cdrec = "\x50\x4b\x01\x02"; |
$cdrec .= "\x00\x00"; // version made by |
$cdrec .= "\x14\x00"; // version needed to extract |
$cdrec .= "\x00\x00"; // gen purpose bit flag |
$cdrec .= "\x08\x00"; // compression method |
$cdrec .= $hexdtime; // last mod time & date |
$cdrec .= pack('V', $crc); // crc32 |
$cdrec .= pack('V', $c_len); // compressed filesize |
$cdrec .= pack('V', $unc_len); // uncompressed filesize |
$cdrec .= pack('v', strlen($name)); // length of filename |
$cdrec .= pack('v', 0); // extra field length |
$cdrec .= pack('v', 0); // file comment length |
$cdrec .= pack('v', 0); // disk number start |
$cdrec .= pack('v', 0); // internal file attributes |
$cdrec .= pack('V', 32); // external file attributes - 'archive' bit set |
$cdrec .= pack('V', $this -> old_offset); // relative offset of local header |
$this -> old_offset += strlen($fr); |
$cdrec .= $name; |
// optional extra field, file comment goes here |
// save to central directory |
$this -> ctrl_dir[] = $cdrec; |
} // end of the 'addFile()' method |
/** |
* Dumps out file |
* |
* @return string the zipped file |
* |
* @access public |
*/ |
function file() |
{ |
$data = implode('', $this -> datasec); |
$ctrldir = implode('', $this -> ctrl_dir); |
return |
$data . |
$ctrldir . |
$this -> eof_ctrl_dir . |
pack('v', sizeof($this -> ctrl_dir)) . // total # of entries "on this disk" |
pack('v', sizeof($this -> ctrl_dir)) . // total # of entries overall |
pack('V', strlen($ctrldir)) . // size of central dir |
pack('V', strlen($data)) . // offset to start of central dir |
"\x00\x00"; // .zip file comment length |
} // end of the 'file()' method |
} // end of the 'zipfile' class |
?> |
/trunk/jrest/lib/PEAR.php |
---|
New file |
0,0 → 1,971 |
<?php |
// |
// +----------------------------------------------------------------------+ |
// | PEAR, the PHP Extension and Application Repository | |
// +----------------------------------------------------------------------+ |
// | Copyright (c) 1997-2004 The PHP Group | |
// +----------------------------------------------------------------------+ |
// | This source file is subject to version 2.0 of the PHP license, | |
// | that is bundled with this package in the file LICENSE, and is | |
// | available through the world-wide-web at the following url: | |
// | http://www.php.net/license/3_0.txt. | |
// | If you did not receive a copy of the PHP license and are unable to | |
// | obtain it through the world-wide-web, please send a note to | |
// | license@php.net so we can mail you a copy immediately. | |
// +----------------------------------------------------------------------+ |
// | Authors: Sterling Hughes <sterling@php.net> | |
// | Stig Bakken <ssb@php.net> | |
// | Tomas V.V.Cox <cox@idecnet.com> | |
// +----------------------------------------------------------------------+ |
// |
// $Id$ |
// |
define('PEAR_ERROR_RETURN', 1); |
define('PEAR_ERROR_PRINT', 2); |
define('PEAR_ERROR_TRIGGER', 4); |
define('PEAR_ERROR_DIE', 8); |
define('PEAR_ERROR_CALLBACK', 16); |
define('PEAR_ERROR_EXCEPTION', 32); |
define('PEAR_ZE2', (function_exists('version_compare') && |
version_compare(zend_version(), "2-dev", "ge"))); |
if (substr(PHP_OS, 0, 3) == 'WIN') { |
define('OS_WINDOWS', true); |
define('OS_UNIX', false); |
define('PEAR_OS', 'Windows'); |
} else { |
define('OS_WINDOWS', false); |
define('OS_UNIX', true); |
define('PEAR_OS', 'Unix'); // blatant assumption |
} |
// instant backwards compatibility |
if (!defined('PATH_SEPARATOR')) { |
if (OS_WINDOWS) { |
define('PATH_SEPARATOR', ';'); |
} else { |
define('PATH_SEPARATOR', ':'); |
} |
} |
$GLOBALS['_PEAR_default_error_mode'] = PEAR_ERROR_RETURN; |
$GLOBALS['_PEAR_default_error_options'] = E_USER_NOTICE; |
$GLOBALS['_PEAR_destructor_object_list'] = array(); |
$GLOBALS['_PEAR_shutdown_funcs'] = array(); |
$GLOBALS['_PEAR_error_handler_stack'] = array(); |
ini_set('track_errors', true); |
/** |
* Base class for other PEAR classes. Provides rudimentary |
* emulation of destructors. |
* |
* If you want a destructor in your class, inherit PEAR and make a |
* destructor method called _yourclassname (same name as the |
* constructor, but with a "_" prefix). Also, in your constructor you |
* have to call the PEAR constructor: $this->PEAR();. |
* The destructor method will be called without parameters. Note that |
* at in some SAPI implementations (such as Apache), any output during |
* the request shutdown (in which destructors are called) seems to be |
* discarded. If you need to get any debug information from your |
* destructor, use error_log(), syslog() or something similar. |
* |
* IMPORTANT! To use the emulated destructors you need to create the |
* objects by reference: $obj =& new PEAR_child; |
* |
* @since PHP 4.0.2 |
* @author Stig Bakken <ssb@php.net> |
* @see http://pear.php.net/manual/ |
*/ |
class PEAR |
{ |
// {{{ properties |
/** |
* Whether to enable internal debug messages. |
* |
* @var bool |
* @access private |
*/ |
var $_debug = false; |
/** |
* Default error mode for this object. |
* |
* @var int |
* @access private |
*/ |
var $_default_error_mode = null; |
/** |
* Default error options used for this object when error mode |
* is PEAR_ERROR_TRIGGER. |
* |
* @var int |
* @access private |
*/ |
var $_default_error_options = null; |
/** |
* Default error handler (callback) for this object, if error mode is |
* PEAR_ERROR_CALLBACK. |
* |
* @var string |
* @access private |
*/ |
var $_default_error_handler = ''; |
/** |
* Which class to use for error objects. |
* |
* @var string |
* @access private |
*/ |
var $_error_class = 'PEAR_Error'; |
/** |
* An array of expected errors. |
* |
* @var array |
* @access private |
*/ |
var $_expected_errors = array(); |
// }}} |
// {{{ constructor |
/** |
* Constructor. Registers this object in |
* $_PEAR_destructor_object_list for destructor emulation if a |
* destructor object exists. |
* |
* @param string $error_class (optional) which class to use for |
* error objects, defaults to PEAR_Error. |
* @access public |
* @return void |
*/ |
function PEAR($error_class = null) |
{ |
$classname = get_class($this); |
if ($this->_debug) { |
print "PEAR constructor called, class=$classname\n"; |
} |
if ($error_class !== null) { |
$this->_error_class = $error_class; |
} |
while ($classname) { |
$destructor = "_$classname"; |
if (method_exists($this, $destructor)) { |
global $_PEAR_destructor_object_list; |
$_PEAR_destructor_object_list[] = &$this; |
break; |
} else { |
$classname = get_parent_class($classname); |
} |
} |
} |
// }}} |
// {{{ destructor |
/** |
* Destructor (the emulated type of...). Does nothing right now, |
* but is included for forward compatibility, so subclass |
* destructors should always call it. |
* |
* See the note in the class desciption about output from |
* destructors. |
* |
* @access public |
* @return void |
*/ |
function _PEAR() { |
if ($this->_debug) { |
printf("PEAR destructor called, class=%s\n", get_class($this)); |
} |
} |
// }}} |
// {{{ getStaticProperty() |
/** |
* If you have a class that's mostly/entirely static, and you need static |
* properties, you can use this method to simulate them. Eg. in your method(s) |
* do this: $myVar = &PEAR::getStaticProperty('myVar'); |
* You MUST use a reference, or they will not persist! |
* |
* @access public |
* @param string $class The calling classname, to prevent clashes |
* @param string $var The variable to retrieve. |
* @return mixed A reference to the variable. If not set it will be |
* auto initialised to NULL. |
*/ |
function &getStaticProperty($class, $var) |
{ |
static $properties; |
return $properties[$class][$var]; |
} |
// }}} |
// {{{ registerShutdownFunc() |
/** |
* Use this function to register a shutdown method for static |
* classes. |
* |
* @access public |
* @param mixed $func The function name (or array of class/method) to call |
* @param mixed $args The arguments to pass to the function |
* @return void |
*/ |
function registerShutdownFunc($func, $args = array()) |
{ |
$GLOBALS['_PEAR_shutdown_funcs'][] = array($func, $args); |
} |
// }}} |
// {{{ isError() |
/** |
* Tell whether a value is a PEAR error. |
* |
* @param mixed $data the value to test |
* @param int $code if $data is an error object, return true |
* only if $code is a string and |
* $obj->getMessage() == $code or |
* $code is an integer and $obj->getCode() == $code |
* @access public |
* @return bool true if parameter is an error |
*/ |
function isError($data, $code = null) |
{ |
if (is_a($data, 'PEAR_Error')) { |
if (is_null($code)) { |
return true; |
} elseif (is_string($code)) { |
return $data->getMessage() == $code; |
} else { |
return $data->getCode() == $code; |
} |
} |
return false; |
} |
// }}} |
// {{{ setErrorHandling() |
/** |
* Sets how errors generated by this object should be handled. |
* Can be invoked both in objects and statically. If called |
* statically, setErrorHandling sets the default behaviour for all |
* PEAR objects. If called in an object, setErrorHandling sets |
* the default behaviour for that object. |
* |
* @param int $mode |
* One of PEAR_ERROR_RETURN, PEAR_ERROR_PRINT, |
* PEAR_ERROR_TRIGGER, PEAR_ERROR_DIE, |
* PEAR_ERROR_CALLBACK or PEAR_ERROR_EXCEPTION. |
* |
* @param mixed $options |
* When $mode is PEAR_ERROR_TRIGGER, this is the error level (one |
* of E_USER_NOTICE, E_USER_WARNING or E_USER_ERROR). |
* |
* When $mode is PEAR_ERROR_CALLBACK, this parameter is expected |
* to be the callback function or method. A callback |
* function is a string with the name of the function, a |
* callback method is an array of two elements: the element |
* at index 0 is the object, and the element at index 1 is |
* the name of the method to call in the object. |
* |
* When $mode is PEAR_ERROR_PRINT or PEAR_ERROR_DIE, this is |
* a printf format string used when printing the error |
* message. |
* |
* @access public |
* @return void |
* @see PEAR_ERROR_RETURN |
* @see PEAR_ERROR_PRINT |
* @see PEAR_ERROR_TRIGGER |
* @see PEAR_ERROR_DIE |
* @see PEAR_ERROR_CALLBACK |
* @see PEAR_ERROR_EXCEPTION |
* |
* @since PHP 4.0.5 |
*/ |
function setErrorHandling($mode = null, $options = null) |
{ |
if (isset($this) && is_a($this, 'PEAR')) { |
$setmode = &$this->_default_error_mode; |
$setoptions = &$this->_default_error_options; |
} else { |
$setmode = &$GLOBALS['_PEAR_default_error_mode']; |
$setoptions = &$GLOBALS['_PEAR_default_error_options']; |
} |
switch ($mode) { |
case PEAR_ERROR_RETURN: |
case PEAR_ERROR_PRINT: |
case PEAR_ERROR_TRIGGER: |
case PEAR_ERROR_DIE: |
case PEAR_ERROR_EXCEPTION: |
case null: |
$setmode = $mode; |
$setoptions = $options; |
break; |
case PEAR_ERROR_CALLBACK: |
$setmode = $mode; |
// class/object method callback |
if (is_callable($options)) { |
$setoptions = $options; |
} else { |
trigger_error("invalid error callback", E_USER_WARNING); |
} |
break; |
default: |
trigger_error("invalid error mode", E_USER_WARNING); |
break; |
} |
} |
// }}} |
// {{{ expectError() |
/** |
* This method is used to tell which errors you expect to get. |
* Expected errors are always returned with error mode |
* PEAR_ERROR_RETURN. Expected error codes are stored in a stack, |
* and this method pushes a new element onto it. The list of |
* expected errors are in effect until they are popped off the |
* stack with the popExpect() method. |
* |
* Note that this method can not be called statically |
* |
* @param mixed $code a single error code or an array of error codes to expect |
* |
* @return int the new depth of the "expected errors" stack |
* @access public |
*/ |
function expectError($code = '*') |
{ |
if (is_array($code)) { |
array_push($this->_expected_errors, $code); |
} else { |
array_push($this->_expected_errors, array($code)); |
} |
return sizeof($this->_expected_errors); |
} |
// }}} |
// {{{ popExpect() |
/** |
* This method pops one element off the expected error codes |
* stack. |
* |
* @return array the list of error codes that were popped |
*/ |
function popExpect() |
{ |
return array_pop($this->_expected_errors); |
} |
// }}} |
// {{{ _checkDelExpect() |
/** |
* This method checks unsets an error code if available |
* |
* @param mixed error code |
* @return bool true if the error code was unset, false otherwise |
* @access private |
* @since PHP 4.3.0 |
*/ |
function _checkDelExpect($error_code) |
{ |
$deleted = false; |
foreach ($this->_expected_errors AS $key => $error_array) { |
if (in_array($error_code, $error_array)) { |
unset($this->_expected_errors[$key][array_search($error_code, $error_array)]); |
$deleted = true; |
} |
// clean up empty arrays |
if (0 == count($this->_expected_errors[$key])) { |
unset($this->_expected_errors[$key]); |
} |
} |
return $deleted; |
} |
// }}} |
// {{{ delExpect() |
/** |
* This method deletes all occurences of the specified element from |
* the expected error codes stack. |
* |
* @param mixed $error_code error code that should be deleted |
* @return mixed list of error codes that were deleted or error |
* @access public |
* @since PHP 4.3.0 |
*/ |
function delExpect($error_code) |
{ |
$deleted = false; |
if ((is_array($error_code) && (0 != count($error_code)))) { |
// $error_code is a non-empty array here; |
// we walk through it trying to unset all |
// values |
foreach($error_code as $key => $error) { |
if ($this->_checkDelExpect($error)) { |
$deleted = true; |
} else { |
$deleted = false; |
} |
} |
return $deleted ? true : PEAR::raiseError("The expected error you submitted does not exist"); // IMPROVE ME |
} elseif (!empty($error_code)) { |
// $error_code comes alone, trying to unset it |
if ($this->_checkDelExpect($error_code)) { |
return true; |
} else { |
return PEAR::raiseError("The expected error you submitted does not exist"); // IMPROVE ME |
} |
} else { |
// $error_code is empty |
return PEAR::raiseError("The expected error you submitted is empty"); // IMPROVE ME |
} |
} |
// }}} |
// {{{ raiseError() |
/** |
* This method is a wrapper that returns an instance of the |
* configured error class with this object's default error |
* handling applied. If the $mode and $options parameters are not |
* specified, the object's defaults are used. |
* |
* @param mixed $message a text error message or a PEAR error object |
* |
* @param int $code a numeric error code (it is up to your class |
* to define these if you want to use codes) |
* |
* @param int $mode One of PEAR_ERROR_RETURN, PEAR_ERROR_PRINT, |
* PEAR_ERROR_TRIGGER, PEAR_ERROR_DIE, |
* PEAR_ERROR_CALLBACK, PEAR_ERROR_EXCEPTION. |
* |
* @param mixed $options If $mode is PEAR_ERROR_TRIGGER, this parameter |
* specifies the PHP-internal error level (one of |
* E_USER_NOTICE, E_USER_WARNING or E_USER_ERROR). |
* If $mode is PEAR_ERROR_CALLBACK, this |
* parameter specifies the callback function or |
* method. In other error modes this parameter |
* is ignored. |
* |
* @param string $userinfo If you need to pass along for example debug |
* information, this parameter is meant for that. |
* |
* @param string $error_class The returned error object will be |
* instantiated from this class, if specified. |
* |
* @param bool $skipmsg If true, raiseError will only pass error codes, |
* the error message parameter will be dropped. |
* |
* @access public |
* @return object a PEAR error object |
* @see PEAR::setErrorHandling |
* @since PHP 4.0.5 |
*/ |
function raiseError($message = null, |
$code = null, |
$mode = null, |
$options = null, |
$userinfo = null, |
$error_class = null, |
$skipmsg = false) |
{ |
// The error is yet a PEAR error object |
if (is_object($message)) { |
$code = $message->getCode(); |
$userinfo = $message->getUserInfo(); |
$error_class = $message->getType(); |
$message->error_message_prefix = ''; |
$message = $message->getMessage(); |
} |
if (isset($this) && isset($this->_expected_errors) && sizeof($this->_expected_errors) > 0 && sizeof($exp = end($this->_expected_errors))) { |
if ($exp[0] == "*" || |
(is_int(reset($exp)) && in_array($code, $exp)) || |
(is_string(reset($exp)) && in_array($message, $exp))) { |
$mode = PEAR_ERROR_RETURN; |
} |
} |
// No mode given, try global ones |
if ($mode === null) { |
// Class error handler |
if (isset($this) && isset($this->_default_error_mode)) { |
$mode = $this->_default_error_mode; |
$options = $this->_default_error_options; |
// Global error handler |
} elseif (isset($GLOBALS['_PEAR_default_error_mode'])) { |
$mode = $GLOBALS['_PEAR_default_error_mode']; |
$options = $GLOBALS['_PEAR_default_error_options']; |
} |
} |
if ($error_class !== null) { |
$ec = $error_class; |
} elseif (isset($this) && isset($this->_error_class)) { |
$ec = $this->_error_class; |
} else { |
$ec = 'PEAR_Error'; |
} |
if ($skipmsg) { |
return new $ec($code, $mode, $options, $userinfo); |
} else { |
return new $ec($message, $code, $mode, $options, $userinfo); |
} |
} |
// }}} |
// {{{ throwError() |
/** |
* Simpler form of raiseError with fewer options. In most cases |
* message, code and userinfo are enough. |
* |
* @param string $message |
* |
*/ |
function throwError($message = null, |
$code = null, |
$userinfo = null) |
{ |
if (isset($this) && is_subclass_of($this, 'PEAR_Error')) { |
return $this->raiseError($message, $code, null, null, $userinfo); |
} else { |
return PEAR::raiseError($message, $code, null, null, $userinfo); |
} |
} |
// }}} |
// {{{ pushErrorHandling() |
/** |
* Push a new error handler on top of the error handler options stack. With this |
* you can easily override the actual error handler for some code and restore |
* it later with popErrorHandling. |
* |
* @param mixed $mode (same as setErrorHandling) |
* @param mixed $options (same as setErrorHandling) |
* |
* @return bool Always true |
* |
* @see PEAR::setErrorHandling |
*/ |
function pushErrorHandling($mode, $options = null) |
{ |
$stack = &$GLOBALS['_PEAR_error_handler_stack']; |
if (isset($this) && is_a($this, 'PEAR')) { |
$def_mode = &$this->_default_error_mode; |
$def_options = &$this->_default_error_options; |
} else { |
$def_mode = &$GLOBALS['_PEAR_default_error_mode']; |
$def_options = &$GLOBALS['_PEAR_default_error_options']; |
} |
$stack[] = array($def_mode, $def_options); |
if (isset($this) && is_a($this, 'PEAR')) { |
$this->setErrorHandling($mode, $options); |
} else { |
PEAR::setErrorHandling($mode, $options); |
} |
$stack[] = array($mode, $options); |
return true; |
} |
// }}} |
// {{{ popErrorHandling() |
/** |
* Pop the last error handler used |
* |
* @return bool Always true |
* |
* @see PEAR::pushErrorHandling |
*/ |
function popErrorHandling() |
{ |
$stack = &$GLOBALS['_PEAR_error_handler_stack']; |
array_pop($stack); |
list($mode, $options) = $stack[sizeof($stack) - 1]; |
array_pop($stack); |
if (isset($this) && is_a($this, 'PEAR')) { |
$this->setErrorHandling($mode, $options); |
} else { |
PEAR::setErrorHandling($mode, $options); |
} |
return true; |
} |
// }}} |
// {{{ loadExtension() |
/** |
* OS independant PHP extension load. Remember to take care |
* on the correct extension name for case sensitive OSes. |
* |
* @param string $ext The extension name |
* @return bool Success or not on the dl() call |
*/ |
function loadExtension($ext) |
{ |
if (!extension_loaded($ext)) { |
// if either returns true dl() will produce a FATAL error, stop that |
if ((ini_get('enable_dl') != 1) || (ini_get('safe_mode') == 1)) { |
return false; |
} |
if (OS_WINDOWS) { |
$suffix = '.dll'; |
} elseif (PHP_OS == 'HP-UX') { |
$suffix = '.sl'; |
} elseif (PHP_OS == 'AIX') { |
$suffix = '.a'; |
} elseif (PHP_OS == 'OSX') { |
$suffix = '.bundle'; |
} else { |
$suffix = '.so'; |
} |
return @dl('php_'.$ext.$suffix) || @dl($ext.$suffix); |
} |
return true; |
} |
// }}} |
} |
// {{{ _PEAR_call_destructors() |
function _PEAR_call_destructors() |
{ |
global $_PEAR_destructor_object_list; |
if (is_array($_PEAR_destructor_object_list) && |
sizeof($_PEAR_destructor_object_list)) |
{ |
reset($_PEAR_destructor_object_list); |
while (list($k, $objref) = each($_PEAR_destructor_object_list)) { |
$classname = get_class($objref); |
while ($classname) { |
$destructor = "_$classname"; |
if (method_exists($objref, $destructor)) { |
$objref->$destructor(); |
break; |
} else { |
$classname = get_parent_class($classname); |
} |
} |
} |
// Empty the object list to ensure that destructors are |
// not called more than once. |
$_PEAR_destructor_object_list = array(); |
} |
// Now call the shutdown functions |
if (is_array($GLOBALS['_PEAR_shutdown_funcs']) AND !empty($GLOBALS['_PEAR_shutdown_funcs'])) { |
foreach ($GLOBALS['_PEAR_shutdown_funcs'] as $value) { |
call_user_func_array($value[0], $value[1]); |
} |
} |
} |
// }}} |
class PEAR_Error |
{ |
// {{{ properties |
var $error_message_prefix = ''; |
var $mode = PEAR_ERROR_RETURN; |
var $level = E_USER_NOTICE; |
var $code = -1; |
var $message = ''; |
var $userinfo = ''; |
var $backtrace = null; |
// }}} |
// {{{ constructor |
/** |
* PEAR_Error constructor |
* |
* @param string $message message |
* |
* @param int $code (optional) error code |
* |
* @param int $mode (optional) error mode, one of: PEAR_ERROR_RETURN, |
* PEAR_ERROR_PRINT, PEAR_ERROR_DIE, PEAR_ERROR_TRIGGER, |
* PEAR_ERROR_CALLBACK or PEAR_ERROR_EXCEPTION |
* |
* @param mixed $options (optional) error level, _OR_ in the case of |
* PEAR_ERROR_CALLBACK, the callback function or object/method |
* tuple. |
* |
* @param string $userinfo (optional) additional user/debug info |
* |
* @access public |
* |
*/ |
function PEAR_Error($message = 'unknown error', $code = null, |
$mode = null, $options = null, $userinfo = null) |
{ |
if ($mode === null) { |
$mode = PEAR_ERROR_RETURN; |
} |
$this->message = $message; |
$this->code = $code; |
$this->mode = $mode; |
$this->userinfo = $userinfo; |
if (function_exists("debug_backtrace")) { |
$this->backtrace = debug_backtrace(); |
} |
if ($mode & PEAR_ERROR_CALLBACK) { |
$this->level = E_USER_NOTICE; |
$this->callback = $options; |
} else { |
if ($options === null) { |
$options = E_USER_NOTICE; |
} |
$this->level = $options; |
$this->callback = null; |
} |
if ($this->mode & PEAR_ERROR_PRINT) { |
if (is_null($options) || is_int($options)) { |
$format = "%s"; |
} else { |
$format = $options; |
} |
printf($format, $this->getMessage()); |
} |
if ($this->mode & PEAR_ERROR_TRIGGER) { |
trigger_error($this->getMessage(), $this->level); |
} |
if ($this->mode & PEAR_ERROR_DIE) { |
$msg = $this->getMessage(); |
if (is_null($options) || is_int($options)) { |
$format = "%s"; |
if (substr($msg, -1) != "\n") { |
$msg .= "\n"; |
} |
} else { |
$format = $options; |
} |
die(sprintf($format, $msg)); |
} |
if ($this->mode & PEAR_ERROR_CALLBACK) { |
if (is_callable($this->callback)) { |
call_user_func($this->callback, $this); |
} |
} |
if (PEAR_ZE2 && $this->mode & PEAR_ERROR_EXCEPTION) { |
eval('throw $this;'); |
} |
} |
// }}} |
// {{{ getMode() |
/** |
* Get the error mode from an error object. |
* |
* @return int error mode |
* @access public |
*/ |
function getMode() { |
return $this->mode; |
} |
// }}} |
// {{{ getCallback() |
/** |
* Get the callback function/method from an error object. |
* |
* @return mixed callback function or object/method array |
* @access public |
*/ |
function getCallback() { |
return $this->callback; |
} |
// }}} |
// {{{ getMessage() |
/** |
* Get the error message from an error object. |
* |
* @return string full error message |
* @access public |
*/ |
function getMessage() |
{ |
return ($this->error_message_prefix . $this->message); |
} |
// }}} |
// {{{ getCode() |
/** |
* Get error code from an error object |
* |
* @return int error code |
* @access public |
*/ |
function getCode() |
{ |
return $this->code; |
} |
// }}} |
// {{{ getType() |
/** |
* Get the name of this error/exception. |
* |
* @return string error/exception name (type) |
* @access public |
*/ |
function getType() |
{ |
return get_class($this); |
} |
// }}} |
// {{{ getUserInfo() |
/** |
* Get additional user-supplied information. |
* |
* @return string user-supplied information |
* @access public |
*/ |
function getUserInfo() |
{ |
return $this->userinfo; |
} |
// }}} |
// {{{ getDebugInfo() |
/** |
* Get additional debug information supplied by the application. |
* |
* @return string debug information |
* @access public |
*/ |
function getDebugInfo() |
{ |
return $this->getUserInfo(); |
} |
// }}} |
// {{{ getBacktrace() |
/** |
* Get the call backtrace from where the error was generated. |
* Supported with PHP 4.3.0 or newer. |
* |
* @param int $frame (optional) what frame to fetch |
* @return array Backtrace, or NULL if not available. |
* @access public |
*/ |
function getBacktrace($frame = null) |
{ |
if ($frame === null) { |
return $this->backtrace; |
} |
return $this->backtrace[$frame]; |
} |
// }}} |
// {{{ addUserInfo() |
function addUserInfo($info) |
{ |
if (empty($this->userinfo)) { |
$this->userinfo = $info; |
} else { |
$this->userinfo .= " ** $info"; |
} |
} |
// }}} |
// {{{ toString() |
/** |
* Make a string representation of this object. |
* |
* @return string a string with an object summary |
* @access public |
*/ |
function toString() { |
$modes = array(); |
$levels = array(E_USER_NOTICE => 'notice', |
E_USER_WARNING => 'warning', |
E_USER_ERROR => 'error'); |
if ($this->mode & PEAR_ERROR_CALLBACK) { |
if (is_array($this->callback)) { |
$callback = get_class($this->callback[0]) . '::' . |
$this->callback[1]; |
} else { |
$callback = $this->callback; |
} |
return sprintf('[%s: message="%s" code=%d mode=callback '. |
'callback=%s prefix="%s" info="%s"]', |
get_class($this), $this->message, $this->code, |
$callback, $this->error_message_prefix, |
$this->userinfo); |
} |
if ($this->mode & PEAR_ERROR_PRINT) { |
$modes[] = 'print'; |
} |
if ($this->mode & PEAR_ERROR_TRIGGER) { |
$modes[] = 'trigger'; |
} |
if ($this->mode & PEAR_ERROR_DIE) { |
$modes[] = 'die'; |
} |
if ($this->mode & PEAR_ERROR_RETURN) { |
$modes[] = 'return'; |
} |
return sprintf('[%s: message="%s" code=%d mode=%s level=%s '. |
'prefix="%s" info="%s"]', |
get_class($this), $this->message, $this->code, |
implode("|", $modes), $levels[$this->level], |
$this->error_message_prefix, |
$this->userinfo); |
} |
// }}} |
} |
register_shutdown_function("_PEAR_call_destructors"); |
/* |
* Local Variables: |
* mode: php |
* tab-width: 4 |
* c-basic-offset: 4 |
* End: |
*/ |
?> |
/trunk/jrest/lib/File/PDF/fonts/timesbi.php |
---|
New file |
0,0 → 1,272 |
<?php |
/** |
* @package File_PDF |
*/ |
$font_widths['timesBI'] = array( |
chr(0) => 250, |
chr(1) => 250, |
chr(2) => 250, |
chr(3) => 250, |
chr(4) => 250, |
chr(5) => 250, |
chr(6) => 250, |
chr(7) => 250, |
chr(8) => 250, |
chr(9) => 250, |
chr(10) => 250, |
chr(11) => 250, |
chr(12) => 250, |
chr(13) => 250, |
chr(14) => 250, |
chr(15) => 250, |
chr(16) => 250, |
chr(17) => 250, |
chr(18) => 250, |
chr(19) => 250, |
chr(20) => 250, |
chr(21) => 250, |
chr(22) => 250, |
chr(23) => 250, |
chr(24) => 250, |
chr(25) => 250, |
chr(26) => 250, |
chr(27) => 250, |
chr(28) => 250, |
chr(29) => 250, |
chr(30) => 250, |
chr(31) => 250, |
' ' => 250, |
'!' => 389, |
'"' => 555, |
'#' => 500, |
'$' => 500, |
'%' => 833, |
'&' => 778, |
'\'' => 278, |
'(' => 333, |
')' => 333, |
'*' => 500, |
'+' => 570, |
',' => 250, |
'-' => 333, |
'.' => 250, |
'/' => 278, |
'0' => 500, |
'1' => 500, |
'2' => 500, |
'3' => 500, |
'4' => 500, |
'5' => 500, |
'6' => 500, |
'7' => 500, |
'8' => 500, |
'9' => 500, |
':' => 333, |
';' => 333, |
'<' => 570, |
'=' => 570, |
'>' => 570, |
'?' => 500, |
'@' => 832, |
'A' => 667, |
'B' => 667, |
'C' => 667, |
'D' => 722, |
'E' => 667, |
'F' => 667, |
'G' => 722, |
'H' => 778, |
'I' => 389, |
'J' => 500, |
'K' => 667, |
'L' => 611, |
'M' => 889, |
'N' => 722, |
'O' => 722, |
'P' => 611, |
'Q' => 722, |
'R' => 667, |
'S' => 556, |
'T' => 611, |
'U' => 722, |
'V' => 667, |
'W' => 889, |
'X' => 667, |
'Y' => 611, |
'Z' => 611, |
'[' => 333, |
'\\' => 278, |
']' => 333, |
'^' => 570, |
'_' => 500, |
'`' => 333, |
'a' => 500, |
'b' => 500, |
'c' => 444, |
'd' => 500, |
'e' => 444, |
'f' => 333, |
'g' => 500, |
'h' => 556, |
'i' => 278, |
'j' => 278, |
'k' => 500, |
'l' => 278, |
'm' => 778, |
'n' => 556, |
'o' => 500, |
'p' => 500, |
'q' => 500, |
'r' => 389, |
's' => 389, |
't' => 278, |
'u' => 556, |
'v' => 444, |
'w' => 667, |
'x' => 500, |
'y' => 444, |
'z' => 389, |
'{' => 348, |
'|' => 220, |
'}' => 348, |
'~' => 570, |
chr(127) => 350, |
chr(128) => 500, |
chr(129) => 350, |
chr(130) => 333, |
chr(131) => 500, |
chr(132) => 500, |
chr(133) => 1000, |
chr(134) => 500, |
chr(135) => 500, |
chr(136) => 333, |
chr(137) => 1000, |
chr(138) => 556, |
chr(139) => 333, |
chr(140) => 944, |
chr(141) => 350, |
chr(142) => 611, |
chr(143) => 350, |
chr(144) => 350, |
chr(145) => 333, |
chr(146) => 333, |
chr(147) => 500, |
chr(148) => 500, |
chr(149) => 350, |
chr(150) => 500, |
chr(151) => 1000, |
chr(152) => 333, |
chr(153) => 1000, |
chr(154) => 389, |
chr(155) => 333, |
chr(156) => 722, |
chr(157) => 350, |
chr(158) => 389, |
chr(159) => 611, |
chr(160) => 250, |
chr(161) => 389, |
chr(162) => 500, |
chr(163) => 500, |
chr(164) => 500, |
chr(165) => 500, |
chr(166) => 220, |
chr(167) => 500, |
chr(168) => 333, |
chr(169) => 747, |
chr(170) => 266, |
chr(171) => 500, |
chr(172) => 606, |
chr(173) => 333, |
chr(174) => 747, |
chr(175) => 333, |
chr(176) => 400, |
chr(177) => 570, |
chr(178) => 300, |
chr(179) => 300, |
chr(180) => 333, |
chr(181) => 576, |
chr(182) => 500, |
chr(183) => 250, |
chr(184) => 333, |
chr(185) => 300, |
chr(186) => 300, |
chr(187) => 500, |
chr(188) => 750, |
chr(189) => 750, |
chr(190) => 750, |
chr(191) => 500, |
chr(192) => 667, |
chr(193) => 667, |
chr(194) => 667, |
chr(195) => 667, |
chr(196) => 667, |
chr(197) => 667, |
chr(198) => 944, |
chr(199) => 667, |
chr(200) => 667, |
chr(201) => 667, |
chr(202) => 667, |
chr(203) => 667, |
chr(204) => 389, |
chr(205) => 389, |
chr(206) => 389, |
chr(207) => 389, |
chr(208) => 722, |
chr(209) => 722, |
chr(210) => 722, |
chr(211) => 722, |
chr(212) => 722, |
chr(213) => 722, |
chr(214) => 722, |
chr(215) => 570, |
chr(216) => 722, |
chr(217) => 722, |
chr(218) => 722, |
chr(219) => 722, |
chr(220) => 722, |
chr(221) => 611, |
chr(222) => 611, |
chr(223) => 500, |
chr(224) => 500, |
chr(225) => 500, |
chr(226) => 500, |
chr(227) => 500, |
chr(228) => 500, |
chr(229) => 500, |
chr(230) => 722, |
chr(231) => 444, |
chr(232) => 444, |
chr(233) => 444, |
chr(234) => 444, |
chr(235) => 444, |
chr(236) => 278, |
chr(237) => 278, |
chr(238) => 278, |
chr(239) => 278, |
chr(240) => 500, |
chr(241) => 556, |
chr(242) => 500, |
chr(243) => 500, |
chr(244) => 500, |
chr(245) => 500, |
chr(246) => 500, |
chr(247) => 570, |
chr(248) => 500, |
chr(249) => 556, |
chr(250) => 556, |
chr(251) => 556, |
chr(252) => 556, |
chr(253) => 444, |
chr(254) => 500, |
chr(255) => 444); |
/trunk/jrest/lib/File/PDF/fonts/zapfdingbats.php |
---|
New file |
0,0 → 1,272 |
<?php |
/** |
* @package File_PDF |
*/ |
$font_widths['zapfdingbats'] = array( |
chr(0) => 0, |
chr(1) => 0, |
chr(2) => 0, |
chr(3) => 0, |
chr(4) => 0, |
chr(5) => 0, |
chr(6) => 0, |
chr(7) => 0, |
chr(8) => 0, |
chr(9) => 0, |
chr(10) => 0, |
chr(11) => 0, |
chr(12) => 0, |
chr(13) => 0, |
chr(14) => 0, |
chr(15) => 0, |
chr(16) => 0, |
chr(17) => 0, |
chr(18) => 0, |
chr(19) => 0, |
chr(20) => 0, |
chr(21) => 0, |
chr(22) => 0, |
chr(23) => 0, |
chr(24) => 0, |
chr(25) => 0, |
chr(26) => 0, |
chr(27) => 0, |
chr(28) => 0, |
chr(29) => 0, |
chr(30) => 0, |
chr(31) => 0, |
' ' => 278, |
'!' => 974, |
'"' => 961, |
'#' => 974, |
'$' => 980, |
'%' => 719, |
'&' => 789, |
'\'' => 790, |
'(' => 791, |
')' => 690, |
'*' => 960, |
'+' => 939, |
',' => 549, |
'-' => 855, |
'.' => 911, |
'/' => 933, |
'0' => 911, |
'1' => 945, |
'2' => 974, |
'3' => 755, |
'4' => 846, |
'5' => 762, |
'6' => 761, |
'7' => 571, |
'8' => 677, |
'9' => 763, |
':' => 760, |
';' => 759, |
'<' => 754, |
'=' => 494, |
'>' => 552, |
'?' => 537, |
'@' => 577, |
'A' => 692, |
'B' => 786, |
'C' => 788, |
'D' => 788, |
'E' => 790, |
'F' => 793, |
'G' => 794, |
'H' => 816, |
'I' => 823, |
'J' => 789, |
'K' => 841, |
'L' => 823, |
'M' => 833, |
'N' => 816, |
'O' => 831, |
'P' => 923, |
'Q' => 744, |
'R' => 723, |
'S' => 749, |
'T' => 790, |
'U' => 792, |
'V' => 695, |
'W' => 776, |
'X' => 768, |
'Y' => 792, |
'Z' => 759, |
'[' => 707, |
'\\' => 708, |
']' => 682, |
'^' => 701, |
'_' => 826, |
'`' => 815, |
'a' => 789, |
'b' => 789, |
'c' => 707, |
'd' => 687, |
'e' => 696, |
'f' => 689, |
'g' => 786, |
'h' => 787, |
'i' => 713, |
'j' => 791, |
'k' => 785, |
'l' => 791, |
'm' => 873, |
'n' => 761, |
'o' => 762, |
'p' => 762, |
'q' => 759, |
'r' => 759, |
's' => 892, |
't' => 892, |
'u' => 788, |
'v' => 784, |
'w' => 438, |
'x' => 138, |
'y' => 277, |
'z' => 415, |
'{' => 392, |
'|' => 392, |
'}' => 668, |
'~' => 668, |
chr(127) => 0, |
chr(128) => 390, |
chr(129) => 390, |
chr(130) => 317, |
chr(131) => 317, |
chr(132) => 276, |
chr(133) => 276, |
chr(134) => 509, |
chr(135) => 509, |
chr(136) => 410, |
chr(137) => 410, |
chr(138) => 234, |
chr(139) => 234, |
chr(140) => 334, |
chr(141) => 334, |
chr(142) => 0, |
chr(143) => 0, |
chr(144) => 0, |
chr(145) => 0, |
chr(146) => 0, |
chr(147) => 0, |
chr(148) => 0, |
chr(149) => 0, |
chr(150) => 0, |
chr(151) => 0, |
chr(152) => 0, |
chr(153) => 0, |
chr(154) => 0, |
chr(155) => 0, |
chr(156) => 0, |
chr(157) => 0, |
chr(158) => 0, |
chr(159) => 0, |
chr(160) => 0, |
chr(161) => 732, |
chr(162) => 544, |
chr(163) => 544, |
chr(164) => 910, |
chr(165) => 667, |
chr(166) => 760, |
chr(167) => 760, |
chr(168) => 776, |
chr(169) => 595, |
chr(170) => 694, |
chr(171) => 626, |
chr(172) => 788, |
chr(173) => 788, |
chr(174) => 788, |
chr(175) => 788, |
chr(176) => 788, |
chr(177) => 788, |
chr(178) => 788, |
chr(179) => 788, |
chr(180) => 788, |
chr(181) => 788, |
chr(182) => 788, |
chr(183) => 788, |
chr(184) => 788, |
chr(185) => 788, |
chr(186) => 788, |
chr(187) => 788, |
chr(188) => 788, |
chr(189) => 788, |
chr(190) => 788, |
chr(191) => 788, |
chr(192) => 788, |
chr(193) => 788, |
chr(194) => 788, |
chr(195) => 788, |
chr(196) => 788, |
chr(197) => 788, |
chr(198) => 788, |
chr(199) => 788, |
chr(200) => 788, |
chr(201) => 788, |
chr(202) => 788, |
chr(203) => 788, |
chr(204) => 788, |
chr(205) => 788, |
chr(206) => 788, |
chr(207) => 788, |
chr(208) => 788, |
chr(209) => 788, |
chr(210) => 788, |
chr(211) => 788, |
chr(212) => 894, |
chr(213) => 838, |
chr(214) => 1016, |
chr(215) => 458, |
chr(216) => 748, |
chr(217) => 924, |
chr(218) => 748, |
chr(219) => 918, |
chr(220) => 927, |
chr(221) => 928, |
chr(222) => 928, |
chr(223) => 834, |
chr(224) => 873, |
chr(225) => 828, |
chr(226) => 924, |
chr(227) => 924, |
chr(228) => 917, |
chr(229) => 930, |
chr(230) => 931, |
chr(231) => 463, |
chr(232) => 883, |
chr(233) => 836, |
chr(234) => 836, |
chr(235) => 867, |
chr(236) => 867, |
chr(237) => 696, |
chr(238) => 696, |
chr(239) => 874, |
chr(240) => 0, |
chr(241) => 874, |
chr(242) => 760, |
chr(243) => 946, |
chr(244) => 771, |
chr(245) => 865, |
chr(246) => 771, |
chr(247) => 888, |
chr(248) => 967, |
chr(249) => 888, |
chr(250) => 831, |
chr(251) => 873, |
chr(252) => 927, |
chr(253) => 970, |
chr(254) => 918, |
chr(255) => 0); |
/trunk/jrest/lib/File/PDF/fonts/helveticai.php |
---|
New file |
0,0 → 1,272 |
<?php |
/** |
* @package File_PDF |
*/ |
$font_widths['helveticaI'] = array( |
chr(0) => 278, |
chr(1) => 278, |
chr(2) => 278, |
chr(3) => 278, |
chr(4) => 278, |
chr(5) => 278, |
chr(6) => 278, |
chr(7) => 278, |
chr(8) => 278, |
chr(9) => 278, |
chr(10) => 278, |
chr(11) => 278, |
chr(12) => 278, |
chr(13) => 278, |
chr(14) => 278, |
chr(15) => 278, |
chr(16) => 278, |
chr(17) => 278, |
chr(18) => 278, |
chr(19) => 278, |
chr(20) => 278, |
chr(21) => 278, |
chr(22) => 278, |
chr(23) => 278, |
chr(24) => 278, |
chr(25) => 278, |
chr(26) => 278, |
chr(27) => 278, |
chr(28) => 278, |
chr(29) => 278, |
chr(30) => 278, |
chr(31) => 278, |
' ' => 278, |
'!' => 278, |
'"' => 355, |
'#' => 556, |
'$' => 556, |
'%' => 889, |
'&' => 667, |
'\'' => 191, |
'(' => 333, |
')' => 333, |
'*' => 389, |
'+' => 584, |
',' => 278, |
'-' => 333, |
'.' => 278, |
'/' => 278, |
'0' => 556, |
'1' => 556, |
'2' => 556, |
'3' => 556, |
'4' => 556, |
'5' => 556, |
'6' => 556, |
'7' => 556, |
'8' => 556, |
'9' => 556, |
':' => 278, |
';' => 278, |
'<' => 584, |
'=' => 584, |
'>' => 584, |
'?' => 556, |
'@' => 1015, |
'A' => 667, |
'B' => 667, |
'C' => 722, |
'D' => 722, |
'E' => 667, |
'F' => 611, |
'G' => 778, |
'H' => 722, |
'I' => 278, |
'J' => 500, |
'K' => 667, |
'L' => 556, |
'M' => 833, |
'N' => 722, |
'O' => 778, |
'P' => 667, |
'Q' => 778, |
'R' => 722, |
'S' => 667, |
'T' => 611, |
'U' => 722, |
'V' => 667, |
'W' => 944, |
'X' => 667, |
'Y' => 667, |
'Z' => 611, |
'[' => 278, |
'\\' => 278, |
']' => 278, |
'^' => 469, |
'_' => 556, |
'`' => 333, |
'a' => 556, |
'b' => 556, |
'c' => 500, |
'd' => 556, |
'e' => 556, |
'f' => 278, |
'g' => 556, |
'h' => 556, |
'i' => 222, |
'j' => 222, |
'k' => 500, |
'l' => 222, |
'm' => 833, |
'n' => 556, |
'o' => 556, |
'p' => 556, |
'q' => 556, |
'r' => 333, |
's' => 500, |
't' => 278, |
'u' => 556, |
'v' => 500, |
'w' => 722, |
'x' => 500, |
'y' => 500, |
'z' => 500, |
'{' => 334, |
'|' => 260, |
'}' => 334, |
'~' => 584, |
chr(127) => 350, |
chr(128) => 556, |
chr(129) => 350, |
chr(130) => 222, |
chr(131) => 556, |
chr(132) => 333, |
chr(133) => 1000, |
chr(134) => 556, |
chr(135) => 556, |
chr(136) => 333, |
chr(137) => 1000, |
chr(138) => 667, |
chr(139) => 333, |
chr(140) => 1000, |
chr(141) => 350, |
chr(142) => 611, |
chr(143) => 350, |
chr(144) => 350, |
chr(145) => 222, |
chr(146) => 222, |
chr(147) => 333, |
chr(148) => 333, |
chr(149) => 350, |
chr(150) => 556, |
chr(151) => 1000, |
chr(152) => 333, |
chr(153) => 1000, |
chr(154) => 500, |
chr(155) => 333, |
chr(156) => 944, |
chr(157) => 350, |
chr(158) => 500, |
chr(159) => 667, |
chr(160) => 278, |
chr(161) => 333, |
chr(162) => 556, |
chr(163) => 556, |
chr(164) => 556, |
chr(165) => 556, |
chr(166) => 260, |
chr(167) => 556, |
chr(168) => 333, |
chr(169) => 737, |
chr(170) => 370, |
chr(171) => 556, |
chr(172) => 584, |
chr(173) => 333, |
chr(174) => 737, |
chr(175) => 333, |
chr(176) => 400, |
chr(177) => 584, |
chr(178) => 333, |
chr(179) => 333, |
chr(180) => 333, |
chr(181) => 556, |
chr(182) => 537, |
chr(183) => 278, |
chr(184) => 333, |
chr(185) => 333, |
chr(186) => 365, |
chr(187) => 556, |
chr(188) => 834, |
chr(189) => 834, |
chr(190) => 834, |
chr(191) => 611, |
chr(192) => 667, |
chr(193) => 667, |
chr(194) => 667, |
chr(195) => 667, |
chr(196) => 667, |
chr(197) => 667, |
chr(198) => 1000, |
chr(199) => 722, |
chr(200) => 667, |
chr(201) => 667, |
chr(202) => 667, |
chr(203) => 667, |
chr(204) => 278, |
chr(205) => 278, |
chr(206) => 278, |
chr(207) => 278, |
chr(208) => 722, |
chr(209) => 722, |
chr(210) => 778, |
chr(211) => 778, |
chr(212) => 778, |
chr(213) => 778, |
chr(214) => 778, |
chr(215) => 584, |
chr(216) => 778, |
chr(217) => 722, |
chr(218) => 722, |
chr(219) => 722, |
chr(220) => 722, |
chr(221) => 667, |
chr(222) => 667, |
chr(223) => 611, |
chr(224) => 556, |
chr(225) => 556, |
chr(226) => 556, |
chr(227) => 556, |
chr(228) => 556, |
chr(229) => 556, |
chr(230) => 889, |
chr(231) => 500, |
chr(232) => 556, |
chr(233) => 556, |
chr(234) => 556, |
chr(235) => 556, |
chr(236) => 278, |
chr(237) => 278, |
chr(238) => 278, |
chr(239) => 278, |
chr(240) => 556, |
chr(241) => 556, |
chr(242) => 556, |
chr(243) => 556, |
chr(244) => 556, |
chr(245) => 556, |
chr(246) => 556, |
chr(247) => 584, |
chr(248) => 611, |
chr(249) => 556, |
chr(250) => 556, |
chr(251) => 556, |
chr(252) => 556, |
chr(253) => 500, |
chr(254) => 556, |
chr(255) => 500); |
/trunk/jrest/lib/File/PDF/fonts/helveticabi.php |
---|
New file |
0,0 → 1,272 |
<?php |
/** |
* @package File_PDF |
*/ |
$font_widths['helveticaBI'] = array( |
chr(0) => 278, |
chr(1) => 278, |
chr(2) => 278, |
chr(3) => 278, |
chr(4) => 278, |
chr(5) => 278, |
chr(6) => 278, |
chr(7) => 278, |
chr(8) => 278, |
chr(9) => 278, |
chr(10) => 278, |
chr(11) => 278, |
chr(12) => 278, |
chr(13) => 278, |
chr(14) => 278, |
chr(15) => 278, |
chr(16) => 278, |
chr(17) => 278, |
chr(18) => 278, |
chr(19) => 278, |
chr(20) => 278, |
chr(21) => 278, |
chr(22) => 278, |
chr(23) => 278, |
chr(24) => 278, |
chr(25) => 278, |
chr(26) => 278, |
chr(27) => 278, |
chr(28) => 278, |
chr(29) => 278, |
chr(30) => 278, |
chr(31) => 278, |
' ' => 278, |
'!' => 333, |
'"' => 474, |
'#' => 556, |
'$' => 556, |
'%' => 889, |
'&' => 722, |
'\'' => 238, |
'(' => 333, |
')' => 333, |
'*' => 389, |
'+' => 584, |
',' => 278, |
'-' => 333, |
'.' => 278, |
'/' => 278, |
'0' => 556, |
'1' => 556, |
'2' => 556, |
'3' => 556, |
'4' => 556, |
'5' => 556, |
'6' => 556, |
'7' => 556, |
'8' => 556, |
'9' => 556, |
':' => 333, |
';' => 333, |
'<' => 584, |
'=' => 584, |
'>' => 584, |
'?' => 611, |
'@' => 975, |
'A' => 722, |
'B' => 722, |
'C' => 722, |
'D' => 722, |
'E' => 667, |
'F' => 611, |
'G' => 778, |
'H' => 722, |
'I' => 278, |
'J' => 556, |
'K' => 722, |
'L' => 611, |
'M' => 833, |
'N' => 722, |
'O' => 778, |
'P' => 667, |
'Q' => 778, |
'R' => 722, |
'S' => 667, |
'T' => 611, |
'U' => 722, |
'V' => 667, |
'W' => 944, |
'X' => 667, |
'Y' => 667, |
'Z' => 611, |
'[' => 333, |
'\\' => 278, |
']' => 333, |
'^' => 584, |
'_' => 556, |
'`' => 333, |
'a' => 556, |
'b' => 611, |
'c' => 556, |
'd' => 611, |
'e' => 556, |
'f' => 333, |
'g' => 611, |
'h' => 611, |
'i' => 278, |
'j' => 278, |
'k' => 556, |
'l' => 278, |
'm' => 889, |
'n' => 611, |
'o' => 611, |
'p' => 611, |
'q' => 611, |
'r' => 389, |
's' => 556, |
't' => 333, |
'u' => 611, |
'v' => 556, |
'w' => 778, |
'x' => 556, |
'y' => 556, |
'z' => 500, |
'{' => 389, |
'|' => 280, |
'}' => 389, |
'~' => 584, |
chr(127) => 350, |
chr(128) => 556, |
chr(129) => 350, |
chr(130) => 278, |
chr(131) => 556, |
chr(132) => 500, |
chr(133) => 1000, |
chr(134) => 556, |
chr(135) => 556, |
chr(136) => 333, |
chr(137) => 1000, |
chr(138) => 667, |
chr(139) => 333, |
chr(140) => 1000, |
chr(141) => 350, |
chr(142) => 611, |
chr(143) => 350, |
chr(144) => 350, |
chr(145) => 278, |
chr(146) => 278, |
chr(147) => 500, |
chr(148) => 500, |
chr(149) => 350, |
chr(150) => 556, |
chr(151) => 1000, |
chr(152) => 333, |
chr(153) => 1000, |
chr(154) => 556, |
chr(155) => 333, |
chr(156) => 944, |
chr(157) => 350, |
chr(158) => 500, |
chr(159) => 667, |
chr(160) => 278, |
chr(161) => 333, |
chr(162) => 556, |
chr(163) => 556, |
chr(164) => 556, |
chr(165) => 556, |
chr(166) => 280, |
chr(167) => 556, |
chr(168) => 333, |
chr(169) => 737, |
chr(170) => 370, |
chr(171) => 556, |
chr(172) => 584, |
chr(173) => 333, |
chr(174) => 737, |
chr(175) => 333, |
chr(176) => 400, |
chr(177) => 584, |
chr(178) => 333, |
chr(179) => 333, |
chr(180) => 333, |
chr(181) => 611, |
chr(182) => 556, |
chr(183) => 278, |
chr(184) => 333, |
chr(185) => 333, |
chr(186) => 365, |
chr(187) => 556, |
chr(188) => 834, |
chr(189) => 834, |
chr(190) => 834, |
chr(191) => 611, |
chr(192) => 722, |
chr(193) => 722, |
chr(194) => 722, |
chr(195) => 722, |
chr(196) => 722, |
chr(197) => 722, |
chr(198) => 1000, |
chr(199) => 722, |
chr(200) => 667, |
chr(201) => 667, |
chr(202) => 667, |
chr(203) => 667, |
chr(204) => 278, |
chr(205) => 278, |
chr(206) => 278, |
chr(207) => 278, |
chr(208) => 722, |
chr(209) => 722, |
chr(210) => 778, |
chr(211) => 778, |
chr(212) => 778, |
chr(213) => 778, |
chr(214) => 778, |
chr(215) => 584, |
chr(216) => 778, |
chr(217) => 722, |
chr(218) => 722, |
chr(219) => 722, |
chr(220) => 722, |
chr(221) => 667, |
chr(222) => 667, |
chr(223) => 611, |
chr(224) => 556, |
chr(225) => 556, |
chr(226) => 556, |
chr(227) => 556, |
chr(228) => 556, |
chr(229) => 556, |
chr(230) => 889, |
chr(231) => 556, |
chr(232) => 556, |
chr(233) => 556, |
chr(234) => 556, |
chr(235) => 556, |
chr(236) => 278, |
chr(237) => 278, |
chr(238) => 278, |
chr(239) => 278, |
chr(240) => 611, |
chr(241) => 611, |
chr(242) => 611, |
chr(243) => 611, |
chr(244) => 611, |
chr(245) => 611, |
chr(246) => 611, |
chr(247) => 584, |
chr(248) => 611, |
chr(249) => 611, |
chr(250) => 611, |
chr(251) => 611, |
chr(252) => 611, |
chr(253) => 556, |
chr(254) => 611, |
chr(255) => 556); |
/trunk/jrest/lib/File/PDF/fonts/times.php |
---|
New file |
0,0 → 1,272 |
<?php |
/** |
* @package File_PDF |
*/ |
$font_widths['times'] = array( |
chr(0) => 250, |
chr(1) => 250, |
chr(2) => 250, |
chr(3) => 250, |
chr(4) => 250, |
chr(5) => 250, |
chr(6) => 250, |
chr(7) => 250, |
chr(8) => 250, |
chr(9) => 250, |
chr(10) => 250, |
chr(11) => 250, |
chr(12) => 250, |
chr(13) => 250, |
chr(14) => 250, |
chr(15) => 250, |
chr(16) => 250, |
chr(17) => 250, |
chr(18) => 250, |
chr(19) => 250, |
chr(20) => 250, |
chr(21) => 250, |
chr(22) => 250, |
chr(23) => 250, |
chr(24) => 250, |
chr(25) => 250, |
chr(26) => 250, |
chr(27) => 250, |
chr(28) => 250, |
chr(29) => 250, |
chr(30) => 250, |
chr(31) => 250, |
' ' => 250, |
'!' => 333, |
'"' => 408, |
'#' => 500, |
'$' => 500, |
'%' => 833, |
'&' => 778, |
'\'' => 180, |
'(' => 333, |
')' => 333, |
'*' => 500, |
'+' => 564, |
',' => 250, |
'-' => 333, |
'.' => 250, |
'/' => 278, |
'0' => 500, |
'1' => 500, |
'2' => 500, |
'3' => 500, |
'4' => 500, |
'5' => 500, |
'6' => 500, |
'7' => 500, |
'8' => 500, |
'9' => 500, |
':' => 278, |
';' => 278, |
'<' => 564, |
'=' => 564, |
'>' => 564, |
'?' => 444, |
'@' => 921, |
'A' => 722, |
'B' => 667, |
'C' => 667, |
'D' => 722, |
'E' => 611, |
'F' => 556, |
'G' => 722, |
'H' => 722, |
'I' => 333, |
'J' => 389, |
'K' => 722, |
'L' => 611, |
'M' => 889, |
'N' => 722, |
'O' => 722, |
'P' => 556, |
'Q' => 722, |
'R' => 667, |
'S' => 556, |
'T' => 611, |
'U' => 722, |
'V' => 722, |
'W' => 944, |
'X' => 722, |
'Y' => 722, |
'Z' => 611, |
'[' => 333, |
'\\' => 278, |
']' => 333, |
'^' => 469, |
'_' => 500, |
'`' => 333, |
'a' => 444, |
'b' => 500, |
'c' => 444, |
'd' => 500, |
'e' => 444, |
'f' => 333, |
'g' => 500, |
'h' => 500, |
'i' => 278, |
'j' => 278, |
'k' => 500, |
'l' => 278, |
'm' => 778, |
'n' => 500, |
'o' => 500, |
'p' => 500, |
'q' => 500, |
'r' => 333, |
's' => 389, |
't' => 278, |
'u' => 500, |
'v' => 500, |
'w' => 722, |
'x' => 500, |
'y' => 500, |
'z' => 444, |
'{' => 480, |
'|' => 200, |
'}' => 480, |
'~' => 541, |
chr(127) => 350, |
chr(128) => 500, |
chr(129) => 350, |
chr(130) => 333, |
chr(131) => 500, |
chr(132) => 444, |
chr(133) => 1000, |
chr(134) => 500, |
chr(135) => 500, |
chr(136) => 333, |
chr(137) => 1000, |
chr(138) => 556, |
chr(139) => 333, |
chr(140) => 889, |
chr(141) => 350, |
chr(142) => 611, |
chr(143) => 350, |
chr(144) => 350, |
chr(145) => 333, |
chr(146) => 333, |
chr(147) => 444, |
chr(148) => 444, |
chr(149) => 350, |
chr(150) => 500, |
chr(151) => 1000, |
chr(152) => 333, |
chr(153) => 980, |
chr(154) => 389, |
chr(155) => 333, |
chr(156) => 722, |
chr(157) => 350, |
chr(158) => 444, |
chr(159) => 722, |
chr(160) => 250, |
chr(161) => 333, |
chr(162) => 500, |
chr(163) => 500, |
chr(164) => 500, |
chr(165) => 500, |
chr(166) => 200, |
chr(167) => 500, |
chr(168) => 333, |
chr(169) => 760, |
chr(170) => 276, |
chr(171) => 500, |
chr(172) => 564, |
chr(173) => 333, |
chr(174) => 760, |
chr(175) => 333, |
chr(176) => 400, |
chr(177) => 564, |
chr(178) => 300, |
chr(179) => 300, |
chr(180) => 333, |
chr(181) => 500, |
chr(182) => 453, |
chr(183) => 250, |
chr(184) => 333, |
chr(185) => 300, |
chr(186) => 310, |
chr(187) => 500, |
chr(188) => 750, |
chr(189) => 750, |
chr(190) => 750, |
chr(191) => 444, |
chr(192) => 722, |
chr(193) => 722, |
chr(194) => 722, |
chr(195) => 722, |
chr(196) => 722, |
chr(197) => 722, |
chr(198) => 889, |
chr(199) => 667, |
chr(200) => 611, |
chr(201) => 611, |
chr(202) => 611, |
chr(203) => 611, |
chr(204) => 333, |
chr(205) => 333, |
chr(206) => 333, |
chr(207) => 333, |
chr(208) => 722, |
chr(209) => 722, |
chr(210) => 722, |
chr(211) => 722, |
chr(212) => 722, |
chr(213) => 722, |
chr(214) => 722, |
chr(215) => 564, |
chr(216) => 722, |
chr(217) => 722, |
chr(218) => 722, |
chr(219) => 722, |
chr(220) => 722, |
chr(221) => 722, |
chr(222) => 556, |
chr(223) => 500, |
chr(224) => 444, |
chr(225) => 444, |
chr(226) => 444, |
chr(227) => 444, |
chr(228) => 444, |
chr(229) => 444, |
chr(230) => 667, |
chr(231) => 444, |
chr(232) => 444, |
chr(233) => 444, |
chr(234) => 444, |
chr(235) => 444, |
chr(236) => 278, |
chr(237) => 278, |
chr(238) => 278, |
chr(239) => 278, |
chr(240) => 500, |
chr(241) => 500, |
chr(242) => 500, |
chr(243) => 500, |
chr(244) => 500, |
chr(245) => 500, |
chr(246) => 500, |
chr(247) => 564, |
chr(248) => 500, |
chr(249) => 500, |
chr(250) => 500, |
chr(251) => 500, |
chr(252) => 500, |
chr(253) => 500, |
chr(254) => 500, |
chr(255) => 500); |
/trunk/jrest/lib/File/PDF/fonts/timesb.php |
---|
New file |
0,0 → 1,272 |
<?php |
/** |
* @package File_PDF |
*/ |
$font_widths['timesB'] = array( |
chr(0) => 250, |
chr(1) => 250, |
chr(2) => 250, |
chr(3) => 250, |
chr(4) => 250, |
chr(5) => 250, |
chr(6) => 250, |
chr(7) => 250, |
chr(8) => 250, |
chr(9) => 250, |
chr(10) => 250, |
chr(11) => 250, |
chr(12) => 250, |
chr(13) => 250, |
chr(14) => 250, |
chr(15) => 250, |
chr(16) => 250, |
chr(17) => 250, |
chr(18) => 250, |
chr(19) => 250, |
chr(20) => 250, |
chr(21) => 250, |
chr(22) => 250, |
chr(23) => 250, |
chr(24) => 250, |
chr(25) => 250, |
chr(26) => 250, |
chr(27) => 250, |
chr(28) => 250, |
chr(29) => 250, |
chr(30) => 250, |
chr(31) => 250, |
' ' => 250, |
'!' => 333, |
'"' => 555, |
'#' => 500, |
'$' => 500, |
'%' => 1000, |
'&' => 833, |
'\'' => 278, |
'(' => 333, |
')' => 333, |
'*' => 500, |
'+' => 570, |
',' => 250, |
'-' => 333, |
'.' => 250, |
'/' => 278, |
'0' => 500, |
'1' => 500, |
'2' => 500, |
'3' => 500, |
'4' => 500, |
'5' => 500, |
'6' => 500, |
'7' => 500, |
'8' => 500, |
'9' => 500, |
':' => 333, |
';' => 333, |
'<' => 570, |
'=' => 570, |
'>' => 570, |
'?' => 500, |
'@' => 930, |
'A' => 722, |
'B' => 667, |
'C' => 722, |
'D' => 722, |
'E' => 667, |
'F' => 611, |
'G' => 778, |
'H' => 778, |
'I' => 389, |
'J' => 500, |
'K' => 778, |
'L' => 667, |
'M' => 944, |
'N' => 722, |
'O' => 778, |
'P' => 611, |
'Q' => 778, |
'R' => 722, |
'S' => 556, |
'T' => 667, |
'U' => 722, |
'V' => 722, |
'W' => 1000, |
'X' => 722, |
'Y' => 722, |
'Z' => 667, |
'[' => 333, |
'\\' => 278, |
']' => 333, |
'^' => 581, |
'_' => 500, |
'`' => 333, |
'a' => 500, |
'b' => 556, |
'c' => 444, |
'd' => 556, |
'e' => 444, |
'f' => 333, |
'g' => 500, |
'h' => 556, |
'i' => 278, |
'j' => 333, |
'k' => 556, |
'l' => 278, |
'm' => 833, |
'n' => 556, |
'o' => 500, |
'p' => 556, |
'q' => 556, |
'r' => 444, |
's' => 389, |
't' => 333, |
'u' => 556, |
'v' => 500, |
'w' => 722, |
'x' => 500, |
'y' => 500, |
'z' => 444, |
'{' => 394, |
'|' => 220, |
'}' => 394, |
'~' => 520, |
chr(127) => 350, |
chr(128) => 500, |
chr(129) => 350, |
chr(130) => 333, |
chr(131) => 500, |
chr(132) => 500, |
chr(133) => 1000, |
chr(134) => 500, |
chr(135) => 500, |
chr(136) => 333, |
chr(137) => 1000, |
chr(138) => 556, |
chr(139) => 333, |
chr(140) => 1000, |
chr(141) => 350, |
chr(142) => 667, |
chr(143) => 350, |
chr(144) => 350, |
chr(145) => 333, |
chr(146) => 333, |
chr(147) => 500, |
chr(148) => 500, |
chr(149) => 350, |
chr(150) => 500, |
chr(151) => 1000, |
chr(152) => 333, |
chr(153) => 1000, |
chr(154) => 389, |
chr(155) => 333, |
chr(156) => 722, |
chr(157) => 350, |
chr(158) => 444, |
chr(159) => 722, |
chr(160) => 250, |
chr(161) => 333, |
chr(162) => 500, |
chr(163) => 500, |
chr(164) => 500, |
chr(165) => 500, |
chr(166) => 220, |
chr(167) => 500, |
chr(168) => 333, |
chr(169) => 747, |
chr(170) => 300, |
chr(171) => 500, |
chr(172) => 570, |
chr(173) => 333, |
chr(174) => 747, |
chr(175) => 333, |
chr(176) => 400, |
chr(177) => 570, |
chr(178) => 300, |
chr(179) => 300, |
chr(180) => 333, |
chr(181) => 556, |
chr(182) => 540, |
chr(183) => 250, |
chr(184) => 333, |
chr(185) => 300, |
chr(186) => 330, |
chr(187) => 500, |
chr(188) => 750, |
chr(189) => 750, |
chr(190) => 750, |
chr(191) => 500, |
chr(192) => 722, |
chr(193) => 722, |
chr(194) => 722, |
chr(195) => 722, |
chr(196) => 722, |
chr(197) => 722, |
chr(198) => 1000, |
chr(199) => 722, |
chr(200) => 667, |
chr(201) => 667, |
chr(202) => 667, |
chr(203) => 667, |
chr(204) => 389, |
chr(205) => 389, |
chr(206) => 389, |
chr(207) => 389, |
chr(208) => 722, |
chr(209) => 722, |
chr(210) => 778, |
chr(211) => 778, |
chr(212) => 778, |
chr(213) => 778, |
chr(214) => 778, |
chr(215) => 570, |
chr(216) => 778, |
chr(217) => 722, |
chr(218) => 722, |
chr(219) => 722, |
chr(220) => 722, |
chr(221) => 722, |
chr(222) => 611, |
chr(223) => 556, |
chr(224) => 500, |
chr(225) => 500, |
chr(226) => 500, |
chr(227) => 500, |
chr(228) => 500, |
chr(229) => 500, |
chr(230) => 722, |
chr(231) => 444, |
chr(232) => 444, |
chr(233) => 444, |
chr(234) => 444, |
chr(235) => 444, |
chr(236) => 278, |
chr(237) => 278, |
chr(238) => 278, |
chr(239) => 278, |
chr(240) => 500, |
chr(241) => 556, |
chr(242) => 500, |
chr(243) => 500, |
chr(244) => 500, |
chr(245) => 500, |
chr(246) => 500, |
chr(247) => 570, |
chr(248) => 500, |
chr(249) => 556, |
chr(250) => 556, |
chr(251) => 556, |
chr(252) => 556, |
chr(253) => 500, |
chr(254) => 556, |
chr(255) => 500); |
/trunk/jrest/lib/File/PDF/fonts/helvetica.php |
---|
New file |
0,0 → 1,272 |
<?php |
/** |
* @package File_PDF |
*/ |
$font_widths['helvetica'] = array( |
chr(0) => 278, |
chr(1) => 278, |
chr(2) => 278, |
chr(3) => 278, |
chr(4) => 278, |
chr(5) => 278, |
chr(6) => 278, |
chr(7) => 278, |
chr(8) => 278, |
chr(9) => 278, |
chr(10) => 278, |
chr(11) => 278, |
chr(12) => 278, |
chr(13) => 278, |
chr(14) => 278, |
chr(15) => 278, |
chr(16) => 278, |
chr(17) => 278, |
chr(18) => 278, |
chr(19) => 278, |
chr(20) => 278, |
chr(21) => 278, |
chr(22) => 278, |
chr(23) => 278, |
chr(24) => 278, |
chr(25) => 278, |
chr(26) => 278, |
chr(27) => 278, |
chr(28) => 278, |
chr(29) => 278, |
chr(30) => 278, |
chr(31) => 278, |
' ' => 278, |
'!' => 278, |
'"' => 355, |
'#' => 556, |
'$' => 556, |
'%' => 889, |
'&' => 667, |
'\'' => 191, |
'(' => 333, |
')' => 333, |
'*' => 389, |
'+' => 584, |
',' => 278, |
'-' => 333, |
'.' => 278, |
'/' => 278, |
'0' => 556, |
'1' => 556, |
'2' => 556, |
'3' => 556, |
'4' => 556, |
'5' => 556, |
'6' => 556, |
'7' => 556, |
'8' => 556, |
'9' => 556, |
':' => 278, |
';' => 278, |
'<' => 584, |
'=' => 584, |
'>' => 584, |
'?' => 556, |
'@' => 1015, |
'A' => 667, |
'B' => 667, |
'C' => 722, |
'D' => 722, |
'E' => 667, |
'F' => 611, |
'G' => 778, |
'H' => 722, |
'I' => 278, |
'J' => 500, |
'K' => 667, |
'L' => 556, |
'M' => 833, |
'N' => 722, |
'O' => 778, |
'P' => 667, |
'Q' => 778, |
'R' => 722, |
'S' => 667, |
'T' => 611, |
'U' => 722, |
'V' => 667, |
'W' => 944, |
'X' => 667, |
'Y' => 667, |
'Z' => 611, |
'[' => 278, |
'\\' => 278, |
']' => 278, |
'^' => 469, |
'_' => 556, |
'`' => 333, |
'a' => 556, |
'b' => 556, |
'c' => 500, |
'd' => 556, |
'e' => 556, |
'f' => 278, |
'g' => 556, |
'h' => 556, |
'i' => 222, |
'j' => 222, |
'k' => 500, |
'l' => 222, |
'm' => 833, |
'n' => 556, |
'o' => 556, |
'p' => 556, |
'q' => 556, |
'r' => 333, |
's' => 500, |
't' => 278, |
'u' => 556, |
'v' => 500, |
'w' => 722, |
'x' => 500, |
'y' => 500, |
'z' => 500, |
'{' => 334, |
'|' => 260, |
'}' => 334, |
'~' => 584, |
chr(127) => 350, |
chr(128) => 556, |
chr(129) => 350, |
chr(130) => 222, |
chr(131) => 556, |
chr(132) => 333, |
chr(133) => 1000, |
chr(134) => 556, |
chr(135) => 556, |
chr(136) => 333, |
chr(137) => 1000, |
chr(138) => 667, |
chr(139) => 333, |
chr(140) => 1000, |
chr(141) => 350, |
chr(142) => 611, |
chr(143) => 350, |
chr(144) => 350, |
chr(145) => 222, |
chr(146) => 222, |
chr(147) => 333, |
chr(148) => 333, |
chr(149) => 350, |
chr(150) => 556, |
chr(151) => 1000, |
chr(152) => 333, |
chr(153) => 1000, |
chr(154) => 500, |
chr(155) => 333, |
chr(156) => 944, |
chr(157) => 350, |
chr(158) => 500, |
chr(159) => 667, |
chr(160) => 278, |
chr(161) => 333, |
chr(162) => 556, |
chr(163) => 556, |
chr(164) => 556, |
chr(165) => 556, |
chr(166) => 260, |
chr(167) => 556, |
chr(168) => 333, |
chr(169) => 737, |
chr(170) => 370, |
chr(171) => 556, |
chr(172) => 584, |
chr(173) => 333, |
chr(174) => 737, |
chr(175) => 333, |
chr(176) => 400, |
chr(177) => 584, |
chr(178) => 333, |
chr(179) => 333, |
chr(180) => 333, |
chr(181) => 556, |
chr(182) => 537, |
chr(183) => 278, |
chr(184) => 333, |
chr(185) => 333, |
chr(186) => 365, |
chr(187) => 556, |
chr(188) => 834, |
chr(189) => 834, |
chr(190) => 834, |
chr(191) => 611, |
chr(192) => 667, |
chr(193) => 667, |
chr(194) => 667, |
chr(195) => 667, |
chr(196) => 667, |
chr(197) => 667, |
chr(198) => 1000, |
chr(199) => 722, |
chr(200) => 667, |
chr(201) => 667, |
chr(202) => 667, |
chr(203) => 667, |
chr(204) => 278, |
chr(205) => 278, |
chr(206) => 278, |
chr(207) => 278, |
chr(208) => 722, |
chr(209) => 722, |
chr(210) => 778, |
chr(211) => 778, |
chr(212) => 778, |
chr(213) => 778, |
chr(214) => 778, |
chr(215) => 584, |
chr(216) => 778, |
chr(217) => 722, |
chr(218) => 722, |
chr(219) => 722, |
chr(220) => 722, |
chr(221) => 667, |
chr(222) => 667, |
chr(223) => 611, |
chr(224) => 556, |
chr(225) => 556, |
chr(226) => 556, |
chr(227) => 556, |
chr(228) => 556, |
chr(229) => 556, |
chr(230) => 889, |
chr(231) => 500, |
chr(232) => 556, |
chr(233) => 556, |
chr(234) => 556, |
chr(235) => 556, |
chr(236) => 278, |
chr(237) => 278, |
chr(238) => 278, |
chr(239) => 278, |
chr(240) => 556, |
chr(241) => 556, |
chr(242) => 556, |
chr(243) => 556, |
chr(244) => 556, |
chr(245) => 556, |
chr(246) => 556, |
chr(247) => 584, |
chr(248) => 611, |
chr(249) => 556, |
chr(250) => 556, |
chr(251) => 556, |
chr(252) => 556, |
chr(253) => 500, |
chr(254) => 556, |
chr(255) => 500); |
/trunk/jrest/lib/File/PDF/fonts/symbol.php |
---|
New file |
0,0 → 1,272 |
<?php |
/** |
* @package File_PDF |
*/ |
$font_widths['symbol'] = array( |
chr(0) => 250, |
chr(1) => 250, |
chr(2) => 250, |
chr(3) => 250, |
chr(4) => 250, |
chr(5) => 250, |
chr(6) => 250, |
chr(7) => 250, |
chr(8) => 250, |
chr(9) => 250, |
chr(10) => 250, |
chr(11) => 250, |
chr(12) => 250, |
chr(13) => 250, |
chr(14) => 250, |
chr(15) => 250, |
chr(16) => 250, |
chr(17) => 250, |
chr(18) => 250, |
chr(19) => 250, |
chr(20) => 250, |
chr(21) => 250, |
chr(22) => 250, |
chr(23) => 250, |
chr(24) => 250, |
chr(25) => 250, |
chr(26) => 250, |
chr(27) => 250, |
chr(28) => 250, |
chr(29) => 250, |
chr(30) => 250, |
chr(31) => 250, |
' ' => 250, |
'!' => 333, |
'"' => 713, |
'#' => 500, |
'$' => 549, |
'%' => 833, |
'&' => 778, |
'\'' => 439, |
'(' => 333, |
')' => 333, |
'*' => 500, |
'+' => 549, |
',' => 250, |
'-' => 549, |
'.' => 250, |
'/' => 278, |
'0' => 500, |
'1' => 500, |
'2' => 500, |
'3' => 500, |
'4' => 500, |
'5' => 500, |
'6' => 500, |
'7' => 500, |
'8' => 500, |
'9' => 500, |
':' => 278, |
';' => 278, |
'<' => 549, |
'=' => 549, |
'>' => 549, |
'?' => 444, |
'@' => 549, |
'A' => 722, |
'B' => 667, |
'C' => 722, |
'D' => 612, |
'E' => 611, |
'F' => 763, |
'G' => 603, |
'H' => 722, |
'I' => 333, |
'J' => 631, |
'K' => 722, |
'L' => 686, |
'M' => 889, |
'N' => 722, |
'O' => 722, |
'P' => 768, |
'Q' => 741, |
'R' => 556, |
'S' => 592, |
'T' => 611, |
'U' => 690, |
'V' => 439, |
'W' => 768, |
'X' => 645, |
'Y' => 795, |
'Z' => 611, |
'[' => 333, |
'\\' => 863, |
']' => 333, |
'^' => 658, |
'_' => 500, |
'`' => 500, |
'a' => 631, |
'b' => 549, |
'c' => 549, |
'd' => 494, |
'e' => 439, |
'f' => 521, |
'g' => 411, |
'h' => 603, |
'i' => 329, |
'j' => 603, |
'k' => 549, |
'l' => 549, |
'm' => 576, |
'n' => 521, |
'o' => 549, |
'p' => 549, |
'q' => 521, |
'r' => 549, |
's' => 603, |
't' => 439, |
'u' => 576, |
'v' => 713, |
'w' => 686, |
'x' => 493, |
'y' => 686, |
'z' => 494, |
'{' => 480, |
'|' => 200, |
'}' => 480, |
'~' => 549, |
chr(127) => 0, |
chr(128) => 0, |
chr(129) => 0, |
chr(130) => 0, |
chr(131) => 0, |
chr(132) => 0, |
chr(133) => 0, |
chr(134) => 0, |
chr(135) => 0, |
chr(136) => 0, |
chr(137) => 0, |
chr(138) => 0, |
chr(139) => 0, |
chr(140) => 0, |
chr(141) => 0, |
chr(142) => 0, |
chr(143) => 0, |
chr(144) => 0, |
chr(145) => 0, |
chr(146) => 0, |
chr(147) => 0, |
chr(148) => 0, |
chr(149) => 0, |
chr(150) => 0, |
chr(151) => 0, |
chr(152) => 0, |
chr(153) => 0, |
chr(154) => 0, |
chr(155) => 0, |
chr(156) => 0, |
chr(157) => 0, |
chr(158) => 0, |
chr(159) => 0, |
chr(160) => 750, |
chr(161) => 620, |
chr(162) => 247, |
chr(163) => 549, |
chr(164) => 167, |
chr(165) => 713, |
chr(166) => 500, |
chr(167) => 753, |
chr(168) => 753, |
chr(169) => 753, |
chr(170) => 753, |
chr(171) => 1042, |
chr(172) => 987, |
chr(173) => 603, |
chr(174) => 987, |
chr(175) => 603, |
chr(176) => 400, |
chr(177) => 549, |
chr(178) => 411, |
chr(179) => 549, |
chr(180) => 549, |
chr(181) => 713, |
chr(182) => 494, |
chr(183) => 460, |
chr(184) => 549, |
chr(185) => 549, |
chr(186) => 549, |
chr(187) => 549, |
chr(188) => 1000, |
chr(189) => 603, |
chr(190) => 1000, |
chr(191) => 658, |
chr(192) => 823, |
chr(193) => 686, |
chr(194) => 795, |
chr(195) => 987, |
chr(196) => 768, |
chr(197) => 768, |
chr(198) => 823, |
chr(199) => 768, |
chr(200) => 768, |
chr(201) => 713, |
chr(202) => 713, |
chr(203) => 713, |
chr(204) => 713, |
chr(205) => 713, |
chr(206) => 713, |
chr(207) => 713, |
chr(208) => 768, |
chr(209) => 713, |
chr(210) => 790, |
chr(211) => 790, |
chr(212) => 890, |
chr(213) => 823, |
chr(214) => 549, |
chr(215) => 250, |
chr(216) => 713, |
chr(217) => 603, |
chr(218) => 603, |
chr(219) => 1042, |
chr(220) => 987, |
chr(221) => 603, |
chr(222) => 987, |
chr(223) => 603, |
chr(224) => 494, |
chr(225) => 329, |
chr(226) => 790, |
chr(227) => 790, |
chr(228) => 786, |
chr(229) => 713, |
chr(230) => 384, |
chr(231) => 384, |
chr(232) => 384, |
chr(233) => 384, |
chr(234) => 384, |
chr(235) => 384, |
chr(236) => 494, |
chr(237) => 494, |
chr(238) => 494, |
chr(239) => 494, |
chr(240) => 0, |
chr(241) => 329, |
chr(242) => 274, |
chr(243) => 686, |
chr(244) => 686, |
chr(245) => 686, |
chr(246) => 384, |
chr(247) => 384, |
chr(248) => 384, |
chr(249) => 384, |
chr(250) => 384, |
chr(251) => 384, |
chr(252) => 494, |
chr(253) => 494, |
chr(254) => 494, |
chr(255) => 0); |
/trunk/jrest/lib/File/PDF/fonts/helveticab.php |
---|
New file |
0,0 → 1,272 |
<?php |
/** |
* @package File_PDF |
*/ |
$font_widths['helveticaB'] = array( |
chr(0) => 278, |
chr(1) => 278, |
chr(2) => 278, |
chr(3) => 278, |
chr(4) => 278, |
chr(5) => 278, |
chr(6) => 278, |
chr(7) => 278, |
chr(8) => 278, |
chr(9) => 278, |
chr(10) => 278, |
chr(11) => 278, |
chr(12) => 278, |
chr(13) => 278, |
chr(14) => 278, |
chr(15) => 278, |
chr(16) => 278, |
chr(17) => 278, |
chr(18) => 278, |
chr(19) => 278, |
chr(20) => 278, |
chr(21) => 278, |
chr(22) => 278, |
chr(23) => 278, |
chr(24) => 278, |
chr(25) => 278, |
chr(26) => 278, |
chr(27) => 278, |
chr(28) => 278, |
chr(29) => 278, |
chr(30) => 278, |
chr(31) => 278, |
' ' => 278, |
'!' => 333, |
'"' => 474, |
'#' => 556, |
'$' => 556, |
'%' => 889, |
'&' => 722, |
'\'' => 238, |
'(' => 333, |
')' => 333, |
'*' => 389, |
'+' => 584, |
',' => 278, |
'-' => 333, |
'.' => 278, |
'/' => 278, |
'0' => 556, |
'1' => 556, |
'2' => 556, |
'3' => 556, |
'4' => 556, |
'5' => 556, |
'6' => 556, |
'7' => 556, |
'8' => 556, |
'9' => 556, |
':' => 333, |
';' => 333, |
'<' => 584, |
'=' => 584, |
'>' => 584, |
'?' => 611, |
'@' => 975, |
'A' => 722, |
'B' => 722, |
'C' => 722, |
'D' => 722, |
'E' => 667, |
'F' => 611, |
'G' => 778, |
'H' => 722, |
'I' => 278, |
'J' => 556, |
'K' => 722, |
'L' => 611, |
'M' => 833, |
'N' => 722, |
'O' => 778, |
'P' => 667, |
'Q' => 778, |
'R' => 722, |
'S' => 667, |
'T' => 611, |
'U' => 722, |
'V' => 667, |
'W' => 944, |
'X' => 667, |
'Y' => 667, |
'Z' => 611, |
'[' => 333, |
'\\' => 278, |
']' => 333, |
'^' => 584, |
'_' => 556, |
'`' => 333, |
'a' => 556, |
'b' => 611, |
'c' => 556, |
'd' => 611, |
'e' => 556, |
'f' => 333, |
'g' => 611, |
'h' => 611, |
'i' => 278, |
'j' => 278, |
'k' => 556, |
'l' => 278, |
'm' => 889, |
'n' => 611, |
'o' => 611, |
'p' => 611, |
'q' => 611, |
'r' => 389, |
's' => 556, |
't' => 333, |
'u' => 611, |
'v' => 556, |
'w' => 778, |
'x' => 556, |
'y' => 556, |
'z' => 500, |
'{' => 389, |
'|' => 280, |
'}' => 389, |
'~' => 584, |
chr(127) => 350, |
chr(128) => 556, |
chr(129) => 350, |
chr(130) => 278, |
chr(131) => 556, |
chr(132) => 500, |
chr(133) => 1000, |
chr(134) => 556, |
chr(135) => 556, |
chr(136) => 333, |
chr(137) => 1000, |
chr(138) => 667, |
chr(139) => 333, |
chr(140) => 1000, |
chr(141) => 350, |
chr(142) => 611, |
chr(143) => 350, |
chr(144) => 350, |
chr(145) => 278, |
chr(146) => 278, |
chr(147) => 500, |
chr(148) => 500, |
chr(149) => 350, |
chr(150) => 556, |
chr(151) => 1000, |
chr(152) => 333, |
chr(153) => 1000, |
chr(154) => 556, |
chr(155) => 333, |
chr(156) => 944, |
chr(157) => 350, |
chr(158) => 500, |
chr(159) => 667, |
chr(160) => 278, |
chr(161) => 333, |
chr(162) => 556, |
chr(163) => 556, |
chr(164) => 556, |
chr(165) => 556, |
chr(166) => 280, |
chr(167) => 556, |
chr(168) => 333, |
chr(169) => 737, |
chr(170) => 370, |
chr(171) => 556, |
chr(172) => 584, |
chr(173) => 333, |
chr(174) => 737, |
chr(175) => 333, |
chr(176) => 400, |
chr(177) => 584, |
chr(178) => 333, |
chr(179) => 333, |
chr(180) => 333, |
chr(181) => 611, |
chr(182) => 556, |
chr(183) => 278, |
chr(184) => 333, |
chr(185) => 333, |
chr(186) => 365, |
chr(187) => 556, |
chr(188) => 834, |
chr(189) => 834, |
chr(190) => 834, |
chr(191) => 611, |
chr(192) => 722, |
chr(193) => 722, |
chr(194) => 722, |
chr(195) => 722, |
chr(196) => 722, |
chr(197) => 722, |
chr(198) => 1000, |
chr(199) => 722, |
chr(200) => 667, |
chr(201) => 667, |
chr(202) => 667, |
chr(203) => 667, |
chr(204) => 278, |
chr(205) => 278, |
chr(206) => 278, |
chr(207) => 278, |
chr(208) => 722, |
chr(209) => 722, |
chr(210) => 778, |
chr(211) => 778, |
chr(212) => 778, |
chr(213) => 778, |
chr(214) => 778, |
chr(215) => 584, |
chr(216) => 778, |
chr(217) => 722, |
chr(218) => 722, |
chr(219) => 722, |
chr(220) => 722, |
chr(221) => 667, |
chr(222) => 667, |
chr(223) => 611, |
chr(224) => 556, |
chr(225) => 556, |
chr(226) => 556, |
chr(227) => 556, |
chr(228) => 556, |
chr(229) => 556, |
chr(230) => 889, |
chr(231) => 556, |
chr(232) => 556, |
chr(233) => 556, |
chr(234) => 556, |
chr(235) => 556, |
chr(236) => 278, |
chr(237) => 278, |
chr(238) => 278, |
chr(239) => 278, |
chr(240) => 611, |
chr(241) => 611, |
chr(242) => 611, |
chr(243) => 611, |
chr(244) => 611, |
chr(245) => 611, |
chr(246) => 611, |
chr(247) => 584, |
chr(248) => 611, |
chr(249) => 611, |
chr(250) => 611, |
chr(251) => 611, |
chr(252) => 611, |
chr(253) => 556, |
chr(254) => 611, |
chr(255) => 556); |
/trunk/jrest/lib/File/PDF/fonts/courier.php |
---|
New file |
0,0 → 1,10 |
<?php |
/** |
* @package File_PDF |
*/ |
for ($i = 0; $i <= 255; $i++) { |
$font_widths['courier'][chr($i)] = 600; |
} |
$font_widths['courierB'] = $font_widths['courier']; |
$font_widths['courierI'] = $font_widths['courier']; |
$font_widths['courierBI'] = $font_widths['courier']; |
/trunk/jrest/lib/File/PDF/fonts/timesi.php |
---|
New file |
0,0 → 1,272 |
<?php |
/** |
* @package File_PDF |
*/ |
$font_widths['timesI'] = array( |
chr(0) => 250, |
chr(1) => 250, |
chr(2) => 250, |
chr(3) => 250, |
chr(4) => 250, |
chr(5) => 250, |
chr(6) => 250, |
chr(7) => 250, |
chr(8) => 250, |
chr(9) => 250, |
chr(10) => 250, |
chr(11) => 250, |
chr(12) => 250, |
chr(13) => 250, |
chr(14) => 250, |
chr(15) => 250, |
chr(16) => 250, |
chr(17) => 250, |
chr(18) => 250, |
chr(19) => 250, |
chr(20) => 250, |
chr(21) => 250, |
chr(22) => 250, |
chr(23) => 250, |
chr(24) => 250, |
chr(25) => 250, |
chr(26) => 250, |
chr(27) => 250, |
chr(28) => 250, |
chr(29) => 250, |
chr(30) => 250, |
chr(31) => 250, |
' ' => 250, |
'!' => 333, |
'"' => 420, |
'#' => 500, |
'$' => 500, |
'%' => 833, |
'&' => 778, |
'\'' => 214, |
'(' => 333, |
')' => 333, |
'*' => 500, |
'+' => 675, |
',' => 250, |
'-' => 333, |
'.' => 250, |
'/' => 278, |
'0' => 500, |
'1' => 500, |
'2' => 500, |
'3' => 500, |
'4' => 500, |
'5' => 500, |
'6' => 500, |
'7' => 500, |
'8' => 500, |
'9' => 500, |
':' => 333, |
';' => 333, |
'<' => 675, |
'=' => 675, |
'>' => 675, |
'?' => 500, |
'@' => 920, |
'A' => 611, |
'B' => 611, |
'C' => 667, |
'D' => 722, |
'E' => 611, |
'F' => 611, |
'G' => 722, |
'H' => 722, |
'I' => 333, |
'J' => 444, |
'K' => 667, |
'L' => 556, |
'M' => 833, |
'N' => 667, |
'O' => 722, |
'P' => 611, |
'Q' => 722, |
'R' => 611, |
'S' => 500, |
'T' => 556, |
'U' => 722, |
'V' => 611, |
'W' => 833, |
'X' => 611, |
'Y' => 556, |
'Z' => 556, |
'[' => 389, |
'\\' => 278, |
']' => 389, |
'^' => 422, |
'_' => 500, |
'`' => 333, |
'a' => 500, |
'b' => 500, |
'c' => 444, |
'd' => 500, |
'e' => 444, |
'f' => 278, |
'g' => 500, |
'h' => 500, |
'i' => 278, |
'j' => 278, |
'k' => 444, |
'l' => 278, |
'm' => 722, |
'n' => 500, |
'o' => 500, |
'p' => 500, |
'q' => 500, |
'r' => 389, |
's' => 389, |
't' => 278, |
'u' => 500, |
'v' => 444, |
'w' => 667, |
'x' => 444, |
'y' => 444, |
'z' => 389, |
'{' => 400, |
'|' => 275, |
'}' => 400, |
'~' => 541, |
chr(127) => 350, |
chr(128) => 500, |
chr(129) => 350, |
chr(130) => 333, |
chr(131) => 500, |
chr(132) => 556, |
chr(133) => 889, |
chr(134) => 500, |
chr(135) => 500, |
chr(136) => 333, |
chr(137) => 1000, |
chr(138) => 500, |
chr(139) => 333, |
chr(140) => 944, |
chr(141) => 350, |
chr(142) => 556, |
chr(143) => 350, |
chr(144) => 350, |
chr(145) => 333, |
chr(146) => 333, |
chr(147) => 556, |
chr(148) => 556, |
chr(149) => 350, |
chr(150) => 500, |
chr(151) => 889, |
chr(152) => 333, |
chr(153) => 980, |
chr(154) => 389, |
chr(155) => 333, |
chr(156) => 667, |
chr(157) => 350, |
chr(158) => 389, |
chr(159) => 556, |
chr(160) => 250, |
chr(161) => 389, |
chr(162) => 500, |
chr(163) => 500, |
chr(164) => 500, |
chr(165) => 500, |
chr(166) => 275, |
chr(167) => 500, |
chr(168) => 333, |
chr(169) => 760, |
chr(170) => 276, |
chr(171) => 500, |
chr(172) => 675, |
chr(173) => 333, |
chr(174) => 760, |
chr(175) => 333, |
chr(176) => 400, |
chr(177) => 675, |
chr(178) => 300, |
chr(179) => 300, |
chr(180) => 333, |
chr(181) => 500, |
chr(182) => 523, |
chr(183) => 250, |
chr(184) => 333, |
chr(185) => 300, |
chr(186) => 310, |
chr(187) => 500, |
chr(188) => 750, |
chr(189) => 750, |
chr(190) => 750, |
chr(191) => 500, |
chr(192) => 611, |
chr(193) => 611, |
chr(194) => 611, |
chr(195) => 611, |
chr(196) => 611, |
chr(197) => 611, |
chr(198) => 889, |
chr(199) => 667, |
chr(200) => 611, |
chr(201) => 611, |
chr(202) => 611, |
chr(203) => 611, |
chr(204) => 333, |
chr(205) => 333, |
chr(206) => 333, |
chr(207) => 333, |
chr(208) => 722, |
chr(209) => 667, |
chr(210) => 722, |
chr(211) => 722, |
chr(212) => 722, |
chr(213) => 722, |
chr(214) => 722, |
chr(215) => 675, |
chr(216) => 722, |
chr(217) => 722, |
chr(218) => 722, |
chr(219) => 722, |
chr(220) => 722, |
chr(221) => 556, |
chr(222) => 611, |
chr(223) => 500, |
chr(224) => 500, |
chr(225) => 500, |
chr(226) => 500, |
chr(227) => 500, |
chr(228) => 500, |
chr(229) => 500, |
chr(230) => 667, |
chr(231) => 444, |
chr(232) => 444, |
chr(233) => 444, |
chr(234) => 444, |
chr(235) => 444, |
chr(236) => 278, |
chr(237) => 278, |
chr(238) => 278, |
chr(239) => 278, |
chr(240) => 500, |
chr(241) => 500, |
chr(242) => 500, |
chr(243) => 500, |
chr(244) => 500, |
chr(245) => 500, |
chr(246) => 500, |
chr(247) => 675, |
chr(248) => 500, |
chr(249) => 500, |
chr(250) => 500, |
chr(251) => 500, |
chr(252) => 500, |
chr(253) => 444, |
chr(254) => 500, |
chr(255) => 444); |
/trunk/jrest/lib/HTTP/Download.php |
---|
New file |
0,0 → 1,1034 |
<?php |
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */ |
/** |
* HTTP::Download |
* |
* PHP versions 4 and 5 |
* |
* @category HTTP |
* @package HTTP_Download |
* @author Michael Wallner <mike@php.net> |
* @copyright 2003-2005 Michael Wallner |
* @license BSD, revised |
* @version CVS: $Id$ |
* @link http://pear.php.net/package/HTTP_Download |
*/ |
// {{{ includes |
/** |
* Requires PEAR |
*/ |
require_once 'PEAR.php'; |
/** |
* Requires HTTP_Header |
*/ |
require_once 'HTTP/Header.php'; |
// }}} |
// {{{ constants |
/**#@+ Use with HTTP_Download::setContentDisposition() **/ |
/** |
* Send data as attachment |
*/ |
define('HTTP_DOWNLOAD_ATTACHMENT', 'attachment'); |
/** |
* Send data inline |
*/ |
define('HTTP_DOWNLOAD_INLINE', 'inline'); |
/**#@-**/ |
/**#@+ Use with HTTP_Download::sendArchive() **/ |
/** |
* Send as uncompressed tar archive |
*/ |
define('HTTP_DOWNLOAD_TAR', 'TAR'); |
/** |
* Send as gzipped tar archive |
*/ |
define('HTTP_DOWNLOAD_TGZ', 'TGZ'); |
/** |
* Send as bzip2 compressed tar archive |
*/ |
define('HTTP_DOWNLOAD_BZ2', 'BZ2'); |
/** |
* Send as zip archive |
*/ |
define('HTTP_DOWNLOAD_ZIP', 'ZIP'); |
/**#@-**/ |
/**#@+ |
* Error constants |
*/ |
define('HTTP_DOWNLOAD_E_HEADERS_SENT', -1); |
define('HTTP_DOWNLOAD_E_NO_EXT_ZLIB', -2); |
define('HTTP_DOWNLOAD_E_NO_EXT_MMAGIC', -3); |
define('HTTP_DOWNLOAD_E_INVALID_FILE', -4); |
define('HTTP_DOWNLOAD_E_INVALID_PARAM', -5); |
define('HTTP_DOWNLOAD_E_INVALID_RESOURCE', -6); |
define('HTTP_DOWNLOAD_E_INVALID_REQUEST', -7); |
define('HTTP_DOWNLOAD_E_INVALID_CONTENT_TYPE', -8); |
define('HTTP_DOWNLOAD_E_INVALID_ARCHIVE_TYPE', -9); |
/**#@-**/ |
// }}} |
/** |
* Send HTTP Downloads/Responses. |
* |
* With this package you can handle (hidden) downloads. |
* It supports partial downloads, resuming and sending |
* raw data ie. from database BLOBs. |
* |
* <i>ATTENTION:</i> |
* You shouldn't use this package together with ob_gzhandler or |
* zlib.output_compression enabled in your php.ini, especially |
* if you want to send already gzipped data! |
* |
* @access public |
* @version $Revision$ |
*/ |
class HTTP_Download |
{ |
// {{{ protected member variables |
/** |
* Path to file for download |
* |
* @see HTTP_Download::setFile() |
* @access protected |
* @var string |
*/ |
var $file = ''; |
/** |
* Data for download |
* |
* @see HTTP_Download::setData() |
* @access protected |
* @var string |
*/ |
var $data = null; |
/** |
* Resource handle for download |
* |
* @see HTTP_Download::setResource() |
* @access protected |
* @var int |
*/ |
var $handle = null; |
/** |
* Whether to gzip the download |
* |
* @access protected |
* @var bool |
*/ |
var $gzip = false; |
/** |
* Whether to allow caching of the download on the clients side |
* |
* @access protected |
* @var bool |
*/ |
var $cache = true; |
/** |
* Size of download |
* |
* @access protected |
* @var int |
*/ |
var $size = 0; |
/** |
* Last modified |
* |
* @access protected |
* @var int |
*/ |
var $lastModified = 0; |
/** |
* HTTP headers |
* |
* @access protected |
* @var array |
*/ |
var $headers = array( |
'Content-Type' => 'application/x-octetstream', |
'Pragma' => 'cache', |
'Cache-Control' => 'public, must-revalidate, max-age=0', |
'Accept-Ranges' => 'bytes', |
'X-Sent-By' => 'PEAR::HTTP::Download' |
); |
/** |
* HTTP_Header |
* |
* @access protected |
* @var object |
*/ |
var $HTTP = null; |
/** |
* ETag |
* |
* @access protected |
* @var string |
*/ |
var $etag = ''; |
/** |
* Buffer Size |
* |
* @access protected |
* @var int |
*/ |
var $bufferSize = 2097152; |
/** |
* Throttle Delay |
* |
* @access protected |
* @var float |
*/ |
var $throttleDelay = 0; |
/** |
* Sent Bytes |
* |
* @access public |
* @var int |
*/ |
var $sentBytes = 0; |
// }}} |
// {{{ constructor |
/** |
* Constructor |
* |
* Set supplied parameters. |
* |
* @access public |
* @param array $params associative array of parameters |
* |
* <b>one of:</b> |
* o 'file' => path to file for download |
* o 'data' => raw data for download |
* o 'resource' => resource handle for download |
* <br/> |
* <b>and any of:</b> |
* o 'cache' => whether to allow cs caching |
* o 'gzip' => whether to gzip the download |
* o 'lastmodified' => unix timestamp |
* o 'contenttype' => content type of download |
* o 'contentdisposition' => content disposition |
* o 'buffersize' => amount of bytes to buffer |
* o 'throttledelay' => amount of secs to sleep |
* o 'cachecontrol' => cache privacy and validity |
* |
* <br /> |
* 'Content-Disposition' is not HTTP compliant, but most browsers |
* follow this header, so it was borrowed from MIME standard. |
* |
* It looks like this: <br /> |
* "Content-Disposition: attachment; filename=example.tgz". |
* |
* @see HTTP_Download::setContentDisposition() |
*/ |
function HTTP_Download($params = array()) |
{ |
$this->HTTP = &new HTTP_Header; |
$this->setParams($params); |
} |
// }}} |
// {{{ public methods |
/** |
* Set parameters |
* |
* Set supplied parameters through its accessor methods. |
* |
* @access public |
* @return mixed Returns true on success or PEAR_Error on failure. |
* @param array $params associative array of parameters |
* |
* @see HTTP_Download::HTTP_Download() |
*/ |
function setParams($params) |
{ |
foreach((array) $params as $param => $value){ |
$method = 'set'. $param; |
if (!method_exists($this, $method)) { |
return PEAR::raiseError( |
"Method '$method' doesn't exist.", |
HTTP_DOWNLOAD_E_INVALID_PARAM |
); |
} |
$e = call_user_func_array(array(&$this, $method), (array) $value); |
if (PEAR::isError($e)) { |
return $e; |
} |
} |
return true; |
} |
/** |
* Set path to file for download |
* |
* The Last-Modified header will be set to files filemtime(), actually. |
* Returns PEAR_Error (HTTP_DOWNLOAD_E_INVALID_FILE) if file doesn't exist. |
* Sends HTTP 404 status if $send_404 is set to true. |
* |
* @access public |
* @return mixed Returns true on success or PEAR_Error on failure. |
* @param string $file path to file for download |
* @param bool $send_404 whether to send HTTP/404 if |
* the file wasn't found |
*/ |
function setFile($file, $send_404 = true) |
{ |
$file = realpath($file); |
if (!is_file($file)) { |
if ($send_404) { |
$this->HTTP->sendStatusCode(404); |
} |
return PEAR::raiseError( |
"File '$file' not found.", |
HTTP_DOWNLOAD_E_INVALID_FILE |
); |
} |
$this->setLastModified(filemtime($file)); |
$this->file = $file; |
$this->size = filesize($file); |
return true; |
} |
/** |
* Set data for download |
* |
* Set $data to null if you want to unset this. |
* |
* @access public |
* @return void |
* @param $data raw data to send |
*/ |
function setData($data = null) |
{ |
$this->data = $data; |
$this->size = strlen($data); |
} |
/** |
* Set resource for download |
* |
* The resource handle supplied will be closed after sending the download. |
* Returns a PEAR_Error (HTTP_DOWNLOAD_E_INVALID_RESOURCE) if $handle |
* is no valid resource. Set $handle to null if you want to unset this. |
* |
* @access public |
* @return mixed Returns true on success or PEAR_Error on failure. |
* @param int $handle resource handle |
*/ |
function setResource($handle = null) |
{ |
if (!isset($handle)) { |
$this->handle = null; |
$this->size = 0; |
return true; |
} |
if (is_resource($handle)) { |
$this->handle = $handle; |
$filestats = fstat($handle); |
$this->size = $filestats['size']; |
return true; |
} |
return PEAR::raiseError( |
"Handle '$handle' is no valid resource.", |
HTTP_DOWNLOAD_E_INVALID_RESOURCE |
); |
} |
/** |
* Whether to gzip the download |
* |
* Returns a PEAR_Error (HTTP_DOWNLOAD_E_NO_EXT_ZLIB) |
* if ext/zlib is not available/loadable. |
* |
* @access public |
* @return mixed Returns true on success or PEAR_Error on failure. |
* @param bool $gzip whether to gzip the download |
*/ |
function setGzip($gzip = false) |
{ |
if ($gzip && !PEAR::loadExtension('zlib')){ |
return PEAR::raiseError( |
'GZIP compression (ext/zlib) not available.', |
HTTP_DOWNLOAD_E_NO_EXT_ZLIB |
); |
} |
$this->gzip = (bool) $gzip; |
return true; |
} |
/** |
* Whether to allow caching |
* |
* If set to true (default) we'll send some headers that are commonly |
* used for caching purposes like ETag, Cache-Control and Last-Modified. |
* |
* If caching is disabled, we'll send the download no matter if it |
* would actually be cached at the client side. |
* |
* @access public |
* @return void |
* @param bool $cache whether to allow caching |
*/ |
function setCache($cache = true) |
{ |
$this->cache = (bool) $cache; |
} |
/** |
* Whether to allow proxies to cache |
* |
* If set to 'private' proxies shouldn't cache the response. |
* This setting defaults to 'public' and affects only cached responses. |
* |
* @access public |
* @return bool |
* @param string $cache private or public |
* @param int $maxage maximum age of the client cache entry |
*/ |
function setCacheControl($cache = 'public', $maxage = 0) |
{ |
switch ($cache = strToLower($cache)) |
{ |
case 'private': |
case 'public': |
$this->headers['Cache-Control'] = |
$cache .', must-revalidate, max-age='. abs($maxage); |
return true; |
break; |
} |
return false; |
} |
/** |
* Set ETag |
* |
* Sets a user-defined ETag for cache-validation. The ETag is usually |
* generated by HTTP_Download through its payload information. |
* |
* @access public |
* @return void |
* @param string $etag Entity tag used for strong cache validation. |
*/ |
function setETag($etag = null) |
{ |
$this->etag = (string) $etag; |
} |
/** |
* Set Size of Buffer |
* |
* The amount of bytes specified as buffer size is the maximum amount |
* of data read at once from resources or files. The default size is 2M |
* (2097152 bytes). Be aware that if you enable gzip compression and |
* you set a very low buffer size that the actual file size may grow |
* due to added gzip headers for each sent chunk of the specified size. |
* |
* Returns PEAR_Error (HTTP_DOWNLOAD_E_INVALID_PARAM) if $size is not |
* greater than 0 bytes. |
* |
* @access public |
* @return mixed Returns true on success or PEAR_Error on failure. |
* @param int $bytes Amount of bytes to use as buffer. |
*/ |
function setBufferSize($bytes = 2097152) |
{ |
if (0 >= $bytes) { |
return PEAR::raiseError( |
'Buffer size must be greater than 0 bytes ('. $bytes .' given)', |
HTTP_DOWNLOAD_E_INVALID_PARAM); |
} |
$this->bufferSize = abs($bytes); |
return true; |
} |
/** |
* Set Throttle Delay |
* |
* Set the amount of seconds to sleep after each chunck that has been |
* sent. One can implement some sort of throttle through adjusting the |
* buffer size and the throttle delay. With the following settings |
* HTTP_Download will sleep a second after each 25 K of data sent. |
* |
* <code> |
* Array( |
* 'throttledelay' => 1, |
* 'buffersize' => 1024 * 25, |
* ) |
* </code> |
* |
* Just be aware that if gzipp'ing is enabled, decreasing the chunk size |
* too much leads to proportionally increased network traffic due to added |
* gzip header and bottom bytes around each chunk. |
* |
* @access public |
* @return void |
* @param float $seconds Amount of seconds to sleep after each |
* chunk that has been sent. |
*/ |
function setThrottleDelay($seconds = 0) |
{ |
$this->throttleDelay = abs($seconds) * 1000; |
} |
/** |
* Set "Last-Modified" |
* |
* This is usually determined by filemtime() in HTTP_Download::setFile() |
* If you set raw data for download with HTTP_Download::setData() and you |
* want do send an appropiate "Last-Modified" header, you should call this |
* method. |
* |
* @access public |
* @return void |
* @param int unix timestamp |
*/ |
function setLastModified($last_modified) |
{ |
$this->lastModified = $this->headers['Last-Modified'] = (int) $last_modified; |
} |
/** |
* Set Content-Disposition header |
* |
* @see HTTP_Download::HTTP_Download |
* |
* @access public |
* @return void |
* @param string $disposition whether to send the download |
* inline or as attachment |
* @param string $file_name the filename to display in |
* the browser's download window |
* |
* <b>Example:</b> |
* <code> |
* $HTTP_Download->setContentDisposition( |
* HTTP_DOWNLOAD_ATTACHMENT, |
* 'download.tgz' |
* ); |
* </code> |
*/ |
function setContentDisposition( $disposition = HTTP_DOWNLOAD_ATTACHMENT, |
$file_name = null) |
{ |
$cd = $disposition; |
if (isset($file_name)) { |
$cd .= '; filename="' . $file_name . '"'; |
} elseif ($this->file) { |
$cd .= '; filename="' . basename($this->file) . '"'; |
} |
$this->headers['Content-Disposition'] = $cd; |
} |
/** |
* Set content type of the download |
* |
* Default content type of the download will be 'application/x-octetstream'. |
* Returns PEAR_Error (HTTP_DOWNLOAD_E_INVALID_CONTENT_TYPE) if |
* $content_type doesn't seem to be valid. |
* |
* @access public |
* @return mixed Returns true on success or PEAR_Error on failure. |
* @param string $content_type content type of file for download |
*/ |
function setContentType($content_type = 'application/x-octetstream') |
{ |
if (!preg_match('/^[a-z]+\w*\/[a-z]+[\w.;= -]*$/', $content_type)) { |
return PEAR::raiseError( |
"Invalid content type '$content_type' supplied.", |
HTTP_DOWNLOAD_E_INVALID_CONTENT_TYPE |
); |
} |
$this->headers['Content-Type'] = $content_type; |
return true; |
} |
/** |
* Guess content type of file |
* |
* First we try to use PEAR::MIME_Type, if installed, to detect the content |
* type, else we check if ext/mime_magic is loaded and properly configured. |
* |
* Returns PEAR_Error if: |
* o if PEAR::MIME_Type failed to detect a proper content type |
* (HTTP_DOWNLOAD_E_INVALID_CONTENT_TYPE) |
* o ext/magic.mime is not installed, or not properly configured |
* (HTTP_DOWNLOAD_E_NO_EXT_MMAGIC) |
* o mime_content_type() couldn't guess content type or returned |
* a content type considered to be bogus by setContentType() |
* (HTTP_DOWNLOAD_E_INVALID_CONTENT_TYPE) |
* |
* @access public |
* @return mixed Returns true on success or PEAR_Error on failure. |
*/ |
function guessContentType() |
{ |
if (class_exists('MIME_Type') || @include_once 'MIME/Type.php') { |
if (PEAR::isError($mime_type = MIME_Type::autoDetect($this->file))) { |
return PEAR::raiseError($mime_type->getMessage(), |
HTTP_DOWNLOAD_E_INVALID_CONTENT_TYPE); |
} |
return $this->setContentType($mime_type); |
} |
if (!function_exists('mime_content_type')) { |
return PEAR::raiseError( |
'This feature requires ext/mime_magic!', |
HTTP_DOWNLOAD_E_NO_EXT_MMAGIC |
); |
} |
if (!is_file(ini_get('mime_magic.magicfile'))) { |
return PEAR::raiseError( |
'ext/mime_magic is loaded but not properly configured!', |
HTTP_DOWNLOAD_E_NO_EXT_MMAGIC |
); |
} |
if (!$content_type = @mime_content_type($this->file)) { |
return PEAR::raiseError( |
'Couldn\'t guess content type with mime_content_type().', |
HTTP_DOWNLOAD_E_INVALID_CONTENT_TYPE |
); |
} |
return $this->setContentType($content_type); |
} |
/** |
* Send |
* |
* Returns PEAR_Error if: |
* o HTTP headers were already sent (HTTP_DOWNLOAD_E_HEADERS_SENT) |
* o HTTP Range was invalid (HTTP_DOWNLOAD_E_INVALID_REQUEST) |
* |
* @access public |
* @return mixed Returns true on success or PEAR_Error on failure. |
* @param bool $autoSetContentDisposition Whether to set the |
* Content-Disposition header if it isn't already. |
*/ |
function send($autoSetContentDisposition = true) |
{ |
if (headers_sent()) { |
return PEAR::raiseError( |
'Headers already sent.', |
HTTP_DOWNLOAD_E_HEADERS_SENT |
); |
} |
if (!ini_get('safe_mode')) { |
@set_time_limit(0); |
} |
if ($autoSetContentDisposition && |
!isset($this->headers['Content-Disposition'])) { |
$this->setContentDisposition(); |
} |
if ($this->cache) { |
$this->headers['ETag'] = $this->generateETag(); |
if ($this->isCached()) { |
$this->HTTP->sendStatusCode(304); |
$this->sendHeaders(); |
return true; |
} |
} else { |
unset($this->headers['Last-Modified']); |
} |
if (ob_get_level()) { |
while (@ob_end_clean()); |
} |
if ($this->gzip) { |
@ob_start('ob_gzhandler'); |
} else { |
ob_start(); |
} |
$this->sentBytes = 0; |
if ($this->isRangeRequest()) { |
$this->HTTP->sendStatusCode(206); |
$chunks = $this->getChunks(); |
} else { |
$this->HTTP->sendStatusCode(200); |
$chunks = array(array(0, $this->size)); |
if (!$this->gzip && count(ob_list_handlers()) < 2) { |
$this->headers['Content-Length'] = $this->size; |
} |
} |
if (PEAR::isError($e = $this->sendChunks($chunks))) { |
ob_end_clean(); |
$this->HTTP->sendStatusCode(416); |
return $e; |
} |
ob_end_flush(); |
flush(); |
return true; |
} |
/** |
* Static send |
* |
* @see HTTP_Download::HTTP_Download() |
* @see HTTP_Download::send() |
* |
* @static |
* @access public |
* @return mixed Returns true on success or PEAR_Error on failure. |
* @param array $params associative array of parameters |
* @param bool $guess whether HTTP_Download::guessContentType() |
* should be called |
*/ |
function staticSend($params, $guess = false) |
{ |
$d = &new HTTP_Download(); |
$e = $d->setParams($params); |
if (PEAR::isError($e)) { |
return $e; |
} |
if ($guess) { |
$e = $d->guessContentType(); |
if (PEAR::isError($e)) { |
return $e; |
} |
} |
return $d->send(); |
} |
/** |
* Send a bunch of files or directories as an archive |
* |
* Example: |
* <code> |
* require_once 'HTTP/Download.php'; |
* HTTP_Download::sendArchive( |
* 'myArchive.tgz', |
* '/var/ftp/pub/mike', |
* HTTP_DOWNLOAD_TGZ, |
* '', |
* '/var/ftp/pub' |
* ); |
* </code> |
* |
* @see Archive_Tar::createModify() |
* @deprecated use HTTP_Download_Archive::send() |
* @static |
* @access public |
* @return mixed Returns true on success or PEAR_Error on failure. |
* @param string $name name the sent archive should have |
* @param mixed $files files/directories |
* @param string $type archive type |
* @param string $add_path path that should be prepended to the files |
* @param string $strip_path path that should be stripped from the files |
*/ |
function sendArchive( $name, |
$files, |
$type = HTTP_DOWNLOAD_TGZ, |
$add_path = '', |
$strip_path = '') |
{ |
require_once 'HTTP/Download/Archive.php'; |
return HTTP_Download_Archive::send($name, $files, $type, |
$add_path, $strip_path); |
} |
// }}} |
// {{{ protected methods |
/** |
* Generate ETag |
* |
* @access protected |
* @return string |
*/ |
function generateETag() |
{ |
if (!$this->etag) { |
if ($this->data) { |
$md5 = md5($this->data); |
} else { |
$fst = is_resource($this->handle) ? |
fstat($this->handle) : stat($this->file); |
$md5 = md5($fst['mtime'] .'='. $fst['ino'] .'='. $fst['size']); |
} |
$this->etag = '"' . $md5 . '-' . crc32($md5) . '"'; |
} |
return $this->etag; |
} |
/** |
* Send multiple chunks |
* |
* @access protected |
* @return mixed Returns true on success or PEAR_Error on failure. |
* @param array $chunks |
*/ |
function sendChunks($chunks) |
{ |
if (count($chunks) == 1) { |
return $this->sendChunk(current($chunks)); |
} |
$bound = uniqid('HTTP_DOWNLOAD-', true); |
$cType = $this->headers['Content-Type']; |
$this->headers['Content-Type'] = |
'multipart/byteranges; boundary=' . $bound; |
$this->sendHeaders(); |
foreach ($chunks as $chunk){ |
if (PEAR::isError($e = $this->sendChunk($chunk, $cType, $bound))) { |
return $e; |
} |
} |
#echo "\r\n--$bound--\r\n"; |
return true; |
} |
/** |
* Send chunk of data |
* |
* @access protected |
* @return mixed Returns true on success or PEAR_Error on failure. |
* @param array $chunk start and end offset of the chunk to send |
* @param string $cType actual content type |
* @param string $bound boundary for multipart/byteranges |
*/ |
function sendChunk($chunk, $cType = null, $bound = null) |
{ |
list($offset, $lastbyte) = $chunk; |
$length = ($lastbyte - $offset) + 1; |
if ($length < 1) { |
return PEAR::raiseError( |
"Error processing range request: $offset-$lastbyte/$length", |
HTTP_DOWNLOAD_E_INVALID_REQUEST |
); |
} |
$range = $offset . '-' . $lastbyte . '/' . $this->size; |
if (isset($cType, $bound)) { |
echo "\r\n--$bound\r\n", |
"Content-Type: $cType\r\n", |
"Content-Range: bytes $range\r\n\r\n"; |
} else { |
if ($this->isRangeRequest()) { |
$this->headers['Content-Length'] = $length; |
$this->headers['Content-Range'] = 'bytes '. $range; |
} |
$this->sendHeaders(); |
} |
if ($this->data) { |
while (($length -= $this->bufferSize) > 0) { |
$this->flush(substr($this->data, $offset, $this->bufferSize)); |
$this->throttleDelay and $this->sleep(); |
$offset += $this->bufferSize; |
} |
if ($length) { |
$this->flush(substr($this->data, $offset, $this->bufferSize + $length)); |
} |
} else { |
if (!is_resource($this->handle)) { |
$this->handle = fopen($this->file, 'rb'); |
} |
fseek($this->handle, $offset); |
while (($length -= $this->bufferSize) > 0) { |
$this->flush(fread($this->handle, $this->bufferSize)); |
$this->throttleDelay and $this->sleep(); |
} |
if ($length) { |
$this->flush(fread($this->handle, $this->bufferSize + $length)); |
} |
} |
return true; |
} |
/** |
* Get chunks to send |
* |
* @access protected |
* @return array |
*/ |
function getChunks() |
{ |
$parts = array(); |
foreach (explode(',', $this->getRanges()) as $chunk){ |
list($o, $e) = explode('-', $chunk); |
if ($e >= $this->size || (empty($e) && $e !== 0 && $e !== '0')) { |
$e = $this->size - 1; |
} |
if (empty($o) && $o !== 0 && $o !== '0') { |
$o = $this->size - $e; |
$e = $this->size - 1; |
} |
$parts[] = array($o, $e); |
} |
return $parts; |
} |
/** |
* Check if range is requested |
* |
* @access protected |
* @return bool |
*/ |
function isRangeRequest() |
{ |
if (!isset($_SERVER['HTTP_RANGE'])) { |
return false; |
} |
return $this->isValidRange(); |
} |
/** |
* Get range request |
* |
* @access protected |
* @return array |
*/ |
function getRanges() |
{ |
return preg_match('/^bytes=((\d*-\d*,? ?)+)$/', |
@$_SERVER['HTTP_RANGE'], $matches) ? $matches[1] : array(); |
} |
/** |
* Check if entity is cached |
* |
* @access protected |
* @return bool |
*/ |
function isCached() |
{ |
return ( |
(isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) && |
$this->lastModified == strtotime(current($a = explode( |
';', $_SERVER['HTTP_IF_MODIFIED_SINCE'])))) || |
(isset($_SERVER['HTTP_IF_NONE_MATCH']) && |
$this->compareAsterisk('HTTP_IF_NONE_MATCH', $this->etag)) |
); |
} |
/** |
* Check if entity hasn't changed |
* |
* @access protected |
* @return bool |
*/ |
function isValidRange() |
{ |
if (isset($_SERVER['HTTP_IF_MATCH']) && |
!$this->compareAsterisk('HTTP_IF_MATCH', $this->etag)) { |
return false; |
} |
if (isset($_SERVER['HTTP_IF_RANGE']) && |
$_SERVER['HTTP_IF_RANGE'] !== $this->etag && |
strtotime($_SERVER['HTTP_IF_RANGE']) !== $this->lastModified) { |
return false; |
} |
if (isset($_SERVER['HTTP_IF_UNMODIFIED_SINCE'])) { |
$lm = current($a = explode(';', $_SERVER['HTTP_IF_UNMODIFIED_SINCE'])); |
if (strtotime($lm) !== $this->lastModified) { |
return false; |
} |
} |
if (isset($_SERVER['HTTP_UNLESS_MODIFIED_SINCE'])) { |
$lm = current($a = explode(';', $_SERVER['HTTP_UNLESS_MODIFIED_SINCE'])); |
if (strtotime($lm) !== $this->lastModified) { |
return false; |
} |
} |
return true; |
} |
/** |
* Compare against an asterisk or check for equality |
* |
* @access protected |
* @return bool |
* @param string key for the $_SERVER array |
* @param string string to compare |
*/ |
function compareAsterisk($svar, $compare) |
{ |
foreach (array_map('trim', explode(',', $_SERVER[$svar])) as $request) { |
if ($request === '*' || $request === $compare) { |
return true; |
} |
} |
return false; |
} |
/** |
* Send HTTP headers |
* |
* @access protected |
* @return void |
*/ |
function sendHeaders() |
{ |
foreach ($this->headers as $header => $value) { |
$this->HTTP->setHeader($header, $value); |
} |
$this->HTTP->sendHeaders(); |
/* NSAPI won't output anything if we did this */ |
if (strncasecmp(PHP_SAPI, 'nsapi', 5)) { |
ob_flush(); |
flush(); |
} |
} |
/** |
* Flush |
* |
* @access protected |
* @return void |
* @param string $data |
*/ |
function flush($data = '') |
{ |
if ($dlen = strlen($data)) { |
$this->sentBytes += $dlen; |
echo $data; |
} |
ob_flush(); |
flush(); |
} |
/** |
* Sleep |
* |
* @access protected |
* @return void |
*/ |
function sleep() |
{ |
if (OS_WINDOWS) { |
com_message_pump($this->throttleDelay); |
} else { |
usleep($this->throttleDelay * 1000); |
} |
} |
// }}} |
} |
?> |
/trunk/jrest/lib/HTTP/HTTP/Header.php |
---|
New file |
0,0 → 1,531 |
<?php |
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */ |
/** |
* HTTP::Header |
* |
* PHP versions 4 and 5 |
* |
* @category HTTP |
* @package HTTP_Header |
* @author Wolfram Kriesing <wk@visionp.de> |
* @author Davey Shafik <davey@php.net> |
* @author Michael Wallner <mike@php.net> |
* @copyright 2003-2005 The Authors |
* @license BSD, revised |
* @version CVS: $Id$ |
* @link http://pear.php.net/package/HTTP_Header |
*/ |
/** |
* Requires HTTP |
*/ |
require_once 'HTTP.php'; |
/**#@+ |
* Information Codes |
*/ |
define('HTTP_HEADER_STATUS_100', '100 Continue'); |
define('HTTP_HEADER_STATUS_101', '101 Switching Protocols'); |
define('HTTP_HEADER_STATUS_102', '102 Processing'); |
define('HTTP_HEADER_STATUS_INFORMATIONAL',1); |
/**#@-*/ |
/**#+ |
* Success Codes |
*/ |
define('HTTP_HEADER_STATUS_200', '200 OK'); |
define('HTTP_HEADER_STATUS_201', '201 Created'); |
define('HTTP_HEADER_STATUS_202', '202 Accepted'); |
define('HTTP_HEADER_STATUS_203', '203 Non-Authoritative Information'); |
define('HTTP_HEADER_STATUS_204', '204 No Content'); |
define('HTTP_HEADER_STATUS_205', '205 Reset Content'); |
define('HTTP_HEADER_STATUS_206', '206 Partial Content'); |
define('HTTP_HEADER_STATUS_207', '207 Multi-Status'); |
define('HTTP_HEADER_STATUS_SUCCESSFUL',2); |
/**#@-*/ |
/**#@+ |
* Redirection Codes |
*/ |
define('HTTP_HEADER_STATUS_300', '300 Multiple Choices'); |
define('HTTP_HEADER_STATUS_301', '301 Moved Permanently'); |
define('HTTP_HEADER_STATUS_302', '302 Found'); |
define('HTTP_HEADER_STATUS_303', '303 See Other'); |
define('HTTP_HEADER_STATUS_304', '304 Not Modified'); |
define('HTTP_HEADER_STATUS_305', '305 Use Proxy'); |
define('HTTP_HEADER_STATUS_306', '306 (Unused)'); |
define('HTTP_HEADER_STATUS_307', '307 Temporary Redirect'); |
define('HTTP_HEADER_STATUS_REDIRECT',3); |
/**#@-*/ |
/**#@+ |
* Error Codes |
*/ |
define('HTTP_HEADER_STATUS_400', '400 Bad Request'); |
define('HTTP_HEADER_STATUS_401', '401 Unauthorized'); |
define('HTTP_HEADER_STATUS_402', '402 Payment Granted'); |
define('HTTP_HEADER_STATUS_403', '403 Forbidden'); |
define('HTTP_HEADER_STATUS_404', '404 File Not Found'); |
define('HTTP_HEADER_STATUS_405', '405 Method Not Allowed'); |
define('HTTP_HEADER_STATUS_406', '406 Not Acceptable'); |
define('HTTP_HEADER_STATUS_407', '407 Proxy Authentication Required'); |
define('HTTP_HEADER_STATUS_408', '408 Request Time-out'); |
define('HTTP_HEADER_STATUS_409', '409 Conflict'); |
define('HTTP_HEADER_STATUS_410', '410 Gone'); |
define('HTTP_HEADER_STATUS_411', '411 Length Required'); |
define('HTTP_HEADER_STATUS_412', '412 Precondition Failed'); |
define('HTTP_HEADER_STATUS_413', '413 Request Entity Too Large'); |
define('HTTP_HEADER_STATUS_414', '414 Request-URI Too Large'); |
define('HTTP_HEADER_STATUS_415', '415 Unsupported Media Type'); |
define('HTTP_HEADER_STATUS_416', '416 Requested range not satisfiable'); |
define('HTTP_HEADER_STATUS_417', '417 Expectation Failed'); |
define('HTTP_HEADER_STATUS_422', '422 Unprocessable Entity'); |
define('HTTP_HEADER_STATUS_423', '423 Locked'); |
define('HTTP_HEADER_STATUS_424', '424 Failed Dependency'); |
define('HTTP_HEADER_STATUS_CLIENT_ERROR',4); |
/**#@-*/ |
/**#@+ |
* Server Errors |
*/ |
define('HTTP_HEADER_STATUS_500', '500 Internal Server Error'); |
define('HTTP_HEADER_STATUS_501', '501 Not Implemented'); |
define('HTTP_HEADER_STATUS_502', '502 Bad Gateway'); |
define('HTTP_HEADER_STATUS_503', '503 Service Unavailable'); |
define('HTTP_HEADER_STATUS_504', '504 Gateway Time-out'); |
define('HTTP_HEADER_STATUS_505', '505 HTTP Version not supported'); |
define('HTTP_HEADER_STATUS_507', '507 Insufficient Storage'); |
define('HTTP_HEADER_STATUS_SERVER_ERROR',5); |
/**#@-*/ |
/** |
* HTTP_Header |
* |
* @package HTTP_Header |
* @category HTTP |
* @access public |
* @version $Revision$ |
*/ |
class HTTP_Header extends HTTP |
{ |
/** |
* Default Headers |
* |
* The values that are set as default, are the same as PHP sends by default. |
* |
* @var array |
* @access private |
*/ |
var $_headers = array( |
'content-type' => 'text/html', |
'pragma' => 'no-cache', |
'cache-control' => 'no-store, no-cache, must-revalidate, post-check=0, pre-check=0' |
); |
/** |
* HTTP version |
* |
* @var string |
* @access private |
*/ |
var $_httpVersion = '1.0'; |
/** |
* Constructor |
* |
* Sets HTTP version. |
* |
* @access public |
* @return object HTTP_Header |
*/ |
function HTTP_Header() |
{ |
if (isset($_SERVER['SERVER_PROTOCOL'])) { |
$this->setHttpVersion(substr($_SERVER['SERVER_PROTOCOL'], -3)); |
} |
} |
/** |
* Set HTTP version |
* |
* @access public |
* @return bool Returns true on success or false if version doesn't |
* match 1.0 or 1.1 (note: 1 will result in 1.0) |
* @param mixed $version HTTP version, either 1.0 or 1.1 |
*/ |
function setHttpVersion($version) |
{ |
$version = round((float) $version, 1); |
if ($version < 1.0 || $version > 1.1) { |
return false; |
} |
$this->_httpVersion = sprintf('%0.1f', $version); |
return true; |
} |
/** |
* Get HTTP version |
* |
* @access public |
* @return string |
*/ |
function getHttpVersion() |
{ |
return $this->_httpVersion; |
} |
/** |
* Set Header |
* |
* The default value for the Last-Modified header will be current |
* date and atime if $value is omitted. |
* |
* @access public |
* @return bool Returns true on success or false if $key was empty or |
* $value was not of an scalar type. |
* @param string $key The name of the header. |
* @param string $value The value of the header. (NULL to unset header) |
*/ |
function setHeader($key, $value = null) |
{ |
if (empty($key) || (isset($value) && !is_scalar($value))) { |
return false; |
} |
$key = strToLower($key); |
if ($key == 'last-modified') { |
if (!isset($value)) { |
$value = HTTP::Date(time()); |
} elseif (is_numeric($value)) { |
$value = HTTP::Date($value); |
} |
} |
if (isset($value)) { |
$this->_headers[$key] = $value; |
} else { |
unset($this->_headers[$key]); |
} |
return true; |
} |
/** |
* Get Header |
* |
* If $key is omitted, all stored headers will be returned. |
* |
* @access public |
* @return mixed Returns string value of the requested header, |
* array values of all headers or false if header $key |
* is not set. |
* @param string $key The name of the header to fetch. |
*/ |
function getHeader($key = null) |
{ |
if (!isset($key)) { |
return $this->_headers; |
} |
$key = strToLower($key); |
if (!isset($this->_headers[$key])) { |
return false; |
} |
return $this->_headers[$key]; |
} |
/** |
* Send Headers |
* |
* Send out the header that you set via setHeader(). |
* |
* @access public |
* @return bool Returns true on success or false if headers are already |
* sent. |
* @param array $keys Headers to (not) send, see $include. |
* @param array $include If true only $keys matching headers will be |
* sent, if false only header not matching $keys will be |
* sent. |
*/ |
function sendHeaders($keys = array(), $include = true) |
{ |
if (headers_sent()) { |
return false; |
} |
if (count($keys)) { |
array_change_key_case($keys, CASE_LOWER); |
foreach ($this->_headers as $key => $value) { |
if ($include ? in_array($key, $keys) : !in_array($key, $keys)) { |
header($key .': '. $value); |
} |
} |
} else { |
foreach ($this->_headers as $header => $value) { |
header($header .': '. $value); |
} |
} |
return true; |
} |
/** |
* Send Satus Code |
* |
* Send out the given HTTP-Status code. Use this for example when you |
* want to tell the client this page is cached, then you would call |
* sendStatusCode(304). |
* |
* @see HTTP_Header_Cache::exitIfCached() |
* |
* @access public |
* @return bool Returns true on success or false if headers are already |
* sent. |
* @param int $code The status code to send, i.e. 404, 304, 200, etc. |
*/ |
function sendStatusCode($code) |
{ |
if (headers_sent()) { |
return false; |
} |
if ($code == (int) $code && defined('HTTP_HEADER_STATUS_'. $code)) { |
$code = constant('HTTP_HEADER_STATUS_'. $code); |
} |
if (strncasecmp(PHP_SAPI, 'cgi', 3)) { |
header('HTTP/'. $this->_httpVersion .' '. $code); |
} else { |
header('Status: '. $code); |
} |
return true; |
} |
/** |
* Date to Timestamp |
* |
* Converts dates like |
* Mon, 31 Mar 2003 15:26:34 GMT |
* Tue, 15 Nov 1994 12:45:26 GMT |
* into a timestamp, strtotime() didn't do it in older versions. |
* |
* @deprecated Use PHPs strtotime() instead. |
* @access public |
* @return mixed Returns int unix timestamp or false if the date doesn't |
* seem to be a valid GMT date. |
* @param string $date The GMT date. |
*/ |
function dateToTimestamp($date) |
{ |
static $months = array( |
null => 0, 'Jan' => 1, 'Feb' => 2, 'Mar' => 3, 'Apr' => 4, |
'May' => 5, 'Jun' => 6, 'Jul' => 7, 'Aug' => 8, 'Sep' => 9, |
'Oct' => 10, 'Nov' => 11, 'Dec' => 12 |
); |
if (-1 < $timestamp = strToTime($date)) { |
return $timestamp; |
} |
if (!preg_match('~[^,]*,\s(\d+)\s(\w+)\s(\d+)\s(\d+):(\d+):(\d+).*~', |
$date, $m)) { |
return false; |
} |
// [0] => Mon, 31 Mar 2003 15:42:55 GMT |
// [1] => 31 [2] => Mar [3] => 2003 [4] => 15 [5] => 42 [6] => 55 |
return mktime($m[4], $m[5], $m[6], $months[$m[2]], $m[1], $m[3]); |
} |
/** |
* Redirect |
* |
* This function redirects the client. This is done by issuing a Location |
* header and exiting. Additionally to HTTP::redirect() you can also add |
* parameters to the url. |
* |
* If you dont need parameters to be added, simply use HTTP::redirect() |
* otherwise use HTTP_Header::redirect(). |
* |
* @see HTTP::redirect() |
* @author Wolfram Kriesing <wk@visionp.de> |
* @access public |
* @return void |
* @param string $url The URL to redirect to, if none is given it |
* redirects to the current page. |
* @param array $param Array of query string parameters to add; usually |
* a set of key => value pairs; if an array entry consists |
* only of an value it is used as key and the respective |
* value is fetched from $GLOBALS[$value] |
* @param bool $session Whether the session name/id should be added |
*/ |
function redirect($url = null, $param = array(), $session = false) |
{ |
if (!isset($url)) { |
$url = $_SERVER['PHP_SELF']; |
} |
$qs = array(); |
if ($session) { |
$qs[] = session_name() .'='. session_id(); |
} |
if (is_array($param) && count($param)) { |
if (count($param)) { |
foreach ($param as $key => $val) { |
if (is_string($key)) { |
$qs[] = urlencode($key) .'='. urlencode($val); |
} else { |
$qs[] = urlencode($val) .'='. urlencode(@$GLOBALS[$val]); |
} |
} |
} |
} |
if ($qstr = implode('&', $qs)) { |
$purl = parse_url($url); |
$url .= (isset($purl['query']) ? '&' : '?') . $qstr; |
} |
parent::redirect($url); |
} |
/**#@+ |
* @author Davey Shafik <davey@php.net> |
* @param int $http_code HTTP Code to check |
* @access public |
*/ |
/** |
* Return HTTP Status Code Type |
* |
* @return int|false |
*/ |
function getStatusType($http_code) |
{ |
if(is_int($http_code) && defined('HTTP_HEADER_STATUS_' .$http_code) || defined($http_code)) { |
$type = substr($http_code,0,1); |
switch ($type) { |
case HTTP_HEADER_STATUS_INFORMATIONAL: |
case HTTP_HEADER_STATUS_SUCCESSFUL: |
case HTTP_HEADER_STATUS_REDIRECT: |
case HTTP_HEADER_STATUS_CLIENT_ERROR: |
case HTTP_HEADER_STATUS_SERVER_ERROR: |
return $type; |
break; |
default: |
return false; |
break; |
} |
} else { |
return false; |
} |
} |
/** |
* Return Status Code Message |
* |
* @return string|false |
*/ |
function getStatusText($http_code) |
{ |
if ($this->getStatusType($http_code)) { |
if (is_int($http_code) && defined('HTTP_HEADER_STATUS_' .$http_code)) { |
return substr(constant('HTTP_HEADER_STATUS_' .$http_code),4); |
} else { |
return substr($http_code,4); |
} |
} else { |
return false; |
} |
} |
/** |
* Checks if HTTP Status code is Information (1xx) |
* |
* @return boolean |
*/ |
function isInformational($http_code) |
{ |
if ($status_type = $this->getStatusType($http_code)) { |
return $status_type{0} == HTTP_HEADER_STATUS_INFORMATIONAL; |
} else { |
return false; |
} |
} |
/** |
* Checks if HTTP Status code is Successful (2xx) |
* |
* @return boolean |
*/ |
function isSuccessful($http_code) |
{ |
if ($status_type = $this->getStatusType($http_code)) { |
return $status_type{0} == HTTP_HEADER_STATUS_SUCCESSFUL; |
} else { |
return false; |
} |
} |
/** |
* Checks if HTTP Status code is a Redirect (3xx) |
* |
* @return boolean |
*/ |
function isRedirect($http_code) |
{ |
if ($status_type = $this->getStatusType($http_code)) { |
return $status_type{0} == HTTP_HEADER_STATUS_REDIRECT; |
} else { |
return false; |
} |
} |
/** |
* Checks if HTTP Status code is a Client Error (4xx) |
* |
* @return boolean |
*/ |
function isClientError($http_code) |
{ |
if ($status_type = $this->getStatusType($http_code)) { |
return $status_type{0} == HTTP_HEADER_STATUS_CLIENT_ERROR; |
} else { |
return false; |
} |
} |
/** |
* Checks if HTTP Status code is Server Error (5xx) |
* |
* @return boolean |
*/ |
function isServerError($http_code) |
{ |
if ($status_type = $this->getStatusType($http_code)) { |
return $status_type{0} == HTTP_HEADER_STATUS_SERVER_ERROR; |
} else { |
return false; |
} |
} |
/** |
* Checks if HTTP Status code is Server OR Client Error (4xx or 5xx) |
* |
* @return boolean |
*/ |
function isError($http_code) |
{ |
if ($status_type = $this->getStatusType($http_code)) { |
return (($status_type == HTTP_HEADER_STATUS_CLIENT_ERROR) || ($status_type == HTTP_HEADER_STATUS_SERVER_ERROR)) ? true : false; |
} else { |
return false; |
} |
} |
/**#@-*/ |
} |
?> |
/trunk/jrest/lib/JSON.php |
---|
New file |
0,0 → 1,806 |
<?php |
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */ |
/** |
* Converts to and from JSON format. |
* |
* JSON (JavaScript Object Notation) is a lightweight data-interchange |
* format. It is easy for humans to read and write. It is easy for machines |
* to parse and generate. It is based on a subset of the JavaScript |
* Programming Language, Standard ECMA-262 3rd Edition - December 1999. |
* This feature can also be found in Python. JSON is a text format that is |
* completely language independent but uses conventions that are familiar |
* to programmers of the C-family of languages, including C, C++, C#, Java, |
* JavaScript, Perl, TCL, and many others. These properties make JSON an |
* ideal data-interchange language. |
* |
* This package provides a simple encoder and decoder for JSON notation. It |
* is intended for use with client-side Javascript applications that make |
* use of HTTPRequest to perform server communication functions - data can |
* be encoded into JSON notation for use in a client-side javascript, or |
* decoded from incoming Javascript requests. JSON format is native to |
* Javascript, and can be directly eval()'ed with no further parsing |
* overhead |
* |
* All strings should be in ASCII or UTF-8 format! |
* |
* LICENSE: Redistribution and use in source and binary forms, with or |
* without modification, are permitted provided that the following |
* conditions are met: Redistributions of source code must retain the |
* above copyright notice, this list of conditions and the following |
* disclaimer. Redistributions in binary form must reproduce the above |
* copyright notice, this list of conditions and the following disclaimer |
* in the documentation and/or other materials provided with the |
* distribution. |
* |
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED |
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF |
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN |
* NO EVENT SHALL CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, |
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS |
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR |
* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE |
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH |
* DAMAGE. |
* |
* @category |
* @package Services_JSON |
* @author Michal Migurski <mike-json@teczno.com> |
* @author Matt Knapp <mdknapp[at]gmail[dot]com> |
* @author Brett Stimmerman <brettstimmerman[at]gmail[dot]com> |
* @copyright 2005 Michal Migurski |
* @version CVS: $Id$ |
* @license http://www.opensource.org/licenses/bsd-license.php |
* @link http://pear.php.net/pepr/pepr-proposal-show.php?id=198 |
*/ |
/** |
* Marker constant for Services_JSON::decode(), used to flag stack state |
*/ |
define('SERVICES_JSON_SLICE', 1); |
/** |
* Marker constant for Services_JSON::decode(), used to flag stack state |
*/ |
define('SERVICES_JSON_IN_STR', 2); |
/** |
* Marker constant for Services_JSON::decode(), used to flag stack state |
*/ |
define('SERVICES_JSON_IN_ARR', 3); |
/** |
* Marker constant for Services_JSON::decode(), used to flag stack state |
*/ |
define('SERVICES_JSON_IN_OBJ', 4); |
/** |
* Marker constant for Services_JSON::decode(), used to flag stack state |
*/ |
define('SERVICES_JSON_IN_CMT', 5); |
/** |
* Behavior switch for Services_JSON::decode() |
*/ |
define('SERVICES_JSON_LOOSE_TYPE', 16); |
/** |
* Behavior switch for Services_JSON::decode() |
*/ |
define('SERVICES_JSON_SUPPRESS_ERRORS', 32); |
/** |
* Converts to and from JSON format. |
* |
* Brief example of use: |
* |
* <code> |
* // create a new instance of Services_JSON |
* $json = new Services_JSON(); |
* |
* // convert a complexe value to JSON notation, and send it to the browser |
* $value = array('foo', 'bar', array(1, 2, 'baz'), array(3, array(4))); |
* $output = $json->encode($value); |
* |
* print($output); |
* // prints: ["foo","bar",[1,2,"baz"],[3,[4]]] |
* |
* // accept incoming POST data, assumed to be in JSON notation |
* $input = file_get_contents('php://input', 1000000); |
* $value = $json->decode($input); |
* </code> |
*/ |
class Services_JSON |
{ |
/** |
* constructs a new JSON instance |
* |
* @param int $use object behavior flags; combine with boolean-OR |
* |
* possible values: |
* - SERVICES_JSON_LOOSE_TYPE: loose typing. |
* "{...}" syntax creates associative arrays |
* instead of objects in decode(). |
* - SERVICES_JSON_SUPPRESS_ERRORS: error suppression. |
* Values which can't be encoded (e.g. resources) |
* appear as NULL instead of throwing errors. |
* By default, a deeply-nested resource will |
* bubble up with an error, so all return values |
* from encode() should be checked with isError() |
*/ |
function Services_JSON($use = 0) |
{ |
$this->use = $use; |
} |
/** |
* convert a string from one UTF-16 char to one UTF-8 char |
* |
* Normally should be handled by mb_convert_encoding, but |
* provides a slower PHP-only method for installations |
* that lack the multibye string extension. |
* |
* @param string $utf16 UTF-16 character |
* @return string UTF-8 character |
* @access private |
*/ |
function utf162utf8($utf16) |
{ |
// oh please oh please oh please oh please oh please |
if(function_exists('mb_convert_encoding')) { |
return mb_convert_encoding($utf16, 'UTF-8', 'UTF-16'); |
} |
$bytes = (ord($utf16{0}) << 8) | ord($utf16{1}); |
switch(true) { |
case ((0x7F & $bytes) == $bytes): |
// this case should never be reached, because we are in ASCII range |
// see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 |
return chr(0x7F & $bytes); |
case (0x07FF & $bytes) == $bytes: |
// return a 2-byte UTF-8 character |
// see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 |
return chr(0xC0 | (($bytes >> 6) & 0x1F)) |
. chr(0x80 | ($bytes & 0x3F)); |
case (0xFFFF & $bytes) == $bytes: |
// return a 3-byte UTF-8 character |
// see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 |
return chr(0xE0 | (($bytes >> 12) & 0x0F)) |
. chr(0x80 | (($bytes >> 6) & 0x3F)) |
. chr(0x80 | ($bytes & 0x3F)); |
} |
// ignoring UTF-32 for now, sorry |
return ''; |
} |
/** |
* convert a string from one UTF-8 char to one UTF-16 char |
* |
* Normally should be handled by mb_convert_encoding, but |
* provides a slower PHP-only method for installations |
* that lack the multibye string extension. |
* |
* @param string $utf8 UTF-8 character |
* @return string UTF-16 character |
* @access private |
*/ |
function utf82utf16($utf8) |
{ |
// oh please oh please oh please oh please oh please |
if(function_exists('mb_convert_encoding')) { |
return mb_convert_encoding($utf8, 'UTF-16', 'UTF-8'); |
} |
switch(strlen($utf8)) { |
case 1: |
// this case should never be reached, because we are in ASCII range |
// see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 |
return $utf8; |
case 2: |
// return a UTF-16 character from a 2-byte UTF-8 char |
// see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 |
return chr(0x07 & (ord($utf8{0}) >> 2)) |
. chr((0xC0 & (ord($utf8{0}) << 6)) |
| (0x3F & ord($utf8{1}))); |
case 3: |
// return a UTF-16 character from a 3-byte UTF-8 char |
// see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 |
return chr((0xF0 & (ord($utf8{0}) << 4)) |
| (0x0F & (ord($utf8{1}) >> 2))) |
. chr((0xC0 & (ord($utf8{1}) << 6)) |
| (0x7F & ord($utf8{2}))); |
} |
// ignoring UTF-32 for now, sorry |
return ''; |
} |
/** |
* encodes an arbitrary variable into JSON format |
* |
* @param mixed $var any number, boolean, string, array, or object to be encoded. |
* see argument 1 to Services_JSON() above for array-parsing behavior. |
* if var is a strng, note that encode() always expects it |
* to be in ASCII or UTF-8 format! |
* |
* @return mixed JSON string representation of input var or an error if a problem occurs |
* @access public |
*/ |
function encode($var) |
{ |
switch (gettype($var)) { |
case 'boolean': |
return $var ? 'true' : 'false'; |
case 'NULL': |
return 'null'; |
case 'integer': |
return (int) $var; |
case 'double': |
case 'float': |
return (float) $var; |
case 'string': |
// STRINGS ARE EXPECTED TO BE IN ASCII OR UTF-8 FORMAT |
$ascii = ''; |
$strlen_var = strlen($var); |
/* |
* Iterate over every character in the string, |
* escaping with a slash or encoding to UTF-8 where necessary |
*/ |
for ($c = 0; $c < $strlen_var; ++$c) { |
$ord_var_c = ord($var{$c}); |
switch (true) { |
case $ord_var_c == 0x08: |
$ascii .= '\b'; |
break; |
case $ord_var_c == 0x09: |
$ascii .= '\t'; |
break; |
case $ord_var_c == 0x0A: |
$ascii .= '\n'; |
break; |
case $ord_var_c == 0x0C: |
$ascii .= '\f'; |
break; |
case $ord_var_c == 0x0D: |
$ascii .= '\r'; |
break; |
case $ord_var_c == 0x22: |
case $ord_var_c == 0x2F: |
case $ord_var_c == 0x5C: |
// double quote, slash, slosh |
$ascii .= '\\'.$var{$c}; |
break; |
case (($ord_var_c >= 0x20) && ($ord_var_c <= 0x7F)): |
// characters U-00000000 - U-0000007F (same as ASCII) |
$ascii .= $var{$c}; |
break; |
case (($ord_var_c & 0xE0) == 0xC0): |
// characters U-00000080 - U-000007FF, mask 110XXXXX |
// see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 |
$char = pack('C*', $ord_var_c, ord($var{$c + 1})); |
$c += 1; |
$utf16 = $this->utf82utf16($char); |
$ascii .= sprintf('\u%04s', bin2hex($utf16)); |
break; |
case (($ord_var_c & 0xF0) == 0xE0): |
// characters U-00000800 - U-0000FFFF, mask 1110XXXX |
// see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 |
$char = pack('C*', $ord_var_c, |
ord($var{$c + 1}), |
ord($var{$c + 2})); |
$c += 2; |
$utf16 = $this->utf82utf16($char); |
$ascii .= sprintf('\u%04s', bin2hex($utf16)); |
break; |
case (($ord_var_c & 0xF8) == 0xF0): |
// characters U-00010000 - U-001FFFFF, mask 11110XXX |
// see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 |
$char = pack('C*', $ord_var_c, |
ord($var{$c + 1}), |
ord($var{$c + 2}), |
ord($var{$c + 3})); |
$c += 3; |
$utf16 = $this->utf82utf16($char); |
$ascii .= sprintf('\u%04s', bin2hex($utf16)); |
break; |
case (($ord_var_c & 0xFC) == 0xF8): |
// characters U-00200000 - U-03FFFFFF, mask 111110XX |
// see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 |
$char = pack('C*', $ord_var_c, |
ord($var{$c + 1}), |
ord($var{$c + 2}), |
ord($var{$c + 3}), |
ord($var{$c + 4})); |
$c += 4; |
$utf16 = $this->utf82utf16($char); |
$ascii .= sprintf('\u%04s', bin2hex($utf16)); |
break; |
case (($ord_var_c & 0xFE) == 0xFC): |
// characters U-04000000 - U-7FFFFFFF, mask 1111110X |
// see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 |
$char = pack('C*', $ord_var_c, |
ord($var{$c + 1}), |
ord($var{$c + 2}), |
ord($var{$c + 3}), |
ord($var{$c + 4}), |
ord($var{$c + 5})); |
$c += 5; |
$utf16 = $this->utf82utf16($char); |
$ascii .= sprintf('\u%04s', bin2hex($utf16)); |
break; |
} |
} |
return '"'.$ascii.'"'; |
case 'array': |
/* |
* As per JSON spec if any array key is not an integer |
* we must treat the the whole array as an object. We |
* also try to catch a sparsely populated associative |
* array with numeric keys here because some JS engines |
* will create an array with empty indexes up to |
* max_index which can cause memory issues and because |
* the keys, which may be relevant, will be remapped |
* otherwise. |
* |
* As per the ECMA and JSON specification an object may |
* have any string as a property. Unfortunately due to |
* a hole in the ECMA specification if the key is a |
* ECMA reserved word or starts with a digit the |
* parameter is only accessible using ECMAScript's |
* bracket notation. |
*/ |
// treat as a JSON object |
if (is_array($var) && count($var) && (array_keys($var) !== range(0, sizeof($var) - 1))) { |
$properties = array_map(array($this, 'name_value'), |
array_keys($var), |
array_values($var)); |
foreach($properties as $property) { |
if(Services_JSON::isError($property)) { |
return $property; |
} |
} |
return '{' . join(',', $properties) . '}'; |
} |
// treat it like a regular array |
$elements = array_map(array($this, 'encode'), $var); |
foreach($elements as $element) { |
if(Services_JSON::isError($element)) { |
return $element; |
} |
} |
return '[' . join(',', $elements) . ']'; |
case 'object': |
$vars = get_object_vars($var); |
$properties = array_map(array($this, 'name_value'), |
array_keys($vars), |
array_values($vars)); |
foreach($properties as $property) { |
if(Services_JSON::isError($property)) { |
return $property; |
} |
} |
return '{' . join(',', $properties) . '}'; |
default: |
return ($this->use & SERVICES_JSON_SUPPRESS_ERRORS) |
? 'null' |
: new Services_JSON_Error(gettype($var)." can not be encoded as JSON string"); |
} |
} |
/** |
* array-walking function for use in generating JSON-formatted name-value pairs |
* |
* @param string $name name of key to use |
* @param mixed $value reference to an array element to be encoded |
* |
* @return string JSON-formatted name-value pair, like '"name":value' |
* @access private |
*/ |
function name_value($name, $value) |
{ |
$encoded_value = $this->encode($value); |
if(Services_JSON::isError($encoded_value)) { |
return $encoded_value; |
} |
return $this->encode(strval($name)) . ':' . $encoded_value; |
} |
/** |
* reduce a string by removing leading and trailing comments and whitespace |
* |
* @param $str string string value to strip of comments and whitespace |
* |
* @return string string value stripped of comments and whitespace |
* @access private |
*/ |
function reduce_string($str) |
{ |
$str = preg_replace(array( |
// eliminate single line comments in '// ...' form |
'#^\s*//(.+)$#m', |
// eliminate multi-line comments in '/* ... */' form, at start of string |
'#^\s*/\*(.+)\*/#Us', |
// eliminate multi-line comments in '/* ... */' form, at end of string |
'#/\*(.+)\*/\s*$#Us' |
), '', $str); |
// eliminate extraneous space |
return trim($str); |
} |
/** |
* decodes a JSON string into appropriate variable |
* |
* @param string $str JSON-formatted string |
* |
* @return mixed number, boolean, string, array, or object |
* corresponding to given JSON input string. |
* See argument 1 to Services_JSON() above for object-output behavior. |
* Note that decode() always returns strings |
* in ASCII or UTF-8 format! |
* @access public |
*/ |
function decode($str) |
{ |
$str = $this->reduce_string($str); |
switch (strtolower($str)) { |
case 'true': |
return true; |
case 'false': |
return false; |
case 'null': |
return null; |
default: |
$m = array(); |
if (is_numeric($str)) { |
// Lookie-loo, it's a number |
// This would work on its own, but I'm trying to be |
// good about returning integers where appropriate: |
// return (float)$str; |
// Return float or int, as appropriate |
return ((float)$str == (integer)$str) |
? (integer)$str |
: (float)$str; |
} elseif (preg_match('/^("|\').*(\1)$/s', $str, $m) && $m[1] == $m[2]) { |
// STRINGS RETURNED IN UTF-8 FORMAT |
$delim = substr($str, 0, 1); |
$chrs = substr($str, 1, -1); |
$utf8 = ''; |
$strlen_chrs = strlen($chrs); |
for ($c = 0; $c < $strlen_chrs; ++$c) { |
$substr_chrs_c_2 = substr($chrs, $c, 2); |
$ord_chrs_c = ord($chrs{$c}); |
switch (true) { |
case $substr_chrs_c_2 == '\b': |
$utf8 .= chr(0x08); |
++$c; |
break; |
case $substr_chrs_c_2 == '\t': |
$utf8 .= chr(0x09); |
++$c; |
break; |
case $substr_chrs_c_2 == '\n': |
$utf8 .= chr(0x0A); |
++$c; |
break; |
case $substr_chrs_c_2 == '\f': |
$utf8 .= chr(0x0C); |
++$c; |
break; |
case $substr_chrs_c_2 == '\r': |
$utf8 .= chr(0x0D); |
++$c; |
break; |
case $substr_chrs_c_2 == '\\"': |
case $substr_chrs_c_2 == '\\\'': |
case $substr_chrs_c_2 == '\\\\': |
case $substr_chrs_c_2 == '\\/': |
if (($delim == '"' && $substr_chrs_c_2 != '\\\'') || |
($delim == "'" && $substr_chrs_c_2 != '\\"')) { |
$utf8 .= $chrs{++$c}; |
} |
break; |
case preg_match('/\\\u[0-9A-F]{4}/i', substr($chrs, $c, 6)): |
// single, escaped unicode character |
$utf16 = chr(hexdec(substr($chrs, ($c + 2), 2))) |
. chr(hexdec(substr($chrs, ($c + 4), 2))); |
$utf8 .= $this->utf162utf8($utf16); |
$c += 5; |
break; |
case ($ord_chrs_c >= 0x20) && ($ord_chrs_c <= 0x7F): |
$utf8 .= $chrs{$c}; |
break; |
case ($ord_chrs_c & 0xE0) == 0xC0: |
// characters U-00000080 - U-000007FF, mask 110XXXXX |
//see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 |
$utf8 .= substr($chrs, $c, 2); |
++$c; |
break; |
case ($ord_chrs_c & 0xF0) == 0xE0: |
// characters U-00000800 - U-0000FFFF, mask 1110XXXX |
// see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 |
$utf8 .= substr($chrs, $c, 3); |
$c += 2; |
break; |
case ($ord_chrs_c & 0xF8) == 0xF0: |
// characters U-00010000 - U-001FFFFF, mask 11110XXX |
// see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 |
$utf8 .= substr($chrs, $c, 4); |
$c += 3; |
break; |
case ($ord_chrs_c & 0xFC) == 0xF8: |
// characters U-00200000 - U-03FFFFFF, mask 111110XX |
// see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 |
$utf8 .= substr($chrs, $c, 5); |
$c += 4; |
break; |
case ($ord_chrs_c & 0xFE) == 0xFC: |
// characters U-04000000 - U-7FFFFFFF, mask 1111110X |
// see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 |
$utf8 .= substr($chrs, $c, 6); |
$c += 5; |
break; |
} |
} |
return $utf8; |
} elseif (preg_match('/^\[.*\]$/s', $str) || preg_match('/^\{.*\}$/s', $str)) { |
// array, or object notation |
if ($str{0} == '[') { |
$stk = array(SERVICES_JSON_IN_ARR); |
$arr = array(); |
} else { |
if ($this->use & SERVICES_JSON_LOOSE_TYPE) { |
$stk = array(SERVICES_JSON_IN_OBJ); |
$obj = array(); |
} else { |
$stk = array(SERVICES_JSON_IN_OBJ); |
$obj = new stdClass(); |
} |
} |
array_push($stk, array('what' => SERVICES_JSON_SLICE, |
'where' => 0, |
'delim' => false)); |
$chrs = substr($str, 1, -1); |
$chrs = $this->reduce_string($chrs); |
if ($chrs == '') { |
if (reset($stk) == SERVICES_JSON_IN_ARR) { |
return $arr; |
} else { |
return $obj; |
} |
} |
//print("\nparsing {$chrs}\n"); |
$strlen_chrs = strlen($chrs); |
for ($c = 0; $c <= $strlen_chrs; ++$c) { |
$top = end($stk); |
$substr_chrs_c_2 = substr($chrs, $c, 2); |
if (($c == $strlen_chrs) || (($chrs{$c} == ',') && ($top['what'] == SERVICES_JSON_SLICE))) { |
// found a comma that is not inside a string, array, etc., |
// OR we've reached the end of the character list |
$slice = substr($chrs, $top['where'], ($c - $top['where'])); |
array_push($stk, array('what' => SERVICES_JSON_SLICE, 'where' => ($c + 1), 'delim' => false)); |
//print("Found split at {$c}: ".substr($chrs, $top['where'], (1 + $c - $top['where']))."\n"); |
if (reset($stk) == SERVICES_JSON_IN_ARR) { |
// we are in an array, so just push an element onto the stack |
array_push($arr, $this->decode($slice)); |
} elseif (reset($stk) == SERVICES_JSON_IN_OBJ) { |
// we are in an object, so figure |
// out the property name and set an |
// element in an associative array, |
// for now |
$parts = array(); |
if (preg_match('/^\s*(["\'].*[^\\\]["\'])\s*:\s*(\S.*),?$/Uis', $slice, $parts)) { |
// "name":value pair |
$key = $this->decode($parts[1]); |
$val = $this->decode($parts[2]); |
if ($this->use & SERVICES_JSON_LOOSE_TYPE) { |
$obj[$key] = $val; |
} else { |
$obj->$key = $val; |
} |
} elseif (preg_match('/^\s*(\w+)\s*:\s*(\S.*),?$/Uis', $slice, $parts)) { |
// name:value pair, where name is unquoted |
$key = $parts[1]; |
$val = $this->decode($parts[2]); |
if ($this->use & SERVICES_JSON_LOOSE_TYPE) { |
$obj[$key] = $val; |
} else { |
$obj->$key = $val; |
} |
} |
} |
} elseif ((($chrs{$c} == '"') || ($chrs{$c} == "'")) && ($top['what'] != SERVICES_JSON_IN_STR)) { |
// found a quote, and we are not inside a string |
array_push($stk, array('what' => SERVICES_JSON_IN_STR, 'where' => $c, 'delim' => $chrs{$c})); |
//print("Found start of string at {$c}\n"); |
} elseif (($chrs{$c} == $top['delim']) && |
($top['what'] == SERVICES_JSON_IN_STR) && |
((strlen(substr($chrs, 0, $c)) - strlen(rtrim(substr($chrs, 0, $c), '\\'))) % 2 != 1)) { |
// found a quote, we're in a string, and it's not escaped |
// we know that it's not escaped becase there is _not_ an |
// odd number of backslashes at the end of the string so far |
array_pop($stk); |
//print("Found end of string at {$c}: ".substr($chrs, $top['where'], (1 + 1 + $c - $top['where']))."\n"); |
} elseif (($chrs{$c} == '[') && |
in_array($top['what'], array(SERVICES_JSON_SLICE, SERVICES_JSON_IN_ARR, SERVICES_JSON_IN_OBJ))) { |
// found a left-bracket, and we are in an array, object, or slice |
array_push($stk, array('what' => SERVICES_JSON_IN_ARR, 'where' => $c, 'delim' => false)); |
//print("Found start of array at {$c}\n"); |
} elseif (($chrs{$c} == ']') && ($top['what'] == SERVICES_JSON_IN_ARR)) { |
// found a right-bracket, and we're in an array |
array_pop($stk); |
//print("Found end of array at {$c}: ".substr($chrs, $top['where'], (1 + $c - $top['where']))."\n"); |
} elseif (($chrs{$c} == '{') && |
in_array($top['what'], array(SERVICES_JSON_SLICE, SERVICES_JSON_IN_ARR, SERVICES_JSON_IN_OBJ))) { |
// found a left-brace, and we are in an array, object, or slice |
array_push($stk, array('what' => SERVICES_JSON_IN_OBJ, 'where' => $c, 'delim' => false)); |
//print("Found start of object at {$c}\n"); |
} elseif (($chrs{$c} == '}') && ($top['what'] == SERVICES_JSON_IN_OBJ)) { |
// found a right-brace, and we're in an object |
array_pop($stk); |
//print("Found end of object at {$c}: ".substr($chrs, $top['where'], (1 + $c - $top['where']))."\n"); |
} elseif (($substr_chrs_c_2 == '/*') && |
in_array($top['what'], array(SERVICES_JSON_SLICE, SERVICES_JSON_IN_ARR, SERVICES_JSON_IN_OBJ))) { |
// found a comment start, and we are in an array, object, or slice |
array_push($stk, array('what' => SERVICES_JSON_IN_CMT, 'where' => $c, 'delim' => false)); |
$c++; |
//print("Found start of comment at {$c}\n"); |
} elseif (($substr_chrs_c_2 == '*/') && ($top['what'] == SERVICES_JSON_IN_CMT)) { |
// found a comment end, and we're in one now |
array_pop($stk); |
$c++; |
for ($i = $top['where']; $i <= $c; ++$i) |
$chrs = substr_replace($chrs, ' ', $i, 1); |
//print("Found end of comment at {$c}: ".substr($chrs, $top['where'], (1 + $c - $top['where']))."\n"); |
} |
} |
if (reset($stk) == SERVICES_JSON_IN_ARR) { |
return $arr; |
} elseif (reset($stk) == SERVICES_JSON_IN_OBJ) { |
return $obj; |
} |
} |
} |
} |
/** |
* @todo Ultimately, this should just call PEAR::isError() |
*/ |
function isError($data, $code = null) |
{ |
if (class_exists('pear')) { |
return PEAR::isError($data, $code); |
} elseif (is_object($data) && (get_class($data) == 'services_json_error' || |
is_subclass_of($data, 'services_json_error'))) { |
return true; |
} |
return false; |
} |
} |
if (class_exists('PEAR_Error')) { |
class Services_JSON_Error extends PEAR_Error |
{ |
function Services_JSON_Error($message = 'unknown error', $code = null, |
$mode = null, $options = null, $userinfo = null) |
{ |
parent::PEAR_Error($message, $code, $mode, $options, $userinfo); |
} |
} |
} else { |
/** |
* @todo Ultimately, this class shall be descended from PEAR_Error |
*/ |
class Services_JSON_Error |
{ |
function Services_JSON_Error($message = 'unknown error', $code = null, |
$mode = null, $options = null, $userinfo = null) |
{ |
} |
} |
} |
?> |
/trunk/jrest/lib/PDF.php |
---|
New file |
0,0 → 1,3001 |
<?php |
/** |
* File_PDF:: |
* |
* The File_PDF:: class provides a PHP-only implementation of a PDF library. |
* No external libs or PHP extensions are required. |
* |
* Based on the FPDF class by Olivier Plathey (http://www.fpdf.org). |
* |
* Copyright 2001-2003 Olivier Plathey <olivier@fpdf.org> |
* Copyright 2003-2007 The Horde Project (http://www.horde.org/) |
* |
* See the enclosed file COPYING for license information (LGPL). If you |
* did not receive this file, see http://www.fsf.org/copyleft/lgpl.html. |
* |
* $Horde: framework/File_PDF/PDF.php,v 1.48 2007/01/05 13:12:21 jan Exp $ |
* |
* @author Olivier Plathey <olivier@fpdf.org> |
* @author Marko Djukic <marko@oblo.com> |
* @author Jan Schneider <jan@horde.org> |
* @package File_PDF |
* @category Fileformats |
*/ |
class File_PDF { |
/** |
* Current page number. |
* |
* @var integer |
*/ |
var $_page = 0; |
/** |
* Current object number. |
* |
* @var integer |
*/ |
var $_n = 2; |
/** |
* Array of object offsets. |
* |
* @var array |
*/ |
var $_offsets = array(); |
/** |
* Buffer holding in-memory PDF. |
* |
* @var string |
*/ |
var $_buffer = ''; |
/** |
* Array containing the pages. |
* |
* @var array |
*/ |
var $_pages = array(); |
/** |
* Current document state. |
* 0 - initial state |
* 1 - document opened |
* 2 - page opened |
* 3 - document closed |
* |
* @var integer |
*/ |
var $_state = 0; |
/** |
* Flag indicating if PDF file is to be compressed or not. |
* |
* @var boolean |
*/ |
var $_compress; |
/** |
* The default page orientation. |
* |
* @var string |
*/ |
var $_default_orientation; |
/** |
* The current page orientation. |
* |
* @var string |
*/ |
var $_current_orientation; |
/** |
* Array indicating orientation changes. |
* |
* @var array |
*/ |
var $_orientation_changes = array(); |
/** |
* Current width of page format in points. |
* |
* @var float |
*/ |
var $fwPt; |
/** |
* Current height of page format in points. |
* |
* @var float |
*/ |
var $fhPt; |
/** |
* Current width of page format in user units. |
* |
* @var float |
*/ |
var $fw; |
/** |
* Current height of page format in user units. |
* |
* @var float |
*/ |
var $fh; |
/** |
* Current width of page in points. |
* |
* @var float |
*/ |
var $wPt; |
/** |
* Current height of page in points. |
* |
* @var float |
*/ |
var $hPt; |
/** |
* Current width of page in user units |
* |
* @var float |
*/ |
var $w; |
/** |
* Current height of page in user units |
* |
* @var float |
*/ |
var $h; |
/** |
* Scale factor (number of points in user units). |
* |
* @var float |
*/ |
var $_scale; |
/** |
* Left page margin size. |
* |
* @var float |
*/ |
var $_left_margin; |
/** |
* Top page margin size. |
* |
* @var float |
*/ |
var $_top_margin; |
/** |
* Right page margin size. |
* |
* @var float |
*/ |
var $_right_margin; |
/** |
* Break page margin size, the bottom margin which triggers a page break. |
* |
* @var float |
*/ |
var $_break_margin; |
/** |
* Cell margin size. |
* |
* @var float |
*/ |
var $_cell_margin; |
/** |
* The current horizontal position for cell positioning. |
* Value is set in user units and is calculated from the top left corner |
* as origin. |
* |
* @var float |
*/ |
var $x; |
/** |
* The current vertical position for cell positioning. |
* Value is set in user units and is calculated from the top left corner |
* as origin. |
* |
* @var float |
*/ |
var $y; |
/** |
* The height of the last cell printed. |
* |
* @var float |
*/ |
var $_last_height; |
/** |
* Line width in user units. |
* |
* @var float |
*/ |
var $_line_width; |
/** |
* An array of standard font names. |
* |
* @var array |
*/ |
var $_core_fonts = array('courier' => 'Courier', |
'courierB' => 'Courier-Bold', |
'courierI' => 'Courier-Oblique', |
'courierBI' => 'Courier-BoldOblique', |
'helvetica' => 'Helvetica', |
'helveticaB' => 'Helvetica-Bold', |
'helveticaI' => 'Helvetica-Oblique', |
'helveticaBI' => 'Helvetica-BoldOblique', |
'times' => 'Times-Roman', |
'timesB' => 'Times-Bold', |
'timesI' => 'Times-Italic', |
'timesBI' => 'Times-BoldItalic', |
'symbol' => 'Symbol', |
'zapfdingbats' => 'ZapfDingbats'); |
/** |
* An array of used fonts. |
* |
* @var array |
*/ |
var $_fonts = array(); |
/** |
* An array of font files. |
* |
* @var array |
*/ |
var $_font_files = array(); |
/** |
* An array of encoding differences. |
* |
* @var array |
*/ |
var $_diffs = array(); |
/** |
* An array of used images. |
* |
* @var array |
*/ |
var $_images = array(); |
/** |
* An array of links in pages. |
* |
* @var array |
*/ |
var $_page_links; |
/** |
* An array of internal links. |
* |
* @var array |
*/ |
var $_links = array(); |
/** |
* Current font family. |
* |
* @var string |
*/ |
var $_font_family = ''; |
/** |
* Current font style. |
* |
* @var string |
*/ |
var $_font_style = ''; |
/** |
* Underlining flag. |
* |
* @var boolean |
*/ |
var $_underline = false; |
/** |
* An array containing current font info. |
* |
* @var array |
*/ |
var $_current_font; |
/** |
* Current font size in points. |
* |
* @var float |
*/ |
var $_font_size_pt = 12; |
/** |
* Current font size in user units. |
* |
* @var float |
*/ |
var $_font_size; |
/** |
* Commands for filling color. |
* |
* @var string |
*/ |
var $_fill_color = '0 g'; |
/** |
* Commands for text color. |
* |
* @var string |
*/ |
var $_text_color = '0 g'; |
/** |
* Whether text color is different from fill color. |
* |
* @var boolean |
*/ |
var $_color_flag = false; |
/** |
* Commands for drawing color. |
* |
* @var string |
*/ |
var $_draw_color = '0 G'; |
/** |
* Word spacing. |
* |
* @var integer |
*/ |
var $_word_spacing = 0; |
/** |
* Automatic page breaking. |
* |
* @var boolean |
*/ |
var $_auto_page_break; |
/** |
* Threshold used to trigger page breaks. |
* |
* @var float |
*/ |
var $_page_break_trigger; |
/** |
* Flag set when processing footer. |
* |
* @var boolean |
*/ |
var $_in_footer = false; |
/** |
* Zoom display mode. |
* |
* @var string |
*/ |
var $_zoom_mode; |
/** |
* Layout display mode. |
* |
* @var string |
*/ |
var $_layout_mode; |
/** |
* An array containing the document info, consisting of: |
* - title |
* - subject |
* - author |
* - keywords |
* - creator |
* |
* @var array |
*/ |
var $_info = array(); |
/** |
* Alias for total number of pages. |
* |
* @var string |
*/ |
var $_alias_nb_pages = '{nb}'; |
/** |
* Attempts to return a conrete PDF instance. It allows to set up the page |
* format, the orientation and the units of measurement used in all the |
* methods (except for the font sizes). |
* |
* Example:<pre> |
* $pdf = &File_PDF::factory(array('orientation' => 'P', |
* 'unit' => 'mm', |
* 'format' => 'A4'));</pre> |
* |
* @param array $params A hash with parameters for the created PDF object. |
* Possible parameters are: |
* orientation - Default page orientation. Possible |
* values are (case insensitive): |
* <pre> |
* - P or Portrait (default) |
* - L or Landscape |
* </pre> |
* unit - User measure units. Possible values values |
* are: |
* <pre> |
* - pt: point |
* - mm: millimeter (default) |
* - cm: centimeter |
* - in: inch |
* </pre> |
* A point equals 1/72 of inch, that is to say about |
* 0.35 mm (an inch being 2.54 cm). This is a very |
* common unit in typography; font sizes are |
* expressed in that unit. |
* format - The format used for pages. It can be |
* either one of the following values (case |
* insensitive): |
* <pre> |
* - A3 |
* - A4 (default) |
* - A5 |
* - Letter |
* - Legal |
* </pre> |
* or a custom format in the form of a two-element |
* array containing the width and the height |
* (expressed in the unit given by the unit |
* parameter). |
* @param string $class The concrete class name to return an instance of. |
* Defaults to File_PDF. |
*/ |
function &factory($params = array(), $class = 'File_PDF') |
{ |
/* Check for PHP locale-related bug. */ |
if (1.1 == 1) { |
$error = File_PDF::raiseError('Do not alter the locale before including the class file.'); |
return $error; |
} |
/* Default parameters. */ |
$defaults = array('orientation' => 'P', 'unit' => 'mm', 'format' => 'A4'); |
/* Backward compatibility with old method signature. */ |
/* Should be removed a few versions later. */ |
if (!is_array($params)) { |
$class = 'File_PDF'; |
$params = $defaults; |
$names = array_keys($defaults); |
for ($i = 0; $i < func_num_args(); $i++) { |
$params[$names[$i]] = func_get_arg($i); |
} |
} else { |
$params = array_merge($defaults, $params); |
} |
/* Create the PDF object. */ |
$pdf = &new $class(); |
/* Scale factor. */ |
if ($params['unit'] == 'pt') { |
$pdf->_scale = 1; |
} elseif ($params['unit'] == 'mm') { |
$pdf->_scale = 72 / 25.4; |
} elseif ($params['unit'] == 'cm') { |
$pdf->_scale = 72 / 2.54; |
} elseif ($params['unit'] == 'in') { |
$pdf->_scale = 72; |
} else { |
$error = File_PDF::raiseError(sprintf('Incorrect units: %s', $params['unit'])); |
return $error; |
} |
/* Page format. */ |
if (is_string($params['format'])) { |
$params['format'] = strtolower($params['format']); |
if ($params['format'] == 'a3') { |
$params['format'] = array(841.89, 1190.55); |
} elseif ($params['format'] == 'a4') { |
$params['format'] = array(595.28, 841.89); |
} elseif ($params['format'] == 'a5') { |
$params['format'] = array(420.94, 595.28); |
} elseif ($params['format'] == 'letter') { |
$params['format'] = array(612, 792); |
} elseif ($params['format'] == 'legal') { |
$params['format'] = array(612, 1008); |
} else { |
$error = File_PDF::raiseError(sprintf('Unknown page format: %s', $params['format'])); |
return $error; |
} |
$pdf->fwPt = $params['format'][0]; |
$pdf->fhPt = $params['format'][1]; |
} else { |
$pdf->fwPt = $params['format'][0] * $pdf->_scale; |
$pdf->fhPt = $params['format'][1] * $pdf->_scale; |
} |
$pdf->fw = $pdf->fwPt / $pdf->_scale; |
$pdf->fh = $pdf->fhPt / $pdf->_scale; |
/* Page orientation. */ |
$params['orientation'] = strtolower($params['orientation']); |
if ($params['orientation'] == 'p' || $params['orientation'] == 'portrait') { |
$pdf->_default_orientation = 'P'; |
$pdf->wPt = $pdf->fwPt; |
$pdf->hPt = $pdf->fhPt; |
} elseif ($params['orientation'] == 'l' || $params['orientation'] == 'landscape') { |
$pdf->_default_orientation = 'L'; |
$pdf->wPt = $pdf->fhPt; |
$pdf->hPt = $pdf->fwPt; |
} else { |
$error = File_PDF::raiseError(sprintf('Incorrect orientation: %s', $params['orientation'])); |
return $error; |
} |
$pdf->_current_orientation = $pdf->_default_orientation; |
$pdf->w = $pdf->wPt / $pdf->_scale; |
$pdf->h = $pdf->hPt / $pdf->_scale; |
/* Page margins (1 cm) */ |
$margin = 28.35 / $pdf->_scale; |
$pdf->setMargins($margin, $margin); |
/* Interior cell margin (1 mm) */ |
$pdf->_cell_margin = $margin / 10; |
/* Line width (0.2 mm) */ |
$pdf->_line_width = .567 / $pdf->_scale; |
/* Automatic page break */ |
$pdf->setAutoPageBreak(true, 2 * $margin); |
/* Full width display mode */ |
$pdf->setDisplayMode('fullwidth'); |
/* Compression */ |
$pdf->setCompression(true); |
return $pdf; |
} |
/** |
* Returns a PEAR_Error object. Wraps around PEAR::raiseError() to |
* avoid having to include PEAR.php unless an error occurs. |
* |
* @param mixed $error The error message. |
* |
* @return object PEAR_Error |
*/ |
function raiseError($error) |
{ |
require_once 'PEAR.php'; |
return PEAR::raiseError($error); |
} |
/** |
* Defines the left, top and right margins. By default, they equal 1 cm. |
* Call this method to change them. |
* |
* @param float $left Left margin. |
* @param float $top Top margin. |
* @param float $right Right margin. If not specified default to the value |
* of the left one. |
* |
* @see File_PDF::setAutoPageBreak |
* @see File_PDF::setLeftMargin |
* @see File_PDF::setRightMargin |
* @see File_PDF::setTopMargin |
*/ |
function setMargins($left, $top, $right = null) |
{ |
/* Set left and top margins. */ |
$this->_left_margin = $left; |
$this->_top_margin = $top; |
/* If no right margin set default to same as left. */ |
$this->_right_margin = (is_null($right) ? $left : $right); |
} |
/** |
* Defines the left margin. The method can be called before creating the |
* first page. |
* If the current abscissa gets out of page, it is brought back to the |
* margin. |
* |
* @param float $margin The margin. |
* |
* @see File_PDF::setAutoPageBreak |
* @see File_PDF::setMargins |
* @see File_PDF::setRightMargin |
* @see File_PDF::setTopMargin |
*/ |
function setLeftMargin($margin) |
{ |
$this->_left_margin = $margin; |
/* If there is a current page and the current X position is less than |
* margin set the X position to the margin value. */ |
if ($this->_page > 0 && $this->x < $margin) { |
$this->x = $margin; |
} |
} |
/** |
* Defines the top margin. The method can be called before creating the |
* first page. |
* |
* @param float $margin The margin. |
*/ |
function setTopMargin($margin) |
{ |
$this->_top_margin = $margin; |
} |
/** |
* Defines the right margin. The method can be called before creating the |
* first page. |
* |
* @param float $margin The margin. |
*/ |
function setRightMargin($margin) |
{ |
$this->_right_margin = $margin; |
} |
/** |
* Returns the actual page width. |
* |
* @since File_PDF 0.2.0 |
* @since Horde 3.2 |
* |
* @return float The page width. |
*/ |
function getPageWidth() |
{ |
return ($this->w - $this->_right_margin - $this->_left_margin); |
} |
/** |
* Returns the actual page height. |
* |
* @since File_PDF 0.2.0 |
* @since Horde 3.2 |
* |
* @return float The page height. |
*/ |
function getPageHeight() |
{ |
return ($this->h - $this->_top_margin - $this->_break_margin); |
} |
/** |
* Enables or disables the automatic page breaking mode. When enabling, |
* the second parameter is the distance from the bottom of the page that |
* defines the triggering limit. By default, the mode is on and the margin |
* is 2 cm. |
* |
* @param boolean auto Boolean indicating if mode should be on or off. |
* @param float $margin Distance from the bottom of the page. |
*/ |
function setAutoPageBreak($auto, $margin = 0) |
{ |
$this->_auto_page_break = $auto; |
$this->_break_margin = $margin; |
$this->_page_break_trigger = $this->h - $margin; |
} |
/** |
* Defines the way the document is to be displayed by the viewer. The zoom |
* level can be set: pages can be displayed entirely on screen, occupy the |
* full width of the window, use real size, be scaled by a specific |
* zooming factor or use viewer default (configured in the Preferences |
* menu of Acrobat). The page layout can be specified too: single at once, |
* continuous display, two columns or viewer default. |
* By default, documents use the full width mode with continuous display. |
* |
* @param mixed $zoom The zoom to use. It can be one of the |
* following string values: |
* - fullpage: entire page on screen |
* - fullwidth: maximum width of window |
* - real: uses real size (100% zoom) |
* - default: uses viewer default mode |
* or a number indicating the zooming factor. |
* @param string layout The page layout. Possible values are: |
* - single: one page at once |
* - continuous: pages in continuously |
* - two: two pages on two columns |
* - default: uses viewer default mode |
* Default value is continuous. |
*/ |
function setDisplayMode($zoom, $layout = 'continuous') |
{ |
$zoom = strtolower($zoom); |
if ($zoom == 'fullpage' || $zoom == 'fullwidth' || $zoom == 'real' |
|| $zoom == 'default' || !is_string($zoom)) { |
$this->_zoom_mode = $zoom; |
} elseif ($zoom == 'zoom') { |
$this->_zoom_mode = $layout; |
} else { |
return $this->raiseError(sprintf('Incorrect zoom display mode: %s', $zoom)); |
} |
$layout = strtolower($layout); |
if ($layout == 'single' || $layout == 'continuous' || $layout == 'two' |
|| $layout == 'default') { |
$this->_layout_mode = $layout; |
} elseif ($zoom != 'zoom') { |
return $this->raiseError(sprintf('Incorrect layout display mode: %s', $layout)); |
} |
} |
/** |
* Activates or deactivates page compression. When activated, the internal |
* representation of each page is compressed, which leads to a compression |
* ratio of about 2 for the resulting document. |
* Compression is on by default. |
* Note: the Zlib extension is required for this feature. If not present, |
* compression will be turned off. |
* |
* @param boolean $compress Boolean indicating if compression must be |
* enabled or not. |
*/ |
function setCompression($compress) |
{ |
/* If no gzcompress function is available then default to false. */ |
$this->_compress = (function_exists('gzcompress') ? $compress : false); |
} |
/** |
* Set the info to a document. Possible info settings are: |
* - title |
* - subject |
* - author |
* - keywords |
* - creator |
* |
* @param mixed $info If passed as an array then the complete hash |
* containing the info to be inserted into the |
* document. Otherwise the name of setting to be set. |
* @param string $value The value of the setting. |
*/ |
function setInfo($info, $value = '') |
{ |
if (is_array($info)) { |
$this->_info = $info; |
} else { |
$this->_info[$info] = $value; |
} |
} |
/** |
* Defines an alias for the total number of pages. It will be substituted |
* as the document is closed. |
* |
* Example: |
* class My_File_PDF extends File_PDF { |
* function footer() |
* { |
* // Go to 1.5 cm from bottom |
* $this->setY(-15); |
* // Select Arial italic 8 |
* $this->setFont('Arial', 'I', 8); |
* // Print current and total page numbers |
* $this->cell(0, 10, 'Page ' . $this->getPageNo() . '/{nb}', 0, |
* 0, 'C'); |
* } |
* } |
* $pdf = &My_File_PDF::factory(); |
* $pdf->aliasNbPages(); |
* |
* @param string $alias The alias. Default value: {nb}. |
* |
* @see File_PDF::getPageNo |
* @see File_PDF::footer |
*/ |
function aliasNbPages($alias = '{nb}') |
{ |
$this->_alias_nb_pages = $alias; |
} |
/** |
* This method begins the generation of the PDF document; it must be |
* called before any output commands. No page is created by this method, |
* therefore it is necessary to call File_PDF::addPage. |
* |
* @see File_PDF::addPage |
* @see File_PDF::close |
*/ |
function open() |
{ |
$this->_beginDoc(); |
} |
/** |
* Terminates the PDF document. It is not necessary to call this method |
* explicitly because File_PDF::output does it automatically. |
* If the document contains no page, File_PDF::addPage is called to prevent |
* from getting an invalid document. |
* |
* @see File_PDF::open |
* @see File_PDF::output |
*/ |
function close() |
{ |
/* Terminate document */ |
if ($this->_page == 0) { |
$this->addPage(); |
} |
/* Page footer */ |
$this->_in_footer = true; |
$this->footer(); |
$this->_in_footer = false; |
/* Close page */ |
$this->_endPage(); |
/* Close document */ |
$this->_endDoc(); |
} |
/** |
* Adds a new page to the document. If a page is already present, the |
* File_PDF::footer method is called first to output the footer. Then the |
* page is added, the current position set to the top-left corner according |
* to the left and top margins, and File_PDF::header is called to display |
* the header. |
* The font which was set before calling is automatically restored. There |
* is no need to call File_PDF::setFont again if you want to continue with |
* the same font. The same is true for colors and line width. |
* The origin of the coordinate system is at the top-left corner and |
* increasing ordinates go downwards. |
* |
* @param string $orientation Page orientation. Possible values |
* are (case insensitive): |
* - P or Portrait |
* - L or Landscape |
* The default value is the one passed to the |
* constructor. |
* |
* @see File_PDF::PDF |
* @see File_PDF::header |
* @see File_PDF::footer |
* @see File_PDF::setMargins |
*/ |
function addPage($orientation = '') |
{ |
/* For good measure make sure this is called. */ |
$this->_beginDoc(); |
/* Save style settings so that they are not overridden by footer(). */ |
$lw = $this->_line_width; |
$dc = $this->_draw_color; |
$fc = $this->_fill_color; |
$tc = $this->_text_color; |
$cf = $this->_color_flag; |
if ($this->_page > 0) { |
/* Page footer. */ |
$this->_in_footer = true; |
$this->footer(); |
$this->_in_footer = false; |
/* Close page. */ |
$this->_endPage(); |
} |
/* Start new page. */ |
$this->_beginPage($orientation); |
/* Set line cap style to square. */ |
$this->_out('2 J'); |
/* Set line width. */ |
$this->_line_width = $lw; |
$this->_out(sprintf('%.2f w', $lw * $this->_scale)); |
/* Set font for the beginning of the page. */ |
$font_family = null; |
if ($this->_font_family) { |
$font_family = $this->_font_family; |
$font_style = $this->_font_style . ($this->_underline ? 'U' : ''); |
$font_size = $this->_font_size_pt; |
$this->setFont($font_family, $font_style, $font_size); |
} |
/* Set colors. */ |
$this->_fill_color = $fc; |
/* Check if fill color has been set before this page. */ |
if ($this->_fill_color != '0 g') { |
$this->_out($this->_fill_color); |
} |
$this->_draw_color = $dc; |
/* Check if draw color has been set before this page. */ |
if ($this->_draw_color != '0 G') { |
$this->_out($this->_draw_color); |
} |
$this->_text_color = $tc; |
$this->_color_flag = $cf; |
/* Page header. */ |
$this->header(); |
/* Restore line width. */ |
if ($this->_line_width != $lw) { |
$this->_line_width = $lw; |
$this->_out(sprintf('%.2f w', $lw * $this->_scale)); |
} |
/* Make sure the font is set for this page as it was before the |
* header. */ |
if ($font_family) { |
$this->setFont($font_family, $font_style, $font_size, true); |
} |
/* Restore colors. */ |
if ($this->_draw_color != $dc) { |
$this->_draw_color = $dc; |
$this->_out($dc); |
} |
if ($this->_fill_color != $fc) { |
$this->_fill_color = $fc; |
$this->_out($fc); |
} |
$this->_text_color = $tc; |
$this->_color_flag = $cf; |
} |
/** |
* This method is used to render the page header. It is automatically |
* called by File_PDF::addPage and should not be called directly by the |
* application. The implementation in File_PDF:: is empty, so you have to |
* subclass it and override the method if you want a specific processing. |
* |
* Example: |
* |
* class My_File_PDF extends File_PDF { |
* function header() |
* { |
* // Select Arial bold 15 |
* $this->setFont('Arial', 'B', 15); |
* // Move to the right |
* $this->cell(80); |
* // Framed title |
* $this->cell(30, 10, 'Title', 1, 0, 'C'); |
* // Line break |
* $this->newLine(20); |
* } |
* } |
* |
* @see File_PDF::footer |
*/ |
function header() |
{ |
/* To be implemented in your own inherited class. */ |
} |
/** |
* This method is used to render the page footer. It is automatically |
* called by File_PDF::addPage and File_PDF::close and should not be called |
* directly by the application. The implementation in File_PDF:: is empty, |
* so you have to subclass it and override the method if you want a specific |
* processing. |
* |
* Example: |
* |
* class My_File_PDF extends File_PDF { |
* function footer() |
* { |
* // Go to 1.5 cm from bottom |
* $this->setY(-15); |
* // Select Arial italic 8 |
* $this->setFont('Arial', 'I', 8); |
* // Print centered page number |
* $this->cell(0, 10, 'Page ' . $this->getPageNo(), 0, 0, 'C'); |
* } |
* } |
* |
* @see File_PDF::header |
*/ |
function footer() |
{ |
/* To be implemented in your own inherited class. */ |
} |
/** |
* Returns the current page number. |
* |
* @return integer |
* |
* @see File_PDF::aliasNbPages |
*/ |
function getPageNo() |
{ |
return $this->_page; |
} |
/** |
* Sets the fill color. |
* |
* Depending on the colorspace called, the number of color component |
* parameters required can be either 1, 3 or 4. The method can be called |
* before the first page is created and the color is retained from page to |
* page. |
* |
* @param string $cs Indicates the colorspace which can be either 'rgb', |
* 'cmyk' or 'gray'. Defaults to 'rgb'. |
* @param float $c1 First color component, floating point value between 0 |
* and 1. Required for gray, rgb and cmyk. |
* @param float $c2 Second color component, floating point value between |
* 0 and 1. Required for rgb and cmyk. |
* @param float $c3 Third color component, floating point value between |
* 0 and 1. Required for rgb and cmyk. |
* @param float $c4 Fourth color component, floating point value between |
* 0 and 1. Required for cmyk. |
* |
* @see File_PDF::setTextColor |
* @see File_PDF::setDrawColor |
* @see File_PDF::rect |
* @see File_PDF::cell |
* @see File_PDF::multiCell |
*/ |
function setFillColor($cs = 'rgb', $c1, $c2 = 0, $c3 = 0, $c4 = 0) |
{ |
$cs = strtolower($cs); |
if ($cs == 'rgb') { |
$this->_fill_color = sprintf('%.3f %.3f %.3f rg', $c1, $c2, $c3); |
} elseif ($cs == 'cmyk') { |
$this->_fill_color = sprintf('%.3f %.3f %.3f %.3f k', $c1, $c2, $c3, $c4); |
} else { |
$this->_fill_color = sprintf('%.3f g', $c1); |
} |
if ($this->_page > 0) { |
$this->_out($this->_fill_color); |
} |
$this->_color_flag = $this->_fill_color != $this->_text_color; |
} |
/** |
* Sets the text color. |
* |
* Depending on the colorspace called, the number of color component |
* parameters required can be either 1, 3 or 4. The method can be called |
* before the first page is created and the color is retained from page to |
* page. |
* |
* @param string $cs Indicates the colorspace which can be either 'rgb', |
* 'cmyk' or 'gray'. Defaults to 'rgb'. |
* @param float $c1 First color component, floating point value between 0 |
* and 1. Required for gray, rgb and cmyk. |
* @param float $c2 Second color component, floating point value between |
* 0 and 1. Required for rgb and cmyk. |
* @param float $c3 Third color component, floating point value between |
* 0 and 1. Required for rgb and cmyk. |
* @param float $c4 Fourth color component, floating point value between |
* 0 and 1. Required for cmyk. |
* |
* @since File_PDF 0.2.0 |
* @since Horde 3.2 |
* @see File_PDF::setFillColor |
* @see File_PDF::setDrawColor |
* @see File_PDF::rect |
* @see File_PDF::cell |
* @see File_PDF::multiCell |
*/ |
function setTextColor($cs = 'rgb', $c1, $c2 = 0, $c3 = 0, $c4 = 0) |
{ |
$cs = strtolower($cs); |
if ($cs == 'rgb') { |
$this->_text_color = sprintf('%.3f %.3f %.3f rg', $c1, $c2, $c3); |
} elseif ($cs == 'cmyk') { |
$this->_text_color = sprintf('%.3f %.3f %.3f %.3f k', $c1, $c2, $c3, $c4); |
} else { |
$this->_text_color = sprintf('%.3f g', $c1); |
} |
if ($this->_page > 0) { |
$this->_out($this->_text_color); |
} |
$this->_color_flag = $this->_fill_color != $this->_text_color; |
} |
/** |
* Sets the draw color, used when drawing lines. Depending on the |
* colorspace called, the number of color component parameters required |
* can be either 1, 3 or 4. The method can be called before the first page |
* is created and the color is retained from page to page. |
* |
* @param string $cs Indicates the colorspace which can be either 'rgb', |
* 'cmyk' or 'gray'. Defaults to 'rgb'. |
* @param float $c1 First color component, floating point value between 0 |
* and 1. Required for gray, rgb and cmyk. |
* @param float $c2 Second color component, floating point value between |
* 0 and 1. Required for rgb and cmyk. |
* @param float $c3 Third color component, floating point value between 0 |
* and 1. Required for rgb and cmyk. |
* @param float $c4 Fourth color component, floating point value between |
* 0 and 1. Required for cmyk. |
* |
* @see File_PDF::setFillColor |
* @see File_PDF::line |
* @see File_PDF::rect |
* @see File_PDF::cell |
* @see File_PDF::multiCell |
*/ |
function setDrawColor($cs = 'rgb', $c1, $c2 = 0, $c3 = 0, $c4 = 0) |
{ |
$cs = strtolower($cs); |
if ($cs == 'rgb') { |
$this->_draw_color = sprintf('%.3f %.3f %.3f RG', $c1, $c2, $c3); |
} elseif ($cs == 'cmyk') { |
$this->_draw_color = sprintf('%.3f %.3f %.3f %.3f K', $c1, $c2, $c3, $c4); |
} else { |
$this->_draw_color = sprintf('%.3f G', $c1); |
} |
if ($this->_page > 0) { |
$this->_out($this->_draw_color); |
} |
} |
/** |
* Returns the length of a text string. A font must be selected. |
* |
* @param string $text The text whose length is to be computed. |
* @param boolean $pt Boolean to indicate if the width should be returned |
* in points or user units. Default is 'false'. |
* |
* @return float |
*/ |
function getStringWidth($text, $pt = false) |
{ |
$text = (string)$text; |
$width = 0; |
$length = strlen($text); |
for ($i = 0; $i < $length; $i++) { |
$width += $this->_current_font['cw'][$text{$i}]; |
} |
/* Adjust for word spacing. */ |
$width += $this->_word_spacing * substr_count($text, ' ') * $this->_current_font['cw'][' ']; |
if ($pt) { |
return $width * $this->_font_size_pt / 1000; |
} else { |
return $width * $this->_font_size / 1000; |
} |
} |
/** |
* Defines the line width. By default, the value equals 0.2 mm. The method |
* can be called before the first page is created and the value is |
* retained from page to page. |
* |
* @param float $width The width. |
* |
* @see File_PDF::line |
* @see File_PDF::rect |
* @see File_PDF::cell |
* @see File_PDF::multiCell |
*/ |
function setLineWidth($width) |
{ |
$this->_line_width = $width; |
if ($this->_page > 0) { |
$this->_out(sprintf('%.2f w', $width * $this->_scale)); |
} |
} |
/** |
* Draws a line between two points. |
* |
* All coordinates can be negative to provide values from the right or |
* bottom edge of the page (since File_PDF 0.2.0, Horde 3.2). |
* |
* @param float $x1 Abscissa of first point. |
* @param float $y1 Ordinate of first point. |
* @param float $x2 Abscissa of second point. |
* @param float $y2 Ordinate of second point. |
* |
* @see File_PDF::setLineWidth |
* @see File_PDF::setDrawColor. |
*/ |
function line($x1, $y1, $x2, $y2) |
{ |
if ($x1 < 0) { |
$x1 += $this->w; |
} |
if ($y1 < 0) { |
$y1 += $this->h; |
} |
if ($x2 < 0) { |
$x2 += $this->w; |
} |
if ($y2 < 0) { |
$y2 += $this->h; |
} |
$this->_out(sprintf('%.2f %.2f m %.2f %.2f l S', $x1 * $this->_scale, ($this->h - $y1) * $this->_scale, $x2 * $this->_scale, ($this->h - $y2) * $this->_scale)); |
} |
/** |
* Outputs a rectangle. It can be drawn (border only), filled (with no |
* border) or both. |
* |
* All coordinates can be negative to provide values from the right or |
* bottom edge of the page (since File_PDF 0.2.0, Horde 3.2). |
* |
* @param float $x Abscissa of upper-left corner. |
* @param float $y Ordinate of upper-left corner. |
* @param float $width Width. |
* @param float $height Height. |
* @param float $style Style of rendering. Possible values are: |
* - D or empty string: draw (default) |
* - F: fill |
* - DF or FD: draw and fill |
* |
* @see File_PDF::setLineWidth |
* @see File_PDF::setDrawColor |
* @see File_PDF::setFillColor |
*/ |
function rect($x, $y, $width, $height, $style = '') |
{ |
if ($x < 0) { |
$x += $this->w; |
} |
if ($y < 0) { |
$y += $this->h; |
} |
$style = strtoupper($style); |
if ($style == 'F') { |
$op = 'f'; |
} elseif ($style == 'FD' || $style == 'DF') { |
$op = 'B'; |
} else { |
$op = 'S'; |
} |
$x = $this->_toPt($x); |
$y = $this->_toPt($y); |
$width = $this->_toPt($width); |
$height = $this->_toPt($height); |
$this->_out(sprintf('%.2f %.2f %.2f %.2f re %s', $x, $this->hPt - $y, $width, -$height, $op)); |
} |
/** |
* Outputs a circle. It can be drawn (border only), filled (with no |
* border) or both. |
* |
* All coordinates can be negative to provide values from the right or |
* bottom edge of the page (since File_PDF 0.2.0, Horde 3.2). |
* |
* @param float $x Abscissa of the center of the circle. |
* @param float $y Ordinate of the center of the circle. |
* @param float $r Circle radius. |
* @param string $style Style of rendering. Possible values are: |
* - D or empty string: draw (default) |
* - F: fill |
* - DF or FD: draw and fill |
*/ |
function circle($x, $y, $r, $style = '') |
{ |
if ($x < 0) { |
$x += $this->w; |
} |
if ($y < 0) { |
$y += $this->h; |
} |
$style = strtolower($style); |
if ($style == 'f') { |
$op = 'f'; // Style is fill only. |
} elseif ($style == 'fd' || $style == 'df') { |
$op = 'B'; // Style is fill and stroke. |
} else { |
$op = 'S'; // Style is stroke only. |
} |
$x = $this->_toPt($x); |
$y = $this->_toPt($y); |
$r = $this->_toPt($r); |
/* Invert the y scale. */ |
$y = $this->hPt - $y; |
/* Length of the Bezier control. */ |
$b = $r * 0.552; |
/* Move from the given origin and set the current point |
* to the start of the first Bezier curve. */ |
$c = sprintf('%.2f %.2f m', $x - $r, $y); |
$x = $x - $r; |
/* First circle quarter. */ |
$c .= sprintf(' %.2f %.2f %.2f %.2f %.2f %.2f c', |
$x, $y + $b, // First control point. |
$x + $r - $b, $y + $r, // Second control point. |
$x + $r, $y + $r); // Final point. |
/* Set x/y to the final point. */ |
$x = $x + $r; |
$y = $y + $r; |
/* Second circle quarter. */ |
$c .= sprintf(' %.2f %.2f %.2f %.2f %.2f %.2f c', |
$x + $b, $y, |
$x + $r, $y - $r + $b, |
$x + $r, $y - $r); |
/* Set x/y to the final point. */ |
$x = $x + $r; |
$y = $y - $r; |
/* Third circle quarter. */ |
$c .= sprintf(' %.2f %.2f %.2f %.2f %.2f %.2f c', |
$x, $y - $b, |
$x - $r + $b, $y - $r, |
$x - $r, $y - $r); |
/* Set x/y to the final point. */ |
$x = $x - $r; |
$y = $y - $r; |
/* Fourth circle quarter. */ |
$c .= sprintf(' %.2f %.2f %.2f %.2f %.2f %.2f c %s', |
$x - $b, $y, |
$x - $r, $y + $r - $b, |
$x - $r, $y + $r, |
$op); |
/* Output the whole string. */ |
$this->_out($c); |
} |
/** |
* Imports a TrueType or Type1 font and makes it available. It is |
* necessary to generate a font definition file first with the |
* makefont.php utility. |
* The location of the definition file (and the font file itself when |
* embedding) must be found at the full path name included. |
* |
* Example: |
* $pdf->addFont('Comic', 'I'); |
* is equivalent to: |
* $pdf->addFont('Comic', 'I', 'comici.php'); |
* |
* @param string $family Font family. The name can be chosen arbitrarily. |
* If it is a standard family name, it will |
* override the corresponding font. |
* @param string $style Font style. Possible values are (case |
* insensitive): |
* - empty string: regular (default) |
* - B: bold |
* - I: italic |
* - BI or IB: bold italic |
* @param string $file The font definition file. By default, the name is |
* built from the family and style, in lower case |
* with no space. |
* |
* @see File_PDF::setFont |
*/ |
function addFont($family, $style = '', $file = '') |
{ |
$family = strtolower($family); |
if ($family == 'arial') { |
$family = 'helvetica'; |
} |
$style = strtoupper($style); |
if ($style == 'IB') { |
$style = 'BI'; |
} |
if (isset($this->_fonts[$family . $style])) { |
return $this->raiseError(sprintf('Font already added: %s %s', $family, $style)); |
} |
if ($file == '') { |
$file = str_replace(' ', '', $family) . strtolower($style) . '.php'; |
} |
include($file); |
if (!isset($name)) { |
return $this->raiseError('Could not include font definition file.'); |
} |
$i = count($this->_fonts) + 1; |
$this->_fonts[$family . $style] = array('i' => $i, 'type' => $type, 'name' => $name, 'desc' => $desc, 'up' => $up, 'ut' => $ut, 'cw' => $cw, 'enc' => $enc, 'file' => $file); |
if ($diff) { |
/* Search existing encodings. */ |
$d = 0; |
$nb = count($this->_diffs); |
for ($i = 1; $i <= $nb; $i++) { |
if ($this->_diffs[$i] == $diff) { |
$d = $i; |
break; |
} |
} |
if ($d == 0) { |
$d = $nb + 1; |
$this->_diffs[$d] = $diff; |
} |
$this->_fonts[$family.$style]['diff'] = $d; |
} |
if ($file) { |
if ($type == 'TrueType') { |
$this->_font_files[$file] = array('length1' => $originalsize); |
} else { |
$this->_font_files[$file] = array('length1' => $size1, 'length2' => $size2); |
} |
} |
} |
/** |
* Sets the font used to print character strings. It is mandatory to call |
* this method at least once before printing text or the resulting |
* document would not be valid. The font can be either a standard one or a |
* font added via the File_PDF::addFont method. Standard fonts use Windows |
* encoding cp1252 (Western Europe). |
* The method can be called before the first page is created and the font |
* is retained from page to page. |
* If you just wish to change the current font size, it is simpler to call |
* File_PDF::setFontSize. |
* |
* @param string $family Family font. It can be either a name defined by |
* File_PDF::addFont or one of the standard families |
* (case insensitive): |
* - Courier (fixed-width) |
* - Helvetica or Arial (sans serif) |
* - Times (serif) |
* - Symbol (symbolic) |
* - ZapfDingbats (symbolic) |
* It is also possible to pass an empty string. In |
* that case, the current family is retained. |
* @param string $style Font style. Possible values are (case |
* insensitive): |
* - empty string: regular |
* - B: bold |
* - I: italic |
* - U: underline |
* or any combination. The default value is regular. |
* Bold and italic styles do not apply to Symbol and |
* ZapfDingbats. |
* @param integer $size Font size in points. The default value is the |
* current size. If no size has been specified since |
* the beginning of the document, the value taken |
* is 12. |
* @param boolean $force Force the setting of the font. Each new page will |
* require a new call to File_PDF::setFont and |
* settings this to true will make sure that the |
* checks for same font calls will be skipped. |
* |
* @see File_PDF::addFont |
* @see File_PDF::setFontSize |
* @see File_PDF::cell |
* @see File_PDF::multiCell |
* @see File_PDF::Write |
*/ |
function setFont($family, $style = '', $size = null, $force = false) |
{ |
$family = strtolower($family); |
if ($family == 'arial') { |
/* Use helvetica instead of arial. */ |
$family = 'helvetica'; |
} elseif ($family == 'symbol' || $family == 'zapfdingbats') { |
/* These two fonts do not have styles available. */ |
$style = ''; |
} |
$style = strtoupper($style); |
/* Underline is handled separately, if specified in the style var |
* remove it from the style and set the underline flag. */ |
if (strpos($style, 'U') !== false) { |
$this->_underline = true; |
$style = str_replace('U', '', $style); |
} else { |
$this->_underline = false; |
} |
if ($style == 'IB') { |
$style = 'BI'; |
} |
/* If no size specified, use current size. */ |
if (is_null($size)) { |
$size = $this->_font_size_pt; |
} |
/* If font requested is already the current font and no force setting |
* of the font is requested (eg. when adding a new page) don't bother |
* with the rest of the function and simply return. */ |
if ($this->_font_family == $family && $this->_font_style == $style && |
$this->_font_size_pt == $size && !$force) { |
return; |
} |
/* Set the font key. */ |
$fontkey = $family . $style; |
/* Test if already cached. */ |
if (!isset($this->_fonts[$fontkey])) { |
/* Get the character width definition file. */ |
$font_widths = &File_PDF::_getFontFile($fontkey); |
if (is_a($font_widths, 'PEAR_Error')) { |
return $font_widths; |
} |
$i = count($this->_fonts) + 1; |
$this->_fonts[$fontkey] = array( |
'i' => $i, |
'type' => 'core', |
'name' => $this->_core_fonts[$fontkey], |
'up' => -100, |
'ut' => 50, |
'cw' => $font_widths[$fontkey]); |
} |
/* Store font information as current font. */ |
$this->_font_family = $family; |
$this->_font_style = $style; |
$this->_font_size_pt = $size; |
$this->_font_size = $size / $this->_scale; |
$this->_current_font = &$this->_fonts[$fontkey]; |
/* Output font information if at least one page has been defined. */ |
if ($this->_page > 0) { |
$this->_out(sprintf('BT /F%d %.2f Tf ET', $this->_current_font['i'], $this->_font_size_pt)); |
} |
} |
/** |
* Defines the size of the current font. |
* |
* @param float $size The size (in points). |
* |
* @see File_PDF::setFont |
*/ |
function setFontSize($size) |
{ |
/* If the font size is already the current font size, just return. */ |
if ($this->_font_size_pt == $size) { |
return; |
} |
/* Set the current font size, both in points and scaled to user |
* units. */ |
$this->_font_size_pt = $size; |
$this->_font_size = $size / $this->_scale; |
/* Output font information if at least one page has been defined. */ |
if ($this->_page > 0) { |
$this->_out(sprintf('BT /F%d %.2f Tf ET', $this->_current_font['i'], $this->_font_size_pt)); |
} |
} |
/** |
* Defines the style of the current font. |
* |
* @param string $style The font style. |
* |
* @see File_PDF::setFont |
* @since File_PDF 0.2.0 |
* @since Horde 3.2 |
*/ |
function setFontStyle($style) |
{ |
$this->setFont($this->_font_family, $style); |
} |
/** |
* Creates a new internal link and returns its identifier. An internal |
* link is a clickable area which directs to another place within the |
* document. |
* The identifier can then be passed to File_PDF::cell, File_PDF::write, |
* File_PDF::image or File_PDF::link. The destination is defined with |
* File_PDF::setLink. |
* |
* @see File_PDF::cell |
* @see File_PDF::Write |
* @see File_PDF::image |
* @see File_PDF::Link |
* @see File_PDF::SetLink |
*/ |
function addLink() |
{ |
$n = count($this->_links) + 1; |
$this->_links[$n] = array(0, 0); |
return $n; |
} |
/** |
* Defines the page and position a link points to. |
* |
* @param integer $link The link identifier returned by File_PDF::addLink. |
* @param float $y Ordinate of target position; -1 indicates the |
* current position. The default value is 0 (top of |
* page). |
* @param integer $page Number of target page; -1 indicates the current |
* page. This is the default value. |
* |
* @see File_PDF::addLink |
*/ |
function setLink($link, $y = 0, $page = -1) |
{ |
if ($y == -1) { |
$y = $this->y; |
} |
if ($page == -1) { |
$page = $this->_page; |
} |
$this->_links[$link] = array($page, $y); |
} |
/** |
* Puts a link on a rectangular area of the page. Text or image links are |
* generally put via File_PDF::cell, File_PDF::Write or File_PDF::image, |
* but this method can be useful for instance to define a clickable area |
* inside an image. |
* |
* All coordinates can be negative to provide values from the right or |
* bottom edge of the page (since File_PDF 0.2.0, Horde 3.2). |
* |
* @param float $x Abscissa of the upper-left corner of the rectangle. |
* @param float $y Ordinate of the upper-left corner of the rectangle. |
* @param float $width Width of the rectangle. |
* @param float $height Height of the rectangle. |
* @param mixed $link URL or identifier returned by File_PDF::addLink. |
* |
* @see File_PDF::addLink |
* @see File_PDF::cell |
* @see File_PDF::Write |
* @see File_PDF::image |
*/ |
function link($x, $y, $width, $height, $link) |
{ |
if ($x < 0) { |
$x += $this->w; |
} |
if ($y < 0) { |
$y += $this->h; |
} |
/* Set up the coordinates with correct scaling in pt. */ |
$x = $this->_toPt($x); |
$y = $this->hPt - $this->_toPt($y); |
$width = $this->_toPt($width); |
$height = $this->_toPt($height); |
/* Save link to page links array. */ |
$this->_link($x, $y, $width, $height, $link); |
} |
/** |
* Prints a character string. The origin is on the left of the first |
* character, on the baseline. This method allows to place a string |
* precisely on the page, but it is usually easier to use File_PDF::cell, |
* File_PDF::multiCell or File_PDF::Write which are the standard methods to |
* print text. |
* |
* All coordinates can be negative to provide values from the right or |
* bottom edge of the page (since File_PDF 0.2.0, Horde 3.2). |
* |
* @param float $x Abscissa of the origin. |
* @param float $y Ordinate of the origin. |
* @param string $text String to print. |
* |
* @see File_PDF::setFont |
* @see File_PDF::cell |
* @see File_PDF::multiCell |
* @see File_PDF::Write |
*/ |
function text($x, $y, $text) |
{ |
if ($x < 0) { |
$x += $this->w; |
} |
if ($y < 0) { |
$y += $this->h; |
} |
/* Scale coordinates into points and set correct Y position. */ |
$x = $this->_toPt($x); |
$y = $this->hPt - $this->_toPt($y); |
/* Escape any potentially harmful characters. */ |
$text = $this->_escape($text); |
$out = sprintf('BT %.2f %.2f Td (%s) Tj ET', $x, $y, $text); |
if ($this->_underline && $text != '') { |
$out .= ' ' . $this->_doUnderline($x, $y, $text); |
} |
if ($this->_color_flag) { |
$out = sprintf('q %s %s Q', $this->_text_color, $out); |
} |
$this->_out($out); |
} |
/** |
* Whenever a page break condition is met, the method is called, and the |
* break is issued or not depending on the returned value. The default |
* implementation returns a value according to the mode selected by |
* File_PDF:setAutoPageBreak. |
* This method is called automatically and should not be called directly |
* by the application. |
* |
* @return boolean |
* |
* @see File_PDF::setAutoPageBreak. |
*/ |
function acceptPageBreak() |
{ |
return $this->_auto_page_break; |
} |
/** |
* Prints a cell (rectangular area) with optional borders, background |
* color and character string. The upper-left corner of the cell |
* corresponds to the current position. The text can be aligned or |
* centered. After the call, the current position moves to the right or to |
* the next line. It is possible to put a link on the text. |
* If automatic page breaking is enabled and the cell goes beyond the |
* limit, a page break is done before outputting. |
* |
* @param float $width Cell width. If 0, the cell extends up to the right |
* margin. |
* @param float $height Cell height. Default value: 0. |
* @param string $text String to print. Default value: empty. |
* @param mixed $border Indicates if borders must be drawn around the |
* cell. The value can be either a number: |
* - 0: no border (default) |
* - 1: frame |
* or a string containing some or all of the |
* following characters (in any order): |
* - L: left |
* - T: top |
* - R: right |
* - B: bottom |
* @param integer $ln Indicates where the current position should go |
* after the call. Possible values are: |
* - 0: to the right (default) |
* - 1: to the beginning of the next line |
* - 2: below |
* Putting 1 is equivalent to putting 0 and calling |
* File_PDF::newLine just after. |
* @param string $align Allows to center or align the text. Possible |
* values are: |
* - L or empty string: left (default) |
* - C: center |
* - R: right |
* @param integer $fill Indicates if the cell fill type. Possible values |
* are: |
* - 0: transparent (default) |
* - 1: painted |
* @param string $link URL or identifier returned by |
* File_PDF:addLink. |
* |
* @see File_PDF::setFont |
* @see File_PDF::setDrawColor |
* @see File_PDF::setFillColor |
* @see File_PDF::setLineWidth |
* @see File_PDF::addLink |
* @see File_PDF::newLine |
* @see File_PDF::multiCell |
* @see File_PDF::Write |
* @see File_PDF::setAutoPageBreak |
*/ |
function cell($width, $height = 0, $text = '', $border = 0, $ln = 0, |
$align = '', $fill = 0, $link = '') |
{ |
$k = $this->_scale; |
if ($this->y + $height > $this->_page_break_trigger && |
!$this->_in_footer && $this->AcceptPageBreak()) { |
$x = $this->x; |
$ws = $this->_word_spacing; |
if ($ws > 0) { |
$this->_word_spacing = 0; |
$this->_out('0 Tw'); |
} |
$this->addPage($this->_current_orientation); |
$this->x = $x; |
if ($ws > 0) { |
$this->_word_spacing = $ws; |
$this->_out(sprintf('%.3f Tw', $ws * $k)); |
} |
} |
if ($width == 0) { |
$width = $this->w - $this->_right_margin - $this->x; |
} |
$s = ''; |
if ($fill == 1 || $border == 1) { |
if ($fill == 1) { |
$op = ($border == 1) ? 'B' : 'f'; |
} else { |
$op = 'S'; |
} |
$s = sprintf('%.2f %.2f %.2f %.2f re %s ', $this->x * $k, ($this->h - $this->y) * $k, $width * $k, -$height * $k, $op); |
} |
if (is_string($border)) { |
if (strpos($border, 'L') !== false) { |
$s .= sprintf('%.2f %.2f m %.2f %.2f l S ', $this->x * $k, ($this->h - $this->y) * $k, $this->x * $k, ($this->h - ($this->y + $height)) * $k); |
} |
if (strpos($border, 'T') !== false) { |
$s .= sprintf('%.2f %.2f m %.2f %.2f l S ', $this->x * $k, ($this->h - $this->y) * $k, ($this->x + $width) * $k, ($this->h - $this->y) * $k); |
} |
if (strpos($border, 'R') !== false) { |
$s .= sprintf('%.2f %.2f m %.2f %.2f l S ', ($this->x + $width) * $k, ($this->h - $this->y) * $k, ($this->x + $width) * $k, ($this->h - ($this->y + $height)) * $k); |
} |
if (strpos($border, 'B') !== false) { |
$s .= sprintf('%.2f %.2f m %.2f %.2f l S ', $this->x * $k, ($this->h - ($this->y + $height)) * $k, ($this->x + $width) * $k, ($this->h - ($this->y + $height)) * $k); |
} |
} |
if ($text != '') { |
if ($align == 'R') { |
$dx = $width - $this->_cell_margin - $this->getStringWidth($text); |
} elseif ($align == 'C') { |
$dx = ($width - $this->getStringWidth($text)) / 2; |
} else { |
$dx = $this->_cell_margin; |
} |
if ($this->_color_flag) { |
$s .= 'q ' . $this->_text_color . ' '; |
} |
$text = str_replace(')', '\\)', str_replace('(', '\\(', str_replace('\\', '\\\\', $text))); |
$test2 = ((.5 * $height) + (.3 * $this->_font_size)); |
$test1 = $this->fhPt - (($this->y + $test2) * $k); |
$s .= sprintf('BT %.2f %.2f Td (%s) Tj ET', ($this->x + $dx) * $k, ($this->h - ($this->y + .5 * $height + .3 * $this->_font_size)) * $k, $text); |
if ($this->_underline) { |
$s .= ' ' . $this->_doUnderline($this->x + $dx, $this->y + .5 * $height + .3 * $this->_font_size, $text); |
} |
if ($this->_color_flag) { |
$s .= ' Q'; |
} |
if ($link) { |
$this->link($this->x + $dx, $this->y + .5 * $height-.5 * $this->_font_size, $this->getStringWidth($text), $this->_font_size, $link); |
} |
} |
if ($s) { |
$this->_out($s); |
} |
$this->_last_height = $height; |
if ($ln > 0) { |
/* Go to next line. */ |
$this->y += $height; |
if ($ln == 1) { |
$this->x = $this->_left_margin; |
} |
} else { |
$this->x += $width; |
} |
} |
/** |
* This method allows printing text with line breaks. They can be |
* automatic (as soon as the text reaches the right border of the cell) or |
* explicit (via the \n character). As many cells as necessary are output, |
* one below the other. |
* Text can be aligned, centered or justified. The cell block can be |
* framed and the background painted. |
* |
* @param float $width Width of cells. If 0, they extend up to the right |
* margin of the page. |
* @param float $height Height of cells. |
* @param string $text String to print. |
* @param mixed $border Indicates if borders must be drawn around the cell |
* block. The value can be either a number: |
* - 0: no border (default) |
* - 1: frame |
* or a string containing some or all of the |
* following characters (in any order): |
* - L: left |
* - T: top |
* - R: right |
* - B: bottom |
* @param string $align Sets the text alignment. Possible values are: |
* - L: left alignment |
* - C: center |
* - R: right alignment |
* - J: justification (default value) |
* @param integer $fill Indicates if the cell background must: |
* - 0: transparent (default) |
* - 1: painted |
* |
* @see File_PDF::setFont |
* @see File_PDF::setDrawColor |
* @see File_PDF::setFillColor |
* @see File_PDF::setLineWidth |
* @see File_PDF::cell |
* @see File_PDF::write |
* @see File_PDF::setAutoPageBreak |
*/ |
function multiCell($width, $height, $text, $border = 0, $align = 'J', |
$fill = 0) |
{ |
$cw = &$this->_current_font['cw']; |
if ($width == 0) { |
$width = $this->w - $this->_right_margin - $this->x; |
} |
$wmax = ($width-2 * $this->_cell_margin) * 1000 / $this->_font_size; |
$s = str_replace("\r", '', $text); |
$nb = strlen($s); |
if ($nb > 0 && $s[$nb-1] == "\n") { |
$nb--; |
} |
$b = 0; |
if ($border) { |
if ($border == 1) { |
$border = 'LTRB'; |
$b = 'LRT'; |
$b2 = 'LR'; |
} else { |
$b2 = ''; |
if (strpos($border, 'L') !== false) { |
$b2 .= 'L'; |
} |
if (strpos($border, 'R') !== false) { |
$b2 .= 'R'; |
} |
$b = (strpos($border, 'T') !== false) ? $b2 . 'T' : $b2; |
} |
} |
$sep = -1; |
$i = 0; |
$j = 0; |
$l = 0; |
$ns = 0; |
$nl = 1; |
while ($i < $nb) { |
/* Get next character. */ |
$c = $s[$i]; |
if ($c == "\n") { |
/* Explicit line break. */ |
if ($this->_word_spacing > 0) { |
$this->_word_spacing = 0; |
$this->_out('0 Tw'); |
} |
$this->cell($width, $height, substr($s, $j, $i-$j), $b, 2, $align, $fill); |
$i++; |
$sep = -1; |
$j = $i; |
$l = 0; |
$ns = 0; |
$nl++; |
if ($border && $nl == 2) { |
$b = $b2; |
} |
continue; |
} |
if ($c == ' ') { |
$sep = $i; |
$ls = $l; |
$ns++; |
} |
$l += $cw[$c]; |
if ($l > $wmax) { |
/* Automatic line break. */ |
if ($sep == -1) { |
if ($i == $j) { |
$i++; |
} |
if ($this->_word_spacing > 0) { |
$this->_word_spacing = 0; |
$this->_out('0 Tw'); |
} |
$this->cell($width, $height, substr($s, $j, $i - $j), $b, 2, $align, $fill); |
} else { |
if ($align == 'J') { |
$this->_word_spacing = ($ns>1) ? ($wmax - $ls)/1000 * $this->_font_size / ($ns - 1) : 0; |
$this->_out(sprintf('%.3f Tw', $this->_word_spacing * $this->_scale)); |
} |
$this->cell($width, $height, substr($s, $j, $sep - $j), $b, 2, $align, $fill); |
$i = $sep + 1; |
} |
$sep = -1; |
$j = $i; |
$l = 0; |
$ns = 0; |
$nl++; |
if ($border && $nl == 2) { |
$b = $b2; |
} |
} else { |
$i++; |
} |
} |
/* Last chunk. */ |
if ($this->_word_spacing > 0) { |
$this->_word_spacing = 0; |
$this->_out('0 Tw'); |
} |
if ($border && strpos($border, 'B') !== false) { |
$b .= 'B'; |
} |
$this->cell($width, $height, substr($s, $j, $i), $b, 2, $align, $fill); |
$this->x = $this->_left_margin; |
} |
/** |
* This method prints text from the current position. When the right |
* margin is reached (or the \n character is met) a line break occurs and |
* text continues from the left margin. Upon method exit, the current |
* position is left just at the end of the text. |
* It is possible to put a link on the text. |
* |
* Example: |
* //Begin with regular font |
* $pdf->setFont('Arial','',14); |
* $pdf->write(5,'Visit '); |
* //Then put a blue underlined link |
* $pdf->setTextColor(0,0,255); |
* $pdf->setFont('','U'); |
* $pdf->write(5,'www.fpdf.org','http://www.fpdf.org'); |
* |
* @param float $height Line height. |
* @param string $text String to print. |
* @param mixed $link URL or identifier returned by AddLink(). |
* |
* @see File_PDF::setFont |
* @see File_PDF::addLink |
* @see File_PDF::multiCell |
* @see File_PDF::setAutoPageBreak |
*/ |
function write($height, $text, $link = '') |
{ |
$cw = &$this->_current_font['cw']; |
$width = $this->w - $this->_right_margin - $this->x; |
$wmax = ($width - 2 * $this->_cell_margin) * 1000 / $this->_font_size; |
$s = str_replace("\r", '', $text); |
$nb = strlen($s); |
$sep = -1; |
$i = 0; |
$j = 0; |
$l = 0; |
$nl = 1; |
while ($i < $nb) { |
/* Get next character. */ |
$c = $s{$i}; |
if ($c == "\n") { |
/* Explicit line break. */ |
$this->cell($width, $height, substr($s, $j, $i - $j), 0, 2, '', 0, $link); |
$i++; |
$sep = -1; |
$j = $i; |
$l = 0; |
if ($nl == 1) { |
$this->x = $this->_left_margin; |
$width = $this->w - $this->_right_margin - $this->x; |
$wmax = ($width - 2 * $this->_cell_margin) * 1000 / $this->_font_size; |
} |
$nl++; |
continue; |
} |
if ($c == ' ') { |
$sep = $i; |
$ls = $l; |
} |
$l += (isset($cw[$c]) ? $cw[$c] : 0); |
if ($l > $wmax) { |
/* Automatic line break. */ |
if ($sep == -1) { |
if ($this->x > $this->_left_margin) { |
/* Move to next line. */ |
$this->x = $this->_left_margin; |
$this->y += $height; |
$width = $this->w - $this->_right_margin - $this->x; |
$wmax = ($width - 2 * $this->_cell_margin) * 1000 / $this->_font_size; |
$i++; |
$nl++; |
continue; |
} |
if ($i == $j) { |
$i++; |
} |
$this->cell($width, $height, substr($s, $j, $i - $j), 0, 2, '', 0, $link); |
} else { |
$this->cell($width, $height, substr($s, $j, $sep - $j), 0, 2, '', 0, $link); |
$i = $sep + 1; |
} |
$sep = -1; |
$j = $i; |
$l = 0; |
if ($nl == 1) { |
$this->x = $this->_left_margin; |
$width = $this->w - $this->_right_margin - $this->x; |
$wmax = ($width - 2 * $this->_cell_margin) * 1000 / $this->_font_size; |
} |
$nl++; |
} else { |
$i++; |
} |
} |
/* Last chunk. */ |
if ($i != $j) { |
$this->cell($l / 1000 * $this->_font_size, $height, substr($s, $j, $i), 0, 0, '', 0, $link); |
} |
} |
/** |
* Writes text at an angle. |
* |
* All coordinates can be negative to provide values from the right or |
* bottom edge of the page (since File_PDF 0.2.0, Horde 3.2). |
* |
* @param integer $x X coordinate. |
* @param integer $y Y coordinate. |
* @param string $text Text to write. |
* @param float $text_angle Angle to rotate (Eg. 90 = bottom to top). |
* @param float $font_angle Rotate characters as well as text. |
* |
* @see File_PDF::setFont |
*/ |
function writeRotated($x, $y, $text, $text_angle, $font_angle = 0) |
{ |
if ($x < 0) { |
$x += $this->w; |
} |
if ($y < 0) { |
$y += $this->h; |
} |
/* Escape text. */ |
$text = $this->_escape($text); |
$font_angle += 90 + $text_angle; |
$text_angle *= M_PI / 180; |
$font_angle *= M_PI / 180; |
$text_dx = cos($text_angle); |
$text_dy = sin($text_angle); |
$font_dx = cos($font_angle); |
$font_dy = sin($font_angle); |
$s= sprintf('BT %.2f %.2f %.2f %.2f %.2f %.2f Tm (%s) Tj ET', |
$text_dx, $text_dy, $font_dx, $font_dy, |
$x * $this->_scale, ($this->h-$y) * $this->_scale, $text); |
if ($this->_draw_color) { |
$s = 'q ' . $this->_draw_color . ' ' . $s . ' Q'; |
} |
$this->_out($s); |
} |
/** |
* Prints an image in the page. The upper-left corner and at least one of |
* the dimensions must be specified; the height or the width can be |
* calculated automatically in order to keep the image proportions. |
* Supported formats are JPEG and PNG. |
* |
* All coordinates can be negative to provide values from the right or |
* bottom edge of the page (since File_PDF 0.2.0, Horde 3.2). |
* |
* For JPEG, all flavors are allowed: |
* - gray scales |
* - true colors (24 bits) |
* - CMYK (32 bits) |
* |
* For PNG, are allowed: |
* - gray scales on at most 8 bits (256 levels) |
* - indexed colors |
* - true colors (24 bits) |
* but are not supported: |
* - Interlacing |
* - Alpha channel |
* |
* If a transparent color is defined, it will be taken into account (but |
* will be only interpreted by Acrobat 4 and above). |
* The format can be specified explicitly or inferred from the file |
* extension. |
* It is possible to put a link on the image. |
* |
* Remark: if an image is used several times, only one copy will be |
* embedded in the file. |
* |
* @param string $file Name of the file containing the image. |
* @param float $x Abscissa of the upper-left corner. |
* @param float $y Ordinate of the upper-left corner. |
* @param float $width Width of the image in the page. If equal to zero, |
* it is automatically calculated to keep the |
* original proportions. |
* @param float $height Height of the image in the page. If not specified |
* or equal to zero, it is automatically calculated |
* to keep the original proportions. |
* @param string $type Image format. Possible values are (case |
* insensitive) : JPG, JPEG, PNG. If not specified, |
* the type is inferred from the file extension. |
* @param mixed $link URL or identifier returned by File_PDF::addLink. |
* |
* @see File_PDF::addLink |
*/ |
function image($file, $x, $y, $width = 0, $height = 0, $type = '', |
$link = '') |
{ |
if ($x < 0) { |
$x += $this->w; |
} |
if ($y < 0) { |
$y += $this->h; |
} |
if (!isset($this->_images[$file])) { |
/* First use of image, get some file info. */ |
if ($type == '') { |
$pos = strrpos($file, '.'); |
if ($pos === false) { |
return $this->raiseError(sprintf('Image file has no extension and no type was specified: %s', $file)); |
} |
$type = substr($file, $pos + 1); |
} |
$type = strtolower($type); |
$mqr = get_magic_quotes_runtime(); |
set_magic_quotes_runtime(0); |
if ($type == 'jpg' || $type == 'jpeg') { |
$info = $this->_parseJPG($file); |
} elseif ($type == 'png') { |
$info = $this->_parsePNG($file); |
} else { |
return $this->raiseError(sprintf('Unsupported image file type: %s', $type)); |
} |
if (is_a($info, 'PEAR_Error')) { |
return $info; |
} |
set_magic_quotes_runtime($mqr); |
$info['i'] = count($this->_images) + 1; |
$this->_images[$file] = $info; |
} else { |
$info = $this->_images[$file]; |
} |
/* Make sure all vars are converted to pt scale. */ |
$x = $this->_toPt($x); |
$y = $this->_toPt($y); |
$width = $this->_toPt($width); |
$height = $this->_toPt($height); |
/* If not specified do automatic width and height calculations. */ |
if (empty($width) && empty($height)) { |
$width = $info['w']; |
$height = $info['h']; |
} elseif (empty($width)) { |
$width = $height * $info['w'] / $info['h']; |
} elseif (empty($height)) { |
$height = $width * $info['h'] / $info['w']; |
} |
$this->_out(sprintf('q %.2f 0 0 %.2f %.2f %.2f cm /I%d Do Q', $width, $height, $x, $this->hPt - ($y + $height), $info['i'])); |
/* Set any link if requested. */ |
if ($link) { |
$this->_link($x, $y, $width, $height, $link); |
} |
} |
/** |
* Performs a line break. The current abscissa goes back to the left |
* margin and the ordinate increases by the amount passed in parameter. |
* |
* @param float $height The height of the break. By default, the value |
* equals the height of the last printed cell. |
* |
* @see File_PDF::cell |
*/ |
function newLine($height = '') |
{ |
$this->x = $this->_left_margin; |
if (is_string($height)) { |
$this->y += $this->_last_height; |
} else { |
$this->y += $height; |
} |
} |
/** |
* Returns the abscissa of the current position in user units. |
* |
* @return float |
* |
* @see File_PDF::setX |
* @see File_PDF::getY |
* @see File_PDF::setY |
*/ |
function getX() |
{ |
return $this->x; |
} |
/** |
* Defines the abscissa of the current position. If the passed value is |
* negative, it is relative to the right of the page. |
* |
* @param float $x The value of the abscissa. |
* |
* @see File_PDF::getX |
* @see File_PDF::getY |
* @see File_PDF::setY |
* @see File_PDF::setXY |
*/ |
function setX($x) |
{ |
if ($x >= 0) { |
/* Absolute value. */ |
$this->x = $x; |
} else { |
/* Negative, so relative to right edge of the page. */ |
$this->x = $this->w + $x; |
} |
} |
/** |
* Returns the ordinate of the current position in user units. |
* |
* @return float |
* |
* @see File_PDF::setY |
* @see File_PDF::getX |
* @see File_PDF::setX |
*/ |
function getY() |
{ |
return $this->y; |
} |
/** |
* Defines the ordinate of the current position. If the passed value is |
* negative, it is relative to the bottom of the page. |
* |
* @param float $y The value of the ordinate. |
* |
* @see File_PDF::getX |
* @see File_PDF::getY |
* @see File_PDF::setY |
* @see File_PDF::setXY |
*/ |
function setY($y) |
{ |
if ($y >= 0) { |
/* Absolute value. */ |
$this->y = $y; |
} else { |
/* Negative, so relative to bottom edge of the page. */ |
$this->y = $this->h + $y; |
} |
} |
/** |
* Defines the abscissa and ordinate of the current position. If the |
* passed values are negative, they are relative respectively to the right |
* and bottom of the page. |
* |
* @param float $x The value of the abscissa. |
* @param float $y The value of the ordinate. |
* |
* @see File_PDF::setX |
* @see File_PDF::setY |
*/ |
function setXY($x, $y) |
{ |
$this->setY($y); |
$this->setX($x); |
} |
/** |
* Returns the raw PDF file. |
* |
* @see File_PDF::output |
*/ |
function getOutput() |
{ |
/* Check whether file has been closed. */ |
if ($this->_state < 3) { |
$this->close(); |
} |
return $this->_buffer; |
} |
/** |
* Function to output the buffered data to the browser. |
* |
* @param string $filename The filename for the output file. |
* @param boolean $inline True if inline, false if attachment. |
*/ |
function output($filename = 'unknown.pdf', $inline = false) |
{ |
/* Check whether file has been closed. */ |
if ($this->_state < 3) { |
$this->close(); |
} |
/* Check if headers have been sent. */ |
if (headers_sent()) { |
return $this->raiseError('Unable to send PDF file, some data has already been output to browser.'); |
} |
/* If HTTP_Download is not available return a PEAR_Error. */ |
if (!include_once 'HTTP/Download.php') { |
return $this->raiseError('Missing PEAR package HTTP_Download.'); |
} |
/* Params for the output. */ |
$disposition = !$inline ? HTTP_DOWNLOAD_ATTACHMENT : HTTP_DOWNLOAD_INLINE; |
$params = array('data' => $this->_buffer, |
'contenttype' => 'application/pdf', |
'contentdisposition' => array($disposition, $filename)); |
/* Output the file. */ |
return HTTP_Download::staticSend($params); |
} |
/** |
* Function to save the PDF file somewhere local to the server. |
* |
* @param string $filename The filename for the output file. |
*/ |
function save($filename = 'unknown.pdf') |
{ |
/* Check whether file has been closed. */ |
if ($this->_state < 3) { |
$this->close(); |
} |
$f = fopen($filename, 'wb'); |
if (!$f) { |
return $this->raiseError(sprintf('Unable to save PDF file: %s', $filename)); |
} |
fwrite($f, $this->_buffer, strlen($this->_buffer)); |
fclose($f); |
} |
function _toPt($val) |
{ |
return $val * $this->_scale; |
} |
function &_getFontFile($fontkey, $path = '') |
{ |
static $font_widths; |
if (!isset($font_widths[$fontkey])) { |
if (!empty($path)) { |
$file = $path . strtolower($fontkey) . '.php'; |
} else { |
$file = 'File/PDF/fonts/' . strtolower($fontkey) . '.php'; |
} |
include $file; |
if (!isset($font_widths[$fontkey])) { |
return $this->raiseError(sprintf('Could not include font metric file: %s', $file)); |
} |
} |
return $font_widths; |
} |
function _link($x, $y, $width, $height, $link) |
{ |
/* Save link to page links array. */ |
$this->_page_links[$this->_page][] = array($x, $y, $width, $height, $link); |
} |
function _beginDoc() |
{ |
/* Start document, but only if not yet started. */ |
if ($this->_state < 1) { |
$this->_state = 1; |
$this->_out('%PDF-1.3'); |
} |
} |
function _putPages() |
{ |
$nb = $this->_page; |
if (!empty($this->_alias_nb_pages)) { |
/* Replace number of pages. */ |
for ($n = 1; $n <= $nb; $n++) { |
$this->_pages[$n] = str_replace($this->_alias_nb_pages, $nb, $this->_pages[$n]); |
} |
} |
if ($this->_default_orientation == 'P') { |
$wPt = $this->fwPt; |
$hPt = $this->fhPt; |
} else { |
$wPt = $this->fhPt; |
$hPt = $this->fwPt; |
} |
$filter = ($this->_compress) ? '/Filter /FlateDecode ' : ''; |
for ($n = 1; $n <= $nb; $n++) { |
/* Page */ |
$this->_newobj(); |
$this->_out('<</Type /Page'); |
$this->_out('/Parent 1 0 R'); |
if (isset($this->_orientation_changes[$n])) { |
$this->_out(sprintf('/MediaBox [0 0 %.2f %.2f]', $hPt, $wPt)); |
} |
$this->_out('/Resources 2 0 R'); |
if (isset($this->_page_links[$n])) { |
/* Links */ |
$annots = '/Annots ['; |
foreach ($this->_page_links[$n] as $pl) { |
$rect = sprintf('%.2f %.2f %.2f %.2f', $pl[0], $pl[1], $pl[0] + $pl[2], $pl[1] - $pl[3]); |
$annots .= '<</Type /Annot /Subtype /Link /Rect [' . $rect . '] /Border [0 0 0] '; |
if (is_string($pl[4])) { |
$annots .= '/A <</S /URI /URI ' . $this->_textString($pl[4]) . '>>>>'; |
} else { |
$l = $this->_links[$pl[4]]; |
$height = isset($this->_orientation_changes[$l[0]]) ? $wPt : $hPt; |
$annots .= sprintf('/Dest [%d 0 R /XYZ 0 %.2f null]>>', 1 + 2 * $l[0], $height - $l[1] * $this->_scale); |
} |
} |
$this->_out($annots.']'); |
} |
$this->_out('/Contents ' . ($this->_n + 1) . ' 0 R>>'); |
$this->_out('endobj'); |
/* Page content */ |
$p = ($this->_compress) ? gzcompress($this->_pages[$n]) : $this->_pages[$n]; |
$this->_newobj(); |
$this->_out('<<' . $filter . '/Length ' . strlen($p) . '>>'); |
$this->_putStream($p); |
$this->_out('endobj'); |
} |
/* Pages root */ |
$this->_offsets[1] = strlen($this->_buffer); |
$this->_out('1 0 obj'); |
$this->_out('<</Type /Pages'); |
$kids = '/Kids ['; |
for ($i = 0; $i < $nb; $i++) { |
$kids .= (3 + 2 * $i) . ' 0 R '; |
} |
$this->_out($kids . ']'); |
$this->_out('/Count ' . $nb); |
$this->_out(sprintf('/MediaBox [0 0 %.2f %.2f]', $wPt, $hPt)); |
$this->_out('>>'); |
$this->_out('endobj'); |
} |
function _putFonts() |
{ |
$nf = $this->_n; |
foreach ($this->_diffs as $diff) { |
/* Encodings */ |
$this->_newobj(); |
$this->_out('<</Type /Encoding /BaseEncoding /WinAnsiEncoding /Differences [' . $diff . ']>>'); |
$this->_out('endobj'); |
} |
$mqr = get_magic_quotes_runtime(); |
set_magic_quotes_runtime(0); |
foreach ($this->_font_files as $file => $info) { |
/* Font file embedding. */ |
$this->_newobj(); |
$this->_font_files[$file]['n'] = $this->_n; |
$size = filesize($file); |
if (!$size) { |
return $this->raiseError('Font file not found.'); |
} |
$this->_out('<</Length ' . $size); |
if (substr($file, -2) == '.z') { |
$this->_out('/Filter /FlateDecode'); |
} |
$this->_out('/Length1 ' . $info['length1']); |
if (isset($info['length2'])) { |
$this->_out('/Length2 ' . $info['length2'] . ' /Length3 0'); |
} |
$this->_out('>>'); |
$f = fopen($file, 'rb'); |
$this->_putStream(fread($f, $size)); |
fclose($f); |
$this->_out('endobj'); |
} |
set_magic_quotes_runtime($mqr); |
foreach ($this->_fonts as $k => $font) { |
/* Font objects */ |
$this->_newobj(); |
$this->_fonts[$k]['n'] = $this->_n; |
$name = $font['name']; |
$this->_out('<</Type /Font'); |
$this->_out('/BaseFont /' . $name); |
if ($font['type'] == 'core') { |
/* Standard font. */ |
$this->_out('/Subtype /Type1'); |
if ($name != 'Symbol' && $name != 'ZapfDingbats') { |
$this->_out('/Encoding /WinAnsiEncoding'); |
} |
} else { |
/* Additional font. */ |
$this->_out('/Subtype /' . $font['type']); |
$this->_out('/FirstChar 32'); |
$this->_out('/LastChar 255'); |
$this->_out('/Widths ' . ($this->_n + 1) . ' 0 R'); |
$this->_out('/FontDescriptor ' . ($this->_n + 2) . ' 0 R'); |
if ($font['enc']) { |
if (isset($font['diff'])) { |
$this->_out('/Encoding ' . ($nf + $font['diff']).' 0 R'); |
} else { |
$this->_out('/Encoding /WinAnsiEncoding'); |
} |
} |
} |
$this->_out('>>'); |
$this->_out('endobj'); |
if ($font['type'] != 'core') { |
/* Widths. */ |
$this->_newobj(); |
$cw = &$font['cw']; |
$s = '['; |
for ($i = 32; $i <= 255; $i++) { |
$s .= $cw[chr($i)] . ' '; |
} |
$this->_out($s . ']'); |
$this->_out('endobj'); |
/* Descriptor. */ |
$this->_newobj(); |
$s = '<</Type /FontDescriptor /FontName /' . $name; |
foreach ($font['desc'] as $k => $v) { |
$s .= ' /' . $k . ' ' . $v; |
} |
$file = $font['file']; |
if ($file) { |
$s .= ' /FontFile' . ($font['type'] == 'Type1' ? '' : '2') . ' ' . $this->_font_files[$file]['n'] . ' 0 R'; |
} |
$this->_out($s . '>>'); |
$this->_out('endobj'); |
} |
} |
} |
function _putImages() |
{ |
$filter = ($this->_compress) ? '/Filter /FlateDecode ' : ''; |
foreach ($this->_images as $file => $info) { |
$this->_newobj(); |
$this->_images[$file]['n'] = $this->_n; |
$this->_out('<</Type /XObject'); |
$this->_out('/Subtype /Image'); |
$this->_out('/Width ' . $info['w']); |
$this->_out('/Height ' . $info['h']); |
if ($info['cs'] == 'Indexed') { |
$this->_out('/ColorSpace [/Indexed /DeviceRGB ' . (strlen($info['pal'])/3 - 1) . ' ' . ($this->_n + 1).' 0 R]'); |
} else { |
$this->_out('/ColorSpace /' . $info['cs']); |
if ($info['cs'] == 'DeviceCMYK') { |
$this->_out('/Decode [1 0 1 0 1 0 1 0]'); |
} |
} |
$this->_out('/BitsPerComponent ' . $info['bpc']); |
$this->_out('/Filter /' . $info['f']); |
if (isset($info['parms'])) { |
$this->_out($info['parms']); |
} |
if (isset($info['trns']) && is_array($info['trns'])) { |
$trns = ''; |
$i_max = count($info['trns']); |
for ($i = 0; $i < $i_max; $i++) { |
$trns .= $info['trns'][$i] . ' ' . $info['trns'][$i].' '; |
} |
$this->_out('/Mask [' . $trns . ']'); |
} |
$this->_out('/Length ' . strlen($info['data']) . '>>'); |
$this->_putStream($info['data']); |
$this->_out('endobj'); |
/* Palette. */ |
if ($info['cs'] == 'Indexed') { |
$this->_newobj(); |
$pal = ($this->_compress) ? gzcompress($info['pal']) : $info['pal']; |
$this->_out('<<' . $filter . '/Length ' . strlen($pal) . '>>'); |
$this->_putStream($pal); |
$this->_out('endobj'); |
} |
} |
} |
function _putResources() |
{ |
$this->_putFonts(); |
$this->_putImages(); |
/* Resource dictionary */ |
$this->_offsets[2] = strlen($this->_buffer); |
$this->_out('2 0 obj'); |
$this->_out('<</ProcSet [/PDF /Text /ImageB /ImageC /ImageI]'); |
$this->_out('/Font <<'); |
foreach ($this->_fonts as $font) { |
$this->_out('/F' . $font['i'] . ' ' . $font['n'] . ' 0 R'); |
} |
$this->_out('>>'); |
if (count($this->_images)) { |
$this->_out('/XObject <<'); |
foreach ($this->_images as $image) { |
$this->_out('/I' . $image['i'] . ' ' . $image['n'] . ' 0 R'); |
} |
$this->_out('>>'); |
} |
$this->_out('>>'); |
$this->_out('endobj'); |
} |
function _putInfo() |
{ |
$this->_out('/Producer ' . $this->_textString('Horde PDF')); |
if (!empty($this->_info['title'])) { |
$this->_out('/Title ' . $this->_textString($this->_info['title'])); |
} |
if (!empty($this->_info['subject'])) { |
$this->_out('/Subject ' . $this->_textString($this->_info['subject'])); |
} |
if (!empty($this->_info['author'])) { |
$this->_out('/Author ' . $this->_textString($this->_info['author'])); |
} |
if (!empty($this->keywords)) { |
$this->_out('/Keywords ' . $this->_textString($this->keywords)); |
} |
if (!empty($this->creator)) { |
$this->_out('/Creator ' . $this->_textString($this->creator)); |
} |
$this->_out('/CreationDate ' . $this->_textString('D:' . date('YmdHis'))); |
} |
function _putCatalog() |
{ |
$this->_out('/Type /Catalog'); |
$this->_out('/Pages 1 0 R'); |
if ($this->_zoom_mode == 'fullpage') { |
$this->_out('/OpenAction [3 0 R /Fit]'); |
} elseif ($this->_zoom_mode == 'fullwidth') { |
$this->_out('/OpenAction [3 0 R /FitH null]'); |
} elseif ($this->_zoom_mode == 'real') { |
$this->_out('/OpenAction [3 0 R /XYZ null null 1]'); |
} elseif (!is_string($this->_zoom_mode)) { |
$this->_out('/OpenAction [3 0 R /XYZ null null ' . ($this->_zoom_mode / 100).']'); |
} |
if ($this->_layout_mode == 'single') { |
$this->_out('/PageLayout /SinglePage'); |
} elseif ($this->_layout_mode == 'continuous') { |
$this->_out('/PageLayout /OneColumn'); |
} elseif ($this->_layout_mode == 'two') { |
$this->_out('/PageLayout /TwoColumnLeft'); |
} |
} |
function _putTrailer() |
{ |
$this->_out('/Size ' . ($this->_n + 1)); |
$this->_out('/Root ' . $this->_n . ' 0 R'); |
$this->_out('/Info ' . ($this->_n - 1) . ' 0 R'); |
} |
function _endDoc() |
{ |
$this->_putPages(); |
$this->_putResources(); |
/* Info */ |
$this->_newobj(); |
$this->_out('<<'); |
$this->_putInfo(); |
$this->_out('>>'); |
$this->_out('endobj'); |
/* Catalog */ |
$this->_newobj(); |
$this->_out('<<'); |
$this->_putCatalog(); |
$this->_out('>>'); |
$this->_out('endobj'); |
/* Cross-ref */ |
$o = strlen($this->_buffer); |
$this->_out('xref'); |
$this->_out('0 ' . ($this->_n + 1)); |
$this->_out('0000000000 65535 f '); |
for ($i = 1; $i <= $this->_n; $i++) { |
$this->_out(sprintf('%010d 00000 n ', $this->_offsets[$i])); |
} |
/* Trailer */ |
$this->_out('trailer'); |
$this->_out('<<'); |
$this->_putTrailer(); |
$this->_out('>>'); |
$this->_out('startxref'); |
$this->_out($o); |
$this->_out('%%EOF'); |
$this->_state = 3; |
} |
function _beginPage($orientation) |
{ |
$this->_page++; |
$this->_pages[$this->_page] = ''; |
$this->_state = 2; |
$this->x = $this->_left_margin; |
$this->y = $this->_top_margin; |
$this->_last_height = 0; |
/* Page orientation */ |
if (!$orientation) { |
$orientation = $this->_default_orientation; |
} else { |
$orientation = strtoupper($orientation[0]); |
if ($orientation != $this->_default_orientation) { |
$this->_orientation_changes[$this->_page] = true; |
} |
} |
if ($orientation != $this->_current_orientation) { |
/* Change orientation */ |
if ($orientation == 'P') { |
$this->wPt = $this->fwPt; |
$this->hPt = $this->fhPt; |
$this->w = $this->fw; |
$this->h = $this->fh; |
} else { |
$this->wPt = $this->fhPt; |
$this->hPt = $this->fwPt; |
$this->w = $this->fh; |
$this->h = $this->fw; |
} |
$this->_page_break_trigger = $this->h - $this->_break_margin; |
$this->_current_orientation = $orientation; |
} |
} |
function _endPage() |
{ |
/* End of page contents */ |
$this->_state = 1; |
} |
function _newobj() |
{ |
/* Begin a new object */ |
$this->_n++; |
$this->_offsets[$this->_n] = strlen($this->_buffer); |
$this->_out($this->_n . ' 0 obj'); |
} |
function _doUnderline($x, $y, $text) |
{ |
/* Set the rectangle width according to text width. */ |
$width = $this->getStringWidth($text, true); |
/* Set rectangle position and height, using underline position and |
* thickness settings scaled by the font size. */ |
$y = $y + ($this->_current_font['up'] * $this->_font_size_pt / 1000); |
$height = -$this->_current_font['ut'] * $this->_font_size_pt / 1000; |
return sprintf('%.2f %.2f %.2f %.2f re f', $x, $y, $width, $height); |
} |
function _parseJPG($file) |
{ |
/* Extract info from a JPEG file. */ |
$img = @getimagesize($file); |
if (!$img) { |
return $this->raiseError(sprintf('Missing or incorrect image file: %s', $file)); |
} |
if ($img[2] != 2) { |
return $this->raiseError(sprintf('Not a JPEG file: %s', $file)); |
} |
if (!isset($img['channels']) || $img['channels'] == 3) { |
$colspace = 'DeviceRGB'; |
} elseif ($img['channels'] == 4) { |
$colspace = 'DeviceCMYK'; |
} else { |
$colspace = 'DeviceGray'; |
} |
$bpc = isset($img['bits']) ? $img['bits'] : 8; |
/* Read whole file. */ |
$f = fopen($file, 'rb'); |
$data = fread($f, filesize($file)); |
fclose($f); |
return array('w' => $img[0], 'h' => $img[1], 'cs' => $colspace, 'bpc' => $bpc, 'f' => 'DCTDecode', 'data' => $data); |
} |
function _parsePNG($file) |
{ |
/* Extract info from a PNG file. */ |
$f = fopen($file, 'rb'); |
if (!$f) { |
return $this->raiseError(sprintf('Unable to open image file: %s', $file)); |
} |
/* Check signature. */ |
if (fread($f, 8) != chr(137) . 'PNG' . chr(13) . chr(10) . chr(26) . chr(10)) { |
return $this->raiseError(sprintf('Not a PNG file: %s', $file)); |
} |
/* Read header chunk. */ |
fread($f, 4); |
if (fread($f, 4) != 'IHDR') { |
return $this->raiseError(sprintf('Incorrect PNG file: %s', $file)); |
} |
$width = $this->_freadInt($f); |
$height = $this->_freadInt($f); |
$bpc = ord(fread($f, 1)); |
if ($bpc > 8) { |
return $this->raiseError(sprintf('16-bit depth not supported: %s', $file)); |
} |
$ct = ord(fread($f, 1)); |
if ($ct == 0) { |
$colspace = 'DeviceGray'; |
} elseif ($ct == 2) { |
$colspace = 'DeviceRGB'; |
} elseif ($ct == 3) { |
$colspace = 'Indexed'; |
} else { |
return $this->raiseError(sprintf('Alpha channel not supported: %s', $file)); |
} |
if (ord(fread($f, 1)) != 0) { |
return $this->raiseError(sprintf('Unknown compression method: %s', $file)); |
} |
if (ord(fread($f, 1)) != 0) { |
return $this->raiseError(sprintf('Unknown filter method: %s', $file)); |
} |
if (ord(fread($f, 1)) != 0) { |
return $this->raiseError(sprintf('Interlacing not supported: %s', $file)); |
} |
fread($f, 4); |
$parms = '/DecodeParms <</Predictor 15 /Colors ' . ($ct == 2 ? 3 : 1).' /BitsPerComponent ' . $bpc . ' /Columns ' . $width.'>>'; |
/* Scan chunks looking for palette, transparency and image data. */ |
$pal = ''; |
$trns = ''; |
$data = ''; |
do { |
$n = $this->_freadInt($f); |
$type = fread($f, 4); |
if ($type == 'PLTE') { |
/* Read palette */ |
$pal = fread($f, $n); |
fread($f, 4); |
} elseif ($type == 'tRNS') { |
/* Read transparency info */ |
$t = fread($f, $n); |
if ($ct == 0) { |
$trns = array(ord(substr($t, 1, 1))); |
} elseif ($ct == 2) { |
$trns = array(ord(substr($t, 1, 1)), ord(substr($t, 3, 1)), ord(substr($t, 5, 1))); |
} else { |
$pos = strpos($t, chr(0)); |
if (is_int($pos)) { |
$trns = array($pos); |
} |
} |
fread($f, 4); |
} elseif ($type == 'IDAT') { |
/* Read image data block */ |
$data .= fread($f, $n); |
fread($f, 4); |
} elseif ($type == 'IEND') { |
break; |
} else { |
fread($f, $n + 4); |
} |
} while ($n); |
if ($colspace == 'Indexed' && empty($pal)) { |
return $this->raiseError(sprintf('Missing palette in: %s', $file)); |
} |
fclose($f); |
return array('w' => $width, 'h' => $height, 'cs' => $colspace, 'bpc' => $bpc, 'f' => 'FlateDecode', 'parms' => $parms, 'pal' => $pal, 'trns' => $trns, 'data' => $data); |
} |
function _freadInt($f) |
{ |
/* Read a 4-byte integer from file. */ |
$i = ord(fread($f, 1)) << 24; |
$i += ord(fread($f, 1)) << 16; |
$i += ord(fread($f, 1)) << 8; |
$i += ord(fread($f, 1)); |
return $i; |
} |
function _textString($s) |
{ |
/* Format a text string */ |
return '(' . $this->_escape($s) . ')'; |
} |
function _escape($s) |
{ |
/* Add \ before \, ( and ) */ |
return str_replace(array(')','(','\\'), |
array('\\)','\\(','\\\\'), |
$s); |
} |
function _putStream($s) |
{ |
$this->_out('stream'); |
$this->_out($s); |
$this->_out('endstream'); |
} |
function _out($s) |
{ |
/* Add a line to the document. */ |
if ($this->_state == 2) { |
$this->_pages[$this->_page] .= $s . "\n"; |
} else { |
$this->_buffer .= $s . "\n"; |
} |
} |
} |
/trunk/jrest/lib/SpreadsheetProductor.php |
---|
New file |
0,0 → 1,15 |
<?php |
Class SpreadsheetProductor { |
function initSpreadsheet() { |
require_once("Spreadsheet/Excel/Writer.php"); |
} |
} |
?> |
/trunk/jrest/lib/PDFProductor.php |
---|
New file |
0,0 → 1,14 |
<?php |
Class PDFProductor { |
function initPDF() { |
require_once("PDF.php"); |
} |
} |
?> |
/trunk/jrest/lib/WdHTMLParser.php |
---|
New file |
0,0 → 1,144 |
<?php |
/** |
* |
* @author Olivier Laviale |
* @see http://www.weirdog.com/blog/php/un-parser-html-des-plus-leger.html |
* |
*/ |
class WdHTMLParser { |
private $encoding; |
private $matches; |
private $escaped; |
private $opened = array(); |
public $malformed; |
public function parse($html, $namespace=NULL, $encoding='utf-8') { |
$this->malformed = false; |
$this->encoding = $encoding; |
// we take care of escaping comments and processing options. they will not be parsed |
// and will end as text nodes |
$html = $this->escapeSpecials($html); |
// in order to create a tree, we first need to split the HTML using the markups, |
// creating a nice flat array of texts and opening and closing markups. |
// |
// the array can be read as follows : |
// |
// i+0 => some text |
// i+1 => '/' for closing markups, nothing otherwise |
// i+2 => the markup it self, without the '<' '>' |
// |
// note that i+2 might end with a '/' indicating an auto-closing markup |
$this->matches = preg_split('#<(/?)' . $namespace . '([^>]*)>#', $html, -1, PREG_SPLIT_DELIM_CAPTURE); |
// the flat representation is now ready, we can create our tree |
$tree = $this->buildTree(); |
// if comments or processing options where escaped, we can |
// safely unescape them now |
if ($this->escaped) { |
$tree = $this->unescapeSpecials($tree); |
} |
return $tree; |
} |
private function escapeSpecials($html) { |
// here we escape comments |
$html = preg_replace_callback('#<\!--.+-->#sU', array($this, 'escapeSpecials_callback'), $html); |
// and processing options |
$html = preg_replace_callback('#<\?.+\?>#sU', array($this, 'escapeSpecials_callback'), $html); |
return $html; |
} |
private function escapeSpecials_callback($m) { |
$this->escaped = true; |
$text = $m[0]; |
$text = str_replace(array('<', '>'), array("\x01", "\x02"), $text); |
return $text; |
} |
private function unescapeSpecials($tree) { |
return is_array($tree) ? array_map(array($this, 'unescapeSpecials'), $tree) : str_replace(array("\x01", "\x02"), array('<', '>'), $tree); |
} |
private function buildTree() { |
$nodes = array(); |
$i = 0; |
$text = NULL; |
while (($value = array_shift($this->matches)) !== NULL) { |
switch ($i++ % 3) { |
case 0: |
// if the trimed value is not empty we preserve the value, |
// otherwise we discard it. |
if (trim($value)){ |
$nodes[] = $value; |
} |
break; |
case 1: |
$closing = ($value == '/'); |
break; |
case 2: |
if (substr($value, -1, 1) == '/') { |
// auto closing |
$nodes[] = $this->parseMarkup(substr($value, 0, -1)); |
} else if ($closing) { |
// closing markup |
$open = array_pop($this->opened); |
if ($value != $open) { |
$this->error($value, $open); |
} |
return $nodes; |
} else { |
// this is an open markup with possible children |
$node = $this->parseMarkup($value); |
// push the markup name into the opened markups |
$this->opened[] = $node['name']; |
// create the node and parse its children |
$node['children'] = $this->buildTree($this->matches); |
$nodes[] = $node; |
} |
break; |
} |
} |
return $nodes; |
} |
public function parseMarkup($markup) { |
// get markup's name |
preg_match('#^[^\s]+#', $markup, $matches); |
$name = $matches[0]; |
// get markup's arguments |
preg_match_all('#\s+([^=]+)\s*=\s*"([^"]+)"#', $markup, $matches, PREG_SET_ORDER); |
// transform the matches into a nice key/value array |
$args = array(); |
foreach ($matches as $m) { |
// we unescape the html entities of the argument's value |
$args[$m[1]] = html_entity_decode($m[2], ENT_QUOTES, $this->encoding); |
} |
return array('name' => $name, 'args' => $args); |
} |
public function error($markup, $expected) { |
$this->malformed = true; |
printf('unexpected closing markup "%s", should be "%s"', $markup, $expected); |
} |
} |
?> |
/trunk/jrest/lib/Writer.php |
---|
New file |
0,0 → 1,104 |
<?php |
/* |
* Module written/ported by Xavier Noguer <xnoguer@rezebra.com> |
* |
* PERL Spreadsheet::WriteExcel module. |
* |
* The author of the Spreadsheet::WriteExcel module is John McNamara |
* <jmcnamara@cpan.org> |
* |
* I _DO_ maintain this code, and John McNamara has nothing to do with the |
* porting of this code to PHP. Any questions directly related to this |
* class library should be directed to me. |
* |
* License Information: |
* |
* Spreadsheet_Excel_Writer: A library for generating Excel Spreadsheets |
* Copyright (c) 2002-2003 Xavier Noguer xnoguer@rezebra.com |
* |
* This library is free software; you can redistribute it and/or |
* modify it under the terms of the GNU Lesser General Public |
* License as published by the Free Software Foundation; either |
* version 2.1 of the License, or (at your option) any later version. |
* |
* This library is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
* Lesser General Public License for more details. |
* |
* You should have received a copy of the GNU Lesser General Public |
* License along with this library; if not, write to the Free Software |
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
*/ |
require_once 'PEAR.php'; |
require_once 'Spreadsheet/Excel/Writer/Workbook.php'; |
/** |
* Class for writing Excel Spreadsheets. This class should change COMPLETELY. |
* |
* @author Xavier Noguer <xnoguer@rezebra.com> |
* @category FileFormats |
* @package Spreadsheet_Excel_Writer |
*/ |
class Spreadsheet_Excel_Writer extends Spreadsheet_Excel_Writer_Workbook |
{ |
/** |
* The constructor. It just creates a Workbook |
* |
* @param string $filename The optional filename for the Workbook. |
* @return Spreadsheet_Excel_Writer_Workbook The Workbook created |
*/ |
function Spreadsheet_Excel_Writer($filename = '') |
{ |
$this->_filename = $filename; |
$this->Spreadsheet_Excel_Writer_Workbook($filename); |
} |
/** |
* Send HTTP headers for the Excel file. |
* |
* @param string $filename The filename to use for HTTP headers |
* @access public |
*/ |
function send($filename) |
{ |
header("Content-type: application/vnd.ms-excel"); |
header("Content-Disposition: attachment; filename=\"$filename\""); |
header("Expires: 0"); |
header("Cache-Control: must-revalidate, post-check=0,pre-check=0"); |
header("Pragma: public"); |
} |
/** |
* Utility function for writing formulas |
* Converts a cell's coordinates to the A1 format. |
* |
* @access public |
* @static |
* @param integer $row Row for the cell to convert (0-indexed). |
* @param integer $col Column for the cell to convert (0-indexed). |
* @return string The cell identifier in A1 format |
*/ |
function rowcolToCell($row, $col) |
{ |
if ($col > 255) { //maximum column value exceeded |
return new PEAR_Error("Maximum column value exceeded: $col"); |
} |
$int = (int)($col / 26); |
$frac = $col % 26; |
$chr1 = ''; |
if ($int > 0) { |
$chr1 = chr(ord('A') + $int - 1); |
} |
$chr2 = chr(ord('A') + $frac); |
$row++; |
return $chr1 . $chr2 . $row; |
} |
} |
?> |
/trunk/jrest/jrest.ini.php |
---|
1,39 → 1,45 |
;<?/* |
[settings] |
baseURL = "/projet_bp/jrest/" |
; Default |
[appli] |
phptype = mysql |
username = aurelien |
password = Canard |
hostspec = localhost |
database = papyrus_bp |
url_service_liste = vpopmail.tela-botanica.org/ |
domaine_service_liste = tela-botanica.org |
adresse_appli_projet = http://www.tela-botanica.org/page:liste_projets |
addresse_telechargement_docs = http://www.tela-botanica.org/projets/%s/telechargement/%s |
; Identification |
[database_ident] |
phptype = mysql |
username = aurelien |
password = Canard |
hostspec = localhost |
database = tela_prod |
annuaire = annuaire_tela |
ann_id = U_MAIL |
ann_pwd = U_PASSWD |
pass_crypt_funct = md5 |
; LOGS |
[log] |
cheminlog = "/home/aurelien/Logs/" |
timezone = "Europe/Paris" |
taillemax = 100000 |
; ADMIN |
[jrest_admin] |
admin = aurelien@tela-botanica.org,david.delon@clapas.net,jpm@tela-botanica.org,marie@tela-botanica.org |
;*/?> |
;<?/* |
[settings] |
baseURL = "/client/projet/jrest/" |
; Default |
[appli] |
phptype = mysql |
username = telabotap |
password = "shah=Ph3" |
hostspec = localhost |
database = tela_prod_v4 |
url_service_liste = vpopmail.tela-botanica.org/ |
domaine_service_liste = tela-botanica.org |
url_base_projet = http://www.tela-botanica.org/page:liste_projets |
guid = urn:lsid:tela-botanica.org:%s:%s |
chemin_wikis_integres = /home/telabotap/www/wikini/ |
chemin_wiki_defaut = /home/telabotap/www/client/integrateur_wikini/bibliotheque/wikini_0_5/ |
nom_admin_wiki = WikiAdmin |
adresse_admin_wiki = accueil@tela-botanica.org |
pass_admin_wiki = "wqa&WQA1" |
; Identification |
[database_ident] |
phptype = mysql |
username = telabotap |
password = "shah=Ph3" |
hostspec = localhost |
database = tela_prod |
annuaire = annuaire_tela |
ann_id = U_MAIL |
ann_pwd = U_PASSWD |
pass_crypt_funct = md5 |
; LOGS |
[log] |
cheminlog = "/client/projet/jrest/logs/" |
timezone = "Europe/Paris" |
taillemax = 100000 |
; ADMIN |
[jrest_admin] |
admin = aurelien@tela-botanica.org,david.delon@clapas.net,jpm@tela-botanica.org,marie@tela-botanica.org |
;*/?> |
/trunk/jrest/JRest.php |
---|
1,304 → 1,304 |
<?php |
// In : utf8 url_encoded (get et post) |
// Out : utf8 |
// TODO : gerer les retours : dans ce controleur : code retour et envoi ... |
class JRest { |
/** Parsed configuration file */ |
private $config; |
/** The HTTP request method used. */ |
private $method = 'GET'; |
/** The HTTP request data sent (if any). */ |
private $requestData = NULL; |
/** Array of strings to convert into the HTTP response. */ |
private $output = array(); |
/** Nom resource. */ |
private $resource = NULL; |
/** Identifiant unique resource. */ |
private $uid = NULL; |
/** |
* Constructor. Parses the configuration file "JRest.ini", grabs any request data sent, records the HTTP |
* request method used and parses the request URL to find out the requested resource |
* @param str iniFile Configuration file to use |
*/ |
public function JRest($iniFile = 'jrest.ini.php') { |
$this->config = parse_ini_file($iniFile, TRUE); |
if (isset($_SERVER['REQUEST_URI']) && isset($_SERVER['REQUEST_METHOD']) && isset($_SERVER['QUERY_STRING'])) { |
if (isset($_SERVER['CONTENT_LENGTH']) && $_SERVER['CONTENT_LENGTH'] > 0) { |
$this->requestData = ''; |
$httpContent = fopen('php://input', 'r'); |
while ($data = fread($httpContent, 1024)) { |
$this->requestData .= $data; |
} |
fclose($httpContent); |
} |
if (strlen($_SERVER['QUERY_STRING']) == 0) { |
$len = strlen($_SERVER['REQUEST_URI']); |
} else { |
$len = -(strlen($_SERVER['QUERY_STRING']) + 1); |
} |
$urlString = substr($_SERVER['REQUEST_URI'], strlen($this->config['settings']['baseURL']), $len); |
$urlParts = explode('/', $urlString); |
if (isset($urlParts[0])) $this->resource = $urlParts[0]; |
if (count($urlParts) > 1 && $urlParts[1] != '') { |
array_shift($urlParts); |
foreach ($urlParts as $uid) { |
if ($uid != '') { |
$this->uid[] = urldecode($uid); |
} |
} |
} |
$this->method = $_SERVER['REQUEST_METHOD']; |
} else { |
trigger_error('I require the server variables REQUEST_URI, REQUEST_METHOD and QUERY_STRING to work.', E_USER_ERROR); |
} |
} |
/** |
* Execute the request. |
*/ |
function exec() { |
switch ($this->method) { |
case 'GET': |
$this->get(); |
break; |
case 'POST': |
$this->post(); |
break; |
case 'DELETE': |
$this->delete(); |
break; |
case 'PUT': |
$this->add(); |
break; |
} |
} |
/** |
* Execute a GET request. A GET request fetches a list of resource when no resource name is given, a list of element |
* when a resource name is given, or a resource element when a resource and resource unique identifier are given. It does not change the |
* database contents. |
*/ |
private function get() { |
if ($this->resource) { |
$resource_file = 'services/'.ucfirst($this->resource).'.php'; |
$resource_class = ucfirst($this->resource); |
if (file_exists($resource_file)) { |
include_once $resource_file; |
if (class_exists($resource_class)) { |
$service = new $resource_class($this->config); |
if ($this->uid) { // get a resource element |
if (method_exists($service, 'getElement')) { |
$service->getElement($this->uid); |
} |
} elseif (method_exists($service, 'getRessource')) { // get all elements of a ressource |
$service->getRessource(); |
} |
} |
} |
} else { // get resources |
// include set.jrest.php, instanticiation et appel |
} |
} |
private function post() { |
$pairs = array(); |
// Récupération des paramètres passés dans le contenu de la requête HTTP (= POST) |
if ($this->requestData) { |
$pairs = $this->parseRequestData(); |
} |
// Ajout des informations concernant l'upload de fichier passées dans la variable $_FILE |
if(isset($_FILES)) { |
foreach ($_FILES as $v) { |
$pairs[$v['name']] = $v; |
} |
// Ne pas effacer cette ligne ! Elle est indispensable pour les services du Carnet en ligne |
// qui n'utilisent que le tableau pairs dans les posts |
$pairs = array_merge($pairs, $_POST); |
} |
// gestion du contenu du post |
if(isset($_POST)) |
{ |
// Safari ne sait pas envoyer des DELETE avec gwt... |
// Nous utilisons le parametre "action" passé dans le POST qui doit contenir DELETE pour lancer la supression |
if ($pairs['action'] == 'DELETE') { |
$this->delete(); |
return; |
} |
if (count($pairs) != 0) { |
if ($this->uid) { // get a resource element |
$resource_file = 'services/'.ucfirst($this->resource).'.php'; |
$resource_class = ucfirst($this->resource); |
if (file_exists($resource_file)) { |
include_once $resource_file; |
if (class_exists($resource_class)) { |
$service = new $resource_class($this->config); |
if (method_exists($service,'updateElement')) { // Update element |
// TODO : a voir le retour ... |
if ($service->updateElement($this->uid, $pairs)) { |
$this->created(); |
} |
} |
} |
} |
} else { // get all elements of a ressource |
$this->add($pairs); |
} |
} else { |
$this->lengthRequired(); |
} |
} |
} |
private function delete() { |
$resource_file = 'services/'.ucfirst($this->resource).'.php'; |
$resource_class = ucfirst($this->resource); |
if (file_exists($resource_file)) { |
include_once $resource_file; |
if (class_exists($resource_class)) { |
$service = new $resource_class($this->config); |
if ($this->uid) { // get a resource element |
if (method_exists($service, 'deleteElement')) { // Delete element |
if ($service->deleteElement($this->uid)) { |
$this->noContent(); |
} |
} |
} |
} |
} |
} |
private function add($pairs = null) { |
if (is_null($pairs)) { |
$pairs = array(); |
// Récupération des paramètres passés dans le contenu de la requête HTTP (= POST) |
// FIXME : vérifier que l'on récupère bien les données passées par PUT |
if ($this->requestData) { |
$pairs = $this->parseRequestData(); |
} |
} |
if (count($pairs) != 0) { |
$resource_file = 'services/'.ucfirst($this->resource).'.php'; |
$resource_class = ucfirst($this->resource); |
if (file_exists($resource_file)) { |
include_once $resource_file; |
if (class_exists($resource_class)) { |
$service = new $resource_class($this->config); |
if (method_exists($service,'createElement')) { // Create a new element |
if ($service->createElement($pairs)) { |
$this->created(); |
} |
} |
} |
} |
} else { |
$this->lengthRequired(); |
} |
} |
/** |
* Parse the HTTP request data. |
* @return str[] Array of name value pairs |
*/ |
private function parseRequestData() { |
$values = array(); |
$pairs = explode('&', $this->requestData); |
foreach ($pairs as $pair) { |
$parts = explode('=', $pair); |
if (isset($parts[0]) && isset($parts[1])) { |
$parts[1] = rtrim(urldecode($parts[1])); |
$values[$parts[0]] = $parts[1]; |
} |
} |
return $values; |
} |
/** |
* Send a HTTP 201 response header. |
*/ |
private function created($url = FALSE) { |
header('HTTP/1.0 201 Created'); |
if ($url) { |
header('Location: '.$url); |
} |
} |
/** |
* Send a HTTP 204 response header. |
*/ |
private function noContent() { |
header('HTTP/1.0 204 No Content'); |
} |
/** |
* Send a HTTP 400 response header. |
*/ |
private function badRequest() { |
header('HTTP/1.0 400 Bad Request'); |
} |
/** |
* Send a HTTP 401 response header. |
*/ |
private function unauthorized($realm = 'JRest') { |
if (!isset($_SERVER['PHP_AUTH_USER']) || !isset($_SERVER['PHP_AUTH_PW'])) { |
header('WWW-Authenticate: Basic realm="'.$realm.'"'); |
} |
header('HTTP/1.0 401 Unauthorized'); |
} |
/** |
* Send a HTTP 404 response header. |
*/ |
private function notFound() { |
header('HTTP/1.0 404 Not Found'); |
} |
/** |
* Send a HTTP 405 response header. |
*/ |
private function methodNotAllowed($allowed = 'GET, HEAD') { |
header('HTTP/1.0 405 Method Not Allowed'); |
header('Allow: '.$allowed); |
} |
/** |
* Send a HTTP 406 response header. |
*/ |
private function notAcceptable() { |
header('HTTP/1.0 406 Not Acceptable'); |
echo join(', ', array_keys($this->config['renderers'])); |
} |
/** |
* Send a HTTP 411 response header. |
*/ |
private function lengthRequired() { |
header('HTTP/1.0 411 Length Required'); |
} |
/** |
* Send a HTTP 500 response header. |
*/ |
private function internalServerError() { |
header('HTTP/1.0 500 Internal Server Error'); |
} |
} |
<?php |
// In : utf8 url_encoded (get et post) |
// Out : utf8 |
// TODO : gerer les retours : dans ce controleur : code retour et envoi ... |
class JRest { |
/** Parsed configuration file */ |
private $config; |
/** The HTTP request method used. */ |
private $method = 'GET'; |
/** The HTTP request data sent (if any). */ |
private $requestData = NULL; |
/** Array of strings to convert into the HTTP response. */ |
private $output = array(); |
/** Nom resource. */ |
private $resource = NULL; |
/** Identifiant unique resource. */ |
private $uid = NULL; |
/** |
* Constructor. Parses the configuration file "JRest.ini", grabs any request data sent, records the HTTP |
* request method used and parses the request URL to find out the requested resource |
* @param str iniFile Configuration file to use |
*/ |
public function JRest($iniFile = 'jrest.ini.php') { |
$this->config = parse_ini_file($iniFile, TRUE); |
if (isset($_SERVER['REQUEST_URI']) && isset($_SERVER['REQUEST_METHOD']) && isset($_SERVER['QUERY_STRING'])) { |
if (isset($_SERVER['CONTENT_LENGTH']) && $_SERVER['CONTENT_LENGTH'] > 0) { |
$this->requestData = ''; |
$httpContent = fopen('php://input', 'r'); |
while ($data = fread($httpContent, 1024)) { |
$this->requestData .= $data; |
} |
fclose($httpContent); |
} |
if (strlen($_SERVER['QUERY_STRING']) == 0) { |
$len = strlen($_SERVER['REQUEST_URI']); |
} else { |
$len = -(strlen($_SERVER['QUERY_STRING']) + 1); |
} |
$urlString = substr($_SERVER['REQUEST_URI'], strlen($this->config['settings']['baseURL']), $len); |
$urlParts = explode('/', $urlString); |
if (isset($urlParts[0])) $this->resource = $urlParts[0]; |
if (count($urlParts) > 1 && $urlParts[1] != '') { |
array_shift($urlParts); |
foreach ($urlParts as $uid) { |
if ($uid != '') { |
$this->uid[] = urldecode($uid); |
} |
} |
} |
$this->method = $_SERVER['REQUEST_METHOD']; |
} else { |
trigger_error('I require the server variables REQUEST_URI, REQUEST_METHOD and QUERY_STRING to work.', E_USER_ERROR); |
} |
} |
/** |
* Execute the request. |
*/ |
function exec() { |
switch ($this->method) { |
case 'GET': |
$this->get(); |
break; |
case 'POST': |
$this->post(); |
break; |
case 'DELETE': |
$this->delete(); |
break; |
case 'PUT': |
$this->add(); |
break; |
} |
} |
/** |
* Execute a GET request. A GET request fetches a list of resource when no resource name is given, a list of element |
* when a resource name is given, or a resource element when a resource and resource unique identifier are given. It does not change the |
* database contents. |
*/ |
private function get() { |
if ($this->resource) { |
$resource_file = 'services/'.ucfirst($this->resource).'.php'; |
$resource_class = ucfirst($this->resource); |
if (file_exists($resource_file)) { |
include_once $resource_file; |
if (class_exists($resource_class)) { |
$service = new $resource_class($this->config); |
if ($this->uid) { // get a resource element |
if (method_exists($service, 'getElement')) { |
$service->getElement($this->uid); |
} |
} elseif (method_exists($service, 'getRessource')) { // get all elements of a ressource |
$service->getRessource(); |
} |
} |
} |
} else { // get resources |
// include set.jrest.php, instanticiation et appel |
} |
} |
private function post() { |
$pairs = array(); |
// Récupération des paramètres passés dans le contenu de la requête HTTP (= POST) |
if ($this->requestData) { |
$pairs = $this->parseRequestData(); |
} |
// Ajout des informations concernant l'upload de fichier passées dans la variable $_FILE |
if(isset($_FILES)) { |
foreach ($_FILES as $v) { |
$pairs[$v['name']] = $v; |
} |
// Ne pas effacer cette ligne ! Elle est indispensable pour les services du Carnet en ligne |
// qui n'utilisent que le tableau pairs dans les posts |
$pairs = array_merge($pairs, $_POST); |
} |
// gestion du contenu du post |
if(isset($_POST)) |
{ |
// Safari ne sait pas envoyer des DELETE avec gwt... |
// Nous utilisons le parametre "action" passé dans le POST qui doit contenir DELETE pour lancer la supression |
if ($pairs['action'] == 'DELETE') { |
$this->delete(); |
return; |
} |
if (count($pairs) != 0) { |
if ($this->uid) { // get a resource element |
$resource_file = 'services/'.ucfirst($this->resource).'.php'; |
$resource_class = ucfirst($this->resource); |
if (file_exists($resource_file)) { |
include_once $resource_file; |
if (class_exists($resource_class)) { |
$service = new $resource_class($this->config); |
if (method_exists($service,'updateElement')) { // Update element |
// TODO : a voir le retour ... |
if ($service->updateElement($this->uid, $pairs)) { |
$this->created(); |
} |
} |
} |
} |
} else { // get all elements of a ressource |
$this->add($pairs); |
} |
} else { |
$this->lengthRequired(); |
} |
} |
} |
private function delete() { |
$resource_file = 'services/'.ucfirst($this->resource).'.php'; |
$resource_class = ucfirst($this->resource); |
if (file_exists($resource_file)) { |
include_once $resource_file; |
if (class_exists($resource_class)) { |
$service = new $resource_class($this->config); |
if ($this->uid) { // get a resource element |
if (method_exists($service, 'deleteElement')) { // Delete element |
if ($service->deleteElement($this->uid)) { |
$this->noContent(); |
} |
} |
} |
} |
} |
} |
private function add($pairs = null) { |
if (is_null($pairs)) { |
$pairs = array(); |
// Récupération des paramètres passés dans le contenu de la requête HTTP (= POST) |
// FIXME : vérifier que l'on récupère bien les données passées par PUT |
if ($this->requestData) { |
$pairs = $this->parseRequestData(); |
} |
} |
if (count($pairs) != 0) { |
$resource_file = 'services/'.ucfirst($this->resource).'.php'; |
$resource_class = ucfirst($this->resource); |
if (file_exists($resource_file)) { |
include_once $resource_file; |
if (class_exists($resource_class)) { |
$service = new $resource_class($this->config); |
if (method_exists($service,'createElement')) { // Create a new element |
if ($service->createElement($pairs)) { |
$this->created(); |
} |
} |
} |
} |
} else { |
$this->lengthRequired(); |
} |
} |
/** |
* Parse the HTTP request data. |
* @return str[] Array of name value pairs |
*/ |
private function parseRequestData() { |
$values = array(); |
$pairs = explode('&', $this->requestData); |
foreach ($pairs as $pair) { |
$parts = explode('=', $pair); |
if (isset($parts[0]) && isset($parts[1])) { |
$parts[1] = rtrim(urldecode($parts[1])); |
$values[$parts[0]] = $parts[1]; |
} |
} |
return $values; |
} |
/** |
* Send a HTTP 201 response header. |
*/ |
private function created($url = FALSE) { |
header('HTTP/1.0 201 Created'); |
if ($url) { |
header('Location: '.$url); |
} |
} |
/** |
* Send a HTTP 204 response header. |
*/ |
private function noContent() { |
header('HTTP/1.0 204 No Content'); |
} |
/** |
* Send a HTTP 400 response header. |
*/ |
private function badRequest() { |
header('HTTP/1.0 400 Bad Request'); |
} |
/** |
* Send a HTTP 401 response header. |
*/ |
private function unauthorized($realm = 'JRest') { |
if (!isset($_SERVER['PHP_AUTH_USER']) || !isset($_SERVER['PHP_AUTH_PW'])) { |
header('WWW-Authenticate: Basic realm="'.$realm.'"'); |
} |
header('HTTP/1.0 401 Unauthorized'); |
} |
/** |
* Send a HTTP 404 response header. |
*/ |
private function notFound() { |
header('HTTP/1.0 404 Not Found'); |
} |
/** |
* Send a HTTP 405 response header. |
*/ |
private function methodNotAllowed($allowed = 'GET, HEAD') { |
header('HTTP/1.0 405 Method Not Allowed'); |
header('Allow: '.$allowed); |
} |
/** |
* Send a HTTP 406 response header. |
*/ |
private function notAcceptable() { |
header('HTTP/1.0 406 Not Acceptable'); |
echo join(', ', array_keys($this->config['renderers'])); |
} |
/** |
* Send a HTTP 411 response header. |
*/ |
private function lengthRequired() { |
header('HTTP/1.0 411 Length Required'); |
} |
/** |
* Send a HTTP 500 response header. |
*/ |
private function internalServerError() { |
header('HTTP/1.0 500 Internal Server Error'); |
} |
} |
?> |
/trunk/jrest/cli.php |
---|
New file |
0,0 → 1,70 |
<?php |
/** |
* Script d'appel aux fonctions de jrest par ligne de commande, pour le moment ne supporte pas |
* correctement les méthodes ayant des paramètres |
* |
*/ |
/** |
* La fonction __autoload() charge dynamiquement les classes trouvées dans le code. |
* |
* Cette fonction est appelée par php5 quand il trouve une instanciation de classe dans le code. |
* |
*@param string le nom de la classe appelée. |
*@return void le fichier contenant la classe doit être inclu par la fonction. |
*/ |
function __autoload($classe) |
{ |
if (class_exists($classe)) { |
return null; |
} |
$chemins = array('', 'services/', 'services/include/', 'lib/'); |
foreach ($chemins as $chemin) { |
$chemin = $chemin.$classe.'.php'; |
if (file_exists($chemin)) { |
require_once $chemin; |
} |
} |
} |
if(php_sapi_name() == 'cli') { |
if ($_SERVER['argc'] < 2){ |
trigger_error("Erreur: vous n'avez pas indiqué le nom du service à appeler."); |
exit; |
} |
// suppression du premier paramètre qui est le nom du script |
array_shift($argv); |
$nom_service = array_shift($argv); |
if ($_SERVER['argc'] < 2){ |
trigger_error("Erreur: vous n'avez pas indiqué le nom de la méthode"); |
exit; |
} |
$nom_methode = array_shift($argv); |
$params = $argv; |
$config = parse_ini_file('jrest.ini.php', TRUE); |
$service = new $nom_service($config); |
if(!is_callable(array($service, $nom_methode))) { |
trigger_error("Erreur: la méthode ".$nom_methode." n'existe pas ou n'est pas accessible"); |
exit; |
} |
// exécution de la méthode |
$service->$nom_methode($params); |
exit; |
} else { |
trigger_error("Erreur: ce fichier est destiné a être appelé en ligne de commande."); |
exit; |
} |
?> |
/trunk/jrest/index.php |
---|
1,38 → 1,38 |
<?php |
// Decommenter ces lignes si version de php < 5 |
//require_once 'lib/JSON.php'; |
// Lazy require |
// TODO : voir si on ne peut pas dépacer ces inclusions directement dans les services. |
//require_once 'lib/DBAccessor.php'; |
//require_once 'lib/SpreadsheetProductor.php'; |
//require_once 'lib/PDFProductor.php'; |
//require 'JRest.php'; |
/** |
* La fonction __autoload() charge dynamiquement les classes trouvées dans le code. |
* |
* Cette fonction est appelée par php5 quand il trouve une instanciation de classe dans le code. |
* |
*@param string le nom de la classe appelée. |
*@return void le fichier contenant la classe doit être inclu par la fonction. |
*/ |
function __autoload($classe) |
{ |
if (class_exists($classe)) { |
return null; |
} |
$chemins = array('', 'services/', 'services/include/', 'lib/'); |
foreach ($chemins as $chemin) { |
$chemin = $chemin.$classe.'.php'; |
if (file_exists($chemin)) { |
require_once $chemin; |
} |
} |
} |
$jRest =& new JRest(); |
$jRest->exec(); |
<?php |
// Decommenter ces lignes si version de php < 5 |
//require_once 'lib/JSON.php'; |
// Lazy require |
// TODO : voir si on ne peut pas dépacer ces inclusions directement dans les services. |
//require_once 'lib/DBAccessor.php'; |
//require_once 'lib/SpreadsheetProductor.php'; |
//require_once 'lib/PDFProductor.php'; |
//require 'JRest.php'; |
/** |
* La fonction __autoload() charge dynamiquement les classes trouvées dans le code. |
* |
* Cette fonction est appelée par php5 quand il trouve une instanciation de classe dans le code. |
* |
*@param string le nom de la classe appelée. |
*@return void le fichier contenant la classe doit être inclu par la fonction. |
*/ |
function __autoload($classe) |
{ |
if (class_exists($classe)) { |
return null; |
} |
$chemins = array('', 'services/', 'services/include/', 'lib/'); |
foreach ($chemins as $chemin) { |
$chemin = $chemin.$classe.'.php'; |
if (file_exists($chemin)) { |
require_once $chemin; |
} |
} |
} |
$jRest =& new JRest(); |
$jRest->exec(); |
?> |
/trunk/jrest/util/phpMyEdit.class.php |
---|
New file |
0,0 → 1,3312 |
<?php |
/* |
* phpMyEdit - instant MySQL table editor and code generator |
* |
* phpMyEdit.class.php - main table editor class definition file |
* ____________________________________________________________ |
* |
* Copyright (c) 1999-2002 John McCreesh <jpmcc@users.sourceforge.net> |
* Copyright (c) 2001-2002 Jim Kraai <jkraai@users.sourceforge.net> |
* Versions 5.0 and higher developed by Ondrej Jombik <nepto@php.net> |
* Copyright (c) 2002-2006 Platon Group, http://platon.sk/ |
* All rights reserved. |
* |
* See README file for more information about this software. |
* See COPYING file for license information. |
* |
* Download the latest version from |
* http://platon.sk/projects/phpMyEdit/ |
*/ |
/* $Platon: phpMyEdit/phpMyEdit.class.php,v 1.188 2006-09-08 16:30:31 michal Exp $ */ |
/* This is a generic table editing program. The table and fields to be |
edited are defined in the calling program. |
This program works in three passes. |
* Pass 1 (the last part of the program) displays the selected MySQL |
table in a scrolling table on the screen. Radio buttons are used to |
select a record for editing or deletion. If the user chooses Add, |
Change, Copy, View or Delete buttons. |
* Pass 2 starts, displaying the selected record. If the user chooses |
the Save button from this screen. |
* Pass 3 processes the update and the display returns to the |
original table view (Pass 1). |
*/ |
class phpMyEdit_timer /* {{{ */ |
{ |
var $startTime; |
var $started; |
function phpMyEdit_timer($start = true) |
{ |
$this->started = false; |
if ($start) { |
$this->start(); |
} |
} |
function start() |
{ |
$startMtime = explode(' ', microtime()); |
$this->startTime = (double) $startMtime[0] + (double) $startMtime[1]; |
$this->started = true; |
} |
function end($iterations = 1) |
{ |
// get the time, check whether the timer was started later |
$endMtime = explode(' ', microtime()); |
if ($this->started) { |
$endTime = (double)($endMtime[0])+(double)($endMtime[1]); |
$dur = $endTime - $this->startTime; |
$avg = 1000 * $dur / $iterations; |
$avg = round(1000 * $avg) / 1000; |
return $avg; |
} else { |
return 'phpMyEdit_timer ERROR: timer not started'; |
} |
} |
} /* }}} */ |
if (! function_exists('array_search')) { /* {{{ */ |
function array_search($needle, $haystack) |
{ |
foreach ($haystack as $key => $value) { |
if ($needle == $value) |
return $key; |
} |
return false; |
} |
} /* }}} */ |
if (! function_exists('realpath')) { /* {{{ */ |
function realpath($path) |
{ |
return $path; |
} |
} /* }}} */ |
class phpMyEdit |
{ |
// Class variables {{{ |
// Database handling |
var $hn; // hostname |
var $un; // user name |
var $pw; // password |
var $tb; // table |
var $db; // database |
var $dbp; // database with point |
var $dbh; // database handle |
var $close_dbh; // if database handle should be closed |
// Record manipulation |
var $key; // name of field which is the unique key |
var $key_num; // number of field which is the unique key |
var $key_type; // type of key field (int/real/string/date etc.) |
var $key_delim; // character used for key value quoting |
var $rec; // number of record selected for editing |
var $inc; // number of records to display |
var $fm; // first record to display |
var $fl; // is the filter row displayed (boolean) |
var $fds; // sql field names |
var $fdn; // sql field names => $k |
var $num_fds; // number of fields |
var $options; // options for users: ACDFVPI |
var $fdd; // field definitions |
var $qfn; // value of all filters used during the last pass |
var $sfn; // sort field number (- = descending sort order) |
var $cur_tab; // current selected tab |
// Operation |
var $navop; // navigation buttons/operations |
var $sw; // filter display/hide/clear button |
var $operation; // operation to do: Add, Change, Delete |
var $saveadd; |
var $moreadd; |
var $canceladd; |
var $savechange; |
var $morechange; |
var $cancelchange; |
var $savecopy; |
var $cancelcopy; |
var $savedelete; |
var $canceldelete; |
var $cancelview; |
// Additional features |
var $labels; // multilingual labels |
var $cgi; // CGI variable features array |
var $js; // JS configuration array |
var $dhtml; // DHTML configuration array |
var $url; // URL array |
var $message; // informational message to print |
var $notify; // change notification e-mail adresses |
var $logtable; // name of optional logtable |
var $navigation; // navigation style |
var $tabs; // TAB names |
var $timer = null; // phpMyEdit_timer object |
// Predefined variables |
var $comp_ops = array('<'=>'<','<='=>'<=','='=>'=','>='=>'>=','>'=>'>'); |
var $sql_aggrs = array( |
'sum' => 'Total', |
'avg' => 'Average', |
'min' => 'Minimum', |
'max' => 'Maximum', |
'count' => 'Count'); |
var $page_types = array( |
'L' => 'list', |
'F' => 'filter', |
'A' => 'add', |
'V' => 'view', |
'C' => 'change', |
'P' => 'copy', |
'D' => 'delete' |
); |
var $default_buttons = array( |
'L' => array('<<','<','add','view','change','copy','delete','>','>>','goto','goto_combo'), |
'F' => array('<<','<','add','view','change','copy','delete','>','>>','goto','goto_combo'), |
'A' => array('save','more','cancel'), |
'C' => array('save','more','cancel'), |
'P' => array('save', 'cancel'), |
'D' => array('save','cancel'), |
'V' => array('change','cancel') |
); |
// }}} |
/* |
* column specific functions |
*/ |
function col_has_sql($k) { return isset($this->fdd[$k]['sql']); } |
function col_has_sqlw($k) { return isset($this->fdd[$k]['sqlw']) && !$this->virtual($k); } |
function col_has_values($k) { return isset($this->fdd[$k]['values']) || isset($this->fdd[$k]['values2']); } |
function col_has_php($k) { return isset($this->fdd[$k]['php']); } |
function col_has_URL($k) { return isset($this->fdd[$k]['URL']) |
|| isset($this->fdd[$k]['URLprefix']) || isset($this->fdd[$k]['URLpostfix']); } |
function col_has_multiple($k) |
{ return $this->col_has_multiple_select($k) || $this->col_has_checkboxes($k); } |
function col_has_multiple_select($k) |
{ return $this->fdd[$k]['select'] == 'M' && ! $this->fdd[$k]['values']['table']; } |
function col_has_checkboxes($k) |
{ return $this->fdd[$k]['select'] == 'C' && ! $this->fdd[$k]['values']['table']; } |
function col_has_radio_buttons($k) |
{ return $this->fdd[$k]['select'] == 'O' && ! $this->fdd[$k]['values']['table']; } |
function col_has_datemask($k) |
{ return isset($this->fdd[$k]['datemask']) || isset($this->fdd[$k]['strftimemask']); } |
/* |
* functions for indicating whether navigation style is enabled |
*/ |
function nav_buttons() { return stristr($this->navigation, 'B'); } |
function nav_text_links() { return stristr($this->navigation, 'T'); } |
function nav_graphic_links() { return stristr($this->navigation, 'G'); } |
function nav_up() { return (stristr($this->navigation, 'U') && !($this->buttons[$this->page_type]['up'] === false)); } |
function nav_down() { return (stristr($this->navigation, 'D') && !($this->buttons[$this->page_type]['down'] === false)); } |
/* |
* functions for indicating whether operations are enabled |
*/ |
function add_enabled() { return stristr($this->options, 'A'); } |
function change_enabled() { return stristr($this->options, 'C'); } |
function delete_enabled() { return stristr($this->options, 'D'); } |
function filter_enabled() { return stristr($this->options, 'F'); } |
function view_enabled() { return stristr($this->options, 'V'); } |
function copy_enabled() { return stristr($this->options, 'P') && $this->add_enabled(); } |
function tabs_enabled() { return $this->display['tabs'] && count($this->tabs) > 0; } |
function hidden($k) { return stristr($this->fdd[$k]['input'],'H'); } |
function password($k) { return stristr($this->fdd[$k]['input'],'W'); } |
function readonly($k) { return stristr($this->fdd[$k]['input'],'R') || $this->virtual($k); } |
function virtual($k) { return stristr($this->fdd[$k]['input'],'V') && $this->col_has_sql($k); } |
function add_operation() { return $this->operation == $this->labels['Add'] && $this->add_enabled(); } |
function change_operation() { return $this->operation == $this->labels['Change'] && $this->change_enabled(); } |
function copy_operation() { return $this->operation == $this->labels['Copy'] && $this->copy_enabled(); } |
function delete_operation() { return $this->operation == $this->labels['Delete'] && $this->delete_enabled(); } |
function view_operation() { return $this->operation == $this->labels['View'] && $this->view_enabled(); } |
function filter_operation() { return $this->fl && $this->filter_enabled() && $this->list_operation(); } |
function list_operation() { /* covers also filtering page */ return ! $this->change_operation() |
&& ! $this->add_operation() && ! $this->copy_operation() |
&& ! $this->delete_operation() && ! $this->view_operation(); } |
function next_operation() { return ($this->navop == $this->labels['Next']) || ($this->navop == '>'); } |
function prev_operation() { return ($this->navop == $this->labels['Prev']) || ($this->navop == '<'); } |
function first_operation() { return ($this->navop == $this->labels['First']) || ($this->navop == '<<'); } |
function last_operation() { return ($this->navop == $this->labels['Last']) || ($this->navop == '>>'); } |
function clear_operation() { return $this->sw == $this->labels['Clear']; } |
function add_canceled() { return $this->canceladd == $this->labels['Cancel']; } |
function view_canceled() { return $this->cancelview == $this->labels['Cancel']; } |
function change_canceled() { return $this->cancelchange == $this->labels['Cancel']; } |
function copy_canceled() { return $this->cancelcopy == $this->labels['Cancel']; } |
function delete_canceled() { return $this->canceldelete == $this->labels['Cancel']; } |
function is_values2($k, $val = 'X') /* {{{ */ |
{ |
return $val === null || |
(isset($this->fdd[$k]['values2']) && !isset($this->fdd[$k]['values']['table'])); |
} /* }}} */ |
function processed($k) /* {{{ */ |
{ |
if ($this->virtual($k)) { |
return false; |
} |
$options = @$this->fdd[$k]['options']; |
if (! isset($options)) { |
return true; |
} |
return |
($this->saveadd == $this->labels['Save'] && stristr($options, 'A')) || |
($this->moreadd == $this->labels['More'] && stristr($options, 'A')) || |
($this->savechange == $this->labels['Save'] && stristr($options, 'C')) || |
($this->morechange == $this->labels['Apply'] && stristr($options, 'C')) || |
($this->savecopy == $this->labels['Save'] && stristr($options, 'P')) || |
($this->savedelete == $this->labels['Save'] && stristr($options, 'D')); |
} /* }}} */ |
function displayed($k) /* {{{ */ |
{ |
if (is_numeric($k)) { |
$k = $this->fds[$k]; |
} |
$options = @$this->fdd[$k]['options']; |
if (! isset($options)) { |
return true; |
} |
return |
($this->add_operation() && stristr($options, 'A')) || |
($this->view_operation() && stristr($options, 'V')) || |
($this->change_operation() && stristr($options, 'C')) || |
($this->copy_operation() && stristr($options, 'P')) || |
($this->delete_operation() && stristr($options, 'D')) || |
($this->filter_operation() && stristr($options, 'F')) || |
($this->list_operation() && stristr($options, 'L')); |
} /* }}} */ |
function debug_var($name, $val) /* {{{ */ |
{ |
if (is_array($val) || is_object($val)) { |
echo "<pre>$name\n"; |
ob_start(); |
//print_r($val); |
var_dump($val); |
$content = ob_get_contents(); |
ob_end_clean(); |
echo htmlspecialchars($content); |
echo "</pre>\n"; |
} else { |
echo 'debug_var()::<i>',htmlspecialchars($name),'</i>'; |
echo '::<b>',htmlspecialchars($val),'</b>::',"<br />\n"; |
} |
} /* }}} */ |
function myquery($qry, $line = 0, $debug = 0) /* {{{ */ |
{ |
global $debug_query; |
if ($debug_query || $debug) { |
$line = intval($line); |
echo '<h4>MySQL query at line ',$line,'</h4>',htmlspecialchars($qry),'<hr />',"\n"; |
} |
if (isset($this->db)) { |
$ret = @mysql_db_query($this->db, $qry, $this->dbh); |
} else { |
$ret = @mysql_query($qry, $this->dbh); |
} |
if (! $ret) { |
echo '<h4>MySQL error ',mysql_errno($this->dbh),'</h4>'; |
echo htmlspecialchars(mysql_error($this->dbh)),'<hr />',"\n"; |
} |
return $ret; |
} /* }}} */ |
function make_language_labels($language) /* {{{ */ |
{ |
// just try the first language and variant |
// this isn't content-negotiation rfc compliant |
$language = strtoupper($language); |
// try the full language w/ variant |
$file = $this->dir['lang'].'PME.lang.'.$language.'.inc'; |
if (! file_exists($file)) { |
// try the language w/o variant |
$file = $this->dir['lang'].'PME.lang.'.substr($language,0,2).'.inc'; |
} |
if (! file_exists($file)) { |
// default to classical English |
$file = $this->dir['lang'].'PME.lang.EN.inc'; |
} |
$ret = @include($file); |
if (! is_array($ret)) { |
return $ret; |
} |
$small = array( |
'Search' => 'v', |
'Hide' => '^', |
'Clear' => 'X', |
'Query' => htmlspecialchars('>')); |
if ((!$this->nav_text_links() && !$this->nav_graphic_links()) |
|| !isset($ret['Search']) || !isset($ret['Query']) |
|| !isset($ret['Hide']) || !isset($ret['Clear'])) { |
foreach ($small as $key => $val) { |
$ret[$key] = $val; |
} |
} |
return $ret; |
} /* }}} */ |
function set_values($field_num, $prepend = null, $append = null, $strict = false) /* {{{ */ |
{ |
return (array) $prepend + (array) $this->fdd[$field_num]['values2'] |
+ (isset($this->fdd[$field_num]['values']['table']) || $strict |
? $this->set_values_from_table($field_num, $strict) |
: array()) |
+ (array) $append; |
} /* }}} */ |
function set_values_from_table($field_num, $strict = false) /* {{{ */ |
{ |
$db = &$this->fdd[$field_num]['values']['db']; |
$table = &$this->fdd[$field_num]['values']['table']; |
$key = &$this->fdd[$field_num]['values']['column']; |
$desc = &$this->fdd[$field_num]['values']['description']; |
$dbp = isset($db) ? "$db." : $this->dbp; |
$qparts['type'] = 'select'; |
if ($table) { |
$qparts['select'] = 'DISTINCT '.$table.'.'.$key; |
if ($desc && is_array($desc) && is_array($desc['columns'])) { |
$qparts['select'] .= ',CONCAT('; // ) |
$num_cols = sizeof($desc['columns']); |
if (isset($desc['divs'][-1])) { |
$qparts['select'] .= '"'.addslashes($desc['divs'][-1]).'",'; |
} |
foreach ($desc['columns'] as $key => $val) { |
if ($val) { |
$qparts['select'] .= 'IFNULL('.$val.',"")'; |
if ($desc['divs'][$key]) { |
$qparts['select'] .= ',"'.addslashes($desc['divs'][$key]).'"'; |
} |
$qparts['select'] .= ','; |
} |
} |
$qparts['select']{strlen($qparts['select']) - 1} = ')'; |
$qparts['select'] .= ' AS PMEalias'.$field_num; |
$qparts['orderby'] = 'PMEalias'.$field_num; |
} else if ($desc && is_array($desc)) { |
// TODO |
} else if ($desc) { |
$qparts['select'] .= ','.$table.'.'.$desc; |
$qparts['orderby'] = $desc; |
} else if ($key) { |
$qparts['orderby'] = $key; |
} |
$qparts['from'] = "$dbp$table"; |
$ar = array( |
'table' => $table, |
'column' => $column, |
'description' => $desc); |
$qparts['where'] = $this->substituteVars($this->fdd[$field_num]['values']['filters'], $ar); |
if ($this->fdd[$field_num]['values']['orderby']) { |
$qparts['orderby'] = $this->substituteVars($this->fdd[$field_num]['values']['orderby'], $ar); |
} |
} else { /* simple value extraction */ |
$key = &$this->fds[$field_num]; |
$this->virtual($field_num) && $key = $this->fqn($field_num); |
$qparts['select'] = 'DISTINCT '.$key.' AS PMEkey'; |
$qparts['orderby'] = 'PMEkey'; |
$qparts['from'] = $this->dbp.$this->tb; |
} |
$values = array(); |
$res = $this->myquery($this->get_SQL_query($qparts), __LINE__); |
while ($row = @mysql_fetch_array($res, MYSQL_NUM)) { |
$values[$row[0]] = $desc ? $row[1] : $row[0]; |
} |
return $values; |
} /* }}} */ |
function fqn($field, $dont_desc = false, $dont_cols = false) /* {{{ */ |
{ |
is_numeric($field) || $field = array_search($field, $this->fds); |
// if read SQL expression exists use it |
if ($this->col_has_sql($field)) |
return $this->fdd[$field]['sql']; |
// on copy/change always use simple key retrieving |
if ($this->add_operation() |
|| $this->copy_operation() |
|| $this->change_operation()) { |
$ret = 'PMEtable0.'.$this->fds[$field]; |
} else { |
if ($this->fdd[$this->fds[$field]]['values']['description'] && ! $dont_desc) { |
$desc = &$this->fdd[$this->fds[$field]]['values']['description']; |
if (is_array($desc) && is_array($desc['columns'])) { |
$ret = 'CONCAT('; // ) |
$num_cols = sizeof($desc['columns']); |
if (isset($desc['divs'][-1])) { |
$ret .= '"'.addslashes($desc['divs'][-1]).'",'; |
} |
foreach ($desc['columns'] as $key => $val) { |
if ($val) { |
$ret .= 'PMEjoin'.$field.'.'.$val; |
if ($desc['divs'][$key]) { |
$ret .= ',"'.addslashes($desc['divs'][$key]).'"'; |
} |
$ret .= ','; |
} |
} |
$ret{strlen($ret) - 1} = ')'; |
} else if (is_array($desc)) { |
// TODO |
} else { |
$ret = 'PMEjoin'.$field.'.'.$this->fdd[$this->fds[$field]]['values']['description']; |
} |
// TODO: remove me |
} elseif (0 && $this->fdd[$this->fds[$field]]['values']['column'] && ! $dont_cols) { |
$ret = 'PMEjoin'.$field.'.'.$this->fdd[$this->fds[$field]]['values']['column']; |
} else { |
$ret = 'PMEtable0.'.$this->fds[$field]; |
} |
// TODO: not neccessary, remove me! |
if (is_array($this->fdd[$this->fds[$field]]['values2'])) { |
} |
} |
return $ret; |
} /* }}} */ |
function get_SQL_query($parts) /* {{{ */ |
{ |
foreach ($parts as $k => $v) { |
$parts[$k] = trim($parts[$k]); |
} |
switch ($parts['type']) { |
case 'select': |
$ret = 'SELECT '; |
if ($parts['DISTINCT']) |
$ret .= 'DISTINCT '; |
$ret .= $parts['select']; |
$ret .= ' FROM '.$parts['from']; |
if ($parts['where'] != '') |
$ret .= ' WHERE '.$parts['where']; |
if ($parts['groupby'] != '') |
$ret .= ' GROUP BY '.$parts['groupby']; |
if ($parts['having'] != '') |
$ret .= ' HAVING '.$parts['having']; |
if ($parts['orderby'] != '') |
$ret .= ' ORDER BY '.$parts['orderby']; |
if ($parts['limit'] != '') |
$ret .= ' LIMIT '.$parts['limit']; |
if ($parts['procedure'] != '') |
$ret .= ' PROCEDURE '.$parts['procedure']; |
break; |
case 'update': |
$ret = 'UPDATE '.$parts['table']; |
$ret .= ' SET '.$parts['fields']; |
if ($parts['where'] != '') |
$ret .= ' WHERE '.$parts['where']; |
break; |
case 'insert': |
$ret = 'INSERT INTO '.$parts['table']; |
$ret .= ' VALUES '.$parts['values']; |
break; |
case 'delete': |
$ret = 'DELETE FROM '.$parts['table']; |
if ($parts['where'] != '') |
$ret .= ' WHERE '.$parts['where']; |
break; |
default: |
die('unknown query type'); |
break; |
} |
return $ret; |
} /* }}} */ |
function get_SQL_column_list() /* {{{ */ |
{ |
$fields = array(); |
for ($k = 0; $k < $this->num_fds; $k++) { |
if (! $this->displayed[$k] && $k != $this->key_num) { |
continue; |
} |
$fields[] = $this->fqn($k).' AS qf'.$k; |
if ($this->col_has_values($k)) { |
$fields[] = $this->fqn($k, true, true).' AS qf'.$k.'_idx'; |
} |
if ($this->col_has_datemask($k)) { |
$fields[] = 'UNIX_TIMESTAMP('.$this->fqn($k).') AS qf'.$k.'_timestamp'; |
} |
} |
return join(',', $fields); |
} /* }}} */ |
function get_SQL_join_clause() /* {{{ */ |
{ |
$main_table = 'PMEtable0'; |
$join_clause = $this->tb." AS $main_table"; |
for ($k = 0, $numfds = sizeof($this->fds); $k < $numfds; $k++) { |
$main_column = $this->fds[$k]; |
if($this->fdd[$main_column]['values']['db']) { |
$dbp = $this->fdd[$main_column]['values']['db'].'.'; |
} else { |
$dbp = $this->dbp; |
} |
$table = @$this->fdd[$main_column]['values']['table']; |
$join_column = @$this->fdd[$main_column]['values']['column']; |
$join_desc = @$this->fdd[$main_column]['values']['description']; |
if ($join_desc != '' && $join_column != '') { |
$join_table = 'PMEjoin'.$k; |
$ar = array( |
'main_table' => $main_table, |
'main_column' => $main_column, |
'join_table' => $join_table, |
'join_column' => $join_column, |
'join_description' => $join_desc); |
$join_clause .= " LEFT OUTER JOIN $dbp$table AS $join_table ON ("; |
$join_clause .= isset($this->fdd[$main_column]['values']['join']) |
? $this->substituteVars($this->fdd[$main_column]['values']['join'], $ar) |
: "$join_table.$join_column = $main_table.$main_column"; |
if (isset($this->fdd[$main_column]['values']['filters'])) { |
$join_clause .= ' AND '; |
$join_clause .= $this->substituteVars($this->fdd[$main_column]['values']['filters'], $ar); |
} |
$join_clause .= ')'; |
} |
} |
return $join_clause; |
} /* }}} */ |
function get_SQL_where_from_query_opts($qp = null, $text = 0) /* {{{ */ |
{ |
if ($qp == null) { |
$qp = $this->query_opts; |
} |
$where = array(); |
foreach ($qp as $field => $ov) { |
if (is_numeric($field)) { |
$tmp_where = array(); |
foreach ($ov as $field2 => $ov2) { |
$tmp_where[] = sprintf('%s %s %s', $field2, $ov2['oper'], $ov2['value']); |
} |
$where[] = '('.join(' OR ', $tmp_where).')'; |
} else { |
if (is_array($ov['value'])) { |
$tmp_ov_val = ''; |
foreach ($ov['value'] as $ov_val) { |
strlen($tmp_ov_val) > 0 && $tmp_ov_val .= ' OR '; |
$tmp_ov_val .= sprintf('FIND_IN_SET("%s",%s)', $ov_val, $field); |
} |
$where[] = "($tmp_ov_val)"; |
} else { |
$where[] = sprintf('%s %s %s', $field, $ov['oper'], $ov['value']); |
} |
} |
} |
// Add any coder specified filters |
if (! $text && $this->filters) { |
$where[] = '('.$this->filters.')'; |
} |
if (count($where) > 0) { |
if ($text) { |
return str_replace('%', '*', join(' AND ',$where)); |
} else { |
return join(' AND ',$where); |
} |
} |
return ''; /* empty string */ |
} /* }}} */ |
function gather_query_opts() /* {{{ */ |
{ |
$this->query_opts = array(); |
$this->prev_qfn = $this->qfn; |
$this->qfn = ''; |
if ($this->clear_operation()) { |
return; |
} |
// gathers query options into an array, $this->query_opts |
$qo = array(); |
for ($k = 0; $k < $this->num_fds; $k++) { |
$l = 'qf'.$k; |
$lc = 'qf'.$k.'_comp'; |
$li = 'qf'.$k.'_id'; |
$m = $this->get_sys_cgi_var($l); |
$mc = $this->get_sys_cgi_var($lc); |
$mi = $this->get_sys_cgi_var($li); |
if (! isset($m) && ! isset($mi)) { |
continue; |
} |
if (is_array($m) || is_array($mi)) { |
if (is_array($mi)) { |
$m = $mi; |
$l = $li; |
} |
if (in_array('*', $m)) { |
continue; |
} |
if ($this->col_has_values($k) && $this->col_has_multiple($k)) { |
foreach (array_keys($m) as $key) { |
$m[$key] = addslashes($m[$key]); |
} |
$qo[$this->fqn($k)] = array('value' => $m); |
} else { |
$qf_op = ''; |
foreach (array_keys($m) as $key) { |
if ($qf_op == '') { |
$qf_op = 'IN'; |
$qf_val = '"'.addslashes($m[$key]).'"'; |
$afilter = ' IN ("'.addslashes($m[$key]).'"'; // ) |
} else { |
$afilter = $afilter.',"'.addslashes($m[$key]).'"'; |
$qf_val .= ',"'.addslashes($m[$key]).'"'; |
} |
$this->qfn .= '&'.$this->cgi['prefix']['sys'].$l.'['.rawurlencode($key).']='.rawurlencode($m[$key]); |
} |
$afilter = $afilter.')'; |
// XXX: $dont_desc and $dont_cols hack |
$dont_desc = isset($this->fdd[$k]['values']['description']); |
$dont_cols = isset($this->fdd[$k]['values']['column']); |
$qo[$this->fqn($k, $dont_desc, $dont_cols)] = |
array('oper' => $qf_op, 'value' => "($qf_val)"); // ) |
} |
} else if (isset($mi)) { |
if ($mi == '*') { |
continue; |
} |
if ($this->fdd[$k]['select'] != 'M' && $this->fdd[$k]['select'] != 'D' && $mi == '') { |
continue; |
} |
$afilter = addslashes($mi); |
$qo[$this->fqn($k, true, true)] = array('oper' => '=', 'value' => "'$afilter'"); |
$this->qfn .= '&'.$this->cgi['prefix']['sys'].$li.'='.rawurlencode($mi); |
} else if (isset($m)) { |
if ($m == '*') { |
continue; |
} |
if ($this->fdd[$k]['select'] != 'M' && $this->fdd[$k]['select'] != 'D' && $m == '') { |
continue; |
} |
$afilter = addslashes($m); |
if ($this->fdd[$k]['select'] == 'N') { |
$mc = in_array($mc, $this->comp_ops) ? $mc : '='; |
$qo[$this->fqn($k)] = array('oper' => $mc, 'value' => "'$afilter'"); |
$this->qfn .= '&'.$this->cgi['prefix']['sys'].$l .'='.rawurlencode($m); |
$this->qfn .= '&'.$this->cgi['prefix']['sys'].$lc.'='.rawurlencode($mc); |
} else { |
$afilter = '%'.str_replace('*', '%', $afilter).'%'; |
$ids = array(); |
$ar = array(); |
$ar[$this->fqn($k)] = array('oper' => 'LIKE', 'value' => "'$afilter'"); |
if (is_array($this->fdd[$k]['values2'])) { |
foreach ($this->fdd[$k]['values2'] as $key => $val) { |
if (strlen($m) > 0 && stristr($val, $m)) { |
$ids[] = '"'.addslashes($key).'"'; |
} |
} |
if (count($ids) > 0) { |
$ar[$this->fqn($k, true, true)] |
= array('oper' => 'IN', 'value' => '('.join(',', $ids).')'); |
} |
} |
$qo[] = $ar; |
$this->qfn .= '&'.$this->cgi['prefix']['sys'].$l.'='.rawurlencode($m); |
} |
} |
} |
$this->query_opts = $qo; |
} /* }}} */ |
/* |
* Create JavaScripts |
*/ |
function form_begin() /* {{{ */ |
{ |
$page_name = htmlspecialchars($this->page_name); |
if ($this->add_operation() || $this->change_operation() || $this->copy_operation() |
|| $this->view_operation() || $this->delete_operation()) { |
$field_to_tab = array(); |
for ($tab = $k = $this->cur_tab = 0; $k < $this->num_fds; $k++) { |
if (isset($this->fdd[$k]['tab'])) { |
if ($tab == 0 && $k > 0) { |
$this->tabs[0] = 'PMEtab0'; |
$this->cur_tab = 1; |
$tab++; |
} |
if (is_array($this->fdd[$k]['tab'])) { |
$this->tabs[$tab] = @$this->fdd[$k]['tab']['name']; |
$this->fdd[$k]['tab']['default'] && $this->cur_tab = $tab; |
} else { |
$this->tabs[$tab] = @$this->fdd[$k]['tab']; |
} |
$tab++; |
} |
$field_to_tab[$k] = max(0, $tab - 1); |
} |
if (preg_match('/^'.$this->dhtml['prefix'].'tab(\d+)$/', $this->get_sys_cgi_var('cur_tab'), $parts)) { |
$this->cur_tab = $parts[1]; |
} |
if ($this->tabs_enabled()) { |
// initial TAB styles |
echo '<style type="text/css" media="screen">',"\n"; |
for ($i = 0; $i < count($this->tabs); $i++) { |
echo ' #'.$this->dhtml['prefix'].'tab',$i,' { display: '; |
echo (($i == $this->cur_tab || $this->tabs[$i] == 'PMEtab0' ) ? 'block' : 'none') ,'; }',"\n"; |
} |
echo '</style>',"\n"; |
// TAB javascripts |
echo '<script type="text/javascript"><!--',"\n\n"; |
$css_class_name1 = $this->getCSSclass('tab', $position); |
$css_class_name2 = $this->getCSSclass('tab-selected', $position); |
echo 'var '.$this->js['prefix'].'cur_tab = "'.$this->dhtml['prefix'].'tab',$this->cur_tab,'"; |
function '.$this->js['prefix'].'show_tab(tab_name) |
{'; |
if ($this->nav_up()) { |
echo ' |
document.getElementById('.$this->js['prefix'].'cur_tab+"_up_label").className = "',$css_class_name1,'"; |
document.getElementById('.$this->js['prefix'].'cur_tab+"_up_link").className = "',$css_class_name1,'"; |
document.getElementById(tab_name+"_up_label").className = "',$css_class_name2,'"; |
document.getElementById(tab_name+"_up_link").className = "',$css_class_name2,'";'; |
} |
if ($this->nav_down()) { |
echo ' |
document.getElementById('.$this->js['prefix'].'cur_tab+"_down_label").className = "',$css_class_name1,'"; |
document.getElementById('.$this->js['prefix'].'cur_tab+"_down_link").className = "',$css_class_name1,'"; |
document.getElementById(tab_name+"_down_label").className = "',$css_class_name2,'"; |
document.getElementById(tab_name+"_down_link").className = "',$css_class_name2,'";'; |
} |
echo ' |
document.getElementById('.$this->js['prefix'].'cur_tab).style.display = "none"; |
document.getElementById(tab_name).style.display = "block"; |
'.$this->js['prefix'].'cur_tab = tab_name; |
document.'.$this->cgi['prefix']['sys'].'form.'.$this->cgi['prefix']['sys'].'cur_tab.value = tab_name; |
}',"\n\n"; |
echo '// --></script>', "\n"; |
} |
} |
if ($this->add_operation() || $this->change_operation() || $this->copy_operation()) { |
$first_required = true; |
for ($k = 0; $k < $this->num_fds; $k++) { |
if ($this->displayed[$k] && ! $this->readonly($k) && ! $this->hidden($k) |
&& ($this->fdd[$k]['js']['required'] || isset($this->fdd[$k]['js']['regexp']))) { |
if ($first_required) { |
$first_required = false; |
echo '<script type="text/javascript"><!--',"\n"; |
echo ' |
function '.$this->js['prefix'].'trim(str) |
{ |
while (str.substring(0, 1) == " " |
|| str.substring(0, 1) == "\\n" |
|| str.substring(0, 1) == "\\r") |
{ |
str = str.substring(1, str.length); |
} |
while (str.substring(str.length - 1, str.length) == " " |
|| str.substring(str.length - 1, str.length) == "\\n" |
|| str.substring(str.length - 1, str.length) == "\\r") |
{ |
str = str.substring(0, str.length - 1); |
} |
return str; |
} |
function '.$this->js['prefix'].'form_control(theForm) |
{',"\n"; |
} |
if ($this->col_has_values($k)) { |
$condition = 'theForm.'.$this->cgi['prefix']['data'].$this->fds[$k].'.selectedIndex == -1'; |
$multiple = $this->col_has_multiple_select($k); |
} else { |
$condition = ''; |
$multiple = false; |
if ($this->fdd[$k]['js']['required']) { |
$condition = $this->js['prefix'].'trim(theForm.'.$this->cgi['prefix']['data'].$this->fds[$k].'.value) == ""'; |
} |
if (isset($this->fdd[$k]['js']['regexp'])) { |
$condition .= (strlen($condition) > 0 ? ' || ' : ''); |
$condition .= sprintf('!(%s.test('.$this->js['prefix'].'trim(theForm.%s.value)))', |
$this->fdd[$k]['js']['regexp'], $this->cgi['prefix']['data'].$this->fds[$k]); |
} |
} |
/* Multiple selects have their name like ``name[]''. |
It is not possible to work with them directly, because |
theForm.name[].something will result into JavaScript |
syntax error. Following search algorithm is provided |
as a workaround for this. |
*/ |
if ($multiple) { |
echo ' |
multiple_select = null; |
for (i = 0; i < theForm.length; i++) { |
if (theForm.elements[i].name == "',$this->cgi['prefix']['data'].$this->fds[$k],'[]") { |
multiple_select = theForm.elements[i]; |
break; |
} |
} |
if (multiple_select != null && multiple_select.selectedIndex == -1) {'; |
} else { |
echo ' |
if (',$condition,') {'; |
} |
echo ' |
alert("'; |
if (isset($this->fdd[$k]['js']['hint'])) { |
echo htmlspecialchars($this->fdd[$k]['js']['hint']); |
} else { |
echo $this->labels['Please enter'],' ',$this->fdd[$k]['name'],'.'; |
} |
echo '");'; |
if ($this->tabs_enabled() && $field_to_tab[$k] >= $this->cur_tab) { |
echo ' |
'.$this->js['prefix'].'show_tab("'.$this->dhtml['prefix'].'tab',$field_to_tab[$k],'");'; |
} |
echo ' |
theForm.',$this->cgi['prefix']['data'].$this->fds[$k],'.focus(); |
return false; |
}',"\n"; |
} |
} |
if (! $first_required) { |
echo ' |
return true; |
}',"\n\n"; |
echo '// --></script>', "\n"; |
} |
} |
if ($this->filter_operation()) { |
echo '<script type="text/javascript"><!--',"\n"; |
echo ' |
function '.$this->js['prefix'].'filter_handler(theForm, theEvent) |
{ |
var pressed_key = null; |
if (theEvent.which) { |
pressed_key = theEvent.which; |
} else { |
pressed_key = theEvent.keyCode; |
} |
if (pressed_key == 13) { // enter pressed |
theForm.submit(); |
return false; |
} |
return true; |
}',"\n\n"; |
echo '// --></script>', "\n"; |
} |
if ($this->display['form']) { |
echo '<form class="',$this->getCSSclass('form'),'" method="post"'; |
echo ' action="',$page_name,'" name="'.$this->cgi['prefix']['sys'].'form">',"\n"; |
} |
return true; |
} /* }}} */ |
function form_end() /* {{{ */ |
{ |
if ($this->display['form']) { |
echo '</form>',"\n"; |
} |
} /* }}} */ |
function display_tab_labels($position) /* {{{ */ |
{ |
if (! is_array($this->tabs)) { |
return false; |
} |
echo '<table summary="labels" class="',$this->getCSSclass('tab', $position),'">',"\n"; |
echo '<tr class="',$this->getCSSclass('tab', $position),'">',"\n"; |
for ($i = ($this->tabs[0] == 'PMEtab0' ? 1 : 0); $i < count($this->tabs); $i++) { |
$css_class_name = $this->getCSSclass($i != $this->cur_tab ? 'tab' : 'tab-selected', $position); |
echo '<td class="',$css_class_name,'" id="'.$this->dhtml['prefix'].'tab',$i,'_',$position,'_label">'; |
echo '<a class="',$css_class_name,'" id="'.$this->dhtml['prefix'].'tab',$i,'_',$position,'_link'; |
echo '" href="javascript:'.$this->js['prefix'].'show_tab(\''.$this->dhtml['prefix'].'tab',$i,'\')">'; |
echo $this->tabs[$i],'</a></td>',"\n"; |
} |
echo '<td class="',$this->getCSSclass('tab-end', $position),'"> </td>',"\n"; |
echo '</tr>',"\n"; |
echo '</table>',"\n"; |
} /* }}} */ |
/* |
* Display functions |
*/ |
function display_add_record() /* {{{ */ |
{ |
for ($tab = 0, $k = 0; $k < $this->num_fds; $k++) { |
if (isset($this->fdd[$k]['tab']) && $this->tabs_enabled() && $k > 0) { |
$tab++; |
echo '</table>',"\n"; |
echo '</div>',"\n"; |
echo '<div id="'.$this->dhtml['prefix'].'tab',$tab,'">',"\n"; |
echo '<table class="',$this->getCSSclass('main'),'" summary="',$this->tb,'">',"\n"; |
} |
if (! $this->displayed[$k]) { |
continue; |
} |
if ($this->hidden($k)) { |
echo $this->htmlHiddenData($this->fds[$k], $this->fdd[$k]['default']); |
continue; |
} |
$css_postfix = @$this->fdd[$k]['css']['postfix']; |
$css_class_name = $this->getCSSclass('input', null, 'next', $css_postfix); |
$escape = isset($this->fdd[$k]['escape']) ? $this->fdd[$k]['escape'] : true; |
echo '<tr class="',$this->getCSSclass('row', null, true, $css_postfix),'">',"\n"; |
echo '<td class="',$this->getCSSclass('key', null, true, $css_postfix),'">'; |
echo $this->fdd[$k]['name'],'</td>',"\n"; |
echo '<td class="',$this->getCSSclass('value', null, true, $css_postfix),'"'; |
echo $this->getColAttributes($k),">\n"; |
if ($this->col_has_values($k)) { |
$vals = $this->set_values($k); |
$selected = @$this->fdd[$k]['default']; |
$multiple = $this->col_has_multiple($k); |
$readonly = $this->readonly($k); |
$strip_tags = true; |
//$escape = true; |
if ($this->col_has_checkboxes($k) || $this->col_has_radio_buttons($k)) { |
echo $this->htmlRadioCheck($this->cgi['prefix']['data'].$this->fds[$k], |
$css_class_name, $vals, $selected, $multiple, $readonly, |
$strip_tags, $escape); |
} else { |
echo $this->htmlSelect($this->cgi['prefix']['data'].$this->fds[$k], |
$css_class_name, $vals, $selected, $multiple, $readonly, |
$strip_tags, $escape); |
} |
} elseif (isset ($this->fdd[$k]['textarea'])) { |
echo '<textarea class="',$css_class_name,'" name="',$this->cgi['prefix']['data'].$this->fds[$k],'"'; |
echo ($this->readonly($k) ? ' disabled="disabled"' : ''); |
if (intval($this->fdd[$k]['textarea']['rows']) > 0) { |
echo ' rows="',$this->fdd[$k]['textarea']['rows'],'"'; |
} |
if (intval($this->fdd[$k]['textarea']['cols']) > 0) { |
echo ' cols="',$this->fdd[$k]['textarea']['cols'],'"'; |
} |
if (isset($this->fdd[$k]['textarea']['wrap'])) { |
echo ' wrap="',$this->fdd[$k]['textarea']['wrap'],'"'; |
} else { |
echo ' wrap="virtual"'; |
} |
echo '>'; |
if($escape) echo htmlspecialchars($this->fdd[$k]['default']); |
else echo $this->fdd[$k]['default']; |
echo '</textarea>',"\n"; |
} elseif ($this->col_has_php($k)) { |
echo include($this->fdd[$k]['php']); |
} else { |
// Simple edit box required |
$size_ml_props = ''; |
$maxlen = intval($this->fdd[$k]['maxlen']); |
$size = isset($this->fdd[$k]['size']) ? $this->fdd[$k]['size'] : min($maxlen, 60); |
$size && $size_ml_props .= ' size="'.$size.'"'; |
$maxlen && $size_ml_props .= ' maxlength="'.$maxlen.'"'; |
echo '<input class="',$css_class_name,'" '; |
echo ($this->password($k) ? 'type="password"' : 'type="text"'); |
echo ($this->readonly($k) ? ' disabled="disabled"' : ''); |
echo ' name="',$this->cgi['prefix']['data'].$this->fds[$k],'"'; |
echo $size_ml_props,' value="'; |
if($escape) echo htmlspecialchars($this->fdd[$k]['default']); |
else echo $this->fdd[$k]['default']; |
echo '" />'; |
} |
echo '</td>',"\n"; |
if ($this->guidance) { |
$css_class_name = $this->getCSSclass('help', null, true, $css_postfix); |
$cell_value = $this->fdd[$k]['help'] ? $this->fdd[$k]['help'] : ' '; |
echo '<td class="',$css_class_name,'">',$cell_value,'</td>',"\n"; |
} |
echo '</tr>',"\n"; |
} |
} /* }}} */ |
function display_copy_change_delete_record() /* {{{ */ |
{ |
/* |
* For delete or change: SQL SELECT to retrieve the selected record |
*/ |
$qparts['type'] = 'select'; |
$qparts['select'] = $this->get_SQL_column_list(); |
$qparts['from'] = $this->get_SQL_join_clause(); |
$qparts['where'] = '('.$this->fqn($this->key).'=' |
.$this->key_delim.$this->rec.$this->key_delim.')'; |
$res = $this->myquery($this->get_SQL_query($qparts),__LINE__); |
if (! ($row = @mysql_fetch_array($res, MYSQL_ASSOC))) { |
return false; |
} |
for ($tab = 0, $k = 0; $k < $this->num_fds; $k++) { |
if (isset($this->fdd[$k]['tab']) && $this->tabs_enabled() && $k > 0) { |
$tab++; |
echo '</table>',"\n"; |
echo '</div>',"\n"; |
echo '<div id="'.$this->dhtml['prefix'].'tab',$tab,'">',"\n"; |
echo '<table class="',$this->getCSSclass('main'),'" summary="',$this->tb,'">',"\n"; |
} |
if (! $this->displayed[$k]) { |
continue; |
} |
if ($this->copy_operation() || $this->change_operation()) { |
if ($this->hidden($k)) { |
if ($k != $this->key_num) { |
echo $this->htmlHiddenData($this->fds[$k], $row["qf$k"]); |
} |
continue; |
} |
$css_postfix = @$this->fdd[$k]['css']['postfix']; |
echo '<tr class="',$this->getCSSclass('row', null, 'next', $css_postfix),'">',"\n"; |
echo '<td class="',$this->getCSSclass('key', null, true, $css_postfix),'">'; |
echo $this->fdd[$k]['name'],'</td>',"\n"; |
/* There are two possibilities of readonly fields handling: |
1. Display plain text for readonly timestamps, dates and URLs. |
2. Display disabled input field |
In all cases particular readonly field will NOT be saved. */ |
if ($this->readonly($k) && ($this->col_has_datemask($k) || $this->col_has_URL($k))) { |
echo $this->display_delete_field($row, $k); |
} elseif ($this->password($k)) { |
echo $this->display_password_field($row, $k); |
} else { |
echo $this->display_change_field($row, $k); |
} |
if ($this->guidance) { |
$css_class_name = $this->getCSSclass('help', null, true, $css_postfix); |
$cell_value = $this->fdd[$k]['help'] ? $this->fdd[$k]['help'] : ' '; |
echo '<td class="',$css_class_name,'">',$cell_value,'</td>',"\n"; |
} |
echo '</tr>',"\n"; |
} elseif ($this->delete_operation() || $this->view_operation()) { |
$css_postfix = @$this->fdd[$k]['css']['postfix']; |
echo '<tr class="',$this->getCSSclass('row', null, 'next', $css_postfix),'">',"\n"; |
echo '<td class="',$this->getCSSclass('key', null, true, $css_postfix),'">'; |
echo $this->fdd[$k]['name'],'</td>',"\n"; |
if ($this->password($k)) { |
echo '<td class="',$this->getCSSclass('value', null, true, $css_postfix),'"'; |
echo $this->getColAttributes($k),'>',$this->labels['hidden'],'</td>',"\n"; |
} else { |
$this->display_delete_field($row, $k); |
} |
if ($this->guidance) { |
$css_class_name = $this->getCSSclass('help', null, true, $css_postfix); |
$cell_value = $this->fdd[$k]['help'] ? $this->fdd[$k]['help'] : ' '; |
echo '<td class="',$css_class_name,'">',$cell_value,'</td>',"\n"; |
} |
echo '</tr>',"\n"; |
} |
} |
} /* }}} */ |
function display_change_field($row, $k) /* {{{ */ |
{ |
$css_postfix = @$this->fdd[$k]['css']['postfix']; |
$css_class_name = $this->getCSSclass('input', null, true, $css_postfix); |
$escape = isset($this->fdd[$k]['escape']) ? $this->fdd[$k]['escape'] : true; |
echo '<td class="',$this->getCSSclass('value', null, true, $css_postfix),'"'; |
echo $this->getColAttributes($k),">\n"; |
if ($this->col_has_values($k)) { |
$vals = $this->set_values($k); |
$multiple = $this->col_has_multiple($k); |
$readonly = $this->readonly($k); |
$strip_tags = true; |
//$escape = true; |
if ($this->col_has_checkboxes($k) || $this->col_has_radio_buttons($k)) { |
echo $this->htmlRadioCheck($this->cgi['prefix']['data'].$this->fds[$k], |
$css_class_name, $vals, $row["qf$k"], $multiple, $readonly, |
$strip_tags, $escape); |
} else { |
echo $this->htmlSelect($this->cgi['prefix']['data'].$this->fds[$k], |
$css_class_name, $vals, $row["qf$k"], $multiple, $readonly, |
$strip_tags, $escape); |
} |
} elseif (isset($this->fdd[$k]['textarea'])) { |
echo '<textarea class="',$css_class_name,'" name="',$this->cgi['prefix']['data'].$this->fds[$k],'"'; |
echo ($this->readonly($k) ? ' disabled="disabled"' : ''); |
if (intval($this->fdd[$k]['textarea']['rows']) > 0) { |
echo ' rows="',$this->fdd[$k]['textarea']['rows'],'"'; |
} |
if (intval($this->fdd[$k]['textarea']['cols']) > 0) { |
echo ' cols="',$this->fdd[$k]['textarea']['cols'],'"'; |
} |
if (isset($this->fdd[$k]['textarea']['wrap'])) { |
echo ' wrap="',$this->fdd[$k]['textarea']['wrap'],'"'; |
} else { |
echo ' wrap="virtual"'; |
} |
echo '>'; |
if($escape) echo htmlspecialchars($row["qf$k"]); |
else echo $row["qf$k"]; |
echo '</textarea>',"\n"; |
} elseif ($this->col_has_php($k)) { |
echo include($this->fdd[$k]['php']); |
} else { |
$size_ml_props = ''; |
$maxlen = intval($this->fdd[$k]['maxlen']); |
$size = isset($this->fdd[$k]['size']) ? $this->fdd[$k]['size'] : min($maxlen, 60); |
$size && $size_ml_props .= ' size="'.$size.'"'; |
$maxlen && $size_ml_props .= ' maxlength="'.$maxlen.'"'; |
echo '<input class="',$css_class_name,'" type="text" '; |
echo ($this->readonly($k) ? 'disabled="disabled" ' : ''); |
echo 'name="',$this->cgi['prefix']['data'].$this->fds[$k],'" value="'; |
if($escape) echo htmlspecialchars($row["qf$k"]); |
else echo $row["qf$k"]; |
echo '" />',"\n"; |
} |
echo '</td>',"\n"; |
} /* }}} */ |
function display_password_field($row, $k) /* {{{ */ |
{ |
$css_postfix = @$this->fdd[$k]['css']['postfix']; |
echo '<td class="',$this->getCSSclass('value', null, true, $css_postfix),'"'; |
echo $this->getColAttributes($k),">\n"; |
$size_ml_props = ''; |
$maxlen = intval($this->fdd[$k]['maxlen']); |
$size = isset($this->fdd[$k]['size']) ? $this->fdd[$k]['size'] : min($maxlen, 60); |
$size && $size_ml_props .= ' size="'.$size.'"'; |
$maxlen && $size_ml_props .= ' maxlength="'.$maxlen.'"'; |
echo '<input class="',$this->getCSSclass('value', null, true, $css_postfix),'" type="password" '; |
echo ($this->readonly($k) ? 'disabled="disabled" ' : ''); |
echo 'name="',$this->cgi['prefix']['data'].$this->fds[$k],'" value="'; |
echo htmlspecialchars($row["qf$k"]),'" ',$size_ml_props,' />',"\n"; |
echo '</td>',"\n"; |
} /* }}} */ |
function display_delete_field($row, $k) /* {{{ */ |
{ |
$css_postfix = @$this->fdd[$k]['css']['postfix']; |
$css_class_name = $this->getCSSclass('value', null, true, $css_postfix); |
echo '<td class="',$css_class_name,'"',$this->getColAttributes($k),">\n"; |
echo $this->cellDisplay($k, $row, $css_class_name); |
echo '</td>',"\n"; |
} /* }}} */ |
/** |
* Returns CSS class name |
*/ |
function getCSSclass($name, $position = null, $divider = null, $postfix = null) /* {{{ */ |
{ |
static $div_idx = -1; |
$elements = array($this->css['prefix'], $name); |
if ($this->page_type && $this->css['page_type']) { |
if ($this->page_type != 'L' && $this->page_type != 'F') { |
$elements[] = $this->page_types[$this->page_type]; |
} |
} |
if ($position && $this->css['position']) { |
$elements[] = $position; |
} |
if ($divider && $this->css['divider']) { |
if ($divider === 'next') { |
$div_idx++; |
if ($this->css['divider'] > 0 && $div_idx >= $this->css['divider']) { |
$div_idx = 0; |
} |
} |
$elements[] = $div_idx; |
} |
if ($postfix) { |
$elements[] = $postfix; |
} |
return join($this->css['separator'], $elements); |
} /* }}} */ |
/** |
* Returns field cell HTML attributes |
*/ |
function getColAttributes($k) /* {{{ */ |
{ |
$colattrs = ''; |
if (isset($this->fdd[$k]['colattrs'])) { |
$colattrs .= ' '; |
$colattrs .= trim($this->fdd[$k]['colattrs']); |
} |
if (isset($this->fdd[$k]['nowrap'])) { |
$colattrs .= ' nowrap'; |
} |
return $colattrs; |
} /* }}} */ |
/** |
* Substitutes variables in string |
* (this is very simple but secure eval() replacement) |
*/ |
function substituteVars($str, $subst_ar) /* {{{ */ |
{ |
$array = preg_split('/(\\$\w+)/', $str, -1, PREG_SPLIT_DELIM_CAPTURE); |
$count = count($array); |
for ($i = 1; $i < $count; $i += 2) { |
$key = substr($array[$i], 1); |
if (isset($subst_ar[$key])) { |
$array[$i] = $subst_ar[$key]; |
} |
} |
return join('', $array); |
} /* }}} */ |
/** |
* Print URL |
*/ |
function urlDisplay($k, $link_val, $disp_val, $css, $key) /* {{{ */ |
{ |
$escape = isset($this->fdd[$k]['escape']) ? $this->fdd[$k]['escape'] : true; |
$ret = ''; |
$name = $this->fds[$k]; |
$page = $this->page_name; |
$url = $this->cgi['prefix']['sys'].'rec'.'='.$key.'&'.$this->cgi['prefix']['sys'].'fm' |
.'='.$this->fm.'&'.$this->cgi['prefix']['sys'].'fl'.'='.$this->fl; |
$url .= '&'.$this->cgi['prefix']['sys'].'qfn'.'='.rawurlencode($this->qfn).$this->qfn; |
$url .= '&'.$this->get_sfn_cgi_vars().$this->cgi['persist']; |
$ar = array( |
'key' => $key, |
'name' => $name, |
'link' => $link_val, |
'value' => $disp_val, |
'css' => $css, |
'page' => $page, |
'url' => $url |
); |
$urllink = isset($this->fdd[$k]['URL']) |
? $this->substituteVars($this->fdd[$k]['URL'], $ar) |
: $link_val; |
$urldisp = isset($this->fdd[$k]['URLdisp']) |
? $this->substituteVars($this->fdd[$k]['URLdisp'], $ar) |
: $disp_val; |
$target = isset($this->fdd[$k]['URLtarget']) |
? 'target="'.htmlspecialchars($this->fdd[$k]['URLtarget']).'" ' |
: ''; |
$prefix_found = false; |
$postfix_found = false; |
$prefix_ar = @$this->fdd[$k]['URLprefix']; |
$postfix_ar = @$this->fdd[$k]['URLpostfix']; |
is_array($prefix_ar) || $prefix_ar = array($prefix_ar); |
is_array($postfix_ar) || $postfix_ar = array($postfix_ar); |
foreach ($prefix_ar as $prefix) { |
if (! strncmp($prefix, $urllink, strlen($prefix))) { |
$prefix_found = true; |
break; |
} |
} |
foreach ($postfix_ar as $postfix) { |
if (! strncmp($postfix, $urllink, strlen($postfix))) { |
$postfix_found = true; |
break; |
} |
} |
$prefix_found || $urllink = array_shift($prefix_ar).$urllink; |
$postfix_found || $urllink = $urllink.array_shift($postfix_ar); |
if (strlen($urllink) <= 0 || strlen($urldisp) <= 0) { |
$ret = ' '; |
} else { |
if ($escape) { |
$urldisp = htmlspecialchars($urldisp); |
} |
$urllink = htmlspecialchars($urllink); |
$ret = '<a '.$target.'class="'.$css.'" href="'.$urllink.'">'.$urldisp.'</a>'; |
} |
return $ret; |
} /* }}} */ |
function cellDisplay($k, $row, $css) /* {{{ */ |
{ |
$escape = isset($this->fdd[$k]['escape']) ? $this->fdd[$k]['escape'] : true; |
$key_rec = $row['qf'.$this->key_num]; |
if (@$this->fdd[$k]['datemask']) { |
$value = intval($row["qf$k".'_timestamp']); |
$value = $value ? @date($this->fdd[$k]['datemask'], $value) : ''; |
} else if (@$this->fdd[$k]['strftimemask']) { |
$value = intval($row["qf$k".'_timestamp']); |
$value = $value ? @strftime($this->fdd[$k]['strftimemask'], $value) : ''; |
} else if ($this->is_values2($k, $row["qf$k"])) { |
$value = $row['qf'.$k.'_idx']; |
if ($this->fdd[$k]['select'] == 'M') { |
$value_ar = explode(',', $value); |
$value_ar2 = array(); |
foreach ($value_ar as $value_key) { |
if (isset($this->fdd[$k]['values2'][$value_key])) { |
$value_ar2[$value_key] = $this->fdd[$k]['values2'][$value_key]; |
$escape = false; |
} |
} |
$value = join(', ', $value_ar2); |
} else { |
if (isset($this->fdd[$k]['values2'][$value])) { |
$value = $this->fdd[$k]['values2'][$value]; |
$escape = false; |
} |
} |
} elseif (isset($this->fdd[$k]['values2'][$row["qf$k"]])) { |
$value = $this->fdd[$k]['values2'][$row["qf$k"]]; |
} else { |
$value = $row["qf$k"]; |
} |
$original_value = $value; |
if (@$this->fdd[$k]['strip_tags']) { |
$value = strip_tags($value); |
} |
if ($num_ar = @$this->fdd[$k]['number_format']) { |
if (! is_array($num_ar)) { |
$num_ar = array($num_ar); |
} |
if (count($num_ar) == 1) { |
list($nbDec) = $num_ar; |
$value = number_format($value, $nbDec); |
} else if (count($num_ar) == 3) { |
list($nbDec, $decPoint, $thSep) = $num_ar; |
$value = number_format($value, $nbDec, $decPoint, $thSep); |
} |
} |
if (intval($this->fdd[$k]['trimlen']) > 0 && strlen($value) > $this->fdd[$k]['trimlen']) { |
$value = ereg_replace("[\r\n\t ]+",' ',$value); |
$value = substr($value, 0, $this->fdd[$k]['trimlen'] - 3).'...'; |
} |
if (@$this->fdd[$k]['mask']) { |
$value = sprintf($this->fdd[$k]['mask'], $value); |
} |
if ($this->col_has_php($k)) { |
return include($this->fdd[$k]['php']); |
} |
if ($this->col_has_URL($k)) { |
return $this->urlDisplay($k, $original_value, $value, $css, $key_rec); |
} |
if (strlen($value) <= 0) { |
return ' '; |
} |
if ($escape) { |
$value = htmlspecialchars($value); |
} |
return nl2br($value); |
} /* }}} */ |
/** |
* Creates HTML submit input element |
* |
* @param name element name |
* @param label key in the language hash used as label |
* @param css_class_name CSS class name |
* @param js_validation if add JavaScript validation subroutine to button |
* @param disabled if mark the button as disabled |
* @param js any extra text in tags |
*/ |
function htmlSubmit($name, $label, $css_class_name, $js_validation = true, $disabled = false, $js = NULL) /* {{{ */ |
{ |
// Note that <input disabled> isn't valid HTML, but most browsers support it |
if($disabled == -1) return; |
$markdisabled = $disabled ? ' disabled="disabled"' : ''; |
$ret = '<input'.$markdisabled.' type="submit" class="'.$css_class_name |
.'" name="'.$this->cgi['prefix']['sys'].ltrim($markdisabled).$name |
.'" value="'.(isset($this->labels[$label]) ? $this->labels[$label] : $label); |
if ($js_validation) { |
$ret .= '" onclick="return '.$this->js['prefix'].'form_control(this.form);'; |
} |
$ret .='"'; |
if(isset($js)) $ret .= ' '.$js; |
$ret .= ' />'; |
return $ret; |
} /* }}} */ |
/** |
* Creates HTML hidden input element |
* |
* @param name element name |
* @param value value |
*/ |
function htmlHiddenSys($name, $value) /* {{{ */ |
{ |
return $this->htmlHidden($this->cgi['prefix']['sys'].$name, $value); |
} /* }}} */ |
function htmlHiddenData($name, $value) /* {{{ */ |
{ |
return $this->htmlHidden($this->cgi['prefix']['data'].$name, $value); |
} /* }}} */ |
function htmlHidden($name, $value) /* {{{ */ |
{ |
return '<input type="hidden" name="'.htmlspecialchars($name) |
.'" value="'.htmlspecialchars($value).'" />'."\n"; |
} /* }}} */ |
/** |
* Creates HTML select element (tag) |
* |
* @param name element name |
* @param css CSS class name |
* @param kv_array key => value array |
* @param selected selected key (it can be single string, array of |
* keys or multiple values separated by comma) |
* @param multiple bool for multiple selection |
* @param readonly bool for readonly/disabled selection |
* @param strip_tags bool for stripping tags from values |
* @param escape bool for HTML escaping values |
* @param js string to be in the <select >, ususally onchange='..'; |
*/ |
function htmlSelect($name, $css, $kv_array, $selected = null, /* ...) {{{ */ |
/* booleans: */ $multiple = false, $readonly = false, $strip_tags = false, $escape = true, $js = NULL) |
{ |
$ret = '<select class="'.htmlspecialchars($css).'" name="'.htmlspecialchars($name); |
if ($multiple) { |
$ret .= '[]" multiple size="'.$this->multiple; |
if (! is_array($selected) && $selected !== null) { |
$selected = explode(',', $selected); |
} |
} |
$ret .= '"'.($readonly ? ' disabled="disabled"' : '').$js.'>'."\n"; |
if (! is_array($selected)) { |
$selected = $selected === null ? array() : array($selected); |
} |
$found = false; |
foreach ($kv_array as $key => $value) { |
$ret .= '<option value="'.htmlspecialchars($key).'"'; |
if ((! $found || $multiple) && in_array((string) $key, $selected, 1) |
|| (count($selected) == 0 && ! $found && ! $multiple)) { |
$ret .= ' selected="selected"'; |
$found = true; |
} |
$strip_tags && $value = strip_tags($value); |
$escape && $value = htmlspecialchars($value); |
$ret .= '>'.$value.'</option>'."\n"; |
} |
$ret .= '</select>'; |
return $ret; |
} /* }}} */ |
/** |
* Creates HTML checkboxes or radio buttons |
* |
* @param name element name |
* @param css CSS class name |
* @param kv_array key => value array |
* @param selected selected key (it can be single string, array of |
* keys or multiple values separated by comma) |
* @param multiple bool for multiple selection (checkboxes) |
* @param readonly bool for readonly/disabled selection |
* @param strip_tags bool for stripping tags from values |
* @param escape bool for HTML escaping values |
* @param js string to be in the <select >, ususally onchange='..'; |
*/ |
function htmlRadioCheck($name, $css, $kv_array, $selected = null, /* ...) {{{ */ |
/* booleans: */ $multiple = false, $readonly = false, $strip_tags = false, $escape = true, $js = NULL) |
{ |
$ret = ''; |
if ($multiple) { |
if (! is_array($selected) && $selected !== null) { |
$selected = explode(',', $selected); |
} |
} |
if (! is_array($selected)) { |
$selected = $selected === null ? array() : array($selected); |
} |
$found = false; |
foreach ($kv_array as $key => $value) { |
$ret .= '<input type="'.($multiple ? 'checkbox' : 'radio').'" name="'; |
$ret .= htmlspecialchars($name).'[]" value="'.htmlspecialchars($key).'"'; |
if ((! $found || $multiple) && in_array((string) $key, $selected, 1) |
|| (count($selected) == 0 && ! $found && ! $multiple)) { |
$ret .= ' checked'; |
$found = true; |
} |
if ($readonly) { |
$ret .= ' disabled="disabled"'; |
} |
$strip_tags && $value = strip_tags($value); |
$escape && $value = htmlspecialchars($value); |
$ret .= '>'.$value.'<br>'."\n"; |
} |
return $ret; |
} /* }}} */ |
/** |
* Returns original variables HTML code for use in forms or links. |
* |
* @param mixed $origvars string or array of original varaibles |
* @param string $method type of method ("POST" or "GET") |
* @param mixed $default_value default value of variables |
* if null, empty values will be skipped |
* @return get HTML code of original varaibles |
*/ |
function get_origvars_html($origvars, $method = 'post', $default_value = '') /* {{{ */ |
{ |
$ret = ''; |
$method = strtoupper($method); |
if ($method == 'POST') { |
if (! is_array($origvars)) { |
$new_origvars = array(); |
foreach (explode('&', $origvars) as $param) { |
$parts = explode('=', $param, 2); |
if (! isset($parts[1])) { |
$parts[1] = $default_value; |
} |
if (strlen($parts[0]) <= 0) { |
continue; |
} |
$new_origvars[$parts[0]] = $parts[1]; |
} |
$origvars =& $new_origvars; |
} |
foreach ($origvars as $key => $val) { |
if (strlen($val) <= 0 && $default_value === null) { |
continue; |
} |
$key = rawurldecode($key); |
$val = rawurldecode($val); |
$ret .= $this->htmlHidden($key, $val); |
} |
} else if (! strncmp('GET', $method, 3)) { |
if (! is_array($origvars)) { |
$ret .= $origvars; |
} else { |
foreach ($origvars as $key => $val) { |
if (strlen($val) <= 0 && $default_value === null) { |
continue; |
} |
$ret == '' || $ret .= '&'; |
$ret .= htmlspecialchars(rawurlencode($key)); |
$ret .= '='; |
$ret .= htmlspecialchars(rawurlencode($val)); |
} |
} |
if ($method[strlen($method) - 1] == '+') { |
$ret = "?$ret"; |
} |
} else { |
trigger_error('Unsupported Platon::get_origvars_html() method: ' |
.$method, E_USER_ERROR); |
} |
return $ret; |
} /* }}} */ |
function get_sfn_cgi_vars($alternative_sfn = null) /* {{{ */ |
{ |
if ($alternative_sfn === null) { // FAST! (cached return value) |
static $ret = null; |
$ret == null && $ret = $this->get_sfn_cgi_vars($this->sfn); |
return $ret; |
} |
$ret = ''; |
$i = 0; |
foreach ($alternative_sfn as $val) { |
$ret != '' && $ret .= '&'; |
$ret .= rawurlencode($this->cgi['prefix']['sys'].'sfn')."[$i]=".rawurlencode($val); |
$i++; |
} |
return $ret; |
} /* }}} */ |
function get_default_cgi_prefix($type) /* {{{ */ |
{ |
switch ($type) { |
case 'operation': return 'PME_op_'; |
case 'sys': return 'PME_sys_'; |
case 'data': return 'PME_data_'; |
} |
return ''; |
} /* }}} */ |
function get_sys_cgi_var($name, $default_value = null) /* {{{ */ |
{ |
if (isset($this)) { |
return $this->get_cgi_var($this->cgi['prefix']['sys'].$name, $default_value); |
} |
return phpMyEdit::get_cgi_var(phpMyEdit::get_default_cgi_prefix('sys').$name, $default_value); |
} /* }}} */ |
function get_data_cgi_var($name, $default_value = null) /* {{{ */ |
{ |
if (isset($this)) { |
return $this->get_cgi_var($this->cgi['prefix']['data'].$name, $default_value); |
} |
return phpMyEdit::get_cgi_var(phpMyEdit::get_default_cgi_prefix('data').$name, $default_value); |
} /* }}} */ |
function get_cgi_var($name, $default_value = null) /* {{{ */ |
{ |
if (isset($this) && isset($this->cgi['overwrite'][$name])) { |
return $this->cgi['overwrite'][$name]; |
} |
static $magic_quotes_gpc = null; |
if ($magic_quotes_gpc === null) { |
$magic_quotes_gpc = get_magic_quotes_gpc(); |
} |
$var = @$_GET[$name]; |
if (! isset($var)) { |
$var = @$_POST[$name]; |
} |
if (isset($var)) { |
if ($magic_quotes_gpc) { |
if (is_array($var)) { |
foreach (array_keys($var) as $key) { |
$var[$key] = stripslashes($var[$key]); |
} |
} else { |
$var = stripslashes($var); |
} |
} |
} else { |
$var = @$default_value; |
} |
if (isset($this) && $var === null && isset($this->cgi['append'][$name])) { |
return $this->cgi['append'][$name]; |
} |
return $var; |
} /* }}} */ |
function get_server_var($name) /* {{{ */ |
{ |
if (isset($_SERVER[$name])) { |
return $_SERVER[$name]; |
} |
global $HTTP_SERVER_VARS; |
if (isset($HTTP_SERVER_VARS[$name])) { |
return $HTTP_SERVER_VARS[$name]; |
} |
global $$name; |
if (isset($$name)) { |
return $$name; |
} |
return null; |
} /* }}} */ |
/* |
* Debug functions |
*/ |
function print_get_vars ($miss = 'No GET variables found') // debug only /* {{{ */ |
{ |
// we parse form GET variables |
if (is_array($_GET)) { |
echo "<p> Variables per GET "; |
foreach ($_GET as $k => $v) { |
if (is_array($v)) { |
foreach ($v as $akey => $aval) { |
// $_GET[$k][$akey] = strip_tags($aval); |
// $$k[$akey] = strip_tags($aval); |
echo "$k\[$akey\]=$aval "; |
} |
} else { |
// $_GET[$k] = strip_tags($val); |
// $$k = strip_tags($val); |
echo "$k=$v "; |
} |
} |
echo '</p>'; |
} else { |
echo '<p>'; |
echo $miss; |
echo '</p>'; |
} |
} /* }}} */ |
function print_post_vars($miss = 'No POST variables found') // debug only /* {{{ */ |
{ |
global $_POST; |
// we parse form POST variables |
if (is_array($_POST)) { |
echo "<p>Variables per POST "; |
foreach ($_POST as $k => $v) { |
if (is_array($v)) { |
foreach ($v as $akey => $aval) { |
// $_POST[$k][$akey] = strip_tags($aval); |
// $$k[$akey] = strip_tags($aval); |
echo "$k\[$akey\]=$aval "; |
} |
} else { |
// $_POST[$k] = strip_tags($val); |
// $$k = strip_tags($val); |
echo "$k=$v "; |
} |
} |
echo '</p>'; |
} else { |
echo '<p>'; |
echo $miss; |
echo '</p>'; |
} |
} /* }}} */ |
function print_vars ($miss = 'Current instance variables') // debug only /* {{{ */ |
{ |
echo "$miss "; |
echo 'page_name=',$this->page_name,' '; |
echo 'hn=',$this->hn,' '; |
echo 'un=',$this->un,' '; |
echo 'pw=',$this->pw,' '; |
echo 'db=',$this->db,' '; |
echo 'dbp=',$this->dbp,' '; |
echo 'dbh=',$this->dbh,' '; |
echo 'tb=',$this->tb,' '; |
echo 'key=',$this->key,' '; |
echo 'key_type=',$this->key_type,' '; |
echo 'inc=',$this->inc,' '; |
echo 'options=',$this->options,' '; |
echo 'fdd=',$this->fdd,' '; |
echo 'fl=',$this->fl,' '; |
echo 'fm=',$this->fm,' '; |
echo 'sfn=',htmlspecialchars($this->get_sfn_cgi_vars()),' '; |
echo 'qfn=',$this->qfn,' '; |
echo 'sw=',$this->sw,' '; |
echo 'rec=',$this->rec,' '; |
echo 'navop=',$this->navop,' '; |
echo 'saveadd=',$this->saveadd,' '; |
echo 'moreadd=',$this->moreadd,' '; |
echo 'canceladd=',$this->canceladd,' '; |
echo 'savechange=',$this->savechange,' '; |
echo 'morechange=',$this->morechange,' '; |
echo 'cancelchange=',$this->cancelchange,' '; |
echo 'savecopy=',$this->savecopy,' '; |
echo 'cancelcopy=',$this->cancelcopy,' '; |
echo 'savedelete=',$this->savedelete,' '; |
echo 'canceldelete=',$this->canceldelete,' '; |
echo 'cancelview=',$this->cancelview,' '; |
echo 'operation=',$this->operation,' '; |
echo "\n"; |
} /* }}} */ |
/* |
* Display buttons at top and bottom of page |
*/ |
function display_list_table_buttons($position, $listall = false) /* {{{ */ |
{ |
if (($but_str = $this->display_buttons($position)) === null) |
return; |
if($position == 'down') echo '<hr class="'.$this->getCSSclass('hr', 'down').'" />'."\n"; |
echo '<table summary="navigation" class="',$this->getCSSclass('navigation', $position),'">',"\n"; |
echo '<tr class="',$this->getCSSclass('navigation', $position),'">',"\n"; |
echo '<td class="',$this->getCSSclass('buttons', $position),'">',"\n"; |
echo $but_str,'</td>',"\n"; |
// Message is now written here |
if (strlen(@$this->message) > 0) { |
echo '<td class="',$this->getCSSclass('message', $position),'">',$this->message,'</td>',"\n"; |
} |
if($this->display['num_pages'] || $this->display['num_records']) |
echo '<td class="',$this->getCSSclass('stats', $position),'">',"\n"; |
if($this->display['num_pages']) { |
if ($listall) { |
echo $this->labels['Page'],': 1 ',$this->labels['of'],' 1'; |
} else { |
$current_page = intval($this->fm / $this->inc) + 1; |
$total_pages = max(1, ceil($this->total_recs / abs($this->inc))); |
echo $this->labels['Page'],': ',$current_page; |
echo ' ',$this->labels['of'],' ',$total_pages; |
} |
} |
if($this->display['num_records']) |
echo ' ',$this->labels['Records'],': ',$this->total_recs; |
if($this->display['num_pages'] || $this->display['num_records']) echo '</td>'; |
echo '</tr></table>',"\n"; |
if($position == 'up') echo '<hr class="'.$this->getCSSclass('hr', 'up').'" />'."\n"; |
} /* }}} */ |
/* |
* Display buttons at top and bottom of page |
*/ |
function display_record_buttons($position) /* {{{ */ |
{ |
if (($but_str = $this->display_buttons($position)) === null) |
return; |
if ($position == 'down') { |
if ($this->tabs_enabled()) $this->display_tab_labels('down'); |
echo '<hr class="',$this->getCSSclass('hr', 'down'),'" />',"\n"; |
} |
echo '<table summary="navigation" class="',$this->getCSSclass('navigation', $position),'">',"\n"; |
echo '<tr class="',$this->getCSSclass('navigation', $position),'">',"\n"; |
echo '<td class="',$this->getCSSclass('buttons', $position),'">',"\n"; |
echo $but_str,'</td>',"\n"; |
// Message is now written here |
//echo '</td>',"\n"; |
if (strlen(@$this->message) > 0) { |
echo '<td class="',$this->getCSSclass('message', $position),'">',$this->message,'</td>',"\n"; |
} |
echo '</tr></table>',"\n"; |
if ($position == 'up') { |
if ($this->tabs_enabled()) $this->display_tab_labels('up'); |
echo '<hr class="',$this->getCSSclass('hr', 'up'),'" />',"\n"; |
} |
} /* }}} */ |
function display_buttons($position) /* {{{ */ |
{ |
$nav_fnc = 'nav_'.$position; |
if(! $this->$nav_fnc()) |
return; |
$buttons = (is_array($this->buttons[$this->page_type][$position])) |
? $this->buttons[$this->page_type][$position] |
: $this->default_buttons[$this->page_type]; |
foreach ($buttons as $name) { |
$ret .= $this->display_button($name, $position)."\n"; |
} |
return $ret; |
} /* }}} */ |
function display_button($name, $position = 'up') /* {{{ */ |
{ |
if (is_array($name)) { |
if (isset($name['code'])) return $name['code']; |
return $this->htmlSubmit($name['name'], $name['value'], $name['css'], $name['disabled'], $name['js']); |
} |
$disabled = 1; // show disabled by default |
if ($name[0] == '+') { $name = substr($name, 1); $disabled = 0; } // always show disabled as enabled |
if ($name[0] == '-') { $name = substr($name, 1); $disabled = -1; } // don't show disabled |
if ($name == 'cancel') { |
return $this->htmlSubmit('cancel'.$this->page_types[$this->page_type], 'Cancel', |
$this->getCSSclass('cancel', $position), false); |
} |
if (in_array($name, array('add','view','change','copy','delete'))) { |
$enabled_fnc = $name.'_enabled'; |
$enabled = $this->$enabled_fnc(); |
if ($name != 'add' && ! $this->total_recs && strstr('LF', $this->page_type)) |
$enabled = false; |
return $this->htmlSubmit('operation', ucfirst($name), |
$this->getCSSclass($name, $position), false, $enabled ? 0 : $disabled); |
} |
if ($name == 'savedelete') { |
$enabled = $this->delete_enabled(); |
$js = 'onclick="return confirm(\''.$this->labels['Delete'].' ?\');"'; |
return $this->htmlSubmit('savedelete', 'Delete', |
$this->getCSSclass('save', $position), false, $enabled ? 0 : $disabled, $js); |
} |
if (in_array($name, array('save','more'))) { |
$validation = true; // if js validation |
if ($this->page_type == 'D' && $name == 'save' ) { $value = 'Delete'; $validation = false; } |
elseif ($this->page_type == 'C' && $name == 'more' ) { $value = 'Apply'; } |
else $value = ucfirst($name); |
return $this->htmlSubmit($name.$this->page_types[$this->page_type], $value, |
$this->getCSSclass($name, $position), $validation); |
} |
$listall = $this->inc <= 0; |
if ($listall) { |
$disabledprev = true; |
$disablednext = true; |
$total_pages = 1; |
$current_page = 1; |
} else { |
$disabledprev = $this->fm <= 0; |
$disablednext = $this->fm + $this->inc >= $this->total_recs; |
$total_pages = max(1, ceil($this->total_recs / abs($this->inc))); |
$current_page = ceil($this->fm / abs($this->inc)); // must + 1 |
} |
$disabledfirst = $disabledprev; |
$disabledlast = $disablednext; |
// some statistics first |
if ($name == 'total_pages') return $total_pages; |
if ($name == 'current_page') return ($current_page+1); |
if ($name == 'total_recs') return ($this->total_recs); |
// now some goto buttons/dropdowns/inputs... |
if ($name == 'goto_text') { |
$ret = '<input type="text" class="'.$this->getCSSclass('gotopn', $position).'"'; |
$ret .= ' name="'.$this->cgi['prefix']['sys'].'navpn'.$position.'" value="'.($current_page+1).'"'; |
$ret .= ' size="'.(strlen($total_pages)+1).'" maxlength="'.(strlen($total_pages)+1).'"'; |
// TODO some js here.... on enter submit, on click erase ?... |
$ret .=' oneypress="return PE_filter_handler(this.form, event);" />'; |
return $ret; |
} |
if ($name == 'goto_combo') { |
$disabledgoto = !($listall || ($disablednext && $disabledprev)) ? '' : ' disabled'; |
if ($disablegoto != '' && $disabled < 0) return; |
$kv_array = array(); |
for ($i = 0; $i < $total_pages; $i++) { |
$kv_array[$this->inc * $i] = $i + 1; |
} |
// TODO: add onchange="return this.form.submit();" DONE ??? |
return $this->htmlSelect($this->cgi['prefix']['sys'].ltrim($disabledgoto).'navfm'.$position, |
$this->getCSSclass('goto', $position), $kv_array, (string)$this->fm, false, $disabledgoto, |
false, true, 'onchange="return this.form.submit();"'); |
} |
if ($name == 'goto') { |
return $this->htmlSubmit('navop', 'Go to', $this->getCSSclass('goto', $position), |
false, ($listall || ($disablednext && $disabledprev)) ? $disabled : 0); |
} |
if (in_array($name, array('first','prev','next','last','<<','<','>','>>'))) { |
$disabled_var = 'disabled'.$name; |
$name2 = $name; |
if (strlen($name) <= 2) { |
$nav_values = array('<<' => 'first', '<' => 'prev', '>' => 'next', '>>' => 'last'); |
$disabled_var = 'disabled'.$nav_values[$name]; |
$name2 = $nav_values[$name]; |
} |
return $this->htmlSubmit('navop', ucfirst($name), |
$this->getCSSclass($name2, $position), false, $$disabled_var ? $disabled : 0); |
} |
if(isset($this->labels[$name])) return $this->labels[$name]; |
return $name; |
} /* }}} */ |
function number_of_recs() /* {{{ */ |
{ |
$count_parts = array( |
'type' => 'select', |
'select' => 'count(*)', |
'from' => $this->get_SQL_join_clause(), |
'where' => $this->get_SQL_where_from_query_opts()); |
$res = $this->myquery($this->get_SQL_query($count_parts), __LINE__); |
$row = @mysql_fetch_array($res, MYSQL_NUM); |
$this->total_recs = $row[0]; |
} /* }}} */ |
/* |
* Table Page Listing |
*/ |
function list_table() /* {{{ */ |
{ |
if ($this->fm == '') { |
$this->fm = 0; |
} |
$this->fm = $this->navfm; |
if ($this->prev_operation()) { |
$this->fm = $this->fm - $this->inc; |
if ($this->fm < 0) { |
$this->fm = 0; |
} |
} |
if ($this->first_operation()) { |
$this->fm = 0; |
} // last operation must be performed below, after retrieving total_recs |
if ($this->next_operation()) { |
$this->fm += $this->inc; |
} |
$this->number_of_recs(); |
if ($this->last_operation() || $this->fm > $this->total_recs) { // if goto_text is badly set |
$this->fm = (int)(($this->total_recs - 1)/$this->inc)*$this->inc; |
} |
// If sort sequence has changed, restart listing |
$this->qfn != $this->prev_qfn && $this->fm = 0; |
if (0) { // DEBUG |
echo 'qfn vs. prev_qfn comparsion '; |
echo '[<b>',htmlspecialchars($this->qfn),'</b>]'; |
echo '[<b>',htmlspecialchars($this->prev_qfn),'</b>]<br />'; |
echo 'comparsion <u>',($this->qfn == $this->prev_qfn ? 'proved' : 'failed'),'</u>'; |
echo '<hr />'; |
} |
/* |
* If user is allowed to Change/Delete records, we need an extra column |
* to allow users to select a record |
*/ |
$select_recs = $this->key != '' && |
($this->change_enabled() || $this->delete_enabled() || $this->view_enabled()); |
// Are we doing a listall? |
$listall = $this->inc <= 0; |
/* |
* Display the MySQL table in an HTML table |
*/ |
$this->form_begin(); |
echo $this->get_origvars_html($this->get_sfn_cgi_vars()); |
echo $this->htmlHiddenSys('fl', $this->fl); |
// Display buttons at top and/or bottom of page. |
$this->display_list_table_buttons('up', $listall); |
if ($this->cgi['persist'] != '') { |
echo $this->get_origvars_html($this->cgi['persist']); |
} |
if (! $this->filter_operation()) { |
echo $this->get_origvars_html($this->qfn); |
} |
echo $this->htmlHiddenSys('qfn', $this->qfn); |
echo $this->htmlHiddenSys('fm', $this->fm); |
echo '<table class="',$this->getCSSclass('main'),'" summary="',$this->tb,'">',"\n"; |
echo '<tr class="',$this->getCSSclass('header'),'">',"\n"; |
/* |
* System (navigation, selection) columns counting |
*/ |
$sys_cols = 0; |
$sys_cols += intval($this->filter_enabled() || $select_recs); |
if ($sys_cols > 0) { |
$sys_cols += intval($this->nav_buttons() |
&& ($this->nav_text_links() || $this->nav_graphic_links())); |
} |
/* |
* We need an initial column(s) (sys columns) |
* if we have filters, Changes or Deletes enabled |
*/ |
if ($sys_cols) { |
echo '<th class="',$this->getCSSclass('header'),'" colspan="',$sys_cols,'">'; |
if ($this->filter_enabled()) { |
if ($this->filter_operation()) { |
echo $this->htmlSubmit('sw', 'Hide', $this->getCSSclass('hide'), false); |
echo $this->htmlSubmit('sw', 'Clear', $this->getCSSclass('clear'), false); |
} else { |
echo $this->htmlSubmit('sw', 'Search', $this->getCSSclass('search'), false); |
} |
} else { |
echo ' '; |
} |
echo '</th>',"\n"; |
} |
for ($k = 0; $k < $this->num_fds; $k++) { |
$fd = $this->fds[$k]; |
if (! $this->displayed[$k]) { |
continue; |
} |
$css_postfix = @$this->fdd[$k]['css']['postfix']; |
$css_class_name = $this->getCSSclass('header', null, null, $css_postfix); |
$fdn = $this->fdd[$fd]['name']; |
if (! $this->fdd[$fd]['sort'] || $this->password($fd)) { |
echo '<th class="',$css_class_name,'">',$fdn,'</th>',"\n"; |
} else { |
// Clicking on the current sort field reverses the sort order |
$new_sfn = $this->sfn; |
array_unshift($new_sfn, in_array("$k", $new_sfn, 1) ? "-$k" : $k); |
echo '<th class="',$css_class_name,'">'; |
echo '<a class="',$css_class_name,'" href="'; |
echo htmlspecialchars($this->page_name.'?'.$this->cgi['prefix']['sys'].'fm'.'=0' |
.'&'.$this->cgi['prefix']['sys'].'fl'.'='.$this->fl |
.'&'.$this->cgi['prefix']['sys'].'qfn'.'='.rawurlencode($this->qfn).$this->qfn |
.'&'.$this->get_sfn_cgi_vars($new_sfn).$this->cgi['persist']); |
echo '">',$fdn,'</a></th>',"\n"; |
} |
} |
echo '</tr>',"\n"; |
/* |
* Prepare the SQL Query from the data definition file |
*/ |
$qparts['type'] = 'select'; |
$qparts['select'] = $this->get_SQL_column_list(); |
// Even if the key field isn't displayed, we still need its value |
if ($select_recs) { |
if (!in_array ($this->key, $this->fds)) { |
$qparts['select'] .= ','.$this->fqn($this->key); |
} |
} |
$qparts['from'] = $this->get_SQL_join_clause(); |
$qparts['where'] = $this->get_SQL_where_from_query_opts(); |
// build up the ORDER BY clause |
if (isset($this->sfn)) { |
$sort_fields = array(); |
$sort_fields_w = array(); |
foreach ($this->sfn as $field) { |
if ($field[0] == '-') { |
$field = substr($field, 1); |
$desc = true; |
} else { |
$field = $field; |
$desc = false; |
} |
$sort_field = $this->fqn($field); |
$sort_field_w = $this->fdd[$field]['name']; |
$this->col_has_sql($field) && $sort_field_w .= ' (sql)'; |
if ($desc) { |
$sort_field .= ' DESC'; |
$sort_field_w .= ' '.$this->labels['descending']; |
} else { |
$sort_field_w .= ' '.$this->labels['ascending']; |
} |
$sort_fields[] = $sort_field; |
$sort_fields_w[] = $sort_field_w; |
} |
if (count($sort_fields) > 0) { |
$qparts['orderby'] = join(',', $sort_fields); |
} |
} |
$qparts['limit'] = $listall ? '' : $this->fm.','.$this->inc; |
/* |
* Main list_table() query |
* |
* Each row of the HTML table is one record from the SQL query. We must |
* perform this query before filter printing, because we want to use |
* mysql_field_len() function. We will also fetch the first row to get |
* the field names. |
*/ |
$query = $this->get_SQL_query($qparts); |
$res = $this->myquery($query, __LINE__); |
if ($res == false) { |
$this->error('invalid SQL query', $query); |
return false; |
} |
$row = @mysql_fetch_array($res, MYSQL_ASSOC); |
/* FILTER {{{ |
* |
* Draw the filter and fill it with any data typed in last pass and stored |
* in the array parameter keyword 'filter'. Prepare the SQL WHERE clause. |
*/ |
if ($this->filter_operation()) { |
// Filter row retrieval |
$fields = false; |
$filter_row = $row; |
if (! is_array($filter_row)) { |
unset($qparts['where']); |
$query = $this->get_SQL_query($qparts); |
$res = $this->myquery($query, __LINE__); |
if ($res == false) { |
$this->error('invalid SQL query', $query); |
return false; |
} |
$filter_row = @mysql_fetch_array($res, MYSQL_ASSOC); |
} |
/* Variable $fields is used to get index of particular field in |
result. That index can be passed in example to mysql_field_len() |
function. Use field names as indexes to $fields array. */ |
if (is_array($filter_row)) { |
$fields = array_flip(array_keys($filter_row)); |
} |
if ($fields != false) { |
$css_class_name = $this->getCSSclass('filter'); |
echo '<tr class="',$css_class_name,'">',"\n"; |
echo '<td class="',$css_class_name,'" colspan="',$sys_cols,'">'; |
echo $this->htmlSubmit('filter', 'Query', $this->getCSSclass('query'), false); |
echo '</td>', "\n"; |
for ($k = 0; $k < $this->num_fds; $k++) { |
if (! $this->displayed[$k]) { |
continue; |
} |
$css_postfix = @$this->fdd[$k]['css']['postfix']; |
$css_class_name = $this->getCSSclass('filter', null, null, $css_postfix); |
$this->field_name = $this->fds[$k]; |
$fd = $this->field_name; |
$this->field = $this->fdd[$fd]; |
$l = 'qf'.$k; |
$lc = 'qf'.$k.'_comp'; |
$li = 'qf'.$k.'_id'; |
if ($this->clear_operation()) { |
$m = null; |
$mc = null; |
$mi = null; |
} else { |
$m = $this->get_sys_cgi_var($l); |
$mc = $this->get_sys_cgi_var($lc); |
$mi = $this->get_sys_cgi_var($li); |
} |
echo '<td class="',$css_class_name,'">'; |
if ($this->password($k)) { |
echo ' '; |
} else if ($this->fdd[$fd]['select'] == 'D' || $this->fdd[$fd]['select'] == 'M') { |
// Multiple fields processing |
// Default size is 2 and array required for values. |
$from_table = ! $this->col_has_values($k) || isset($this->fdd[$k]['values']['table']); |
$vals = $this->set_values($k, array('*' => '*'), null, $from_table); |
$selected = $mi; |
$multiple = $this->col_has_multiple_select($k); |
$multiple |= $this->fdd[$fd]['select'] == 'M'; |
$readonly = false; |
$strip_tags = true; |
$escape = true; |
echo $this->htmlSelect($this->cgi['prefix']['sys'].$l.'_id', $css_class_name, |
$vals, $selected, $multiple, $readonly, $strip_tags, $escape); |
} elseif ($this->fdd[$fd]['select'] == 'N' || $this->fdd[$fd]['select'] == 'T') { |
$size_ml_props = ''; |
$maxlen = intval($this->fdd[$k]['maxlen']); |
$maxlen > 0 || $maxlen = intval(@mysql_field_len($res, $fields["qf$k"])); |
$size = isset($this->fdd[$k]['size']) ? $this->fdd[$k]['size'] |
: ($maxlen < 30 ? min($maxlen, 8) : 12); |
$size && $size_ml_props .= ' size="'.$size.'"'; |
$maxlen && $size_ml_props .= ' maxlength="'.$maxlen.'"'; |
if ($this->fdd[$fd]['select'] == 'N') { |
$mc = in_array($mc, $this->comp_ops) ? $mc : '='; |
echo $this->htmlSelect($this->cgi['prefix']['sys'].$l.'_comp', |
$css_class_name, $this->comp_ops, $mc); |
} |
echo '<input class="',$css_class_name,'" value="',htmlspecialchars(@$m); |
echo '" type="text" name="'.$this->cgi['prefix']['sys'].'qf'.$k.'"',$size_ml_props; |
echo ' onkeypress="return '.$this->js['prefix'].'filter_handler(this.form, event);" />'; |
} else { |
echo ' '; |
} |
echo '</td>',"\n"; |
} |
echo '</tr>',"\n"; |
} |
} // }}} |
/* |
* Display sorting sequence |
*/ |
if ($qparts['orderby'] && $this->display['sort']) { |
$css_class_name = $this->getCSSclass('sortinfo'); |
echo '<tr class="',$css_class_name,'">',"\n"; |
echo '<td class="',$css_class_name,'" colspan="',$sys_cols,'">'; |
echo '<a class="',$css_class_name,'" href="'; |
echo htmlspecialchars($this->page_name |
.'?'.$this->cgi['prefix']['sys'].'fl'.'='.$this->fl |
.'&'.$this->cgi['prefix']['sys'].'fm'.'='.$this->fm |
.'&'.$this->cgi['prefix']['sys'].'qfn'.'='.rawurlencode($this->qfn) |
.$this->qfn.$this->cgi['persist']); |
echo '">',$this->labels['Clear'],'</a></td>',"\n"; |
echo '<td class="',$css_class_name,'" colspan="',$this->num_fields_displayed,'">'; |
echo $this->labels['Sorted By'],': ',join(', ', $sort_fields_w),'</td></tr>',"\n"; |
} |
/* |
* Display the current query |
*/ |
$text_query = $this->get_SQL_where_from_query_opts(null, true); |
if ($text_query != '' && $this->display['query']) { |
$css_class_name = $this->getCSSclass('queryinfo'); |
echo '<tr class="',$css_class_name,'">',"\n"; |
echo '<td class="',$css_class_name,'" colspan="',$sys_cols,'">'; |
echo '<a class="',$css_class_name,'" href="'; |
echo htmlspecialchars($this->get_server_var('PHP_SELF') |
.'?'.$this->cgi['prefix']['sys'].'fl'.'='.$this->fl |
.'&'.$this->cgi['prefix']['sys'].'fm'.'='.$this->fm |
.'&'.$this->cgi['prefix']['sys'].'qfn'.'='.rawurlencode($this->qfn) |
.'&'.$this->get_sfn_cgi_vars().$this->cgi['persist']); |
echo '">',$this->labels['Clear'],'</a></td>',"\n"; |
echo '<td class="',$css_class_name,'" colspan="',$this->num_fields_displayed,'">'; |
echo $this->labels['Current Query'],': ',htmlspecialchars($text_query),'</td></tr>',"\n"; |
} |
if ($this->nav_text_links() || $this->nav_graphic_links()) { |
$qstrparts = array(); |
strlen($this->fl) > 0 && $qstrparts[] = $this->cgi['prefix']['sys'].'fl'.'='.$this->fl; |
strlen($this->fm) > 0 && $qstrparts[] = $this->cgi['prefix']['sys'].'fm'.'='.$this->fm; |
count($this->sfn) > 0 && $qstrparts[] = $this->get_sfn_cgi_vars(); |
strlen($this->cgi['persist']) > 0 && $qstrparts[] = $this->cgi['persist']; |
$qpview = $qstrparts; |
$qpcopy = $qstrparts; |
$qpchange = $qstrparts; |
$qpdelete = $qstrparts; |
$qp_prefix = $this->cgi['prefix']['sys'].'operation'.'='.$this->cgi['prefix']['operation']; |
$qpview[] = $qp_prefix.'View'; |
$qpcopy[] = $qp_prefix.'Copy'; |
$qpchange[] = $qp_prefix.'Change'; |
$qpdelete[] = $qp_prefix.'Delete'; |
$qpviewStr = htmlspecialchars($this->page_name.'?'.join('&',$qpview).$this->qfn); |
$qpcopyStr = htmlspecialchars($this->page_name.'?'.join('&',$qpcopy).$this->qfn); |
$qpchangeStr = htmlspecialchars($this->page_name.'?'.join('&',$qpchange).$this->qfn); |
$qpdeleteStr = htmlspecialchars($this->page_name.'?'.join('&',$qpdelete).$this->qfn); |
} |
$fetched = true; |
$first = true; |
$rowCount = 0; |
while ((!$fetched && ($row = @mysql_fetch_array($res, MYSQL_ASSOC)) != false) |
|| ($fetched && $row != false)) { |
$fetched = false; |
echo '<tr class="',$this->getCSSclass('row', null, 'next'),'">',"\n"; |
if ($sys_cols) { /* {{{ */ |
$key_rec = $row['qf'.$this->key_num]; |
$queryAppend = htmlspecialchars('&'.$this->cgi['prefix']['sys'].'rec'.'='.$key_rec); |
$viewQuery = $qpviewStr . $queryAppend; |
$copyQuery = $qpcopyStr . $queryAppend; |
$changeQuery = $qpchangeStr . $queryAppend; |
$deleteQuery = $qpdeleteStr . $queryAppend; |
$viewTitle = htmlspecialchars($this->labels['View']); |
$changeTitle = htmlspecialchars($this->labels['Change']); |
$copyTitle = htmlspecialchars($this->labels['Copy']); |
$deleteTitle = htmlspecialchars($this->labels['Delete']); |
$css_class_name = $this->getCSSclass('navigation', null, true); |
if ($select_recs) { |
if (! $this->nav_buttons() || $sys_cols > 1) { |
echo '<td class="',$css_class_name,'">'; |
} |
if ($this->nav_graphic_links()) { |
$printed_out = false; |
if ($this->view_enabled()) { |
$printed_out = true; |
echo '<a class="',$css_class_name,'" href="',$viewQuery,'"><img class="'; |
echo $css_class_name,'" src="',$this->url['images']; |
echo 'pme-view.png" height="15" width="16" border="0" '; |
echo 'alt="',$viewTitle,'" title="',$viewTitle,'" /></a>'; |
} |
if ($this->change_enabled()) { |
$printed_out && print(' '); |
$printed_out = true; |
echo '<a class="',$css_class_name,'" href="',$changeQuery,'"><img class="'; |
echo $css_class_name,'" src="',$this->url['images']; |
echo 'pme-change.png" height="15" width="16" border="0" '; |
echo 'alt="',$changeTitle,'" title="',$changeTitle,'" /></a>'; |
} |
if ($this->copy_enabled()) { |
$printed_out && print(' '); |
$printed_out = true; |
echo '<a class="',$css_class_name,'" href="',$copyQuery,'"><img class="'; |
echo $css_class_name,'" src="',$this->url['images']; |
echo 'pme-copy.png" height="15" width="16" border="0" '; |
echo 'alt="',$copyTitle,'" title="',$copyTitle,'" /></a>'; |
} |
if ($this->delete_enabled()) { |
$printed_out && print(' '); |
$printed_out = true; |
echo '<a class="',$css_class_name,'" href="',$deleteQuery,'"><img class="'; |
echo $css_class_name,'" src="',$this->url['images']; |
echo 'pme-delete.png" height="15" width="16" border="0" '; |
echo 'alt="',$deleteTitle,'" title="',$deleteTitle,'" /></a>'; |
} |
} |
if ($this->nav_text_links()) { |
if ($this->nav_graphic_links()) { |
echo '<br class="',$css_class_name,'">'; |
} |
$printed_out = false; |
if ($this->view_enabled()) { |
$printed_out = true; |
echo '<a href="',$viewQuery,'" title="',$viewTitle,'" class="',$css_class_name,'">V</a>'; |
} |
if ($this->change_enabled()) { |
$printed_out && print(' '); |
$printed_out = true; |
echo '<a href="',$changeQuery,'" title="',$changeTitle,'" class="',$css_class_name,'">C</a>'; |
} |
if ($this->copy_enabled()) { |
$printed_out && print(' '); |
$printed_out = true; |
echo '<a href="',$copyQuery,'" title="',$copyTitle,'" class="',$css_class_name,'">P</a>'; |
} |
if ($this->delete_enabled()) { |
$printed_out && print(' '); |
$printed_out = true; |
echo '<a href="',$deleteQuery,'" title="',$deleteTitle,'" class="',$css_class_name,'">D</a>'; |
} |
} |
if (! $this->nav_buttons() || $sys_cols > 1) { |
echo '</td>',"\n"; |
} |
if ($this->nav_buttons()) { |
echo '<td class="',$css_class_name,'"><input class="',$css_class_name; |
echo '" type="radio" name="'.$this->cgi['prefix']['sys'].'rec'; |
echo '" value="',htmlspecialchars($key_rec),'"'; |
if (($this->rec == '' && $first) || ($this->rec == $key_rec)) { |
echo ' checked'; |
$first = false; |
} |
echo ' /></td>',"\n"; |
} |
} elseif ($this->filter_enabled()) { |
echo '<td class="',$css_class_name,'" colspan=',$sys_cols,'> </td>',"\n"; |
} |
} /* }}} */ |
for ($k = 0; $k < $this->num_fds; $k++) { /* {{{ */ |
$fd = $this->fds[$k]; |
if (! $this->displayed[$k]) { |
continue; |
} |
$css_postfix = @$this->fdd[$k]['css']['postfix']; |
$css_class_name = $this->getCSSclass('cell', null, true, $css_postfix); |
if ($this->password($k)) { |
echo '<td class="',$css_class_name,'">',$this->labels['hidden'],'</td>',"\n"; |
continue; |
} |
echo '<td class="',$css_class_name,'"',$this->getColAttributes($fd),'>'; |
echo $this->cellDisplay($k, $row, $css_class_name); |
echo '</td>',"\n"; |
} /* }}} */ |
echo '</tr>',"\n"; |
} |
/* |
* Display and accumulate column aggregation info, do totalling query |
* XXX this feature does not work yet!!! |
*/ |
// aggregates listing (if any) |
if ($$var_to_total) { |
// do the aggregate query if necessary |
//if ($vars_to_total) { |
$qp = array(); |
$qp['type'] = 'select'; |
$qp['select'] = $aggr_from_clause; |
$qp['from'] = $this->get_SQL_join_clause(); |
$qp['where'] = $this->get_SQL_where_from_query_opts(); |
$tot_query = $this->get_SQL_query($qp); |
$totals_result = $this->myquery($tot_query,__LINE__); |
$tot_row = @mysql_fetch_array($totals_result, MYSQL_ASSOC); |
//} |
$qp_aggr = $qp; |
echo "\n",'<tr class="TODO-class">',"\n",'<td class="TODO-class"> </td>',"\n"; |
/* |
echo '<td>'; |
echo printarray($qp_aggr); |
echo printarray($vars_to_total); |
echo '</td>'; |
echo '<td colspan="'.($this->num_fds-1).'">'.$var_to_total.' '.$$var_to_total.'</td>'; |
*/ |
// display the results |
for ($k=0;$k<$this->num_fds;$k++) { |
$fd = $this->fds[$k]; |
if (stristr($this->fdd[$fd]['options'],'L') or !isset($this->fdd[$fd]['options'])) { |
echo '<td>'; |
$aggr_var = 'qf'.$k.'_aggr'; |
$$aggr_var = $this->get_sys_cgi_var($aggr_var); |
if ($$aggr_var) { |
echo $this->sql_aggrs[$$aggr_var],': ',$tot_row[$aggr_var]; |
} else { |
echo ' '; |
} |
echo '</td>',"\n"; |
} |
} |
echo '</tr>',"\n"; |
} |
echo '</table>',"\n"; // end of table rows listing |
$this->display_list_table_buttons('down', $listall); |
$this->form_end(); |
} /* }}} */ |
function display_record() /* {{{ */ |
{ |
// PRE Triggers |
$ret = true; |
if ($this->change_operation()) { |
$ret &= $this->exec_triggers_simple('update', 'pre'); |
// if PRE update fails, then back to view operation |
if (! $ret) { |
$this->operation = $this->labels['View']; |
$ret = true; |
} |
} |
if ($this->add_operation() || $this->copy_operation()) { |
$ret &= $this->exec_triggers_simple('insert', 'pre'); |
} |
if ($this->view_operation()) { |
$ret &= $this->exec_triggers_simple('select', 'pre'); |
} |
if ($this->delete_operation()) { |
$ret &= $this->exec_triggers_simple('delete', 'pre'); |
} |
// if PRE insert/view/delete fail, then back to the list |
if ($ret == false) { |
$this->operation = ''; |
$this->list_table(); |
return; |
} |
$this->form_begin(); |
if ($this->cgi['persist'] != '') { |
echo $this->get_origvars_html($this->cgi['persist']); |
} |
echo $this->get_origvars_html($this->get_sfn_cgi_vars()); |
echo $this->get_origvars_html($this->qfn); |
echo $this->htmlHiddenSys('cur_tab', $this->dhtml['prefix'].'tab'.$this->cur_tab); |
echo $this->htmlHiddenSys('qfn', $this->qfn); |
echo $this->htmlHiddenSys('rec', $this->copy_operation() ? '' : $this->rec); |
echo $this->htmlHiddenSys('fm', $this->fm); |
echo $this->htmlHiddenSys('fl', $this->fl); |
$this->display_record_buttons('up'); |
if ($this->tabs_enabled()) { |
echo '<div id="'.$this->dhtml['prefix'].'tab0">',"\n"; |
} |
echo '<table class="',$this->getCSSclass('main'),'" summary="',$this->tb,'">',"\n"; |
if ($this->add_operation()) { |
$this->display_add_record(); |
} else { |
$this->display_copy_change_delete_record(); |
} |
echo '</table>',"\n"; |
if ($this->tabs_enabled()) { |
echo '</div>',"\n"; |
} |
$this->display_record_buttons('down'); |
$this->form_end(); |
} /* }}} */ |
/* |
* Action functions |
*/ |
function do_add_record() /* {{{ */ |
{ |
// Preparing query |
$query = ''; |
$key_col_val = ''; |
$newvals = array(); |
for ($k = 0; $k < $this->num_fds; $k++) { |
if ($this->processed($k)) { |
$fd = $this->fds[$k]; |
if ($this->readonly($k)) { |
$fn = (string) @$this->fdd[$k]['default']; |
} else { |
$fn = $this->get_data_cgi_var($fd); |
} |
if ($fd == $this->key) { |
$key_col_val = $fn; |
} |
$newvals[$fd] = is_array($fn) ? join(',',$fn) : $fn; |
} |
} |
// Creating array of changed keys ($changed) |
$changed = array_keys($newvals); |
// Before trigger, newvals can be efectively changed |
if ($this->exec_triggers('insert', 'before', $oldvals, $changed, $newvals) == false) { |
return false; |
} |
// Real query (no additional query in this method) |
foreach ($newvals as $fd => $val) { |
if ($fd == '') continue; |
if ($this->col_has_sqlw($this->fdn[$fd])) { |
$val_as = addslashes($val); |
$val_qas = '"'.addslashes($val).'"'; |
$value = $this->substituteVars( |
$this->fdd[$this->fdn[$fd]]['sqlw'], array( |
'val_qas' => $val_qas, |
'val_as' => $val_as, |
'val' => $val |
)); |
} else { |
$value = "'".addslashes($val)."'"; |
} |
if ($query == '') { |
$query = 'INSERT INTO `'.$this->tb.'` (`'.$fd.'`'; // ) |
$query2 = ') VALUES ('.$value.''; |
} else { |
$query .= ', `'.$fd.'`'; |
$query2 .= ', '.$value.''; |
} |
} |
$query .= $query2.')'; |
$res = $this->myquery($query, __LINE__); |
$this->message = @mysql_affected_rows($this->dbh).' '.$this->labels['record added']; |
if (! $res) { |
return false; |
} |
$this->rec = mysql_insert_id($this->dbh); |
// Notify list |
if (@$this->notify['insert'] || @$this->notify['all']) { |
$this->email_notify(false, $newvals); |
} |
// Note change in log table |
if ($this->logtable) { |
$query = sprintf('INSERT INTO %s' |
.' (updated, user, host, operation, tab, rowkey, col, oldval, newval)' |
.' VALUES (NOW(), "%s", "%s", "insert", "%s", "%s", "", "", "%s")', |
$this->logtable, addslashes($this->get_server_var('REMOTE_USER')), |
addslashes($this->get_server_var('REMOTE_ADDR')), addslashes($this->tb), |
addslashes($key_col_val), addslashes(serialize($newvals))); |
$this->myquery($query, __LINE__); |
} |
// After trigger |
if ($this->exec_triggers('insert', 'after', $oldvals, $changed, $newvals) == false) { |
return false; |
} |
return true; |
} /* }}} */ |
function do_change_record() /* {{{ */ |
{ |
// Preparing queries |
$query_real = ''; |
$query_oldrec = ''; |
$newvals = array(); |
$oldvals = array(); |
$changed = array(); |
// Prepare query to retrieve oldvals |
for ($k = 0; $k < $this->num_fds; $k++) { |
if ($this->processed($k) && !$this->readonly($k)) { |
$fd = $this->fds[$k]; |
$fn = $this->get_data_cgi_var($fd); |
$newvals[$this->fds[$k]] = is_array($fn) ? join(',',$fn) : $fn; |
if ($query_oldrec == '') { |
$query_oldrec = 'SELECT '.$fd; |
} else { |
$query_oldrec .= ','.$fd; |
} |
} |
} |
$where_part = " WHERE (".$this->key.'='.$this->key_delim.$this->rec.$this->key_delim.')'; |
$query_newrec = $query_oldrec.' FROM ' . $this->tb; |
$query_oldrec .= ' FROM ' . $this->tb . $where_part; |
// Additional query (must go before real query) |
$res = $this->myquery($query_oldrec, __LINE__); |
$oldvals = @mysql_fetch_array($res, MYSQL_ASSOC); |
@mysql_free_result($res); |
// Creating array of changed keys ($changed) |
foreach ($newvals as $fd => $value) { |
if ($value != $oldvals[$fd]) |
$changed[] = $fd; |
} |
// Before trigger |
if ($this->exec_triggers('update', 'before', $oldvals, $changed, $newvals) == false) { |
return false; |
} |
// Build the real query respecting changes to the newvals array |
foreach ($newvals as $fd => $val) { |
if ($fd == '') continue; |
if ($this->col_has_sqlw($this->fdn[$fd])) { |
$val_as = addslashes($val); |
$val_qas = '"'.addslashes($val).'"'; |
$value = $this->substituteVars( |
$this->fdd[$this->fdn[$fd]]['sqlw'], array( |
'val_qas' => $val_qas, |
'val_as' => $val_as, |
'val' => $val |
)); |
} else { |
$value = "'".addslashes($val)."'"; |
} |
if ($query_real == '') { |
$query_real = 'UPDATE '.$this->tb.' SET '.$fd.'='.$value; |
} else { |
$query_real .= ','.$fd.'='.$value; |
} |
} |
$query_real .= $where_part; |
// Real query |
$res = $this->myquery($query_real, __LINE__); |
$this->message = @mysql_affected_rows($this->dbh).' '.$this->labels['record changed']; |
if (! $res) { |
return false; |
} |
// Another additional query (must go after real query) |
if (in_array($this->key, $changed)) { |
$this->rec = $newvals[$this->key]; // key has changed |
} |
$query_newrec .= ' WHERE ('.$this->key.'='.$this->key_delim.$this->rec.$this->key_delim.')'; |
$res = $this->myquery($query_newrec, __LINE__); |
$newvals = @mysql_fetch_array($res, MYSQL_ASSOC); |
@mysql_free_result($res); |
// Creating array of changed keys ($changed) |
$changed = array(); |
foreach ($newvals as $fd => $value) { |
if ($value != $oldvals[$fd]) |
$changed[] = $fd; |
} |
// Notify list |
if (@$this->notify['update'] || @$this->notify['all']) { |
if (count($changed) > 0) { |
$this->email_notify($oldvals, $newvals); |
} |
} |
// Note change in log table |
if ($this->logtable) { |
foreach ($changed as $key) { |
$qry = sprintf('INSERT INTO %s' |
.' (updated, user, host, operation, tab, rowkey, col, oldval, newval)' |
.' VALUES (NOW(), "%s", "%s", "update", "%s", "%s", "%s", "%s", "%s")', |
$this->logtable, addslashes($this->get_server_var('REMOTE_USER')), |
addslashes($this->get_server_var('REMOTE_ADDR')), addslashes($this->tb), |
addslashes($this->rec), addslashes($key), |
addslashes($oldvals[$key]), addslashes($newvals[$key])); |
$this->myquery($qry, __LINE__); |
} |
} |
// After trigger |
if ($this->exec_triggers('update', 'after', $oldvals, $changed, $newvals) == false) { |
return false; |
} |
return true; |
} /* }}} */ |
function do_delete_record() /* {{{ */ |
{ |
// Additional query |
$query = 'SELECT * FROM '.$this->tb.' WHERE ('.$this->key.' = ' |
.$this->key_delim.$this->rec.$this->key_delim.')'; // ) |
$res = $this->myquery($query, __LINE__); |
$oldvals = @mysql_fetch_array($res, MYSQL_ASSOC); |
@mysql_free_result($res); |
// Creating array of changed keys ($changed) |
$changed = array_keys($oldvals); |
$newvals = array(); |
// Before trigger |
if ($this->exec_triggers('delete', 'before', $oldvals, $changed, $newvals) == false) { |
return false; |
} |
// Real query |
$query = 'DELETE FROM '.$this->tb.' WHERE ('.$this->key.' = ' |
.$this->key_delim.$this->rec.$this->key_delim.')'; // ) |
$res = $this->myquery($query, __LINE__); |
$this->message = @mysql_affected_rows($this->dbh).' '.$this->labels['record deleted']; |
if (! $res) { |
return false; |
} |
// Notify list |
if (@$this->notify['delete'] || @$this->notify['all']) { |
$this->email_notify($oldvals, false); |
} |
// Note change in log table |
if ($this->logtable) { |
$query = sprintf('INSERT INTO %s' |
.' (updated, user, host, operation, tab, rowkey, col, oldval, newval)' |
.' VALUES (NOW(), "%s", "%s", "delete", "%s", "%s", "%s", "%s", "")', |
$this->logtable, addslashes($this->get_server_var('REMOTE_USER')), |
addslashes($this->get_server_var('REMOTE_ADDR')), addslashes($this->tb), |
addslashes($this->rec), addslashes($key), addslashes(serialize($oldvals))); |
$this->myquery($query, __LINE__); |
} |
// After trigger |
if ($this->exec_triggers('delete', 'after', $oldvals, $changed, $newvals) == false) { |
return false; |
} |
return true; |
} /* }}} */ |
function email_notify($old_vals, $new_vals) /* {{{ */ |
{ |
if (! function_exists('mail')) { |
return false; |
} |
if ($old_vals != false && $new_vals != false) { |
$action = 'update'; |
$subject = 'Record updated in'; |
$body = 'An item with '.$this->fdd[$this->key]['name'].' = ' |
.$this->key_delim.$this->rec.$this->key_delim .' was updated in'; |
$vals = $new_vals; |
} elseif ($new_vals != false) { |
$action = 'insert'; |
$subject = 'Record added to'; |
$body = 'A new item was added into'; |
$vals = $new_vals; |
} elseif ($old_vals != false) { |
$action = 'delete'; |
$subject = 'Record deleted from'; |
$body = 'An item was deleted from'; |
$vals = $old_vals; |
} else { |
return false; |
} |
$addr = $this->get_server_var('REMOTE_ADDR'); |
$user = $this->get_server_var('REMOTE_USER'); |
$body = 'This notification e-mail was automatically generated by phpMyEdit.'."\n\n".$body; |
$body .= ' table '.$this->tb.' in MySQL database '.$this->db.' on '.$this->page_name; |
$body .= ' by '.($user == '' ? 'unknown user' : "user $user").' from '.$addr; |
$body .= ' at '.date('d/M/Y H:i').' with the following fields:'."\n\n"; |
$i = 1; |
foreach ($vals as $k => $text) { |
$name = isset($this->fdd[$k]['name~']) |
? $this->fdd[$k]['name~'] : $this->fdd[$k]['name']; |
if ($action == 'update') { |
if ($old_vals[$k] == $new_vals[$k]) { |
continue; |
} |
$body .= sprintf("[%02s] %s (%s)\n WAS: %s\n IS: %s\n", |
$i, $name, $k, $old_vals[$k], $new_vals[$k]); |
} else { |
$body .= sprintf('[%02s] %s (%s): %s'."\n", $i, $name, $k, $text); |
} |
$i++; |
} |
$body .= "\n--\r\n"; // \r is needed for signature separating |
$body .= "phpMyEdit\ninstant MySQL table editor and code generator\n"; |
$body .= "http://platon.sk/projects/phpMyEdit/\n\n"; |
$subject = @$this->notify['prefix'].$subject.' '.$this->dbp.$this->tb; |
$subject = trim($subject); // just for sure |
$wrap_w = intval(@$this->notify['wrap']); |
$wrap_w > 0 || $wrap_w = 72; |
$from = (string) @$this->notify['from']; |
$from != '' || $from = 'webmaster@'.strtolower($this->get_server_var('SERVER_NAME')); |
$headers = 'From: '.$from."\n".'X-Mailer: PHP/'.phpversion().' (phpMyEdit)'; |
$body = wordwrap($body, $wrap_w, "\n", 1); |
$emails = (array) $this->notify[$action] + (array) $this->notify['all']; |
foreach ($emails as $email) { |
if (! empty($email)) { |
mail(trim($email), $subject, $body, $headers); |
} |
} |
return true; |
} /* }}} */ |
/* |
* Apply triggers function |
* Run a (set of) trigger(s). $trigger can be an Array or a filename |
* Break and return false as soon as a trigger return false |
* we need a reference on $newvals to be able to change value before insert/update |
*/ |
function exec_triggers($op, $step, $oldvals, &$changed, &$newvals) /* {{{ */ |
{ |
if (! isset($this->triggers[$op][$step])) { |
return true; |
} |
$ret = true; |
$trig = $this->triggers[$op][$step]; |
if (is_array($trig)) { |
ksort($trig); |
for ($t = reset($trig); $t !== false && $ret != false; $t = next($trig)) { |
$ret = include($t); |
} |
} else { |
$ret = include($trig); |
} |
return $ret; |
} /* }}} */ |
function exec_triggers_simple($op, $step) /* {{{ */ |
{ |
$oldvals = $newvals = $changed = array(); |
return $this->exec_triggers($op, $step, $oldvals, $changed, $newvals); |
} /* }}} */ |
/* |
* Recreate functions |
*/ |
function recreate_fdd($default_page_type = 'L') /* {{{ */ |
{ |
// TODO: one level deeper browsing |
$this->page_type = $default_page_type; |
$this->filter_operation() && $this->page_type = 'F'; |
$this->view_operation() && $this->page_type = 'V'; |
if ($this->add_operation() |
|| $this->saveadd == $this->labels['Save'] |
|| $this->moreadd == $this->labels['More']) { |
$this->page_type = 'A'; |
} |
if ($this->change_operation() |
|| $this->savechange == $this->labels['Save'] |
|| $this->morechange == $this->labels['Apply']) { |
$this->page_type = 'C'; |
} |
if ($this->copy_operation() || $this->savecopy == $this->labels['Save']) { |
$this->page_type = 'P'; |
} |
if ($this->delete_operation() || $this->savedelete == $this->labels['Delete']) { |
$this->page_type = 'D'; |
} |
// Restore backups (if exists) |
foreach (array_keys($this->fdd) as $column) { |
foreach (array_keys($this->fdd[$column]) as $col_option) { |
if ($col_option[strlen($col_option) - 1] != '~') |
continue; |
$this->fdd[$column][substr($col_option, 0, strlen($col_option) - 1)] |
= $this->fdd[$column][$col_option]; |
unset($this->fdd[$column][$col_option]); |
} |
} |
foreach (array_keys($this->fdd) as $column) { |
foreach (array_keys($this->fdd[$column]) as $col_option) { |
if (! strchr($col_option, '|')) { |
continue; |
} |
$col_ar = explode('|', $col_option, 2); |
if (! stristr($col_ar[1], $this->page_type)) { |
continue; |
} |
// Make field backups |
$this->fdd[$column][$col_ar[0] .'~'] = $this->fdd[$column][$col_ar[0]]; |
$this->fdd[$column][$col_option.'~'] = $this->fdd[$column][$col_option]; |
// Set particular field |
$this->fdd[$column][$col_ar[0]] = $this->fdd[$column][$col_option]; |
unset($this->fdd[$column][$col_option]); |
} |
} |
} /* }}} */ |
function recreate_displayed() /* {{{ */ |
{ |
$field_num = 0; |
$num_fields_displayed = 0; |
$this->fds = array(); |
$this->fdn = array(); |
$this->displayed = array(); |
$this->guidance = false; |
foreach (array_keys($this->fdd) as $key) { |
if (preg_match('/^\d+$/', $key)) { // skipping numeric keys |
continue; |
} |
$this->fds[$field_num] = $key; |
$this->fdn[$key] = $field_num; |
/* We must use here displayed() function, because displayed[] array |
is not created yet. We will simultaneously create that array as well. */ |
if ($this->displayed[$field_num] = $this->displayed($field_num)) { |
$num_fields_displayed++; |
} |
if (is_array(@$this->fdd[$key]['values']) && ! isset($this->fdd[$key]['values']['table'])) { |
foreach ($this->fdd[$key]['values'] as $val) { |
$this->fdd[$key]['values2'][$val] = $val; |
} |
unset($this->fdd[$key]['values']); |
} |
isset($this->fdd[$key]['help']) && $this->guidance = true; |
$this->fdd[$field_num] = $this->fdd[$key]; |
$field_num++; |
} |
$this->num_fds = $field_num; |
$this->num_fields_displayed = $num_fields_displayed; |
$this->key_num = array_search($this->key, $this->fds); |
/* Adds first displayed column into sorting fields by replacing last |
array entry. Also remove duplicite values and change column names to |
their particular field numbers. |
Note that entries like [0]=>'9' [1]=>'-9' are correct and they will |
have desirable sorting behaviour. So there is no need to remove them. |
*/ |
$this->sfn = array_unique($this->sfn); |
$check_ar = array(); |
foreach ($this->sfn as $key => $val) { |
if (preg_match('/^[-]?\d+$/', $val)) { // skipping numeric keys |
$val = abs($val); |
if (in_array($val, $check_ar) || $this->password($val)) { |
unset($this->sfn[$key]); |
} else { |
$check_ar[] = $val; |
} |
continue; |
} |
if ($val[0] == '-') { |
$val = substr($val, 1); |
$minus = '-'; |
} else { |
$minus = ''; |
} |
if (($val = array_search($val, $this->fds)) === false || $this->password($val)) { |
unset($this->sfn[$key]); |
} else { |
$val = intval($val); |
if (in_array($val, $check_ar)) { |
unset($this->sfn[$key]); |
} else { |
$this->sfn[$key] = $minus.$val; |
$check_ar[] = $val; |
} |
} |
} |
$this->sfn = array_unique($this->sfn); |
return true; |
} /* }}} */ |
function backward_compatibility() /* {{{ */ |
{ |
foreach (array_keys($this->fdd) as $column) { |
// move ['required'] to ['js']['required'] |
if (! isset($this->fdd[$column]['js']['required']) && isset($this->fdd[$column]['required'])) { |
$this->fdd[$column]['js']['required'] = $this->fdd[$column]['required']; |
} |
// move 'HWR' flags from ['options'] into ['input'] |
if (isset($this->fdd[$column]['options'])) { |
stristr($this->fdd[$column]['options'], 'H') && $this->fdd[$column]['input'] .= 'H'; |
stristr($this->fdd[$column]['options'], 'W') && $this->fdd[$column]['input'] .= 'W'; |
stristr($this->fdd[$column]['options'], 'R') && $this->fdd[$column]['input'] .= 'R'; |
} |
} |
} /* }}} */ |
/* |
* Error handling function |
*/ |
function error($message, $additional_info = '') /* {{{ */ |
{ |
echo '<h1>phpMyEdit error: ',htmlspecialchars($message),'</h1>',"\n"; |
if ($additional_info != '') { |
echo '<hr />',htmlspecialchars($additional_info); |
} |
return false; |
} /* }}} */ |
/* |
* Database connection function |
*/ |
function connect() /* {{{ */ |
{ |
if (isset($this->dbh)) { |
return true; |
} |
if (!isset($this->db)) { |
$this->error('no database defined'); |
return false; |
} |
if (!isset ($this->tb)) { |
$this->error('no table defined'); |
return false; |
} |
$this->dbh = @ini_get('allow_persistent') |
? @mysql_pconnect($this->hn, $this->un, $this->pw) |
: @mysql_connect($this->hn, $this->un, $this->pw); |
if (!$this->dbh) { |
$this->error('could not connect to MySQL'); |
return false; |
} |
return true; |
} /* }}} */ |
/* |
* Database disconnection function |
*/ |
function disconnect() /* {{{ */ |
{ |
if ($this->close_dbh) { |
@mysql_close($this->dbh); |
$this->dbh = null; |
} |
} /* }}} */ |
/* |
* The workhorse |
*/ |
function execute() /* {{{ */ |
{ |
// DEBUG - uncomment to enable |
/* |
//phpinfo(); |
$this->print_get_vars(); |
$this->print_post_vars(); |
$this->print_vars(); |
echo "<pre>query opts:\n"; |
echo print_r($this->query_opts); |
echo "</pre>\n"; |
echo "<pre>get vars:\n"; |
echo print_r($this->get_opts); |
echo "</pre>\n"; |
*/ |
// Let's do explicit quoting - it's safer |
set_magic_quotes_runtime(0); |
// Checking if language file inclusion was successful |
if (! is_array($this->labels)) { |
$this->error('could not locate language files', 'searched path: '.$this->dir['lang']); |
return false; |
} |
// Database connection |
if ($this->connect() == false) { |
return false; |
} |
/* |
* ====================================================================== |
* Pass 3: process any updates generated if the user has selected |
* a save or cancel button during Pass 2 |
* ====================================================================== |
*/ |
// Cancel button - Cancel Triggers |
if ($this->add_canceled() || $this->copy_canceled()) { |
$this->exec_triggers_simple('insert', 'cancel'); |
} |
if ($this->view_canceled()) { |
$this->exec_triggers_simple('select', 'cancel'); |
} |
if ($this->change_canceled()) { |
$this->exec_triggers_simple('update', 'cancel'); |
} |
if ($this->delete_canceled()) { |
$this->exec_triggers_simple('delete', 'cancel'); |
} |
// Save/More Button - database operations |
if ($this->saveadd == $this->labels['Save'] || $this->savecopy == $this->labels['Save']) { |
$this->add_enabled() && $this->do_add_record(); |
unset($this->saveadd); |
unset($this->savecopy); |
$this->recreate_fdd(); |
} |
elseif ($this->moreadd == $this->labels['More']) { |
$this->add_enabled() && $this->do_add_record(); |
$this->operation = $this->labels['Add']; // to force add operation |
$this->recreate_fdd(); |
$this->recreate_displayed(); |
$this->backward_compatibility(); |
} |
elseif ($this->savechange == $this->labels['Save']) { |
$this->change_enabled() && $this->do_change_record(); |
unset($this->savechange); |
$this->recreate_fdd(); |
} |
elseif ($this->morechange == $this->labels['Apply']) { |
$this->change_enabled() && $this->do_change_record(); |
$this->operation = $this->labels['Change']; // to force change operation |
$this->recreate_fdd(); |
$this->recreate_displayed(); |
$this->backward_compatibility(); |
} |
elseif ($this->savedelete == $this->labels['Delete']) { |
$this->delete_enabled() && $this->do_delete_record(); |
unset($this->savedelete); |
$this->recreate_fdd(); |
} |
/* |
* ====================================================================== |
* Pass 2: display an input/edit/confirmation screen if the user has |
* selected an editing button on Pass 1 through this page |
* ====================================================================== |
*/ |
if ($this->add_operation() |
|| $this->change_operation() || $this->delete_operation() |
|| $this->view_operation() || $this->copy_operation()) { |
$this->display_record(); |
} |
/* |
* ====================================================================== |
* Pass 1 and Pass 3: display the MySQL table in a scrolling window on |
* the screen (skip this step in 'Add More' mode) |
* ====================================================================== |
*/ |
else { |
$this->list_table(); |
} |
$this->disconnect(); |
if ($this->display['time'] && $this->timer != null) { |
echo $this->timer->end(),' miliseconds'; |
} |
} /* }}} */ |
/* |
* Class constructor |
*/ |
function phpMyEdit($opts) /* {{{ */ |
{ |
// Set desirable error reporting level |
$error_reporting = error_reporting(E_ALL & ~E_NOTICE); |
// Database handle variables |
if (isset($opts['dbh'])) { |
$this->close_dbh = false; |
$this->dbh = $opts['dbh']; |
$this->dbp = ''; |
} else { |
$this->close_dbh = true; |
$this->dbh = null; |
$this->dbp = $opts['db'].'.'; |
$this->hn = $opts['hn']; |
$this->un = $opts['un']; |
$this->pw = $opts['pw']; |
$this->db = $opts['db']; |
} |
$this->tb = $opts['tb']; |
// Other variables |
$this->key = $opts['key']; |
$this->key_type = $opts['key_type']; |
$this->inc = $opts['inc']; |
$this->options = $opts['options']; |
$this->fdd = $opts['fdd']; |
$this->multiple = intval($opts['multiple']); |
$this->multiple <= 0 && $this->multiple = 2; |
$this->filters = @$opts['filters']; |
$this->triggers = @$opts['triggers']; |
$this->notify = @$opts['notify']; |
$this->logtable = @$opts['logtable']; |
$this->page_name = @$opts['page_name']; |
if (! isset($this->page_name)) { |
$this->page_name = basename($this->get_server_var('PHP_SELF')); |
isset($this->page_name) || $this->page_name = $this->tb; |
} |
$this->display['query'] = @$opts['display']['query']; |
$this->display['sort'] = @$opts['display']['sort']; |
$this->display['time'] = @$opts['display']['time']; |
if ($this->display['time']) { |
$this->timer = new phpMyEdit_timer(); |
} |
$this->display['tabs'] = isset($opts['display']['tabs']) |
? $opts['display']['tabs'] : true; |
$this->display['form'] = isset($opts['display']['form']) |
? $opts['display']['form'] : true; |
$this->display['num_records'] = isset($opts['display']['num_records']) |
? $opts['display']['num_records'] : true; |
$this->display['num_pages'] = isset($opts['display']['num_pages']) |
? $opts['display']['num_pages'] : true; |
// Creating directory variables |
$this->dir['root'] = dirname(realpath(__FILE__)) |
. (strlen(dirname(realpath(__FILE__))) > 0 ? '/' : ''); |
$this->dir['lang'] = $this->dir['root'].'lang/'; |
// Creating URL variables |
$this->url['images'] = 'images/'; |
isset($opts['url']['images']) && $this->url['images'] = $opts['url']['images']; |
// CSS classes policy |
$this->css = @$opts['css']; |
!isset($this->css['separator']) && $this->css['separator'] = '-'; |
!isset($this->css['prefix']) && $this->css['prefix'] = 'pme'; |
!isset($this->css['page_type']) && $this->css['page_type'] = false; |
!isset($this->css['position']) && $this->css['position'] = false; |
!isset($this->css['divider']) && $this->css['divider'] = 2; |
$this->css['divider'] = intval(@$this->css['divider']); |
// JS overall configuration |
$this->js = @$opts['js']; |
!isset($this->js['prefix']) && $this->js['prefix'] = 'PME_js_'; |
// DHTML overall configuration |
$this->dhtml = @$opts['dhtml']; |
!isset($this->dhtml['prefix']) && $this->dhtml['prefix'] = 'PME_dhtml_'; |
// Navigation |
$this->navigation = @$opts['navigation']; |
if (! $this->nav_buttons() && ! $this->nav_text_links() && ! $this->nav_graphic_links()) { |
$this->navigation .= 'B'; // buttons are default |
} |
if (! $this->nav_up() && ! $this->nav_down()) { |
$this->navigation .= 'D'; // down position is default |
} |
$this->buttons = $opts['buttons']; |
// Language labels (must go after navigation) |
$this->labels = $this->make_language_labels(isset($opts['language']) |
? $opts['language'] : $this->get_server_var('HTTP_ACCEPT_LANGUAGE')); |
// CGI variables |
$this->cgi = @$opts['cgi']; |
$this->cgi['persist'] = ''; |
if (@is_array($opts['cgi']['persist'])) { |
foreach ($opts['cgi']['persist'] as $key => $val) { |
if (is_array($val)) { |
foreach($val as $key2 => $val2) { |
$this->cgi['persist'] .= '&'.rawurlencode($key) |
.'['.rawurlencode($key2).']='.rawurlencode($val2); |
} |
} else { |
$this->cgi['persist'] .= '&'.rawurlencode($key).'='.rawurlencode($val); |
} |
} |
} |
foreach (array('operation', 'sys', 'data') as $type) { |
if (! isset($this->cgi['prefix'][$type])) { |
$this->cgi['prefix'][$type] = $this->get_default_cgi_prefix($type); |
} |
} |
// Sorting variables |
$this->sfn = $this->get_sys_cgi_var('sfn'); |
isset($this->sfn) || $this->sfn = array(); |
is_array($this->sfn) || $this->sfn = array($this->sfn); |
isset($opts['sort_field']) || $opts['sort_field'] = array(); |
is_array($opts['sort_field']) || $opts['sort_field'] = array($opts['sort_field']); |
$this->sfn = array_merge($this->sfn, $opts['sort_field']); |
// Form variables all around |
$this->fl = intval($this->get_sys_cgi_var('fl')); |
$this->fm = intval($this->get_sys_cgi_var('fm')); |
// $old_page = ceil($this->fm / abs($this->inc)) + 1; |
$this->qfn = $this->get_sys_cgi_var('qfn'); |
$this->sw = $this->get_sys_cgi_var('sw'); |
$this->rec = $this->get_sys_cgi_var('rec', ''); |
$this->navop = $this->get_sys_cgi_var('navop'); |
$navfmup = $this->get_sys_cgi_var('navfmup'); |
$navfmdown = $this->get_sys_cgi_var('navfmdown'); |
$navpnup = $this->get_sys_cgi_var('navpnup'); |
$navpndown = $this->get_sys_cgi_var('navpndown'); |
if($navfmdown!=NULL && $navfmdown != $this->fm) $this->navfm = $navfmdown; |
elseif($navfmup!=NULL && $navfmup != $this->fm) $this->navfm = $navfmup; |
elseif($navpndown!=NULL && ($navpndown-1)*$this->inc != $this->fm) $this->navfm = ($navpndown-1)*$this->inc; |
elseif($navpnup!=NULL && ($navpnup-1)*$this->inc != $this->fm) $this->navfm = ($navpnup-1)*$this->inc; |
else $this->navfm = $this->fm; |
$this->operation = $this->get_sys_cgi_var('operation'); |
$oper_prefix_len = strlen($this->cgi['prefix']['operation']); |
if (! strncmp($this->cgi['prefix']['operation'], $this->operation, $oper_prefix_len)) { |
$this->operation = $this->labels[substr($this->operation, $oper_prefix_len)]; |
} |
$this->saveadd = $this->get_sys_cgi_var('saveadd'); |
$this->moreadd = $this->get_sys_cgi_var('moreadd'); |
$this->canceladd = $this->get_sys_cgi_var('canceladd'); |
$this->savechange = $this->get_sys_cgi_var('savechange'); |
$this->morechange = $this->get_sys_cgi_var('morechange'); |
$this->cancelchange = $this->get_sys_cgi_var('cancelchange'); |
$this->savecopy = $this->get_sys_cgi_var('savecopy'); |
$this->cancelcopy = $this->get_sys_cgi_var('cancelcopy'); |
$this->savedelete = $this->get_sys_cgi_var('savedelete'); |
$this->canceldelete = $this->get_sys_cgi_var('canceldelete'); |
$this->cancelview = $this->get_sys_cgi_var('cancelview'); |
// Filter setting |
if (isset($this->sw)) { |
$this->sw == $this->labels['Search'] && $this->fl = 1; |
$this->sw == $this->labels['Hide'] && $this->fl = 0; |
//$this->sw == $this->labels['Clear'] && $this->fl = 0; |
} |
// TAB names |
$this->tabs = array(); |
// Setting key_delim according to key_type |
if ($this->key_type == 'real') { |
/* If 'real' key_type does not work, |
try change MySQL datatype from float to double */ |
$this->rec = doubleval($this->rec); |
$this->key_delim = ''; |
} elseif ($this->key_type == 'int') { |
$this->rec = intval($this->rec); |
$this->key_delim = ''; |
} else { |
$this->key_delim = '"'; |
// $this->rec remains unmodified |
} |
// Specific $fdd modifications depending on performed action |
$this->recreate_fdd(); |
// Extract SQL Field Names and number of fields |
$this->recreate_displayed(); |
// Issue backward compatibility |
$this->backward_compatibility(); |
// Gathering query options |
$this->gather_query_opts(); |
// Call to action |
!isset($opts['execute']) && $opts['execute'] = 1; |
$opts['execute'] && $this->execute(); |
// Restore original error reporting level |
error_reporting($error_reporting); |
} /* }}} */ |
} |
/* Modeline for ViM {{{ |
* vim:set ts=4: |
* vim600:fdm=marker fdl=0 fdc=0: |
* }}} */ |
?> |
/trunk/jrest/util/extensions/phpMyEdit-slide.class.php |
---|
New file |
0,0 → 1,144 |
<?php |
/* |
* phpMyEdit - instant MySQL table editor and code generator |
* |
* extensions/phpMyEdit-slide.class.php - slide show extension for phpMyEdit |
* ____________________________________________________________ |
* |
* Developed by Ondrej Jombik <nepto@platon.sk> |
* Copyright (c) 2002-2006 Platon Group, http://platon.sk/ |
* All rights reserved. |
* |
* See README file for more information about this software. |
* See COPYING file for license information. |
* |
* Download the latest version from |
* http://platon.sk/projects/phpMyEdit/ |
*/ |
/* $Platon: phpMyEdit/extensions/phpMyEdit-slide.class.php,v 1.10 2006-01-22 21:44:24 nepto Exp $ */ |
/* |
* Coding elapsed time: from 8:30 to 10:30 at 30th October 2002 |
* with heavy patching phpMyEdit core class. |
* |
* Music used: E-Type (Campione, This is the Way and others) |
*/ |
require_once dirname(__FILE__).'/../phpMyEdit.class.php'; |
class phpMyEdit_slide extends phpMyEdit |
{ |
// Extension options array |
var $ext; |
function phpMyEdit_slide($opts) /* {{{ */ |
{ |
$execute = 1; |
isset($opts['execute']) && $execute = $opts['execute']; |
$opts['execute'] = 0; |
parent::phpMyEdit($opts); |
$this->ext = $opts['ext']; |
$execute && $this->execute($opts); |
} /* }}} */ |
function display_record_buttons() /* {{{ */ |
{ |
// TODO: classify this table and cells |
echo '<table border=0 cellpadding=0 cellspacing=0 width="100%" style="border:0;padding:0;">'; |
echo '<tr><td align=left style="text-align:left;border:0;padding:0;" nowrap>' . "\n"; |
if ($this->change_operation()) { |
echo '<input type="submit" name="savechange" value="'.$this->labels['Save'].'" />'."\n"; |
echo '<input type="submit" name="morechange" value="'.$this->labels['Apply'].'" />'."\n"; |
echo '<input type="button" name="cancel" value="'.$this->labels['Cancel'].'" onClick="form.submit();" />'."\n"; |
echo '<input type="hidden" name="rec_change" value="1">'; |
} elseif ($this->view_operation()) { |
if ($this->change_enabled()) { |
echo '<input type="submit" name="operation" value="'.$this->labels['Change'].'" />'."\n"; |
} |
echo '<input type="submit" name="cancel" value="'.$this->labels['Cancel'].'" />'."\n"; |
} |
if (! $this->ext['prev_disable']) { |
$disabled = $this->ext['prev'] ? '' : ' disabled'; |
echo '<input'.$disabled.' type="submit" name="'.ltrim($disabled).'prev" value="' |
.$this->labels['Prev'].'"> '; |
echo '<input type="hidden" name="rec_prev" value="'.$this->ext['prev'].'">'; |
} |
if (! $this->ext['next_disable']) { |
$disabled = $this->ext['next'] ? '' : ' disabled'; |
echo '<input'.$disabled.' type="submit" name="'.ltrim($disabled).'next" value="' |
.$this->labels['Next'].'">'; |
echo '<input type="hidden" name="rec_next" value="'.$this->ext['next'].'">'; |
} |
echo '</td></tr></table>'."\n"; |
} /* }}} */ |
function execute($opts) /* {{{ */ |
{ |
if ($this->get_cgi_var('rec_change') |
&& ($this->next_operation() || $this->prev_operation())) { |
$this->operation = $this->labels['Change']; |
} |
if (! $this->change_operation()) { |
$this->operation = $this->labels['View']; |
} |
if ($this->prev_operation()) { |
! $this->ext['prev_disabled'] && $this->rec = $this->get_cgi_var('rec_prev'); |
$this->prev = ''; |
} |
if ($this->next_operation()) { |
! $this->ext['next_disabled'] && $this->rec = $this->get_cgi_var('rec_next'); |
$this->next = ''; |
} |
if (! $this->rec) { |
$this->rec = $this->ext['rec']; |
} |
if (! $this->rec |
|| (! $this->ext['prev_disable'] && ! $this->ext['prev']) |
|| (! $this->ext['next_disable'] && ! $this->ext['next'])) { |
if ($this->connect() == false) { |
return false; |
} |
$query_parts = array( |
'type' => 'select', |
// XXX FIXME - simplify query |
'select' => 'PMEtable0.'.$this->key, |
'from' => $this->get_SQL_join_clause(), |
'where' => $this->get_SQL_where_from_query_opts()); |
// TODO: order by clausule according to default sort order options |
$res = $this->myquery($this->get_SQL_query($query_parts), __LINE__); |
$ids = array(); |
while (($row = @mysql_fetch_array($res, MYSQL_NUM)) !== false) { |
$ids[] = $row[0]; |
} |
@mysql_free_result($res); |
if ($this->rec) { |
$idx = array_search($this->rec, $ids); |
$idx === false && $idx = 0; |
} else { |
$idx = 0; |
} |
$this->rec = $ids[$idx]; |
! $this->ext['prev'] && $this->ext['prev'] = $ids[$idx - 1]; |
! $this->ext['next'] && $this->ext['next'] = $ids[$idx + 1]; |
} |
$this->recreate_fdd(); |
$this->recreate_displayed(); |
parent::execute(); |
} /* }}} */ |
} |
/* Modeline for ViM {{{ |
* vim:set ts=4: |
* vim600:fdm=marker fdl=0 fdc=0: |
* }}} */ |
?> |
/trunk/jrest/util/extensions/phpMyEdit-mce-cal.class.php |
---|
New file |
0,0 → 1,509 |
<?php |
/* |
* phpMyEdit - instant MySQL table editor and code generator |
* |
* extensions/phpMyEdit-mce-cal.class.php - phpMyEdit html area & calendar popup extension |
* ____________________________________________________________ |
* |
* Contribution of Adam Hammond <php@pixolet.co.uk>, London, UK |
* Contribution of Ezudin Kurtowich <ekurtovic@ieee.org>, Sarajevo |
* Copyright (c) 2003-2006 Platon Group, http://platon.sk/ |
* All rights reserved. |
* |
* Updated 28th Jul 2005 |
* |
* Updated to use TinyMCE instead of HTMLArea |
* Updated to handle multiple tabs and to use PME prefixes. |
* Updated to include sub-form patch |
* |
* |
* |
* See README file for more information about this software. |
* See COPYING file for license information. |
* |
* Download the latest version from |
* http://platon.sk/projects/phpMyEdit/ |
*/ |
/* $Platon: phpMyEdit/extensions/phpMyEdit-mce-cal.class.php,v 1.6 2006-09-16 18:43:47 nepto Exp $ */ |
/* |
OVERVIEW |
-------- |
mce_cal extends the standard phpMyEdit class to allow |
a calendar popup helper to be put on any text field and for any textarea |
field to turned into an HTML editor. |
This extension uses the free jsCalendar from http://dynarch.com/mishoo |
and the TinyMCE code from http://tinymce.moxiecode.com/ |
REQUIREMENTS |
------------ |
The requirement is a properly installed jsCalendar and TinyMCE script. |
All browsers supported by these scripts are supported by this |
extension. Note that version 1.44 or later for TinyMCE is required. |
USAGE |
----- |
For both features: |
1. Call to phpMyEdit-mce-cal.class.php instead |
of phpMyEdit.class.php. |
Example: |
require_once 'extensions/phpMyEdit-mce-cal.class.php'; |
new phpMyEdit_mce_cal($opts); |
HTML TextArea |
This enables WYSIWYG editing of a textarea field. |
In order to use it, you should: |
1. Load TinyMCE script in the <head>...</head> section of your |
phpMyEdit calling program as described in the htmlarea manual. |
<!-- tinyMCE --> |
<script language="javascript" type="text/javascript" src="js/<path to TinyMCE>"></script> |
<script language="javascript" type="text/javascript"> |
tinyMCE.init({ |
mode : "specific_textareas", |
auto_reset_designmode : true |
}); |
</script> |
<!-- /tinyMCE --> |
where 'js/<path to TinyMCE>' is the path to the javascript code |
NOTES: |
A. The PME implementation uses the "specific_textareas" mode - this |
must always be set |
B. Due to a bug in Mozilla, if any of the textareas being used as HTML |
editors are in tabs and are initially hidden, the width and height |
need to be specified in the tinyMCE initialization and |
'auto_reset_designmode' must be set to 'true': |
tinyMCE.init({ |
mode : "specific_textareas", |
auto_reset_designmode : true, |
width: "800", |
height: "200" |
}); |
2. Add 'html'=>true parameter to the textarea field definition |
in your phpMyEdit calling program. |
Example: |
$opts['fdd']['col_name'] = array( |
'name' => 'Column', |
'select' => 'T', |
'options' => 'ACPVD', |
'required' => true, |
'textarea' => array( |
'html' => true, |
'rows' => 11, |
'cols' => 81) |
); |
3. It is also possible to have multiple text area formats on the same |
form. This is done by specifying a text tag for the textarea: |
$opts['fdd']['col_name'] = array( |
'name' => 'Column', |
'select' => 'T', |
'options' => 'ACPVD', |
'required' => true, |
'textarea' => array( |
'html' => 'format1', |
'rows' => 11, |
'cols' => 81) |
); |
You then need to initialize TinyMCE in the header to recognize all of |
the tags used in the textareas. |
EXAMPLE |
In the following, two formats of tinyMCE editor are defined. |
This example is the default, and will be used for any fields where |
'html' is set to true. |
tinyMCE.init({ |
mode : "specific_textareas", |
auto_reset_designmode : true |
}); |
This second example has an extra parameter, 'textarea_trigger', which is |
set to the text tag given to the textarea in PME with 'mce_' prepended |
to it. |
tinyMCE.init({ |
mode : "specific_textareas", |
auto_reset_designmode : true, |
textarea_trigger : "mce_format1", |
theme : "advanced", |
width: "800", |
height: "200", |
plugins : "table,save,advhr,advimage,advlink,emotions,iespell,insertdatetime,preview,zoom,flash,searchreplace,print", |
theme_advanced_buttons1_add_before : "save,separator", |
theme_advanced_buttons1_add : "fontselect,fontsizeselect", |
theme_advanced_buttons2_add : "separator,insertdate,inserttime,preview,zoom,separator,forecolor,backcolor", |
theme_advanced_buttons2_add_before: "cut,copy,paste,separator,search,replace,separator", |
theme_advanced_buttons3_add_before : "tablecontrols,separator", |
theme_advanced_buttons3_add : "emotions,iespell,flash,advhr,separator,print", |
theme_advanced_toolbar_location : "top", |
theme_advanced_toolbar_align : "left", |
theme_advanced_path_location : "bottom", |
content_css : "example_full.css", |
plugin_insertdate_dateFormat : "%Y-%m-%d", |
plugin_insertdate_timeFormat : "%H:%M:%S", |
extended_valid_elements : "a[name|href|target|title|onclick],img[class|src|border=0|alt|title|hspace|vspace|width|height|align|onmouseover|onmouseout|name],hr[class|width|size|noshade],font[face|size|color|style],span[class|align|style]" |
}); |
So: |
'html' => 'format1' maps to textarea_trigger : "mce_format1" |
'html' => 'foo' maps to textarea_trigger : "mce_foo" |
'html' => 'bar' maps to textarea_trigger : "mce_bar" |
You can initialize TinyMCE as many times as you need to give you as many |
editor formats as you need. |
CALENDAR |
This extension enables the display of a popup calendar selection |
against selected fields. |
In order to use it, you should: |
1. Load the jsCalendar scripts in the <head>...</head> section of |
your phpMyEdit calling program, substituting the correct paths: |
<script type="text/javascript" src="js/jscalendar/calendar.js"></script> |
<script type="text/javascript" src="js/jscalendar/lang/calendar-en.js"></script> |
<script type="text/javascript" src="js/jscalendar/calendar-setup.js"></script> |
2. Choose your preferred jsCalendar CSS file (see jsCalendar |
documentation) and add the following in the <head>...</head> |
section of your phpMyEdit calling program, substituting the |
correct path: |
<link rel="stylesheet" type="text/css" media="screen" |
href="js/jscalendar/calendar-system.css"> |
3. Add 'calendar' parameter to the field definitions where you |
want a calendar popup in your phpMyEdit calling program. |
Example: |
$opts['fdd']['col_name'] = array( |
'name' => 'Column', |
'select' => 'T', |
'options' => 'ACPVD', |
'required' => true, |
'calendar' => true |
); |
This is will display a button next to the field which pops up |
a calendar when clicked. If that field has a 'strftimemask' |
parameter set, it will use this for the date format. |
For more advanced usage, you can set the 'calendar' parameter |
to an array of valid jsCalendar Calendar.setup options |
(see jSCalendar document for details). Note that not all |
of these options make sense to use in phpMyEdit, and some |
of them will actively break the function. |
Example: |
$opts['fdd']['col_name'] = array( |
'name' => 'Column', |
'select' => 'T', |
'options' => 'ACPVD', |
'required' => true, |
'calendar' => array( |
'ifFormat' => '%Y/%m/%d', // defaults to the ['strftimemask'] |
'firstDay' => 1, // 0 = Sunday, 1 = Monday |
'singleClick' => true, // single or double click to close |
'weekNumbers' => true, // Show week numbers |
'showsTime' => false, // Show time as well as date |
'timeFormat' => '24', // 12 or 24 hour clock |
'button' => true, // Display button (rather then clickable area) |
'label' => '...', // button label (used by phpMyEdit) |
'date' => '2003-12-19 10:00' // Initial date/time for popup |
// (see notes below) |
) |
); |
NOTES |
----- |
1. The popup will normally set the initial value to the current |
field value or to current date/time. 'date' option will always |
override this, even if there is a current date/time value |
in the field. If you want a default value only if the field |
is currently empty, use the phpMyEdit 'default' option. |
2. Only the options listed above may be set by the user, any other |
options will be ignored. |
3. The 'label' option can contain HTML markup which will be displayed as |
the button/clickable area to pull up the calendar |
SEARCH KEYWORD |
-------------- |
Search for "htmlcal" string in this source code, |
to find all extension related modifications. |
*/ |
require_once dirname(__FILE__).'/../phpMyEdit.class.php'; |
class phpMyEdit_mce_cal extends phpMyEdit |
{ |
/* calendar mod start */ |
var $calendars; // Array for collecting list of fields with calendar popups |
/* Array of valid options for passing to Calendar.setup */ |
var $valid_opts = array( |
'button','ifFormat','singleClick','firstDay', |
'weekNumbers','showsTime','timeFormat','date' |
); |
/** |
* Checks to see if the calendar parameter is set on the field |
* |
* @param k current field name |
* @param curval current value of field (set to null for default) |
* |
* If the calendar parameter is set on the field, this function displays |
* the button. It then pushes the Calendar.setup parameters into an array, |
* including the user specified ones in the calling program is they exist. |
* This array is then added to the $calendars array indexed by the field |
* name. This allows for multiple fields with calendar popups. |
*/ |
function calPopup_helper($k, $curval) /* {{{ */ |
{ |
if (@$this->fdd[$k]['calendar']) { |
$cal_ar['ifFormat'] = '%Y-%m-%d %H:%M'; |
$cal_ar['showsTime'] = true; |
$cal_ar['singleClick'] = false; |
if (isset($curval)) { |
if (substr($curval, 0, 4) != '0000') |
$cal_ar['date'] = $curval; |
} |
if (isset($this->fdd[$k]['strftimemask'])) { |
$cal_ar['ifFormat'] = $this->fdd[$k]['strftimemask']; |
} |
if (is_array($this->fdd[$k]['calendar'])) { |
foreach($this->fdd[$k]['calendar'] as $ck => $cv) { |
$cal_ar[$ck] = $cv; |
} |
} |
$cal_ar['button'] = $this->dhtml['prefix'].'calbutton_'.$this->fds[$k]; |
$this->calendars[$this->fds[$k]] = $cal_ar; |
$label = @$this->fdd[$k]['calendar']['label']; |
strlen($label) || $label = '...'; |
$do_button = true; |
if (isset($this->fdd[$k]['calendar']['button'])) { |
$do_button = $this->fdd[$k]['calendar']['button']; |
}; |
if ($do_button) { |
echo '<button id="',$cal_ar['button'],'">',$label,'</button>'; |
} else { |
echo '<span style="cursor: pointer" id="',$cal_ar['button'],'">',$label,'</span>'; |
} |
} |
} /* }}} */ |
/* calendar mod end */ |
function display_add_record() /* {{{ */ |
{ |
for ($tab = 0, $k = 0; $k < $this->num_fds; $k++) { |
if (isset($this->fdd[$k]['tab']) && $this->tabs_enabled() && $k > 0) { |
$tab++; |
echo '</table>',"\n"; |
echo '</div>',"\n"; |
echo '<div id="'.$this->dhtml['prefix'].'tab',$tab,'">',"\n"; |
echo '<table class="',$this->getCSSclass('main'),'" summary="',$this->tb,'">',"\n"; |
} |
if (! $this->displayed[$k]) { |
continue; |
} |
if ($this->hidden($k)) { |
echo $this->htmlHiddenData($this->fds[$k], $this->fdd[$k]['default']); |
continue; |
} |
$css_postfix = @$this->fdd[$k]['css']['postfix']; |
$css_class_name = $this->getCSSclass('input', null, 'next', $css_postfix); |
echo '<tr class="',$this->getCSSclass('row', null, true, $css_postfix),'">',"\n"; |
echo '<td class="',$this->getCSSclass('key', null, true, $css_postfix),'">'; |
echo $this->fdd[$k]['name'],'</td>',"\n"; |
echo '<td class="',$this->getCSSclass('value', null, true, $css_postfix),'"'; |
echo $this->getColAttributes($k),">\n"; |
if ($this->col_has_values($k)) { |
$vals = $this->set_values($k); |
$selected = @$this->fdd[$k]['default']; |
$multiple = $this->col_has_multiple_select($k); |
$readonly = $this->readonly($k); |
$strip_tags = true; |
$escape = true; |
echo $this->htmlSelect($this->cgi['prefix']['data'].$this->fds[$k], $css_class_name, |
$vals, $selected, $multiple, $readonly, $strip_tags, $escape); |
} elseif (isset ($this->fdd[$k]['textarea'])) { |
echo '<textarea class="',$css_class_name,'" name="',$this->cgi['prefix']['data'].$this->fds[$k],'"'; |
echo ($this->readonly($k) ? ' disabled' : ''); |
if (intval($this->fdd[$k]['textarea']['rows']) > 0) { |
echo ' rows="',$this->fdd[$k]['textarea']['rows'],'"'; |
} |
if (intval($this->fdd[$k]['textarea']['cols']) > 0) { |
echo ' cols="',$this->fdd[$k]['textarea']['cols'],'"'; |
} |
if (isset($this->fdd[$k]['textarea']['wrap'])) { |
echo ' wrap="',$this->fdd[$k]['textarea']['wrap'],'"'; |
} else { |
echo ' wrap="virtual"'; |
}; |
// mce mod start |
if (isset($this->fdd[$k]['textarea']['html'])) { |
$mce_tag = 'editable'; |
if (is_string($this->fdd[$k]['textarea']['html'])) { |
$mce_tag = $this->fdd[$k]['textarea']['html']; |
}; |
echo ' mce_'.$mce_tag.'=true '; |
}; |
// mce mod end |
echo '>',htmlspecialchars($this->fdd[$k]['default']),'</textarea>',"\n"; |
} else { |
// Simple edit box required |
$size_ml_props = ''; |
$maxlen = intval($this->fdd[$k]['maxlen']); |
$size = isset($this->fdd[$k]['size']) ? $this->fdd[$k]['size'] : min($maxlen, 60); |
$size && $size_ml_props .= ' size="'.$size.'"'; |
$maxlen && $size_ml_props .= ' maxlength="'.$maxlen.'"'; |
echo '<input class="',$css_class_name,'" '; |
echo ($this->password($k) ? 'type="password"' : 'type="text"'); |
echo ($this->readonly($k) ? ' disabled' : ''); |
/* calendar mod start */ |
echo ' id="',$this->dhtml['prefix'].'fld_'.$this->fds[$k],'"'; |
/* calendar mod end */ |
echo ' name="',$this->cgi['prefix']['data'].$this->fds[$k],'"'; |
echo $size_ml_props,' value="'; |
echo htmlspecialchars($this->fdd[$k]['default']),'">'; |
/* calendar mod start */ |
/* Call htmlcal helper function */ |
$this->calPopup_helper($k, null); |
/* calendar mod end */ |
} |
echo '</td>',"\n"; |
if ($this->guidance) { |
$css_class_name = $this->getCSSclass('help', null, true, $css_postfix); |
$cell_value = $this->fdd[$k]['help'] ? $this->fdd[$k]['help'] : ' '; |
echo '<td class="',$css_class_name,'">',$cell_value,'</td>',"\n"; |
} |
echo '</tr>',"\n"; |
} |
} /* }}} */ |
function display_change_field($row, $k) /* {{{ */ |
{ |
$css_postfix = @$this->fdd[$k]['css']['postfix']; |
$css_class_name = $this->getCSSclass('input', null, true, $css_postfix); |
echo '<td class="',$this->getCSSclass('value', null, true, $css_postfix),'"'; |
echo $this->getColAttributes($k),">\n"; |
if ($this->col_has_values($k)) { |
$vals = $this->set_values($k); |
$multiple = $this->col_has_multiple_select($k); |
$readonly = $this->readonly($k); |
$strip_tags = true; |
$escape = true; |
echo $this->htmlSelect($this->cgi['prefix']['data'].$this->fds[$k], $css_class_name, |
$vals, $row["qf$k"], $multiple, $readonly, $strip_tags, $escape); |
} elseif (isset($this->fdd[$k]['textarea'])) { |
echo '<textarea class="',$css_class_name,'" name="',$this->cgi['prefix']['data'].$this->fds[$k],'"'; |
echo ($this->readonly($k) ? ' disabled' : ''); |
if (intval($this->fdd[$k]['textarea']['rows']) > 0) { |
echo ' rows="',$this->fdd[$k]['textarea']['rows'],'"'; |
} |
if (intval($this->fdd[$k]['textarea']['cols']) > 0) { |
echo ' cols="',$this->fdd[$k]['textarea']['cols'],'"'; |
} |
if (isset($this->fdd[$k]['textarea']['wrap'])) { |
echo ' wrap="',$this->fdd[$k]['textarea']['wrap'],'"'; |
} else { |
echo ' wrap="virtual"'; |
}; |
// mce mod start |
if (isset($this->fdd[$k]['textarea']['html'])) { |
$mce_tag = 'editable'; |
if (is_string($this->fdd[$k]['textarea']['html'])) { |
$mce_tag = $this->fdd[$k]['textarea']['html']; |
}; |
echo ' mce_'.$mce_tag.'=true '; |
}; |
// mce mod end |
echo '>',htmlspecialchars($row["qf$k"]),'</textarea>',"\n"; |
} else { |
$size_ml_props = ''; |
$maxlen = intval($this->fdd[$k]['maxlen']); |
$size = isset($this->fdd[$k]['size']) ? $this->fdd[$k]['size'] : min($maxlen, 60); |
$size && $size_ml_props .= ' size="'.$size.'"'; |
$maxlen && $size_ml_props .= ' maxlength="'.$maxlen.'"'; |
echo '<input class="',$css_class_name,'" type="text" '; |
echo ($this->readonly($k) ? 'disabled ' : ''); |
/* calendar mod start */ |
echo ' id="',$this->dhtml['prefix'].'fld_'.$this->fds[$k],'"'; |
/* calendar mod end */ |
echo 'name="',$this->cgi['prefix']['data'].$this->fds[$k],'" value="'; |
echo htmlspecialchars($row["qf$k"]),'" ',$size_ml_props,'>',"\n"; |
/* calendar mod start */ |
/* Call calPopup helper function */ |
$this->calPopup_helper($k, htmlspecialchars($row["qf$k"])); |
/* calendar mod end */ |
} |
echo '</td>',"\n"; |
} /* }}} */ |
function form_end() /* {{{ */ |
{ |
if ($this->display['form']) { |
echo '</form>',"\n"; |
/* calendar mod start */ |
/* Add script calls to the end of the form for all fields |
with calendar popups. */ |
if (isset($this->calendars)) { |
echo '<script type="text/javascript"><!--',"\n"; |
foreach($this->calendars as $ck => $cv) { |
echo 'Calendar.setup({',"\n"; |
foreach ($cv as $ck1 => $cv1) { |
if (in_array($ck1, $this->valid_opts)) { |
echo "\t",str_pad($ck1, 15),' : "',$cv1,'",',"\n"; |
} |
} |
echo "\t",str_pad('inputField', 15),' : "',$this->dhtml['prefix'].'fld_'.$ck,'"',"\n"; |
echo '});',"\n"; |
}; |
echo '// -->',"\n"; |
echo '</script>',"\n"; |
}; |
/* calendar mod end */ |
}; |
} /* }}} */ |
} |
?> |
/trunk/jrest/util/extensions/phpMyEdit-calpopup.class.php |
---|
New file |
0,0 → 1,357 |
<?php |
/* |
* phpMyEdit - instant MySQL table editor and code generator |
* |
* extensions/phpMyEdit-calpopup.class.php - phpMyEdit calendar popup extension |
* ____________________________________________________________ |
* |
* Contribution of Adam Hammond <php@pixolet.co.uk>, London, UK |
* Copyright (c) 2003-2006 Platon Group, http://platon.sk/ |
* All rights reserved. |
* |
* See README file for more information about this software. |
* See COPYING file for license information. |
* |
* Download the latest version from |
* http://platon.sk/projects/phpMyEdit/ |
*/ |
/* $Platon: phpMyEdit/extensions/phpMyEdit-calpopup.class.php,v 1.9 2006-01-22 21:44:17 nepto Exp $ */ |
/* |
OVERVIEW |
-------- |
NOTE...This extension will not work with the CVS version of PME |
calPopup extends the standard phpMyEdit class to allow |
a calendar popup helper to be put on any text field. |
This extension uses the free jsCalendar code from |
http://dynarch.com/mishoo/calendar.epl website. |
REQUIREMENTS |
------------ |
The requirement is a properly installed jsCalendar script. |
All browsers supported by jsCalendar are supported by this |
extension. |
USAGE |
----- |
This extension enables the display of a popup calendar selection |
against selected fields. |
In order to use it, you should: |
1. Load the jsCalendar scripts in the <head>...</head> section of |
your phpMyEdit calling program, substituting the correct paths: |
<script type="text/javascript" src="js/calendar.js"></script> |
<script type="text/javascript" src="js/lang/calendar-en.js"></script> |
<script type="text/javascript" src="js/calendar-setup.js"></script> |
2. Choose your preferred jsCalendar CSS file (see jsCalendar |
documentation) and add the following in the <head>...</head> |
section of your phpMyEdit calling program, substituting the |
correct path: |
<link rel="stylesheet" type="text/css" media="screen" |
href="css/calendar-system.css"> |
NOTE: To avoid an unwanted side effect in the CSS style |
produced by phpMyEditSetup.php, add a 'width:auto' property |
into the '.calendar table' entry in your selected jsCalendar |
style sheet. |
3. Call to phpMyEdit-calPopup.class.php instead |
of phpMyEdit.class.php. |
Example: |
require_once 'extensions/phpMyEdit-calpopup.class.php'; |
new phpMyEdit_calpopup($opts); |
4. Add 'calendar' parameter to the field definitions where you |
want a calendar popup in your phpMyEdit calling program. |
Example: |
$opts['fdd']['col_name'] = array( |
'name' => 'Column', |
'select' => 'T', |
'options' => 'ACPVD', |
'required' => true, |
'calendar' => true |
); |
This is will display a button next to the field which pops up |
a calendar when clicked. If that field has a 'strftimemask' |
parameter set, it will use this for the date format. |
For more advanced usage, you can set the 'calendar' parameter |
to an array of valid jsCalendar Calendar.setup options |
(see jSCalendar document for details). Note that not all |
of these options make sense to use in phpMyEdit, and some |
of them will actively break the function. |
Example: |
$opts['fdd']['col_name'] = array( |
'name' => 'Column', |
'select' => 'T', |
'options' => 'ACPVD', |
'required' => true, |
'calendar' => array( |
'ifFormat' => '%Y/%m/%d', // defaults to the ['strftimemask'] |
'firstDay' => 1, // 0 = Sunday, 1 = Monday |
'singleClick' => true, // single or double click to close |
'weekNumbers' => true, // Show week numbers |
'showsTime' => false, // Show time as well as date |
'timeFormat' => '24', // 12 or 24 hour clock |
'label' => '...', // button label (used by phpMyEdit) |
'date' => '2003-12-19 10:00' // Initial date/time for popup |
// (see notes below) |
) |
); |
NOTES |
----- |
1. The popup will normally set the initial value to the current |
field value or to current date/time. 'date' option will always |
override this, even if there is a current date/time value |
in the field. If you want a default value only if the field |
is currently empty, use the phpMyEdit 'default' option. |
2. Only the options listed above may be set by the user, any other |
options will be ignored. |
SEARCH KEYWORD |
-------------- |
Search for "CalPopup" string in this source code, |
to find all extension related modifications. |
*/ |
require_once dirname(__FILE__).'/../phpMyEdit.class.php'; |
class phpMyEdit_calpopup extends phpMyEdit |
{ |
/* CalPopup mod start */ |
/* Array for collecting list of fields with calendar popups */ |
var $calendars; |
/* Array of valid options for passing to Calendar.setup */ |
var $valid_opts = array( |
'button','ifFormat','singleClick','firstDay', |
'weekNumbers','showsTime','timeFormat','date' |
); |
/** |
* Checks to see if the calendar parameter is set on the field |
* |
* @param k current field name |
* @param curval current value of field (set to null for default) |
* |
* If the calendar parameter is set on the field, this function displays |
* the button. It then pushes the Calendar.setup parameters into an array, |
* including the user specified ones in the calling program is they exist. |
* This array is then added to the $calendars array indexed by the field |
* name. This allows for multiple fields with calendar popups. |
*/ |
function CalPopup_helper($k, $curval) /* {{{ */ |
{ |
if (@$this->fdd[$k]['calendar']) { |
$cal_ar['ifFormat'] = '%Y-%m-%d %H:%M'; |
$cal_ar['showsTime'] = true; |
$cal_ar['singleClick'] = false; |
if (isset($curval)) { |
if (substr($curval, 0, 4) != '0000') |
$cal_ar['date'] = $curval; |
} |
if (isset($this->fdd[$k]['strftimemask'])) { |
$cal_ar['ifFormat'] = $this->fdd[$k]['strftimemask']; |
} |
if (is_array($this->fdd[$k]['calendar'])) { |
foreach($this->fdd[$k]['calendar'] as $ck => $cv) { |
$cal_ar[$ck] = $cv; |
} |
} |
$cal_ar['button'] = 'pme_calpopup_button_'.$this->fds[$k]; |
$this->calendars[$this->fds[$k]] = $cal_ar; |
$label = @$this->fdd[$k]['calendar']['label']; |
strlen($label) || $label = '...'; |
echo '<button id="',$cal_ar['button'],'">',$label,'</button>'; |
} |
} /* }}} */ |
/* CalPopup mod end */ |
function display_add_record() /* {{{ */ |
{ |
for ($tab = 0, $k = 0; $k < $this->num_fds; $k++) { |
if (isset($this->fdd[$k]['tab']) && $this->tabs_enabled() && $k > 0) { |
$tab++; |
echo '</table>',"\n"; |
echo '</div>',"\n"; |
echo '<div id="phpMyEdit_tab',$tab,'">',"\n"; |
echo '<table class="',$this->getCSSclass('main'),'" summary="',$this->tb,'">',"\n"; |
} |
if (! $this->displayed[$k]) { |
continue; |
} |
if ($this->hidden($k)) { |
echo $this->htmlHidden($this->fds[$k], $row["qf$k"]); |
continue; |
} |
$css_postfix = @$this->fdd[$k]['css']['postfix']; |
$css_class_name = $this->getCSSclass('input', null, 'next', $css_postfix); |
echo '<tr class="',$this->getCSSclass('row', null, true, $css_postfix),'">',"\n"; |
echo '<td class="',$this->getCSSclass('key', null, true, $css_postfix),'">',$this->fdd[$k]['name'],'</td>',"\n"; |
echo '<td class="',$this->getCSSclass('value', null, true, $css_postfix),'"'; |
echo $this->getColAttributes($k),">\n"; |
if ($this->col_has_values($k)) { |
$vals = $this->set_values($k); |
$selected = @$this->fdd[$k]['default']; |
$multiple = $this->col_has_multiple_select($k); |
$readonly = $this->readonly($k); |
$strip_tags = true; |
$escape = true; |
echo $this->htmlSelect($this->fds[$k], $css_class_name, $vals, $selected, |
$multiple, $readonly, $strip_tags, $escape); |
} elseif (isset ($this->fdd[$k]['textarea'])) { |
echo '<textarea class="',$css_class_name,'" name="',$this->fds[$k],'"'; |
echo ($this->readonly($k) ? ' disabled' : ''); |
if (intval($this->fdd[$k]['textarea']['rows']) > 0) { |
echo ' rows="',$this->fdd[$k]['textarea']['rows'],'"'; |
} |
if (intval($this->fdd[$k]['textarea']['cols']) > 0) { |
echo ' cols="',$this->fdd[$k]['textarea']['cols'],'"'; |
} |
if (isset($this->fdd[$k]['textarea']['wrap'])) { |
echo ' wrap="',$this->fdd[$k]['textarea']['wrap'],'"'; |
} else { |
echo ' wrap="virtual"'; |
} |
echo '>',htmlspecialchars($this->fdd[$k]['default']),'</textarea>',"\n"; |
} else { |
// Simple edit box required |
$size_ml_props = ''; |
$maxlen = intval($this->fdd[$k]['maxlen']); |
$size = isset($this->fdd[$k]['size']) ? $this->fdd[$k]['size'] : min($maxlen, 60); |
$size && $size_ml_props .= ' size="'.$size.'"'; |
$maxlen && $size_ml_props .= ' maxlength="'.$maxlen.'"'; |
/* CalPopup mod start */ |
if (@$this->fdd[$k]['calendar']) { |
$size_ml_props .= ' id="pme_calpopup_input_'.$this->fds[$k].'"'; |
} |
/* CalPopup mod end */ |
echo '<input class="',$css_class_name,'" type="text" '; |
echo ($this->readonly($k) ? 'disabled ' : ''),' name="',$this->fds[$k],'"'; |
echo $size_ml_props,' value="'; |
echo htmlspecialchars($this->fdd[$k]['default']),'">'; |
/* CalPopup mod start */ |
/* Call CalPopup helper function */ |
$this->CalPopup_helper($k, null); |
/* CalPopup mod end */ |
} |
echo '</td>',"\n"; |
if ($this->guidance) { |
$css_class_name = $this->getCSSclass('help', null, true, $css_postfix); |
$cell_value = $this->fdd[$k]['help'] ? $this->fdd[$k]['help'] : ' '; |
echo '<td class="',$css_class_name,'">',$cell_value,'</td>',"\n"; |
} |
echo '</tr>',"\n"; |
} |
} /* }}} */ |
function display_change_field($row, $k) /* {{{ */ |
{ |
$css_postfix = @$this->fdd[$k]['css']['postfix']; |
$css_class_name = $this->getCSSclass('input', null, true, $css_postfix); |
echo '<td class="',$this->getCSSclass('value', null, true, $css_postfix),'"'; |
echo $this->getColAttributes($k),">\n"; |
if ($this->col_has_values($k)) { |
$vals = $this->set_values($k); |
$multiple = $this->col_has_multiple_select($k); |
$readonly = $this->readonly($k); |
$strip_tags = true; |
$escape = true; |
echo $this->htmlSelect($this->fds[$k], $css_class_name, $vals, $row["qf$k"], |
$multiple, $readonly, $strip_tags, $escape); |
} elseif (isset($this->fdd[$k]['textarea'])) { |
echo '<textarea class="',$css_class_name,'" name="',$this->fds[$k],'"'; |
echo ($this->readonly($k) ? ' disabled' : ''); |
if (intval($this->fdd[$k]['textarea']['rows']) > 0) { |
echo ' rows="',$this->fdd[$k]['textarea']['rows'],'"'; |
} |
if (intval($this->fdd[$k]['textarea']['cols']) > 0) { |
echo ' cols="',$this->fdd[$k]['textarea']['cols'],'"'; |
} |
if (isset($this->fdd[$k]['textarea']['wrap'])) { |
echo ' wrap="',$this->fdd[$k]['textarea']['wrap'],'"'; |
} else { |
echo ' wrap="virtual"'; |
} |
echo '>',htmlspecialchars($row["qf$k"]),'</textarea>',"\n"; |
} else { |
$size_ml_props = ''; |
$maxlen = intval($this->fdd[$k]['maxlen']); |
$size = isset($this->fdd[$k]['size']) ? $this->fdd[$k]['size'] : min($maxlen, 60); |
$size && $size_ml_props .= ' size="'.$size.'"'; |
$maxlen && $size_ml_props .= ' maxlength="'.$maxlen.'"'; |
/* CalPopup mod start */ |
if (@$this->fdd[$k]['calendar']) { |
$size_ml_props .= ' id="pme_calpopup_input_'.$this->fds[$k].'"'; |
} |
/* CalPopup mod end */ |
echo '<input class="',$css_class_name,'" type="text" '; |
echo ($this->readonly($k) ? 'disabled ' : ''),'name="',$this->fds[$k],'" value="'; |
echo htmlspecialchars($row["qf$k"]),'" ',$size_ml_props,'>',"\n"; |
/* CalPopup mod start */ |
/* Call CalPopup helper function */ |
$this->CalPopup_helper($k, htmlspecialchars($row["qf$k"])); |
/* CalPopup mod end */ |
} |
echo '</td>',"\n"; |
} /* }}} */ |
function form_end() /* {{{ */ |
{ |
if ($this->display['form']) { |
echo '</form>',"\n"; |
/* CalPopup mod start */ |
/* Add script calls to the end of the form for all fields |
with calendar popups. */ |
if (isset($this->calendars)) { |
echo '<script type="text/javascript"><!--',"\n"; |
foreach($this->calendars as $ck => $cv) { |
echo 'Calendar.setup({',"\n"; |
foreach ($cv as $ck1 => $cv1) { |
if (in_array($ck1, $this->valid_opts)) { |
echo "\t",str_pad($ck1, 15),' : "',$cv1,'",',"\n"; |
} |
} |
echo "\t",str_pad('inputField', 15),' : "pme_calpopup_input_',$ck,'"',"\n"; |
echo '});',"\n"; |
}; |
echo '// --></script>',"\n"; |
}; |
/* CalPopup mod end */ |
}; |
} /* }}} */ |
} |
?> |
/trunk/jrest/util/extensions/phpMyEdit-messages.class.php |
---|
New file |
0,0 → 1,329 |
<?php |
/* |
* phpMyEdit - instant MySQL table editor and code generator |
* |
* extensions/phpMyEdit-messages.class.php - phpMyEdit messages extension |
* ____________________________________________________________ |
* |
* Developed by Ondrej Jombik <nepto@platon.sk> |
* Copyright (c) 2002-2006 Platon Group, http://platon.sk/ |
* All rights reserved. |
* |
* See README file for more information about this software. |
* See COPYING file for license information. |
* |
* Download the latest version from |
* http://platon.sk/projects/phpMyEdit/ |
*/ |
/* $Platon: phpMyEdit/extensions/phpMyEdit-messages.class.php,v 1.15 2006-06-17 11:14:54 nepto Exp $ */ |
/* This extension is part of phpMyEzin: Content Management System project, |
where it handles discussion messages for particular articles. It depends on |
some phpMyEzin characteristics, thus extension should not and cannot be used |
outside this project. However there are planned some improvements for future |
to make this extension handle any kind of tree-structured data. */ |
require_once dirname(__FILE__).'/../phpMyEdit.class.php'; |
class phpMyEdit_messages extends phpMyEdit |
{ |
function phpMyEdit_messages($opts) /* {{{ */ |
{ |
$execute = 1; |
isset($opts['execute']) && $execute = $opts['execute']; |
$opts['execute'] = 0; |
parent::phpMyEdit($opts); |
$this->tb2 = $opts['tb2']; |
$this->format_date = $opts['format_date']; |
/* Preserved article ID in CGI environment. */ |
/* TODO: change to $this->article_id or something like this */ |
global $ezin_admin_article; |
$ezin_admin_article = $this->get_data_cgi_var('article_id'); |
$execute && $this->execute(); |
} /* }}} */ |
function list_table() /* {{{ */ |
{ |
$ezin_admin_article_change_up = $this->get_sys_cgi_var('ezin_admin_article_change_up'); |
$ezin_admin_article_change_down = $this->get_sys_cgi_var('ezin_admin_article_change_down'); |
if (isset($ezin_admin_article_change_up)) { |
$ezin_admin_article = $this->get_sys_cgi_var('ezin_admin_article_up'); |
} elseif (isset($ezin_admin_article_change_down)) { |
$ezin_admin_article = $this->get_sys_cgi_var('ezin_admin_article_down'); |
} |
!isset($ezin_admin_article) && $ezin_admin_article = $this->get_data_cgi_var('article_id'); |
$ezin_admin_article = intval($ezin_admin_article); |
$query = sprintf('SELECT article_id, count(id) AS messages FROM %s' |
.' GROUP BY article_id HAVING article_id = %d', |
$this->tb, intval($ezin_admin_article)); |
if (($result = $this->myquery($query)) == false) { |
return false; |
} |
$row = @mysql_fetch_array($result, MYSQL_ASSOC); |
//$ezin_admin_article = intval($row['article_id']); |
$ezin_admin_msgcount = intval($row['messages']); |
@mysql_free_result($result); |
echo '<form class="',$this->getCSSclass('form'); |
echo '" action="',$page_name,'" method="POST">',"\n"; |
if ($this->nav_up() || $ezin_admin_article <= 0) { |
$this->message_nav_buttons($ezin_admin_article, $ezin_admin_msgcount, 'up'); |
echo '<hr class="',$this->getCSSclass('hr', 'up'),'">',"\n"; |
} |
if ($ezin_admin_article > 0) { |
echo '<table class="',$this->getCSSclass('main'),'" summary="',$this->tb,'">',"\n"; |
echo '<tr class="',$this->getCSSclass('header'),'">',"\n"; |
foreach (array('ID', 'Subject', ' ', 'Author', 'Date & Time', 'IP addresses') as $str) { |
echo '<th class="',$this->getCSSclass('header'),'">'; |
echo Platon::htmlspecialchars2($str),'</th>',"\n"; |
} |
echo '</tr>',"\n"; |
echo '<tr class="',$this->getCSSclass('header'),'">',"\n"; |
echo '<th class="',$this->getCSSclass('header'),'" colspan="6">'; |
echo 'Valid messages</td></tr>',"\n"; |
$message_ids = $this->message_process($ezin_admin_article, 0, 0); |
$count_message_ids = count($message_ids); |
if ($count_message_ids == 0) { |
echo '<tr class="',$this->getCSSclass('row', null, 'next'),'">',"\n"; |
echo '<td class="',$this->getCSSclass('cell', null, true),'" colspan="6">',"\n"; |
echo '<i>There are no valid messages for this article.</i>'; |
echo '</td></tr>',"\n"; |
} |
$query = sprintf('SELECT id, parent, article_id, author,' |
.' email, homepage, subject, datetime, ip' |
.' FROM %s WHERE article_id = %d ORDER BY datetime ASC', |
$this->tb, intval($ezin_admin_article)); |
if (($result = $this->myquery($query)) == false) { |
return false; |
} |
$all_ids = array(); |
$parents = array(); |
for ($i = 0; ($row = @mysql_fetch_array($result, MYSQL_ASSOC)); $i++) { |
$all_ids[] = $row['id']; |
$parents[$row['id']] = $row['parent']; |
} |
@mysql_free_result($result); |
$all_ids = array_diff($all_ids, $message_ids); |
echo '<tr class="',$this->getCSSclass('header'),'">',"\n"; |
echo '<th class="',$this->getCSSclass('header'),'" colspan="6">'; |
echo 'Invalid messages</td></tr>',"\n"; |
if (count($all_ids) > 0) { |
/* To force buttons */ |
$count_message_ids = -1; |
while (count($all_ids) > 0) { |
//echo "<p>all_ids: "; var_dump($all_ids);echo '<br>'; |
$sub_ids = $this->message_process($ezin_admin_article, |
$parents[array_shift($all_ids)], 0, true); |
$all_ids = array_diff($all_ids, $sub_ids); |
} |
} else { |
echo '<tr class="',$this->getCSSclass('row', null, 'next'),'">',"\n"; |
echo '<td class="',$this->getCSSclass('cell', null, true),'" colspan="6">',"\n"; |
echo '<i>There are no invalid messages for this article.</i>'; |
echo '</td></tr>',"\n"; |
} |
echo '</table>'; |
} |
if ($this->nav_down() && $ezin_admin_article > 0) { |
echo '<hr class="',$this->getCSSclass('hr', 'down'),'">',"\n"; |
$this->message_nav_buttons($ezin_admin_article, $ezin_admin_msgcount, 'down'); |
} |
echo $this->htmlHiddenData('article_id', $ezin_admin_article); |
echo '</form>',"\n"; |
} /* }}} */ |
function message_process($article_id, $id, $level = 0, $parent = true) /* {{{ */ |
{ |
$id = intval($id); |
$level = intval($level); |
$query = sprintf('SELECT id, parent, article_id, author,' |
.' email, homepage, subject, datetime, ip' |
.' FROM %s WHERE %s = %d AND article_id = %d' |
.' ORDER BY datetime ASC', $this->tb, |
$parent == true ? 'parent' : 'id', intval($id), intval($article_id)); |
if (($result = $this->myquery($query)) == false) { |
return false; |
} |
$ar = array(); |
$ar_out = array(); |
for ($i = 0; ($row = @mysql_fetch_array($result, MYSQL_ASSOC)); $i++) { |
$ar[$i] = $row; |
$ar_out[] = $row['id']; |
} |
$checked = ! $level && $parent ? ' checked' : ''; |
for ($i = 0; $i < count($ar); $i++) { |
echo '<tr class="',$this->getCSSclass('row', null, 'next'),'">',"\n"; |
$css_class_name = $this->getCSSclass('cell', null, true); |
$css_class_name2 = $this->getCSSclass('navigation', null, true); |
echo '<td class="',$css_class_name,'">',$ar[$i]['id'],'</td>',"\n"; |
echo '<td class="',$css_class_name,'">'; |
for ($j = 0; $j < $level; $j++) { |
echo ' '; |
} |
echo htmlspecialchars($ar[$i]['subject']); |
echo '</td>',"\n"; |
echo '<td class="',$css_class_name2,'">'; |
echo '<input',$checked,' class="',$css_class_name2,'"'; |
echo ' type="radio" ','name="',$this->cgi['prefix']['sys'],'rec"'; |
echo ' value="',$ar[$i]['id'],'" class="link"></td>',"\n"; |
echo '<td class="',$css_class_name,'">',htmlspecialchars($ar[$i]['author']), '</td>'; |
echo '<td class="',$css_class_name,'">',htmlspecialchars($ar[$i]['datetime']),'</td>'; |
// TODO: do resolving |
echo '<td class="',$css_class_name,'"><small>'; |
// this shoud be global IP-adress-deliminator |
$output = false; |
$ar_ip = preg_split('|([ ]*[ \\/,;]+[ ]*)|', $ar[$i]['ip'], -1, PREG_SPLIT_DELIM_CAPTURE); |
foreach ($ar_ip as $ip) { |
if (strlen($output) > 0) { |
$output = true; |
} |
$ip = htmlspecialchars($ip); |
if (preg_match('/^(\d{1,3}\.){3}\d{1,3}$/', $ip)) { |
echo '<a class="',$css_class_name,'" target="_blank" href="http://',$ip,'">'; |
echo '<small>',$ip,'</small></a>'; |
} else { |
echo $ip; |
} |
} |
if (! $output) { |
echo ' '; |
} |
echo '</small></td>',"\n"; |
echo '</tr>',"\n"; |
if ($parent) { |
$ar_out = array_merge($ar_out, $this->message_process( |
$article_id, $ar[$i]['id'], $level + 1)); |
} |
strlen($checked) && $checked = ''; |
} |
return $ar_out; |
} /* }}} */ |
function message_nav_buttons($article_id, $messages_count, $position) /* {{{ */ |
{ |
echo '<table class="',$this->getCSSclass('navigation', $position),'">',"\n"; |
echo '<tr class="',$this->getCSSclass('navigation', $position),'">',"\n"; |
echo '<td class="',$this->getCSSclass('buttons', $position),'">',"\n"; |
$this->print_article_select($article_id, 0, $position); |
echo '</td>',"\n"; |
echo '<td class="',$this->getCSSclass('buttons2', $position),'">',"\n"; |
if ($article_id > 0) { |
if ($this->add_enabled()) { |
echo $this->htmlSubmit('operation', 'Add', $this->getCSSclass('add', $position), false, false); |
} |
if ($this->view_enabled()) { |
echo ' '; |
echo $this->htmlSubmit('operation', 'View', $this->getCSSclass('view', $position), |
false, $messages_count <= 0); |
} |
if ($this->change_enabled()) { |
echo ' '; |
echo $this->htmlSubmit('operation', 'Change', $this->getCSSclass('change', $position), |
false, $messages_count <= 0); |
} |
if ($this->delete_enabled()) { |
echo ' '; |
echo $this->htmlSubmit('operation', 'Delete', $this->getCSSclass('delete', $position), |
false, $messages_count <= 0); |
} |
} |
echo '</td></tr></table>',"\n"; |
} /* }}} */ |
function display_record_buttons() /* {{{ */ |
{ |
echo '<table class="',$this->getCSSclass('navigation', $position),'">',"\n"; |
echo '<tr class="',$this->getCSSclass('navigation', $position),'">',"\n"; |
echo '<td class="',$this->getCSSclass('buttons', $position),'">',"\n"; |
$this->print_article_select($article_id, 1, $position); |
echo '</td>',"\n"; |
if (strlen(@$this->message) > 0) { |
echo '<td class="',$this->getCSSclass('message', $position),'">',$this->message,'</td>',"\n"; |
} |
echo '<td class="',$this->getCSSclass('buttons2', $position),'">',"\n"; |
if ($this->change_operation()) { |
echo $this->htmlSubmit('savechange', 'Save', $this->getCSSclass('save', $position), true), ' '; |
echo $this->htmlSubmit('morechange', 'Apply', $this->getCSSclass('more', $position), true), ' '; |
echo $this->htmlSubmit('cancelchange', 'Cancel', $this->getCSSclass('cancel', $position), false); |
} elseif ($this->add_operation()) { |
echo $this->htmlSubmit('saveadd', 'Save', $this->getCSSclass('save', $position), true), ' '; |
echo $this->htmlSubmit('moreadd', 'More', $this->getCSSclass('more', $position), true), ' '; |
echo $this->htmlSubmit('canceladd', 'Cancel', $this->getCSSclass('cancel', $position), false); |
} elseif ($this->delete_operation()) { |
echo $this->htmlSubmit('savedelete', 'Delete', $this->getCSSclass('save', $position), false), ' '; |
echo $this->htmlSubmit('canceldelete', 'Cancel', $this->getCSSclass('cancel', $position), false); |
} elseif ($this->view_operation()) { |
if ($this->change_enabled()) { |
echo $this->htmlSubmit('operation', 'Change', $this->getCSSclass('save', $position), false), ' '; |
} |
echo $this->htmlSubmit('cancelview', 'Cancel', $this->getCSSclass('cancel', $position), false); |
} |
// Message is now written here |
echo '</td>',"\n"; |
echo '</tr></table>',"\n"; |
} /* }}} */ |
function print_article_select($selected_id, $disabled, $position) /* {{{ */ |
{ |
if ($selected_id <= 0) { |
$rec = intval($this->get_sys_cgi_var('rec')); |
if ($rec > 0) { |
$query = sprintf('SELECT article_id FROM %s WHERE id = %d', |
$this->tb, $rec); |
$result = $this->myquery($query); |
if ($result != false) { |
$row = @mysql_fetch_array($result, MYSQL_NUM); |
$selected_id = $row[0]; |
} |
@mysql_free_result($result); |
} |
} |
static $articles = null; |
if ($articles == null) { |
$articles = array(); |
$query = 'SELECT id, title, atitle, UNIX_TIMESTAMP(datetime) AS date' |
.' FROM '.$this->tb2 |
.' ORDER BY date DESC'; |
if (($result = $this->myquery($query)) == false) { |
return false; |
} |
for ($k = 0; ($row = @mysql_fetch_array($result, MYSQL_ASSOC)); $k++) { |
$articles[] = $row; |
} |
@mysql_free_result($result); |
} |
echo '<select',($disabled ? ' disabled' : ''),' name="'; |
echo $this->cgi['prefix']['sys'].'ezin_admin_article_',$position,'" size="1">',"\n"; |
echo '<option value="0">-- Choose article --</option>',"\n"; |
foreach ($articles as $row) { |
$row['title'] = empty($row['title']) ? $row['atitle'] : $row['title']; |
$row['title'] = Platon::pretty_substr(strip_tags($row['title']), 40); |
echo '<option'.($selected_id == $row['id'] ? ' selected' : ''); |
echo ' value="',$row['id'],'">',$row['title']; |
if ($row['date'] > 0) { |
printf(' [%d] (%s)', $row['id'], date($this->format_date, $row['date'])); |
} |
echo '</option>',"\n"; |
} |
echo '</select>',"\n"; |
if (! $disabled) { |
echo $this->htmlSubmit('ezin_admin_article_change_'.$position, ' > ', $this->get_sys_cgi_var('change', $position)), ' ', "\n"; |
} |
return true; |
} /* }}} */ |
} |
/* Modeline for ViM {{{ |
* vim:set ts=4: |
* vim600:fdm=marker fdl=0 fdc=0: |
* }}} */ |
?> |
/trunk/jrest/util/extensions/phpMyEdit-report.class.php |
---|
New file |
0,0 → 1,319 |
<?php |
/* |
* phpMyEdit - instant MySQL table editor and code generator |
* |
* extensions/phpMyEdit-report.class.php - phpMyEdit report extension |
* ____________________________________________________________ |
* |
* Developed by Ondrej Jombik <nepto@platon.sk> |
* Copyright (c) 2002-2006 Platon Group, http://platon.sk/ |
* All rights reserved. |
* |
* See README file for more information about this software. |
* See COPYING file for license information. |
* |
* Download the latest version from |
* http://platon.sk/projects/phpMyEdit/ |
*/ |
/* $Platon: phpMyEdit/extensions/phpMyEdit-report.class.php,v 1.12 2006-01-22 21:44:23 nepto Exp $ */ |
/* Extension TODO: |
- allow user to enable/disable particular field in reporting (maybe 'X' flag |
for indicating that field is forbidden is good idea) |
- support for ['help'] in select fields screen |
- make extension's option for selecting "Select fields" link or button |
*/ |
require_once dirname(__FILE__).'/../phpMyEdit.class.php'; |
class phpMyEdit_report extends phpMyEdit |
{ |
function phpMyEdit_report($opts) /* {{{ */ |
{ |
$opts['options'] = 'L'; |
$execute = 1; |
isset($opts['execute']) && $execute = $opts['execute']; |
$opts['execute'] = 0; |
parent::phpMyEdit($opts); |
$execute && $this->execute(); |
} /* }}} */ |
function make_language_labels($language) /* {{{ */ |
{ |
$ret = parent::make_language_labels($language); |
strlen($ret['Make report']) <= 0 && $ret['Make report'] = 'Make report'; |
strlen($ret['Select fields']) <= 0 && $ret['Select fields'] = 'Select fields'; |
strlen($ret['Records per screen']) <= 0 && $ret['Records per screen'] = 'Records per screen'; |
return $ret; |
} /* }}} */ |
function get_cgi_cookie_var($name, $default_value = null) /* {{{ */ |
{ |
$ret = $this->get_cgi_var($name, null); |
if ($ret === null) { |
global $HTTP_COOKIE_VARS; |
$ret = @$HTTP_COOKIE_VARS[$name.'_'.$this->tb.'_cookie']; |
if (! isset($ret)) { |
$ret = $default_value; |
} |
} |
return $ret; |
} /* }}} */ |
function display_list_table_buttons($total_recs, $position) /* {{{ */ |
{ /* This is mostly copy/paste from core class. */ |
$listall = $this->inc <= 0; // Are we doing a listall? |
echo '<table class="',$this->getCSSclass('navigation', $position),'">',"\n"; |
echo '<tr class="',$this->getCSSclass('navigation', $position),'">',"\n"; |
echo '<td class="',$this->getCSSclass('buttons', $position),'">',"\n"; |
echo '<input class="',$this->getCSSclass('fields-select', $position); |
echo '" type="submit" name="fields_select" value="',$this->labels['Select fields'],'"> '; |
// Note that <input disabled isn't valid HTML, but most browsers support it |
$disabled = ($this->fm > 0 && ! $listall) ? '' : ' disabled'; |
echo '<input',$disabled,' class="',$this->getCSSclass('prev', $position); |
echo '" type="submit" name="',ltrim($disabled),'prev" value="',$this->labels['Prev'],'"> '; |
$disabled = ($this->fm + $this->inc < $total_recs && ! $listall) ? '' : ' disabled'; |
echo '<input',$disabled,' class="',$this->getCSSclass('next', $position); |
echo '" type="submit" name="',ltrim($disabled),'next" value="',$this->labels['Next'],'">'; |
// Message is now written here |
echo '</td>',"\n"; |
if (strlen(@$this->message) > 0) { |
echo '<td class="',$this->getCSSclass('message', $position),'">',$this->message,'</td>',"\n"; |
} |
// Display page and records statistics |
echo '<td class="',$this->getCSSclass('stats', $position),'">',"\n"; |
if ($listall) { |
echo $this->labels['Page'],': 1 ',$this->labels['of'],' 1'; |
} else { |
echo $this->labels['Page'],': ',($this->fm / $this->inc) + 1; |
echo ' ',$this->labels['of'],' ',max(1, ceil($total_recs / abs($this->inc))); |
} |
echo ' ',$this->labels['Records'],': ',$total_recs; |
echo '</td></tr></table>',"\n"; |
} /* }}} */ |
function display_report_selection_buttons($position) /* {{{ */ |
{ |
echo '<table class="',$this->getCSSclass('navigation', $position),'">',"\n"; |
echo '<tr class="',$this->getCSSclass('navigation', $position),'">',"\n"; |
echo '<td class="',$this->getCSSclass('buttons', $position),'">',"\n"; |
echo '<input class="',$this->getCSSclass('make-report', $position); |
echo '" type="submit" name="prepare_filter" value="',$this->labels['Make report'],'">',"\n"; |
echo '</td></tr></table>',"\n"; |
} /* }}} */ |
function get_select_fields_link() /* {{{ */ |
{ |
$link = '<a href="'.htmlspecialchars($this->page_name).'?fields_select=1'; |
for ($i = 0; $i < count($table_cols); $i++) { |
$varname = 'qf'.$i; |
$value = $this->get_cgi_cookie_var($varname); |
if (! empty($value)) { |
$link .= htmlspecialchars( |
'&'.rawurlencode($varname). |
'='.rawurlencode($value)); |
} |
} |
$link .= htmlspecialchars($this->cgi['persist']); |
$link .= '">'.$this->labels['Select fields'].'</a>'; |
return $link; |
} /* }}} */ |
function execute() /* {{{ */ |
{ |
global $HTTP_GET_VARS; |
global $HTTP_POST_VARS; |
/* |
* Extracting field names |
*/ |
$table_cols = array(); |
$all_table_cols = array(); |
if ($this->connect() == false) { |
return false; |
} |
$query_parts = array( |
'type' => 'select', |
'select' => '*', |
'from' => $this->tb, |
'limit' => '1'); |
$result = $this->myquery($this->get_SQL_query($query_parts), __LINE__); |
$all_table_cols = array_keys(@mysql_fetch_array($result, MYSQL_ASSOC)); |
if (count($all_table_cols) <= 0) { |
$this->error('database fetch error'); |
return false; |
} |
foreach (array_keys($this->fdd) as $field_name) { |
if (preg_match('/^\d*$/', $field_name)) |
continue; |
if (($idx = array_search($field_name, $all_table_cols)) !== false) |
$table_cols[$field_name] = mysql_field_len($result, $idx); |
} |
@mysql_free_result($result); |
unset($all_table_cols); |
/* |
* Preparing variables |
*/ |
$fields_select = $this->get_cgi_var('fields_select'); |
$filter = $this->get_cgi_var('filter'); |
$prepare_filter = $this->get_cgi_var('prepare_filter'); |
$this->inc = intval($this->get_cgi_cookie_var('inc')); |
$force_select = true; |
$none_displayed = true; |
$expire_time = time() + (3600 * 24 * 30 * 12 * 5); // five years |
$headers_sent = @headers_sent(); |
foreach (array_merge(array('@inc'), array_keys($table_cols)) as $col) { |
$varname = ($col[0] == '@' ? substr($col, 1) : 'have_'.$col); |
if (isset($HTTP_POST_VARS[$varname]) || isset($HTTP_GET_VARS[$varname])) { |
$value = $HTTP_POST_VARS[$varname]; |
if (isset($HTTP_GET_VARS[$varname])) { |
$value = $HTTP_GET_VARS[$varname]; |
} |
if ($varname != 'inc' && ! empty($value)) { |
$force_select = false; |
} |
$headers_sent || setcookie($varname.'_'.$this->tb.'_cookie', $value, $expire_time); |
$this->cgi['persist'] .= '&'.urlencode($varname); |
$this->cgi['persist'] .= '='.urlencode($value); |
} else { |
$headers_sent || setcookie($varname.'_'.$this->tb.'_cookie', '', time() - 10000); |
} |
} |
$i = -1; |
foreach (array_keys($this->fdd) as $key) { |
$i++; |
if (preg_match('/^\d*$/', $key)) |
continue; |
$varname = 'have_'.$key; |
$value = @$this->get_cgi_cookie_var($varname, ''); |
$options = @$value ? 'LV' : ''; |
$this->fdd[$i]['options'] = $options; |
$this->fdd[$key]['options'] = $options; |
$this->displayed[$i] = @$value ? true : false; |
$value && $none_displayed = false; |
} |
/* |
* Redirecting when neccessary |
* (hackity hack with unregistering/unchecking fields) |
*/ |
if ($prepare_filter && ! $headers_sent) { |
$this->execute_redirect(); |
exit; |
} |
/* |
* Check if field selection report screen has to be displayed |
*/ |
if (isset($fields_select) || $force_select || $none_displayed) { |
$this->execute_report_screen($table_cols); |
return true; |
} |
if (0) { |
$this->message .= $this->get_select_fields_link(); |
} |
// parent class call |
return parent::execute(); |
} /* }}} */ |
function execute_redirect() /* {{{ */ |
{ |
global $HTTP_SERVER_VARS; |
global $HTTP_GET_VARS; |
global $HTTP_POST_VARS; |
$redirect_url = 'http://'.$HTTP_SERVER_VARS['HTTP_HOST'].$HTTP_SERVER_VARS['SCRIPT_NAME']; |
$delim = '?'; |
foreach ($HTTP_POST_VARS + $HTTP_GET_VARS as $cgi_var_name => $cgi_var_value) { |
$cgi_var_name == 'prepare_filter' && $cgi_var_name = 'filter'; |
$redirect_url .= $delim; |
$redirect_url .= rawurlencode($cgi_var_name).'='.rawurlencode($cgi_var_value); |
$delim == '?' && $delim = '&'; |
} |
$redirect_url .= $this->cgi['persist']; |
header('Location: '.$redirect_url); |
exit; |
} /* }}} */ |
function execute_report_screen($table_cols) /* {{{ */ |
{ |
echo '<form class="',$this->getCSSclass('form'),'" action="'; |
echo htmlspecialchars($this->page_name),'" method="POST">',"\n"; |
if ($this->nav_up()) { |
$this->display_report_selection_buttons('up'); |
echo '<hr class="',$this->getCSSclass('hr', 'up'),'">',"\n"; |
} |
echo '<table class="',$this->getCSSclass('main'),'" summary="',$this->tb,'">',"\n"; |
$i = 0; |
foreach ($table_cols as $key => $val) { |
$css_postfix = @$this->fdd[$key]['css']['postfix']; |
$css_class_name = $this->getCSSclass('input', null, true, $css_postfix); |
$varname = 'have_'.$key; |
$value = $this->get_cgi_cookie_var($varname); |
$checked = @$value ? ' checked' : ''; |
echo '<tr class="',$this->getCSSclass('row', null, 'next', $css_postfix),'">',"\n"; |
echo '<td class="',$this->getCSSclass('key', null, true, $css_postfix),'">'; |
echo $this->fdd[$i]['name'],'</td>',"\n"; |
echo '<td class="',$this->getCSSclass('check', null, true, $css_postfix),'">'; |
echo '<input class="',$css_class_name,'" type="checkbox" name="'; |
echo htmlspecialchars($varname),'"',$checked,'>'; |
echo '</td>',"\n"; |
echo '<td class="',$this->getCSSclass('value', null, true, $css_postfix),'"'; |
echo $this->getColAttributes($key),">\n"; |
$varname = 'qf'.$i; |
$value = $this->get_cgi_cookie_var($varname); |
if ($this->fdd[$key]['select'] == 'D' || $this->fdd[$key]['select'] == 'M') { |
$from_table = ! $this->col_has_values($key) || isset($this->fdd[$key]['values']['table']); |
$selected = $value; |
$value = $this->set_values($key, array('*' => '*'), null, $from_table); |
$multiple = $this->col_has_multiple_select($key); |
$multiple |= $this->fdd[$key]['select'] == 'M'; |
$readonly = false; |
$strip_tags = true; |
$escape = true; |
echo $this->htmlSelect($varname.'_id', $css_class_name, $value, $selected, |
$multiple, $readonly, $strip_tags, $escape); |
} else { |
echo '<input class="',$css_class_name,'" type=text name="'; |
echo htmlspecialchars($varname),'" value="',htmlspecialchars($value),'" size="'; |
echo min(40, $val),'" maxlength="',min(40, max(10, $val)),'">'; |
} |
echo '</td>',"\n",'</tr>',"\n"; |
$i++; |
} |
echo '<tr class="',$this->getCSSclass('row', null, 'next', $css_postfix),'">',"\n"; |
echo '<td class="',$this->getCSSclass('key', null, true, $css_postfix),'" colspan="2">'; |
echo $this->labels['Records per screen'],'</td>'; |
echo '<td class="',$this->getCSSclass('value', null, true, $css_postfix),'">'; |
echo '<input class="',$css_class_name,'" type="text" name="inc" value="',$this->inc.'">'; |
echo '</td></tr>',"\n"; |
echo '</table>',"\n"; |
if ($this->nav_down()) { |
echo '<hr class="',$this->getCSSclass('hr', 'down'),'">',"\n"; |
$this->display_report_selection_buttons('down'); |
} |
echo '</form>'; |
} /* }}} */ |
} |
/* Modeline for ViM {{{ |
* vim:set ts=4: |
* vim600:fdm=marker fdl=0 fdc=0: |
* }}} */ |
?> |
/trunk/jrest/util/extensions/phpMyEdit-htmlarea.class.php |
---|
New file |
0,0 → 1,209 |
<?php |
/* |
* phpMyEdit - instant MySQL table editor and code generator |
* |
* extensions/phpMyEdit-htmlarea.class.php - phpMyEdit htmlArea extension |
* ____________________________________________________________ |
* |
* Contribution of Ezudin Kurtowich <ekurtovic@ieee.org>, Sarajevo |
* Copyright (c) 2003-2006 Platon Group, http://platon.sk/ |
* All rights reserved. |
* |
* See README file for more information about this software. |
* See COPYING file for license information. |
* |
* Download the latest version from |
* http://platon.sk/projects/phpMyEdit/ |
*/ |
/* $Platon: phpMyEdit/extensions/phpMyEdit-htmlarea.class.php,v 1.10 2006-01-22 21:44:18 nepto Exp $ */ |
/* |
OVERVIEW |
-------- |
NOTE...This extension will not work with the CVS version of PME. It has |
been replaced by the mce_cal extension. |
htmlArea is a free WYSIWYG textarea replacement from |
http://www.interactivetools.com/ website. |
REQUIREMENTS |
------------ |
The extension requires a properly installed htmlArea script |
as described on the http://www.interactivetools.com/ site. |
USAGE |
----- |
This extension enables WYSIWYG editing of a textarea field. |
In order to use it, you should: |
1. Load htmlArea script in the <head>...</head> section of your |
phpMyEdit calling program as described in the htmlarea manual. |
NOTE: To avoid an unwanted side effect in css style produced |
by phpMyEditSetup.php, delete 'table-width:100%' property. |
2. Call to phpMyEdit-htmlarea.class.php instead |
of phpMyEdit.class.php. |
Example: |
require_once 'extensions/phpMyEdit-htmlarea.class.php'; |
new phpMyEdit_htmlarea($opts); |
3. Add 'html'=>true parameter to the textarea field definition |
in your phpMyEdit calling program. |
Example: |
$opts['fdd']['col_name'] = array( |
'name' => 'Column', |
'select' => 'T', |
'options' => 'ACPVD', |
'required' => true, |
'textarea' => array( |
'html' => true, |
'rows' => 11, |
'cols' => 81) |
); |
SEARCH KEYWORD |
-------------- |
Search for "htmlArea" string in this source code, |
to find all extension related modifications. |
*/ |
require_once dirname(__FILE__).'/../phpMyEdit.class.php'; |
class phpMyEdit_htmlarea extends phpMyEdit |
{ |
/* |
* Display functions overriding |
*/ |
function display_add_record() /* {{{ */ |
{ |
for ($k = 0; $k < $this->num_fds; $k++) { |
if ($this->hidden($k)) { |
echo $this->htmlHidden($this->fds[$k], $row["qf$k"]); |
continue; |
} |
if (! $this->displayed[$k]) { |
continue; |
} |
$css_postfix = @$this->fdd[$k]['css']['postfix']; |
$css_class_name = $this->getCSSclass('input', null, 'next', $css_postfix); |
echo '<tr class="',$this->getCSSclass('row', null, true, $css_postfix),'">',"\n"; |
echo '<td class="',$this->getCSSclass('key', null, true, $css_postfix),'">',$this->fdd[$k]['name'],'</td>',"\n"; |
echo '<td class="',$this->getCSSclass('value', null, true, $css_postfix),'">'."\n"; |
if ($this->col_has_values($k)) { |
$vals = $this->set_values($k); |
$selected = @$this->fdd[$k]['default']; |
$multiple = $this->fdd[$k]['select'] == 'M' && ! $this->fdd[$k]['values']['table']; |
$readonly = $this->readonly($k); |
echo $this->htmlSelect($this->fds[$k], $css_class_name, $vals, $selected, $multiple,$readonly); |
} elseif (isset ($this->fdd[$k]['textarea'])) { |
echo '<textarea class="',$css_class_name,'" name="'.$this->fds[$k].'"'; |
echo ($this->readonly($k) ? ' disabled' : ''); |
if (intval($this->fdd[$k]['textarea']['rows']) > 0) { |
echo ' rows="',$this->fdd[$k]['textarea']['rows'],'"'; |
} |
if (intval($this->fdd[$k]['textarea']['cols']) > 0) { |
echo ' cols="',$this->fdd[$k]['textarea']['cols'],'"'; |
} |
if (isset($this->fdd[$k]['textarea']['wrap'])) { |
echo ' wrap="',$this->fdd[$k]['textarea']['wrap'],'"'; |
} else { |
echo ' wrap="virtual"'; |
} |
echo '>',htmlspecialchars($this->fdd[$k]['default']),'</textarea>',"\n"; |
// EK htmlArea code modification is here |
if (isset($this->fdd[$k]['textarea']['html'])) { |
echo '<script type="text/javascript" language="javascript1.2"><!--',"\n"; |
echo 'editor_generate("',$this->fds[$k],'");',"\n"; |
echo '// --></script>'; |
} |
} else { |
// Simple edit box required |
$size_ml_props = ''; |
$maxlen = intval($this->fdd[$k]['maxlen']); |
//$maxlen > 0 || $maxlen = 300; |
$size = min($maxlen, 60); |
$size && $size_ml_props .= ' size="'.$size.'"'; |
$maxlen && $size_ml_props .= ' maxlength="'.$maxlen.'"'; |
echo '<input class="',$css_class_name,'" type="text" '; |
echo ($this->readonly($k) ? 'disabled ' : ''),' name="',$this->fds[$k],'"'; |
echo $size_ml_props,' value="'; |
echo htmlspecialchars($this->fdd[$k]['default']),'">'; |
} |
echo '</td>',"\n"; |
if ($this->guidance) { |
$css_class_name = $this->getCSSclass('help', null, true, $css_postfix); |
$cell_value = $this->fdd[$k]['help'] ? $this->fdd[$k]['help'] : ' '; |
echo '<td class="',$css_class_name,'">',$cell_value,'</td>',"\n"; |
} |
echo '</tr>',"\n"; |
} |
} /* }}} */ |
function display_change_field($row, $k) /* {{{ */ |
{ |
$css_postfix = @$this->fdd[$k]['css']['postfix']; |
$css_class_name = $this->getCSSclass('input', null, true, $css_postfix); |
echo '<td class="',$this->getCSSclass('value', null, true, $css_postfix),'">',"\n"; |
if ($this->col_has_values($k)) { |
$vals = $this->set_values($k); |
$multiple = $this->fdd[$k]['select'] == 'M' && ! $this->fdd[$k]['values']['table']; |
$readonly = $this->readonly($k); |
echo $this->htmlSelect($this->fds[$k], $css_class_name, $vals, $row["qf$k"], $multiple, $readonly); |
} elseif (isset($this->fdd[$k]['textarea'])) { |
echo '<textarea class="',$css_class_name,'" name="'.$this->fds[$k].'"'; |
echo ($this->readonly($k) ? ' disabled' : ''); |
if (intval($this->fdd[$k]['textarea']['rows']) > 0) { |
echo ' rows="',$this->fdd[$k]['textarea']['rows'],'"'; |
} |
if (intval($this->fdd[$k]['textarea']['cols']) > 0) { |
echo ' cols="',$this->fdd[$k]['textarea']['cols'],'"'; |
} |
if (isset($this->fdd[$k]['textarea']['wrap'])) { |
echo ' wrap="',$this->fdd[$k]['textarea']['wrap'],'"'; |
} else { |
echo ' wrap="virtual"'; |
} |
echo '>',htmlspecialchars($row["qf$k"]),'</textarea>',"\n"; |
// EK htmlArea code modification is here |
if (isset($this->fdd[$k]['textarea']['html'])) { |
echo '<script type="text/javascript" language="javascript1.2"><!--',"\n"; |
echo 'editor_generate("',$this->fds[$k],'");',"\n"; |
echo '// --></script>'; |
} |
} else { |
$size_ml_props = ''; |
$maxlen = intval($this->fdd[$k]['maxlen']); |
//$maxlen > 0 || $maxlen = 300; |
$size = min($maxlen, 60); |
$size && $size_ml_props .= ' size="'.$size.'"'; |
$maxlen && $size_ml_props .= ' maxlength="'.$maxlen.'"'; |
echo '<input class="',$css_class_name,'" type="text" '; |
echo ($this->readonly($k) ? 'disabled ' : ''),'name="',$this->fds[$k],'" value="'; |
echo htmlspecialchars($row["qf$k"]),'" ',$size_ml_props,'>',"\n"; |
} |
echo '</td>',"\n"; |
} /* }}} */ |
} |
/* Modeline for ViM {{{ |
* vim:set ts=4: |
* vim600:fdm=marker fdl=0 fdc=0: |
* }}} */ |
?> |
/trunk/jrest/util/lang/PME.lang.DE.inc |
---|
New file |
0,0 → 1,67 |
<?php |
/* |
* phpMyEdit language file |
* |
* language: german (standard) |
* encoding: iso-8859-1 |
* date: 2002-07 |
* authors: |
* Christof Brandstetter <fellz@users.sourceforge.net> |
* Gerd Xhonneux, http://xsite.xhonneux.com |
* info: http://makeashorterlink.com/?O116223C2 |
*/ |
/* $Platon: phpMyEdit/lang/PME.lang.DE.inc,v 1.14 2004-12-27 20:14:29 nepto Exp $ */ |
return Array( |
'Add' =>'Hinzufügen', |
'Copy' =>'Kopieren', |
'Change' =>'Ändern', |
'Delete' =>'Löschen', |
'View' =>'Anzeigen', |
'Prev' =>'Zurück', |
'Next' =>'Weiter', |
'First' =>'First', // untranslated |
'Last' =>'Last', // untranslated |
'Go to' =>'Go to', // untranslated |
'Page' =>'Seite', |
'Records' =>'Datensätze', |
'Save' =>'Speichern', |
'More' =>'Speichern, weiteren Datensatz hinzufügen', |
'Apply' =>'Anwenden', |
'Cancel' =>'Abbrechen', |
'Search' =>'Suche', |
'Hide' =>'Verstecken', |
'Clear' =>'Löschen', |
'Query' =>'Abfrage', |
'Current Query' =>'Aktuelle Abfrage', |
'Sorted By' =>'Sortiert nach', |
'ascending' =>'aufsteigend', |
'descending' =>'absteigend', |
'hidden' =>'versteckt', |
'of' =>'von', |
'record added' =>'Datensatz hinzugefügt', |
'record changed'=>'Datensatz geändert', |
'record deleted'=>'Datensatz gelöscht', |
'Please enter' =>'Bitte füllen sie dieses Feld aus:', |
'months' => Array( |
'01'=>'Januar', |
'02'=>'Februar', |
'03'=>'März', |
'04'=>'April', |
'05'=>'Mai', |
'06'=>'Juni', |
'07'=>'Juli', |
'08'=>'August', |
'09'=>'September', |
'10'=>'Oktober', |
'11'=>'November', |
'12'=>'Dezember'), |
// phpMyEdit-report |
'Make report' => 'Make report', |
'Select fields' => 'Select fields', |
'Records per screen' => 'Records per screen', |
); |
?> |
/trunk/jrest/util/lang/PME.lang.ZH-SG.inc |
---|
New file |
0,0 → 1,64 |
<?php |
/* |
* phpMyEdit language file |
* |
* language: chinese (Singapore) |
* encoding: utf-8 |
* date: 2003-07-03 |
* author: Juraj Benadik <gastan at gastan.sk> |
*/ |
/* $Platon: phpMyEdit/lang/PME.lang.ZH-SG.inc,v 1.4 2004-12-27 20:14:29 nepto Exp $ */ |
return Array( |
'Add' =>'添加', |
'Copy' =>'复制', |
'Change' =>'更改', |
'Delete' =>'删除', |
'View' =>'查看', |
'Prev' =>'上页', |
'Next' =>'下页', |
'First' =>'First', // untranslated |
'Last' =>'Last', // untranslated |
'Go to' =>'Go to', // untranslated |
'Page' =>'页', |
'Records' =>'记录', |
'Save' =>'保存', |
'More' =>'更多', |
'Apply' =>'应用', |
'Cancel' =>'取消', |
'Search' =>'搜寻', |
'Hide' =>'隐藏', |
'Clear' =>'清除', |
'Query' =>'查询', |
'Current Query' =>'当前 查询', |
'Sorted By' =>'排序方式', |
'ascending' =>'上升', |
'descending' =>'递减', |
'hidden' =>'隐藏的', |
'of' =>'总', |
'record added' =>'记录添加', |
'record changed' =>'记录更改', |
'record deleted' =>'记录删除', |
'Please enter' =>'请进入', |
'months' => Array( |
'01'=>'一月', |
'02'=>'二月', |
'03'=>'三月', |
'04'=>'四月', |
'05'=>'五月', |
'06'=>'六月', |
'07'=>'七月', |
'08'=>'八月', |
'09'=>'九月', |
'10'=>'十月', |
'11'=>'十一月', |
'12'=>'十二月'), |
// phpMyEdit-report |
'Make report' => 'Make report', |
'Select fields' => 'Select fields', |
'Records per screen' => 'Records per screen', |
); |
?> |
/trunk/jrest/util/lang/PME.lang.ES-MX.inc |
---|
New file |
0,0 → 1,64 |
<?php |
/* |
* phpMyEdit language file |
* |
* language: spanish (mexican) |
* encoding: iso-8859-1 |
* date: 2003-04-30 |
* author: unknown |
*/ |
/* $Platon: phpMyEdit/lang/PME.lang.ES-MX.inc,v 1.3 2004-12-27 20:14:29 nepto Exp $ */ |
return Array( |
'Add' =>'Agregar', |
'Copy' =>'Copiar', |
'Change' =>'Cambiar', |
'Delete' =>'Suprimir', |
'View' =>'Ver', |
'Prev' =>'Anterior', |
'Next' =>'Siguiente', |
'First' =>'First', // untranslated |
'Last' =>'Last', // untranslated |
'Go to' =>'Go to', // untranslated |
'Page' =>'Página', |
'Records' =>'Registros', |
'Save' =>'Guardar', |
'More' =>'Más', |
'Apply' =>'Aplicar', |
'Cancel' =>'Cancelar', |
'Search' =>'Buscar', |
'Hide' =>'Ocultar', |
'Clear' =>'Limpiar', |
'Query' =>'Consulta SQL', |
'Current Query' =>'Consulta actual', |
'Sorted By' =>'Ordenado por', |
'ascending' =>'ascendente', |
'descending' =>'descendente', |
'hidden' =>'oculto', |
'of' =>'de', |
'record added' =>'registro agregado', |
'record changed'=>'registro cambiado', |
'record deleted'=>'registro borrado', |
'Please enter' =>'Por favor introduzca ', |
'months' => Array( |
'01'=>'Enero', |
'02'=>'Febrero', |
'03'=>'Marzoa', |
'04'=>'Abril', |
'05'=>'Mayo', |
'06'=>'Junio', |
'07'=>'Julio', |
'08'=>'Agosto', |
'09'=>'Septiembre', |
'10'=>'Octubre', |
'11'=>'Noviembre', |
'12'=>'Diciembre'), |
// phpMyEdit-report |
'Make report' => 'Make report', |
'Select fields' => 'Select fields', |
'Records per screen' => 'Records per screen', |
); |
?> |
/trunk/jrest/util/lang/PME.lang.DK.inc |
---|
New file |
0,0 → 1,64 |
<?php |
/* |
* phpMyEdit language file |
* |
* language: danish |
* encoding: iso-8859-1 |
* date: 2003-03-19 |
* author: Henrik Nielsen <kontakt@innovapage.dk> |
*/ |
/* $Platon: phpMyEdit/lang/PME.lang.DK.inc,v 1.5 2004-12-27 20:14:29 nepto Exp $ */ |
return Array( |
'Add' =>'Tilføj', |
'Copy' =>'Kopier', |
'Change' =>'Ret', |
'Delete' =>'Slet', |
'View' =>'Se', |
'Prev' =>'Tilbage', |
'Next' =>'Næste', |
'First' =>'First', // untranslated |
'Last' =>'Last', // untranslated |
'Go to' =>'Go to', // untranslated |
'Page' =>'Side', |
'Records' =>'Rækker', |
'Save' =>'Gem', |
'More' =>'Mere', |
'Apply' =>'Tilføj', |
'Cancel' =>'Fortryd', |
'Search' =>'Søg', |
'Hide' =>'Skjul', |
'Clear' =>'Tøm', |
'Query' =>'Søg', |
'Current Query' =>'Current Query', // untranslated |
'Sorted By' =>'Sorted By', // untranslated |
'ascending' =>'ascending', // untranslated |
'descending' =>'descending', // untranslated |
'hidden' =>'hidden', // untranslated |
'of' =>'af', |
'record added' =>'række tilføjet', |
'record changed' =>'række ændret', |
'record deleted' =>'række slettet', |
'Please enter' =>'Indtast venligst', |
'months' => Array( |
'01'=>'Januar', |
'02'=>'Februar', |
'03'=>'Marts', |
'04'=>'April', |
'05'=>'Maj', |
'06'=>'Juni', |
'07'=>'Juli', |
'08'=>'August', |
'09'=>'September', |
'10'=>'Oktober', |
'11'=>'November', |
'12'=>'December'), |
// phpMyEdit-report |
'Make report' => 'Make report', |
'Select fields' => 'Select fields', |
'Records per screen' => 'Records per screen', |
); |
?> |
/trunk/jrest/util/lang/PME.lang.EL.inc |
---|
New file |
0,0 → 1,64 |
<?php |
/* |
* phpMyEdit language file |
* |
* language: greek |
* encoding: iso-8859-7 |
* date: 2005-08-03 |
* author: Alexandros Vellis <avel@users.sourceforge.net> |
*/ |
/* $Id$ */ |
return Array( |
'Add' =>'Ðñüóèåóç', |
'Copy' =>'ÁíôéãñáöÞ', |
'Change' =>'ÁëëáãÞ', |
'Delete' =>'ÄéáãñáöÞ', |
'View' =>'ÅìöÜíéóç', |
'Prev' =>'Ðñïçãïýìåíï', |
'Next' =>'Åðüìåíï', |
'First' =>'Ðñþôï', |
'Last' =>'Ôåëåõôáßï', |
'Go to' =>'ÐÞãáéíå óå', |
'Page' =>'Óåëßäá', |
'Records' =>'ÅããñáöÝò', |
'Save' =>'ÁðïèÞêåõóç', |
'More' =>'Ðåñéóóüôåñá', |
'Apply' =>'ÕðïâïëÞ', |
'Cancel' =>'Áêýñùóç', |
'Search' =>'ÁíáæÞôçóç', |
'Hide' =>'Êñýøå', |
'Clear' =>'ÊáèÜñéóå', |
'Query' =>'Åðåñþôçìá', |
'Current Query' =>'ÔñÝ÷ïí Åðåñþôçìá', |
'Sorted By' =>'Ôáîéíüìçóç Ìå', |
'ascending' =>'áýîïõóá', |
'descending' =>'öèßíïõóá', |
'hidden' =>'êñõììÝíï', |
'of' =>'áðü', |
'record added' =>'ç åããñáöÞ ðñïóôÝèçêå', |
'record changed' =>'ç åããñáöÞ Üëëáîå', |
'record deleted' =>'ç åããñáöÞ äéáãñÜöçêå', |
'Please enter' =>'Ðáñáêáëþ åéóÜãåôå', |
'months' => Array( |
'01'=>'ÉáíïõÜñéïò', |
'02'=>'ÖåâñïõÜñéïò', |
'03'=>'ÌÜñôéïò', |
'04'=>'Áðñßëéïò', |
'05'=>'ÌÜéïò', |
'06'=>'Éïýíéïò', |
'07'=>'Éïýëéïò', |
'08'=>'Áýãïõóôïò', |
'09'=>'ÓåðôÝìâñéïò', |
'10'=>'Ïêôþâñéïò', |
'11'=>'ÍïÝìâñéïò', |
'12'=>'ÄåêÝìâñéïò'), |
// phpMyEdit-report |
'Make report' => 'Äçìéïõñãßá áíáöïñÜò', |
'Select fields' => 'ÅðéëïãÞ ðåäßùí', |
'Records per screen' => 'ÅããñáöÝò áíÜ ïèüíç', |
); |
?> |
/trunk/jrest/util/lang/PME.lang.EN.inc |
---|
New file |
0,0 → 1,64 |
<?php |
/* |
* phpMyEdit language file |
* |
* language: english |
* encoding: iso-8859-1 |
* date: 2000, 2001, 2003-05-01 |
* author: John McCreesh <jpmcc@users.sourceforge.net> |
*/ |
/* $Platon: phpMyEdit/lang/PME.lang.EN.inc,v 1.11 2004-12-27 20:14:29 nepto Exp $ */ |
return Array( |
'Add' =>'Add', |
'Copy' =>'Copy', |
'Change' =>'Change', |
'Delete' =>'Delete', |
'View' =>'View', |
'Prev' =>'Prev', |
'Next' =>'Next', |
'First' =>'First', |
'Last' =>'Last', |
'Go to' =>'Go to', |
'Page' =>'Page', |
'Records' =>'Records', |
'Save' =>'Save', |
'More' =>'More', |
'Apply' =>'Apply', |
'Cancel' =>'Cancel', |
'Search' =>'Search', |
'Hide' =>'Hide', |
'Clear' =>'Clear', |
'Query' =>'Query', |
'Current Query' =>'Current Query', |
'Sorted By' =>'Sorted By', |
'ascending' =>'ascending', |
'descending' =>'descending', |
'hidden' =>'hidden', |
'of' =>'of', |
'record added' =>'record added', |
'record changed' =>'record changed', |
'record deleted' =>'record deleted', |
'Please enter' =>'Please enter', |
'months' => Array( |
'01'=>'January', |
'02'=>'February', |
'03'=>'March', |
'04'=>'April', |
'05'=>'May', |
'06'=>'June', |
'07'=>'July', |
'08'=>'August', |
'09'=>'September', |
'10'=>'October', |
'11'=>'November', |
'12'=>'December'), |
// phpMyEdit-report |
'Make report' => 'Make report', |
'Select fields' => 'Select fields', |
'Records per screen' => 'Records per screen', |
); |
?> |
/trunk/jrest/util/lang/PME.lang.SE.inc |
---|
New file |
0,0 → 1,73 |
<?php |
/* |
* phpMyEdit language file |
* |
* language: swedish |
* encoding: iso-8859-1 |
* date: 2004-01-21, 2004-02-07 |
* authors: |
* Björn Hammarbäck <bjorn@hammarback.se> |
* Stefan Lindmark <stefan@lindmark.net> |
*/ |
/* $Platon: phpMyEdit/lang/PME.lang.SE.inc,v 1.4 2004-12-27 20:14:29 nepto Exp $ */ |
/* |
* å = å |
* ä = ä |
* ö = ö |
* Ä = Ä |
*/ |
return Array( |
'Add' =>'Lägg till', |
'Copy' =>'Kopiera', |
'Change' =>'Ändra', |
'Delete' =>'Ta bort', |
'View' =>'Visa detaljer', |
'Prev' =>'Föregående', |
'Next' =>'Nästa', |
'First' =>'Första', |
'Last' =>'Sista', |
'Go to' =>'Gå till sida', |
'Page' =>'Sida', |
'Records' =>'Poster', |
'Save' =>'Spara', |
'More' =>'Mer', |
'Apply' =>'Verkställ', |
'Cancel' =>'Avbryt', |
'Search' =>'Sök', |
'Hide' =>'Dölj', |
'Clear' =>'Rensa', |
'Query' =>'Sök', |
'Current Query' =>'Nuvarande fråga', |
'Sorted By' =>'Sorterad efter', |
'ascending' =>'stigande', |
'descending' =>'fallande', |
'hidden' =>'gömd', |
'of' =>'av', |
'record added' =>'post adderad', |
'record changed' =>'post ändrad', |
'record deleted' =>'post borttagen', |
'Please enter' =>'Fyll i fältet', |
'months' => Array( |
'01'=>'Januari', |
'02'=>'Februari', |
'03'=>'Mars', |
'04'=>'April', |
'05'=>'Maj', |
'06'=>'Juni', |
'07'=>'Juli', |
'08'=>'Augusti', |
'09'=>'September', |
'10'=>'Oktober', |
'11'=>'November', |
'12'=>'December'), |
// phpMyEdit-report |
'Make report' => 'Skapa rapport', |
'Select fields' => 'Välj fält', |
'Records per screen' => 'Poster per skärm', |
); |
?> |
/trunk/jrest/util/lang/PME.lang.ES-AR.inc |
---|
New file |
0,0 → 1,59 |
<?php |
/* |
* phpMyEdit language file |
* |
* language: spanish (argentinian) |
* encoding: iso-8859-1 |
* date: 2003-02-28, 2004-02-15 |
* author: Mariano Vassallo <mvassallo@ciudad.com.ar> |
*/ |
/* $Platon: phpMyEdit/lang/PME.lang.ES-AR.inc,v 1.5 2004-12-27 20:14:29 nepto Exp $ */ |
return Array( |
'Add' =>'Agregar', |
'Copy' =>'Copiar', |
'Change' =>'Cambiar', |
'Delete' =>'Suprimir', |
'View' =>'Visualización', |
'Prev' =>'Anterior', |
'Next' =>'Siguiente', |
'First' =>'Primero', |
'Last' =>'Ultimo', |
'Go to' =>'Ir a', |
'Page' =>'Paginación', |
'Records' =>'Registros', |
'Save' =>'Grabar', |
'More' =>'Más', |
'Apply' =>'Aplicar', |
'Cancel' =>'Cancelar', |
'Search' =>'Buscar', |
'Hide' =>'Ocultar', |
'Clear' =>'Limpiar', |
'Query' =>'Consulta', |
'of' =>'/', // intentionaly untranslated. Alternatve: "de" |
'record added' =>'registro añadido', |
'record changed'=>'registro cambiado', |
'record deleted'=>'registro borrado', |
'Please enter' =>'Por favor introduzca ', |
'months' => Array( |
'01'=>'Enero', |
'02'=>'Febrero', |
'03'=>'Marzo', |
'04'=>'Abril', |
'05'=>'Mayo', |
'06'=>'Junio', |
'07'=>'Julio', |
'08'=>'Agosto', |
'09'=>'Septiembre', |
'10'=>'Octubre', |
'11'=>'Noviembre', |
'12'=>'Diciembre'), |
// phpMyEdit-report |
'Make report' => 'Hacer reporte', |
'Select fields' => 'Seleccionar campos', |
'Records per screen' => 'Registros por pantalla', |
); |
?> |
/trunk/jrest/util/lang/PME.lang.ES.inc |
---|
New file |
0,0 → 1,66 |
<?php |
/* |
* phpMyEdit language file |
* |
* language: spanish |
* encoding: iso-8859-1 |
* date: 2003-02, 2003-04-22, 2004-04-04 |
* authors: |
* Jorge Nadal <jornamon@ya.com> |
* Eduardo Diaz <ediaz@pk25.com> |
*/ |
/* $Platon: phpMyEdit/lang/PME.lang.ES.inc,v 1.6 2004-12-27 20:14:29 nepto Exp $ */ |
return Array( |
'Add' =>'Agregar', |
'Copy' =>'Copiar', |
'Change' =>'Cambiar', |
'Delete' =>'Suprimir', |
'View' =>'Visualizar', |
'Prev' =>'Anterior', |
'Next' =>'Siguiente', |
'First' =>'Primero', |
'Last' =>'Último', |
'Go to' =>'Ir a', |
'Page' =>'Página', |
'Records' =>'Registros', |
'Save' =>'Grabar', |
'More' =>'Más', |
'Apply' =>'Aplicar', |
'Cancel' =>'Cancelar', |
'Search' =>'Buscar', |
'Hide' =>'Ocultar', |
'Clear' =>'Limpiar', |
'Query' =>'Consultar', |
'Current Query' =>'Consulta actual', |
'Sorted By' =>'Ordenado por', |
'ascending' =>'ascendente', |
'descending' =>'descendente', |
'hidden' =>'oculto', |
'of' =>'de', |
'record added' =>'Registro añadido', |
'record changed'=>'Registro cambiado', |
'record deleted'=>'Registro borrado', |
'Please enter' =>'Por favor introduzca ', |
'months' => Array( |
'01'=>'Enero', |
'02'=>'Febrero', |
'03'=>'Marzo', |
'04'=>'Abril', |
'05'=>'Mayo', |
'06'=>'Junio', |
'07'=>'Julio', |
'08'=>'Agosto', |
'09'=>'Septiembre', |
'10'=>'Octubre', |
'11'=>'Noviembre', |
'12'=>'Diciembre'), |
// phpMyEdit-report |
'Make report' => 'Realizar Informe', |
'Select fields' => 'Seleccionar campos', |
'Records per screen' => 'Registros por pantalla', |
); |
?> |
/trunk/jrest/util/lang/PME.lang.FR.inc |
---|
New file |
0,0 → 1,67 |
<?php |
/* |
* phpMyEdit language file |
* |
* language: french (standard) |
* encoding: iso-8859-1 |
* date: 2002-02, 2002-11-07, 2002-12-29 |
* authors: |
* Dario <dartar@users.sourceforge.net> |
* Kaid <kaid@fr.st> |
* hbernard <hbernard@gynov.org> |
*/ |
/* $Platon: phpMyEdit/lang/PME.lang.FR.inc,v 1.15 2004-12-27 20:14:29 nepto Exp $ */ |
return Array( |
'Add' =>'Ajouter', |
'Copy' =>'Copier', |
'Change' =>'Modifier', |
'Delete' =>'Supprimer', |
'View' =>'Afficher', |
'Prev' =>'Précédent', |
'Next' =>'Suivant', |
'First' =>'Début', |
'Last' =>'Fin', |
'Go to' =>'Aller à ', |
'Page' =>'Page', |
'Records' =>'Enregistrements', |
'Save' =>'Enregistrer', |
'More' =>'Enregistrer et continuer', |
'Apply' =>'Appliquer', |
'Cancel' =>'Annuler', |
'Search' =>'Rechercher', |
'Hide' =>'Cacher', |
'Clear' =>'Vider', |
'Query' =>'Requête', |
'Current Query' =>'Requête courante', |
'Sorted By' =>'Tri', |
'ascending' =>'croissant', |
'descending' =>'décroissant', |
'hidden' =>'caché', |
'of' =>'/', // untranslated |
'record added' =>'Enregistrement ajouté', |
'record changed'=>'Enregistrement modifié', |
'record deleted'=>'Enregistrement supprimé', |
'Please enter' =>'Entrez s\'il vous plaît', |
'months' => Array( |
'01'=>'Janvier', |
'02'=>'Février', |
'03'=>'Mars', |
'04'=>'Avril', |
'05'=>'Mai', |
'06'=>'Juin', |
'07'=>'Juillet', |
'08'=>'Août', |
'09'=>'Septembre', |
'10'=>'Octobre', |
'11'=>'Novembre', |
'12'=>'Décembre'), |
// phpMyEdit-report |
'Make report' => 'Make report', |
'Select fields' => 'Select fields', |
'Records per screen' => 'Records per screen', |
); |
?> |
/trunk/jrest/util/lang/PME.lang.ET.inc |
---|
New file |
0,0 → 1,64 |
<?php |
/* |
* phpMyEdit language file |
* |
* language: estonian |
* encoding: any latin |
* date: 2005-09-13 |
* author: Alexia Death <alexiadeath@hotmail.com> |
*/ |
/* $Platon: phpMyEdit/lang/PME.lang.ET.inc,v 1.1 2005-09-14 13:40:19 nepto Exp $ */ |
return Array( |
'Add' =>'Lisa', |
'Copy' =>'Kopeeri', |
'Change' =>'Muuda', |
'Delete' =>'Kustuta', |
'View' =>'Vaata', |
'Prev' =>'Eelmine', |
'Next' =>htmlentities('Järgmine'), |
'First' =>'Esimene', |
'Last' =>'Viimane', |
'Go to' =>'Positsioon', |
'Page' =>'Leht', |
'Records' =>'Kirjed', |
'Save' =>'Salvesta', |
'More' =>htmlentities('Järgneb...'), |
'Apply' =>'Rakenda muutused', |
'Cancel' =>htmlentities('Tühista'), |
'Search' =>'Otsi', |
'Hide' =>'Peida', |
'Clear' =>htmlentities('Tühjenda väljad'), |
'Query' =>htmlentities('Päring'), |
'Current Query' =>htmlentities('Hetke päring'), |
'Sorted By' =>htmlentities('Sorteermisjärjekord'), |
'ascending' =>'kahanevalt', |
'descending' =>'kasvavalt', |
'hidden' =>'peidetud', |
'of' =>'/', |
'record added' =>'kirje lisatud', |
'record changed' =>'kirje muudetud', |
'record deleted' =>'kirje kustutatud', |
'Please enter' =>'Palun sisesta', |
'months' => Array( |
'01'=>'Jaanuar', |
'02'=>'Veebruar', |
'03'=>htmlentities('Märts'), |
'04'=>'Aprill', |
'05'=>'Mai', |
'06'=>'Juuni', |
'07'=>'Juuli', |
'08'=>'August', |
'09'=>'September', |
'10'=>'Oktoober', |
'11'=>'November', |
'12'=>'Detsember'), |
// phpMyEdit-report |
'Make report' => 'Koosta raport', |
'Select fields' => htmlentities('Vali väljad'), |
'Records per screen' => 'Kirjeid lehe kohta', |
); |
?> |
/trunk/jrest/util/lang/PME.lang.EU.inc |
---|
New file |
0,0 → 1,64 |
<?php |
/* |
* phpMyEdit language file |
* |
* language: basque |
* encoding: iso-8859-1 |
* date: 2004-05-11 |
* author: Ibon Igartua <ibon@zuhar.net> |
*/ |
/* $Platon: phpMyEdit/lang/PME.lang.EU.inc,v 1.1 2004-05-17 10:53:06 nepto Exp $ */ |
return Array( |
'Add' =>'Gehitu', |
'Copy' =>'Kopiatu', |
'Change' =>'Aldatu', |
'Delete' =>'Ezabatu', |
'View' =>'Ikusi', |
'Prev' =>'Aurrekoa', |
'Next' =>'Hurrengoa', |
'First' =>'Lehena', |
'Last' =>'Azkena', |
'Go to' =>'Joan', |
'Page' =>'Orrialdea', |
'Records' =>'Erregistroak', |
'Save' =>'Gorde', |
'More' =>'Gehiago', |
'Apply' =>'Aplikatu', |
'Cancel' =>'Utzi', |
'Search' =>'Bilatu', |
'Hide' =>'Ezkutatu', |
'Clear' =>'Garbitu', |
'Query' =>'Kontsulta', |
'Current Query' =>'Uneko Kontsulta', |
'Sorted By' =>'Orden Irizpidea', |
'ascending' =>'gorantz', |
'descending' =>'beherantz', |
'hidden' =>'ezkutukoa', |
'of' =>'-', |
'record added' =>'erregistroa gehituta', |
'record changed'=>'erregistroa aldatuta', |
'record deleted'=>'erregistroa ezabatuta', |
'Please enter' =>'Mesedez, sartu ezazu ', |
'months' => Array( |
'01'=>'urtarrila', |
'02'=>'otsaila', |
'03'=>'martxoa', |
'04'=>'apirila', |
'05'=>'maiatza', |
'06'=>'ekaina', |
'07'=>'uztaila', |
'08'=>'abuztua', |
'09'=>'iraila', |
'10'=>'urria', |
'11'=>'azaroa', |
'12'=>'abendua'), |
// phpMyEdit-report |
'Make report' => 'Txostena sortu', |
'Select fields' => 'Eremuak aukertau', |
'Records per screen' => 'Erregistroak orrialdeko', |
); |
?> |
/trunk/jrest/util/lang/PME.lang.NL.inc |
---|
New file |
0,0 → 1,68 |
<?php |
/* |
* phpMyEdit language file |
* |
* language: dutch (standard) |
* encoding: iso-8859-1 |
* date: 2002-09-21, 2002-12-17, 2006-01-05 |
* authors: |
* Paul Barends <pbarends@xs4all.nl> |
* Erwin Janszen <Erwin.Janszen@mail.ing.nl> |
* URL: |
* http://platon.sk/projects/bug_view_advanced_page.php?f_bug_id=197 |
*/ |
/* $Platon: phpMyEdit/lang/PME.lang.NL.inc,v 1.16 2006-01-05 04:45:22 nepto Exp $ */ |
return Array( |
'Add' =>'Toevoegen', |
'Copy' =>'Kopiëren', |
'Change' =>'Bewerken', |
'Delete' =>'Wissen', |
'View' =>'Details', |
'Prev' =>'Vorige', |
'Next' =>'Volgende', |
'First' =>'Eerste', |
'Last' =>'Laatste', |
'Go to' =>'Ga naar', |
'Page' =>'Pagina', |
'Records' =>'Rijen', |
'Save' =>'Bewaren', |
'More' =>'Meer', |
'Apply' =>'Toepassen', |
'Cancel' =>'Annuleren', |
'Search' =>'Zoeken', |
'Hide' =>'Verbergen', |
'Clear' =>'Schonen', // 'Leeg maken', |
'Query' =>'Selecteer', // 'Selectie maken', |
'Current Query' =>'Huidige selectie', |
'Sorted By' =>'Gesorteerd op', |
'ascending' =>'oplopend', |
'descending' =>'aflopend', |
'hidden' =>'verborgen', |
'of' =>'van', |
'record added' =>'rij toegevoegd', |
'record changed' =>'rij aangepast', |
'record deleted' =>'rij gewist', |
'Please enter' =>'Voer a.u.b. in:', |
'months' => Array( |
'01'=>'januari', |
'02'=>'februari', |
'03'=>'maart', |
'04'=>'april', |
'05'=>'mei', |
'06'=>'juni', |
'07'=>'juli', |
'08'=>'augustus', |
'09'=>'september', |
'10'=>'october', |
'11'=>'november', |
'12'=>'december'), |
// phpMyEdit-report |
'Make report' => 'Maak rapport', |
'Select fields' => 'Selecteer velden', |
'Records per screen' => 'Rij per scherm', |
); |
?> |
/trunk/jrest/util/lang/PME.lang.PL.inc |
---|
New file |
0,0 → 1,60 |
<?php |
/* |
* phpMyEdit language file |
* |
* language: polish |
* encoding: iso-8859-2 |
* date: 2002-10-01, 2003-06-30 |
* author: Piotr Walesiuk <p.walesiuk@bos.com.pl> |
*/ |
/* $Platon: phpMyEdit/lang/PME.lang.PL.inc,v 1.9 2004-12-27 20:14:29 nepto Exp $ */ |
return Array( |
'Add' =>'Dodaj', |
'Copy' =>'Kopiuj', |
'Change' =>'Zmieñ', |
'Delete' =>'Usuñ', |
'View' =>'Poka¿', |
'Prev' =>'Wstecz', |
'Next' =>'Dalej', |
'First' =>'First', // untranslated |
'Last' =>'Last', // untranslated |
'Go to' =>'Go to', // untranslated |
'Page' =>'Strona', |
'Records' =>'Rekordy', |
'Save' =>'Zapisz', |
'More' =>'Wiêcej', |
'Apply' =>'Zastosuj', |
'Cancel' =>'Anuluj', |
'Search' =>'Szukaj', |
'Hide' =>'Ukryj', |
'Clear' =>'Wyczy¶æ', |
'Query' =>'Zapytanie', |
'Current Query' =>'Aktualne zapytanie', |
'Sorted By' =>'Posortowane wed³ug', |
'ascending' =>'rosn±co', |
'descending' =>'malej±co', |
'hidden' =>'ukryte', |
'of' =>'z', |
'record added' =>'rekord dodany', |
'record changed'=>'rekord zmieniony', |
'record deleted'=>'rekord usuniêty', |
'Please enter' =>'Proszê wprowadziæ', |
'months' => Array( |
'01'=>'Styczeñ', |
'02'=>'Luty', |
'03'=>'Marzec', |
'04'=>'Kwiecieñ', |
'05'=>'Maj', |
'06'=>'Czerwiec', |
'07'=>'Lipiec', |
'08'=>'Sierpieñ', |
'09'=>'Wrzesieñ', |
'10'=>'Pa¼dziernik', |
'11'=>'Listopad', |
'12'=>'Grudzieñ') |
); |
?> |
/trunk/jrest/util/lang/PME.lang.CZ.inc |
---|
New file |
0,0 → 1,64 |
<?php |
/* |
* phpMyEdit language file |
* |
* language: czech |
* encoding: iso-8859-2 |
* date: 2005-04-26 |
* author: Jan Cinert <ion_lord@seznam.cz> |
*/ |
/* $Platon: phpMyEdit/lang/PME.lang.CZ.inc,v 1.1 2005-04-26 13:15:38 nepto Exp $ */ |
return Array( |
'Add' =>'Pøidat', |
'Copy' =>'Kopírovat', |
'Change' =>'Zmìnit', |
'Delete' =>'Smazat', |
'View' =>'Zobrazit', |
'Prev' =>'Pøedcházející', |
'Next' =>'Následující', |
'First' =>'První', |
'Last' =>'Poslední', |
'Go to' =>'Otevøít', |
'Page' =>'Stránka', |
'Records' =>'Záznamù', |
'Save' =>'Ulo¾it', |
'More' =>'Více', |
'Apply' =>'Pou¾ít', |
'Cancel' =>'Zru¹it', |
'Search' =>'Hledat', |
'Hide' =>'Skrýt', |
'Clear' =>'Smazat', |
'Query' =>'Dotaz', |
'Current Query' =>'Stávající dotaz', |
'Sorted By' =>'Uspoøádané podle', |
'ascending' =>'vzestupnì', |
'descending' =>'sestupnì', |
'hidden' =>'skrytý', |
'of' =>'z', |
'record added' =>'pøidaný záznam', |
'record changed'=>'zmìnìný záznam', |
'record deleted'=>'smazaný záznam', |
'Please enter' =>'Zadejte prosím', |
'months' => Array( |
'01'=>'Leden', |
'02'=>'Únor', |
'03'=>'Bøezen', |
'04'=>'Duben', |
'05'=>'Kvìten', |
'06'=>'Èerve', |
'07'=>'Èervenec', |
'08'=>'Srpen', |
'09'=>'Záøí', |
'10'=>'Øíjen', |
'11'=>'Listopad', |
'12'=>'Prosinec'), |
// phpMyEdit-report |
'Make report' => 'Vytvoøit zprávu', |
'Select fields' => 'Vybrat pole', |
'Records per screen' => 'Poèet záznamù na stránce', |
); |
?> |
/trunk/jrest/util/lang/PME.lang.IT.inc |
---|
New file |
0,0 → 1,66 |
<?php |
/* |
* phpMyEdit language file |
* |
* language: italian (standard) |
* encoding: iso-8859-1 |
* date: 2002-02, 2002-11-07, 2003-04-13, 2004-03-31 |
* authors: |
* Dario <dartar@users.sourceforge.net> |
* Keatch <raffaele.spangaro@eurika.net> |
*/ |
/* $Platon: phpMyEdit/lang/PME.lang.IT.inc,v 1.15 2004-12-27 20:14:29 nepto Exp $ */ |
return Array( |
'Add' =>'Aggiungi', |
'Copy' =>'Copia', |
'Change' =>'Modifica', |
'Delete' =>'Cancella', |
'View' =>'Visualizza', |
'Prev' =>'Precedente', |
'Next' =>'Seguente', |
'First' =>'Prima', |
'Last' =>'Ultima', |
'Go to' =>'Vai a', |
'Page' =>'Pagina', |
'Records' =>'Voci', |
'Save' =>'Salva', |
'More' =>'Salva & Continua', |
'Apply' =>'Applica', |
'Cancel' =>'Annulla', |
'Search' =>'Cerca', |
'Hide' =>'Nascondi', |
'Clear' =>'Svuota', |
'Query' =>'Chiedi', |
'Current Query' =>'Richiesta Corrente', |
'Sorted By' =>'Ordinato per', |
'ascending' =>'crescente', |
'descending' =>'decrescente', |
'hidden' =>'nascosto', |
'of' =>'/', |
'record added' =>'voce aggiunta', |
'record changed'=>'voce modificata', |
'record deleted'=>'voce eliminata', |
'Please enter' =>'Si prega di riempire il campo: ', |
'months' => Array( |
'01'=>'Gennaio', |
'02'=>'Febbraio', |
'03'=>'Marzo', |
'04'=>'Aprile', |
'05'=>'Maggio', |
'06'=>'Giugno', |
'07'=>'Luglio', |
'08'=>'Agosto', |
'09'=>'Settembre', |
'10'=>'Ottobre', |
'11'=>'Novembre', |
'12'=>'Dicembre'), |
// phpMyEdit-report |
'Make report' => 'Genera report', |
'Select fields' => 'Seleziona campi', |
'Records per screen' => 'Record per schermata', |
); |
?> |
/trunk/jrest/util/lang/PME.lang.SK.inc |
---|
New file |
0,0 → 1,64 |
<?php |
/* |
* phpMyEdit language file |
* |
* language: slovak |
* encoding: iso-8859-2 |
* date: 2002-02-02, 2003-05-01 |
* author: Ondrej Jombik <nepto@php.net> |
*/ |
/* $Platon: phpMyEdit/lang/PME.lang.SK.inc,v 1.12 2004-12-27 20:14:29 nepto Exp $ */ |
return Array( |
'Add' =>'Prida»', |
'Copy' =>'Kopírova»', |
'Change' =>'Zmeni»', |
'Delete' =>'Zmaza»', |
'View' =>'Pozrie»', |
'Prev' =>'Predchádzajúci', |
'Next' =>'Ïal¹í', |
'First' =>'Prvý', |
'Last' =>'Posledný', |
'Go to' =>'Choï na', |
'Page' =>'Stránka', |
'Records' =>'Záznamov', |
'Save' =>'Ulo¾i»', |
'More' =>'Viac', |
'Apply' =>'Pou¾i»', |
'Cancel' =>'Storno', |
'Search' =>'Hµada»', |
'Hide' =>'Skry»', |
'Clear' =>'Zru¹i»', |
'Query' =>'Vyhµada»', |
'Current Query' =>'Aktuálny dotaz', |
'Sorted By' =>'Usporiadané podµa', |
'ascending' =>'vzostupne', |
'descending' =>'zostupne', |
'hidden' =>'skryté', |
'of' =>'z', |
'record added' =>'záznam pridaný', |
'record changed'=>'záznam zmenený', |
'record deleted'=>'záznam zmazaný', |
'Please enter' =>'Prosím zadajte', |
'months' => Array( |
'01'=>'Január', |
'02'=>'Február', |
'03'=>'Marec', |
'04'=>'Apríl', |
'05'=>'Máj', |
'06'=>'Jún', |
'07'=>'Júl', |
'08'=>'August', |
'09'=>'September', |
'10'=>'Október', |
'11'=>'November', |
'12'=>'December'), |
// phpMyEdit-report |
'Make report' => 'Vytvori» report', |
'Select fields' => 'Vybra» ståpce', |
'Records per screen' => 'Poèet záznamov na stránke', |
); |
?> |
/trunk/jrest/util/lang/PME.lang.RO.inc |
---|
New file |
0,0 → 1,64 |
<?php |
/* |
* phpMyEdit language file |
* |
* language: romanian |
* encoding: iso-8859-1 |
* date: 2004-12-23 |
* author: Sebastian Proksch <sproksch@yahoo.com> |
*/ |
/* $Platon: phpMyEdit/lang/PME.lang.RO.inc,v 1.2 2004-12-27 20:14:29 nepto Exp $ */ |
return Array( |
'Add' =>'Adauga', |
'Copy' =>'Copiaza', |
'Change' =>'Modifica', |
'Delete' =>'Sterge', |
'View' =>'Vizualizeaza', |
'Prev' =>'Precedentul', |
'Next' =>'Urmatorul', |
'First' =>'First', // untranslated |
'Last' =>'Last', // untranslated |
'Go to' =>'Go to', // untranslated |
'Page' =>'Pagina', |
'Records' =>'Inregistrari', |
'Save' =>'Salveaza', |
'More' =>'Mai mult', |
'Apply' =>'Aplica', |
'Cancel' =>'Anuleaza', |
'Search' =>'Cauta', |
'Hide' =>'Ascunde', |
'Clear' =>'Anuleaza tot', |
'Query' =>'Interogare', |
'Current Query' =>'Interogarea curenta', |
'Sorted By' =>'Sortat dupa', |
'ascending' =>'crescator', |
'descending' =>'descrescator', |
'hidden' =>'ascuns', |
'of' =>'din', |
'record added' =>'inregistrare adaugata', |
'record changed'=>'inregistrare modificata', |
'record deleted'=>'inregistrare stearsa', |
'Please enter' =>'Introduceti va rog', |
'months' => Array( |
'01'=>'Ianuarie', |
'02'=>'Februarie', |
'03'=>'Martie', |
'04'=>'Aprilie', |
'05'=>'Mai', |
'06'=>'Iunie', |
'07'=>'Iulie', |
'08'=>'August', |
'09'=>'Septembrie', |
'10'=>'Octombrie', |
'11'=>'Noiembrie', |
'12'=>'Decembrie'), |
// phpMyEdit-report // untranslated |
'Make report' => 'Make report', |
'Select fields' => 'Select fields', |
'Records per screen' => 'Records per screen', |
); |
?> |
/trunk/jrest/util/lang/PME.lang.ZH.inc |
---|
New file |
0,0 → 1,66 |
<?php |
/* |
* phpMyEdit language file |
* |
* language: chinese (traditional) |
* encoding: big5 |
* date: 2003-06-26, 2004-10-17 |
* authors: |
* Pao-Hsi Huang <doggy@miniasp.com> |
* Manix Sio <manixsio@gmail.com> |
*/ |
/* $Platon: phpMyEdit/lang/PME.lang.ZH.inc,v 1.5 2004-12-27 20:14:29 nepto Exp $ */ |
return Array( |
'Add' =>'·s¼W', |
'Copy' =>'½Æ»s', |
'Change' =>'Åܧó', |
'Delete' =>'§R°£', |
'View' =>'À˵ø', |
'Prev' =>'¤W¤@¶', |
'Next' =>'¤U¤@¶', |
'First' =>'²Ä¤@¶', |
'Last' =>'³Ì¥½¤@¶', |
'Go to' =>'«e©¹', |
'Page' =>'¶¼Æ', |
'Records' =>'¸ê®Æµ§¼Æ', |
'Save' =>'Àx¦s', |
'More' =>'Àx¦s«áÄ~Äò·s¼W', |
'Apply' =>'®M¥Î', |
'Cancel' =>'¨ú®ø', |
'Search' =>'·j´M', |
'Hide' =>'ÁôÂÃ', |
'Clear' =>'²M°£', |
'Query' =>'¬d¸ß', |
'Current Query' =>'¥Ø«e¬d¸ß±ø¥ó', |
'Sorted By' =>'±Æ§Ç¨Ì¾Ú', |
'ascending' =>'¤É¾±Æ§Ç', |
'descending' =>'°¾±Æ§Ç', |
'hidden' =>'ÁôÂÃ', |
'of' =>'Á`¦@¶¼Æ', |
'record added' =>'µ§¸ê®Æ³Q·s¼W', |
'record changed' =>'µ§¸ê®Æ³Q§ó·s', |
'record deleted' =>'µ§¸ê®Æ³Q§R°£', |
'Please enter' =>'½Ð¿é¤J', |
'months' => Array( |
'01'=>'¤@¤ë', |
'02'=>'¤G¤ë', |
'03'=>'¤T¤ë', |
'04'=>'¥|¤ë', |
'05'=>'¤¤ë', |
'06'=>'¤»¤ë', |
'07'=>'¤C¤ë', |
'08'=>'¤K¤ë', |
'09'=>'¤E¤ë', |
'10'=>'¤Q¤ë', |
'11'=>'¤Q¤@¤ë', |
'12'=>'¤Q¤G¤ë'), |
// phpMyEdit-report |
'Make report' => '²£¥Í³øªí', |
'Select fields' => '¿ï¨úÄæ¦ì', |
'Records per screen' => '¨C¶µ§¼Æ', |
); |
?> |
/trunk/jrest/util/lang/PME.lang.PT.inc |
---|
New file |
0,0 → 1,67 |
<?php |
/* |
* phpMyEdit language file |
* |
* language: portuguese (standard) |
* encoding: iso-8859-1 |
* date: 2002-02 |
* author: unknown |
* |
* last_edit: 2006-05-23 by Sérgio Sanches <ssanches@dcc.online.pt> |
* last_edit_purpose: full translation and correction |
*/ |
/* $Platon: phpMyEdit/lang/PME.lang.PT.inc,v 1.6 2006-05-29 08:18:04 nepto Exp $ */ |
return Array( |
'Add' =>'Adicionar', |
'Copy' =>'Copiar', |
'Change' =>'Mudar', |
'Delete' =>'Apagar', |
'View' =>'Ver', |
'Prev' =>'Anterior', |
'Next' =>'Seguinte', |
'First' =>'Primeiro', |
'Last' =>'Último', |
'Go to' =>'Ir para', |
'Page' =>'Página', |
'Records' =>'Registos', |
'Save' =>'Guardar', |
'More' =>'Mais', |
'Apply' =>'Aplicar', |
'Cancel' =>'Cancelar', |
'Search' =>'Procurar', |
'Hide' =>'Esconder', |
'Clear' =>'Limpar', |
'Query' =>'Pesquisa', |
'Current Query' =>'Pesquisa Actual', |
'Sorted By' =>'Ordenado Por', |
'ascending' =>'ascendente', |
'descending' =>'descendente', |
'hidden' =>'escondido', |
'of' =>'de', |
'record added' =>'registo adicionado', |
'record changed' =>'registo alterado', |
'record deleted' =>'registo apagado', |
'Please enter' =>'Por favor introduza ', |
'months' => Array( |
'01'=>'Janeiro', |
'02'=>'Fevereiro', |
'03'=>'Março', |
'04'=>'Abril', |
'05'=>'Maio', |
'06'=>'Junho', |
'07'=>'Julho', |
'08'=>'Agosto', |
'09'=>'Setembro', |
'10'=>'Outubro', |
'11'=>'Novembro', |
'12'=>'Dezembro'), |
// phpMyEdit-report |
'Make report' => 'Criar relatório', |
'Select fields' => 'Escolher campos', |
'Records per screen' => 'Registos por ecran', |
); |
?> |
/trunk/jrest/util/lang/PME.lang.CA.inc |
---|
New file |
0,0 → 1,64 |
<?php |
/* |
* phpMyEdit language file |
* |
* language: català |
* encoding: iso-8859-1 |
* date: 2006-04-06 |
* author: Josep Maria Faura <j.m.faura@telefonica.net> |
*/ |
/* $Platon: phpMyEdit/lang/PME.lang.CA.inc,v 1.2 2006-04-11 10:30:46 nepto Exp $ */ |
return Array( |
'Add' =>'Afegir', |
'Copy' =>'Copiar', |
'Change' =>'Modificar', |
'Delete' =>'Suprimir', |
'View' =>'Visualitzar', |
'Prev' =>'Anterior', |
'Next' =>'Següent', |
'First' =>'Primer', |
'Last' =>'Últim', |
'Go to' =>'Ves a', |
'Page' =>'Pàgina', |
'Records' =>'Registres', |
'Save' =>'Salvar', |
'More' =>'Més', |
'Apply' =>'Aplicar', |
'Cancel' =>'Cancel·lar', |
'Search' =>'Cercar', |
'Hide' =>'Amagar', |
'Clear' =>'Netejar', |
'Query' =>'Consultar', |
'Current Query' =>'Consulta actual', |
'Sorted By' =>'Ordenat per', |
'ascending' =>'ascendent', |
'descending' =>'descendent', |
'hidden' =>'amagat', |
'of' =>'de', |
'record added' =>'Registre afegit', |
'record changed'=>'Registre modificat', |
'record deleted'=>'Registre esborrat', |
'Please enter' =>'Sisplau introdueixi ', |
'months' => Array( |
'01'=>'Gener', |
'02'=>'Febrer', |
'03'=>'Març', |
'04'=>'Abril', |
'05'=>'Maig', |
'06'=>'Juny', |
'07'=>'Juliol', |
'08'=>'Agost', |
'09'=>'Septembre', |
'10'=>'Octubre', |
'11'=>'Novembre', |
'12'=>'Desembre'), |
// phpMyEdit-report |
'Make report' => 'Construir informe', |
'Select fields' => 'Seleccionar camps', |
'Records per screen' => 'Registres per pantalla', |
); |
?> |
/trunk/jrest/util/lang/PME.lang.PT-BR.inc |
---|
New file |
0,0 → 1,64 |
<?php |
/* |
* phpMyEdit language file |
* |
* language: portuguese (brazilian) |
* encoding: iso-8859-1 |
* date: 2002-12-23, 2003-01-14, 2003-05-17, 2004-01-21 |
* author: Roberto Cohen <roberto.cohen@fireman.com.br> |
*/ |
/* $Platon: phpMyEdit/lang/PME.lang.PT-BR.inc,v 1.8 2004-12-27 20:14:29 nepto Exp $ */ |
return Array( |
'Add' =>'Adiciona', |
'Copy' =>'Copia', |
'Change' =>'Edita', |
'Delete' =>'Remove', |
'View' =>'Visualiza', |
'Prev' =>'Anterior', |
'Next' =>'Próximo', |
'First' =>'Primeiro', |
'Last' =>'Último', |
'Go to' =>'Vai para', |
'Page' =>'Página', |
'Records' =>'Registros', |
'Save' =>'Salva', |
'More' =>'Mais', |
'Apply' =>'Aplica', |
'Cancel' =>'Cancela', |
'Search' =>'Pesquisa', |
'Hide' =>'Esconde', |
'Clear' =>'Limpa', |
'Query' =>'Resultado', |
'Current Query' =>'Resultado atual', |
'Sorted By' =>'Ordernado por', |
'ascending' =>'crescente', |
'descending' =>'descendente', |
'hidden' =>'escondido', |
'of' =>'de', |
'record added' =>'registro adicionado', |
'record changed'=>'registro editado', |
'record deleted'=>'registro removido', |
'Please enter' =>'Por favor, entre', |
'months' => Array( |
'01'=>'Janeiro', |
'02'=>'Fevereiro', |
'03'=>'Março', |
'04'=>'Abril', |
'05'=>'Maio', |
'06'=>'Junho', |
'07'=>'Julho', |
'08'=>'Agosto', |
'09'=>'Setembro', |
'10'=>'Outubro', |
'11'=>'Novembro', |
'12'=>'Dezembro'), |
// phpMyEdit-report |
'Gerar relatório' => 'Make report', |
'Selecionar campos' => 'Select fields', |
'Registros por tela' => 'Records per screen', |
); |
?> |
/trunk/jrest/util/lang/PME.lang.TR.inc |
---|
New file |
0,0 → 1,66 |
<?php |
/* |
* phpMyEdit language file |
* |
* language: turkish |
* encoding: iso-8859-9 |
* date: 2003-10-24, 2005-11-13 |
* authors: |
* Nuri Akman <nuri.akman@hazine.gov.tr> |
* Kadan Kongar <kagan.kongar@tsrsb.org.tr> |
*/ |
/* $Platon: phpMyEdit/lang/PME.lang.TR.inc,v 1.4 2005-11-14 03:15:04 nepto Exp $ */ |
return Array( |
'Add' =>'Ekle', |
'Copy' =>'Kopyala', |
'Change' =>'Deðiþtir', |
'Delete' =>'Sil', |
'View' =>'Bak', |
'Prev' =>'Önceki', |
'Next' =>'Sonraki', |
'First' =>'Ýlk', |
'Last' =>'Son', |
'Go to' =>'Git', |
'Page' =>'Sayfa', |
'Records' =>'Kayýt', |
'Save' =>'Kaydet', |
'More' =>'Devamý', |
'Apply' =>'Uygula', |
'Cancel' =>'Ýptal', |
'Search' =>'Ara', |
'Hide' =>'Gizle', |
'Clear' =>'Temizle', |
'Query' =>'Sorgu', |
'Current Query' =>'Aktif Sorgu', |
'Sorted By' =>'Sýralama', |
'ascending' =>'artan', |
'descending' =>'azalan', |
'hidden' =>'gizli', |
'of' =>' / ', |
'record added' =>'kayýt eklendi', |
'record changed' =>'kayýt deðiþtirildi', |
'record deleted' =>'kayýt silindi', |
'Please enter' =>'Lütfen giriniz :', |
'months' => Array( |
'01'=>'Ocak', |
'02'=>'Þubat', |
'03'=>'Mart', |
'04'=>'Nisan', |
'05'=>'Mayýs', |
'06'=>'Haziran', |
'07'=>'Temmuz', |
'08'=>'Auðustos', |
'09'=>'Eylül', |
'10'=>'Ekim', |
'11'=>'Kasým', |
'12'=>'Aralýk'), |
// phpMyEdit-report |
'Make report' => 'Rapor hazýrla', |
'Select fields' => 'Alanlarý seçiniz', |
'Records per screen' => 'Sayfa baþýna kayýt', |
); |
?> |
/trunk/jrest/util/lang/PME.lang.RU.inc |
---|
New file |
0,0 → 1,64 |
<?php |
/* |
* phpMyEdit language file |
* |
* language: russian |
* encoding: windows-1251 |
* date: 2002-11-23 |
* author: Lev Zabudkin <zabudkin@mail.ru> |
*/ |
/* $Platon: phpMyEdit/lang/PME.lang.RU.inc,v 1.11 2004-12-27 20:14:29 nepto Exp $ */ |
return Array( |
'Add' =>'Äîáàâèòü', |
'Copy' =>'Êîïèðîâàòü', |
'Change' =>'Èçìåíèòü', |
'Delete' =>'Óäàëèòü', |
'View' =>'Ïðîñìîòð', |
'Prev' =>'<<', |
'Next' =>'>>', |
'First' =>'I<', |
'Last' =>'>I', |
'Go to' =>'Ïåðåéòè', |
'Page' =>'Ñòð.', |
'Records' =>'Çàïèñåé', |
'Save' =>'Ñîõðàíèòü', |
'More' =>'Áîëüøå', |
'Apply' =>'Ïðèìåíèòü', |
'Cancel' =>'Îòìåíà', |
'Search' =>'Ïîèñê', |
'Hide' =>'Ñêðûòü', |
'Clear' =>'Î÷èñòèòü', |
'Query' =>'Çàïðîñ', |
'Current Query' =>'Òåêóùèé çàïðîñ', |
'Sorted By' =>'Îòñîðòèðîâàíî ïî', |
'ascending' =>'- âîçðàñòàíèþ', |
'descending' =>'- óáûâàíèþ', |
'hidden' =>'ñêðûòî', |
'of' =>'èç', |
'record added' =>'çàïèñü äîáàâëåíà', |
'record changed'=>'çàïèñü îáíîâëåíà', |
'record deleted'=>'çàïèñü óäàëåíà', |
'Please enter' =>'Ïîæàëóéñòà ââåäèòå', |
'months' => Array( |
'01'=>'ßíâàðü', |
'02'=>'Ôåâðàëü', |
'03'=>'Ìàðò', |
'04'=>'Àïðåëü', |
'05'=>'Ìàé', |
'06'=>'Èþíü', |
'07'=>'Èþëü', |
'08'=>'Àâãóñò', |
'09'=>'Ñåíòÿáðü', |
'10'=>'Îêòÿáðü', |
'11'=>'Íîÿáðü', |
'12'=>'Äåêàáðü'), |
// phpMyEdit-report |
'Make report' => 'Ñîçäàòü îò÷åò', |
'Select fields' => 'Âûáðàòü ïîëÿ', |
'Records per screen' => 'Çàïèñåé íà ýêðàíå', |
); |
?> |
/trunk/jrest/util/lang/PME.lang.EN-US.inc |
---|
New file |
0,0 → 1,64 |
<?php |
/* |
* phpMyEdit language file |
* |
* language: english (United States) |
* encoding: iso-8859-1 |
* date: 2002-02, 2003-05-01 |
* author: Jim Kraai <jkraai@users.sourceforge.net> |
*/ |
/* $Platon: phpMyEdit/lang/PME.lang.EN-US.inc,v 1.10 2004-12-27 20:14:29 nepto Exp $ */ |
return Array( |
'Add' =>'Add', |
'Copy' =>'Copy', |
'Change' =>'Change', |
'Delete' =>'Delete', |
'View' =>'View', |
'Prev' =>'Prev', |
'Next' =>'Next', |
'First' =>'First', |
'Last' =>'Last', |
'Go to' =>'Go to', |
'Page' =>'Page', |
'Records' =>'Records', |
'Save' =>'Save', |
'More' =>'More', |
'Apply' =>'Apply', |
'Cancel' =>'Cancel', |
'Search' =>'Search', |
'Hide' =>'Hide', |
'Clear' =>'Clear', |
'Query' =>'Query', |
'Current Query' =>'Current Query', |
'Sorted By' =>'Sorted By', |
'ascending' =>'ascending', |
'descending' =>'descending', |
'hidden' =>'hidden', |
'of' =>'of', |
'record added' =>'record added', |
'record changed' =>'record changed', |
'record deleted' =>'record deleted', |
'Please enter' =>'Please enter', |
'months' => Array( |
'01'=>'January', |
'02'=>'February', |
'03'=>'March', |
'04'=>'April', |
'05'=>'May', |
'06'=>'June', |
'07'=>'July', |
'08'=>'August', |
'09'=>'September', |
'10'=>'October', |
'11'=>'November', |
'12'=>'December'), |
// phpMyEdit-report |
'Make report' => 'Make report', |
'Select fields' => 'Select fields', |
'Records per screen' => 'Records per screen', |
); |
?> |
/trunk/jrest/util/images/alt/pme-delete.png |
---|
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
/trunk/jrest/util/images/alt/pme-delete.png |
---|
New file |
Property changes: |
Added: svn:mime-type |
+application/octet-stream |
\ No newline at end of property |
/trunk/jrest/util/images/alt/pme-change.png |
---|
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
/trunk/jrest/util/images/alt/pme-change.png |
---|
New file |
Property changes: |
Added: svn:mime-type |
+application/octet-stream |
\ No newline at end of property |
/trunk/jrest/util/images/alt/pme-copy.png |
---|
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
/trunk/jrest/util/images/alt/pme-copy.png |
---|
New file |
Property changes: |
Added: svn:mime-type |
+application/octet-stream |
\ No newline at end of property |
/trunk/jrest/util/images/alt/pme-view.png |
---|
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
/trunk/jrest/util/images/alt/pme-view.png |
---|
New file |
Property changes: |
Added: svn:mime-type |
+application/octet-stream |
\ No newline at end of property |
/trunk/jrest/util/images/pme-delete.png |
---|
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
/trunk/jrest/util/images/pme-delete.png |
---|
New file |
Property changes: |
Added: svn:mime-type |
+application/octet-stream |
\ No newline at end of property |
/trunk/jrest/util/images/pme-change.png |
---|
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
/trunk/jrest/util/images/pme-change.png |
---|
New file |
Property changes: |
Added: svn:mime-type |
+application/octet-stream |
\ No newline at end of property |
/trunk/jrest/util/images/pme-copy.png |
---|
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
/trunk/jrest/util/images/pme-copy.png |
---|
New file |
Property changes: |
Added: svn:mime-type |
+application/octet-stream |
\ No newline at end of property |
/trunk/jrest/util/images/pme-view.png |
---|
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
/trunk/jrest/util/images/pme-view.png |
---|
New file |
Property changes: |
Added: svn:mime-type |
+application/octet-stream |
\ No newline at end of property |
/trunk/jrest/util/cel_inventory.php |
---|
New file |
0,0 → 1,252 |
<style type="text/css"> |
hr.pme-hr { border: 0px solid; padding: 0px; margin: 0px; border-top-width: 1px; height: 1px; } |
table.pme-main { border: #004d9c 1px solid; border-collapse: collapse; border-spacing: 0px; width: 100%; } |
table.pme-navigation { border: #004d9c 0px solid; border-collapse: collapse; border-spacing: 0px; width: 100%; } |
th.pme-header { border: #004d9c 1px solid; padding: 4px; background: #add8e6; } |
td.pme-key-0, td.pme-value-0, td.pme-help-0, td.pme-navigation-0, td.pme-cell-0, |
td.pme-key-1, td.pme-value-1, td.pme-help-0, td.pme-navigation-1, td.pme-cell-1, |
td.pme-sortinfo, td.pme-filter { border: #004d9c 1px solid; padding: 3px; } |
td.pme-buttons { text-align: left; } |
td.pme-message { text-align: center; } |
td.pme-stats { text-align: right; } |
</style><?php |
/* |
* IMPORTANT NOTE: This generated file contains only a subset of huge amount |
* of options that can be used with phpMyEdit. To get information about all |
* features offered by phpMyEdit, check official documentation. It is available |
* online and also for download on phpMyEdit project management page: |
* |
* http://platon.sk/projects/main_page.php?project_id=5 |
* |
* This file was generated by: |
* |
* phpMyEdit version: 5.6 |
* phpMyEdit.class.php core class: 1.188 |
* phpMyEditSetup.php script: 1.48 |
* generating setup script: 1.48 |
*/ |
// MySQL host name, user name, password, database, and table |
$opts['hn'] = 'localhost'; |
$opts['un'] = 'root'; |
$opts['pw'] = ''; |
$opts['db'] = 'cel'; |
$opts['tb'] = 'cel_inventory'; |
// Name of field which is the unique key |
$opts['key'] = 'id'; |
// Type of key field (int/real/string/date etc.) |
$opts['key_type'] = 'int'; |
// Sorting field(s) |
$opts['sort_field'] = array('id'); |
// Number of records to display on the screen |
// Value of -1 lists all records in a table |
$opts['inc'] = 15; |
// Options you wish to give the users |
// A - add, C - change, P - copy, V - view, D - delete, |
// F - filter, I - initial sort suppressed |
$opts['options'] = 'ACPVDF'; |
// Number of lines to display on multiple selection filters |
$opts['multiple'] = '4'; |
// Navigation style: B - buttons (default), T - text links, G - graphic links |
// Buttons position: U - up, D - down (default) |
$opts['navigation'] = 'TB'; |
// Display special page elements |
$opts['display'] = array( |
'form' => true, |
'query' => true, |
'sort' => true, |
'time' => true, |
'tabs' => true |
); |
// Set default prefixes for variables |
$opts['js']['prefix'] = 'PME_js_'; |
$opts['dhtml']['prefix'] = 'PME_dhtml_'; |
$opts['cgi']['prefix']['operation'] = 'PME_op_'; |
$opts['cgi']['prefix']['sys'] = 'PME_sys_'; |
$opts['cgi']['prefix']['data'] = 'PME_data_'; |
/* Get the user's default language and use it if possible or you can |
specify particular one you want to use. Refer to official documentation |
for list of available languages. */ |
$opts['language'] = $_SERVER['HTTP_ACCEPT_LANGUAGE']; |
/* Table-level filter capability. If set, it is included in the WHERE clause |
of any generated SELECT statement in SQL query. This gives you ability to |
work only with subset of data from table. |
$opts['filters'] = "column1 like '%11%' AND column2<17"; |
$opts['filters'] = "section_id = 9"; |
$opts['filters'] = "PMEtable0.sessions_count > 200"; |
*/ |
/* Field definitions |
Fields will be displayed left to right on the screen in the order in which they |
appear in generated list. Here are some most used field options documented. |
['name'] is the title used for column headings, etc.; |
['maxlen'] maximum length to display add/edit/search input boxes |
['trimlen'] maximum length of string content to display in row listing |
['width'] is an optional display width specification for the column |
e.g. ['width'] = '100px'; |
['mask'] a string that is used by sprintf() to format field output |
['sort'] true or false; means the users may sort the display on this column |
['strip_tags'] true or false; whether to strip tags from content |
['nowrap'] true or false; whether this field should get a NOWRAP |
['select'] T - text, N - numeric, D - drop-down, M - multiple selection |
['options'] optional parameter to control whether a field is displayed |
L - list, F - filter, A - add, C - change, P - copy, D - delete, V - view |
Another flags are: |
R - indicates that a field is read only |
W - indicates that a field is a password field |
H - indicates that a field is to be hidden and marked as hidden |
['URL'] is used to make a field 'clickable' in the display |
e.g.: 'mailto:$value', 'http://$value' or '$page?stuff'; |
['URLtarget'] HTML target link specification (for example: _blank) |
['textarea']['rows'] and/or ['textarea']['cols'] |
specifies a textarea is to be used to give multi-line input |
e.g. ['textarea']['rows'] = 5; ['textarea']['cols'] = 10 |
['values'] restricts user input to the specified constants, |
e.g. ['values'] = array('A','B','C') or ['values'] = range(1,99) |
['values']['table'] and ['values']['column'] restricts user input |
to the values found in the specified column of another table |
['values']['description'] = 'desc_column' |
The optional ['values']['description'] field allows the value(s) displayed |
to the user to be different to those in the ['values']['column'] field. |
This is useful for giving more meaning to column values. Multiple |
descriptions fields are also possible. Check documentation for this. |
*/ |
$opts['fdd']['id'] = array( |
'name' => 'ID', |
'select' => 'T', |
'options' => 'AVCPDR', // auto increment |
'maxlen' => 20, |
'default' => '0', |
'sort' => true |
); |
$opts['fdd']['identifiant'] = array( |
'name' => 'Identifiant', |
'select' => 'T', |
'maxlen' => 128, |
'sort' => true |
); |
$opts['fdd']['ordre'] = array( |
'name' => 'Ordre', |
'select' => 'T', |
'maxlen' => 20, |
'sort' => true |
); |
$opts['fdd']['nom_sel'] = array( |
'name' => 'Nom sel', |
'select' => 'T', |
'maxlen' => 255, |
'sort' => true |
); |
$opts['fdd']['num_nom_sel'] = array( |
'name' => 'Num nom sel', |
'select' => 'T', |
'maxlen' => 11, |
'sort' => true |
); |
$opts['fdd']['nom_ret'] = array( |
'name' => 'Nom ret', |
'select' => 'T', |
'maxlen' => 255, |
'sort' => true |
); |
$opts['fdd']['num_nom_ret'] = array( |
'name' => 'Num nom ret', |
'select' => 'T', |
'maxlen' => 11, |
'sort' => true |
); |
$opts['fdd']['num_taxon'] = array( |
'name' => 'Num taxon', |
'select' => 'T', |
'maxlen' => 11, |
'sort' => true |
); |
$opts['fdd']['famille'] = array( |
'name' => 'Famille', |
'select' => 'T', |
'maxlen' => 255, |
'sort' => true |
); |
$opts['fdd']['location'] = array( |
'name' => 'Location', |
'select' => 'T', |
'maxlen' => 50, |
'sort' => true |
); |
$opts['fdd']['id_location'] = array( |
'name' => 'ID location', |
'select' => 'T', |
'maxlen' => 10, |
'sort' => true |
); |
$opts['fdd']['date_observation'] = array( |
'name' => 'Date observation', |
'select' => 'T', |
'maxlen' => 19, |
'sort' => true |
); |
$opts['fdd']['station'] = array( |
'name' => 'Station', |
'select' => 'T', |
'maxlen' => 255, |
'sort' => true |
); |
$opts['fdd']['milieu'] = array( |
'name' => 'Milieu', |
'select' => 'T', |
'maxlen' => 255, |
'sort' => true |
); |
$opts['fdd']['commentaire'] = array( |
'name' => 'Commentaire', |
'select' => 'T', |
'maxlen' => 1024, |
'sort' => true |
); |
$opts['fdd']['transmission'] = array( |
'name' => 'Transmission', |
'select' => 'T', |
'maxlen' => 4, |
'sort' => true |
); |
$opts['fdd']['date_creation'] = array( |
'name' => 'Date creation', |
'select' => 'T', |
'maxlen' => 19, |
'sort' => true |
); |
$opts['fdd']['date_modification'] = array( |
'name' => 'Date modification', |
'select' => 'T', |
'maxlen' => 19, |
'sort' => true |
); |
$opts['fdd']['date_transmission'] = array( |
'name' => 'Date transmission', |
'select' => 'T', |
'maxlen' => 19, |
'sort' => true |
); |
// Now important call to phpMyEdit |
require_once 'phpMyEdit.class.php'; |
new phpMyEdit($opts); |
?> |
/trunk/jrest/util/phpMyEditSetup.php |
---|
New file |
0,0 → 1,569 |
<?php |
/* |
* phpMyEdit - instant MySQL table editor and code generator |
* |
* phpMyEditSetup.php - interactive table configuration utility (setup) |
* ____________________________________________________________ |
* |
* Copyright (c) 1999-2002 John McCreesh <jpmcc@users.sourceforge.net> |
* Copyright (c) 2001-2002 Jim Kraai <jkraai@users.sourceforge.net> |
* Versions 5.0 and higher developed by Ondrej Jombik <nepto@php.net> |
* Copyright (c) 2002-2006 Platon Group, http://platon.sk/ |
* All rights reserved. |
* |
* See README file for more information about this software. |
* See COPYING file for license information. |
* |
* Download the latest version from |
* http://platon.sk/projects/phpMyEdit/ |
*/ |
/* $Platon: phpMyEdit/phpMyEditSetup.php,v 1.48 2006-09-09 07:38:54 nepto Exp $ */ |
?> |
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" |
"http://www.w3.org/TR/html4/loose.dtd"> |
<html> |
<head> |
<meta http-equiv="Content-Type" content="text/html; charset=us-ascii"> |
<title>phpMyEdit Setup</title> |
<style type="text/css"> |
<!-- |
body { font-family: "Verdana", "Arial", "Sans-Serif"; text-align: left } |
h1 { color: #004d9c; font-size: 13pt; font-weight: bold } |
h2 { color: #004d9c; font-size: 11pt; font-weight: bold } |
h3 { color: #004d9c; font-size: 11pt; } |
p { color: #004d9c; font-size: 9pt; } |
table { border: 1px solid #004d9c; border-collapse: collapse; border-spacing: 0px; } |
td { border: 1px solid; padding: 3px; color: #004d9c; font-size: 9pt; } |
hr |
{ |
height: 1px; |
background-color: #000000; |
color: #000000; |
border: solid #000000 0; |
padding: 0; |
margin: 0; |
border-top-width: 1px; |
} |
--> |
</style> |
</head> |
<body bgcolor="white"> |
<?php |
if (! defined('PHP_EOL')) { |
define('PHP_EOL', strtoupper(substr(PHP_OS, 0, 3) == 'WIN') ? "\r\n" |
: strtoupper(substr(PHP_OS, 0, 3) == 'MAC') ? "\r" : "\n"); |
} |
$hn = @$_POST['hn']; |
$un = @$_POST['un']; |
$pw = @$_POST['pw']; |
if(strlen($_POST['db'])>0) $db = @$_POST['db']; |
if(strlen($_POST['tb'])>0) $tb = @$_POST['tb']; |
$id = @$_POST['id']; |
$submit = @$_POST['submit']; |
$options = @$_POST['options']; |
$baseFilename = @$_POST['baseFilename']; |
$pageTitle = @$_POST['pageTitle']; |
$pageHeader = @$_POST['pageHeader']; |
$HTMLissues = @$_POST['HTMLissues']; |
$CSSstylesheet = @$_POST['CSSstylesheet']; |
$phpExtension = '.php'; |
if (isset($baseFilename) && $baseFilename != '') { |
$phpFile = $baseFilename.$phpExtension; |
//$contentFile = $baseFilename.'Content.inc'; |
$contentFile = $baseFilename.'.php'; |
} elseif (isset($tb)) { |
$phpFile = $tb.$phpExtension; |
//$contentFile = $tb.'Content.inc'; |
$contentFile = $tb.'.php'; |
} else { |
$phpFile = 'index'.$phpExtension; |
//$contentFile = 'Content.inc'; |
$contentFile = 'phpMyEdit-content.php'; |
} |
$buffer = ''; |
function echo_html($x) |
{ |
echo htmlspecialchars($x),PHP_EOL; |
} |
function echo_buffer($x) |
{ |
global $buffer; |
$buffer .= $x.PHP_EOL; |
} |
#:#####################################:# |
#:# Function: check_constraints #:# |
#:# Parameters: tb=table name #:# |
#:# fd=field name #:# |
#:# return: lookup default for #:# |
#:# said constraint #:# |
#:# or null if no #:# |
#:# constraint is found. #:# |
#:# Contributed by Wade Ryan, #:# |
#:# 20060906 #:# |
#:#####################################:# |
function check_constraints($tb,$fd) |
{ |
$query = "show create table $tb"; |
$result = mysql_query($query); |
$tableDef = preg_split('/\n/',mysql_result($result,0,1)); |
$constraint_arg=""; |
while (list($key,$val) = each($tableDef)) { |
$words=preg_split("/[\s'`()]+/", $val); |
if ($words[1] == "CONSTRAINT" && $words[6]=="REFERENCES") { |
if ($words[5]==$fd) { |
$constraint_arg=" 'values' => array(\n". |
" 'table' => '$words[7]',\n". |
" 'column' => '$words[8]'\n". |
" ),\n"; |
} |
} |
} |
return $constraint_arg; |
} |
function get_versions() |
{ |
$ret_ar = array(); |
$dirname = dirname(__FILE__); |
foreach (array( |
'current' => __FILE__, |
'setup' => "$dirname/phpMyEditSetup.php", |
'core' => "$dirname/phpMyEdit.class.php", |
'version' => "$dirname/doc/VERSION") |
as $type => $file) { |
if (@file_exists($file) && @is_readable($file)) { |
if (($f = fopen($file, 'r')) == false) { |
continue; |
} |
$str = trim(fread($f, 4096)); |
if (strpos($str, ' ') === false && strlen($str) < 10) { |
$ret_ar[$type] = $str; |
} else if (preg_match('|\$'.'Platon:\s+\S+,v\s+(\d+.\d+)\s+|', $str, $matches)) { |
$ret_ar[$type] = $matches[1]; |
} |
fclose($f); |
} |
} |
return $ret_ar; |
} |
$self = basename($_SERVER['PHP_SELF']); |
$dbl = @mysql_pconnect($hn, $un, $pw); |
if ((!$dbl) or empty($submit)) { |
echo '<h1>Please log in to your MySQL database</h1>'; |
if (!empty($submit)) { |
echo '<h2>Sorry - login failed - please try again</h2>'.PHP_EOL; |
} |
if (! isset($hn)) { |
$hn = 'localhost'; |
} |
echo ' |
<form action="'.htmlspecialchars($self).'" method="POST"> |
<table border="1" cellpadding="1" cellspacing="0" summary="Login form"> |
<tr> |
<td>Hostname:</td> |
<td><input type="text" name="hn" value="'.htmlspecialchars($hn).'"></td> |
</tr><tr> |
<td>Username:</td> |
<td><input type="text" name="un" value="'.htmlspecialchars($un).'"></td> |
</tr><tr> |
<td>Password:</td> |
<td><input type="password" name="pw" value="'.htmlspecialchars($pw).'"></td> |
</tr><tr> |
<td>Database:</td> |
<td><input type="text" name="db" value="'.htmlspecialchars($db).'"></td> |
</tr><tr> |
<td>Table:</td> |
<td><input type="text" name="tb" value="'.htmlspecialchars($tb).'"></td> |
</tr> |
</table><br> |
<input type="submit" name="submit" value="Submit"> |
</form>'.PHP_EOL; |
} else if (! isset($db)) { |
$dbs = @mysql_list_dbs($dbl); |
$num_dbs = @mysql_num_rows($dbs); |
echo '<h1>Please select a database</h1> |
<form action="'.htmlspecialchars($self).'" method="POST"> |
<input type="hidden" name="hn" value="'.htmlspecialchars($hn).'"> |
<input type="hidden" name="un" value="'.htmlspecialchars($un).'"> |
<input type="hidden" name="pw" value="'.htmlspecialchars($pw).'"> |
<table border="1" cellpadding="1" cellspacing="1" summary="Database selection">'.PHP_EOL; |
for ($i = 0; $i < $num_dbs; $i++) { |
$db = @mysql_db_name($dbs, $i); |
$checked = ! strcasecmp($un, $db) ? ' checked' : ''; |
$db = htmlspecialchars($db); |
echo '<tr><td><input'.$checked.' type="radio" name="db" value="'.$db.'"></td><td>'.$db.'</td></tr>'.PHP_EOL; |
} |
echo '</table><br> |
<input type="submit" name="submit" value="Submit"> |
<input type="submit" name="cancel" value="Cancel"> |
</form>'.PHP_EOL; |
} else if (!isset($tb)) { |
echo '<h1>Please select a table from database: '.htmlspecialchars($db).'</h1> |
<form action="'.htmlspecialchars($self).'" method="POST"> |
<input type="hidden" name="hn" value="'.htmlspecialchars($hn).'"> |
<input type="hidden" name="un" value="'.htmlspecialchars($un).'"> |
<input type="hidden" name="pw" value="'.htmlspecialchars($pw).'"> |
<input type="hidden" name="db" value="'.htmlspecialchars($db).'"> |
<table border="1" cellpadding="1" cellspacing="1" summary="Table selection">'.PHP_EOL; |
$tbs = @mysql_list_tables($db, $dbl); |
$num_tbs = @mysql_num_rows($tbs); |
for ($j = 0; $j < $num_tbs; $j++) { |
$tb = @mysql_tablename($tbs, $j); |
$tb = htmlspecialchars($tb); |
$checked = $j == 0 ? ' checked' : ''; |
echo '<tr><td><input'.$checked.' type="radio" name="tb" value="'.$tb.'"></td><td>'.$tb.'</td></tr>'.PHP_EOL; |
} |
echo '</table><br> |
<input type="submit" name="submit" value="Submit"> |
<input type="submit" name="cancel" value="Cancel"> |
</form>'.PHP_EOL; |
} else if (!isset($id)) { |
echo ' <h1>Please select an identifier from table: '.htmlspecialchars($tb).'</h1> |
<p> |
This field will be used in change, view, copy and delete operations.<br> |
The field should be numeric and must uniquely identify a record. |
</p> |
<p> |
Please note, that there were problems reported by phpMyEdit users |
regarding using MySQL reserved word as unique key name (the example for |
this is "key" name). Thus we recommend you to use another name |
of unique key. Usage of "id" or "ID" should be safe and good idea. |
</p> |
<form action="'.htmlspecialchars($self).'" method="POST"> |
<input type="hidden" name="hn" value="'.htmlspecialchars($hn).'"> |
<input type="hidden" name="un" value="'.htmlspecialchars($un).'"> |
<input type="hidden" name="pw" value="'.htmlspecialchars($pw).'"> |
<input type="hidden" name="db" value="'.htmlspecialchars($db).'"> |
<input type="hidden" name="tb" value="'.htmlspecialchars($tb).'"> |
<table border="1" cellpadding="1" cellspacing="1" summary="Key selection">'.PHP_EOL; |
// <tr><td><input type="radio" name="id" value=""> |
// <td><i>None</i></td><td><i>No id field required</i></td></tr> |
@mysql_select_db($db); |
$tb_desc = @mysql_query("DESCRIBE $tb"); |
$fds = @mysql_list_fields($db,$tb,$dbl); |
for ($j = 0; ($fd = @mysql_field_name($fds, $j)) != false; $j++) { |
$ff = @mysql_field_flags($fds, $j); |
strlen($ff) <= 0 && $ff = '---'; |
$checked = stristr($ff, 'primary_key') ? ' checked' : ''; |
echo '<tr><td><input',$checked,' type="radio" name="id" value="',htmlspecialchars($fd),'"></td>'; |
echo '<td>',htmlspecialchars($fd),'</td>'; |
echo '<td>',htmlspecialchars($ff),'</td>'; |
$r = @mysql_fetch_array($tb_desc, $j); |
} |
echo '</table><br> |
<input type="submit" name="submit" value="Submit"> |
<input type="submit" name="cancel" value="Cancel"> |
</form>'.PHP_EOL; |
} else if (!isset($options)) { |
echo '<h1>Please select additional options</h1> |
<form action="'.htmlspecialchars($self).'" method="POST"> |
<input type="hidden" name="hn" value="'.htmlspecialchars($hn).'"> |
<input type="hidden" name="un" value="'.htmlspecialchars($un).'"> |
<input type="hidden" name="pw" value="'.htmlspecialchars($pw).'"> |
<input type="hidden" name="db" value="'.htmlspecialchars($db).'"> |
<input type="hidden" name="tb" value="'.htmlspecialchars($tb).'"> |
<input type="hidden" name="id" value="'.htmlspecialchars($id).'"> |
<table border="1" cellpadding="1" cellspacing="1" summary="Additional options"> |
<tr><td>Base filename</td><td><input type="text" name=baseFilename value ="'.htmlspecialchars($tb).'"></td></tr> |
<tr><td>Page title</td><td><input type="text" name=pageTitle value ="'.htmlspecialchars($tb).'"></td></tr> |
<tr><td>Page header</td><td><input type="checkbox" name=pageHeader></td></tr> |
<tr><td>HTML header & footer</td><td><input type="checkbox" name=HTMLissues></td></tr> |
<tr><td>CSS basic stylesheet</td><td><input checked type="checkbox" name=CSSstylesheet></td></tr> |
</table><br> |
<input type="submit" name="submit" value="Submit"> |
<input type="submit" name="cancel" value="Cancel"> |
<input type="hidden" name="options" value="1"> |
</form>'.PHP_EOL; |
} else { |
echo '<h1>Here is your phpMyEdit calling program</h1>'.PHP_EOL; |
echo '<h2>You may now copy and paste it into your PHP editor</h2>'.PHP_EOL; |
if ($pageHeader) { |
echo_buffer('<h3>'.$pageTitle.'</h3>'); |
} |
$versions = ''; |
$versions_ar = get_versions(); |
foreach (array( |
'version' => 'phpMyEdit version:', |
'core' => 'phpMyEdit.class.php core class:', |
'setup' => 'phpMyEditSetup.php script:', |
'current' => 'generating setup script:') |
as $type => $desc) { |
$version = isset($versions_ar[$type]) ? $versions_ar[$type] : 'unknown'; |
$versions .= sprintf("\n * %36s %s", $desc, $version); |
} |
echo_buffer("<?php |
/* |
* IMPORTANT NOTE: This generated file contains only a subset of huge amount |
* of options that can be used with phpMyEdit. To get information about all |
* features offered by phpMyEdit, check official documentation. It is available |
* online and also for download on phpMyEdit project management page: |
* |
* http://platon.sk/projects/main_page.php?project_id=5 |
* |
* This file was generated by: |
*$versions |
*/ |
// MySQL host name, user name, password, database, and table |
\$opts['hn'] = '$hn'; |
\$opts['un'] = '$un'; |
\$opts['pw'] = '$pw'; |
\$opts['db'] = '$db'; |
\$opts['tb'] = '$tb'; |
// Name of field which is the unique key |
\$opts['key'] = '$id'; |
// Type of key field (int/real/string/date etc.)"); |
if ($id == '') { |
echo_buffer("\$opts['key_type'] = '';"); |
} else { |
$fds = @mysql_list_fields($db,$tb,$dbl); |
for ($j = 0; ($fd = @mysql_field_name($fds, $j)) != ''; $j++) { |
if ($fd == $id) { |
echo_buffer("\$opts['key_type'] = '".@mysql_field_type($fds, $j)."';"); |
break; |
} |
} |
} |
echo_buffer(" |
// Sorting field(s) |
\$opts['sort_field'] = array('$id'); |
// Number of records to display on the screen |
// Value of -1 lists all records in a table |
\$opts['inc'] = 15; |
// Options you wish to give the users |
// A - add, C - change, P - copy, V - view, D - delete, |
// F - filter, I - initial sort suppressed |
\$opts['options'] = 'ACPVDF'; |
// Number of lines to display on multiple selection filters |
\$opts['multiple'] = '4'; |
// Navigation style: B - buttons (default), T - text links, G - graphic links |
// Buttons position: U - up, D - down (default) |
\$opts['navigation'] = 'DB'; |
// Display special page elements |
\$opts['display'] = array( |
'form' => true, |
'query' => true, |
'sort' => true, |
'time' => true, |
'tabs' => true |
); |
// Set default prefixes for variables |
\$opts['js']['prefix'] = 'PME_js_'; |
\$opts['dhtml']['prefix'] = 'PME_dhtml_'; |
\$opts['cgi']['prefix']['operation'] = 'PME_op_'; |
\$opts['cgi']['prefix']['sys'] = 'PME_sys_'; |
\$opts['cgi']['prefix']['data'] = 'PME_data_'; |
/* Get the user's default language and use it if possible or you can |
specify particular one you want to use. Refer to official documentation |
for list of available languages. */ |
\$opts['language'] = \$_SERVER['HTTP_ACCEPT_LANGUAGE']; |
/* Table-level filter capability. If set, it is included in the WHERE clause |
of any generated SELECT statement in SQL query. This gives you ability to |
work only with subset of data from table. |
\$opts['filters'] = \"column1 like '%11%' AND column2<17\"; |
\$opts['filters'] = \"section_id = 9\"; |
\$opts['filters'] = \"PMEtable0.sessions_count > 200\"; |
*/ |
/* Field definitions |
Fields will be displayed left to right on the screen in the order in which they |
appear in generated list. Here are some most used field options documented. |
['name'] is the title used for column headings, etc.; |
['maxlen'] maximum length to display add/edit/search input boxes |
['trimlen'] maximum length of string content to display in row listing |
['width'] is an optional display width specification for the column |
e.g. ['width'] = '100px'; |
['mask'] a string that is used by sprintf() to format field output |
['sort'] true or false; means the users may sort the display on this column |
['strip_tags'] true or false; whether to strip tags from content |
['nowrap'] true or false; whether this field should get a NOWRAP |
['select'] T - text, N - numeric, D - drop-down, M - multiple selection |
['options'] optional parameter to control whether a field is displayed |
L - list, F - filter, A - add, C - change, P - copy, D - delete, V - view |
Another flags are: |
R - indicates that a field is read only |
W - indicates that a field is a password field |
H - indicates that a field is to be hidden and marked as hidden |
['URL'] is used to make a field 'clickable' in the display |
e.g.: 'mailto:\$value', 'http://\$value' or '\$page?stuff'; |
['URLtarget'] HTML target link specification (for example: _blank) |
['textarea']['rows'] and/or ['textarea']['cols'] |
specifies a textarea is to be used to give multi-line input |
e.g. ['textarea']['rows'] = 5; ['textarea']['cols'] = 10 |
['values'] restricts user input to the specified constants, |
e.g. ['values'] = array('A','B','C') or ['values'] = range(1,99) |
['values']['table'] and ['values']['column'] restricts user input |
to the values found in the specified column of another table |
['values']['description'] = 'desc_column' |
The optional ['values']['description'] field allows the value(s) displayed |
to the user to be different to those in the ['values']['column'] field. |
This is useful for giving more meaning to column values. Multiple |
descriptions fields are also possible. Check documentation for this. |
*/ |
"); |
@mysql_select_db($db); |
$tb_desc = @mysql_query("DESCRIBE $tb"); |
$fds = @mysql_list_fields($db, $tb, $dbl); |
$num_fds = @mysql_num_fields($fds); |
$ts_cnt = 0; |
for ($k = 0; $k < $num_fds; $k++) { |
$fd = mysql_field_name($fds,$k); |
$fm = mysql_fetch_field($fds,$k); |
$fn = strtr($fd, '_-.', ' '); |
$fn = preg_replace('/(^| +)id( +|$)/', '\\1ID\\2', $fn); // uppercase IDs |
$fn = ucfirst($fn); |
$row = @mysql_fetch_array($tb_desc); |
echo_buffer('$opts[\'fdd\'][\''.$fd.'\'] = array('); // ) |
echo_buffer(" 'name' => '".str_replace('\'','\\\'',$fn)."',"); |
$auto_increment = strstr($row[5], 'auto_increment') ? 1 : 0; |
if (substr($row[1],0,3) == 'set') { |
echo_buffer(" 'select' => 'M',"); |
} else { |
echo_buffer(" 'select' => 'T',"); |
} |
if ($auto_increment) { |
echo_buffer(" 'options' => 'AVCPDR', // auto increment"); |
} |
// timestamps are read-only |
else if (@mysql_field_type($fds, $k) == 'timestamp') { |
if ($ts_cnt > 0) { |
echo_buffer(" 'options' => 'AVCPD',"); |
} else { // first timestamp |
echo_buffer(" 'options' => 'AVCPDR', // updated automatically (MySQL feature)"); |
} |
$ts_cnt++; |
} |
echo_buffer(" 'maxlen' => ".@mysql_field_len($fds,$k).','); |
// blobs -> textarea |
if (@mysql_field_type($fds,$k) == 'blob') { |
echo_buffer(" 'textarea' => array("); |
echo_buffer(" 'rows' => 5,"); |
echo_buffer(" 'cols' => 50),"); |
} |
// SETs and ENUMs get special treatment |
if ((substr($row[1],0,3) == 'set' || substr($row[1],0,4) == 'enum') |
&& ! (($pos = strpos($row[1], '(')) === false)) { |
$indent = str_repeat(' ', 18); |
$outstr = substr($row[1], $pos + 2, -2); |
$outstr = explode("','", $outstr); |
$outstr = str_replace("''", "'", $outstr); |
$outstr = str_replace('"', '\\"', $outstr); |
$outstr = implode('",'.PHP_EOL.$indent.'"', $outstr); |
echo_buffer(" 'values' => array(".PHP_EOL.$indent.'"'.$outstr.'"),'); |
} |
// automatic support for Default values |
if ($row[4] != '' && $row[4] != 'NULL') { |
echo_buffer(" 'default' => '".$row[4]."',"); |
} else if ($auto_increment) { |
echo_buffer(" 'default' => '0',"); |
} |
// check for table constraints |
$outstr = check_constraints($tb, $fd); |
if ($outstr != '') { |
echo_buffer($outstr); |
} |
echo_buffer(" 'sort' => true"); |
//echo_buffer(" 'nowrap' => false,"); |
echo_buffer(');'); |
} |
echo_buffer(" |
// Now important call to phpMyEdit |
require_once 'phpMyEdit.class.php'; |
new phpMyEdit(\$opts); |
?> |
"); |
$css_directive = <<<END |
<style type="text/css"> |
hr.pme-hr { border: 0px solid; padding: 0px; margin: 0px; border-top-width: 1px; height: 1px; } |
table.pme-main { border: #004d9c 1px solid; border-collapse: collapse; border-spacing: 0px; width: 100%; } |
table.pme-navigation { border: #004d9c 0px solid; border-collapse: collapse; border-spacing: 0px; width: 100%; } |
th.pme-header { border: #004d9c 1px solid; padding: 4px; background: #add8e6; } |
td.pme-key-0, td.pme-value-0, td.pme-help-0, td.pme-navigation-0, td.pme-cell-0, |
td.pme-key-1, td.pme-value-1, td.pme-help-0, td.pme-navigation-1, td.pme-cell-1, |
td.pme-sortinfo, td.pme-filter { border: #004d9c 1px solid; padding: 3px; } |
td.pme-buttons { text-align: left; } |
td.pme-message { text-align: center; } |
td.pme-stats { text-align: right; } |
</style> |
END; |
if (! $CSSstylesheet) { |
$css_directive = ''; |
} |
if ($HTMLissues) { |
$buffer = <<<END |
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" |
"http://www.w3.org/TR/html4/loose.dtd"> |
<html> |
<head> |
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"> |
<title>$pageTitle</title> |
$css_directive |
</head> |
<body> |
$buffer |
</body> |
</html> |
END; |
} else if ($CSSstylesheet) { |
$buffer = $css_directive . $buffer; |
} |
// write the content include file |
echo 'Trying to write content file to: <b>'.'./'.$contentFile.'</b><br>'.PHP_EOL; |
$filehandle = @fopen('./'.$contentFile, 'w+'); |
if ($filehandle) { |
fwrite($filehandle, $buffer); |
flush($filehandle); |
fclose($filehandle); |
echo 'phpMyEdit content file written successfully<br>'; |
} else { |
echo 'phpMyEdit content file was NOT written due to inssufficient privileges.<br>'; |
echo 'Please copy and paste content listed below to <i>'.'./'.$contentFile.'</i> file.'; |
} |
echo '<br><hr>'; |
echo '<pre>'; |
echo_html($buffer); |
echo '</pre><hr>'.PHP_EOL; |
} |
?> |
</body> |
</html> |
/trunk/jrest/XML/Parser.php |
---|
New file |
0,0 → 1,690 |
<?php |
// |
// +----------------------------------------------------------------------+ |
// | PHP Version 4 | |
// +----------------------------------------------------------------------+ |
// | Copyright (c) 1997-2004 The PHP Group | |
// +----------------------------------------------------------------------+ |
// | This source file is subject to version 3.0 of the PHP license, | |
// | that is bundled with this package in the file LICENSE, and is | |
// | available at through the world-wide-web at | |
// | http://www.php.net/license/3_0.txt. | |
// | If you did not receive a copy of the PHP license and are unable to | |
// | obtain it through the world-wide-web, please send a note to | |
// | license@php.net so we can mail you a copy immediately. | |
// +----------------------------------------------------------------------+ |
// | Author: Stig Bakken <ssb@fast.no> | |
// | Tomas V.V.Cox <cox@idecnet.com> | |
// | Stephan Schmidt <schst@php-tools.net> | |
// +----------------------------------------------------------------------+ |
// |
// $Id: Parser.php,v 1.3 2007-11-19 15:11:00 jp_milcent Exp $ |
/** |
* XML Parser class. |
* |
* This is an XML parser based on PHP's "xml" extension, |
* based on the bundled expat library. |
* |
* @category XML |
* @package XML_Parser |
* @author Stig Bakken <ssb@fast.no> |
* @author Tomas V.V.Cox <cox@idecnet.com> |
* @author Stephan Schmidt <schst@php-tools.net> |
*/ |
/** |
* uses PEAR's error handling |
*/ |
require_once 'PEAR.php'; |
/** |
* resource could not be created |
*/ |
define('XML_PARSER_ERROR_NO_RESOURCE', 200); |
/** |
* unsupported mode |
*/ |
define('XML_PARSER_ERROR_UNSUPPORTED_MODE', 201); |
/** |
* invalid encoding was given |
*/ |
define('XML_PARSER_ERROR_INVALID_ENCODING', 202); |
/** |
* specified file could not be read |
*/ |
define('XML_PARSER_ERROR_FILE_NOT_READABLE', 203); |
/** |
* invalid input |
*/ |
define('XML_PARSER_ERROR_INVALID_INPUT', 204); |
/** |
* remote file cannot be retrieved in safe mode |
*/ |
define('XML_PARSER_ERROR_REMOTE', 205); |
/** |
* XML Parser class. |
* |
* This is an XML parser based on PHP's "xml" extension, |
* based on the bundled expat library. |
* |
* Notes: |
* - It requires PHP 4.0.4pl1 or greater |
* - From revision 1.17, the function names used by the 'func' mode |
* are in the format "xmltag_$elem", for example: use "xmltag_name" |
* to handle the <name></name> tags of your xml file. |
* |
* @category XML |
* @package XML_Parser |
* @author Stig Bakken <ssb@fast.no> |
* @author Tomas V.V.Cox <cox@idecnet.com> |
* @author Stephan Schmidt <schst@php-tools.net> |
* @todo create XML_Parser_Namespace to parse documents with namespaces |
* @todo create XML_Parser_Pull |
* @todo Tests that need to be made: |
* - mixing character encodings |
* - a test using all expat handlers |
* - options (folding, output charset) |
* - different parsing modes |
*/ |
class XML_Parser extends PEAR |
{ |
// {{{ properties |
/** |
* XML parser handle |
* |
* @var resource |
* @see xml_parser_create() |
*/ |
var $parser; |
/** |
* File handle if parsing from a file |
* |
* @var resource |
*/ |
var $fp; |
/** |
* Whether to do case folding |
* |
* If set to true, all tag and attribute names will |
* be converted to UPPER CASE. |
* |
* @var boolean |
*/ |
var $folding = true; |
/** |
* Mode of operation, one of "event" or "func" |
* |
* @var string |
*/ |
var $mode; |
/** |
* Mapping from expat handler function to class method. |
* |
* @var array |
*/ |
var $handler = array( |
'character_data_handler' => 'cdataHandler', |
'default_handler' => 'defaultHandler', |
'processing_instruction_handler' => 'piHandler', |
'unparsed_entity_decl_handler' => 'unparsedHandler', |
'notation_decl_handler' => 'notationHandler', |
'external_entity_ref_handler' => 'entityrefHandler' |
); |
/** |
* source encoding |
* |
* @var string |
*/ |
var $srcenc; |
/** |
* target encoding |
* |
* @var string |
*/ |
var $tgtenc; |
/** |
* handler object |
* |
* @var object |
*/ |
var $_handlerObj; |
/** |
* valid encodings |
* |
* @var array |
*/ |
var $_validEncodings = array('ISO-8859-1', 'UTF-8', 'US-ASCII'); |
// }}} |
// {{{ constructor |
/** |
* Creates an XML parser. |
* |
* This is needed for PHP4 compatibility, it will |
* call the constructor, when a new instance is created. |
* |
* @param string $srcenc source charset encoding, use NULL (default) to use |
* whatever the document specifies |
* @param string $mode how this parser object should work, "event" for |
* startelement/endelement-type events, "func" |
* to have it call functions named after elements |
* @param string $tgenc a valid target encoding |
*/ |
function XML_Parser($srcenc = null, $mode = 'event', $tgtenc = null) |
{ |
XML_Parser::__construct($srcenc, $mode, $tgtenc); |
} |
// }}} |
/** |
* PHP5 constructor |
* |
* @param string $srcenc source charset encoding, use NULL (default) to use |
* whatever the document specifies |
* @param string $mode how this parser object should work, "event" for |
* startelement/endelement-type events, "func" |
* to have it call functions named after elements |
* @param string $tgenc a valid target encoding |
*/ |
function __construct($srcenc = null, $mode = 'event', $tgtenc = null) |
{ |
$this->PEAR('XML_Parser_Error'); |
$this->mode = $mode; |
$this->srcenc = $srcenc; |
$this->tgtenc = $tgtenc; |
} |
// }}} |
/** |
* Sets the mode of the parser. |
* |
* Possible modes are: |
* - func |
* - event |
* |
* You can set the mode using the second parameter |
* in the constructor. |
* |
* This method is only needed, when switching to a new |
* mode at a later point. |
* |
* @access public |
* @param string mode, either 'func' or 'event' |
* @return boolean|object true on success, PEAR_Error otherwise |
*/ |
function setMode($mode) |
{ |
if ($mode != 'func' && $mode != 'event') { |
$this->raiseError('Unsupported mode given', XML_PARSER_ERROR_UNSUPPORTED_MODE); |
} |
$this->mode = $mode; |
return true; |
} |
/** |
* Sets the object, that will handle the XML events |
* |
* This allows you to create a handler object independent of the |
* parser object that you are using and easily switch the underlying |
* parser. |
* |
* If no object will be set, XML_Parser assumes that you |
* extend this class and handle the events in $this. |
* |
* @access public |
* @param object object to handle the events |
* @return boolean will always return true |
* @since v1.2.0beta3 |
*/ |
function setHandlerObj(&$obj) |
{ |
$this->_handlerObj = &$obj; |
return true; |
} |
/** |
* Init the element handlers |
* |
* @access private |
*/ |
function _initHandlers() |
{ |
if (!is_resource($this->parser)) { |
return false; |
} |
if (!is_object($this->_handlerObj)) { |
$this->_handlerObj = &$this; |
} |
switch ($this->mode) { |
case 'func': |
xml_set_object($this->parser, $this->_handlerObj); |
xml_set_element_handler($this->parser, array(&$this, 'funcStartHandler'), array(&$this, 'funcEndHandler')); |
break; |
case 'event': |
xml_set_object($this->parser, $this->_handlerObj); |
xml_set_element_handler($this->parser, 'startHandler', 'endHandler'); |
break; |
default: |
return $this->raiseError('Unsupported mode given', XML_PARSER_ERROR_UNSUPPORTED_MODE); |
break; |
} |
/** |
* set additional handlers for character data, entities, etc. |
*/ |
foreach ($this->handler as $xml_func => $method) { |
if (method_exists($this->_handlerObj, $method)) { |
$xml_func = 'xml_set_' . $xml_func; |
$xml_func($this->parser, $method); |
} |
} |
} |
// {{{ _create() |
/** |
* create the XML parser resource |
* |
* Has been moved from the constructor to avoid |
* problems with object references. |
* |
* Furthermore it allows us returning an error |
* if something fails. |
* |
* @access private |
* @return boolean|object true on success, PEAR_Error otherwise |
* |
* @see xml_parser_create |
*/ |
function _create() |
{ |
if ($this->srcenc === null) { |
$xp = @xml_parser_create(); |
} else { |
$xp = @xml_parser_create($this->srcenc); |
} |
if (is_resource($xp)) { |
if ($this->tgtenc !== null) { |
if (!@xml_parser_set_option($xp, XML_OPTION_TARGET_ENCODING, |
$this->tgtenc)) { |
return $this->raiseError('invalid target encoding', XML_PARSER_ERROR_INVALID_ENCODING); |
} |
} |
$this->parser = $xp; |
$result = $this->_initHandlers($this->mode); |
if ($this->isError($result)) { |
return $result; |
} |
xml_parser_set_option($xp, XML_OPTION_CASE_FOLDING, $this->folding); |
return true; |
} |
if (!in_array(strtoupper($this->srcenc), $this->_validEncodings)) { |
return $this->raiseError('invalid source encoding', XML_PARSER_ERROR_INVALID_ENCODING); |
} |
return $this->raiseError('Unable to create XML parser resource.', XML_PARSER_ERROR_NO_RESOURCE); |
} |
// }}} |
// {{{ reset() |
/** |
* Reset the parser. |
* |
* This allows you to use one parser instance |
* to parse multiple XML documents. |
* |
* @access public |
* @return boolean|object true on success, PEAR_Error otherwise |
*/ |
function reset() |
{ |
$result = $this->_create(); |
if ($this->isError( $result )) { |
return $result; |
} |
return true; |
} |
// }}} |
// {{{ setInputFile() |
/** |
* Sets the input xml file to be parsed |
* |
* @param string Filename (full path) |
* @return resource fopen handle of the given file |
* @throws XML_Parser_Error |
* @see setInput(), setInputString(), parse() |
* @access public |
*/ |
function setInputFile($file) |
{ |
/** |
* check, if file is a remote file |
*/ |
if (eregi('^(http|ftp)://', substr($file, 0, 10))) { |
if (!ini_get('allow_url_fopen')) { |
return $this->raiseError('Remote files cannot be parsed, as safe mode is enabled.', XML_PARSER_ERROR_REMOTE); |
} |
} |
$fp = @fopen($file, 'rb'); |
if (is_resource($fp)) { |
$this->fp = $fp; |
return $fp; |
} |
return $this->raiseError('File could not be opened.', XML_PARSER_ERROR_FILE_NOT_READABLE); |
} |
// }}} |
// {{{ setInputString() |
/** |
* XML_Parser::setInputString() |
* |
* Sets the xml input from a string |
* |
* @param string $data a string containing the XML document |
* @return null |
**/ |
function setInputString($data) |
{ |
$this->fp = $data; |
return null; |
} |
// }}} |
// {{{ setInput() |
/** |
* Sets the file handle to use with parse(). |
* |
* You should use setInputFile() or setInputString() if you |
* pass a string |
* |
* @param mixed $fp Can be either a resource returned from fopen(), |
* a URL, a local filename or a string. |
* @access public |
* @see parse() |
* @uses setInputString(), setInputFile() |
*/ |
function setInput($fp) |
{ |
if (is_resource($fp)) { |
$this->fp = $fp; |
return true; |
} |
// see if it's an absolute URL (has a scheme at the beginning) |
elseif (eregi('^[a-z]+://', substr($fp, 0, 10))) { |
return $this->setInputFile($fp); |
} |
// see if it's a local file |
elseif (file_exists($fp)) { |
return $this->setInputFile($fp); |
} |
// it must be a string |
else { |
$this->fp = $fp; |
return true; |
} |
return $this->raiseError('Illegal input format', XML_PARSER_ERROR_INVALID_INPUT); |
} |
// }}} |
// {{{ parse() |
/** |
* Central parsing function. |
* |
* @return true|object PEAR error returns true on success, or a PEAR_Error otherwise |
* @access public |
*/ |
function parse() |
{ |
/** |
* reset the parser |
*/ |
$result = $this->reset(); |
if ($this->isError($result)) { |
return $result; |
} |
// if $this->fp was fopened previously |
if (is_resource($this->fp)) { |
while ($data = fread($this->fp, 4096)) { |
if (!$this->_parseString($data, feof($this->fp))) { |
$error = &$this->raiseError(); |
$this->free(); |
return $error; |
} |
} |
// otherwise, $this->fp must be a string |
} else { |
if (!$this->_parseString($this->fp, true)) { |
$error = &$this->raiseError(); |
$this->free(); |
return $error; |
} |
} |
$this->free(); |
return true; |
} |
/** |
* XML_Parser::_parseString() |
* |
* @param string $data |
* @param boolean $eof |
* @return bool |
* @access private |
* @see parseString() |
**/ |
function _parseString($data, $eof = false) |
{ |
return xml_parse($this->parser, $data, $eof); |
} |
// }}} |
// {{{ parseString() |
/** |
* XML_Parser::parseString() |
* |
* Parses a string. |
* |
* @param string $data XML data |
* @param boolean $eof If set and TRUE, data is the last piece of data sent in this parser |
* @throws XML_Parser_Error |
* @return Pear Error|true true on success or a PEAR Error |
* @see _parseString() |
*/ |
function parseString($data, $eof = false) |
{ |
if (!isset($this->parser) || !is_resource($this->parser)) { |
$this->reset(); |
} |
if (!$this->_parseString($data, $eof)) { |
$error = &$this->raiseError(); |
$this->free(); |
return $error; |
} |
if ($eof === true) { |
$this->free(); |
} |
return true; |
} |
/** |
* XML_Parser::free() |
* |
* Free the internal resources associated with the parser |
* |
* @return null |
**/ |
function free() |
{ |
if (isset($this->parser) && is_resource($this->parser)) { |
xml_parser_free($this->parser); |
unset( $this->parser ); |
} |
if (isset($this->fp) && is_resource($this->fp)) { |
fclose($this->fp); |
} |
unset($this->fp); |
return null; |
} |
/** |
* XML_Parser::raiseError() |
* |
* Throws a XML_Parser_Error |
* |
* @param string $msg the error message |
* @param integer $ecode the error message code |
* @return XML_Parser_Error |
**/ |
function raiseError($msg = null, $ecode = 0) |
{ |
$msg = !is_null($msg) ? $msg : $this->parser; |
$err = &new XML_Parser_Error($msg, $ecode); |
return parent::raiseError($err); |
} |
// }}} |
// {{{ funcStartHandler() |
function funcStartHandler($xp, $elem, $attribs) |
{ |
$func = 'xmltag_' . $elem; |
$func = str_replace(array('.', '-', ':'), '_', $func); |
if (method_exists($this->_handlerObj, $func)) { |
call_user_func(array(&$this->_handlerObj, $func), $xp, $elem, $attribs); |
} elseif (method_exists($this->_handlerObj, 'xmltag')) { |
call_user_func(array(&$this->_handlerObj, 'xmltag'), $xp, $elem, $attribs); |
} |
} |
// }}} |
// {{{ funcEndHandler() |
function funcEndHandler($xp, $elem) |
{ |
$func = 'xmltag_' . $elem . '_'; |
$func = str_replace(array('.', '-', ':'), '_', $func); |
if (method_exists($this->_handlerObj, $func)) { |
call_user_func(array(&$this->_handlerObj, $func), $xp, $elem); |
} elseif (method_exists($this->_handlerObj, 'xmltag_')) { |
call_user_func(array(&$this->_handlerObj, 'xmltag_'), $xp, $elem); |
} |
} |
// }}} |
// {{{ startHandler() |
/** |
* |
* @abstract |
*/ |
function startHandler($xp, $elem, &$attribs) |
{ |
return NULL; |
} |
// }}} |
// {{{ endHandler() |
/** |
* |
* @abstract |
*/ |
function endHandler($xp, $elem) |
{ |
return NULL; |
} |
// }}}me |
} |
/** |
* error class, replaces PEAR_Error |
* |
* An instance of this class will be returned |
* if an error occurs inside XML_Parser. |
* |
* There are three advantages over using the standard PEAR_Error: |
* - All messages will be prefixed |
* - check for XML_Parser error, using is_a( $error, 'XML_Parser_Error' ) |
* - messages can be generated from the xml_parser resource |
* |
* @package XML_Parser |
* @access public |
* @see PEAR_Error |
*/ |
class XML_Parser_Error extends PEAR_Error |
{ |
// {{{ properties |
/** |
* prefix for all messages |
* |
* @var string |
*/ |
var $error_message_prefix = 'XML_Parser: '; |
// }}} |
// {{{ constructor() |
/** |
* construct a new error instance |
* |
* You may either pass a message or an xml_parser resource as first |
* parameter. If a resource has been passed, the last error that |
* happened will be retrieved and returned. |
* |
* @access public |
* @param string|resource message or parser resource |
* @param integer error code |
* @param integer error handling |
* @param integer error level |
*/ |
function XML_Parser_Error($msgorparser = 'unknown error', $code = 0, $mode = PEAR_ERROR_RETURN, $level = E_USER_NOTICE) |
{ |
if (is_resource($msgorparser)) { |
$code = xml_get_error_code($msgorparser); |
$msgorparser = sprintf('%s at XML input line %d:%d', |
xml_error_string($code), |
xml_get_current_line_number($msgorparser), |
xml_get_current_column_number($msgorparser)); |
} |
$this->PEAR_Error($msgorparser, $code, $mode, $level); |
} |
// }}} |
} |
?> |
/trunk/jrest/XML/Feed/Parser.php |
---|
New file |
0,0 → 1,351 |
<?php |
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */ |
/** |
* Key gateway class for XML_Feed_Parser package |
* |
* PHP versions 5 |
* |
* LICENSE: This source file is subject to version 3.0 of the PHP license |
* that is available through the world-wide-web at the following URI: |
* http://www.php.net/license/3_0.txt. If you did not receive a copy of |
* the PHP License and are unable to obtain it through the web, please |
* send a note to license@php.net so we can mail you a copy immediately. |
* |
* @category XML |
* @package XML_Feed_Parser |
* @author James Stewart <james@jystewart.net> |
* @copyright 2005 James Stewart <james@jystewart.net> |
* @license http://www.gnu.org/copyleft/lesser.html GNU LGPL |
* @version CVS: $Id: Parser.php,v 1.2 2007-07-25 15:05:34 jp_milcent Exp $ |
* @link http://pear.php.net/package/XML_Feed_Parser/ |
*/ |
/** |
* XML_Feed_Parser_Type is an abstract class required by all of our |
* feed types. It makes sense to load it here to keep the other files |
* clean. |
*/ |
require_once 'XML/Feed/Parser/Type.php'; |
/** |
* We will throw exceptions when errors occur. |
*/ |
require_once 'XML/Feed/Parser/Exception.php'; |
/** |
* This is the core of the XML_Feed_Parser package. It identifies feed types |
* and abstracts access to them. It is an iterator, allowing for easy access |
* to the entire feed. |
* |
* @author James Stewart <james@jystewart.net> |
* @version Release: 1.0.2 |
* @package XML_Feed_Parser |
*/ |
class XML_Feed_Parser implements Iterator |
{ |
/** |
* This is where we hold the feed object |
* @var Object |
*/ |
private $feed; |
/** |
* To allow for extensions, we make a public reference to the feed model |
* @var DOMDocument |
*/ |
public $model; |
/** |
* A map between entry ID and offset |
* @var array |
*/ |
protected $idMappings = array(); |
/** |
* A storage space for Namespace URIs. |
* @var array |
*/ |
private $feedNamespaces = array( |
'rss2' => array( |
'http://backend.userland.com/rss', |
'http://backend.userland.com/rss2', |
'http://blogs.law.harvard.edu/tech/rss')); |
/** |
* Detects feed types and instantiate appropriate objects. |
* |
* Our constructor takes care of detecting feed types and instantiating |
* appropriate classes. For now we're going to treat Atom 0.3 as Atom 1.0 |
* but raise a warning. I do not intend to introduce full support for |
* Atom 0.3 as it has been deprecated, but others are welcome to. |
* |
* @param string $feed XML serialization of the feed |
* @param bool $strict Whether or not to validate the feed |
* @param bool $suppressWarnings Trigger errors for deprecated feed types? |
* @param bool $tidy Whether or not to try and use the tidy library on input |
*/ |
function __construct($feed, $strict = false, $suppressWarnings = false, $tidy = false) |
{ |
$this->model = new DOMDocument; |
if (! $this->model->loadXML($feed)) { |
if (extension_loaded('tidy') && $tidy) { |
$tidy = new tidy; |
$tidy->parseString($feed, |
array('input-xml' => true, 'output-xml' => true)); |
$tidy->cleanRepair(); |
if (! $this->model->loadXML((string) $tidy)) { |
throw new XML_Feed_Parser_Exception('Invalid input: this is not ' . |
'valid XML'); |
} |
} else { |
throw new XML_Feed_Parser_Exception('Invalid input: this is not valid XML'); |
} |
} |
/* detect feed type */ |
$doc_element = $this->model->documentElement; |
$error = false; |
switch (true) { |
case ($doc_element->namespaceURI == 'http://www.w3.org/2005/Atom'): |
require_once 'XML/Feed/Parser/Atom.php'; |
require_once 'XML/Feed/Parser/AtomElement.php'; |
$class = 'XML_Feed_Parser_Atom'; |
break; |
case ($doc_element->namespaceURI == 'http://purl.org/atom/ns#'): |
require_once 'XML/Feed/Parser/Atom.php'; |
require_once 'XML/Feed/Parser/AtomElement.php'; |
$class = 'XML_Feed_Parser_Atom'; |
$error = 'Atom 0.3 deprecated, using 1.0 parser which won\'t provide ' . |
'all options'; |
break; |
case ($doc_element->namespaceURI == 'http://purl.org/rss/1.0/' || |
($doc_element->hasChildNodes() && $doc_element->childNodes->length > 1 |
&& $doc_element->childNodes->item(1)->namespaceURI == |
'http://purl.org/rss/1.0/')): |
require_once 'XML/Feed/Parser/RSS1.php'; |
require_once 'XML/Feed/Parser/RSS1Element.php'; |
$class = 'XML_Feed_Parser_RSS1'; |
break; |
case ($doc_element->namespaceURI == 'http://purl.org/rss/1.1/' || |
($doc_element->hasChildNodes() && $doc_element->childNodes->length > 1 |
&& $doc_element->childNodes->item(1)->namespaceURI == |
'http://purl.org/rss/1.1/')): |
require_once 'XML/Feed/Parser/RSS11.php'; |
require_once 'XML/Feed/Parser/RSS11Element.php'; |
$class = 'XML_Feed_Parser_RSS11'; |
break; |
case (($doc_element->hasChildNodes() && $doc_element->childNodes->length > 1 |
&& $doc_element->childNodes->item(1)->namespaceURI == |
'http://my.netscape.com/rdf/simple/0.9/') || |
$doc_element->namespaceURI == 'http://my.netscape.com/rdf/simple/0.9/'): |
require_once 'XML/Feed/Parser/RSS09.php'; |
require_once 'XML/Feed/Parser/RSS09Element.php'; |
$class = 'XML_Feed_Parser_RSS09'; |
break; |
case ($doc_element->tagName == 'rss' and |
$doc_element->hasAttribute('version') && |
$doc_element->getAttribute('version') == 0.91): |
$error = 'RSS 0.91 has been superceded by RSS2.0. Using RSS2.0 parser.'; |
require_once 'XML/Feed/Parser/RSS2.php'; |
require_once 'XML/Feed/Parser/RSS2Element.php'; |
$class = 'XML_Feed_Parser_RSS2'; |
break; |
case ($doc_element->tagName == 'rss' and |
$doc_element->hasAttribute('version') && |
$doc_element->getAttribute('version') == 0.92): |
$error = 'RSS 0.92 has been superceded by RSS2.0. Using RSS2.0 parser.'; |
require_once 'XML/Feed/Parser/RSS2.php'; |
require_once 'XML/Feed/Parser/RSS2Element.php'; |
$class = 'XML_Feed_Parser_RSS2'; |
break; |
case (in_array($doc_element->namespaceURI, $this->feedNamespaces['rss2']) |
|| $doc_element->tagName == 'rss'): |
if (! $doc_element->hasAttribute('version') || |
$doc_element->getAttribute('version') != 2) { |
$error = 'RSS version not specified. Parsing as RSS2.0'; |
} |
require_once 'XML/Feed/Parser/RSS2.php'; |
require_once 'XML/Feed/Parser/RSS2Element.php'; |
$class = 'XML_Feed_Parser_RSS2'; |
break; |
default: |
throw new XML_Feed_Parser_Exception('Feed type unknown'); |
break; |
} |
if (! $suppressWarnings && ! empty($error)) { |
trigger_error($error, E_USER_WARNING); |
} |
/* Instantiate feed object */ |
$this->feed = new $class($this->model, $strict); |
} |
/** |
* Proxy to allow feed element names to be used as method names |
* |
* For top-level feed elements we will provide access using methods or |
* attributes. This function simply passes on a request to the appropriate |
* feed type object. |
* |
* @param string $call - the method being called |
* @param array $attributes |
*/ |
function __call($call, $attributes) |
{ |
$attributes = array_pad($attributes, 5, false); |
list($a, $b, $c, $d, $e) = $attributes; |
return $this->feed->$call($a, $b, $c, $d, $e); |
} |
/** |
* Proxy to allow feed element names to be used as attribute names |
* |
* To allow variable-like access to feed-level data we use this |
* method. It simply passes along to __call() which in turn passes |
* along to the relevant object. |
* |
* @param string $val - the name of the variable required |
*/ |
function __get($val) |
{ |
return $this->feed->$val; |
} |
/** |
* Provides iteration functionality. |
* |
* Of course we must be able to iterate... This function simply increases |
* our internal counter. |
*/ |
function next() |
{ |
if (isset($this->current_item) && |
$this->current_item <= $this->feed->numberEntries - 1) { |
++$this->current_item; |
} else if (! isset($this->current_item)) { |
$this->current_item = 0; |
} else { |
return false; |
} |
} |
/** |
* Return XML_Feed_Type object for current element |
* |
* @return XML_Feed_Parser_Type Object |
*/ |
function current() |
{ |
return $this->getEntryByOffset($this->current_item); |
} |
/** |
* For iteration -- returns the key for the current stage in the array. |
* |
* @return int |
*/ |
function key() |
{ |
return $this->current_item; |
} |
/** |
* For iteration -- tells whether we have reached the |
* end. |
* |
* @return bool |
*/ |
function valid() |
{ |
return $this->current_item < $this->feed->numberEntries; |
} |
/** |
* For iteration -- resets the internal counter to the beginning. |
*/ |
function rewind() |
{ |
$this->current_item = 0; |
} |
/** |
* Provides access to entries by ID if one is specified in the source feed. |
* |
* As well as allowing the items to be iterated over we want to allow |
* users to be able to access a specific entry. This is one of two ways of |
* doing that, the other being by offset. This method can be quite slow |
* if dealing with a large feed that hasn't yet been processed as it |
* instantiates objects for every entry until it finds the one needed. |
* |
* @param string $id Valid ID for the given feed format |
* @return XML_Feed_Parser_Type|false |
*/ |
function getEntryById($id) |
{ |
if (isset($this->idMappings[$id])) { |
return $this->getEntryByOffset($this->idMappings[$id]); |
} |
/* |
* Since we have not yet encountered that ID, let's go through all the |
* remaining entries in order till we find it. |
* This is a fairly slow implementation, but it should work. |
*/ |
return $this->feed->getEntryById($id); |
} |
/** |
* Retrieve entry by numeric offset, starting from zero. |
* |
* As well as allowing the items to be iterated over we want to allow |
* users to be able to access a specific entry. This is one of two ways of |
* doing that, the other being by ID. |
* |
* @param int $offset The position of the entry within the feed, starting from 0 |
* @return XML_Feed_Parser_Type|false |
*/ |
function getEntryByOffset($offset) |
{ |
if ($offset < $this->feed->numberEntries) { |
if (isset($this->feed->entries[$offset])) { |
return $this->feed->entries[$offset]; |
} else { |
try { |
$this->feed->getEntryByOffset($offset); |
} catch (Exception $e) { |
return false; |
} |
$id = $this->feed->entries[$offset]->getID(); |
$this->idMappings[$id] = $offset; |
return $this->feed->entries[$offset]; |
} |
} else { |
return false; |
} |
} |
/** |
* Retrieve version details from feed type class. |
* |
* @return void |
* @author James Stewart |
*/ |
function version() |
{ |
return $this->feed->version; |
} |
/** |
* Returns a string representation of the feed. |
* |
* @return String |
**/ |
function __toString() |
{ |
return $this->feed->__toString(); |
} |
} |
?> |
/trunk/jrest/XML/Feed/Parser/RSS1.php |
---|
New file |
0,0 → 1,277 |
<?php |
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */ |
/** |
* RSS1 class for XML_Feed_Parser |
* |
* PHP versions 5 |
* |
* LICENSE: This source file is subject to version 3.0 of the PHP license |
* that is available through the world-wide-web at the following URI: |
* http://www.php.net/license/3_0.txt. If you did not receive a copy of |
* the PHP License and are unable to obtain it through the web, please |
* send a note to license@php.net so we can mail you a copy immediately. |
* |
* @category XML |
* @package XML_Feed_Parser |
* @author James Stewart <james@jystewart.net> |
* @copyright 2005 James Stewart <james@jystewart.net> |
* @license http://www.gnu.org/copyleft/lesser.html GNU LGPL 2.1 |
* @version CVS: $Id: RSS1.php,v 1.2 2007-07-25 15:05:34 jp_milcent Exp $ |
* @link http://pear.php.net/package/XML_Feed_Parser/ |
*/ |
/** |
* This class handles RSS1.0 feeds. |
* |
* @author James Stewart <james@jystewart.net> |
* @version Release: 1.0.2 |
* @package XML_Feed_Parser |
* @todo Find a Relax NG URI we can use |
*/ |
class XML_Feed_Parser_RSS1 extends XML_Feed_Parser_Type |
{ |
/** |
* The URI of the RelaxNG schema used to (optionally) validate the feed |
* @var string |
*/ |
private $relax = 'rss10.rnc'; |
/** |
* We're likely to use XPath, so let's keep it global |
* @var DOMXPath |
*/ |
protected $xpath; |
/** |
* The feed type we are parsing |
* @var string |
*/ |
public $version = 'RSS 1.0'; |
/** |
* The class used to represent individual items |
* @var string |
*/ |
protected $itemClass = 'XML_Feed_Parser_RSS1Element'; |
/** |
* The element containing entries |
* @var string |
*/ |
protected $itemElement = 'item'; |
/** |
* Here we map those elements we're not going to handle individually |
* to the constructs they are. The optional second parameter in the array |
* tells the parser whether to 'fall back' (not apt. at the feed level) or |
* fail if the element is missing. If the parameter is not set, the function |
* will simply return false and leave it to the client to decide what to do. |
* @var array |
*/ |
protected $map = array( |
'title' => array('Text'), |
'link' => array('Text'), |
'description' => array('Text'), |
'image' => array('Image'), |
'textinput' => array('TextInput'), |
'updatePeriod' => array('Text'), |
'updateFrequency' => array('Text'), |
'updateBase' => array('Date'), |
'rights' => array('Text'), # dc:rights |
'description' => array('Text'), # dc:description |
'creator' => array('Text'), # dc:creator |
'publisher' => array('Text'), # dc:publisher |
'contributor' => array('Text'), # dc:contributor |
'date' => array('Date') # dc:contributor |
); |
/** |
* Here we map some elements to their atom equivalents. This is going to be |
* quite tricky to pull off effectively (and some users' methods may vary) |
* but is worth trying. The key is the atom version, the value is RSS2. |
* @var array |
*/ |
protected $compatMap = array( |
'title' => array('title'), |
'link' => array('link'), |
'subtitle' => array('description'), |
'author' => array('creator'), |
'updated' => array('date')); |
/** |
* We will be working with multiple namespaces and it is useful to |
* keep them together |
* @var array |
*/ |
protected $namespaces = array( |
'rdf' => 'http://www.w3.org/1999/02/22-rdf-syntax-ns#', |
'rss' => 'http://purl.org/rss/1.0/', |
'dc' => 'http://purl.org/rss/1.0/modules/dc/', |
'content' => 'http://purl.org/rss/1.0/modules/content/', |
'sy' => 'http://web.resource.org/rss/1.0/modules/syndication/'); |
/** |
* Our constructor does nothing more than its parent. |
* |
* @param DOMDocument $xml A DOM object representing the feed |
* @param bool (optional) $string Whether or not to validate this feed |
*/ |
function __construct(DOMDocument $model, $strict = false) |
{ |
$this->model = $model; |
if ($strict) { |
$validate = $this->model->relaxNGValidate(self::getSchemaDir . |
DIRECTORY_SEPARATOR . $this->relax); |
if (! $validate) { |
throw new XML_Feed_Parser_Exception('Failed required validation'); |
} |
} |
$this->xpath = new DOMXPath($model); |
foreach ($this->namespaces as $key => $value) { |
$this->xpath->registerNamespace($key, $value); |
} |
$this->numberEntries = $this->count('item'); |
} |
/** |
* Allows retrieval of an entry by ID where the rdf:about attribute is used |
* |
* This is not really something that will work with RSS1 as it does not have |
* clear restrictions on the global uniqueness of IDs. We will employ the |
* _very_ hit and miss method of selecting entries based on the rdf:about |
* attribute. If DOMXPath::evaluate is available, we also use that to store |
* a reference to the entry in the array used by getEntryByOffset so that |
* method does not have to seek out the entry if it's requested that way. |
* |
* @param string $id any valid ID. |
* @return XML_Feed_Parser_RSS1Element |
*/ |
function getEntryById($id) |
{ |
if (isset($this->idMappings[$id])) { |
return $this->entries[$this->idMappings[$id]]; |
} |
$entries = $this->xpath->query("//rss:item[@rdf:about='$id']"); |
if ($entries->length > 0) { |
$classname = $this->itemClass; |
$entry = new $classname($entries->item(0), $this); |
if (in_array('evaluate', get_class_methods($this->xpath))) { |
$offset = $this->xpath->evaluate("count(preceding-sibling::rss:item)", $entries->item(0)); |
$this->entries[$offset] = $entry; |
} |
$this->idMappings[$id] = $entry; |
return $entry; |
} |
return false; |
} |
/** |
* Get details of the image associated with the feed. |
* |
* @return array|false an array simply containing the child elements |
*/ |
protected function getImage() |
{ |
$images = $this->model->getElementsByTagName('image'); |
if ($images->length > 0) { |
$image = $images->item(0); |
$details = array(); |
if ($image->hasChildNodes()) { |
$details = array( |
'title' => $image->getElementsByTagName('title')->item(0)->value, |
'link' => $image->getElementsByTagName('link')->item(0)->value, |
'url' => $image->getElementsByTagName('url')->item(0)->value); |
} else { |
$details = array('title' => false, |
'link' => false, |
'url' => $image->attributes->getNamedItem('resource')->nodeValue); |
} |
$details = array_merge($details, array('description' => false, 'height' => false, 'width' => false)); |
if (! empty($details)) { |
return $details; |
} |
} |
return false; |
} |
/** |
* The textinput element is little used, but in the interests of |
* completeness we will support it. |
* |
* @return array|false |
*/ |
protected function getTextInput() |
{ |
$inputs = $this->model->getElementsByTagName('textinput'); |
if ($inputs->length > 0) { |
$input = $inputs->item(0); |
$results = array(); |
$results['title'] = isset( |
$input->getElementsByTagName('title')->item(0)->value) ? |
$input->getElementsByTagName('title')->item(0)->value : null; |
$results['description'] = isset( |
$input->getElementsByTagName('description')->item(0)->value) ? |
$input->getElementsByTagName('description')->item(0)->value : null; |
$results['name'] = isset( |
$input->getElementsByTagName('name')->item(0)->value) ? |
$input->getElementsByTagName('name')->item(0)->value : null; |
$results['link'] = isset( |
$input->getElementsByTagName('link')->item(0)->value) ? |
$input->getElementsByTagName('link')->item(0)->value : null; |
if (empty($results['link']) and |
$input->attributes->getNamedItem('resource')) { |
$results['link'] = |
$input->attributes->getNamedItem('resource')->nodeValue; |
} |
if (! empty($results)) { |
return $results; |
} |
} |
return false; |
} |
/** |
* Employs various techniques to identify the author |
* |
* Dublin Core provides the dc:creator, dc:contributor, and dc:publisher |
* elements for defining authorship in RSS1. We will try each of those in |
* turn in order to simulate the atom author element and will return it |
* as text. |
* |
* @return array|false |
*/ |
function getAuthor() |
{ |
$options = array('creator', 'contributor', 'publisher'); |
foreach ($options as $element) { |
$test = $this->model->getElementsByTagName($element); |
if ($test->length > 0) { |
return $test->item(0)->value; |
} |
} |
return false; |
} |
/** |
* Retrieve a link |
* |
* In RSS1 a link is a text element but in order to ensure that we resolve |
* URLs properly we have a special function for them. |
* |
* @return string |
*/ |
function getLink($offset = 0, $attribute = 'href', $params = false) |
{ |
$links = $this->model->getElementsByTagName('link'); |
if ($links->length <= $offset) { |
return false; |
} |
$link = $links->item($offset); |
return $this->addBase($link->nodeValue, $link); |
} |
} |
?> |
/trunk/jrest/XML/Feed/Parser/RSS11.php |
---|
New file |
0,0 → 1,276 |
<?php |
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */ |
/** |
* RSS1.1 class for XML_Feed_Parser |
* |
* PHP versions 5 |
* |
* LICENSE: This source file is subject to version 3.0 of the PHP license |
* that is available through the world-wide-web at the following URI: |
* http://www.php.net/license/3_0.txt. If you did not receive a copy of |
* the PHP License and are unable to obtain it through the web, please |
* send a note to license@php.net so we can mail you a copy immediately. |
* |
* @category XML |
* @package XML_Feed_Parser |
* @author James Stewart <james@jystewart.net> |
* @copyright 2005 James Stewart <james@jystewart.net> |
* @license http://www.gnu.org/copyleft/lesser.html GNU LGPL 2.1 |
* @version CVS: $Id: RSS11.php,v 1.2 2007-07-25 15:05:34 jp_milcent Exp $ |
* @link http://pear.php.net/package/XML_Feed_Parser/ |
*/ |
/** |
* This class handles RSS1.1 feeds. RSS1.1 is documented at: |
* http://inamidst.com/rss1.1/ |
* |
* @author James Stewart <james@jystewart.net> |
* @version Release: 1.0.2 |
* @package XML_Feed_Parser |
* @todo Support for RDF:List |
* @todo Ensure xml:lang is accessible to users |
*/ |
class XML_Feed_Parser_RSS11 extends XML_Feed_Parser_Type |
{ |
/** |
* The URI of the RelaxNG schema used to (optionally) validate the feed |
* @var string |
*/ |
private $relax = 'rss11.rnc'; |
/** |
* We're likely to use XPath, so let's keep it global |
* @var DOMXPath |
*/ |
protected $xpath; |
/** |
* The feed type we are parsing |
* @var string |
*/ |
public $version = 'RSS 1.0'; |
/** |
* The class used to represent individual items |
* @var string |
*/ |
protected $itemClass = 'XML_Feed_Parser_RSS1Element'; |
/** |
* The element containing entries |
* @var string |
*/ |
protected $itemElement = 'item'; |
/** |
* Here we map those elements we're not going to handle individually |
* to the constructs they are. The optional second parameter in the array |
* tells the parser whether to 'fall back' (not apt. at the feed level) or |
* fail if the element is missing. If the parameter is not set, the function |
* will simply return false and leave it to the client to decide what to do. |
* @var array |
*/ |
protected $map = array( |
'title' => array('Text'), |
'link' => array('Text'), |
'description' => array('Text'), |
'image' => array('Image'), |
'updatePeriod' => array('Text'), |
'updateFrequency' => array('Text'), |
'updateBase' => array('Date'), |
'rights' => array('Text'), # dc:rights |
'description' => array('Text'), # dc:description |
'creator' => array('Text'), # dc:creator |
'publisher' => array('Text'), # dc:publisher |
'contributor' => array('Text'), # dc:contributor |
'date' => array('Date') # dc:contributor |
); |
/** |
* Here we map some elements to their atom equivalents. This is going to be |
* quite tricky to pull off effectively (and some users' methods may vary) |
* but is worth trying. The key is the atom version, the value is RSS2. |
* @var array |
*/ |
protected $compatMap = array( |
'title' => array('title'), |
'link' => array('link'), |
'subtitle' => array('description'), |
'author' => array('creator'), |
'updated' => array('date')); |
/** |
* We will be working with multiple namespaces and it is useful to |
* keep them together. We will retain support for some common RSS1.0 modules |
* @var array |
*/ |
protected $namespaces = array( |
'rdf' => 'http://www.w3.org/1999/02/22-rdf-syntax-ns#', |
'rss' => 'http://purl.org/net/rss1.1#', |
'dc' => 'http://purl.org/rss/1.0/modules/dc/', |
'content' => 'http://purl.org/rss/1.0/modules/content/', |
'sy' => 'http://web.resource.org/rss/1.0/modules/syndication/'); |
/** |
* Our constructor does nothing more than its parent. |
* |
* @param DOMDocument $xml A DOM object representing the feed |
* @param bool (optional) $string Whether or not to validate this feed |
*/ |
function __construct(DOMDocument $model, $strict = false) |
{ |
$this->model = $model; |
if ($strict) { |
$validate = $this->model->relaxNGValidate(self::getSchemaDir . |
DIRECTORY_SEPARATOR . $this->relax); |
if (! $validate) { |
throw new XML_Feed_Parser_Exception('Failed required validation'); |
} |
} |
$this->xpath = new DOMXPath($model); |
foreach ($this->namespaces as $key => $value) { |
$this->xpath->registerNamespace($key, $value); |
} |
$this->numberEntries = $this->count('item'); |
} |
/** |
* Attempts to identify an element by ID given by the rdf:about attribute |
* |
* This is not really something that will work with RSS1.1 as it does not have |
* clear restrictions on the global uniqueness of IDs. We will employ the |
* _very_ hit and miss method of selecting entries based on the rdf:about |
* attribute. Please note that this is even more hit and miss with RSS1.1 than |
* with RSS1.0 since RSS1.1 does not require the rdf:about attribute for items. |
* |
* @param string $id any valid ID. |
* @return XML_Feed_Parser_RSS1Element |
*/ |
function getEntryById($id) |
{ |
if (isset($this->idMappings[$id])) { |
return $this->entries[$this->idMappings[$id]]; |
} |
$entries = $this->xpath->query("//rss:item[@rdf:about='$id']"); |
if ($entries->length > 0) { |
$classname = $this->itemClass; |
$entry = new $classname($entries->item(0), $this); |
return $entry; |
} |
return false; |
} |
/** |
* Get details of the image associated with the feed. |
* |
* @return array|false an array simply containing the child elements |
*/ |
protected function getImage() |
{ |
$images = $this->model->getElementsByTagName('image'); |
if ($images->length > 0) { |
$image = $images->item(0); |
$details = array(); |
if ($image->hasChildNodes()) { |
$details = array( |
'title' => $image->getElementsByTagName('title')->item(0)->value, |
'url' => $image->getElementsByTagName('url')->item(0)->value); |
if ($image->getElementsByTagName('link')->length > 0) { |
$details['link'] = |
$image->getElementsByTagName('link')->item(0)->value; |
} |
} else { |
$details = array('title' => false, |
'link' => false, |
'url' => $image->attributes->getNamedItem('resource')->nodeValue); |
} |
$details = array_merge($details, |
array('description' => false, 'height' => false, 'width' => false)); |
if (! empty($details)) { |
return $details; |
} |
} |
return false; |
} |
/** |
* The textinput element is little used, but in the interests of |
* completeness we will support it. |
* |
* @return array|false |
*/ |
protected function getTextInput() |
{ |
$inputs = $this->model->getElementsByTagName('textinput'); |
if ($inputs->length > 0) { |
$input = $inputs->item(0); |
$results = array(); |
$results['title'] = isset( |
$input->getElementsByTagName('title')->item(0)->value) ? |
$input->getElementsByTagName('title')->item(0)->value : null; |
$results['description'] = isset( |
$input->getElementsByTagName('description')->item(0)->value) ? |
$input->getElementsByTagName('description')->item(0)->value : null; |
$results['name'] = isset( |
$input->getElementsByTagName('name')->item(0)->value) ? |
$input->getElementsByTagName('name')->item(0)->value : null; |
$results['link'] = isset( |
$input->getElementsByTagName('link')->item(0)->value) ? |
$input->getElementsByTagName('link')->item(0)->value : null; |
if (empty($results['link']) and |
$input->attributes->getNamedItem('resource')) { |
$results['link'] = $input->attributes->getNamedItem('resource')->nodeValue; |
} |
if (! empty($results)) { |
return $results; |
} |
} |
return false; |
} |
/** |
* Attempts to discern authorship |
* |
* Dublin Core provides the dc:creator, dc:contributor, and dc:publisher |
* elements for defining authorship in RSS1. We will try each of those in |
* turn in order to simulate the atom author element and will return it |
* as text. |
* |
* @return array|false |
*/ |
function getAuthor() |
{ |
$options = array('creator', 'contributor', 'publisher'); |
foreach ($options as $element) { |
$test = $this->model->getElementsByTagName($element); |
if ($test->length > 0) { |
return $test->item(0)->value; |
} |
} |
return false; |
} |
/** |
* Retrieve a link |
* |
* In RSS1 a link is a text element but in order to ensure that we resolve |
* URLs properly we have a special function for them. |
* |
* @return string |
*/ |
function getLink($offset = 0, $attribute = 'href', $params = false) |
{ |
$links = $this->model->getElementsByTagName('link'); |
if ($links->length <= $offset) { |
return false; |
} |
$link = $links->item($offset); |
return $this->addBase($link->nodeValue, $link); |
} |
} |
?> |
/trunk/jrest/XML/Feed/Parser/RSS2.php |
---|
New file |
0,0 → 1,334 |
<?php |
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */ |
/** |
* Class representing feed-level data for an RSS2 feed |
* |
* PHP versions 5 |
* |
* LICENSE: This source file is subject to version 3.0 of the PHP license |
* that is available through the world-wide-web at the following URI: |
* http://www.php.net/license/3_0.txt. If you did not receive a copy of |
* the PHP License and are unable to obtain it through the web, please |
* send a note to license@php.net so we can mail you a copy immediately. |
* |
* @category XML |
* @package XML_Feed_Parser |
* @author James Stewart <james@jystewart.net> |
* @copyright 2005 James Stewart <james@jystewart.net> |
* @license http://www.gnu.org/copyleft/lesser.html GNU LGPL 2.1 |
* @version CVS: $Id: RSS2.php,v 1.2 2007-07-25 15:05:34 jp_milcent Exp $ |
* @link http://pear.php.net/package/XML_Feed_Parser/ |
*/ |
/** |
* This class handles RSS2 feeds. |
* |
* @author James Stewart <james@jystewart.net> |
* @version Release: 1.0.2 |
* @package XML_Feed_Parser |
*/ |
class XML_Feed_Parser_RSS2 extends XML_Feed_Parser_Type |
{ |
/** |
* The URI of the RelaxNG schema used to (optionally) validate the feed |
* @var string |
*/ |
private $relax = 'rss20.rnc'; |
/** |
* We're likely to use XPath, so let's keep it global |
* @var DOMXPath |
*/ |
protected $xpath; |
/** |
* The feed type we are parsing |
* @var string |
*/ |
public $version = 'RSS 2.0'; |
/** |
* The class used to represent individual items |
* @var string |
*/ |
protected $itemClass = 'XML_Feed_Parser_RSS2Element'; |
/** |
* The element containing entries |
* @var string |
*/ |
protected $itemElement = 'item'; |
/** |
* Here we map those elements we're not going to handle individually |
* to the constructs they are. The optional second parameter in the array |
* tells the parser whether to 'fall back' (not apt. at the feed level) or |
* fail if the element is missing. If the parameter is not set, the function |
* will simply return false and leave it to the client to decide what to do. |
* @var array |
*/ |
protected $map = array( |
'ttl' => array('Text'), |
'pubDate' => array('Date'), |
'lastBuildDate' => array('Date'), |
'title' => array('Text'), |
'link' => array('Link'), |
'description' => array('Text'), |
'language' => array('Text'), |
'copyright' => array('Text'), |
'managingEditor' => array('Text'), |
'webMaster' => array('Text'), |
'category' => array('Text'), |
'generator' => array('Text'), |
'docs' => array('Text'), |
'ttl' => array('Text'), |
'image' => array('Image'), |
'skipDays' => array('skipDays'), |
'skipHours' => array('skipHours')); |
/** |
* Here we map some elements to their atom equivalents. This is going to be |
* quite tricky to pull off effectively (and some users' methods may vary) |
* but is worth trying. The key is the atom version, the value is RSS2. |
* @var array |
*/ |
protected $compatMap = array( |
'title' => array('title'), |
'rights' => array('copyright'), |
'updated' => array('lastBuildDate'), |
'subtitle' => array('description'), |
'date' => array('pubDate'), |
'author' => array('managingEditor')); |
protected $namespaces = array( |
'dc' => 'http://purl.org/rss/1.0/modules/dc/', |
'content' => 'http://purl.org/rss/1.0/modules/content/'); |
/** |
* Our constructor does nothing more than its parent. |
* |
* @param DOMDocument $xml A DOM object representing the feed |
* @param bool (optional) $string Whether or not to validate this feed |
*/ |
function __construct(DOMDocument $model, $strict = false) |
{ |
$this->model = $model; |
if ($strict) { |
if (! $this->model->relaxNGValidate($this->relax)) { |
throw new XML_Feed_Parser_Exception('Failed required validation'); |
} |
} |
$this->xpath = new DOMXPath($this->model); |
foreach ($this->namespaces as $key => $value) { |
$this->xpath->registerNamespace($key, $value); |
} |
$this->numberEntries = $this->count('item'); |
} |
/** |
* Retrieves an entry by ID, if the ID is specified with the guid element |
* |
* This is not really something that will work with RSS2 as it does not have |
* clear restrictions on the global uniqueness of IDs. But we can emulate |
* it by allowing access based on the 'guid' element. If DOMXPath::evaluate |
* is available, we also use that to store a reference to the entry in the array |
* used by getEntryByOffset so that method does not have to seek out the entry |
* if it's requested that way. |
* |
* @param string $id any valid ID. |
* @return XML_Feed_Parser_RSS2Element |
*/ |
function getEntryById($id) |
{ |
if (isset($this->idMappings[$id])) { |
return $this->entries[$this->idMappings[$id]]; |
} |
$entries = $this->xpath->query("//item[guid='$id']"); |
if ($entries->length > 0) { |
$entry = new $this->itemElement($entries->item(0), $this); |
if (in_array('evaluate', get_class_methods($this->xpath))) { |
$offset = $this->xpath->evaluate("count(preceding-sibling::item)", $entries->item(0)); |
$this->entries[$offset] = $entry; |
} |
$this->idMappings[$id] = $entry; |
return $entry; |
} |
} |
/** |
* Get a category from the element |
* |
* The category element is a simple text construct which can occur any number |
* of times. We allow access by offset or access to an array of results. |
* |
* @param string $call for compatibility with our overloading |
* @param array $arguments - arg 0 is the offset, arg 1 is whether to return as array |
* @return string|array|false |
*/ |
function getCategory($call, $arguments = array()) |
{ |
$categories = $this->model->getElementsByTagName('category'); |
$offset = empty($arguments[0]) ? 0 : $arguments[0]; |
$array = empty($arguments[1]) ? false : true; |
if ($categories->length <= $offset) { |
return false; |
} |
if ($array) { |
$list = array(); |
foreach ($categories as $category) { |
array_push($list, $category->nodeValue); |
} |
return $list; |
} |
return $categories->item($offset)->nodeValue; |
} |
/** |
* Get details of the image associated with the feed. |
* |
* @return array|false an array simply containing the child elements |
*/ |
protected function getImage() |
{ |
$images = $this->model->getElementsByTagName('image'); |
if ($images->length > 0) { |
$image = $images->item(0); |
$desc = $image->getElementsByTagName('description'); |
$description = $desc->length ? $desc->item(0)->nodeValue : false; |
$heigh = $image->getElementsByTagName('height'); |
$height = $heigh->length ? $heigh->item(0)->nodeValue : false; |
$widt = $image->getElementsByTagName('width'); |
$width = $widt->length ? $widt->item(0)->nodeValue : false; |
return array( |
'title' => $image->getElementsByTagName('title')->item(0)->nodeValue, |
'link' => $image->getElementsByTagName('link')->item(0)->nodeValue, |
'url' => $image->getElementsByTagName('url')->item(0)->nodeValue, |
'description' => $description, |
'height' => $height, |
'width' => $width); |
} |
return false; |
} |
/** |
* The textinput element is little used, but in the interests of |
* completeness... |
* |
* @return array|false |
*/ |
function getTextInput() |
{ |
$inputs = $this->model->getElementsByTagName('input'); |
if ($inputs->length > 0) { |
$input = $inputs->item(0); |
return array( |
'title' => $input->getElementsByTagName('title')->item(0)->value, |
'description' => |
$input->getElementsByTagName('description')->item(0)->value, |
'name' => $input->getElementsByTagName('name')->item(0)->value, |
'link' => $input->getElementsByTagName('link')->item(0)->value); |
} |
return false; |
} |
/** |
* Utility function for getSkipDays and getSkipHours |
* |
* This is a general function used by both getSkipDays and getSkipHours. It simply |
* returns an array of the values of the children of the appropriate tag. |
* |
* @param string $tagName The tag name (getSkipDays or getSkipHours) |
* @return array|false |
*/ |
protected function getSkips($tagName) |
{ |
$hours = $this->model->getElementsByTagName($tagName); |
if ($hours->length == 0) { |
return false; |
} |
$skipHours = array(); |
foreach($hours->item(0)->childNodes as $hour) { |
if ($hour instanceof DOMElement) { |
array_push($skipHours, $hour->nodeValue); |
} |
} |
return $skipHours; |
} |
/** |
* Retrieve skipHours data |
* |
* The skiphours element provides a list of hours on which this feed should |
* not be checked. We return an array of those hours (integers, 24 hour clock) |
* |
* @return array |
*/ |
function getSkipHours() |
{ |
return $this->getSkips('skipHours'); |
} |
/** |
* Retrieve skipDays data |
* |
* The skipdays element provides a list of days on which this feed should |
* not be checked. We return an array of those days. |
* |
* @return array |
*/ |
function getSkipDays() |
{ |
return $this->getSkips('skipDays'); |
} |
/** |
* Return content of the little-used 'cloud' element |
* |
* The cloud element is rarely used. It is designed to provide some details |
* of a location to update the feed. |
* |
* @return array an array of the attributes of the element |
*/ |
function getCloud() |
{ |
$cloud = $this->model->getElementsByTagName('cloud'); |
if ($cloud->length == 0) { |
return false; |
} |
$cloudData = array(); |
foreach ($cloud->item(0)->attributes as $attribute) { |
$cloudData[$attribute->name] = $attribute->value; |
} |
return $cloudData; |
} |
/** |
* Get link URL |
* |
* In RSS2 a link is a text element but in order to ensure that we resolve |
* URLs properly we have a special function for them. We maintain the |
* parameter used by the atom getLink method, though we only use the offset |
* parameter. |
* |
* @param int $offset The position of the link within the feed. Starts from 0 |
* @param string $attribute The attribute of the link element required |
* @param array $params An array of other parameters. Not used. |
* @return string |
*/ |
function getLink($offset, $attribute = 'href', $params = array()) |
{ |
$links = $this->model->getElementsByTagName('link'); |
if ($links->length <= $offset) { |
return false; |
} |
$link = $links->item($offset); |
return $this->addBase($link->nodeValue, $link); |
} |
} |
?> |
/trunk/jrest/XML/Feed/Parser/AtomElement.php |
---|
New file |
0,0 → 1,261 |
<?php |
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */ |
/** |
* AtomElement class for XML_Feed_Parser package |
* |
* PHP versions 5 |
* |
* LICENSE: This source file is subject to version 3.0 of the PHP license |
* that is available through the world-wide-web at the following URI: |
* http://www.php.net/license/3_0.txt. If you did not receive a copy of |
* the PHP License and are unable to obtain it through the web, please |
* send a note to license@php.net so we can mail you a copy immediately. |
* |
* @category XML |
* @package XML_Feed_Parser |
* @author James Stewart <james@jystewart.net> |
* @copyright 2005 James Stewart <james@jystewart.net> |
* @license http://www.gnu.org/copyleft/lesser.html GNU LGPL 2.1 |
* @version CVS: $Id: AtomElement.php,v 1.2 2007-07-25 15:05:34 jp_milcent Exp $ |
* @link http://pear.php.net/package/XML_Feed_Parser/ |
*/ |
/** |
* This class provides support for atom entries. It will usually be called by |
* XML_Feed_Parser_Atom with which it shares many methods. |
* |
* @author James Stewart <james@jystewart.net> |
* @version Release: 1.0.2 |
* @package XML_Feed_Parser |
*/ |
class XML_Feed_Parser_AtomElement extends XML_Feed_Parser_Atom |
{ |
/** |
* This will be a reference to the parent object for when we want |
* to use a 'fallback' rule |
* @var XML_Feed_Parser_Atom |
*/ |
protected $parent; |
/** |
* When performing XPath queries we will use this prefix |
* @var string |
*/ |
private $xpathPrefix = ''; |
/** |
* xml:base values inherited by the element |
* @var string |
*/ |
protected $xmlBase; |
/** |
* Here we provide a few mappings for those very special circumstances in |
* which it makes sense to map back to the RSS2 spec or to manage other |
* compatibilities (eg. with the Univeral Feed Parser). Key is the other version's |
* name for the command, value is an array consisting of the equivalent in our atom |
* api and any attributes needed to make the mapping. |
* @var array |
*/ |
protected $compatMap = array( |
'guid' => array('id'), |
'links' => array('link'), |
'tags' => array('category'), |
'contributors' => array('contributor')); |
/** |
* Our specific element map |
* @var array |
*/ |
protected $map = array( |
'author' => array('Person', 'fallback'), |
'contributor' => array('Person'), |
'id' => array('Text', 'fail'), |
'published' => array('Date'), |
'updated' => array('Date', 'fail'), |
'title' => array('Text', 'fail'), |
'rights' => array('Text', 'fallback'), |
'summary' => array('Text'), |
'content' => array('Content'), |
'link' => array('Link'), |
'enclosure' => array('Enclosure'), |
'category' => array('Category')); |
/** |
* Store useful information for later. |
* |
* @param DOMElement $element - this item as a DOM element |
* @param XML_Feed_Parser_Atom $parent - the feed of which this is a member |
*/ |
function __construct(DOMElement $element, $parent, $xmlBase = '') |
{ |
$this->model = $element; |
$this->parent = $parent; |
$this->xmlBase = $xmlBase; |
$this->xpathPrefix = "//atom:entry[atom:id='" . $this->id . "']/"; |
$this->xpath = $this->parent->xpath; |
} |
/** |
* Provides access to specific aspects of the author data for an atom entry |
* |
* Author data at the entry level is more complex than at the feed level. |
* If atom:author is not present for the entry we need to look for it in |
* an atom:source child of the atom:entry. If it's not there either, then |
* we look to the parent for data. |
* |
* @param array |
* @return string |
*/ |
function getAuthor($arguments) |
{ |
/* Find out which part of the author data we're looking for */ |
if (isset($arguments['param'])) { |
$parameter = $arguments['param']; |
} else { |
$parameter = 'name'; |
} |
$test = $this->model->getElementsByTagName('author'); |
if ($test->length > 0) { |
$item = $test->item(0); |
return $item->getElementsByTagName($parameter)->item(0)->nodeValue; |
} |
$source = $this->model->getElementsByTagName('source'); |
if ($source->length > 0) { |
$test = $this->model->getElementsByTagName('author'); |
if ($test->length > 0) { |
$item = $test->item(0); |
return $item->getElementsByTagName($parameter)->item(0)->nodeValue; |
} |
} |
return $this->parent->getAuthor($arguments); |
} |
/** |
* Returns the content of the content element or info on a specific attribute |
* |
* This element may or may not be present. It cannot be present more than |
* once. It may have a 'src' attribute, in which case there's no content |
* If not present, then the entry must have link with rel="alternate". |
* If there is content we return it, if not and there's a 'src' attribute |
* we return the value of that instead. The method can take an 'attribute' |
* argument, in which case we return the value of that attribute if present. |
* eg. $item->content("type") will return the type of the content. It is |
* recommended that all users check the type before getting the content to |
* ensure that their script is capable of handling the type of returned data. |
* (data carried in the content element can be either 'text', 'html', 'xhtml', |
* or any standard MIME type). |
* |
* @return string|false |
*/ |
protected function getContent($method, $arguments = array()) |
{ |
$attribute = empty($arguments[0]) ? false : $arguments[0]; |
$tags = $this->model->getElementsByTagName('content'); |
if ($tags->length == 0) { |
return false; |
} |
$content = $tags->item(0); |
if (! $content->hasAttribute('type')) { |
$content->setAttribute('type', 'text'); |
} |
if (! empty($attribute)) { |
return $content->getAttribute($attribute); |
} |
$type = $content->getAttribute('type'); |
if (! empty($attribute)) { |
if ($content->hasAttribute($attribute)) |
{ |
return $content->getAttribute($attribute); |
} |
return false; |
} |
if ($content->hasAttribute('src')) { |
return $content->getAttribute('src'); |
} |
return $this->parseTextConstruct($content); |
} |
/** |
* For compatibility, this method provides a mapping to access enclosures. |
* |
* The Atom spec doesn't provide for an enclosure element, but it is |
* generally supported using the link element with rel='enclosure'. |
* |
* @param string $method - for compatibility with our __call usage |
* @param array $arguments - for compatibility with our __call usage |
* @return array|false |
*/ |
function getEnclosure($method, $arguments = array()) |
{ |
$offset = isset($arguments[0]) ? $arguments[0] : 0; |
$query = "//atom:entry[atom:id='" . $this->getText('id', false) . |
"']/atom:link[@rel='enclosure']"; |
$encs = $this->parent->xpath->query($query); |
if ($encs->length > $offset) { |
try { |
if (! $encs->item($offset)->hasAttribute('href')) { |
return false; |
} |
$attrs = $encs->item($offset)->attributes; |
$length = $encs->item($offset)->hasAttribute('length') ? |
$encs->item($offset)->getAttribute('length') : false; |
return array( |
'url' => $attrs->getNamedItem('href')->value, |
'type' => $attrs->getNamedItem('type')->value, |
'length' => $length); |
} catch (Exception $e) { |
return false; |
} |
} |
return false; |
} |
/** |
* Get details of this entry's source, if available/relevant |
* |
* Where an atom:entry is taken from another feed then the aggregator |
* is supposed to include an atom:source element which replicates at least |
* the atom:id, atom:title, and atom:updated metadata from the original |
* feed. Atom:source therefore has a very similar structure to atom:feed |
* and if we find it we will return it as an XML_Feed_Parser_Atom object. |
* |
* @return XML_Feed_Parser_Atom|false |
*/ |
function getSource() |
{ |
$test = $this->model->getElementsByTagName('source'); |
if ($test->length == 0) { |
return false; |
} |
$source = new XML_Feed_Parser_Atom($test->item(0)); |
} |
/** |
* Get the entry as an XML string |
* |
* Return an XML serialization of the feed, should it be required. Most |
* users however, will already have a serialization that they used when |
* instantiating the object. |
* |
* @return string XML serialization of element |
*/ |
function __toString() |
{ |
$simple = simplexml_import_dom($this->model); |
return $simple->asXML(); |
} |
} |
?> |
/trunk/jrest/XML/Feed/Parser/RSS09Element.php |
---|
New file |
0,0 → 1,62 |
<?php |
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */ |
/** |
* RSS0.9 Element class for XML_Feed_Parser |
* |
* PHP versions 5 |
* |
* LICENSE: This source file is subject to version 3.0 of the PHP license |
* that is available through the world-wide-web at the following URI: |
* http://www.php.net/license/3_0.txt. If you did not receive a copy of |
* the PHP License and are unable to obtain it through the web, please |
* send a note to license@php.net so we can mail you a copy immediately. |
* |
* @category XML |
* @package XML_Feed_Parser |
* @author James Stewart <james@jystewart.net> |
* @copyright 2005 James Stewart <james@jystewart.net> |
* @license http://www.gnu.org/copyleft/lesser.html GNU LGPL 2.1 |
* @version CVS: $Id: RSS09Element.php,v 1.2 2007-07-25 15:05:34 jp_milcent Exp $ |
* @link http://pear.php.net/package/XML_Feed_Parser/ |
*/ |
/* |
* This class provides support for RSS 0.9 entries. It will usually be called by |
* XML_Feed_Parser_RSS09 with which it shares many methods. |
* |
* @author James Stewart <james@jystewart.net> |
* @version Release: 1.0.2 |
* @package XML_Feed_Parser |
*/ |
class XML_Feed_Parser_RSS09Element extends XML_Feed_Parser_RSS09 |
{ |
/** |
* This will be a reference to the parent object for when we want |
* to use a 'fallback' rule |
* @var XML_Feed_Parser_RSS09 |
*/ |
protected $parent; |
/** |
* Our specific element map |
* @var array |
*/ |
protected $map = array( |
'title' => array('Text'), |
'link' => array('Link')); |
/** |
* Store useful information for later. |
* |
* @param DOMElement $element - this item as a DOM element |
* @param XML_Feed_Parser_RSS1 $parent - the feed of which this is a member |
*/ |
function __construct(DOMElement $element, $parent, $xmlBase = '') |
{ |
$this->model = $element; |
$this->parent = $parent; |
} |
} |
?> |
/trunk/jrest/XML/Feed/Parser/Exception.php |
---|
New file |
0,0 → 1,42 |
<?php |
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */ |
/** |
* Keeps the exception class for XML_Feed_Parser. |
* |
* PHP versions 5 |
* |
* LICENSE: This source file is subject to version 3.0 of the PHP license |
* that is available through the world-wide-web at the following URI: |
* http://www.php.net/license/3_0.txt. If you did not receive a copy of |
* the PHP License and are unable to obtain it through the web, please |
* send a note to license@php.net so we can mail you a copy immediately. |
* |
* @category XML |
* @package XML_Feed_Parser |
* @author James Stewart <james@jystewart.net> |
* @copyright 2005 James Stewart <james@jystewart.net> |
* @license http://www.gnu.org/copyleft/lesser.html GNU LGPL |
* @version CVS: $Id: Exception.php,v 1.2 2007-07-25 15:05:34 jp_milcent Exp $ |
* @link http://pear.php.net/package/XML_Feed_Parser/ |
*/ |
/** |
* We are extending PEAR_Exception |
*/ |
require_once 'PEAR/Exception.php'; |
/** |
* XML_Feed_Parser_Exception is a simple extension of PEAR_Exception, existing |
* to help with identification of the source of exceptions. |
* |
* @author James Stewart <james@jystewart.net> |
* @version Release: 1.0.2 |
* @package XML_Feed_Parser |
*/ |
class XML_Feed_Parser_Exception extends PEAR_Exception |
{ |
} |
?> |
/trunk/jrest/XML/Feed/Parser/Atom.php |
---|
New file |
0,0 → 1,365 |
<?php |
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */ |
/** |
* Atom feed class for XML_Feed_Parser |
* |
* PHP versions 5 |
* |
* LICENSE: This source file is subject to version 3.0 of the PHP license |
* that is available through the world-wide-web at the following URI: |
* http://www.php.net/license/3_0.txt. If you did not receive a copy of |
* the PHP License and are unable to obtain it through the web, please |
* send a note to license@php.net so we can mail you a copy immediately. |
* |
* @category XML |
* @package XML_Feed_Parser |
* @author James Stewart <james@jystewart.net> |
* @copyright 2005 James Stewart <james@jystewart.net> |
* @license http://www.gnu.org/copyleft/lesser.html GNU LGPL 2.1 |
* @version CVS: $Id: Atom.php,v 1.2 2007-07-25 15:05:34 jp_milcent Exp $ |
* @link http://pear.php.net/package/XML_Feed_Parser/ |
*/ |
/** |
* This is the class that determines how we manage Atom 1.0 feeds |
* |
* How we deal with constructs: |
* date - return as unix datetime for use with the 'date' function unless specified otherwise |
* text - return as is. optional parameter will give access to attributes |
* person - defaults to name, but parameter based access |
* |
* @author James Stewart <james@jystewart.net> |
* @version Release: 1.0.2 |
* @package XML_Feed_Parser |
*/ |
class XML_Feed_Parser_Atom extends XML_Feed_Parser_Type |
{ |
/** |
* The URI of the RelaxNG schema used to (optionally) validate the feed |
* @var string |
*/ |
private $relax = 'atom.rnc'; |
/** |
* We're likely to use XPath, so let's keep it global |
* @var DOMXPath |
*/ |
public $xpath; |
/** |
* When performing XPath queries we will use this prefix |
* @var string |
*/ |
private $xpathPrefix = '//'; |
/** |
* The feed type we are parsing |
* @var string |
*/ |
public $version = 'Atom 1.0'; |
/** |
* The class used to represent individual items |
* @var string |
*/ |
protected $itemClass = 'XML_Feed_Parser_AtomElement'; |
/** |
* The element containing entries |
* @var string |
*/ |
protected $itemElement = 'entry'; |
/** |
* Here we map those elements we're not going to handle individually |
* to the constructs they are. The optional second parameter in the array |
* tells the parser whether to 'fall back' (not apt. at the feed level) or |
* fail if the element is missing. If the parameter is not set, the function |
* will simply return false and leave it to the client to decide what to do. |
* @var array |
*/ |
protected $map = array( |
'author' => array('Person'), |
'contributor' => array('Person'), |
'icon' => array('Text'), |
'logo' => array('Text'), |
'id' => array('Text', 'fail'), |
'rights' => array('Text'), |
'subtitle' => array('Text'), |
'title' => array('Text', 'fail'), |
'updated' => array('Date', 'fail'), |
'link' => array('Link'), |
'generator' => array('Text'), |
'category' => array('Category')); |
/** |
* Here we provide a few mappings for those very special circumstances in |
* which it makes sense to map back to the RSS2 spec. Key is RSS2 version |
* value is an array consisting of the equivalent in atom and any attributes |
* needed to make the mapping. |
* @var array |
*/ |
protected $compatMap = array( |
'guid' => array('id'), |
'links' => array('link'), |
'tags' => array('category'), |
'contributors' => array('contributor')); |
/** |
* Our constructor does nothing more than its parent. |
* |
* @param DOMDocument $xml A DOM object representing the feed |
* @param bool (optional) $string Whether or not to validate this feed |
*/ |
function __construct(DOMDocument $model, $strict = false) |
{ |
$this->model = $model; |
if ($strict) { |
if (! $this->model->relaxNGValidateSource($this->relax)) { |
throw new XML_Feed_Parser_Exception('Failed required validation'); |
} |
} |
$this->xpath = new DOMXPath($this->model); |
$this->xpath->registerNamespace('atom', 'http://www.w3.org/2005/Atom'); |
$this->numberEntries = $this->count('entry'); |
} |
/** |
* Implement retrieval of an entry based on its ID for atom feeds. |
* |
* This function uses XPath to get the entry based on its ID. If DOMXPath::evaluate |
* is available, we also use that to store a reference to the entry in the array |
* used by getEntryByOffset so that method does not have to seek out the entry |
* if it's requested that way. |
* |
* @param string $id any valid Atom ID. |
* @return XML_Feed_Parser_AtomElement |
*/ |
function getEntryById($id) |
{ |
if (isset($this->idMappings[$id])) { |
return $this->entries[$this->idMappings[$id]]; |
} |
$entries = $this->xpath->query("//atom:entry[atom:id='$id']"); |
if ($entries->length > 0) { |
$xmlBase = $entries->item(0)->baseURI; |
$entry = new $this->itemElement($entries->item(0), $this, $xmlBase); |
if (in_array('evaluate', get_class_methods($this->xpath))) { |
$offset = $this->xpath->evaluate("count(preceding-sibling::atom:entry)", $entries->item(0)); |
$this->entries[$offset] = $entry; |
} |
$this->idMappings[$id] = $entry; |
return $entry; |
} |
} |
/** |
* Retrieves data from a person construct. |
* |
* Get a person construct. We default to the 'name' element but allow |
* access to any of the elements. |
* |
* @param string $method The name of the person construct we want |
* @param array $arguments An array which we hope gives a 'param' |
* @return string|false |
*/ |
protected function getPerson($method, $arguments) |
{ |
$offset = empty($arguments[0]) ? 0 : $arguments[0]; |
$parameter = empty($arguments[1]['param']) ? 'name' : $arguments[1]['param']; |
$section = $this->model->getElementsByTagName($method); |
if ($parameter == 'url') { |
$parameter = 'uri'; |
} |
if ($section->length <= $offset) { |
return false; |
} |
$param = $section->item($offset)->getElementsByTagName($parameter); |
if ($param->length == 0) { |
return false; |
} |
return $param->item(0)->nodeValue; |
} |
/** |
* Retrieves an element's content where that content is a text construct. |
* |
* Get a text construct. When calling this method, the two arguments |
* allowed are 'offset' and 'attribute', so $parser->subtitle() would |
* return the content of the element, while $parser->subtitle(false, 'type') |
* would return the value of the type attribute. |
* |
* @todo Clarify overlap with getContent() |
* @param string $method The name of the text construct we want |
* @param array $arguments An array which we hope gives a 'param' |
* @return string |
*/ |
protected function getText($method, $arguments) |
{ |
$offset = empty($arguments[0]) ? 0: $arguments[0]; |
$attribute = empty($arguments[1]) ? false : $arguments[1]; |
$tags = $this->model->getElementsByTagName($method); |
if ($tags->length <= $offset) { |
return false; |
} |
$content = $tags->item($offset); |
if (! $content->hasAttribute('type')) { |
$content->setAttribute('type', 'text'); |
} |
$type = $content->getAttribute('type'); |
if (! empty($attribute) and |
! ($method == 'generator' and $attribute == 'name')) { |
if ($content->hasAttribute($attribute)) { |
return $content->getAttribute($attribute); |
} else if ($attribute == 'href' and $content->hasAttribute('uri')) { |
return $content->getAttribute('uri'); |
} |
return false; |
} |
return $this->parseTextConstruct($content); |
} |
/** |
* Extract content appropriately from atom text constructs |
* |
* Because of different rules applied to the content element and other text |
* constructs, they are deployed as separate functions, but they share quite |
* a bit of processing. This method performs the core common process, which is |
* to apply the rules for different mime types in order to extract the content. |
* |
* @param DOMNode $content the text construct node to be parsed |
* @return String |
* @author James Stewart |
**/ |
protected function parseTextConstruct(DOMNode $content) |
{ |
if ($content->hasAttribute('type')) { |
$type = $content->getAttribute('type'); |
} else { |
$type = 'text'; |
} |
if (strpos($type, 'text/') === 0) { |
$type = 'text'; |
} |
switch ($type) { |
case 'text': |
return $content->nodeValue; |
break; |
case 'html': |
return str_replace('<', '<', $content->nodeValue); |
break; |
case 'xhtml': |
$container = $content->getElementsByTagName('div'); |
if ($container->length == 0) { |
return false; |
} |
$contents = $container->item(0); |
if ($contents->hasChildNodes()) { |
/* Iterate through, applying xml:base and store the result */ |
$result = ''; |
foreach ($contents->childNodes as $node) { |
$result .= $this->traverseNode($node); |
} |
return utf8_decode($result); |
} |
break; |
case preg_match('@^[a-zA-Z]+/[a-zA-Z+]*xml@i', $type) > 0: |
return $content; |
break; |
case 'application/octet-stream': |
default: |
return base64_decode(trim($content->nodeValue)); |
break; |
} |
return false; |
} |
/** |
* Get a category from the entry. |
* |
* A feed or entry can have any number of categories. A category can have the |
* attributes term, scheme and label. |
* |
* @param string $method The name of the text construct we want |
* @param array $arguments An array which we hope gives a 'param' |
* @return string |
*/ |
function getCategory($method, $arguments) |
{ |
$offset = empty($arguments[0]) ? 0: $arguments[0]; |
$attribute = empty($arguments[1]) ? 'term' : $arguments[1]; |
$categories = $this->model->getElementsByTagName('category'); |
if ($categories->length <= $offset) { |
$category = $categories->item($offset); |
if ($category->hasAttribute($attribute)) { |
return $category->getAttribute($attribute); |
} |
} |
return false; |
} |
/** |
* This element must be present at least once with rel="feed". This element may be |
* present any number of further times so long as there is no clash. If no 'rel' is |
* present and we're asked for one, we follow the example of the Universal Feed |
* Parser and presume 'alternate'. |
* |
* @param int $offset the position of the link within the container |
* @param string $attribute the attribute name required |
* @param array an array of attributes to search by |
* @return string the value of the attribute |
*/ |
function getLink($offset = 0, $attribute = 'href', $params = false) |
{ |
if (is_array($params) and !empty($params)) { |
$terms = array(); |
$alt_predicate = ''; |
$other_predicate = ''; |
foreach ($params as $key => $value) { |
if ($key == 'rel' && $value == 'alternate') { |
$alt_predicate = '[not(@rel) or @rel="alternate"]'; |
} else { |
$terms[] = "@$key='$value'"; |
} |
} |
if (!empty($terms)) { |
$other_predicate = '[' . join(' and ', $terms) . ']'; |
} |
$query = $this->xpathPrefix . 'atom:link' . $alt_predicate . $other_predicate; |
$links = $this->xpath->query($query); |
} else { |
$links = $this->model->getElementsByTagName('link'); |
} |
if ($links->length > $offset) { |
if ($links->item($offset)->hasAttribute($attribute)) { |
$value = $links->item($offset)->getAttribute($attribute); |
if ($attribute == 'href') { |
$value = $this->addBase($value, $links->item($offset)); |
} |
return $value; |
} else if ($attribute == 'rel') { |
return 'alternate'; |
} |
} |
return false; |
} |
} |
?> |
/trunk/jrest/XML/Feed/Parser/RSS09.php |
---|
New file |
0,0 → 1,214 |
<?php |
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */ |
/** |
* RSS0.9 class for XML_Feed_Parser |
* |
* PHP versions 5 |
* |
* LICENSE: This source file is subject to version 3.0 of the PHP license |
* that is available through the world-wide-web at the following URI: |
* http://www.php.net/license/3_0.txt. If you did not receive a copy of |
* the PHP License and are unable to obtain it through the web, please |
* send a note to license@php.net so we can mail you a copy immediately. |
* |
* @category XML |
* @package XML_Feed_Parser |
* @author James Stewart <james@jystewart.net> |
* @copyright 2005 James Stewart <james@jystewart.net> |
* @license http://www.gnu.org/copyleft/lesser.html GNU LGPL 2.1 |
* @version CVS: $Id: RSS09.php,v 1.2 2007-07-25 15:05:34 jp_milcent Exp $ |
* @link http://pear.php.net/package/XML_Feed_Parser/ |
*/ |
/** |
* This class handles RSS0.9 feeds. |
* |
* @author James Stewart <james@jystewart.net> |
* @version Release: 1.0.2 |
* @package XML_Feed_Parser |
* @todo Find a Relax NG URI we can use |
*/ |
class XML_Feed_Parser_RSS09 extends XML_Feed_Parser_Type |
{ |
/** |
* The URI of the RelaxNG schema used to (optionally) validate the feed |
* @var string |
*/ |
private $relax = ''; |
/** |
* We're likely to use XPath, so let's keep it global |
* @var DOMXPath |
*/ |
protected $xpath; |
/** |
* The feed type we are parsing |
* @var string |
*/ |
public $version = 'RSS 0.9'; |
/** |
* The class used to represent individual items |
* @var string |
*/ |
protected $itemClass = 'XML_Feed_Parser_RSS09Element'; |
/** |
* The element containing entries |
* @var string |
*/ |
protected $itemElement = 'item'; |
/** |
* Here we map those elements we're not going to handle individually |
* to the constructs they are. The optional second parameter in the array |
* tells the parser whether to 'fall back' (not apt. at the feed level) or |
* fail if the element is missing. If the parameter is not set, the function |
* will simply return false and leave it to the client to decide what to do. |
* @var array |
*/ |
protected $map = array( |
'title' => array('Text'), |
'link' => array('Text'), |
'description' => array('Text'), |
'image' => array('Image'), |
'textinput' => array('TextInput')); |
/** |
* Here we map some elements to their atom equivalents. This is going to be |
* quite tricky to pull off effectively (and some users' methods may vary) |
* but is worth trying. The key is the atom version, the value is RSS2. |
* @var array |
*/ |
protected $compatMap = array( |
'title' => array('title'), |
'link' => array('link'), |
'subtitle' => array('description')); |
/** |
* We will be working with multiple namespaces and it is useful to |
* keep them together |
* @var array |
*/ |
protected $namespaces = array( |
'rdf' => 'http://www.w3.org/1999/02/22-rdf-syntax-ns#'); |
/** |
* Our constructor does nothing more than its parent. |
* |
* @todo RelaxNG validation |
* @param DOMDocument $xml A DOM object representing the feed |
* @param bool (optional) $string Whether or not to validate this feed |
*/ |
function __construct(DOMDocument $model, $strict = false) |
{ |
$this->model = $model; |
$this->xpath = new DOMXPath($model); |
foreach ($this->namespaces as $key => $value) { |
$this->xpath->registerNamespace($key, $value); |
} |
$this->numberEntries = $this->count('item'); |
} |
/** |
* Included for compatibility -- will not work with RSS 0.9 |
* |
* This is not something that will work with RSS0.9 as it does not have |
* clear restrictions on the global uniqueness of IDs. |
* |
* @param string $id any valid ID. |
* @return false |
*/ |
function getEntryById($id) |
{ |
return false; |
} |
/** |
* Get details of the image associated with the feed. |
* |
* @return array|false an array simply containing the child elements |
*/ |
protected function getImage() |
{ |
$images = $this->model->getElementsByTagName('image'); |
if ($images->length > 0) { |
$image = $images->item(0); |
$details = array(); |
if ($image->hasChildNodes()) { |
$details = array( |
'title' => $image->getElementsByTagName('title')->item(0)->value, |
'link' => $image->getElementsByTagName('link')->item(0)->value, |
'url' => $image->getElementsByTagName('url')->item(0)->value); |
} else { |
$details = array('title' => false, |
'link' => false, |
'url' => $image->attributes->getNamedItem('resource')->nodeValue); |
} |
$details = array_merge($details, |
array('description' => false, 'height' => false, 'width' => false)); |
if (! empty($details)) { |
return $details; |
} |
} |
return false; |
} |
/** |
* The textinput element is little used, but in the interests of |
* completeness we will support it. |
* |
* @return array|false |
*/ |
protected function getTextInput() |
{ |
$inputs = $this->model->getElementsByTagName('textinput'); |
if ($inputs->length > 0) { |
$input = $inputs->item(0); |
$results = array(); |
$results['title'] = isset( |
$input->getElementsByTagName('title')->item(0)->value) ? |
$input->getElementsByTagName('title')->item(0)->value : null; |
$results['description'] = isset( |
$input->getElementsByTagName('description')->item(0)->value) ? |
$input->getElementsByTagName('description')->item(0)->value : null; |
$results['name'] = isset( |
$input->getElementsByTagName('name')->item(0)->value) ? |
$input->getElementsByTagName('name')->item(0)->value : null; |
$results['link'] = isset( |
$input->getElementsByTagName('link')->item(0)->value) ? |
$input->getElementsByTagName('link')->item(0)->value : null; |
if (empty($results['link']) && |
$input->attributes->getNamedItem('resource')) { |
$results['link'] = $input->attributes->getNamedItem('resource')->nodeValue; |
} |
if (! empty($results)) { |
return $results; |
} |
} |
return false; |
} |
/** |
* Get details of a link from the feed. |
* |
* In RSS1 a link is a text element but in order to ensure that we resolve |
* URLs properly we have a special function for them. |
* |
* @return string |
*/ |
function getLink($offset = 0, $attribute = 'href', $params = false) |
{ |
$links = $this->model->getElementsByTagName('link'); |
if ($links->length <= $offset) { |
return false; |
} |
$link = $links->item($offset); |
return $this->addBase($link->nodeValue, $link); |
} |
} |
?> |
/trunk/jrest/XML/Feed/Parser/Type.php |
---|
New file |
0,0 → 1,443 |
<?php |
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */ |
/** |
* Abstract class providing common methods for XML_Feed_Parser feeds. |
* |
* PHP versions 5 |
* |
* LICENSE: This source file is subject to version 3.0 of the PHP license |
* that is available through the world-wide-web at the following URI: |
* http://www.php.net/license/3_0.txt. If you did not receive a copy of |
* the PHP License and are unable to obtain it through the web, please |
* send a note to license@php.net so we can mail you a copy immediately. |
* |
* @category XML |
* @package XML_Feed_Parser |
* @author James Stewart <james@jystewart.net> |
* @copyright 2005 James Stewart <james@jystewart.net> |
* @license http://www.gnu.org/copyleft/lesser.html GNU LGPL 2.1 |
* @version CVS: $Id: Type.php,v 1.3 2008-09-30 15:21:39 alexandre_tb Exp $ |
* @link http://pear.php.net/package/XML_Feed_Parser/ |
*/ |
/** |
* This abstract class provides some general methods that are likely to be |
* implemented exactly the same way for all feed types. |
* |
* @package XML_Feed_Parser |
* @author James Stewart <james@jystewart.net> |
* @version Release: 1.0.2 |
*/ |
abstract class XML_Feed_Parser_Type |
{ |
/** |
* Where we store our DOM object for this feed |
* @var DOMDocument |
*/ |
public $model; |
/** |
* For iteration we'll want a count of the number of entries |
* @var int |
*/ |
public $numberEntries; |
/** |
* Where we store our entry objects once instantiated |
* @var array |
*/ |
public $entries = array(); |
/** |
* Proxy to allow use of element names as method names |
* |
* We are not going to provide methods for every entry type so this |
* function will allow for a lot of mapping. We rely pretty heavily |
* on this to handle our mappings between other feed types and atom. |
* |
* @param string $call - the method attempted |
* @param array $arguments - arguments to that method |
* @return mixed |
*/ |
function __call($call, $arguments = array()) |
{ |
if (! is_array($arguments)) { |
$arguments = array(); |
} |
if (isset($this->compatMap[$call])) { |
$tempMap = $this->compatMap; |
$tempcall = array_pop($tempMap[$call]); |
if (! empty($tempMap)) { |
$arguments = array_merge($arguments, $tempMap[$call]); |
} |
$call = $tempcall; |
} |
/* To be helpful, we allow a case-insensitive search for this method */ |
if (! isset($this->map[$call])) { |
foreach (array_keys($this->map) as $key) { |
if (strtoupper($key) == strtoupper($call)) { |
$call = $key; |
break; |
} |
} |
} |
if (empty($this->map[$call])) { |
return false; |
} |
$method = 'get' . $this->map[$call][0]; |
if ($method == 'getLink') { |
$offset = empty($arguments[0]) ? 0 : $arguments[0]; |
$attribute = empty($arguments[1]) ? 'href' : $arguments[1]; |
$params = isset($arguments[2]) ? $arguments[2] : array(); |
return $this->getLink($offset, $attribute, $params); |
} |
if (method_exists($this, $method)) { |
return $this->$method($call, $arguments); |
} |
return false; |
} |
/** |
* Proxy to allow use of element names as attribute names |
* |
* For many elements variable-style access will be desirable. This function |
* provides for that. |
* |
* @param string $value - the variable required |
* @return mixed |
*/ |
function __get($value) |
{ |
return $this->__call($value, array()); |
} |
/** |
* Utility function to help us resolve xml:base values |
* |
* We have other methods which will traverse the DOM and work out the different |
* xml:base declarations we need to be aware of. We then need to combine them. |
* If a declaration starts with a protocol then we restart the string. If it |
* starts with a / then we add on to the domain name. Otherwise we simply tag |
* it on to the end. |
* |
* @param string $base - the base to add the link to |
* @param string $link |
*/ |
function combineBases($base, $link) |
{ |
if (preg_match('/^[A-Za-z]+:\/\//', $link)) { |
return $link; |
} else if (preg_match('/^\//', $link)) { |
/* Extract domain and suffix link to that */ |
preg_match('/^([A-Za-z]+:\/\/.*)?\/*/', $base, $results); |
$firstLayer = $results[0]; |
return $firstLayer . "/" . $link; |
} else if (preg_match('/^\.\.\//', $base)) { |
/* Step up link to find place to be */ |
preg_match('/^((\.\.\/)+)(.*)$/', $link, $bases); |
$suffix = $bases[3]; |
$count = preg_match_all('/\.\.\//', $bases[1], $steps); |
$url = explode("/", $base); |
for ($i = 0; $i <= $count; $i++) { |
array_pop($url); |
} |
return implode("/", $url) . "/" . $suffix; |
} else if (preg_match('/^(?!\/$)/', $base)) { |
$base = preg_replace('/(.*\/).*$/', '$1', $base) ; |
return $base . $link; |
} else { |
/* Just stick it on the end */ |
return $base . $link; |
} |
} |
/** |
* Determine whether we need to apply our xml:base rules |
* |
* Gets us the xml:base data and then processes that with regard |
* to our current link. |
* |
* @param string |
* @param DOMElement |
* @return string |
*/ |
function addBase($link, $element) |
{ |
if (preg_match('/^[A-Za-z]+:\/\//', $link)) { |
return $link; |
} |
return $this->combineBases($element->baseURI, $link); |
} |
/** |
* Get an entry by its position in the feed, starting from zero |
* |
* As well as allowing the items to be iterated over we want to allow |
* users to be able to access a specific entry. This is one of two ways of |
* doing that, the other being by ID. |
* |
* @param int $offset |
* @return XML_Feed_Parser_RSS1Element |
*/ |
function getEntryByOffset($offset) |
{ |
if (! isset($this->entries[$offset])) { |
$entries = $this->model->getElementsByTagName($this->itemElement); |
if ($entries->length > $offset) { |
$xmlBase = $entries->item($offset)->baseURI; |
$this->entries[$offset] = new $this->itemClass( |
$entries->item($offset), $this, $xmlBase); |
if ($id = $this->entries[$offset]->id) { |
$id_mappings = $this->idMappings; |
$id_mappings[$id] = $this->entries[$offset]; |
$this->idMappings = $id_mappings; |
} |
} else { |
throw new XML_Feed_Parser_Exception('No entries found'); |
} |
} |
return $this->entries[$offset]; |
} |
/** |
* Return a date in seconds since epoch. |
* |
* Get a date construct. We use PHP's strtotime to return it as a unix datetime, which |
* is the number of seconds since 1970-01-01 00:00:00. |
* |
* @link http://php.net/strtotime |
* @param string $method The name of the date construct we want |
* @param array $arguments Included for compatibility with our __call usage |
* @return int|false datetime |
*/ |
protected function getDate($method, $arguments) |
{ |
$time = $this->model->getElementsByTagName($method); |
if ($time->length == 0) { |
return false; |
} |
return strtotime($time->item(0)->nodeValue); |
} |
/** |
* Get a text construct. |
* |
* @param string $method The name of the text construct we want |
* @param array $arguments Included for compatibility with our __call usage |
* @return string |
*/ |
protected function getText($method, $arguments = array()) |
{ |
$tags = $this->model->getElementsByTagName($method); |
if ($tags->length > 0) { |
$value = $tags->item(0)->nodeValue; |
return $value; |
} |
return false; |
} |
/** |
* Apply various rules to retrieve category data. |
* |
* There is no single way of declaring a category in RSS1/1.1 as there is in RSS2 |
* and Atom. Instead the usual approach is to use the dublin core namespace to |
* declare categories. For example delicious use both: |
* <dc:subject>PEAR</dc:subject> and: <taxo:topics><rdf:Bag> |
* <rdf:li resource="http://del.icio.us/tag/PEAR" /></rdf:Bag></taxo:topics> |
* to declare a categorisation of 'PEAR'. |
* |
* We need to be sensitive to this where possible. |
* |
* @param string $call for compatibility with our overloading |
* @param array $arguments - arg 0 is the offset, arg 1 is whether to return as array |
* @return string|array|false |
*/ |
protected function getCategory($call, $arguments) |
{ |
$categories = $this->model->getElementsByTagName('subject'); |
$offset = empty($arguments[0]) ? 0 : $arguments[0]; |
$array = empty($arguments[1]) ? false : true; |
if ($categories->length <= $offset) { |
return false; |
} |
if ($array) { |
$list = array(); |
foreach ($categories as $category) { |
array_push($list, $category->nodeValue); |
} |
return $list; |
} |
return $categories->item($offset)->nodeValue; |
} |
/** |
* Count occurrences of an element |
* |
* This function will tell us how many times the element $type |
* appears at this level of the feed. |
* |
* @param string $type the element we want to get a count of |
* @return int |
*/ |
protected function count($type) |
{ |
if ($tags = $this->model->getElementsByTagName($type)) { |
return $tags->length; |
} |
return 0; |
} |
/** |
* Part of our xml:base processing code |
* |
* We need a couple of methods to access XHTML content stored in feeds. |
* This is because we dereference all xml:base references before returning |
* the element. This method handles the attributes. |
* |
* @param DOMElement $node The DOM node we are iterating over |
* @return string |
*/ |
function processXHTMLAttributes($node) { |
$return = ''; |
foreach ($node->attributes as $attribute) { |
if ($attribute->name == 'src' or $attribute->name == 'href') { |
$attribute->value = $this->addBase($attribute->value, $attribute); |
} |
if ($attribute->name == 'base') { |
continue; |
} |
$return .= $attribute->name . '="' . $attribute->value .'" '; |
} |
if (! empty($return)) { |
return ' ' . trim($return); |
} |
return ''; |
} |
/** |
* Part of our xml:base processing code |
* |
* We need a couple of methods to access XHTML content stored in feeds. |
* This is because we dereference all xml:base references before returning |
* the element. This method recurs through the tree descending from the node |
* and builds our string |
* |
* @param DOMElement $node The DOM node we are processing |
* @return string |
*/ |
function traverseNode($node) |
{ |
$content = ''; |
/* Add the opening of this node to the content */ |
if ($node instanceof DOMElement) { |
$content .= '<' . $node->tagName . |
$this->processXHTMLAttributes($node) . '>'; |
} |
/* Process children */ |
if ($node->hasChildNodes()) { |
foreach ($node->childNodes as $child) { |
$content .= $this->traverseNode($child); |
} |
} |
if ($node instanceof DOMText) { |
$content .= htmlentities($node->nodeValue); |
} |
/* Add the closing of this node to the content */ |
if ($node instanceof DOMElement) { |
$content .= '</' . $node->tagName . '>'; |
} |
return $content; |
} |
/** |
* Get content from RSS feeds (atom has its own implementation) |
* |
* The official way to include full content in an RSS1 entry is to use |
* the content module's element 'encoded', and RSS2 feeds often duplicate that. |
* Often, however, the 'description' element is used instead. We will offer that |
* as a fallback. Atom uses its own approach and overrides this method. |
* |
* @return string|false |
*/ |
protected function getContent() |
{ |
$options = array('encoded', 'description'); |
foreach ($options as $element) { |
$test = $this->model->getElementsByTagName($element); |
if ($test->length == 0) { |
continue; |
} |
if ($test->item(0)->hasChildNodes()) { |
$value = ''; |
foreach ($test->item(0)->childNodes as $child) { |
if ($child instanceof DOMText) { |
$value .= $child->nodeValue; |
} else { |
$simple = simplexml_import_dom($child); |
$value .= $simple->asXML(); |
} |
} |
return $value; |
} else if ($test->length > 0) { |
return $test->item(0)->nodeValue; |
} |
} |
return false; |
} |
/** |
* Checks if this element has a particular child element. |
* |
* @param String |
* @param Integer |
* @return bool |
**/ |
function hasKey($name, $offset = 0) |
{ |
$search = $this->model->getElementsByTagName($name); |
return $search->length > $offset; |
} |
/** |
* Return an XML serialization of the feed, should it be required. Most |
* users however, will already have a serialization that they used when |
* instantiating the object. |
* |
* @return string XML serialization of element |
*/ |
function __toString() |
{ |
$simple = simplexml_import_dom($this->model); |
return $simple->asXML(); |
} |
/** |
* Get directory holding RNG schemas. Method is based on that |
* found in Contact_AddressBook. |
* |
* @return string PEAR data directory. |
* @access public |
* @static |
*/ |
static function getSchemaDir() |
{ |
require_once 'PEAR/Config.php'; |
$config = new PEAR_Config; |
return $config->get('data_dir') . '/XML_Feed_Parser/schemas'; |
} |
} |
?> |
/trunk/jrest/XML/Feed/Parser/RSS1Element.php |
---|
New file |
0,0 → 1,116 |
<?php |
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */ |
/** |
* RSS1 Element class for XML_Feed_Parser |
* |
* PHP versions 5 |
* |
* LICENSE: This source file is subject to version 3.0 of the PHP license |
* that is available through the world-wide-web at the following URI: |
* http://www.php.net/license/3_0.txt. If you did not receive a copy of |
* the PHP License and are unable to obtain it through the web, please |
* send a note to license@php.net so we can mail you a copy immediately. |
* |
* @category XML |
* @package XML_Feed_Parser |
* @author James Stewart <james@jystewart.net> |
* @copyright 2005 James Stewart <james@jystewart.net> |
* @license http://www.gnu.org/copyleft/lesser.html GNU LGPL 2.1 |
* @version CVS: $Id: RSS1Element.php,v 1.2 2007-07-25 15:05:34 jp_milcent Exp $ |
* @link http://pear.php.net/package/XML_Feed_Parser/ |
*/ |
/* |
* This class provides support for RSS 1.0 entries. It will usually be called by |
* XML_Feed_Parser_RSS1 with which it shares many methods. |
* |
* @author James Stewart <james@jystewart.net> |
* @version Release: 1.0.2 |
* @package XML_Feed_Parser |
*/ |
class XML_Feed_Parser_RSS1Element extends XML_Feed_Parser_RSS1 |
{ |
/** |
* This will be a reference to the parent object for when we want |
* to use a 'fallback' rule |
* @var XML_Feed_Parser_RSS1 |
*/ |
protected $parent; |
/** |
* Our specific element map |
* @var array |
*/ |
protected $map = array( |
'id' => array('Id'), |
'title' => array('Text'), |
'link' => array('Link'), |
'description' => array('Text'), # or dc:description |
'category' => array('Category'), |
'rights' => array('Text'), # dc:rights |
'creator' => array('Text'), # dc:creator |
'publisher' => array('Text'), # dc:publisher |
'contributor' => array('Text'), # dc:contributor |
'date' => array('Date'), # dc:date |
'content' => array('Content') |
); |
/** |
* Here we map some elements to their atom equivalents. This is going to be |
* quite tricky to pull off effectively (and some users' methods may vary) |
* but is worth trying. The key is the atom version, the value is RSS1. |
* @var array |
*/ |
protected $compatMap = array( |
'content' => array('content'), |
'updated' => array('lastBuildDate'), |
'published' => array('pubdate'), |
'subtitle' => array('description'), |
'updated' => array('date'), |
'author' => array('creator'), |
'contributor' => array('contributor') |
); |
/** |
* Store useful information for later. |
* |
* @param DOMElement $element - this item as a DOM element |
* @param XML_Feed_Parser_RSS1 $parent - the feed of which this is a member |
*/ |
function __construct(DOMElement $element, $parent, $xmlBase = '') |
{ |
$this->model = $element; |
$this->parent = $parent; |
} |
/** |
* If an rdf:about attribute is specified, return it as an ID |
* |
* There is no established way of showing an ID for an RSS1 entry. We will |
* simulate it using the rdf:about attribute of the entry element. This cannot |
* be relied upon for unique IDs but may prove useful. |
* |
* @return string|false |
*/ |
function getId() |
{ |
if ($this->model->attributes->getNamedItem('about')) { |
return $this->model->attributes->getNamedItem('about')->nodeValue; |
} |
return false; |
} |
/** |
* How RSS1 should support for enclosures is not clear. For now we will return |
* false. |
* |
* @return false |
*/ |
function getEnclosure() |
{ |
return false; |
} |
} |
?> |
/trunk/jrest/XML/Feed/Parser/RSS11Element.php |
---|
New file |
0,0 → 1,151 |
<?php |
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */ |
/** |
* RSS1 Element class for XML_Feed_Parser |
* |
* PHP versions 5 |
* |
* LICENSE: This source file is subject to version 3.0 of the PHP license |
* that is available through the world-wide-web at the following URI: |
* http://www.php.net/license/3_0.txt. If you did not receive a copy of |
* the PHP License and are unable to obtain it through the web, please |
* send a note to license@php.net so we can mail you a copy immediately. |
* |
* @category XML |
* @package XML_Feed_Parser |
* @author James Stewart <james@jystewart.net> |
* @copyright 2005 James Stewart <james@jystewart.net> |
* @license http://www.gnu.org/copyleft/lesser.html GNU LGPL 2.1 |
* @version CVS: $Id: RSS11Element.php,v 1.2 2007-07-25 15:05:34 jp_milcent Exp $ |
* @link http://pear.php.net/package/XML_Feed_Parser/ |
*/ |
/* |
* This class provides support for RSS 1.1 entries. It will usually be called by |
* XML_Feed_Parser_RSS11 with which it shares many methods. |
* |
* @author James Stewart <james@jystewart.net> |
* @version Release: 1.0.2 |
* @package XML_Feed_Parser |
*/ |
class XML_Feed_Parser_RSS11Element extends XML_Feed_Parser_RSS11 |
{ |
/** |
* This will be a reference to the parent object for when we want |
* to use a 'fallback' rule |
* @var XML_Feed_Parser_RSS1 |
*/ |
protected $parent; |
/** |
* Our specific element map |
* @var array |
*/ |
protected $map = array( |
'id' => array('Id'), |
'title' => array('Text'), |
'link' => array('Link'), |
'description' => array('Text'), # or dc:description |
'category' => array('Category'), |
'rights' => array('Text'), # dc:rights |
'creator' => array('Text'), # dc:creator |
'publisher' => array('Text'), # dc:publisher |
'contributor' => array('Text'), # dc:contributor |
'date' => array('Date'), # dc:date |
'content' => array('Content') |
); |
/** |
* Here we map some elements to their atom equivalents. This is going to be |
* quite tricky to pull off effectively (and some users' methods may vary) |
* but is worth trying. The key is the atom version, the value is RSS1. |
* @var array |
*/ |
protected $compatMap = array( |
'content' => array('content'), |
'updated' => array('lastBuildDate'), |
'published' => array('pubdate'), |
'subtitle' => array('description'), |
'updated' => array('date'), |
'author' => array('creator'), |
'contributor' => array('contributor') |
); |
/** |
* Store useful information for later. |
* |
* @param DOMElement $element - this item as a DOM element |
* @param XML_Feed_Parser_RSS1 $parent - the feed of which this is a member |
*/ |
function __construct(DOMElement $element, $parent, $xmlBase = '') |
{ |
$this->model = $element; |
$this->parent = $parent; |
} |
/** |
* If an rdf:about attribute is specified, return that as an ID |
* |
* There is no established way of showing an ID for an RSS1 entry. We will |
* simulate it using the rdf:about attribute of the entry element. This cannot |
* be relied upon for unique IDs but may prove useful. |
* |
* @return string|false |
*/ |
function getId() |
{ |
if ($this->model->attributes->getNamedItem('about')) { |
return $this->model->attributes->getNamedItem('about')->nodeValue; |
} |
return false; |
} |
/** |
* Return the entry's content |
* |
* The official way to include full content in an RSS1 entry is to use |
* the content module's element 'encoded'. Often, however, the 'description' |
* element is used instead. We will offer that as a fallback. |
* |
* @return string|false |
*/ |
function getContent() |
{ |
$options = array('encoded', 'description'); |
foreach ($options as $element) { |
$test = $this->model->getElementsByTagName($element); |
if ($test->length == 0) { |
continue; |
} |
if ($test->item(0)->hasChildNodes()) { |
$value = ''; |
foreach ($test->item(0)->childNodes as $child) { |
if ($child instanceof DOMText) { |
$value .= $child->nodeValue; |
} else { |
$simple = simplexml_import_dom($child); |
$value .= $simple->asXML(); |
} |
} |
return $value; |
} else if ($test->length > 0) { |
return $test->item(0)->nodeValue; |
} |
} |
return false; |
} |
/** |
* How RSS1.1 should support for enclosures is not clear. For now we will return |
* false. |
* |
* @return false |
*/ |
function getEnclosure() |
{ |
return false; |
} |
} |
?> |
/trunk/jrest/XML/Feed/Parser/RSS2Element.php |
---|
New file |
0,0 → 1,171 |
<?php |
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */ |
/** |
* Class representing entries in an RSS2 feed. |
* |
* PHP versions 5 |
* |
* LICENSE: This source file is subject to version 3.0 of the PHP license |
* that is available through the world-wide-web at the following URI: |
* http://www.php.net/license/3_0.txt. If you did not receive a copy of |
* the PHP License and are unable to obtain it through the web, please |
* send a note to license@php.net so we can mail you a copy immediately. |
* |
* @category XML |
* @package XML_Feed_Parser |
* @author James Stewart <james@jystewart.net> |
* @copyright 2005 James Stewart <james@jystewart.net> |
* @license http://www.gnu.org/copyleft/lesser.html GNU LGPL 2.1 |
* @version CVS: $Id: RSS2Element.php,v 1.2 2007-07-25 15:05:34 jp_milcent Exp $ |
* @link http://pear.php.net/package/XML_Feed_Parser/ |
*/ |
/** |
* This class provides support for RSS 2.0 entries. It will usually be |
* called by XML_Feed_Parser_RSS2 with which it shares many methods. |
* |
* @author James Stewart <james@jystewart.net> |
* @version Release: 1.0.2 |
* @package XML_Feed_Parser |
*/ |
class XML_Feed_Parser_RSS2Element extends XML_Feed_Parser_RSS2 |
{ |
/** |
* This will be a reference to the parent object for when we want |
* to use a 'fallback' rule |
* @var XML_Feed_Parser_RSS2 |
*/ |
protected $parent; |
/** |
* Our specific element map |
* @var array |
*/ |
protected $map = array( |
'title' => array('Text'), |
'guid' => array('Guid'), |
'description' => array('Text'), |
'author' => array('Text'), |
'comments' => array('Text'), |
'enclosure' => array('Enclosure'), |
'pubDate' => array('Date'), |
'source' => array('Source'), |
'link' => array('Text'), |
'content' => array('Content')); |
/** |
* Here we map some elements to their atom equivalents. This is going to be |
* quite tricky to pull off effectively (and some users' methods may vary) |
* but is worth trying. The key is the atom version, the value is RSS2. |
* @var array |
*/ |
protected $compatMap = array( |
'id' => array('guid'), |
'updated' => array('lastBuildDate'), |
'published' => array('pubdate'), |
'guidislink' => array('guid', 'ispermalink'), |
'summary' => array('description')); |
/** |
* Store useful information for later. |
* |
* @param DOMElement $element - this item as a DOM element |
* @param XML_Feed_Parser_RSS2 $parent - the feed of which this is a member |
*/ |
function __construct(DOMElement $element, $parent, $xmlBase = '') |
{ |
$this->model = $element; |
$this->parent = $parent; |
} |
/** |
* Get the value of the guid element, if specified |
* |
* guid is the closest RSS2 has to atom's ID. It is usually but not always a |
* URI. The one attribute that RSS2 can posess is 'ispermalink' which specifies |
* whether the guid is itself dereferencable. Use of guid is not obligatory, |
* but is advisable. To get the guid you would call $item->id() (for atom |
* compatibility) or $item->guid(). To check if this guid is a permalink call |
* $item->guid("ispermalink"). |
* |
* @param string $method - the method name being called |
* @param array $params - parameters required |
* @return string the guid or value of ispermalink |
*/ |
protected function getGuid($method, $params) |
{ |
$attribute = (isset($params[0]) and $params[0] == 'ispermalink') ? |
true : false; |
$tag = $this->model->getElementsByTagName('guid'); |
if ($tag->length > 0) { |
if ($attribute) { |
if ($tag->hasAttribute("ispermalink")) { |
return $tag->getAttribute("ispermalink"); |
} |
} |
return $tag->item(0)->nodeValue; |
} |
return false; |
} |
/** |
* Access details of file enclosures |
* |
* The RSS2 spec is ambiguous as to whether an enclosure element must be |
* unique in a given entry. For now we will assume it needn't, and allow |
* for an offset. |
* |
* @param string $method - the method being called |
* @param array $parameters - we expect the first of these to be our offset |
* @return array|false |
*/ |
protected function getEnclosure($method, $parameters) |
{ |
$encs = $this->model->getElementsByTagName('enclosure'); |
$offset = isset($parameters[0]) ? $parameters[0] : 0; |
if ($encs->length > $offset) { |
try { |
if (! $encs->item($offset)->hasAttribute('url')) { |
return false; |
} |
$attrs = $encs->item($offset)->attributes; |
return array( |
'url' => $attrs->getNamedItem('url')->value, |
'length' => $attrs->getNamedItem('length')->value, |
'type' => $attrs->getNamedItem('type')->value); |
} catch (Exception $e) { |
return false; |
} |
} |
return false; |
} |
/** |
* Get the entry source if specified |
* |
* source is an optional sub-element of item. Like atom:source it tells |
* us about where the entry came from (eg. if it's been copied from another |
* feed). It is not a rich source of metadata in the same way as atom:source |
* and while it would be good to maintain compatibility by returning an |
* XML_Feed_Parser_RSS2 element, it makes a lot more sense to return an array. |
* |
* @return array|false |
*/ |
protected function getSource() |
{ |
$get = $this->model->getElementsByTagName('source'); |
if ($get->length) { |
$source = $get->item(0); |
$array = array( |
'content' => $source->nodeValue); |
foreach ($source->attributes as $attribute) { |
$array[$attribute->name] = $attribute->value; |
} |
return $array; |
} |
return false; |
} |
} |
?> |
/trunk/jrest/XML/Util.php |
---|
New file |
0,0 → 1,752 |
<?PHP |
/* vim: set expandtab tabstop=4 shiftwidth=4: */ |
// +----------------------------------------------------------------------+ |
// | PHP Version 4 | |
// +----------------------------------------------------------------------+ |
// | Copyright (c) 1997-2002 The PHP Group | |
// +----------------------------------------------------------------------+ |
// | This source file is subject to version 2.0 of the PHP license, | |
// | that is bundled with this package in the file LICENSE, and is | |
// | available at through the world-wide-web at | |
// | http://www.php.net/license/2_02.txt. | |
// | If you did not receive a copy of the PHP license and are unable to | |
// | obtain it through the world-wide-web, please send a note to | |
// | license@php.net so we can mail you a copy immediately. | |
// +----------------------------------------------------------------------+ |
// | Authors: Stephan Schmidt <schst@php-tools.net> | |
// +----------------------------------------------------------------------+ |
// |
// $Id: Util.php,v 1.1 2007-03-28 08:51:22 neiluj Exp $ |
/** |
* error code for invalid chars in XML name |
*/ |
define("XML_UTIL_ERROR_INVALID_CHARS", 51); |
/** |
* error code for invalid chars in XML name |
*/ |
define("XML_UTIL_ERROR_INVALID_START", 52); |
/** |
* error code for non-scalar tag content |
*/ |
define("XML_UTIL_ERROR_NON_SCALAR_CONTENT", 60); |
/** |
* error code for missing tag name |
*/ |
define("XML_UTIL_ERROR_NO_TAG_NAME", 61); |
/** |
* replace XML entities |
*/ |
define("XML_UTIL_REPLACE_ENTITIES", 1); |
/** |
* embedd content in a CData Section |
*/ |
define("XML_UTIL_CDATA_SECTION", 5); |
/** |
* do not replace entitites |
*/ |
define("XML_UTIL_ENTITIES_NONE", 0); |
/** |
* replace all XML entitites |
* This setting will replace <, >, ", ' and & |
*/ |
define("XML_UTIL_ENTITIES_XML", 1); |
/** |
* replace only required XML entitites |
* This setting will replace <, " and & |
*/ |
define("XML_UTIL_ENTITIES_XML_REQUIRED", 2); |
/** |
* replace HTML entitites |
* @link http://www.php.net/htmlentities |
*/ |
define("XML_UTIL_ENTITIES_HTML", 3); |
/** |
* Collapse all empty tags. |
*/ |
define("XML_UTIL_COLLAPSE_ALL", 1); |
/** |
* Collapse only empty XHTML tags that have no end tag. |
*/ |
define("XML_UTIL_COLLAPSE_XHTML_ONLY", 2); |
/** |
* utility class for working with XML documents |
* |
* @category XML |
* @package XML_Util |
* @version 1.1.0 |
* @author Stephan Schmidt <schst@php.net> |
*/ |
class XML_Util { |
/** |
* return API version |
* |
* @access public |
* @static |
* @return string $version API version |
*/ |
function apiVersion() |
{ |
return '1.1'; |
} |
/** |
* replace XML entities |
* |
* With the optional second parameter, you may select, which |
* entities should be replaced. |
* |
* <code> |
* require_once 'XML/Util.php'; |
* |
* // replace XML entites: |
* $string = XML_Util::replaceEntities("This string contains < & >."); |
* </code> |
* |
* @access public |
* @static |
* @param string string where XML special chars should be replaced |
* @param integer setting for entities in attribute values (one of XML_UTIL_ENTITIES_XML, XML_UTIL_ENTITIES_XML_REQUIRED, XML_UTIL_ENTITIES_HTML) |
* @return string string with replaced chars |
* @see reverseEntities() |
*/ |
function replaceEntities($string, $replaceEntities = XML_UTIL_ENTITIES_XML) |
{ |
switch ($replaceEntities) { |
case XML_UTIL_ENTITIES_XML: |
return strtr($string,array( |
'&' => '&', |
'>' => '>', |
'<' => '<', |
'"' => '"', |
'\'' => ''' )); |
break; |
case XML_UTIL_ENTITIES_XML_REQUIRED: |
return strtr($string,array( |
'&' => '&', |
'<' => '<', |
'"' => '"' )); |
break; |
case XML_UTIL_ENTITIES_HTML: |
return htmlentities($string); |
break; |
} |
return $string; |
} |
/** |
* reverse XML entities |
* |
* With the optional second parameter, you may select, which |
* entities should be reversed. |
* |
* <code> |
* require_once 'XML/Util.php'; |
* |
* // reverse XML entites: |
* $string = XML_Util::reverseEntities("This string contains < & >."); |
* </code> |
* |
* @access public |
* @static |
* @param string string where XML special chars should be replaced |
* @param integer setting for entities in attribute values (one of XML_UTIL_ENTITIES_XML, XML_UTIL_ENTITIES_XML_REQUIRED, XML_UTIL_ENTITIES_HTML) |
* @return string string with replaced chars |
* @see replaceEntities() |
*/ |
function reverseEntities($string, $replaceEntities = XML_UTIL_ENTITIES_XML) |
{ |
switch ($replaceEntities) { |
case XML_UTIL_ENTITIES_XML: |
return strtr($string,array( |
'&' => '&', |
'>' => '>', |
'<' => '<', |
'"' => '"', |
''' => '\'' )); |
break; |
case XML_UTIL_ENTITIES_XML_REQUIRED: |
return strtr($string,array( |
'&' => '&', |
'<' => '<', |
'"' => '"' )); |
break; |
case XML_UTIL_ENTITIES_HTML: |
$arr = array_flip(get_html_translation_table(HTML_ENTITIES)); |
return strtr($string, $arr); |
break; |
} |
return $string; |
} |
/** |
* build an xml declaration |
* |
* <code> |
* require_once 'XML/Util.php'; |
* |
* // get an XML declaration: |
* $xmlDecl = XML_Util::getXMLDeclaration("1.0", "UTF-8", true); |
* </code> |
* |
* @access public |
* @static |
* @param string $version xml version |
* @param string $encoding character encoding |
* @param boolean $standAlone document is standalone (or not) |
* @return string $decl xml declaration |
* @uses XML_Util::attributesToString() to serialize the attributes of the XML declaration |
*/ |
function getXMLDeclaration($version = "1.0", $encoding = null, $standalone = null) |
{ |
$attributes = array( |
"version" => $version, |
); |
// add encoding |
if ($encoding !== null) { |
$attributes["encoding"] = $encoding; |
} |
// add standalone, if specified |
if ($standalone !== null) { |
$attributes["standalone"] = $standalone ? "yes" : "no"; |
} |
return sprintf("<?xml%s?>", XML_Util::attributesToString($attributes, false)); |
} |
/** |
* build a document type declaration |
* |
* <code> |
* require_once 'XML/Util.php'; |
* |
* // get a doctype declaration: |
* $xmlDecl = XML_Util::getDocTypeDeclaration("rootTag","myDocType.dtd"); |
* </code> |
* |
* @access public |
* @static |
* @param string $root name of the root tag |
* @param string $uri uri of the doctype definition (or array with uri and public id) |
* @param string $internalDtd internal dtd entries |
* @return string $decl doctype declaration |
* @since 0.2 |
*/ |
function getDocTypeDeclaration($root, $uri = null, $internalDtd = null) |
{ |
if (is_array($uri)) { |
$ref = sprintf( ' PUBLIC "%s" "%s"', $uri["id"], $uri["uri"] ); |
} elseif (!empty($uri)) { |
$ref = sprintf( ' SYSTEM "%s"', $uri ); |
} else { |
$ref = ""; |
} |
if (empty($internalDtd)) { |
return sprintf("<!DOCTYPE %s%s>", $root, $ref); |
} else { |
return sprintf("<!DOCTYPE %s%s [\n%s\n]>", $root, $ref, $internalDtd); |
} |
} |
/** |
* create string representation of an attribute list |
* |
* <code> |
* require_once 'XML/Util.php'; |
* |
* // build an attribute string |
* $att = array( |
* "foo" => "bar", |
* "argh" => "tomato" |
* ); |
* |
* $attList = XML_Util::attributesToString($att); |
* </code> |
* |
* @access public |
* @static |
* @param array $attributes attribute array |
* @param boolean|array $sort sort attribute list alphabetically, may also be an assoc array containing the keys 'sort', 'multiline', 'indent', 'linebreak' and 'entities' |
* @param boolean $multiline use linebreaks, if more than one attribute is given |
* @param string $indent string used for indentation of multiline attributes |
* @param string $linebreak string used for linebreaks of multiline attributes |
* @param integer $entities setting for entities in attribute values (one of XML_UTIL_ENTITIES_NONE, XML_UTIL_ENTITIES_XML, XML_UTIL_ENTITIES_XML_REQUIRED, XML_UTIL_ENTITIES_HTML) |
* @return string string representation of the attributes |
* @uses XML_Util::replaceEntities() to replace XML entities in attribute values |
* @todo allow sort also to be an options array |
*/ |
function attributesToString($attributes, $sort = true, $multiline = false, $indent = ' ', $linebreak = "\n", $entities = XML_UTIL_ENTITIES_XML) |
{ |
/** |
* second parameter may be an array |
*/ |
if (is_array($sort)) { |
if (isset($sort['multiline'])) { |
$multiline = $sort['multiline']; |
} |
if (isset($sort['indent'])) { |
$indent = $sort['indent']; |
} |
if (isset($sort['linebreak'])) { |
$multiline = $sort['linebreak']; |
} |
if (isset($sort['entities'])) { |
$entities = $sort['entities']; |
} |
if (isset($sort['sort'])) { |
$sort = $sort['sort']; |
} else { |
$sort = true; |
} |
} |
$string = ''; |
if (is_array($attributes) && !empty($attributes)) { |
if ($sort) { |
ksort($attributes); |
} |
if( !$multiline || count($attributes) == 1) { |
foreach ($attributes as $key => $value) { |
if ($entities != XML_UTIL_ENTITIES_NONE) { |
if ($entities === XML_UTIL_CDATA_SECTION) { |
$entities = XML_UTIL_ENTITIES_XML; |
} |
$value = XML_Util::replaceEntities($value, $entities); |
} |
$string .= ' '.$key.'="'.$value.'"'; |
} |
} else { |
$first = true; |
foreach ($attributes as $key => $value) { |
if ($entities != XML_UTIL_ENTITIES_NONE) { |
$value = XML_Util::replaceEntities($value, $entities); |
} |
if ($first) { |
$string .= " ".$key.'="'.$value.'"'; |
$first = false; |
} else { |
$string .= $linebreak.$indent.$key.'="'.$value.'"'; |
} |
} |
} |
} |
return $string; |
} |
/** |
* Collapses empty tags. |
* |
* @access public |
* @static |
* @param string $xml XML |
* @param integer $mode Whether to collapse all empty tags (XML_UTIL_COLLAPSE_ALL) or only XHTML (XML_UTIL_COLLAPSE_XHTML_ONLY) ones. |
* @return string $xml XML |
*/ |
function collapseEmptyTags($xml, $mode = XML_UTIL_COLLAPSE_ALL) { |
if ($mode == XML_UTIL_COLLAPSE_XHTML_ONLY) { |
return preg_replace( |
'/<(area|base|br|col|hr|img|input|link|meta|param)([^>]*)><\/\\1>/s', |
'<\\1\\2 />', |
$xml |
); |
} else { |
return preg_replace( |
'/<(\w+)([^>]*)><\/\\1>/s', |
'<\\1\\2 />', |
$xml |
); |
} |
} |
/** |
* create a tag |
* |
* This method will call XML_Util::createTagFromArray(), which |
* is more flexible. |
* |
* <code> |
* require_once 'XML/Util.php'; |
* |
* // create an XML tag: |
* $tag = XML_Util::createTag("myNs:myTag", array("foo" => "bar"), "This is inside the tag", "http://www.w3c.org/myNs#"); |
* </code> |
* |
* @access public |
* @static |
* @param string $qname qualified tagname (including namespace) |
* @param array $attributes array containg attributes |
* @param mixed $content |
* @param string $namespaceUri URI of the namespace |
* @param integer $replaceEntities whether to replace XML special chars in content, embedd it in a CData section or none of both |
* @param boolean $multiline whether to create a multiline tag where each attribute gets written to a single line |
* @param string $indent string used to indent attributes (_auto indents attributes so they start at the same column) |
* @param string $linebreak string used for linebreaks |
* @param boolean $sortAttributes Whether to sort the attributes or not |
* @return string $string XML tag |
* @see XML_Util::createTagFromArray() |
* @uses XML_Util::createTagFromArray() to create the tag |
*/ |
function createTag($qname, $attributes = array(), $content = null, $namespaceUri = null, $replaceEntities = XML_UTIL_REPLACE_ENTITIES, $multiline = false, $indent = "_auto", $linebreak = "\n", $sortAttributes = true) |
{ |
$tag = array( |
"qname" => $qname, |
"attributes" => $attributes |
); |
// add tag content |
if ($content !== null) { |
$tag["content"] = $content; |
} |
// add namespace Uri |
if ($namespaceUri !== null) { |
$tag["namespaceUri"] = $namespaceUri; |
} |
return XML_Util::createTagFromArray($tag, $replaceEntities, $multiline, $indent, $linebreak, $sortAttributes); |
} |
/** |
* create a tag from an array |
* this method awaits an array in the following format |
* <pre> |
* array( |
* "qname" => $qname // qualified name of the tag |
* "namespace" => $namespace // namespace prefix (optional, if qname is specified or no namespace) |
* "localpart" => $localpart, // local part of the tagname (optional, if qname is specified) |
* "attributes" => array(), // array containing all attributes (optional) |
* "content" => $content, // tag content (optional) |
* "namespaceUri" => $namespaceUri // namespaceUri for the given namespace (optional) |
* ) |
* </pre> |
* |
* <code> |
* require_once 'XML/Util.php'; |
* |
* $tag = array( |
* "qname" => "foo:bar", |
* "namespaceUri" => "http://foo.com", |
* "attributes" => array( "key" => "value", "argh" => "fruit&vegetable" ), |
* "content" => "I'm inside the tag", |
* ); |
* // creating a tag with qualified name and namespaceUri |
* $string = XML_Util::createTagFromArray($tag); |
* </code> |
* |
* @access public |
* @static |
* @param array $tag tag definition |
* @param integer $replaceEntities whether to replace XML special chars in content, embedd it in a CData section or none of both |
* @param boolean $multiline whether to create a multiline tag where each attribute gets written to a single line |
* @param string $indent string used to indent attributes (_auto indents attributes so they start at the same column) |
* @param string $linebreak string used for linebreaks |
* @param boolean $sortAttributes Whether to sort the attributes or not |
* @return string $string XML tag |
* @see XML_Util::createTag() |
* @uses XML_Util::attributesToString() to serialize the attributes of the tag |
* @uses XML_Util::splitQualifiedName() to get local part and namespace of a qualified name |
*/ |
function createTagFromArray($tag, $replaceEntities = XML_UTIL_REPLACE_ENTITIES, $multiline = false, $indent = "_auto", $linebreak = "\n", $sortAttributes = true) |
{ |
if (isset($tag['content']) && !is_scalar($tag['content'])) { |
return XML_Util::raiseError( 'Supplied non-scalar value as tag content', XML_UTIL_ERROR_NON_SCALAR_CONTENT ); |
} |
if (!isset($tag['qname']) && !isset($tag['localPart'])) { |
return XML_Util::raiseError( 'You must either supply a qualified name (qname) or local tag name (localPart).', XML_UTIL_ERROR_NO_TAG_NAME ); |
} |
// if no attributes hav been set, use empty attributes |
if (!isset($tag["attributes"]) || !is_array($tag["attributes"])) { |
$tag["attributes"] = array(); |
} |
if (isset($tag['namespaces'])) { |
foreach ($tag['namespaces'] as $ns => $uri) { |
$tag['attributes']['xmlns:'.$ns] = $uri; |
} |
} |
// qualified name is not given |
if (!isset($tag["qname"])) { |
// check for namespace |
if (isset($tag["namespace"]) && !empty($tag["namespace"])) { |
$tag["qname"] = $tag["namespace"].":".$tag["localPart"]; |
} else { |
$tag["qname"] = $tag["localPart"]; |
} |
// namespace URI is set, but no namespace |
} elseif (isset($tag["namespaceUri"]) && !isset($tag["namespace"])) { |
$parts = XML_Util::splitQualifiedName($tag["qname"]); |
$tag["localPart"] = $parts["localPart"]; |
if (isset($parts["namespace"])) { |
$tag["namespace"] = $parts["namespace"]; |
} |
} |
if (isset($tag["namespaceUri"]) && !empty($tag["namespaceUri"])) { |
// is a namespace given |
if (isset($tag["namespace"]) && !empty($tag["namespace"])) { |
$tag["attributes"]["xmlns:".$tag["namespace"]] = $tag["namespaceUri"]; |
} else { |
// define this Uri as the default namespace |
$tag["attributes"]["xmlns"] = $tag["namespaceUri"]; |
} |
} |
// check for multiline attributes |
if ($multiline === true) { |
if ($indent === "_auto") { |
$indent = str_repeat(" ", (strlen($tag["qname"])+2)); |
} |
} |
// create attribute list |
$attList = XML_Util::attributesToString($tag['attributes'], $sortAttributes, $multiline, $indent, $linebreak, $replaceEntities ); |
if (!isset($tag['content']) || (string)$tag['content'] == '') { |
$tag = sprintf('<%s%s />', $tag['qname'], $attList); |
} else { |
switch ($replaceEntities) { |
case XML_UTIL_ENTITIES_NONE: |
break; |
case XML_UTIL_CDATA_SECTION: |
$tag['content'] = XML_Util::createCDataSection($tag['content']); |
break; |
default: |
$tag['content'] = XML_Util::replaceEntities($tag['content'], $replaceEntities); |
break; |
} |
$tag = sprintf('<%s%s>%s</%s>', $tag['qname'], $attList, $tag['content'], $tag['qname'] ); |
} |
return $tag; |
} |
/** |
* create a start element |
* |
* <code> |
* require_once 'XML/Util.php'; |
* |
* // create an XML start element: |
* $tag = XML_Util::createStartElement("myNs:myTag", array("foo" => "bar") ,"http://www.w3c.org/myNs#"); |
* </code> |
* |
* @access public |
* @static |
* @param string $qname qualified tagname (including namespace) |
* @param array $attributes array containg attributes |
* @param string $namespaceUri URI of the namespace |
* @param boolean $multiline whether to create a multiline tag where each attribute gets written to a single line |
* @param string $indent string used to indent attributes (_auto indents attributes so they start at the same column) |
* @param string $linebreak string used for linebreaks |
* @param boolean $sortAttributes Whether to sort the attributes or not |
* @return string $string XML start element |
* @see XML_Util::createEndElement(), XML_Util::createTag() |
*/ |
function createStartElement($qname, $attributes = array(), $namespaceUri = null, $multiline = false, $indent = '_auto', $linebreak = "\n", $sortAttributes = true) |
{ |
// if no attributes hav been set, use empty attributes |
if (!isset($attributes) || !is_array($attributes)) { |
$attributes = array(); |
} |
if ($namespaceUri != null) { |
$parts = XML_Util::splitQualifiedName($qname); |
} |
// check for multiline attributes |
if ($multiline === true) { |
if ($indent === "_auto") { |
$indent = str_repeat(" ", (strlen($qname)+2)); |
} |
} |
if ($namespaceUri != null) { |
// is a namespace given |
if (isset($parts["namespace"]) && !empty($parts["namespace"])) { |
$attributes["xmlns:".$parts["namespace"]] = $namespaceUri; |
} else { |
// define this Uri as the default namespace |
$attributes["xmlns"] = $namespaceUri; |
} |
} |
// create attribute list |
$attList = XML_Util::attributesToString($attributes, $sortAttributes, $multiline, $indent, $linebreak); |
$element = sprintf("<%s%s>", $qname, $attList); |
return $element; |
} |
/** |
* create an end element |
* |
* <code> |
* require_once 'XML/Util.php'; |
* |
* // create an XML start element: |
* $tag = XML_Util::createEndElement("myNs:myTag"); |
* </code> |
* |
* @access public |
* @static |
* @param string $qname qualified tagname (including namespace) |
* @return string $string XML end element |
* @see XML_Util::createStartElement(), XML_Util::createTag() |
*/ |
function createEndElement($qname) |
{ |
$element = sprintf("</%s>", $qname); |
return $element; |
} |
/** |
* create an XML comment |
* |
* <code> |
* require_once 'XML/Util.php'; |
* |
* // create an XML start element: |
* $tag = XML_Util::createComment("I am a comment"); |
* </code> |
* |
* @access public |
* @static |
* @param string $content content of the comment |
* @return string $comment XML comment |
*/ |
function createComment($content) |
{ |
$comment = sprintf("<!-- %s -->", $content); |
return $comment; |
} |
/** |
* create a CData section |
* |
* <code> |
* require_once 'XML/Util.php'; |
* |
* // create a CData section |
* $tag = XML_Util::createCDataSection("I am content."); |
* </code> |
* |
* @access public |
* @static |
* @param string $data data of the CData section |
* @return string $string CData section with content |
*/ |
function createCDataSection($data) |
{ |
return sprintf("<![CDATA[%s]]>", $data); |
} |
/** |
* split qualified name and return namespace and local part |
* |
* <code> |
* require_once 'XML/Util.php'; |
* |
* // split qualified tag |
* $parts = XML_Util::splitQualifiedName("xslt:stylesheet"); |
* </code> |
* the returned array will contain two elements: |
* <pre> |
* array( |
* "namespace" => "xslt", |
* "localPart" => "stylesheet" |
* ); |
* </pre> |
* |
* @access public |
* @static |
* @param string $qname qualified tag name |
* @param string $defaultNs default namespace (optional) |
* @return array $parts array containing namespace and local part |
*/ |
function splitQualifiedName($qname, $defaultNs = null) |
{ |
if (strstr($qname, ':')) { |
$tmp = explode(":", $qname); |
return array( |
"namespace" => $tmp[0], |
"localPart" => $tmp[1] |
); |
} |
return array( |
"namespace" => $defaultNs, |
"localPart" => $qname |
); |
} |
/** |
* check, whether string is valid XML name |
* |
* <p>XML names are used for tagname, attribute names and various |
* other, lesser known entities.</p> |
* <p>An XML name may only consist of alphanumeric characters, |
* dashes, undescores and periods, and has to start with a letter |
* or an underscore. |
* </p> |
* |
* <code> |
* require_once 'XML/Util.php'; |
* |
* // verify tag name |
* $result = XML_Util::isValidName("invalidTag?"); |
* if (XML_Util::isError($result)) { |
* print "Invalid XML name: " . $result->getMessage(); |
* } |
* </code> |
* |
* @access public |
* @static |
* @param string $string string that should be checked |
* @return mixed $valid true, if string is a valid XML name, PEAR error otherwise |
* @todo support for other charsets |
*/ |
function isValidName($string) |
{ |
// check for invalid chars |
if (!preg_match('/^[[:alpha:]_]$/', $string{0})) { |
return XML_Util::raiseError('XML names may only start with letter or underscore', XML_UTIL_ERROR_INVALID_START); |
} |
// check for invalid chars |
if (!preg_match('/^([[:alpha:]_]([[:alnum:]\-\.]*)?:)?[[:alpha:]_]([[:alnum:]\_\-\.]+)?$/', $string)) { |
return XML_Util::raiseError('XML names may only contain alphanumeric chars, period, hyphen, colon and underscores', XML_UTIL_ERROR_INVALID_CHARS); |
} |
// XML name is valid |
return true; |
} |
/** |
* replacement for XML_Util::raiseError |
* |
* Avoids the necessity to always require |
* PEAR.php |
* |
* @access public |
* @param string error message |
* @param integer error code |
* @return object PEAR_Error |
*/ |
function raiseError($msg, $code) |
{ |
require_once 'PEAR.php'; |
return PEAR::raiseError($msg, $code); |
} |
} |
?> |
/trunk/jrest/XML/Tree.php |
---|
New file |
0,0 → 1,370 |
<?php |
// |
// +----------------------------------------------------------------------+ |
// | PHP Version 4 | |
// +----------------------------------------------------------------------+ |
// | Copyright (c) 1997-2002 The PHP Group | |
// +----------------------------------------------------------------------+ |
// | This source file is subject to version 2.02 of the PHP license, | |
// | that is bundled with this package in the file LICENSE, and is | |
// | available at through the world-wide-web at | |
// | http://www.php.net/license/2_02.txt. | |
// | If you did not receive a copy of the PHP license and are unable to | |
// | obtain it through the world-wide-web, please send a note to | |
// | license@php.net so we can mail you a copy immediately. | |
// +----------------------------------------------------------------------+ |
// | Authors: Bernd Römer <berndr@bonn.edu> | |
// | Sebastian Bergmann <sb@sebastian-bergmann.de> | |
// | Tomas V.V.Cox <cox@idecnet.com> (tree mapping from xml file)| |
// +----------------------------------------------------------------------+ |
// |
// $Id: Tree.php,v 1.1 2005-04-18 16:13:31 jpm Exp $ |
// |
require_once 'XML/Parser.php'; |
require_once 'XML/Tree/Node.php'; |
/** |
* PEAR::XML_Tree |
* |
* Purpose |
* |
* Allows for the building of XML data structures |
* using a tree representation, without the need |
* for an extension like DOMXML. |
* |
* Example |
* |
* $tree = new XML_Tree; |
* $root =& $tree->addRoot('root'); |
* $foo =& $root->addChild('foo'); |
* |
* header('Content-Type: text/xml'); |
* $tree->dump(); |
* |
* @author Bernd Römer <berndr@bonn.edu> |
* @package XML |
* @version $Version$ - 1.0 |
*/ |
class XML_Tree extends XML_Parser |
{ |
/** |
* File Handle |
* |
* @var ressource |
*/ |
var $file = NULL; |
/** |
* Filename |
* |
* @var string |
*/ |
var $filename = ''; |
/** |
* Namespace |
* |
* @var array |
*/ |
var $namespace = array(); |
/** |
* Root |
* |
* @var object XML_Tree_Node |
*/ |
var $root = NULL; |
/** |
* XML Version |
* |
* @var string |
*/ |
var $version = '1.0'; |
/** |
* Constructor |
* |
* @param string Filename |
* @param string XML Version |
*/ |
function XML_Tree($filename = '', $version = '1.0') { |
$this->filename = $filename; |
$this->version = $version; |
} |
/** |
* Add root node. |
* |
* @param string $name name of root element |
* @return object XML_Tree_Node reference to root node |
* |
* @access public |
*/ |
function &addRoot($name, $content = '', $attributes = array()) { |
$this->root = new XML_Tree_Node($name, $content, $attributes); |
return $this->root; |
} |
/** |
* @deprecated |
*/ |
function &add_root($name, $content = '', $attributes = array()) { |
return $this->addRoot($name, $content, $attributes); |
} |
/** |
* inserts a child/tree (child) into tree ($path,$pos) and |
* maintains namespace integrity |
* |
* @param array $path path to parent of child to remove |
* @param integer $pos position of child to be inserted in its parents children-list |
* @param mixed $child child-node (by XML_Tree,XML_Node or Name) |
* @param string $content content (text) for new node |
* @param array $attributes attribute-hash for new node |
* |
* @return object XML_Tree_Node inserted child (node) |
* @access public |
*/ |
function &insertChild($path,$pos,$child, $content = '', $attributes = array()) { |
// update namespace to maintain namespace integrity |
$count=count($path); |
foreach($this->namespace as $key => $val) { |
if ((array_slice($val,0,$count)==$path) && ($val[$count]>=$pos)) |
$this->namespace[$key][$count]++; |
} |
$parent=&$this->get_node_by_path($path); |
return($parent->insert_child($pos,$child,$content,$attributes)); |
} |
/** |
* @deprecated |
*/ |
function &insert_child($path,$pos,$child, $content = '', $attributes = array()) { |
return $this->insertChild($path, $child, $content, $attributes); |
} |
/* |
* removes a child ($path,$pos) from tree ($path,$pos) and |
* maintains namespace integrity |
* |
* @param array $path path to parent of child to remove |
* @param integer $pos position of child in parents children-list |
* |
* @return object XML_Tree_Node parent whichs child was removed |
* @access public |
*/ |
function &removeChild($path,$pos) { |
// update namespace to maintain namespace integrity |
$count=count($path); |
foreach($this->namespace as $key => $val) { |
if (array_slice($val,0,$count)==$path) { |
if ($val[$count]==$pos) { unset($this->namespace[$key]); break; } |
if ($val[$count]>$pos) |
$this->namespace[$key][$count]--; |
} |
} |
$parent=&$this->get_node_by_path($path); |
return($parent->remove_child($pos)); |
} |
/** |
* @deprecated |
*/ |
function &remove_child($path, $pos) { |
return $this->removeChild($path, $pos); |
} |
/* |
* Maps a xml file to a objects tree |
* |
* @return mixed The objects tree (XML_tree or an Pear error) |
* @access public |
*/ |
function &getTreeFromFile () |
{ |
$this->folding = false; |
$this->XML_Parser(null, 'event'); |
$err = $this->setInputFile($this->filename); |
if (PEAR::isError($err)) { |
return $err; |
} |
$this->cdata = null; |
$err = $this->parse(); |
if (PEAR::isError($err)) { |
return $err; |
} |
return $this->root; |
} |
function getTreeFromString($str) |
{ |
$this->folding = false; |
$this->XML_Parser(null, 'event'); |
$this->cdata = null; |
$err = $this->parseString($str); |
if (PEAR::isError($err)) { |
return $err; |
} |
return $this->root; |
} |
/** |
* Handler for the xml-data |
* |
* @param mixed $xp ignored |
* @param string $elem name of the element |
* @param array $attribs attributes for the generated node |
* |
* @access private |
*/ |
function startHandler($xp, $elem, &$attribs) |
{ |
// root elem |
if (!isset($this->i)) { |
$this->obj1 =& $this->add_root($elem, null, $attribs); |
$this->i = 2; |
} else { |
// mixed contents |
if (!empty($this->cdata)) { |
$parent_id = 'obj' . ($this->i - 1); |
$parent =& $this->$parent_id; |
$parent->children[] = &new XML_Tree_Node(null, $this->cdata); |
} |
$obj_id = 'obj' . $this->i++; |
$this->$obj_id = &new XML_Tree_Node($elem, null, $attribs); |
} |
$this->cdata = null; |
return null; |
} |
/** |
* Handler for the xml-data |
* |
* @param mixed $xp ignored |
* @param string $elem name of the element |
* |
* @access private |
*/ |
function endHandler($xp, $elem) |
{ |
$this->i--; |
if ($this->i > 1) { |
$obj_id = 'obj' . $this->i; |
// recover the node created in StartHandler |
$node =& $this->$obj_id; |
// mixed contents |
if (count($node->children) > 0) { |
if (trim($this->cdata)) { |
$node->children[] = &new XML_Tree_Node(null, $this->cdata); |
} |
} else { |
$node->set_content($this->cdata); |
} |
$parent_id = 'obj' . ($this->i - 1); |
$parent =& $this->$parent_id; |
// attach the node to its parent node children array |
$parent->children[] = $node; |
} |
$this->cdata = null; |
return null; |
} |
/* |
* The xml character data handler |
* |
* @param mixed $xp ignored |
* @param string $data PCDATA between tags |
* |
* @access private |
*/ |
function cdataHandler($xp, $data) |
{ |
if (trim($data)) { |
$this->cdata .= $data; |
} |
} |
/** |
* Get a copy of this tree. |
* |
* @return object XML_Tree |
* @access public |
*/ |
function clone() { |
$clone=new XML_Tree($this->filename,$this->version); |
$clone->root=$this->root->clone(); |
// clone all other vars |
$temp=get_object_vars($this); |
foreach($temp as $varname => $value) |
if (!in_array($varname,array('filename','version','root'))) |
$clone->$varname=$value; |
return($clone); |
} |
/** |
* Print text representation of XML tree. |
* |
* @access public |
*/ |
function dump() { |
echo $this->get(); |
} |
/** |
* Get text representation of XML tree. |
* |
* @return string XML |
* @access public |
*/ |
function &get() { |
$out = '<?xml version="' . $this->version . "\"?>\n"; |
$out .= $this->root->get(); |
return $out; |
} |
/** |
* Get current namespace. |
* |
* @param string $name namespace |
* @return string |
* |
* @access public |
*/ |
function &getName($name) { |
return $this->root->get_element($this->namespace[$name]); |
} |
/** |
* @deprecated |
*/ |
function &get_name($name) { |
return $this->getName($name); |
} |
/** |
* Register a namespace. |
* |
* @param string $name namespace |
* @param string $path path |
* |
* @access public |
*/ |
function registerName($name, $path) { |
$this->namespace[$name] = $path; |
} |
/** |
* @deprecated |
*/ |
function register_name($name, $path) { |
return $this->registerName($name, $path); |
} |
} |
?> |
/trunk/jrest/XML/Parser/Simple.php |
---|
New file |
0,0 → 1,297 |
<?php |
// |
// +----------------------------------------------------------------------+ |
// | PHP Version 4 | |
// +----------------------------------------------------------------------+ |
// | Copyright (c) 1997-2004 The PHP Group | |
// +----------------------------------------------------------------------+ |
// | This source file is subject to version 3.0 of the PHP license, | |
// | that is bundled with this package in the file LICENSE, and is | |
// | available at through the world-wide-web at | |
// | http://www.php.net/license/3_0.txt. | |
// | If you did not receive a copy of the PHP license and are unable to | |
// | obtain it through the world-wide-web, please send a note to | |
// | license@php.net so we can mail you a copy immediately. | |
// +----------------------------------------------------------------------+ |
// | Author: Stephan Schmidt <schst@php-tools.net> | |
// +----------------------------------------------------------------------+ |
// |
// $Id: Simple.php,v 1.1 2005-04-18 16:13:31 jpm Exp $ |
/** |
* Simple XML parser class. |
* |
* This class is a simplified version of XML_Parser. |
* In most XML applications the real action is executed, |
* when a closing tag is found. |
* |
* XML_Parser_Simple allows you to just implement one callback |
* for each tag that will receive the tag with its attributes |
* and CData |
* |
* @category XML |
* @package XML_Parser |
* @author Stephan Schmidt <schst@php-tools.net> |
*/ |
/** |
* built on XML_Parser |
*/ |
require_once 'XML/Parser.php'; |
/** |
* Simple XML parser class. |
* |
* This class is a simplified version of XML_Parser. |
* In most XML applications the real action is executed, |
* when a closing tag is found. |
* |
* XML_Parser_Simple allows you to just implement one callback |
* for each tag that will receive the tag with its attributes |
* and CData. |
* |
* <code> |
* require_once '../Parser/Simple.php'; |
* |
* class myParser extends XML_Parser_Simple |
* { |
* function myParser() |
* { |
* $this->XML_Parser_Simple(); |
* } |
* |
* function handleElement($name, $attribs, $data) |
* { |
* printf('handle %s<br>', $name); |
* } |
* } |
* |
* $p = &new myParser(); |
* |
* $result = $p->setInputFile('myDoc.xml'); |
* $result = $p->parse(); |
* </code> |
* |
* @category XML |
* @package XML_Parser |
* @author Stephan Schmidt <schst@php-tools.net> |
*/ |
class XML_Parser_Simple extends XML_Parser |
{ |
/** |
* element stack |
* |
* @access private |
* @var array |
*/ |
var $_elStack = array(); |
/** |
* all character data |
* |
* @access private |
* @var array |
*/ |
var $_data = array(); |
/** |
* element depth |
* |
* @access private |
* @var integer |
*/ |
var $_depth = 0; |
/** |
* Mapping from expat handler function to class method. |
* |
* @var array |
*/ |
var $handler = array( |
'default_handler' => 'defaultHandler', |
'processing_instruction_handler' => 'piHandler', |
'unparsed_entity_decl_handler' => 'unparsedHandler', |
'notation_decl_handler' => 'notationHandler', |
'external_entity_ref_handler' => 'entityrefHandler' |
); |
/** |
* Creates an XML parser. |
* |
* This is needed for PHP4 compatibility, it will |
* call the constructor, when a new instance is created. |
* |
* @param string $srcenc source charset encoding, use NULL (default) to use |
* whatever the document specifies |
* @param string $mode how this parser object should work, "event" for |
* handleElement(), "func" to have it call functions |
* named after elements (handleElement_$name()) |
* @param string $tgenc a valid target encoding |
*/ |
function XML_Parser_Simple($srcenc = null, $mode = 'event', $tgtenc = null) |
{ |
$this->XML_Parser($srcenc, $mode, $tgtenc); |
} |
/** |
* inits the handlers |
* |
* @access private |
*/ |
function _initHandlers() |
{ |
if (!is_object($this->_handlerObj)) { |
$this->_handlerObj = &$this; |
} |
if ($this->mode != 'func' && $this->mode != 'event') { |
return $this->raiseError('Unsupported mode given', XML_PARSER_ERROR_UNSUPPORTED_MODE); |
} |
xml_set_object($this->parser, $this->_handlerObj); |
xml_set_element_handler($this->parser, array(&$this, 'startHandler'), array(&$this, 'endHandler')); |
xml_set_character_data_handler($this->parser, array(&$this, 'cdataHandler')); |
/** |
* set additional handlers for character data, entities, etc. |
*/ |
foreach ($this->handler as $xml_func => $method) { |
if (method_exists($this->_handlerObj, $method)) { |
$xml_func = 'xml_set_' . $xml_func; |
$xml_func($this->parser, $method); |
} |
} |
} |
/** |
* Reset the parser. |
* |
* This allows you to use one parser instance |
* to parse multiple XML documents. |
* |
* @access public |
* @return boolean|object true on success, PEAR_Error otherwise |
*/ |
function reset() |
{ |
$this->_elStack = array(); |
$this->_data = array(); |
$this->_depth = 0; |
$result = $this->_create(); |
if ($this->isError( $result )) { |
return $result; |
} |
return true; |
} |
/** |
* start handler |
* |
* Pushes attributes and tagname onto a stack |
* |
* @access private |
* @final |
* @param resource xml parser resource |
* @param string element name |
* @param array attributes |
*/ |
function startHandler($xp, $elem, &$attribs) |
{ |
array_push($this->_elStack, array( |
'name' => $elem, |
'attribs' => $attribs |
) |
); |
$this->_depth++; |
$this->_data[$this->_depth] = ''; |
} |
/** |
* end handler |
* |
* Pulls attributes and tagname from a stack |
* |
* @access private |
* @final |
* @param resource xml parser resource |
* @param string element name |
*/ |
function endHandler($xp, $elem) |
{ |
$el = array_pop($this->_elStack); |
$data = $this->_data[$this->_depth]; |
$this->_depth--; |
switch ($this->mode) { |
case 'event': |
$this->_handlerObj->handleElement($el['name'], $el['attribs'], $data); |
break; |
case 'func': |
$func = 'handleElement_' . $elem; |
if (strchr($func, '.')) { |
$func = str_replace('.', '_', $func); |
} |
if (method_exists($this->_handlerObj, $func)) { |
call_user_func(array(&$this->_handlerObj, $func), $el['name'], $el['attribs'], $data); |
} |
break; |
} |
} |
/** |
* handle character data |
* |
* @access private |
* @final |
* @param resource xml parser resource |
* @param string data |
*/ |
function cdataHandler($xp, $data) |
{ |
$this->_data[$this->_depth] .= $data; |
} |
/** |
* handle a tag |
* |
* Implement this in your parser |
* |
* @access public |
* @abstract |
* @param string element name |
* @param array attributes |
* @param string character data |
*/ |
function handleElement($name, $attribs, $data) |
{ |
} |
/** |
* get the current tag depth |
* |
* The root tag is in depth 0. |
* |
* @access public |
* @return integer |
*/ |
function getCurrentDepth() |
{ |
return $this->_depth; |
} |
/** |
* add some string to the current ddata. |
* |
* This is commonly needed, when a document is parsed recursively. |
* |
* @access public |
* @param string data to add |
* @return void |
*/ |
function addToData( $data ) |
{ |
$this->_data[$this->_depth] .= $data; |
} |
} |
?> |
/trunk/jrest/XML/RSS.php |
---|
New file |
0,0 → 1,359 |
<?php |
// vim: set expandtab tabstop=4 shiftwidth=4 fdm=marker: |
// +----------------------------------------------------------------------+ |
// | PHP Version 4 | |
// +----------------------------------------------------------------------+ |
// | Copyright (c) 1997-2003 The PHP Group | |
// +----------------------------------------------------------------------+ |
// | This source file is subject to version 2.02 of the PHP license, | |
// | that is bundled with this package in the file LICENSE, and is | |
// | available at through the world-wide-web at | |
// | http://www.php.net/license/2_02.txt. | |
// | If you did not receive a copy of the PHP license and are unable to | |
// | obtain it through the world-wide-web, please send a note to | |
// | license@php.net so we can mail you a copy immediately. | |
// +----------------------------------------------------------------------+ |
// | Authors: Martin Jansen <mj@php.net> | |
// | | |
// +----------------------------------------------------------------------+ |
// |
// $Id: RSS.php,v 1.1 2005-04-18 16:13:31 jpm Exp $ |
// |
require_once 'XML/Parser.php'; |
/** |
* RSS parser class. |
* |
* This class is a parser for Resource Description Framework (RDF) Site |
* Summary (RSS) documents. For more information on RSS see the |
* website of the RSS working group (http://www.purl.org/rss/). |
* |
* @author Martin Jansen <mj@php.net> |
* @version $Revision: 1.1 $ |
* @access public |
*/ |
class XML_RSS extends XML_Parser |
{ |
// {{{ properties |
/** |
* @var string |
*/ |
var $insideTag = ''; |
/** |
* @var string |
*/ |
var $activeTag = ''; |
/** |
* @var array |
*/ |
var $channel = array(); |
/** |
* @var array |
*/ |
var $items = array(); |
/** |
* @var array |
*/ |
var $item = array(); |
/** |
* @var array |
*/ |
var $image = array(); |
/** |
* @var array |
*/ |
var $textinput = array(); |
/** |
* @var array |
*/ |
var $textinputs = array(); |
/** |
* @var array |
*/ |
var $parentTags = array('CHANNEL', 'ITEM', 'IMAGE', 'TEXTINPUT'); |
/** |
* @var array |
*/ |
var $channelTags = array('TITLE', 'LINK', 'DESCRIPTION', 'IMAGE', |
'ITEMS', 'TEXTINPUT'); |
/** |
* @var array |
*/ |
var $itemTags = array('TITLE', 'LINK', 'DESCRIPTION', 'PUBDATE'); |
/** |
* @var array |
*/ |
var $imageTags = array('TITLE', 'URL', 'LINK'); |
var $textinputTags = array('TITLE', 'DESCRIPTION', 'NAME', 'LINK'); |
/** |
* List of allowed module tags |
* |
* Currently Dublin Core Metadata and the blogChannel RSS module |
* are supported. |
* |
* @var array |
*/ |
var $moduleTags = array('DC:TITLE', 'DC:CREATOR', 'DC:SUBJECT', 'DC:DESCRIPTION', |
'DC:PUBLISHER', 'DC:CONTRIBUTOR', 'DC:DATE', 'DC:TYPE', |
'DC:FORMAT', 'DC:IDENTIFIER', 'DC:SOURCE', 'DC:LANGUAGE', |
'DC:RELATION', 'DC:COVERAGE', 'DC:RIGHTS', |
'BLOGCHANNEL:BLOGROLL', 'BLOGCHANNEL:MYSUBSCRIPTIONS', |
'BLOGCHANNEL:MYSUBSCRIPTIONS', 'BLOGCHANNEL:CHANGES'); |
// }}} |
// {{{ Constructor |
/** |
* Constructor |
* |
* @access public |
* @param mixed File pointer or name of the RDF file. |
* @return void |
*/ |
function XML_RSS($handle = '') |
{ |
$this->XML_Parser(); |
if (@is_resource($handle)) { |
$this->setInput($handle); |
} elseif ($handle != '') { |
$this->setInputFile($handle); |
} else { |
$this->raiseError('No filename passed.'); |
} |
} |
// }}} |
// {{{ startHandler() |
/** |
* Start element handler for XML parser |
* |
* @access private |
* @param object XML parser object |
* @param string XML element |
* @param array Attributes of XML tag |
* @return void |
*/ |
function startHandler($parser, $element, $attribs) |
{ |
switch ($element) { |
case 'CHANNEL': |
case 'ITEM': |
case 'IMAGE': |
case 'TEXTINPUT': |
$this->insideTag = $element; |
break; |
default: |
$this->activeTag = $element; |
} |
} |
// }}} |
// {{{ endHandler() |
/** |
* End element handler for XML parser |
* |
* If the end of <item>, <channel>, <image> or <textinput> |
* is reached, this function updates the structure array |
* $this->struct[] and adds the field "type" to this array, |
* that defines the type of the current field. |
* |
* @access private |
* @param object XML parser object |
* @param string |
* @return void |
*/ |
function endHandler($parser, $element) |
{ |
if ($element == $this->insideTag) { |
$this->insideTag = ''; |
$this->struct[] = array_merge(array('type' => strtolower($element)), |
$this->last); |
} |
if ($element == 'ITEM') { |
$this->items[] = $this->item; |
$this->item = ''; |
} |
if ($element == 'IMAGE') { |
$this->images[] = $this->image; |
$this->image = ''; |
} |
if ($element == 'TEXTINPUT') { |
$this->textinputs = $this->textinput; |
$this->textinput = ''; |
} |
$this->activeTag = ''; |
} |
// }}} |
// {{{ cdataHandler() |
/** |
* Handler for character data |
* |
* @access private |
* @param object XML parser object |
* @param string CDATA |
* @return void |
*/ |
function cdataHandler($parser, $cdata) |
{ |
if (in_array($this->insideTag, $this->parentTags)) { |
$tagName = strtolower($this->insideTag); |
$var = $this->{$tagName . 'Tags'}; |
if (in_array($this->activeTag, $var) || |
in_array($this->activeTag, $this->moduleTags)) { |
$this->_add($tagName, strtolower($this->activeTag), |
$cdata); |
} |
} |
} |
// }}} |
// {{{ defaultHandler() |
/** |
* Default handler for XML parser |
* |
* @access private |
* @param object XML parser object |
* @param string CDATA |
* @return void |
*/ |
function defaultHandler($parser, $cdata) |
{ |
return; |
} |
// }}} |
// {{{ _add() |
/** |
* Add element to internal result sets |
* |
* @access private |
* @param string Name of the result set |
* @param string Fieldname |
* @param string Value |
* @return void |
* @see cdataHandler |
*/ |
function _add($type, $field, $value) |
{ |
if (empty($this->{$type}) || empty($this->{$type}[$field])) { |
$this->{$type}[$field] = $value; |
} else { |
$this->{$type}[$field] .= $value; |
} |
$this->last = $this->{$type}; |
} |
// }}} |
// {{{ getStructure() |
/** |
* Get complete structure of RSS file |
* |
* @access public |
* @return array |
*/ |
function getStructure() |
{ |
return (array)$this->struct; |
} |
// }}} |
// {{{ getchannelInfo() |
/** |
* Get general information about current channel |
* |
* This function returns an array containing the information |
* that has been extracted from the <channel>-tag while parsing |
* the RSS file. |
* |
* @access public |
* @return array |
*/ |
function getChannelInfo() |
{ |
return (array)$this->channel; |
} |
// }}} |
// {{{ getItems() |
/** |
* Get items from RSS file |
* |
* This function returns an array containing the set of items |
* that are provided by the RSS file. |
* |
* @access public |
* @return array |
*/ |
function getItems() |
{ |
return (array)$this->items; |
} |
// }}} |
// {{{ getImages() |
/** |
* Get images from RSS file |
* |
* This function returns an array containing the set of images |
* that are provided by the RSS file. |
* |
* @access public |
* @return array |
*/ |
function getImages() |
{ |
return (array)$this->images; |
} |
// }}} |
// {{{ getTextinputs() |
/** |
* Get text input fields from RSS file |
* |
* @access public |
* @return array |
*/ |
function getTextinputs() |
{ |
return (array)$this->textinputs; |
} |
// }}} |
} |
?> |
/trunk/jrest/XML/Tree/Node.php |
---|
New file |
0,0 → 1,354 |
<?php |
// |
// +----------------------------------------------------------------------+ |
// | PHP Version 4 | |
// +----------------------------------------------------------------------+ |
// | Copyright (c) 1997-2002 The PHP Group | |
// +----------------------------------------------------------------------+ |
// | This source file is subject to version 2.02 of the PHP license, | |
// | that is bundled with this package in the file LICENSE, and is | |
// | available at through the world-wide-web at | |
// | http://www.php.net/license/2_02.txt. | |
// | If you did not receive a copy of the PHP license and are unable to | |
// | obtain it through the world-wide-web, please send a note to | |
// | license@php.net so we can mail you a copy immediately. | |
// +----------------------------------------------------------------------+ |
// | Authors: Bernd Römer <berndr@bonn.edu> | |
// | Sebastian Bergmann <sb@sebastian-bergmann.de> | |
// | Christian Kühn <ck@chkuehn.de> (escape xml entities) | |
// +----------------------------------------------------------------------+ |
// |
// $Id: Node.php,v 1.1 2005-04-18 16:13:31 jpm Exp $ |
// |
/** |
* PEAR::XML_Tree_Node |
* |
* @author Bernd Römer <berndr@bonn.edu> |
* @package XML_Tree |
* @version 1.0 16-Aug-2001 |
*/ |
class XML_Tree_Node { |
/** |
* Attributes of this node |
* |
* @var array |
*/ |
var $attributes; |
/** |
* Children of this node |
* |
* @var array |
*/ |
var $children; |
/** |
* Content |
* |
* @var string |
*/ |
var $content; |
/** |
* Name |
* |
* @var string |
*/ |
var $name; |
/** |
* Constructor |
* |
* @param string name |
* @param string content |
* @param array attributes |
*/ |
function XML_Tree_Node($name, $content = '', $attributes = array()) { |
$this->attributes = $attributes; |
$this->children = array(); |
$this->set_content($content); |
$this->name = $name; |
} |
/** |
* Adds a child node to this node. |
* |
* @param mixed child |
* @param string content |
* @param array attributes |
* @return object reference to new child node |
*/ |
function &addChild($child, $content = '', $attributes = array()) { |
$index = sizeof($this->children); |
if (is_object($child)) { |
if (strtolower(get_class($child)) == 'xml_tree_node') { |
$this->children[$index] = $child; |
} |
if (strtolower(get_class($child)) == 'xml_tree' && isset($child->root)) { |
$this->children[$index] = $child->root->get_element(); |
} |
} else { |
$this->children[$index] = new XML_Tree_Node($child, $content, $attributes); |
} |
return $this->children[$index]; |
} |
/** |
* @deprecated |
*/ |
function &add_child($child, $content = '', $attributes = array()) { |
return $this->addChild($child, $content, $attributes); |
} |
/** |
* clone node and all its children (recursive) |
* |
* @return object reference to the clone-node |
*/ |
function &clone() { |
$clone=new XML_Tree_Node($this->name,$this->content,$this->attributes); |
$max_child=count($this->children); |
for($i=0;$i<$max_child;$i++) { |
$clone->children[]=$this->children[$i]->clone(); |
} |
/* for future use.... |
// clone all other vars |
$temp=get_object_vars($this); |
foreach($temp as $varname => $value) |
if (!in_array($varname,array('name','content','attributes','children'))) |
$clone->$varname=$value; |
*/ |
return($clone); |
} |
/** |
* inserts child ($child) to a specified child-position ($pos) |
* |
* @return inserted node |
*/ |
function &insertChild($path,$pos,&$child, $content = '', $attributes = array()) { |
// direct insert of objects useing array_splice() faild :( |
array_splice($this->children,$pos,0,'dummy'); |
if (is_object($child)) { // child offered is not instanziated |
// insert a single node |
if (strtolower(get_class($child)) == 'xml_tree_node') { |
$this->children[$pos]=&$child; |
} |
// insert a tree i.e insert root-element |
if (strtolower(get_class($child)) == 'xml_tree' && isset($child->root)) { |
$this->children[$pos]=$child->root->get_element(); |
} |
} else { // child offered is not instanziated |
$this->children[$pos]=new XML_Tree_Node($child, $content, $attributes); |
} |
return($this); |
} |
/** |
* @deprecated |
*/ |
function &insert_child($path,$pos,&$child, $content = '', $attributes = array()) { |
return $this->insertChild($path,$pos,$child, $content, $attributes); |
} |
/** |
* removes child ($pos) |
* |
* @param integer pos position of child in children-list |
* |
* @return removed node |
*/ |
function &removeChild($pos) { |
// array_splice() instead of a simple unset() to maintain index-integrity |
return(array_splice($this->children,$pos,1)); |
} |
/** |
* @deprecated |
*/ |
function &remove_child($pos) { |
return $this->removeChild($pos); |
} |
/** |
* Returns text representation of this node. |
* |
* @return string xml |
*/ |
function &get() |
{ |
static $deep = -1; |
static $do_ident = true; |
$deep++; |
if ($this->name !== null) { |
$ident = str_repeat(' ', $deep); |
if ($do_ident) { |
$out = $ident . '<' . $this->name; |
} else { |
$out = '<' . $this->name; |
} |
foreach ($this->attributes as $name => $value) { |
$out .= ' ' . $name . '="' . $value . '"'; |
} |
$out .= '>' . $this->content; |
if (sizeof($this->children) > 0) { |
$out .= "\n"; |
foreach ($this->children as $child) { |
$out .= $child->get(); |
} |
} else { |
$ident = ''; |
} |
if ($do_ident) { |
$out .= $ident . '</' . $this->name . ">\n"; |
} else { |
$out .= '</' . $this->name . '>'; |
} |
$do_ident = true; |
} else { |
$out = $this->content; |
$do_ident = false; |
} |
$deep--; |
return $out; |
} |
/** |
* Gets an attribute by its name. |
* |
* @param string name |
* @return string attribute |
*/ |
function getAttribute($name) { |
return $this->attributes[strtolower($name)]; |
} |
/** |
* @deprecated |
*/ |
function get_attribute($name) { |
return $this->getAttribute($name); |
} |
/** |
* Gets an element by its 'path'. |
* |
* @param string path |
* @return object element |
*/ |
function &getElement($path) { |
if (sizeof($path) == 0) { |
return $this; |
} |
$next = array_shift($path); |
return $this->children[$next]->get_element($path); |
} |
/** |
* @deprecated |
*/ |
function &get_element($path) { |
return $this->getElement($path); |
} |
/** |
* Sets an attribute. |
* |
* @param string name |
* @param string value |
*/ |
function setAttribute($name, $value = '') { |
$this->attributes[strtolower($name)] = $value; |
} |
/** |
* @deprecated |
*/ |
function set_attribute($name, $value = '') { |
return $this->setAttribute($name, $value); |
} |
/** |
* Unsets an attribute. |
* |
* @param string name |
*/ |
function unsetAttribute($name) { |
unset($this->attributes[strtolower($name)]); |
} |
/** |
* @deprecated |
*/ |
function unset_attribute($name) { |
return $this->unsetAttribute($name); |
} |
/** |
* |
* |
*/ |
function setContent(&$content) |
{ |
$this->content = $this->_xml_entities($content); |
} |
function set_content(&$content) |
{ |
return $this->setContent($content); |
} |
/** |
* Escape XML entities. |
* |
* @param string xml |
* @return string xml |
* @access private |
*/ |
function _xml_entities($xml) { |
$xml = str_replace(array('ü', 'Ü', 'ö', |
'Ö', 'ä', 'Ä', |
'ß' |
), |
array('ü', 'Ü', 'ö', |
'Ö', 'ä', 'Ä', |
'ß' |
), |
$xml |
); |
$xml = preg_replace(array("/\&([a-z\d\#]+)\;/i", |
"/\&/", |
"/\#\|\|([a-z\d\#]+)\|\|\#/i", |
"/([^a-zA-Z\d\s\<\>\&\;\.\:\=\"\-\/\%\?\!\'\(\)\[\]\{\}\$\#\+\,\@_])/e" |
), |
array("#||\\1||#", |
"&", |
"&\\1;", |
"'&#'.ord('\\1').';'" |
), |
$xml |
); |
return $xml; |
} |
/** |
* Print text representation of XML tree. |
*/ |
function dump() { |
echo $this->get(); |
} |
} |
?> |
/trunk/jrest/services/Resume.php |
---|
1,108 → 1,107 |
<?php |
/** |
* PHP Version 5 |
* |
* @category PHP |
* @package papyrus_bp |
* @author aurelien <aurelien@tela-botanica.org> |
* @copyright 2010 Tela-Botanica |
* @license http://www.cecill.info/licences/Licence_CeCILL_V2-fr.txt Licence CECILL |
* @version SVN: <svn_id> |
* @link /doc/papyrus_bp/ |
*/ |
Class Resume extends ProjetService { |
public function __construct($config, $demarrer_session= true) { |
parent::__construct($config, $demarrer_session); |
} |
public function getElement($uid){ |
$id_utilisateur = $uid[0]; |
$mail_utilisateur = $uid[1]; |
// on selectionne les projets les plus actifs |
$requete_projets = 'SELECT DISTINCT *'. |
' FROM projet_statistiques'. |
' WHERE ps_ce_projet'. |
' IN '. |
'(SELECT psu_id_projet FROM projet_statut_utilisateurs'. |
' WHERE psu_id_utilisateur = '.$this->bdd->quote($id_utilisateur).')'. |
' GROUP BY ps_ce_projet'. |
' ORDER BY ps_msg_derniere_semaine DESC'. |
' LIMIT 0,5'; |
$resume = array(); |
$resume['titre'] = 'Vos projets les plus actifs'; |
$resume['lien_appli'] = '<a href="http://www.tela-botanica.org/page:liste_projets"> Voir tous les projets </a>'; |
$projets = $this->bdd->query($requete_projets)->fetchAll(); |
if(!$projets) { |
$resume['message'] = 'Vous n\'êtes inscrit à aucun projet'; |
} else { |
foreach($projets as $projet) { |
$requete_info_projet = 'SELECT p_titre'. |
' FROM projet'. |
' WHERE p_id = '.$this->bdd->quote($projet['ps_ce_projet']); |
$projet_infos = $this->bdd->query($requete_info_projet)->fetchAll(); |
$infos_messages = ''; |
if($projet['ps_msg_derniere_semaine'] > 0) { |
$infos_messages = ' (+ '.$projet['ps_msg_derniere_semaine'].' nouveaux messages) '; |
} else { |
$infos_messages = ' (aucun nouveau message) '; |
} |
$cible_lien = 'http://www.tela-botanica.org/page:liste_projets?id_projet='.$projet['ps_ce_projet']; |
$resume_item = array('element' => $projet_infos[0]['p_titre'].$infos_messages, 'lien' => $cible_lien); |
$resume['elements'][] = $resume_item; |
} |
} |
$this->envoyer($resume); |
} |
public function gererInscription($id_utilisateur, $mail_utilisateur) { |
$requete_projets_utilisateur = 'SELECT * FROM projet_statut_utilisateurs'. |
' WHERE psu_id_utilisateur = '.$this->bdd->quote($id_utilisateur); |
$resume = ''; |
$projets = $this->requeteTous($requete_projets_utilisateur); |
if($projets <= 0) { |
$resume = '<h3> Vous n\'êtes inscrit à aucun projet </h3>'; |
} else { |
$resume = '<h3> Vos projets </h3>'; |
$resume .= '<ul id="liste_projets">'; |
foreach($projets as $projet) { |
$requete_info_projet = 'SELECT *'. |
' FROM projet'. |
' WHERE p_id = '.$this->bdd->quote($projet['psu_id_projet']); |
$projet_infos = $this->requeteUn($requete_info_projet); |
$infos_messages = ''; |
$resume .= '<li> |
<a href="http://www.tela-botanica.org/page:liste_projets?id_projet='.$projet_infos['p_id'].'" >'. |
'<b>'.$projet_infos['p_titre'].'</b> |
</a> |
<a onclick="javascript:return confirm(\'Se désinscrire du projet ?\');" href="http://www.tela-botanica.org/page:mes_preferences_des_projets?id_projet=7&act=26"> |
Se désinscrire du projet |
</a> |
</li>'; |
} |
$resume .= '</ul>'; |
} |
return $resume; |
} |
} |
<?php |
/** |
* PHP Version 5 |
* |
* @category PHP |
* @package papyrus_bp |
* @author aurelien <aurelien@tela-botanica.org> |
* @copyright 2010 Tela-Botanica |
* @license http://www.cecill.info/licences/Licence_CeCILL_V2-fr.txt Licence CECILL |
* @version SVN: <svn_id> |
* @link /doc/papyrus_bp/ |
*/ |
Class Resume extends ProjetService { |
public function __construct($config, $demarrer_session= true) { |
parent::__construct($config, $demarrer_session); |
} |
public function getElement($uid){ |
$id_utilisateur = $uid[0]; |
$mail_utilisateur = $uid[1]; |
// on selectionne les projets les plus actifs |
$requete_projets = 'SELECT DISTINCT *'. |
' FROM projet_statistiques'. |
' WHERE ps_ce_projet'. |
' IN '. |
'(SELECT psu_id_projet FROM projet_statut_utilisateurs'. |
' WHERE psu_id_utilisateur = '.$this->bdd->quote($id_utilisateur).')'. |
' GROUP BY ps_ce_projet'. |
' ORDER BY ps_msg_derniere_semaine DESC'; |
$resume = array(); |
$resume['titre'] = 'Mes projets les plus actifs'; |
$resume['lien_appli'] = '<a href="http://www.tela-botanica.org/page:liste_projets"> Voir tous les projets </a>'; |
$projets = $this->bdd->query($requete_projets)->fetchAll(); |
if(!$projets) { |
$resume['message'] = 'Vous n\'êtes inscrit à aucun projet'; |
} else { |
foreach($projets as $projet) { |
$requete_info_projet = 'SELECT p_titre'. |
' FROM projet'. |
' WHERE p_id = '.$this->bdd->quote($projet['ps_ce_projet']); |
$projet_infos = $this->bdd->query($requete_info_projet)->fetchAll(); |
$infos_messages = ''; |
if($projet['ps_msg_derniere_semaine'] > 0) { |
$infos_messages = ' (+ '.$projet['ps_msg_derniere_semaine'].' nouveaux messages) '; |
} else { |
$infos_messages = ' (aucun nouveau message) '; |
} |
$cible_lien = 'http://www.tela-botanica.org/page:liste_projets?id_projet='.$projet['ps_ce_projet']; |
$resume_item = array('element' => $projet_infos[0]['p_titre'].$infos_messages, 'lien' => $cible_lien); |
$resume['elements'][] = $resume_item; |
} |
} |
$this->envoyer($resume); |
} |
public function gererInscription($id_utilisateur, $mail_utilisateur) { |
$requete_projets_utilisateur = 'SELECT * FROM projet_statut_utilisateurs'. |
' WHERE psu_id_utilisateur = '.$this->bdd->quote($id_utilisateur); |
$resume = ''; |
$projets = $this->requeteTous($requete_projets_utilisateur); |
if($projets <= 0) { |
$resume = '<h3> Vous n\'êtes inscrit à aucun projet </h3>'; |
} else { |
$resume = '<h3> Vos projets </h3>'; |
$resume .= '<ul id="liste_projets">'; |
foreach($projets as $projet) { |
$requete_info_projet = 'SELECT *'. |
' FROM projet'. |
' WHERE p_id = '.$this->bdd->quote($projet['psu_id_projet']); |
$projet_infos = $this->requeteUn($requete_info_projet); |
$infos_messages = ''; |
$resume .= '<li> |
<a href="http://www.tela-botanica.org/page:liste_projets?id_projet='.$projet_infos['p_id'].'" >'. |
'<b>'.$projet_infos['p_titre'].'</b> |
</a> |
<a onclick="javascript:return confirm(\'Se désinscrire du projet ?\');" href="http://www.tela-botanica.org/page:mes_preferences_des_projets?id_projet=7&act=26"> |
Se désinscrire du projet |
</a> |
</li>'; |
} |
$resume .= '</ul>'; |
} |
return $resume; |
} |
} |
?> |
/trunk/jrest/services/DesinscriptionProjet.php |
---|
1,45 → 1,45 |
<?php |
Class DesinscriptionProjet extends ProjetService { |
public function getElement($uid) { |
$id_utilisateur = (isset($_GET['id_utilisateur'])) ? $_GET['id_utilisateur'] : false; |
$mail = (isset($_GET['mail'])) ? $_GET['mail'] : false; |
$id_projet = (isset($_GET['id_projet'])) ? $_GET['id_projet'] : false; |
if(!$id_utilisateur || !$id_projet) { |
return false; |
} |
// et on le supprime du projet |
$suppression_participant = $this->supprimerParticipantAProjet($id_utilisateur, $id_projet); |
// ainsi que des listes associées |
if($mail) { |
$listes = $this->obtenirListesAssocieesAuProjet($id_projet); |
// si pas de liste, rien à faire |
if(count($listes) <= 0) { |
continue; |
} |
$nom_liste = $listes[0]['pl_nom_liste']; |
$id_liste = $listes[0]['pl_id_liste']; |
$suppression_liste = $this->supprimerInscriptionAListeProjet($id_utilisateur, $id_liste); |
// on supprime l'abonnement |
if($this->estAbonneAListe($nom_liste, $mail)) { |
if(!$this->desinscriptionListe($nom_liste, $mail)) { |
$this->envoyer("false"); |
} |
} |
} |
$this->envoyer("OK"); |
return; |
} |
} |
<?php |
Class DesinscriptionProjet extends ProjetService { |
public function getElement($uid) { |
$id_utilisateur = (isset($_GET['id_utilisateur'])) ? $_GET['id_utilisateur'] : false; |
$mail = (isset($_GET['mail'])) ? $_GET['mail'] : false; |
$id_projet = (isset($_GET['id_projet'])) ? $_GET['id_projet'] : false; |
if(!$id_utilisateur || !$id_projet) { |
return false; |
} |
// et on le supprime du projet |
$suppression_participant = $this->supprimerParticipantAProjet($id_utilisateur, $id_projet); |
// ainsi que des listes associées |
if($mail) { |
$listes = $this->obtenirListesAssocieesAuProjet($id_projet); |
// si pas de liste, rien à faire |
if(count($listes) <= 0) { |
continue; |
} |
$nom_liste = $listes[0]['pl_nom_liste']; |
$id_liste = $listes[0]['pl_id_liste']; |
$suppression_liste = $this->supprimerInscriptionAListeProjet($id_utilisateur, $id_liste); |
// on supprime l'abonnement |
if($this->estAbonneAListe($nom_liste, $mail)) { |
if(!$this->desinscriptionListe($nom_liste, $mail)) { |
$this->envoyer("false"); |
} |
} |
} |
$this->envoyer("OK"); |
return; |
} |
} |
?> |
/trunk/jrest/services/Documents.php |
---|
1,63 → 1,65 |
<?php |
/** |
* PHP Version 5 |
* |
* @category PHP |
* @package papyrus_bp |
* @author aurelien <aurelien@tela-botanica.org> |
* @copyright 2010 Tela-Botanica |
* @license http://www.cecill.info/licences/Licence_CeCILL_V2-fr.txt Licence CECILL |
* @version SVN: <svn_id> |
* @link /doc/papyrus_bp/ |
*/ |
Class Documents extends ProjetService { |
public function __construct($config, $demarrer_session= true) { |
parent::__construct($config, $demarrer_session); |
} |
public function getElement($uid){ |
$id_utilisateur = $uid[1]; |
$mail_utilisateur = $uid[2]; |
if($id_utilisateur == "") { |
return; |
} |
// on selectionne les projets les plus actifs |
$requete_docs_projets = 'SELECT * FROM projet_documents WHERE pd_ce_utilisateur = '.$this->bdd->quote($id_utilisateur).' '. |
'AND pd_ce_type != 0 AND pd_visibilite = "public" '. |
'ORDER BY pd_date_de_mise_a_jour DESC '. |
'LIMIT 0,5'; |
$resume = array(); |
$resume['titre'] = 'Vos derniers documents déposés'; |
//$resume['lien_appli'] = '<a href="http://www.tela-botanica.org/page:liste_projets"> Voir tous les projets </a>'; |
$docs = $this->bdd->query($requete_docs_projets)->fetchAll(); |
if(!$docs) { |
$resume['message'] = 'Vous n\'avez déposé aucun document'; |
} else { |
foreach($docs as $doc) { |
$infos_projet = $this->obtenirInformationsProjet($doc['pd_ce_projet']); |
$nom_projet = $infos_projet[0]['p_titre']; |
$date_formatee = strftime( "%d/%m/%Y" , strtotime( $doc['pd_date_de_mise_a_jour'] ) ); |
$infos_messages = ' ('.$nom_projet.' le '.$date_formatee.') '; |
$cible_lien = 'http://www.tela-botanica.org/projets/'.$doc['pd_ce_projet'].'/telechargement/'.$doc['pd_id']; |
$resume_item = array('element' => $doc['pd_nom'].$infos_messages, 'lien' => $cible_lien); |
$resume['elements'][] = $resume_item; |
} |
} |
$this->envoyer($resume); |
} |
} |
<?php |
/** |
* PHP Version 5 |
* |
* @category PHP |
* @package papyrus_bp |
* @author aurelien <aurelien@tela-botanica.org> |
* @copyright 2010 Tela-Botanica |
* @license http://www.cecill.info/licences/Licence_CeCILL_V2-fr.txt Licence CECILL |
* @version SVN: <svn_id> |
* @link /doc/papyrus_bp/ |
*/ |
Class Documents extends ProjetService { |
public function __construct($config, $demarrer_session= true) { |
parent::__construct($config, $demarrer_session); |
} |
public function getElement($uid){ |
$id_utilisateur = $uid[1]; |
$mail_utilisateur = $uid[2]; |
if($id_utilisateur == "") { |
return; |
} |
// on selectionne les projets les plus actifs |
$requete_docs_projets = 'SELECT * FROM projet_documents WHERE pd_ce_utilisateur = '.$this->bdd->quote($id_utilisateur).' '. |
'AND pd_ce_type != 0 AND pd_visibilite = "public" '. |
'ORDER BY pd_date_de_mise_a_jour DESC '. |
'LIMIT 0,5'; |
$resume = array(); |
$resume['titre'] = 'Mes derniers documents déposés'; |
//$resume['lien_appli'] = '<a href="http://www.tela-botanica.org/page:liste_projets"> Voir tous les projets </a>'; |
$docs = $this->bdd->query($requete_docs_projets)->fetchAll(); |
if(!$docs) { |
$resume['message'] = 'Vous n\'avez déposé aucun document'; |
} else { |
foreach($docs as $doc) { |
$infos_projet = $this->obtenirInformationsProjet($doc['pd_ce_projet']); |
//print_r($infos_projet); |
$nom_projet = $infos_projet[0]['p_titre']; |
$date_formatee = strftime( "%d/%m/%Y" , strtotime( $doc['pd_date_de_mise_a_jour'] ) ); |
$infos_messages = ' ('.$nom_projet.' le '.$date_formatee.') '; |
$cible_lien = 'http://www.tela-botanica.org/projets/'.$doc['pd_ce_projet'].'/telechargement/'.$doc['pd_id']; |
$resume_item = array('element' => $doc['pd_nom'].$infos_messages, 'lien' => $cible_lien); |
$resume['elements'][] = $resume_item; |
} |
} |
$this->envoyer($resume); |
} |
} |
?> |
/trunk/jrest/services/Inscription.php |
---|
1,21 → 1,21 |
<?php |
/** |
* PHP Version 5 |
* |
* @category PHP |
* @package papyrus_bp |
* @author aurelien <aurelien@tela-botanica.org> |
* @copyright 2010 Tela-Botanica |
* @license http://www.cecill.info/licences/Licence_CeCILL_V2-fr.txt Licence CECILL |
* @version SVN: <svn_id> |
* @link /doc/papyrus_bp/ |
*/ |
Class Inscription extends JRestService { |
public function getElement($uid){ |
$this->envoyer("OK"); |
} |
} |
<?php |
/** |
* PHP Version 5 |
* |
* @category PHP |
* @package papyrus_bp |
* @author aurelien <aurelien@tela-botanica.org> |
* @copyright 2010 Tela-Botanica |
* @license http://www.cecill.info/licences/Licence_CeCILL_V2-fr.txt Licence CECILL |
* @version SVN: <svn_id> |
* @link /doc/papyrus_bp/ |
*/ |
Class Inscription extends JRestService { |
public function getElement($uid){ |
$this->envoyer("OK"); |
} |
} |
?> |
/trunk/jrest/services/ProjetService.php |
---|
1,174 → 1,149 |
<?php |
/** |
* PHP Version 5 |
* |
* @category PHP |
* @package projet_bp |
* @author aurelien <aurelien@tela-botanica.org> |
* @copyright 2010 Tela-Botanica |
* @license http://www.cecill.info/licences/Licence_CeCILL_V2-fr.txt Licence CECILL |
* @version SVN: <svn_id> |
* @link /doc/projet_bp/ |
*/ |
class ProjetService extends JRestService { |
public function __construct($config, $demarrer_session= true) { |
parent::__construct($config, $demarrer_session); |
} |
protected function obtenirProjetsPourParticipant($id_utilisateur) { |
// on selectionne la liste des projets auxquel on est inscrit |
$requete_projets = 'SELECT DISTINCT *'. |
' FROM projet'. |
' WHERE p_id'. |
' IN '. |
'(SELECT psu_id_projet FROM projet_statut_utilisateurs'. |
' WHERE psu_id_utilisateur = '.$this->bdd->quote($id_utilisateur).')'. |
' GROUP BY p_id'; |
try { |
$projets = $this->bdd->query($requete_projets)->fetchAll(PDO::FETCH_ASSOC); |
} catch (PDOException $e) { |
Log::getInstance()->ajouterEntree('projet','Fichier: '.$e->getFile().' Ligne: '.$e->getLine().' '.$e->getMessage()); |
return array(); |
} |
// pas de projets ? alors c'est fait ! |
if(!$projets || count($projets) <= 0) { |
return array(); |
} |
return $projets; |
} |
protected function obtenirInformationsProjet($id_projet) { |
$requete_informations_projet = 'SELECT DISTINCT *'. |
' FROM projet'. |
' WHERE p_id = '.$this->bdd->quote($id_projet) ; |
try { |
$projet = $this->bdd->query($requete_informations_projet)->fetchAll(PDO::FETCH_ASSOC); |
} catch (PDOException $e) { |
Log::getInstance()->ajouterEntree('projet','Fichier: '.$e->getFile().' Ligne: '.$e->getLine().' '.$e->getMessage()); |
return false; |
} |
// pas de projets ? alors c'est fait ! |
if(!$projet) { |
return false; |
} |
return $projet; |
} |
protected function obtenirListesAssocieesAuProjet($id_projet) { |
$requete_liste_projets = 'SELECT * FROM projet_liste '. |
'WHERE pl_id_liste IN '. |
'(SELECT pl_id_liste from projet_lien_liste '. |
'WHERE pl_id_projet='.$this->bdd->quote($id_projet).')' ; |
try { |
$listes_projets = $this->bdd->query($requete_liste_projets)->fetchAll(PDO::FETCH_ASSOC); |
} catch (PDOException $e) { |
Log::getInstance()->ajouterEntree('projet','Fichier: '.$e->getFile().' Ligne: '.$e->getLine().' '.$e->getMessage()); |
return array(); |
} |
if(!$listes_projets || count($listes_projets) <= 0) { |
return array(); |
} |
return $listes_projets; |
} |
protected function obtenirListesExternesAssocieesAuProjet($id_projet) { |
$requete_liste_projets = 'SELECT * FROM agora '. |
'WHERE plle_id_liste IN '. |
'(SELECT plle_id_liste from projet_lien_liste_externe '. |
'WHERE plle_id_projet='.$this->bdd->quote($id_projet).')' ; |
try { |
$listes_projets = $this->bdd->query($requete_liste_projets)->fetchAll(PDO::FETCH_ASSOC); |
} catch (PDOException $e) { |
Log::getInstance()->ajouterEntree('projet','Fichier: '.$e->getFile().' Ligne: '.$e->getLine().' '.$e->getMessage()); |
return array(); |
} |
if(!$listes_projets || count($listes_projets) <= 0) { |
return array(); |
} |
return $listes_projets; |
} |
protected function supprimerInscriptionAListeProjet($id_utilisateur, $id_liste) { |
$requete_suppression_liste = 'DELETE FROM projet_inscription_liste '. |
'WHERE pil_id_utilisateur='.$this->bdd->quote($id_utilisateur).' and pil_id_liste='.$this->bdd->quote($id_liste); |
try { |
$requete_suppression_liste = $this->bdd->query($requete_suppression_liste); |
} catch (PDOException $e) { |
Log::getInstance()->ajouterEntree('projet','Fichier: '.$e->getFile().' Ligne: '.$e->getLine().' '.$e->getMessage().' '.$requete_suppression_liste); |
return false; |
} |
} |
protected function supprimerParticipantAProjet($id_utilisateur, $id_projet) { |
$requete_suppression_projets = 'DELETE FROM projet_statut_utilisateurs '. |
'WHERE psu_id_utilisateur='.$this->bdd->quote($id_utilisateur).' and psu_id_projet='.$this->bdd->quote($id_projet); |
try { |
$requete_suppression_projets = $this->bdd->query($requete_suppression_projets); |
} catch (PDOException $e) { |
Log::getInstance()->ajouterEntree('projet','Fichier: '.$e->getFile().' Ligne: '.$e->getLine().' '.$e->getMessage().' '.$requete_suppression_projets); |
return false; |
} |
return true; |
} |
protected function estAbonneAListe($nom_liste, $mail) { |
try { |
$est_abonne = '0' ; |
// TODO: externaliser l'adresse |
$xml_abonne = new SimpleXMLElement(file_get_contents('http://vpopmail.tela-botanica.org/est_abonne.php?domaine=tela-botanica.org&liste='.$nom_liste.'&mail='.$mail)) ; |
$est_abonne = $xml_abonne[0] ; |
if($est_abonne == '1') { |
return true; |
} else { |
return false; |
} |
} |
catch(Exception $e) { |
trigger_error($e->getMessage()) ; |
return false; |
} |
} |
protected function modifierMailPourListe($nom_liste, $ancien_mail, $nouveau_mail) { |
return ($this->desinscriptionListe($nom_liste, $ancien_mail) && $this->inscriptionListe($nom_liste, $nouveau_mail)); |
} |
protected function inscriptionListe($nom_liste, $mail) { |
// TODO: externaliser l'adresse |
return $inscription_abonne = file_get_contents('http://vpopmail.tela-botanica.org/ajout_abonne.php?domaine=tela-botanica.org&liste='.$nom_liste.'&mail='.$mail) ; |
} |
protected function desinscriptionListe($nom_liste, $mail) { |
// TODO: externaliser l'adresse |
return $suppression_abonne = file_get_contents('http://vpopmail.tela-botanica.org/suppression_abonne.php?domaine=tela-botanica.org&liste='.$nom_liste.'&mail='.$mail) ; |
} |
} |
?> |
<?php |
/** |
* PHP Version 5 |
* |
* @category PHP |
* @package projet_bp |
* @author aurelien <aurelien@tela-botanica.org> |
* @copyright 2010 Tela-Botanica |
* @license http://www.cecill.info/licences/Licence_CeCILL_V2-fr.txt Licence CECILL |
* @version SVN: <svn_id> |
* @link /doc/projet_bp/ |
*/ |
class ProjetService extends JRestService { |
public function __construct($config, $demarrer_session= true) { |
parent::__construct($config, $demarrer_session); |
} |
protected function obtenirProjetsPourParticipant($id_utilisateur) { |
// on selectionne la liste des projets auxquel on est inscrit |
$requete_projets = 'SELECT DISTINCT *'. |
' FROM projet'. |
' WHERE p_id'. |
' IN '. |
'(SELECT psu_id_projet FROM projet_statut_utilisateurs'. |
' WHERE psu_id_utilisateur = '.$this->bdd->quote($id_utilisateur).')'. |
' GROUP BY p_id'; |
try { |
$projets = $this->bdd->query($requete_projets)->fetchAll(PDO::FETCH_ASSOC); |
} catch (PDOException $e) { |
Log::getInstance()->ajouterEntree('projet','Fichier: '.$e->getFile().' Ligne: '.$e->getLine().' '.$e->getMessage()); |
return array(); |
} |
// pas de projets ? alors c'est fait ! |
if(!$projets || count($projets) <= 0) { |
return array(); |
} |
return $projets; |
} |
protected function obtenirInformationsProjet($id_projet) { |
$requete_informations_projet = 'SELECT DISTINCT *'. |
' FROM projet'. |
' WHERE p_id = '.$this->bdd->quote($id_projet) ; |
try { |
$projet = $this->bdd->query($requete_informations_projet)->fetchAll(PDO::FETCH_ASSOC); |
} catch (PDOException $e) { |
Log::getInstance()->ajouterEntree('projet','Fichier: '.$e->getFile().' Ligne: '.$e->getLine().' '.$e->getMessage()); |
return false; |
} |
// pas de projets ? alors c'est fait ! |
if(!$projet) { |
return false; |
} |
return $projet; |
} |
protected function obtenirListesAssocieesAuProjet($id_projet) { |
$requete_liste_projets = 'SELECT * FROM projet_liste '. |
'WHERE pl_id_liste IN '. |
'(SELECT pl_id_liste from projet_lien_liste '. |
'WHERE pl_id_projet='.$this->bdd->quote($id_projet).')' ; |
try { |
$listes_projets = $this->bdd->query($requete_liste_projets)->fetchAll(PDO::FETCH_ASSOC); |
} catch (PDOException $e) { |
Log::getInstance()->ajouterEntree('projet','Fichier: '.$e->getFile().' Ligne: '.$e->getLine().' '.$e->getMessage()); |
return array(); |
} |
if(!$listes_projets || count($listes_projets) <= 0) { |
return array(); |
} |
return $listes_projets; |
} |
protected function supprimerInscriptionAListeProjet($id_utilisateur, $id_liste) { |
$requete_suppression_liste = 'DELETE FROM projet_inscription_liste '. |
'WHERE pil_id_utilisateur='.$this->bdd->quote($id_utilisateur).' and pil_id_liste='.$this->bdd->quote($id_liste) ; |
try { |
$requete_suppression_liste = $this->bdd->query($requete_suppression_liste); |
} catch (PDOException $e) { |
Log::getInstance()->ajouterEntree('projet','Fichier: '.$e->getFile().' Ligne: '.$e->getLine().' '.$e->getMessage().' '.$requete_suppression_liste); |
return false; |
} |
} |
protected function supprimerParticipantAProjet($id_utilisateur, $id_projet) { |
$requete_suppression_projets = 'DELETE FROM projet_statut_utilisateurs '. |
'WHERE psu_id_utilisateur='.$this->bdd->quote($id_utilisateur).' and psu_id_projet='.$this->bdd->quote($id_projet) ; |
try { |
$requete_suppression_projets = $this->bdd->query($requete_suppression_projets); |
} catch (PDOException $e) { |
Log::getInstance()->ajouterEntree('projet','Fichier: '.$e->getFile().' Ligne: '.$e->getLine().' '.$e->getMessage().' '.$requete_suppression_projets); |
return false; |
} |
return true; |
} |
protected function estAbonneAListe($nom_liste, $mail) { |
try { |
$est_abonne = '0' ; |
$xml_abonne = new SimpleXMLElement(file_get_contents('http://vpopmail.tela-botanica.org/est_abonne.php?domaine=tela-botanica.org&liste='.$nom_liste.'&mail='.$mail)) ; |
$est_abonne = $xml_abonne[0] ; |
if($est_abonne == '1') { |
return true; |
} else { |
return false; |
} |
} |
catch(Exception $e) { |
trigger_error($e->getMessage()) ; |
return false; |
} |
} |
protected function modifierMailPourListe($nom_liste, $ancien_mail, $nouveau_mail) { |
return ($this->desinscriptionListe($nom_liste, $ancien_mail) && $this->inscriptionListe($nom_liste, $nouveau_mail)); |
} |
protected function inscriptionListe($nom_liste, $mail) { |
return $inscription_abonne = file_get_contents('http://vpopmail.tela-botanica.org/ajout_abonne.php?domaine=tela-botanica.org&liste='.$nom_liste.'&mail='.$mail) ; |
} |
protected function desinscriptionListe($nom_liste, $mail) { |
return $suppression_abonne = file_get_contents('http://vpopmail.tela-botanica.org/suppression_abonne.php?domaine=tela-botanica.org&liste='.$nom_liste.'&mail='.$mail) ; |
} |
} |
?> |
/trunk/jrest/services/Modification.php |
---|
1,69 → 1,69 |
<?php |
/** |
* PHP Version 5 |
* |
* @category PHP |
* @package projet_bp |
* @author aurelien <aurelien@tela-botanica.org> |
* @copyright 2010 Tela-Botanica |
* @license http://www.cecill.info/licences/Licence_CeCILL_V2-fr.txt Licence CECILL |
* @version SVN: <svn_id> |
* @link /doc/projet_bp/ |
*/ |
class Modification extends ProjetService { |
public function getElement($uid){ |
$id_utilisateur = (isset($_GET['id_utilisateur'])) ? $_GET['id_utilisateur'] : false; |
$mail = (isset($_GET['mail'])) ? $_GET['mail'] : false; |
$nouveau_mail = (isset($_GET['nouveau_mail'])) ? $_GET['nouveau_mail'] : false; |
if(!$mail || !$id_utilisateur) { |
$this->envoyer("false"); |
} |
$ancien_mail = $mail; |
$nouveau_mail = $nouveau_mail; |
// si le mail n'a pas changé, on ne change rien |
if($ancien_mail == $nouveau_mail) { |
$this->envoyer("OK"); |
return; |
} |
$projets = $this->obtenirProjetsPourParticipant($id_utilisateur); |
// si pas de projets, rien à faire |
if(count($projets) <= 0) { |
$this->envoyer("OK"); |
return; |
} |
// sinon on récupère la liste associée à chaque projet |
foreach($projets as $projet) { |
$id_projet = $projet['p_id']; |
$listes = $this->obtenirListesAssocieesAuProjet($id_projet); |
// si pas de liste, rien à faire |
if(count($listes) <= 0) { |
continue; |
} |
$nom_liste = $listes[0]['pl_nom_liste']; |
// on modifie l'abonnement |
if($this->estAbonneAListe($nom_liste, $mail)) { |
if(!$this->modifierMailPourListe($nom_liste, $ancien_mail, $nouveau_mail)) { |
$this->envoyer("false"); |
} |
} |
} |
$this->envoyer("OK"); |
return; |
} |
} |
?> |
<?php |
/** |
* PHP Version 5 |
* |
* @category PHP |
* @package projet_bp |
* @author aurelien <aurelien@tela-botanica.org> |
* @copyright 2010 Tela-Botanica |
* @license http://www.cecill.info/licences/Licence_CeCILL_V2-fr.txt Licence CECILL |
* @version SVN: <svn_id> |
* @link /doc/projet_bp/ |
*/ |
class Modification extends ProjetService { |
public function getElement($uid){ |
$id_utilisateur = (isset($_GET['id_utilisateur'])) ? $_GET['id_utilisateur'] : false; |
$mail = (isset($_GET['mail'])) ? $_GET['mail'] : false; |
$nouveau_mail = (isset($_GET['nouveau_mail'])) ? $_GET['nouveau_mail'] : false; |
if(!$mail || !$id_utilisateur) { |
$this->envoyer("false"); |
} |
$ancien_mail = $mail; |
$nouveau_mail = $nouveau_mail; |
// si le mail n'a pas changé, on ne change rien |
if($ancien_mail == $nouveau_mail) { |
$this->envoyer("OK"); |
return; |
} |
$projets = $this->obtenirProjetsPourParticipant($id_utilisateur); |
// si pas de projets, rien à faire |
if(count($projets) <= 0) { |
$this->envoyer("OK"); |
return; |
} |
// sinon on récupère la liste associée à chaque projet |
foreach($projets as $projet) { |
$id_projet = $projet['p_id']; |
$listes = $this->obtenirListesAssocieesAuProjet($id_projet); |
// si pas de liste, rien à faire |
if(count($listes) <= 0) { |
continue; |
} |
$nom_liste = $listes[0]['pl_nom_liste']; |
// on modifie l'abonnement |
if($this->estAbonneAListe($nom_liste, $mail)) { |
if(!$this->modifierMailPourListe($nom_liste, $ancien_mail, $nouveau_mail)) { |
$this->envoyer("false"); |
} |
} |
} |
$this->envoyer("OK"); |
return; |
} |
} |
?> |
/trunk/jrest/services/Gestion.php |
---|
1,52 → 1,52 |
<?php |
/** |
* PHP Version 5 |
* |
* @category PHP |
* @package papyrus_bp |
* @author aurelien <aurelien@tela-botanica.org> |
* @copyright 2010 Tela-Botanica |
* @license http://www.cecill.info/licences/Licence_CeCILL_V2-fr.txt Licence CECILL |
* @version SVN: <svn_id> |
* @link /doc/papyrus_bp/ |
*/ |
Class Gestion extends JRestService { |
public function getElement($uid){ |
$id_utilisateur = $uid[0]; |
$mail_utilisateur = $uid[1]; |
// on selectionne la liste des projets auxquel on est inscrit |
$requete_projets = 'SELECT DISTINCT *'. |
' FROM projet'. |
' WHERE p_id'. |
' IN '. |
'(SELECT psu_id_projet FROM projet_statut_utilisateurs'. |
' WHERE psu_id_utilisateur = '.$this->bdd->quote($id_utilisateur).')'. |
' GROUP BY p_id'; |
$resume = array(); |
$resume['titre'] = 'Gestion de mes projets'; |
$resume['info'] = 'Vous souhaitez vous inscrire à d\'autres projets ? <a href="http://www.tela-botanica.org/page:liste_projets" > Consultez la liste des projets et forums </a>'; |
$projets = $this->bdd->query($requete_projets)->fetchAll(); |
if(!$projets) { |
$resume['message'] = 'Vous n\'êtes inscrit à aucun projet'; |
} else { |
foreach($projets as $projet) { |
$cible_lien_desinscrire = 'http://www.tela-botanica.org/client/projet/jrest/DesinscriptionProjet/?id_projet='.$projet['p_id'].'&id_utilisateur='.$id_utilisateur.'&mail='.$mail_utilisateur; |
$cible_lien = 'http://www.tela-botanica.org/page:liste_projets?id_projet='.$projet['p_id']; |
$resume_item = array('element' => $projet['p_titre'], 'lien_desinscrire' => $cible_lien_desinscrire, 'lien' => $cible_lien, 'intitule_lien' => 'Se désinscrire'); |
$resume['elements'][] = $resume_item; |
} |
} |
$this->envoyer($resume); |
} |
} |
<?php |
/** |
* PHP Version 5 |
* |
* @category PHP |
* @package papyrus_bp |
* @author aurelien <aurelien@tela-botanica.org> |
* @copyright 2010 Tela-Botanica |
* @license http://www.cecill.info/licences/Licence_CeCILL_V2-fr.txt Licence CECILL |
* @version SVN: <svn_id> |
* @link /doc/papyrus_bp/ |
*/ |
Class Gestion extends JRestService { |
public function getElement($uid){ |
$id_utilisateur = $uid[0]; |
$mail_utilisateur = $uid[1]; |
// on selectionne la liste des projets auxquel on est inscrit |
$requete_projets = 'SELECT DISTINCT *'. |
' FROM projet'. |
' WHERE p_id'. |
' IN '. |
'(SELECT psu_id_projet FROM projet_statut_utilisateurs'. |
' WHERE psu_id_utilisateur = '.$this->bdd->quote($id_utilisateur).')'. |
' GROUP BY p_id'; |
$resume = array(); |
$resume['titre'] = 'Gestion de mes projets'; |
$resume['info'] = 'Vous souhaitez vous inscrire à d\'autres projets ? <a href="http://www.tela-botanica.org/page:liste_projets" > Consultez la liste des projets et forums </a>'; |
$projets = $this->bdd->query($requete_projets)->fetchAll(); |
if(!$projets) { |
$resume['message'] = 'Vous n\'êtes inscrit à aucun projet'; |
} else { |
foreach($projets as $projet) { |
$cible_lien_desinscrire = 'http://www.tela-botanica.org/client/projet/jrest/DesinscriptionProjet/?id_projet='.$projet['p_id'].'&id_utilisateur='.$id_utilisateur.'&mail='.$mail_utilisateur; |
$cible_lien = 'http://www.tela-botanica.org/page:liste_projets?id_projet='.$projet['p_id']; |
$resume_item = array('element' => $projet['p_titre'], 'lien_desinscrire' => $cible_lien_desinscrire, 'lien' => $cible_lien, 'intitule_lien' => 'Se désinscrire'); |
$resume['elements'][] = $resume_item; |
} |
} |
$this->envoyer($resume); |
} |
} |
?> |
/trunk/jrest/services/JRestService.php |
---|
1,238 → 1,238 |
<?php |
/** |
* Classe mère abstraite contenant les méthodes génériques des services. |
* Encodage en entrée : utf8 |
* Encodage en sortie : utf8 |
* |
* @author Jean-Pascal MILCENT <jpm@tela-botanica.org> |
* @license GPL v3 <http://www.gnu.org/licenses/gpl.txt> |
* @license CECILL v2 <http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt> |
* @version $Id$ |
* @copyright 2009 |
*/ |
abstract class JRestService { |
public $config; |
protected $bdd; |
protected $log = array(); |
protected $messages = array(); |
protected $debug = array(); |
protected $distinct = false; |
protected $orderby = null; |
protected $formatRetour = 'objet'; |
protected $start = 0; |
protected $limit = 150; |
public function __construct($config, $demarrer_session = true) { |
// Tableau contenant la config de Jrest |
$this->config = $config; |
// Connection à la base de données |
$this->bdd = $this->connecterPDO($this->config, 'appli'); |
// Nettoyage du $_GET (sécurité) |
if (isset($_GET)) { |
$get_params = array('orderby', 'distinct', 'start', 'limit', 'formatRetour'); |
foreach ($get_params as $get) { |
$verifier = array('NULL', "\n", "\r", "\\", "'", '"', "\x00", "\x1a", ';'); |
$_GET[$get] = str_replace($verifier, '', $_GET[$get]); |
if (isset($_GET[$get]) && $_GET[$get] != '') { |
$this->$get = $_GET[$get]; |
} else { |
$_GET[$get] = null; |
} |
} |
} |
} |
/** |
* Méthode appelée quand aucun paramètre n'est passé dans l'url et avec une requête de type GET. |
*/ |
public function getRessource() { |
$this->getElement(array()); |
} |
protected function envoyer($donnees = null, $mime = 'text/html', $encodage = 'utf-8', $json = true) { |
// Traitements des messages d'erreurs et données |
if (count($this->messages) != 0) { |
header('HTTP/1.1 500 Internal Server Error'); |
$mime = 'text/html'; |
$encodage = 'utf-8'; |
$json = true; |
$sortie = $this->messages; |
} else { |
$sortie = $donnees; |
if (is_null($donnees)) { |
$sortie = 'OK'; |
} |
} |
// Gestion de l'envoie du déboguage |
$this->envoyerDebogage(); |
// Encodage au format et JSON et envoie sur la sortie standard |
$contenu = $json ? json_encode($sortie) : $sortie; |
$this->envoyerContenu($encodage, $mime, $contenu); |
} |
protected function envoyerDebogage() { |
if (!is_array($this->debug)) { |
$this->debug[] = $this->debug; |
} |
if (count($this->debug) != 0) { |
foreach ($this->debug as $cle => $val) { |
if (is_array($val)) { |
$this->debug[$cle] = print_r($val, true); |
} |
} |
header('X-DebugJrest-Data:'.json_encode($this->debug)); |
} |
} |
protected function envoyerContenu($encodage, $mime, $contenu) { |
header("Content-Type: $mime; charset=$encodage"); |
print $contenu; |
} |
private function connecterPDO($config, $base = 'database') { |
$cfg = $config[$base]; |
$dsn = $cfg['phptype'].':dbname='.$cfg['database'].';host='.$cfg['hostspec']; |
try { |
$PDO = new PDO($dsn, $cfg['username'], $cfg['password']); |
} catch (PDOException $e) { |
echo 'La connexion à la base de donnée via PDO a échouée : ' . $e->getMessage(); |
} |
// Passe en UTF-8 la connexion à la BDD |
$PDO->exec("SET NAMES 'utf8'"); |
// Affiche les erreurs détectées par PDO (sinon mode silencieux => aucune erreur affiché) |
$PDO->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); |
return $PDO; |
} |
protected function getTxt($id) { |
$sortie = ''; |
switch ($id) { |
case 'sql_erreur' : $sortie = 'Requête echec. Fichier : "%s". Ligne : "%s". Message : %s'; break; |
default : $sortie = $id; |
} |
return $sortie; |
} |
protected function traiterParametresUrl($params_attendu, $params, $pourBDD = true) { |
$sortie = array(); |
foreach ($params_attendu as $num => $nom) { |
if (isset($params[$num]) && $params[$num] != '*') { |
if ($pourBDD) { |
$params[$num] = $this->bdd->quote($params[$num]); |
} |
$sortie[$nom] = $params[$num]; |
} |
} |
return $sortie; |
} |
protected function traiterParametresPost($params) { |
$sortie = array(); |
foreach ($params as $cle => $valeur) { |
$sortie[$cle] = $this->bdd->quote($valeur); |
} |
return $sortie; |
} |
protected function getIdentification(&$params) { |
// Initialisation des variables |
$utilisateur = array(0, session_id()); |
// L'id utilisateur est soit passé par le POST soit dans l'url |
if (is_array($params) && isset($params['cmhl_ce_modifier_par'])) { |
$utilisateur[0] = $params['cmhl_ce_modifier_par']; |
unset($params['cmhl_ce_modifier_par']); |
} else if (is_string($params)) { |
$utilisateur[0] = $params; |
} |
return $utilisateur; |
} |
protected function etreAutorise($id_utilisateur) { |
$autorisation = false; |
if (($_SESSION['coel_utilisateur'] != '') && $_SESSION['coel_utilisateur']['id'] != $id_utilisateur) { |
$this->messages[] = 'Accès interdit.'; |
} else if ($_SESSION['coel_utilisateur'] == '') { |
$this->messages[] = 'Veuillez vous identifiez pour accéder à cette fonction.'; |
} else { |
$autorisation = true; |
} |
return $autorisation; |
} |
private function gererIdentificationPermanente() { |
// Pour maintenir l'utilisateur tjrs réellement identifié nous sommes obligé de recréer une SESSION et de le recharger depuis la bdd |
if ($this->getUtilisateur() == '' |
&& isset($_COOKIE['coel_login']) |
&& ($utilisateur = $this->chargerUtilisateur($_COOKIE['coel_login'], $_COOKIE['coel_mot_de_passe']))) { |
$this->setUtilisateur($utilisateur, $_COOKIE['coel_permanence']); |
} |
} |
protected function getUtilisateur() { |
return (isset($_SESSION['coel_utilisateur']) ? $_SESSION['coel_utilisateur'] : ''); |
} |
/** |
* Méthode prenant en paramètre un chemin de fichier squelette et un tableau associatif de données, |
* en extrait les variables, charge le squelette et retourne le résultat des deux combinés. |
* |
* @param String $fichier le chemin du fichier du squelette |
* @param Array $donnees un tableau associatif contenant les variables a injecter dans le squelette. |
* |
* @return boolean false si le squelette n'existe pas, sinon la chaine résultat. |
*/ |
public static function traiterSquelettePhp($fichier, Array $donnees = array()) { |
$sortie = false; |
if (file_exists($fichier)) { |
// Extraction des variables du tableau de données |
extract($donnees); |
// Démarage de la bufferisation de sortie |
ob_start(); |
// Si les tags courts sont activés |
if ((bool) @ini_get('short_open_tag') === true) { |
// Simple inclusion du squelette |
include $fichier; |
} else { |
// Sinon, remplacement des tags courts par la syntaxe classique avec echo |
$html_et_code_php = self::traiterTagsCourts($fichier); |
// Pour évaluer du php mélangé dans du html il est nécessaire de fermer la balise php ouverte par eval |
$html_et_code_php = '?>'.$html_et_code_php; |
// Interprétation du html et du php dans le buffer |
echo eval($html_et_code_php); |
} |
// Récupèration du contenu du buffer |
$sortie = ob_get_contents(); |
// Suppression du buffer |
@ob_end_clean(); |
} else { |
$msg = "Le fichier du squelette '$fichier' n'existe pas."; |
trigger_error($msg, E_USER_WARNING); |
} |
// Retourne le contenu |
return $sortie; |
} |
/** |
* Fonction chargeant le contenu du squelette et remplaçant les tags court php (<?= ...) par un tag long avec echo. |
* |
* @param String $chemin_squelette le chemin du fichier du squelette |
* |
* @return string le contenu du fichier du squelette php avec les tags courts remplacés. |
*/ |
private static function traiterTagsCourts($chemin_squelette) { |
$contenu = file_get_contents($chemin_squelette); |
// Remplacement de tags courts par un tag long avec echo |
$contenu = str_replace('<?=', '<?php echo ', $contenu); |
// Ajout systématique d'un point virgule avant la fermeture php |
$contenu = preg_replace("/;*\s*\?>/", "; ?>", $contenu); |
return $contenu; |
} |
} |
<?php |
/** |
* Classe mère abstraite contenant les méthodes génériques des services. |
* Encodage en entrée : utf8 |
* Encodage en sortie : utf8 |
* |
* @author Jean-Pascal MILCENT <jpm@tela-botanica.org> |
* @license GPL v3 <http://www.gnu.org/licenses/gpl.txt> |
* @license CECILL v2 <http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt> |
* @version $Id$ |
* @copyright 2009 |
*/ |
abstract class JRestService { |
public $config; |
protected $bdd; |
protected $log = array(); |
protected $messages = array(); |
protected $debug = array(); |
protected $distinct = false; |
protected $orderby = null; |
protected $formatRetour = 'objet'; |
protected $start = 0; |
protected $limit = 150; |
public function __construct($config, $demarrer_session = true) { |
// Tableau contenant la config de Jrest |
$this->config = $config; |
// Connection à la base de données |
$this->bdd = $this->connecterPDO($this->config, 'appli'); |
// Nettoyage du $_GET (sécurité) |
if (isset($_GET)) { |
$get_params = array('orderby', 'distinct', 'start', 'limit', 'formatRetour'); |
foreach ($get_params as $get) { |
$verifier = array('NULL', "\n", "\r", "\\", "'", '"', "\x00", "\x1a", ';'); |
$_GET[$get] = str_replace($verifier, '', $_GET[$get]); |
if (isset($_GET[$get]) && $_GET[$get] != '') { |
$this->$get = $_GET[$get]; |
} else { |
$_GET[$get] = null; |
} |
} |
} |
} |
/** |
* Méthode appelée quand aucun paramètre n'est passé dans l'url et avec une requête de type GET. |
*/ |
public function getRessource() { |
$this->getElement(array()); |
} |
protected function envoyer($donnees = null, $mime = 'text/html', $encodage = 'utf-8', $json = true) { |
// Traitements des messages d'erreurs et données |
if (count($this->messages) != 0) { |
header('HTTP/1.1 500 Internal Server Error'); |
$mime = 'text/html'; |
$encodage = 'utf-8'; |
$json = true; |
$sortie = $this->messages; |
} else { |
$sortie = $donnees; |
if (is_null($donnees)) { |
$sortie = 'OK'; |
} |
} |
// Gestion de l'envoie du déboguage |
$this->envoyerDebogage(); |
// Encodage au format et JSON et envoie sur la sortie standard |
$contenu = $json ? json_encode($sortie) : $sortie; |
$this->envoyerContenu($encodage, $mime, $contenu); |
} |
protected function envoyerDebogage() { |
if (!is_array($this->debug)) { |
$this->debug[] = $this->debug; |
} |
if (count($this->debug) != 0) { |
foreach ($this->debug as $cle => $val) { |
if (is_array($val)) { |
$this->debug[$cle] = print_r($val, true); |
} |
} |
header('X-DebugJrest-Data:'.json_encode($this->debug)); |
} |
} |
protected function envoyerContenu($encodage, $mime, $contenu) { |
header("Content-Type: $mime; charset=$encodage"); |
print $contenu; |
} |
private function connecterPDO($config, $base = 'database') { |
$cfg = $config[$base]; |
$dsn = $cfg['phptype'].':dbname='.$cfg['database'].';host='.$cfg['hostspec']; |
try { |
$PDO = new PDO($dsn, $cfg['username'], $cfg['password']); |
} catch (PDOException $e) { |
echo 'La connexion à la base de donnée via PDO a échouée : ' . $e->getMessage(); |
} |
// Passe en UTF-8 la connexion à la BDD |
$PDO->exec("SET NAMES 'utf8'"); |
// Affiche les erreurs détectées par PDO (sinon mode silencieux => aucune erreur affiché) |
$PDO->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); |
return $PDO; |
} |
protected function getTxt($id) { |
$sortie = ''; |
switch ($id) { |
case 'sql_erreur' : $sortie = 'Requête echec. Fichier : "%s". Ligne : "%s". Message : %s'; break; |
default : $sortie = $id; |
} |
return $sortie; |
} |
protected function traiterParametresUrl($params_attendu, $params, $pourBDD = true) { |
$sortie = array(); |
foreach ($params_attendu as $num => $nom) { |
if (isset($params[$num]) && $params[$num] != '*') { |
if ($pourBDD) { |
$params[$num] = $this->bdd->quote($params[$num]); |
} |
$sortie[$nom] = $params[$num]; |
} |
} |
return $sortie; |
} |
protected function traiterParametresPost($params) { |
$sortie = array(); |
foreach ($params as $cle => $valeur) { |
$sortie[$cle] = $this->bdd->quote($valeur); |
} |
return $sortie; |
} |
protected function getIdentification(&$params) { |
// Initialisation des variables |
$utilisateur = array(0, session_id()); |
// L'id utilisateur est soit passé par le POST soit dans l'url |
if (is_array($params) && isset($params['cmhl_ce_modifier_par'])) { |
$utilisateur[0] = $params['cmhl_ce_modifier_par']; |
unset($params['cmhl_ce_modifier_par']); |
} else if (is_string($params)) { |
$utilisateur[0] = $params; |
} |
return $utilisateur; |
} |
protected function etreAutorise($id_utilisateur) { |
$autorisation = false; |
if (($_SESSION['coel_utilisateur'] != '') && $_SESSION['coel_utilisateur']['id'] != $id_utilisateur) { |
$this->messages[] = 'Accès interdit.'; |
} else if ($_SESSION['coel_utilisateur'] == '') { |
$this->messages[] = 'Veuillez vous identifiez pour accéder à cette fonction.'; |
} else { |
$autorisation = true; |
} |
return $autorisation; |
} |
private function gererIdentificationPermanente() { |
// Pour maintenir l'utilisateur tjrs réellement identifié nous sommes obligé de recréer une SESSION et de le recharger depuis la bdd |
if ($this->getUtilisateur() == '' |
&& isset($_COOKIE['coel_login']) |
&& ($utilisateur = $this->chargerUtilisateur($_COOKIE['coel_login'], $_COOKIE['coel_mot_de_passe']))) { |
$this->setUtilisateur($utilisateur, $_COOKIE['coel_permanence']); |
} |
} |
protected function getUtilisateur() { |
return (isset($_SESSION['coel_utilisateur']) ? $_SESSION['coel_utilisateur'] : ''); |
} |
/** |
* Méthode prenant en paramètre un chemin de fichier squelette et un tableau associatif de données, |
* en extrait les variables, charge le squelette et retourne le résultat des deux combinés. |
* |
* @param String $fichier le chemin du fichier du squelette |
* @param Array $donnees un tableau associatif contenant les variables a injecter dans le squelette. |
* |
* @return boolean false si le squelette n'existe pas, sinon la chaine résultat. |
*/ |
public static function traiterSquelettePhp($fichier, Array $donnees = array()) { |
$sortie = false; |
if (file_exists($fichier)) { |
// Extraction des variables du tableau de données |
extract($donnees); |
// Démarage de la bufferisation de sortie |
ob_start(); |
// Si les tags courts sont activés |
if ((bool) @ini_get('short_open_tag') === true) { |
// Simple inclusion du squelette |
include $fichier; |
} else { |
// Sinon, remplacement des tags courts par la syntaxe classique avec echo |
$html_et_code_php = self::traiterTagsCourts($fichier); |
// Pour évaluer du php mélangé dans du html il est nécessaire de fermer la balise php ouverte par eval |
$html_et_code_php = '?>'.$html_et_code_php; |
// Interprétation du html et du php dans le buffer |
echo eval($html_et_code_php); |
} |
// Récupèration du contenu du buffer |
$sortie = ob_get_contents(); |
// Suppression du buffer |
@ob_end_clean(); |
} else { |
$msg = "Le fichier du squelette '$fichier' n'existe pas."; |
trigger_error($msg, E_USER_WARNING); |
} |
// Retourne le contenu |
return $sortie; |
} |
/** |
* Fonction chargeant le contenu du squelette et remplaçant les tags court php (<?= ...) par un tag long avec echo. |
* |
* @param String $chemin_squelette le chemin du fichier du squelette |
* |
* @return string le contenu du fichier du squelette php avec les tags courts remplacés. |
*/ |
private static function traiterTagsCourts($chemin_squelette) { |
$contenu = file_get_contents($chemin_squelette); |
// Remplacement de tags courts par un tag long avec echo |
$contenu = str_replace('<?=', '<?php echo ', $contenu); |
// Ajout systématique d'un point virgule avant la fermeture php |
$contenu = preg_replace("/;*\s*\?>/", "; ?>", $contenu); |
return $contenu; |
} |
} |
?> |
/trunk/jrest/services/ProjetSyndication.php |
---|
New file |
0,0 → 1,342 |
<?php |
/** |
* Service fournissant des informations concernant PROJET au format RSS1, RSS2 ou ATOM. |
* Encodage en entrée : utf8 |
* Encodage en sortie : utf8 |
* |
* @author Grégoire Duché <gregoire@tela-botanica.org> |
* @license GPL v3 <http://www.gnu.org/licenses/gpl.txt> |
* @license CECILL v2 <http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt> |
* @version $Id: CoelSyndication.php 381 2010-05-17 17:10:37Z jpm $ |
* @copyright 2009 |
*/ |
class ProjetSyndication extends ProjetService { |
private $format = null; |
private $service = null; |
private $squelette = null; |
private $squelette_dossier = null; |
private $squelette_diff = null; |
private $flux = array(); |
/** |
* Méthode appelée avec une requête de type GET. |
*/ |
public function getElement($param = array()) { |
// Initialisation des variables |
$info = array(); |
$contenu = ''; |
// Pré traitement des paramètres |
$pour_bdd = false; |
$p = $this->traiterParametresUrl(array('service', 'format'), $param, $pour_bdd); |
// Récupération de la liste des flux |
$this->chargerListeDesFlux(); |
// Chargement du bon type de service demandé |
if (isset($p['service'])) { |
$this->service = strtolower($p['service']); |
$methode = $this->getNomMethodeService(); |
if (method_exists($this, $methode)) { |
if ($this->service != 'liste_des_flux') { |
if (isset($p['format']) && preg_match('/^(?:rss1|rss2|atom)$/i', $p['format'])) { |
// Multiplication par deux de la limite car nous récupérons deux lignes par item |
$this->limit = $this->limit*2; |
// Mise en minuscule de l'indication du format |
$this->format = strtolower($p['format']); |
// Définition du fichier squelette demandé |
$this->squelette_dossier = dirname(__FILE__).DIRECTORY_SEPARATOR.'squelettes'.DIRECTORY_SEPARATOR; |
$this->squelette = $this->squelette_dossier.$this->format.'.tpl.xml'; |
$this->squelette_diff = $this->squelette_dossier.'diff.tpl.html'; |
} else { |
$this->format = ''; |
$this->messages[] = "Le service Projet Syndication nécessite d'indiquer en second paramètre le format : rss1, rss2 ou atom."; |
} |
} |
// Récupération du contenu à renvoyer |
$contenu = $this->$methode(); |
} else { |
$this->messages[] = "Le type d'information demandé '$this->service' n'est pas disponible."; |
} |
} else { |
$this->messages[] = "Le service Projet Syndication nécessite d'indiquer en premier paramètre le type d'information demandé."; |
} |
// Envoie sur la sortie standard |
$encodage = 'utf-8'; |
$mime = $this->getTypeMime(); |
$formatage_json = $this->getFormatageJson(); |
$this->envoyer($contenu, $mime, $encodage, $formatage_json); |
} |
private function getUrlServiceBase() { |
$url_service = $this->config['coel']['urlBaseJrest'].'CoelSyndication/'.$this->service.'/'.$this->format; |
return $url_service; |
} |
private function getNomMethodeService() { |
$methode = ''; |
$service_formate = str_replace(' ', '', ucwords(implode(' ', explode('_', $this->service)))); |
$methode = 'getService'.$service_formate; |
return $methode; |
} |
private function getTypeMime() { |
$mime = ''; |
switch ($this->format) { |
case 'atom' : |
$mime = 'application/atom+xml'; |
break; |
case 'rss1' : |
case 'rss2' : |
$mime = 'application/rss+xml'; |
break; |
default: |
$mime = 'text/html'; |
} |
return $mime; |
} |
private function getFormatageJson() { |
$json = false; |
switch ($this->service) { |
case 'liste_des_flux' : |
$json = true; |
break; |
default: |
$json = false; |
} |
return $json; |
} |
private function getFlux($nom) { |
$nom = strtolower($nom); |
return isset($this->flux[$nom]) ? $this->flux[$nom] : array(); |
} |
private function setFlux($nom, $titre, $description) { |
$url_base = $this->config['appli']['urlBaseJrest'].'ProjetSyndication/'; |
$formats = array('atom', 'rss2', 'rss1'); |
$flux = array(); |
foreach ($formats as $format) { |
$url = $url_base.$nom.'/'.$format; |
$flux[$format] = $url; |
} |
$this->flux[$nom] = array('titre' => $titre, 'description' => $description, 'urls' => $flux); |
} |
private function chargerListeDesFlux() { |
$this->setFlux('actifs', 'Flux de syndication des projets les plus actifs', |
'Ce flux fournit des informations sur les projets les plus actifs de l\'espace projet'); |
$this->setFlux('derniers_messages', 'Flux de syndication des derniers messages', |
'Ce flux fournit des informations sur les derniers messages de l\'espace projet'); |
} |
private function getServiceListeDesFlux() { |
return $this->flux; |
} |
private function getServiceActifs() { |
// Construction de la requête |
$requete_projets = ' select p_id, p_titre as titre, p_resume as description, pl_id_liste, plle_id_liste, p_avoir_document, ps_nombre_inscrit, ps_pourcent,'. |
' p_wikini, ps_doc_derniere_semaine, p_avoir_document, ps_nombre_inscrit_derniere_semaine, '. |
' ps_nombre_membre_yahoo, ps_msg_derniere_semaine, ps_modifwiki_derniere_semaine, p_en_dormance from'. |
' projet left join projet_lien_liste on p_id=pl_id_projet'. |
' left join projet_lien_liste_externe on p_id=plle_id_projet'. |
' left join projet_statistiques on p_id=ps_ce_projet and ps_dernier=1'. |
' WHERE p_en_dormance = 0'. |
' group by p_id order by ps_pourcent desc'; |
$elements = $this->executerRequete($requete_projets); |
// Création du contenu |
$contenu = $this->executerService('cpr_nom', $elements); |
return $contenu; |
} |
private function getServiceDerniersMessages() { |
/*include_once("lib/ezmlmAccessObject.class.php"); |
$xml_parser = &new ezmlmAccessObject('list_info', 'tela-botanica.org', |
'determination_plantes', 'fr', 'http://localhost') ; |
$xml_parser->load(); |
ob_start(); |
$resultat = $xml_parser->parse() ; |
$calendrier = ob_get_contents(); |
ob_end_clean();*/ |
} |
private function executerRequete($requete) { |
try { |
$infos = $this->bdd->query($requete)->fetchAll(PDO::FETCH_ASSOC); |
if ($infos === false) { |
$this->messages[] = "La requête a retourné aucun résultat."; |
} |
} catch (PDOException $e) { |
$this->messages[] = sprintf($this->getTxt('sql_erreur'), $e->getFile(), $e->getLine(), $e->getMessage()); |
} |
return $infos; |
} |
private function executerService($champ_titre, $elements) { |
// Prétraitement des données |
$donnees = $this->construireDonneesCommunesAuFlux($elements); |
foreach ($elements as $element) { |
//$xml = $this->getXmlHisto($element); |
//$enrg = $this->getTableauDepuisXmlHisto($xml); |
//$diff = $this->getDiffInfos($element); |
//$diff['differences'] = $this->getDiff($element); |
//$diff_html = (!is_null($diff['differences'])) ? Coel::traiterSquelettePhp($this->squelette_diff, $diff) : ''; |
$item = $this->construireDonneesCommunesAuxItems($element); |
$item['titre'] = $this->creerTitre($champ_titre, $element, $enrg); |
$item['guid'] = sprintf($this->config['appli']['guid'], 'projet', $element['p_id']); |
$item['lien'] = $this->config['appli']['url_base_projet'].'?id_projet='.urlencode($element['p_id']); |
$item['description'] = "<h4>".$element['ps_nombre_inscrit'].' inscrits - '.$element['ps_msg_derniere_semaine'].' nouveaux messages</h4>'; |
$item['description'] .= '<p>'.$this->creerDescription($element, $enrg).'</p>'; |
$item['description'] .= $diff_html; |
$item['description'] = $this->nettoyerTexte($item['description']); |
$item['description_encodee'] = htmlspecialchars($item['description']); |
$donnees['items'][] = $item; |
} |
// Création du contenu à partir d'un template PHP |
$contenu = ProjetService::traiterSquelettePhp($this->squelette, $donnees); |
return $contenu; |
} |
private function creerTitre($champ, $element, $enrg) { |
$titre = ''; |
if (isset($element['titre'])) { |
$titre = $element['titre']; |
} else if (isset($element[$champ])) { |
$titre = $element[$champ]; |
} else if (isset($enrg[$champ])) { |
$titre = $enrg[$champ]; |
} |
$titre = $this->nettoyerTexte($titre); |
return $titre; |
} |
private function creerDescription($element, $enrg) { |
$description = ''; |
if (isset($element['description'])) { |
$description = strip_tags($element['description']); |
} |
return $description; |
} |
private function nettoyerNomChamps($infos) { |
$sortie = array(); |
foreach ($infos as $champ => $valeur) { |
if (preg_match('/^__(.+)$/', $champ, $match)) { |
$sortie[$match[1]] = $valeur; |
} else { |
$sortie[$champ] = $valeur; |
} |
} |
return $sortie; |
} |
private function traiterInfosPrecedentes($infos_courantes, $infos_precedentes) { |
$infos_precedentes_traitees = array(); |
foreach ($infos_precedentes as $champ => $valeur) { |
if ($champ == 'cmhl_date_modification') { |
$infos_precedentes_traitees['date_prec'] = $valeur; |
} else if ($champ == 'cmhl_enregistrement') { |
$infos_precedentes_traitees['enrg_prec'] = $valeur; |
} else if (preg_match('/^__(.+)$/', $champ, $match)) { |
$infos_precedentes_traitees[$match[1].'_prec'] = $valeur; |
} |
} |
$sortie = array_merge($infos_courantes, $infos_precedentes_traitees); |
return $sortie; |
} |
private function nettoyerTexte($txt) { |
$txt = preg_replace('/&(?!amp;)/i', '&', $txt, -1); |
return $txt; |
} |
private function getMessageModif($item) { |
$message = $item['etat'].' le '.$item['date_maj_simple'].' par '.$item['modifier_par'].' depuis l\'IP '.$item['ip']; |
return $message; |
} |
private function construireDonneesCommunesAuxItems($info) { |
$item = array(); |
$date_modification_timestamp = strtotime($info['cmhl_date_modification']); |
$item['date_maj_simple'] = strftime('%A %d %B %Y à %H:%M', $date_modification_timestamp); |
$item['date_maj_RSS'] = date(DATE_RSS, $date_modification_timestamp); |
$item['date_maj_ATOM'] = date(DATE_ATOM, $date_modification_timestamp); |
$item['date_maj_W3C'] = date(DATE_W3C, $date_modification_timestamp); |
$item['guid'] = $info['cmhl_id_historique_ligne']; |
$item['cle'] = $info['cmhl_cle_ligne']; |
$item['ip'] = $info['cmhl_ip']; |
$item['modifier_par'] = $info['modifier_par']; |
$item['etat'] = isset($info['cmhl_ce_etat']) ? $this->getTexteEtat($info['cmhl_ce_etat']) : ''; |
return $item; |
} |
private function getTexteEtat($code) { |
$etat = ''; |
switch ($code) { |
case '1' : |
$etat = 'Ajouté'; |
break; |
case '2' : |
$etat = 'Modifié'; |
break; |
case '3' : |
$etat = 'Supprimé'; |
break; |
default : |
$etat = '!Problème!'; |
$e = "Le champ cmhl_ce_etat possède une valeur innatendue : $code"; |
$this->messages[] = $e; |
} |
return $etat; |
} |
private function construireDonneesCommunesAuFlux($infos) { |
$donnees = $this->getFlux($this->service); |
$donnees['guid'] = $this->getUrlServiceBase(); |
$donnees['lien_service'] = $this->creerUrlService(); |
$donnees['lien_projet'] = $this->config['appli']['url_base_projet']; |
$donnees['editeur'] = $this->config['coel']['editeur']; |
$derniere_info_en_date = reset($infos); |
$date_modification_timestamp = strtotime($derniere_info_en_date['cmhl_date_modification']); |
$donnees['date_maj_RSS'] = date(DATE_RSS, $date_modification_timestamp); |
$donnees['date_maj_ATOM'] = date(DATE_ATOM, $date_modification_timestamp); |
$donnees['date_maj_W3C'] = date(DATE_W3C, $date_modification_timestamp); |
$donnees['annee_courante'] = date('Y'); |
$donnees['generateur'] = 'COEL - Jrest'; |
preg_match('/([0-9]+)/', '$Revision: 381 $', $match); |
$donnees['generateur_version'] = $match[1]; |
return $donnees; |
} |
private function creerUrlService() { |
$url_service = $this->getUrlServiceBase(); |
if (isset($this->start) || isset($this->limit)) { |
$arguments = array(); |
if (isset($this->start) && isset($_GET['start'])) { |
$arguments[] = 'start='.$this->start; |
} |
if (isset($this->limit) && isset($_GET['limit'])) { |
$arguments[] = 'limit='.($this->limit/2); |
} |
if (count($arguments) > 0) { |
$url_service .= '?'.implode('&', $arguments); |
} |
} |
return $url_service; |
} |
} |
/trunk/jrest/services/squelettes/diff.tpl.html |
---|
New file |
0,0 → 1,36 |
<table style="border:1px solid black;border-collapse:collapse;" summary="Différences entre les données du <?=$date_ancienne?> et du <?=$date_nouvelle?>."> |
<caption style="text-align:left;font-weight:bold;">Différences</caption> |
<thead style="border:1px solid black;"> |
<tr> |
<th rowspan="2" style="border:1px dotted;">Champ</th> |
<th rowspan="2" style="border:1px dotted;">Type</th> |
<th <?=(($etat == 'M') ? 'colspan="2"' : '');?> style="border:1px dotted;">Valeur</th> |
</tr> |
<tr> |
<?php if ($etat == 'M') : ?> |
<th style="border:1px dotted;">Ancienne (<?=$date_ancienne?>)</th> |
<?php endif; ?> |
<th style="border:1px dotted;">Nouvelle (<?=$date_nouvelle?>)</th> |
</tr> |
</thead> |
<tbody> |
<?php foreach ($differences as $champ => $diff) : ?> |
<?php if ($diff['type'] == 'A') : |
$couleur = CFC; |
elseif ($diff['type'] == 'M') : |
$couleur = FFC; |
elseif ($diff['type'] == 'S') : |
$couleur = F99; |
endif; ?> |
<tr style="background-color:#<?=$couleur?>;"> |
<td style="border:1px dotted;"><?=$champ?></td> |
<td style="text-align:center;border:1px dotted;"><?=$diff['type_txt']?></td> |
<?php if ($etat == 'M') : ?> |
<td style="border:1px dotted;"><?=$diff['ancien']?></td> |
<?php endif; ?> |
<td style="border:1px dotted;"><?=$diff['nouveau']?></td> |
</tr> |
<?php endforeach; ?> |
</tbody> |
</table> |
/trunk/jrest/services/squelettes/atom.tpl.xml |
---|
New file |
0,0 → 1,33 |
<?php echo '<?xml version="1.0" encoding="UTF-8"?>'."\n";?> |
<feed xmlns="http://www.w3.org/2005/Atom"> |
<title><?=$titre?></title> |
<link href="<?=$lien_coel?>" rel="alternate" type="text/html" hreflang="fr" /> |
<link href="<?=$lien_service?>" rel="self" type="application/atom+xml"/> |
<updated><?=$date_maj_ATOM?></updated> |
<author> |
<name><?=$editeur?></name> |
</author> |
<id><?=$guid?></id> |
<rights>Copyright (c) <?=$annee_courante?>, <?=$editeur?></rights> |
<generator uri="<?=$lien_coel?>" version="<?=$generateur_version?>"><?=$generateur?></generator> |
<?php if (isset($items)) : ?> |
<?php foreach ($items as $item) : ?> |
<entry> |
<id><?=$item['lien']?></id> |
<title><?=$item['titre']?></title> |
<link href="<?=$item['lien']?>"/> |
<updated><?=$item['date_maj_ATOM']?></updated> |
<author><name><?=$item['modifier_par']?></name></author> |
<content type="xhtml" xml:lang="fr"> |
<div xmlns="http://www.w3.org/1999/xhtml"> |
<?=$item['description'];?> |
</div> |
</content> |
</entry> |
<?php endforeach; ?> |
<?php endif; ?> |
</feed> |
/trunk/jrest/services/squelettes/rss1.tpl.xml |
---|
New file |
0,0 → 1,45 |
<?php echo '<?xml version="1.0" encoding="UTF-8"?>'."\n";?> |
<!DOCTYPE rdf:RDF [ |
<!ENTITY % HTMLlat1 PUBLIC |
"-//W3C//ENTITIES Latin 1 for XHTML//EN" |
"http://www.w3.org/TR/xhtml1/DTD/xhtml-lat1.ent"> |
%HTMLlat1; |
]> |
<rdf:RDF |
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" |
xmlns:dc="http://purl.org/dc/elements/1.1/" |
xmlns="http://purl.org/rss/1.0/"> |
<channel rdf:about="<?=$guid?>"> |
<title><?=$titre?></title> |
<link><?=$lien_coel?></link> |
<description><?=$description?></description> |
<dc:publisher><?=$editeur?></dc:publisher> |
<dc:date><?=$date_maj_W3C?></dc:date> |
<?php if (isset($items)) : ?> |
<items> |
<rdf:Seq> |
<?php foreach ($items as $item) : ?> |
<rdf:li resource="<?=$item['guid']?>" /> |
<?php endforeach; ?> |
</rdf:Seq> |
</items> |
<?php endif; ?> |
</channel> |
<?php if (isset($items)) : ?> |
<?php foreach ($items as $item) : ?> |
<item rdf:about="<?=$item['guid']?>"> |
<title><?=$item['titre']?></title> |
<link><?=$item['lien']?></link> |
<description><?=$item['description_encodee']?></description> |
<dc:date><?=$item['date_maj_W3C']?></dc:date> |
</item> |
<?php endforeach; ?> |
<?php endif; ?> |
</rdf:RDF> |
/trunk/jrest/services/squelettes/rss2.tpl.xml |
---|
New file |
0,0 → 1,22 |
<?php echo '<?xml version="1.0" encoding="UTF-8"?>'."\n";?> |
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"> |
<channel> |
<title><?=$titre?></title> |
<link><?=$lien_projet?></link> |
<atom:link href="<?=$lien_service?>" rel="self" type="application/rss+xml" /> |
<description><?=$description?></description> |
<?php if (isset($items)) : ?> |
<?php foreach ($items as $item) : ?> |
<item> |
<guid><?=$item['guid']?></guid> |
<title><?=$item['titre']?></title> |
<link><?=$item['lien']?></link> |
<description><?=$item['description_encodee']?></description> |
<pubDate><?=$item['date_maj_RSS']?></pubDate> |
</item> |
<?php endforeach; ?> |
<?php endif; ?> |
</channel> |
</rss> |
/trunk/jrest/services/DocumentsRss.php |
---|
1,81 → 1,81 |
<?php |
/** |
* PHP Version 5 |
* |
* @category PHP |
* @package papyrus_bp |
* @author aurelien <aurelien@tela-botanica.org> |
* @copyright 2010 Tela-Botanica |
* @license http://www.cecill.info/licences/Licence_CeCILL_V2-fr.txt Licence CECILL |
* @version SVN: <svn_id> |
* @link /doc/papyrus_bp/ |
*/ |
Class DocumentsRss extends ProjetService { |
public function __construct($config, $demarrer_session= true) { |
parent::__construct($config, $demarrer_session); |
} |
// TODO: gérer plusieurs format et utiliser les mêmes classes communes que |
// celles du cel |
public function getElement($uid){ |
$format = 'rss2'; |
// on selectionne les projets les plus actifs |
$requete_docs_projets = 'SELECT * FROM projet_documents '. |
'WHERE pd_ce_type != 0 AND pd_visibilite = "public" '. |
'ORDER BY pd_date_de_mise_a_jour DESC '. |
'LIMIT 0,5'; |
$resume = array(); |
$titre = htmlspecialchars('Derniers documents publics '); |
$lien = 'http://www.tela-botanica.org/page:liste_projets'; |
$docs = $this->bdd->query($requete_docs_projets)->fetchAll(); |
$rss = '<?xml version="1.0" encoding="UTF-8"?>'. |
'<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"> |
<channel> |
<title>'.$titre.'</title> |
<link>'.$lien.'</link> |
<atom:link href="" rel="self" type="application/rss+xml" /> |
<description>'.$titre.'</description>'; |
foreach($docs as $doc) { |
$infos_projet = $this->obtenirInformationsProjet($doc['pd_ce_projet']); |
$date_modification_timestamp = strtotime($doc['pd_date_de_mise_a_jour']); |
$date_maj_doc = date(DATE_RSS, $date_modification_timestamp); |
$nom_projet = 'Dans le projet '.$infos_projet[0]['p_titre']; |
$id_doc = $doc['pd_id']; |
$nom_doc = $doc['pd_nom']; |
$description = preg_replace('/&(?!(a-z+|#0-9+|#x0-9a-f+);)/i', '&', $nom_projet); |
$description = preg_replace('/000null/i', '', $nom_projet); |
$description = htmlspecialchars($description); |
$lien_doc = 'http://www.tela-botanica.org/projets/'.$doc['pd_ce_projet'].'/telechargement/'.$doc['pd_id']; |
$rss .='<item> |
<guid>'.$id_doc.'</guid> |
<title>'.$nom_doc.'</title> |
<link>'.$lien_doc.'</link> |
<description>'.$description.'</description> |
<category>Document</category> |
<pubDate>'.$date_maj_doc.'</pubDate> |
</item>'; |
} |
$rss .= '</channel>'. |
'</rss>'; |
echo $rss; |
} |
} |
<?php |
/** |
* PHP Version 5 |
* |
* @category PHP |
* @package papyrus_bp |
* @author aurelien <aurelien@tela-botanica.org> |
* @copyright 2010 Tela-Botanica |
* @license http://www.cecill.info/licences/Licence_CeCILL_V2-fr.txt Licence CECILL |
* @version SVN: <svn_id> |
* @link /doc/papyrus_bp/ |
*/ |
Class DocumentsRss extends ProjetService { |
public function __construct($config, $demarrer_session= true) { |
parent::__construct($config, $demarrer_session); |
} |
// TODO: gérer plusieurs format et utiliser les mêmes classes communes que |
// celles du cel |
public function getElement($uid){ |
$format = 'rss2'; |
// on selectionne les projets les plus actifs |
$requete_docs_projets = 'SELECT * FROM projet_documents '. |
'WHERE pd_ce_type != 0 AND pd_visibilite = "public" '. |
'ORDER BY pd_date_de_mise_a_jour DESC '. |
'LIMIT 0,5'; |
$resume = array(); |
$titre = htmlspecialchars('Derniers documents publics '); |
$lien = 'http://www.tela-botanica.org/page:liste_projets'; |
$docs = $this->bdd->query($requete_docs_projets)->fetchAll(); |
$rss = '<?xml version="1.0" encoding="UTF-8"?>'. |
'<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"> |
<channel> |
<title>'.$titre.'</title> |
<link>'.$lien.'</link> |
<atom:link href="" rel="self" type="application/rss+xml" /> |
<description>'.$titre.'</description>'; |
foreach($docs as $doc) { |
$infos_projet = $this->obtenirInformationsProjet($doc['pd_ce_projet']); |
$date_modification_timestamp = strtotime($doc['pd_date_de_mise_a_jour']); |
$date_maj_doc = date(DATE_RSS, $date_modification_timestamp); |
$nom_projet = 'Dans le projet '.$infos_projet[0]['p_titre']; |
$id_doc = $doc['pd_id']; |
$nom_doc = $doc['pd_nom']; |
$description = preg_replace('/&(?!(a-z+|#0-9+|#x0-9a-f+);)/i', '&', $nom_projet); |
$description = preg_replace('/000null/i', '', $nom_projet); |
$description = htmlspecialchars($description); |
$lien_doc = 'http://www.tela-botanica.org/projets/'.$doc['pd_ce_projet'].'/telechargement/'.$doc['pd_id']; |
$rss .='<item> |
<guid>'.$id_doc.'</guid> |
<title>'.$nom_doc.'</title> |
<link>'.$lien_doc.'</link> |
<description>'.$description.'</description> |
<category>Document</category> |
<pubDate>'.$date_maj_doc.'</pubDate> |
</item>'; |
} |
$rss .= '</channel>'. |
'</rss>'; |
echo $rss; |
} |
} |
?> |
/trunk/jrest/services/Suppression.php |
---|
1,69 → 1,69 |
<?php |
/** |
* PHP Version 5 |
* |
* @category PHP |
* @package projet_bp |
* @author aurelien <aurelien@tela-botanica.org> |
* @copyright 2010 Tela-Botanica |
* @license http://www.cecill.info/licences/Licence_CeCILL_V2-fr.txt Licence CECILL |
* @version SVN: <svn_id> |
* @link /doc/projet_bp/ |
*/ |
class Suppression extends ProjetService { |
public function getElement($uid) { |
$id_utilisateur = (isset($_GET['id_utilisateur'])) ? $_GET['id_utilisateur'] : false; |
$mail = (isset($_GET['mail'])) ? $_GET['mail'] : false; |
if(!$id_utilisateur) { |
return false; |
} |
// on selectionne la liste des projets auxquel on est inscrit |
$projets = $this->obtenirProjetsPourParticipant($id_utilisateur); |
// si pas de projets, rien à faire |
if(count($projets) <= 0) { |
$this->envoyer("OK"); |
return; |
} |
// sinon on itère sur chaque projet |
foreach($projets as $projet) { |
$id_projet = $projet['p_id']; |
// et on le supprime du projet |
$suppression_participant = $this->supprimerParticipantAProjet($id_utilisateur, $id_projet); |
// ainsi que des listes associées |
if($mail) { |
$id_projet = $projet['p_id']; |
$listes = $this->obtenirListesAssocieesAuProjet($id_projet); |
// si pas de liste, rien à faire |
if(count($listes) <= 0) { |
continue; |
} |
$nom_liste = $listes[0]['pl_nom_liste']; |
$id_liste = $listes[0]['pl_id_liste']; |
$suppression_liste = $this->supprimerInscriptionAListeProjet($id_utilisateur, $id_liste); |
// on supprime l'abonnement |
if($this->estAbonneAListe($nom_liste, $mail)) { |
if(!$this->desinscriptionListe($nom_liste, $mail)) { |
$this->envoyer("false"); |
} |
} |
} |
} |
$this->envoyer("OK"); |
return; |
} |
} |
?> |
<?php |
/** |
* PHP Version 5 |
* |
* @category PHP |
* @package projet_bp |
* @author aurelien <aurelien@tela-botanica.org> |
* @copyright 2010 Tela-Botanica |
* @license http://www.cecill.info/licences/Licence_CeCILL_V2-fr.txt Licence CECILL |
* @version SVN: <svn_id> |
* @link /doc/projet_bp/ |
*/ |
class Suppression extends ProjetService { |
public function getElement($uid) { |
$id_utilisateur = (isset($_GET['id_utilisateur'])) ? $_GET['id_utilisateur'] : false; |
$mail = (isset($_GET['mail'])) ? $_GET['mail'] : false; |
if(!$id_utilisateur) { |
return false; |
} |
// on selectionne la liste des projets auxquel on est inscrit |
$projets = $this->obtenirProjetsPourParticipant($id_utilisateur); |
// si pas de projets, rien à faire |
if(count($projets) <= 0) { |
$this->envoyer("OK"); |
return; |
} |
// sinon on itère sur chaque projet |
foreach($projets as $projet) { |
$id_projet = $projet['p_id']; |
// et on le supprime du projet |
$suppression_participant = $this->supprimerParticipantAProjet($id_utilisateur, $id_projet); |
// ainsi que des listes associées |
if($mail) { |
$id_projet = $projet['p_id']; |
$listes = $this->obtenirListesAssocieesAuProjet($id_projet); |
// si pas de liste, rien à faire |
if(count($listes) <= 0) { |
continue; |
} |
$nom_liste = $listes[0]['pl_nom_liste']; |
$id_liste = $listes[0]['pl_id_liste']; |
$suppression_liste = $this->supprimerInscriptionAListeProjet($id_utilisateur, $id_liste); |
// on supprime l'abonnement |
if($this->estAbonneAListe($nom_liste, $mail)) { |
if(!$this->desinscriptionListe($nom_liste, $mail)) { |
$this->envoyer("false"); |
} |
} |
} |
} |
$this->envoyer("OK"); |
return; |
} |
} |
?> |
/trunk/jrest/services/MigrationWiki.php |
---|
1,273 → 1,195 |
<?php |
class MigrationWiki extends ProjetService { |
const dry_run = false; |
public function __construct($config, $demarrer_session= true) { |
parent::__construct($config, $demarrer_session); |
define('NL',"\n"); |
} |
private function executerRequeteManip($requete, $mode_fetch = false) { |
// Fonction de commodité pour afficher les requetes au lieu de les executer |
if (self::dry_run) { |
echo '<pre>'.str_replace('),','),'.NL, $requete).'</pre>'; |
return true; |
} else { |
if($mode_fetch) { |
return $this->bdd->query($requete)->fetchAll($mode_fetch); |
} else { |
return $this->bdd->query($requete); |
} |
} |
} |
private function executerRequete($requete, $mode_fetch = false) { |
if (self::dry_run) { |
echo '<pre>'.str_replace('),','),'.NL, $requete).'</pre>'.NL.NL; |
} |
return $this->bdd->query($requete)->fetchAll($mode_fetch); |
} |
public function getElement($uid){ |
$nom_admin = $this->config['appli']['nom_admin_wiki']; |
$mail_admin = $this->config['appli']['adresse_admin_wiki']; |
$pass_admin = $this->config['appli']['pass_admin_wiki']; |
$requete_projets_wikinis = 'SELECT * FROM gen_wikini'; |
$wikinis_projets = $this->executerRequete($requete_projets_wikinis, PDO::FETCH_ASSOC); |
foreach($wikinis_projets as $wikini) { |
// test sur un wiki |
/*if($wikini['gewi_code_alpha_wikini'] != 'bibliobota') { |
continue; |
}*/ |
$base = $wikini['gewi_bdd_nom']; |
$prefixe = $wikini['gewi_table_prefix']; |
$chemin_wiki_sur_site = $this->config['appli']['chemin_wikis_integres']; |
//$chemin_wiki = $wikini['gewi_chemin']; |
$chemin_wiki = '/home/aurelien/web/wikini/'.$wikini['gewi_code_alpha_wikini']; |
echo NL.'Traitement du wiki '.$chemin_wiki.NL; |
echo NL.$chemin_wiki.NL; |
if(!file_exists($chemin_wiki)) { |
echo 'Impossible de migrer le wikini '.$wikini['gewi_code_alpha_wikini'].' : le dossier n\'existe pas'.NL.NL.NL.NL; |
continue; |
} |
$chemin_base_wiki_defaut = $this->config['appli']['chemin_wiki_defaut']; |
$infos_admin = array('name' =>$nom_admin, 'email' => $mail_admin, 'password' => $pass_admin); |
if(!$this->verifierPresenceTableTriple($base, $prefixe)) { |
echo 'migration du wiki '.$wikini['gewi_code_alpha_wikini'].NL; |
$this->creerTableTriple($base, $prefixe); |
$this->ajouterUtilisateurAdmin($base,$prefixe, $infos_admin); |
$this->copierFichiersWikini($chemin_base_wiki_defaut, $chemin_wiki); |
$this->changerVersionWakkaConfig($chemin_wiki); |
echo 'migration du wiki '.$wikini['gewi_code_alpha_wikini'].' effectuée '.NL.NL.NL.NL; |
} else { |
echo 'wiki dejà à jour '.$wikini['gewi_code_alpha_wikini'].NL.NL.NL.NL; |
} |
$this->ajoutPageFormatees($chemin_wiki, $infos_admin); |
} |
} |
private function verifierPresenceTableTriple($base, $prefixe) { |
$requete_presence_table = 'SELECT COUNT(*) as table_existe FROM information_schema.tables |
WHERE TABLE_SCHEMA = "'.$base.'" AND TABLE_NAME = "'.$prefixe.'triples"'; |
$resultat_presence_table = $this->executerRequete($requete_presence_table); |
$presence_table = false; |
foreach($resultat_presence_table as $table_est_presente) { |
if($table_est_presente['table_existe'] >= 1) { |
$presence_table = true; |
break; |
} |
} |
return $presence_table; |
} |
private function creerTableTriple($base, $prefixe) { |
echo 'Création de la table triple '.NL; |
$requete_creation_table = 'CREATE TABLE '.$base.'.'.$prefixe.'triples (' . |
' id int(10) unsigned NOT NULL auto_increment,' . |
' resource varchar(255) NOT NULL default \'\',' . |
' property varchar(255) NOT NULL default \'\',' . |
' value text NOT NULL default \'\',' . |
' PRIMARY KEY (id),' . |
' KEY resource (resource),' . |
' KEY property (property)' . |
') TYPE=MyISAM'; |
return $this->executerRequeteManip($requete_creation_table); |
} |
private function verifierPresenceTableUsers($base, $prefixe) { |
$requete_presence_table = 'SELECT COUNT(*) as table_existe FROM information_schema.tables |
WHERE TABLE_SCHEMA = "'.$base.'" AND TABLE_NAME = "'.$prefixe.'users"'; |
$resultat_presence_table = $this->executerRequete($requete_presence_table); |
$presence_table = false; |
foreach($resultat_presence_table as $table_est_presente) { |
if($table_est_presente['table_existe'] >= 1) { |
$presence_table = true; |
break; |
} |
} |
return $presence_table; |
} |
private function ajouterUtilisateurAdmin($base, $prefixe, $infos_admin) { |
if(!$this->verifierPresenceTableUsers($base, $prefixe)) { |
echo 'Impossible d\'ajouter l\'adminwiki : '.$prefixe.'_users n\'existe_pas'.NL; |
return; |
} |
echo 'Ajout de l\'utilisateur wikiAdmin '.NL; |
$requete_suppression_si_admin_present = 'DELETE FROM '.$base.'.'.$prefixe.'users '. |
'WHERE name ="'.$infos_admin['name'].'"'; |
$this->executerRequeteManip($requete_suppression_si_admin_present); |
$requete_creation_admin = "insert into ".$base.'.'.$prefixe."users set ". |
"signuptime = now(), ". |
"name = '".$infos_admin['name']."', ". |
"email = '".$infos_admin['email']."', ". |
"password = md5('".$infos_admin['password']."')"; |
return $this->executerRequeteManip($requete_creation_admin); |
} |
private function changerVersionWakkaConfig($chemin_wikini) { |
if(file_exists($chemin_wikini.'wakka.config.php')) { |
$contenu_wakka_config = file_get_contents($chemin_wikini.'wakka.config.php'); |
$contenu_wakka_config_maj = str_replace('"wikini_version" => "0.4.3"','"wikini_version" => "0.5.0"',$contenu_wakka_config); |
$contenu_wakka_config_maj = str_replace("'wikini_version' => '0.4.3'","'wikini_version' => '0.5.0'",$contenu_wakka_config_maj); |
if(self::dry_run) { |
echo 'Wakka Config mis à jour '.$contenu_wakka_config_maj.NL; |
} else { |
//file_put_contents($chemin_wikini.'wakka.config.php', $contenu_wakka_config_maj); |
} |
echo 'Changement de la version de wikini '.NL; |
} else { |
echo 'Attention ! le fichier '.$chemin_wikini.'wakka.config.php n\'existe pas '.NL; |
} |
} |
private function copierFichiersWikini($chemin_base_wiki_defaut, $chemin_wiki_dest) { |
if(self::dry_run) { |
echo 'copie de '.$chemin_base_wiki_defaut.' vers '.$chemin_wiki_dest.NL; |
$copie_recursive = true; |
} else { |
if(trim($chemin_base_wiki_defaut) != '/' && trim($chemin_wiki_dest) != '/') { |
$copie_recursive = shell_exec( " cp -Rf -a ".$chemin_base_wiki_defaut."* ".$chemin_wiki_dest." 2>&1 " ); |
} |
} |
return $copie_recursive; |
} |
private function ajoutPageFormatees($chemin_wikini, $utilisateur) { |
$chemin_base_wiki_defaut = $this->config['appli']['chemin_wiki_defaut']; |
require_once($chemin_base_wiki_defaut.'wakka_class.php'); |
$nom_admin = $this->config['appli']['nom_admin_wiki']; |
$chemin_wikini = rtrim($chemin_wikini,'/'); |
require_once($chemin_wikini.'/wakka.config.php'); |
// la variable $wakkaConfig est contenu dans le fichier wakka.config.php |
$config = $wakkaConfig; |
$wiki = new Wiki($config); |
$wiki->SetGroupACL("admins", $nom_admin); |
$wiki->setUser($utilisateur); |
//insertion des pages de documentation et des pages standards |
$d = dir($chemin_base_wiki_defaut.'/setup/doc/'); |
while ($doc = $d->read()){ |
if (is_dir($doc) || substr($doc, -4) != '.txt') {continue;} |
$pagecontent = implode ('', file($chemin_base_wiki_defaut.'/setup/doc/'.$doc)); |
$pagecontent = mb_convert_encoding($pagecontent,'UTF-8','ISO-8859-15'); |
if ($doc=='_root_page.txt'){ |
$pagename = $config["root_page"]; |
}else{ |
$pagename = substr($doc,0,strpos($doc,'.txt')); |
} |
$base = $config['mysql_database']; |
$requete_existence_page = "Select tag from ".$base.".".$config['table_prefix']."pages where tag='$pagename'"; |
$existence_page = $this->executerRequete($requete_existence_page); |
if (is_array($existence_page) && count($existence_page) > 0) { |
echo 'la page '.$pagename.' existe déjà '.NL; |
} else { |
echo 'Ajout de la page '.$pagename.NL; |
$requete_maj_pages_anciennes = "UPDATE ".$base.".".$config['table_prefix']."pages ". |
"SET ". |
"latest = 'N'". |
"WHERE tag = '$pagename'"; |
$reussite = $this->executerRequeteManip($requete_maj_pages_anciennes); |
$requete_insertion_page = "INSERT INTO ".$base.".".$config['table_prefix']."pages ". |
"SET tag = '$pagename', ". |
"body = ".$this->bdd->quote($pagecontent).", ". |
"user = '".$nom_admin."', ". |
"owner = '".$nom_admin."', " . |
"time = now(), ". |
"latest = 'Y'"; |
$reussite = $this->executerRequeteManip($requete_insertion_page); |
if(!$reussite) { |
echo 'echec de l\'ajout de la page '.$pagename.NL; |
} else { |
// mise à jour des liens entre pages |
$wiki->SetPage($wiki->LoadPage($pagename,"",0)); |
$wiki->ClearLinkTable(); |
$wiki->StartLinkTracking(); |
$wiki->TrackLinkTo($pagename); |
$wiki->StopLinkTracking(); |
$wiki->WriteLinkTable(); |
$wiki->ClearLinkTable(); |
} |
} |
} |
} |
} |
?> |
<?php |
class MigrationWiki extends ProjetService { |
const dry_run = false; |
private function executerRequeteManip($requete, $mode_fetch = false) { |
// Fonction de commodité pour afficher les requetes au lieu de les executer |
if (self::dry_run) { |
echo str_replace('),','),'.NL, $requete); |
return true; |
} else { |
if($mode_fetch) { |
return $this->bdd->query($requete)->fetchAll($mode_fetch); |
} else { |
return $this->bdd->query($requete); |
} |
} |
} |
private function executerRequete($requete, $mode_fetch = false) { |
if (self::dry_run) { |
echo '<pre>'.str_replace('),','),'.NL, $requete).'</pre>'; |
} |
$retour = $this->bdd->query($requete)->fetchAll($mode_fetch); |
return $retour; |
} |
public function __construct($config, $demarrer_session= true) { |
parent::__construct($config, $demarrer_session); |
define('NL',"\n"); |
} |
public function getElement($uid){ |
exit; |
$requete_projets_wikinis = 'SELECT * FROM gen_wikini'; |
$wikinis_projets = $this->executerRequete($requete_projets_wikinis, PDO::FETCH_ASSOC); |
foreach($wikinis_projets as $wikini) { |
// test sur un wiki |
if($wikini['gewi_code_alpha_wikini'] != 'relais') { |
continue; |
} |
$base = $wikini['gewi_bdd_nom']; |
$prefixe = $wikini['gewi_table_prefix']; |
$chemin_wiki_sur_site = $this->config['appli']['chemin_wikis_integres']; |
$chemin_wiki = $wikini['gewi_chemin']; |
echo NL.'Traitement du wiki '.$chemin_wiki.NL; |
echo NL.$chemin_wiki.NL; |
if(!file_exists($chemin_wiki)) { |
echo 'Impossible de migrer le wikini '.$wikini['gewi_code_alpha_wikini'].' : le dossier n\'existe pas'.NL.NL.NL.NL; |
continue; |
} |
$chemin_base_wiki_defaut = $this->config['appli']['chemin_wiki_defaut']; |
$nom_admin = $this->config['appli']['nom_admin_wiki']; |
$mail_admin = $this->config['appli']['adresse_admin_wiki']; |
$pass_admin = $this->config['appli']['pass_admin_wiki']; |
$infos_admin = array('name' =>$nom_admin, 'email' => $mail_admin, 'password' => $pass_admin); |
//if(!$this->verifierPresenceTableTriple($base, $prefixe)) { |
echo 'migration du wiki '.$wikini['gewi_code_alpha_wikini'].NL; |
// $this->creerTableTriple($base, $prefixe); |
// $this->ajouterUtilisateurAdmin($base,$prefixe, $infos_admin); |
$this->copierFichiersWikini($chemin_base_wiki_defaut, $chemin_wiki); |
$this->changerVersionWakkaConfig($chemin_wiki); |
echo 'migration du wiki '.$wikini['gewi_code_alpha_wikini'].' effectuée '.NL.NL.NL.NL; |
//} else { |
// echo 'wiki dejà à jour '.$wikini['gewi_code_alpha_wikini'].NL.NL.NL.NL; |
//} |
} |
} |
private function verifierPresenceTableTriple($base, $prefixe) { |
$requete_presence_table = 'SELECT COUNT(*) as table_existe FROM information_schema.tables |
WHERE TABLE_SCHEMA = "'.$base.'" AND TABLE_NAME = "'.$prefixe.'triples"'; |
$resultat_presence_table = $this->executerRequete($requete_presence_table); |
$presence_table = false; |
foreach($resultat_presence_table as $table_est_presente) { |
if($table_est_presente['table_existe'] >= 1) { |
$presence_table = true; |
break; |
} |
} |
return $presence_table; |
} |
private function creerTableTriple($base, $prefixe) { |
echo 'Création de la table triple '.NL; |
$requete_creation_table = 'CREATE TABLE '.$base.'.'.$prefixe.'triples (' . |
' id int(10) unsigned NOT NULL auto_increment,' . |
' resource varchar(255) NOT NULL default \'\',' . |
' property varchar(255) NOT NULL default \'\',' . |
' value text NOT NULL default \'\',' . |
' PRIMARY KEY (id),' . |
' KEY resource (resource),' . |
' KEY property (property)' . |
') TYPE=MyISAM'; |
return $this->executerRequeteManip($requete_creation_table); |
} |
private function verifierPresenceTableUsers($base, $prefixe) { |
$requete_presence_table = 'SELECT COUNT(*) as table_existe FROM information_schema.tables |
WHERE TABLE_SCHEMA = "'.$base.'" AND TABLE_NAME = "'.$prefixe.'users"'; |
$resultat_presence_table = $this->executerRequete($requete_presence_table); |
$presence_table = false; |
foreach($resultat_presence_table as $table_est_presente) { |
if($table_est_presente['table_existe'] >= 1) { |
$presence_table = true; |
break; |
} |
} |
return $presence_table; |
} |
private function ajouterUtilisateurAdmin($base, $prefixe, $infos_admin) { |
if(!$this->verifierPresenceTableUsers($base, $prefixe)) { |
echo 'Impossible d\'ajouter l\'adminwiki : '.$prefixe.'_users n\'existe_pas'.NL; |
return; |
} |
echo 'Ajout de l\'utilisateur wikiAdmin '.NL; |
$requete_suppression_si_admin_present = 'DELETE FROM '.$base.'.'.$prefixe.'users '. |
'WHERE name ="'.$infos_admin['name'].'"'; |
$this->executerRequeteManip($requete_suppression_si_admin_present); |
$requete_creation_admin = "INSERT INTO ".$base.'.'.$prefixe."users SET ". |
"signuptime = now(), ". |
"name = '".$infos_admin['name']."', ". |
"email = '".$infos_admin['email']."', ". |
"password = md5('".$infos_admin['password']."')"; |
return $this->executerRequeteManip($requete_creation_admin); |
} |
private function changerVersionWakkaConfig($chemin_wikini) { |
if(file_exists($chemin_wikini.'/wakka.config.php')) { |
$contenu_wakka_config = file_get_contents($chemin_wikini.'/wakka.config.php'); |
$contenu_wakka_config_maj = str_replace('"wikini_version" => "0.4.3"','"wikini_version" => "0.5.0"',$contenu_wakka_config); |
$contenu_wakka_config_maj = str_replace("'wikini_version' => '0.4.3'","'wikini_version' => '0.5.0'",$contenu_wakka_config_maj); |
if(self::dry_run) { |
echo 'Wakka Config mis à jour '.$contenu_wakka_config_maj.NL; |
} else { |
file_put_contents($chemin_wikini.'/wakka.config.php', $contenu_wakka_config_maj); |
} |
echo 'Changement de la version de wikini '.NL; |
} else { |
echo 'Attention ! le fichier '.$chemin_wikini.'/wakka.config.php n\'existe pas '.NL; |
} |
} |
private function copierFichiersWikini($chemin_base_wiki_defaut, $chemin_wiki_dest) { |
echo 'copie de '.$chemin_base_wiki_defaut.' vers '.$chemin_wiki_dest.NL; |
if(self::dry_run) { |
$copie_recursive = true; |
} else { |
if(trim($chemin_base_wiki_defaut) != '/' && trim($chemin_wiki_dest) != '/') { |
echo " cp -Rf -a ".$chemin_base_wiki_defaut."* ".$chemin_wiki_dest."/ 2>&1 "; |
$copie_recursive = shell_exec( " cp -Rf -a ".$chemin_base_wiki_defaut."* ".$chemin_wiki_dest."/ 2>&1 " ); |
} |
} |
return $copie_recursive; |
} |
} |
?> |