CC-3547 : Refactoring Views, removing action stack to better work with permissions. Reorganizing Statistics Dialog.

This commit is contained in:
Naomi Aro 2012-03-29 16:27:08 +02:00
parent f48c5ff575
commit 12b23443db
8 changed files with 12 additions and 1311 deletions

View file

@ -18,12 +18,9 @@ $ccAcl->add(new Zend_Acl_Resource('library'))
->add(new Zend_Acl_Resource('plupload'))
->add(new Zend_Acl_Resource('schedule'))
->add(new Zend_Acl_Resource('api'))
->add(new Zend_Acl_Resource('nowplaying'))
->add(new Zend_Acl_Resource('systemstatus'))
->add(new Zend_Acl_Resource('search'))
->add(new Zend_Acl_Resource('dashboard'))
->add(new Zend_Acl_Resource('preference'))
->add(new Zend_Acl_Resource('recorder'))
->add(new Zend_Acl_Resource('showbuilder'))
->add(new Zend_Acl_Resource('auth'))
->add(new Zend_Acl_Resource('playouthistory'))
@ -37,13 +34,11 @@ $ccAcl->allow('G', 'index')
->allow('G', 'showbuilder')
->allow('G', 'api')
->allow('G', 'auth')
->allow('G', 'recorder')
->allow('G', 'schedule')
->allow('G', 'dashboard')
->allow('H', 'usersettings')
->allow('H', 'plupload')
->allow('H', 'library')
->allow('H', 'search')
->allow('H', 'playlist')
->allow('A', 'playouthistory')
->allow('A', 'user')

View file

@ -45,10 +45,7 @@ class ShowbuilderController extends Zend_Controller_Action
$this->view->headScript()->appendFile($this->view->baseUrl('/js/airtime/library/events/library_showbuilder.js?'.$CC_CONFIG['airtime_version']),'text/javascript');
$user = Application_Model_User::GetCurrentUser();
$refer_sses = new Zend_Session_Namespace('referrer');
$userInfo = Zend_Auth::getInstance()->getStorage()->read();
$user = new Application_Model_User($userInfo->id);
if ($request->isPost()) {
$form = new Application_Form_RegisterAirtime();
@ -96,7 +93,7 @@ class ShowbuilderController extends Zend_Controller_Action
}
//popup if previous page was login
if ($refer_sses->referrer == 'login' && Application_Model_Nowplaying::ShouldShowPopUp()
if ($refer_sses->referrer == 'login' && Application_Model_Preference::ShouldShowPopUp()
&& !Application_Model_Preference::GetSupportFeedback() && $user->isAdmin()){
$form = new Application_Form_RegisterAirtime();
@ -111,7 +108,6 @@ class ShowbuilderController extends Zend_Controller_Action
//determine whether to remove/hide/display the library.
$showLib = false;
$user = Application_Model_User::GetCurrentUser();
if (!$user->isGuest()) {
$hideLib = false;
$data = Application_Model_Preference::GetValue("nowplaying_screen", true);
@ -168,8 +164,7 @@ class ShowbuilderController extends Zend_Controller_Action
$baseUrl = $request->getBaseUrl();
$menu = array();
$userInfo = Zend_Auth::getInstance()->getStorage()->read();
$user = new Application_Model_User($userInfo->id);
$user = Application_Model_User::GetCurrentUser();
$item = CcScheduleQuery::create()->findPK($id);
$instance = $item->getCcShowInstances();

View file

@ -1,168 +0,0 @@
<?php
require_once('Subjects.php');
define('USE_ALIB_CLASSES', TRUE);
define('ALIBERR_NOTLOGGED', 30);
define('ALIBERR_NOTEXISTS', 31);
/**
* Authentication/authorization class
*
* @package Airtime
* @subpackage Alib
* @copyright 2010 Sourcefabric O.P.S.
* @license http://www.gnu.org/licenses/gpl.txt
*/
class Alib {
/* ======================================================= public methods */
/* ----------------------------------------------- session/authentication */
/* -------------------------------------------------------- authorization */
/**
* Remove permission record
*
* @param int $permid
* local permission id
* @param int $subj
* local user/group id
* @param int $obj
* local object id
* @return boolean|PEAR_Error
*/
public static function RemovePerm($permid=NULL, $subj=NULL, $obj=NULL)
{
global $CC_CONFIG, $CC_DBC;
$ca = array();
if ($permid) {
$ca[] = "permid=$permid";
}
if ($subj) {
$ca[] = "subj=$subj";
}
if ($obj) {
$ca[] = "obj=$obj";
}
$cond = join(" AND ", $ca);
if (!$cond) {
return TRUE;
}
$sql = "DELETE FROM ".$CC_CONFIG['permTable']." WHERE $cond";
return $CC_DBC->query($sql);
} // fn removePerm
/* ---------------------------------------------------------- object tree */
/* --------------------------------------------------------- users/groups */
/* ------------------------------------------------------------- sessions */
/**
* Get login from session id (token)
*
* @param string $sessid
* @return string|PEAR_Error
*/
public static function GetSessLogin($sessid)
{
global $CC_CONFIG, $CC_DBC;
$sql = "SELECT login FROM ".$CC_CONFIG['sessTable']." WHERE sessid='$sessid'";
$r = $CC_DBC->getOne($sql);
if (PEAR::isError($r)) {
return $r;
}
if (is_null($r)){
return PEAR::raiseError("Alib::GetSessLogin:".
" invalid session id ($sessid)",
ALIBERR_NOTEXISTS, PEAR_ERROR_RETURN);
}
return $r;
} // fn GetSessLogin
/**
* Get user id from session id.
*
* @param string $p_sessid
* @return int|PEAR_Error
*/
public static function GetSessUserId($p_sessid)
{
global $CC_CONFIG, $CC_DBC;
$sql = "SELECT userid FROM ".$CC_CONFIG['sessTable']." WHERE sessid='$p_sessid'";
$r = $CC_DBC->getOne($sql);
if (PEAR::isError($r)) {
return $r;
}
if (is_null($r)) {
return PEAR::raiseError("Alib::getSessUserId:".
" invalid session id ($p_sessid)",
ALIBERR_NOTEXISTS, PEAR_ERROR_RETURN);
}
return $r;
} // fn getSessUserId
/* --------------------------------------------------------- info methods */
/**
* Get all permissions on object.
*
* @param int $id
* @return array|null|PEAR_Error
*/
public static function GetObjPerms($id)
{
global $CC_CONFIG, $CC_DBC;
$sql = "SELECT s.login, p.* FROM ".$CC_CONFIG['permTable']." p, ".$CC_CONFIG['subjTable']." s"
." WHERE s.id=p.subj AND p.obj=$id";
return $CC_DBC->getAll($sql);
} // fn GetObjPerms
/**
* Get all permissions of subject.
*
* @param int $sid
* @return array
*/
public static function GetSubjPerms($sid)
{
global $CC_CONFIG, $CC_DBC;
$sql = "SELECT *"
." FROM ".$CC_CONFIG['permTable']
." WHERE p.subj=$sid";
$a1 = $CC_DBC->getAll($sql);
return $a1;
} // fn GetSubjPerms
/* ------------------------ info methods related to application structure */
/* (this part should be added/rewritten to allow defining/modifying/using
* application structure)
* (only very simple structure definition - in $CC_CONFIG - supported now)
*/
/* ====================================================== private methods */
/**
* Create new session id. Return the new session ID.
*
* @return string
*/
private static function _createSessid()
{
global $CC_CONFIG, $CC_DBC;
for ($c = 1; $c > 0; ){
$sessid = md5(uniqid(rand()));
$sql = "SELECT count(*) FROM ".$CC_CONFIG['sessTable']
." WHERE sessid='$sessid'";
$c = $CC_DBC->getOne($sql);
if (PEAR::isError($c)) {
return $c;
}
}
return $sessid;
} // fn _createSessid
} // class Alib

View file

@ -1,194 +0,0 @@
<?php
class Application_Model_Nowplaying
{
private static function CreateHeaderRow($p_showName, $p_showStart, $p_showEnd){
return array("h", "", $p_showStart, $p_showEnd, $p_showName, "", "", "", "", "", "");
}
private static function CreateDatatableRows($p_dbRows){
$dataTablesRows = array();
$epochNow = time();
$lastRow = end($p_dbRows);
//Information about show is true for all rows in parameter so only check the last row's show
//start and end times.
if (isset($lastRow)){
$showStartDateTime = Application_Model_DateHelper::ConvertToLocalDateTime($lastRow['show_starts']);
$showEndDateTime = Application_Model_DateHelper::ConvertToLocalDateTime($lastRow['show_ends']);
$showStarts = $showStartDateTime->format("Y-m-d H:i:s");
$showEnds = $showEndDateTime->format("Y-m-d H:i:s");
}
foreach ($p_dbRows as $dbRow) {
$itemStartDateTime = Application_Model_DateHelper::ConvertToLocalDateTime($dbRow['item_starts']);
$itemEndDateTime = Application_Model_DateHelper::ConvertToLocalDateTime($dbRow['item_ends']);
$itemStarts = $itemStartDateTime->format("Y-m-d H:i:s");
$itemEnds = $itemEndDateTime->format("Y-m-d H:i:s");
// Allow show to exceed 1 second per CC-3183
$status = ($showEnds < $itemEnds) ? "x" : "";
$type = "a";
$type .= ($itemStartDateTime->getTimestamp() <= $epochNow
&& $epochNow < $itemEndDateTime->getTimestamp()
&& $epochNow < $showEndDateTime->getTimestamp()) ? "c" : "";
// remove millisecond from the time format
$itemStart = explode('.', $dbRow['item_starts']);
$itemEnd = explode('.', $dbRow['item_ends']);
//format duration
$duration = explode('.', $dbRow['clip_length']);
$formatted = self::FormatDuration($duration[0]);
$dataTablesRows[] = array($type, $itemStarts, $itemStarts, $itemEnds,
$formatted, $dbRow['track_title'], $dbRow['artist_name'], $dbRow['album_title'],
$dbRow['playlist_name'], $dbRow['show_name'], $status);
}
//Modify the last entry in the data table to adjust its end time to be equal to the
//shows end time if it exceeds it.
$lastRow = end($dataTablesRows);
if (isset($lastRow) && strtotime($showEnds) < strtotime($lastRow[3])){
$dataTablesRows[sizeof($dataTablesRows)-1][3] = $showEnds;
}
return $dataTablesRows;
}
private static function CreateGapRow($p_gapTime){
return array("g", "", "", "", $p_gapTime, "", "", "", "", "", "");
}
private static function CreateRecordingRow($p_showInstance){
return array("r", "", "", "", $p_showInstance->getName(), "", "", "", "", "", "");
}
/*
* The purpose of this function is to return an array of scheduled
* items. There are two parameters. $p_viewType can be either "now"
* or "day". If "now", we show all scheduled items in the near future.
*
* If "day" we need to find what day was requested by the user, and return
* scheduled items for that day.
*
* $p_dateString is only used when $p_viewType is "day" it is in the format
* "2012-12-31". In this case it tells us which day to use.
*/
public static function GetDataGridData($p_viewType, $p_dateString){
if ($p_viewType == "now"){
$start_dt = new DateTime("now", new DateTimeZone("UTC"));
$end_dt = clone $start_dt;
$start_dt->sub(new DateInterval("PT60S"));
$end_dt->add(new DateInterval("PT24H"));
} else {
//convert to UTC
$utc_dt = Application_Model_DateHelper::ConvertToUtcDateTime($p_dateString);
$start_dt = $utc_dt;
$end_dt = clone $utc_dt;
$end_dt->add(new DateInterval("PT24H"));
}
$starts = $start_dt->format("Y-m-d H:i:s");
$ends = $end_dt->format("Y-m-d H:i:s");
$showIds = Application_Model_ShowInstance::GetShowsInstancesIdsInRange($starts, $ends);
//get all the pieces to be played between the start cut off and the end cut off.
$scheduledItems = Application_Model_Schedule::getScheduleItemsInRange($starts, $ends);
$orderedScheduledItems;
foreach ($scheduledItems as $scheduledItem){
$orderedScheduledItems[$scheduledItem['instance_id']][] = $scheduledItem;
}
$data = array();
foreach ($showIds as $showId){
$instanceId = $showId['id'];
//gets the show information
$si = new Application_Model_ShowInstance($instanceId);
$showId = $si->getShowId();
$show = new Application_Model_Show($showId);
$showStartDateTime = Application_Model_DateHelper::ConvertToLocalDateTime($si->getShowInstanceStart());
$showEndDateTime = Application_Model_DateHelper::ConvertToLocalDateTime($si->getShowInstanceEnd());
//append show header row
$data[] = self::CreateHeaderRow($show->getName(), $showStartDateTime->format("Y-m-d H:i:s"), $showEndDateTime->format("Y-m-d H:i:s"));
$dataTablesRows = self::CreateDatatableRows($orderedScheduledItems[$instanceId]);
//append show audio item rows
$data = array_merge($data, $dataTablesRows);
//append show gap time row
$gapTime = self::FormatDuration($si->getShowEndGapTime(), true);
if ($si->isRecorded())
$data[] = self::CreateRecordingRow($si);
else if ($gapTime > 0)
$data[] = self::CreateGapRow($gapTime);
}
$timeNow = gmdate("Y-m-d H:i:s");
$rows = Application_Model_Show::GetCurrentShow($timeNow);
Application_Model_Show::ConvertToLocalTimeZone($rows, array("starts", "ends", "start_timestamp", "end_timestamp"));
return array("currentShow"=>$rows, "rows"=>$data);
}
public static function ShouldShowPopUp(){
$today = mktime(0, 0, 0, gmdate("m"), gmdate("d"), gmdate("Y"));
$remindDate = Application_Model_Preference::GetRemindMeDate();
if($remindDate == NULL || $today >= $remindDate){
return true;
}
}
/*
* default $time format should be in format of 00:00:00
* if $inSecond = true, then $time should be in seconds
*/
private static function FormatDuration($time, $inSecond=false){
if($inSecond == false){
$duration = explode(':', $time);
}else{
$duration = array();
$duration[0] = intval(($time/3600)%24);
$duration[1] = intval(($time/60)%60);
$duration[2] = $time%60;
}
if($duration[2] == 0){
$duration[2] = '';
}else{
$duration[2] = intval($duration[2],10).'s';
}
if($duration[1] == 0){
if($duration[2] == ''){
$duration[1] = '';
}else{
$duration[1] = intval($duration[1],10).'m ';
}
}else{
$duration[1] = intval($duration[1],10).'m ';
}
if($duration[0] == 0){
$duration[0] = '';
}else{
$duration[0] = intval($duration[0],10).'h ';
}
$out = $duration[0].$duration[1].$duration[2];
return $out;
}
}

View file

@ -773,5 +773,13 @@ class Application_Model_Preference
return self::GetValue("live_dj_source_connection_url");
}
/* User specific preferences end */
public static function ShouldShowPopUp(){
$today = mktime(0, 0, 0, gmdate("m"), gmdate("d"), gmdate("Y"));
$remindDate = Application_Model_Preference::GetRemindMeDate();
if($remindDate == NULL || $today >= $remindDate){
return true;
}
}
}

View file

@ -1,401 +0,0 @@
<?php
/**
* Preference storage class.
*
* @package Airtime
* @subpackage StorageServer
* @copyright 2010 Sourcefabric O.P.S.
* @license http://www.gnu.org/licenses/gpl.txt
* @see Application_Model_StoredFile
*/
/* ================== Prefs ================== */
class Prefs {
/**
* Constructor
*/
public function __construct()
{
}
/* ======================================================= public methods */
/* ----------------------------------------------------- user preferences */
/**
* Read preference record by session id
*
* @param string $sessid
* session id
* @param string $key
* preference key
* @return string
* preference value
*/
function loadPref($sessid, $key)
{
$subjid = Alib::GetSessUserId($sessid);
if (PEAR::isError($subjid)) {
return $subjid;
}
if (is_null($subjid)) {
return PEAR::raiseError("Prefs::loadPref: invalid session id",
GBERR_SESS);
}
$val = $this->readVal($subjid, $key);
if (PEAR::isError($val)) {
return $val;
}
if ($val === FALSE) {
return PEAR::raiseError("Prefs::loadPref: invalid preference key",
GBERR_PREF);
}
return $val;
}
/**
* Save preference record by session id
*
* @param string $sessid
* session id
* @param string $key
* preference key
* @param string $value
* preference value
* @return boolean
*/
function savePref($sessid, $key, $value)
{
$subjid = Alib::GetSessUserId($sessid);
if (PEAR::isError($subjid)) {
return $subjid;
}
if (is_null($subjid)) {
return PEAR::raiseError("Prefs::savePref: invalid session id", GBERR_SESS);
}
$r = $this->update($subjid, $key, $value);
if (PEAR::isError($r)) {
return $r;
}
if ($r === FALSE) {
$r = $this->insert($subjid, $key, $value);
if (PEAR::isError($r)) {
return $r;
}
}
return TRUE;
}
/**
* Delete preference record by session id
*
* @param string $sessid
* session id
* @param string $key
* preference key
* @return boolean
*/
function delPref($sessid, $key)
{
$subjid = Alib::GetSessUserId($sessid);
if (PEAR::isError($subjid)) {
return $subjid;
}
if (is_null($subjid)) {
return PEAR::raiseError("Prefs::delPref: invalid session id", GBERR_SESS);
}
$r = $this->delete($subjid, $key);
if (PEAR::isError($r)) {
return $r;
}
if ($r === FALSE) {
return PEAR::raiseError("Prefs::delPref: invalid preference key", GBERR_PREF);
}
return TRUE;
}
/* ---------------------------------------------------- group preferences */
/**
* Read group preference record
*
* @param string $group
* group name
* @param string $key
* preference key
* @param boolean $returnErrorIfKeyNotExists
* If set to true and the key doesnt exist, return a PEAR error.
* @return string
* preference value
*/
function loadGroupPref($group, $key, $returnErrorIfKeyNotExists = true)
{
// if sessid is would be used here fix Transport::cronCallMethod !
$subjid = Application_Model_Subjects::GetSubjId($group);
if (PEAR::isError($subjid)) {
return $subjid;
}
if (is_null($subjid)) {
return PEAR::raiseError(
"Prefs::loadGroupPref: invalid group name", ALIBERR_NOTGR);
}
$val = $this->readVal($subjid, $key);
if (PEAR::isError($val)) {
return $val;
}
if ($val === FALSE) {
if ($returnErrorIfKeyNotExists) {
return PEAR::raiseError(
"Prefs::loadGroupPref: invalid preference key", GBERR_PREF);
} else {
return '';
}
}
return $val;
}
/**
* Save group preference record
*
* @param string $sessid
* session id
* @param string $group
* group name
* @param string $key
* preference key
* @param string $value
* preference value
* @return boolean
*/
function saveGroupPref($sessid, $group, $key, $value)
{
$uid = Alib::GetSessUserId($sessid);
if (PEAR::isError($uid)) {
return $uid;
}
if (is_null($uid)) {
return PEAR::raiseError(
"Prefs::saveGroupPref: invalid session id", GBERR_SESS);
}
$gid = Application_Model_Subjects::GetSubjId($group);
if (PEAR::isError($gid)) {
return $gid;
}
if (is_null($gid)) {
return PEAR::raiseError(
"Prefs::saveGroupPref: invalid group name", GBERR_SESS);
}
$memb = Application_Model_Subjects::IsMemberOf($uid, $gid);
if (PEAR::isError($memb)) {
return $memb;
}
if (!$memb) {
return PEAR::raiseError(
"Prefs::saveGroupPref: access denied", GBERR_DENY);
}
$r = $this->update($gid, $key, $value);
if (PEAR::isError($r)) {
return $r;
}
if ($r === FALSE) {
$r = $this->insert($gid, $key, $value);
if (PEAR::isError($r)) {
return $r;
}
}
return TRUE;
}
/**
* Delete group preference record
*
* @param string $sessid
* session id
* @param string $group
* group name
* @param string $key
* preference key
* @return boolean
*/
function delGroupPref($sessid, $group, $key)
{
$uid = Alib::GetSessUserId($sessid);
if (PEAR::isError($uid)) {
return $uid;
}
if (is_null($uid)) {
return PEAR::raiseError(
"Prefs::delGroupPref: invalid session id", GBERR_SESS);
}
$gid = Application_Model_Subjects::GetSubjId($group);
if (PEAR::isError($gid)) {
return $gid;
}
if (is_null($gid)) {
return PEAR::raiseError(
"Prefs::delGroupPref: invalid group name", GBERR_SESS);
}
$memb = Application_Model_Subjects::IsMemberOf($uid, $gid);
if (PEAR::isError($memb)) {
return $memb;
}
if (!$memb) {
return PEAR::raiseError(
"Prefs::delGroupPref: access denied", GBERR_DENY);
}
$r = $this->delete($gid, $key);
if (PEAR::isError($r)) {
return $r;
}
if ($r === FALSE) {
return PEAR::raiseError(
"Prefs::delGroupPref: invalid preference key", GBERR_PREF);
}
return TRUE;
}
/* ==================================================== low level methods */
/**
* Insert of new preference record
*
* @param int $subjid
* local user/group id
* @param string $keystr
* preference key
* @param string $valstr
* preference value
* @return int
* local user id
*/
public static function Insert($subjid, $keystr, $valstr='')
{
global $CC_CONFIG, $CC_DBC;
$id = $CC_DBC->nextId($CC_CONFIG['prefSequence']);
if (PEAR::isError($id)) {
return $id;
}
$r = $CC_DBC->query("
INSERT INTO ".$CC_CONFIG['prefTable']."
(id, subjid, keystr, valstr)
VALUES
($id, $subjid, '$keystr', '$valstr')
");
if (PEAR::isError($r)) {
return $r;
}
return $id;
}
/**
* Read value of preference record
*
* @param int $subjid
* local user/group id
* @param string $keystr
* preference key
* @return string
* preference value
*/
function readVal($subjid, $keystr)
{
global $CC_CONFIG, $CC_DBC;
$val = $CC_DBC->getOne("
SELECT valstr FROM ".$CC_CONFIG['prefTable']."
WHERE subjid=$subjid AND keystr='$keystr'
");
if (PEAR::isError($val)) {
return $val;
}
if (is_null($val)) {
return FALSE;
}
return $val;
}
/**
* Read all keys of subject's preferences
*
* @param int $subjid
* local user/group id
* @return array
* preference keys
*/
function readKeys($subjid)
{
global $CC_CONFIG, $CC_DBC;
$res = $CC_DBC->getAll("
SELECT keystr FROM ".$CC_CONFIG['prefTable']."
WHERE subjid=$subjid
");
if (PEAR::isError($res)) {
return $res;
}
if (is_null($res)) {
return FALSE;
}
return $res;
}
/**
* Update value of preference record
*
* @param int $subjid
* local user/group id
* @param string $keystr
* preference key
* @param string $newvalstr
* new preference value
* @return boolean
*/
function update($subjid, $keystr, $newvalstr='')
{
global $CC_CONFIG, $CC_DBC;
$r = $CC_DBC->query("
UPDATE ".$CC_CONFIG['prefTable']." SET
valstr='$newvalstr'
WHERE subjid=$subjid AND keystr='$keystr'
");
if (PEAR::isError($r)) {
return $r;
}
if ($CC_DBC->affectedRows() < 1) {
return FALSE;
}
return TRUE;
}
/**
* Delete preference record
*
* @param int $subjid
* local user/group id
* @param string $keystr
* preference key
* @return boolean
*/
function delete($subjid, $keystr)
{
global $CC_CONFIG, $CC_DBC;
$r = $CC_DBC->query("
DELETE FROM ".$CC_CONFIG['prefTable']."
WHERE subjid=$subjid AND keystr='$keystr'
");
if (PEAR::isError($r)) {
return $r;
}
if ($CC_DBC->affectedRows() < 1) {
return FALSE;
}
return TRUE;
}
} // class Prefs

View file

@ -1,398 +0,0 @@
<?php
/**
* @package Airtime
* @subpackage StorageServer
*/
require_once "XML/Util.php";
/* ================================================================== Element */
/**
* Object representation of one XML element
*
* @package Airtime
* @subpackage StorageServer
* @copyright 2010 Sourcefabric O.P.S.
* @license http://www.gnu.org/licenses/gpl.txt
* @see MetaData
*/
class XmlElement {
/**
* Namespace prefix
* @var string
*/
public $ns;
/**
* Element name
* @var string
*/
public $name;
/**
* Attributes
* @var array
*/
public $attrs = array();
/**
* Namespace definitions
* @var array
*/
public $nSpaces = array();
/**
* Child nodes
* @var array
*/
public $children = array();
/**
* Text content of element
* @var string
*/
public $content = '';
/**
* @param string $fullname
* Fully qualified name of element
* @param array $attrs
* hash of attributes
* @param array $nSpaces
* hash of namespace definitions
* @param array $children
* hash of child nodes
*/
public function __construct($fullname, $attrs, $nSpaces=array(), $children=array())
{
$a = XML_Util::splitQualifiedName($fullname);
$this->ns = $a['namespace'];
$this->name = $a['localPart'];
$this->attrs = $attrs;
$this->nSpaces = $nSpaces;
$this->children = $children;
}
} // class XmlElement
/* ================================================================ Attribute */
/**
* Object representation of one XML attribute
*
* @package Airtime
* @subpackage StorageServer
* @copyright 2010 Sourcefabric O.P.S.
* @license http://www.gnu.org/licenses/gpl.txt
* @see MetaData
*/
class XmlAttrib {
/**
* Namespace prefix
* @var string
*/
public $ns;
/**
* Attribute name
* @var string
*/
public $name;
/**
* Attribute value
* @var string
*/
public $val;
/**
* @param string $atns
* namespace prefix
* @param string $atnm
* attribute name
* @param string $atv
* attribute value
*/
public function __construct($atns, $atnm, $atv)
{
$this->ns = $atns;
$this->name = $atnm;
$this->val = $atv;
}
} // fn XmlAttrib
/* =================================================================== Parser */
/**
* XML parser object encapsulation
*
* @package Airtime
* @subpackage StorageServer
* @copyright 2010 Sourcefabric O.P.S.
* @license http://www.gnu.org/licenses/gpl.txt
* @see MetaData
*/
class XmlParser {
/**
* Tree of nodes
* @var array
*/
private $tree = NULL;
/**
* Parse stack
* @var array
*/
private $stack = array();
/**
* Error structure
* @var array
*/
private $err = array(FALSE, '');
/**
* @param string $data
* XML string to be parsed
*/
public function __construct($data){
$xml_parser = xml_parser_create('UTF-8');
xml_parser_set_option($xml_parser, XML_OPTION_CASE_FOLDING, FALSE);
xml_set_object($xml_parser, $this);
xml_set_element_handler($xml_parser, "startTag", "endTag");
xml_set_character_data_handler($xml_parser, 'characterData');
$res = xml_parse($xml_parser, $data, TRUE);
if (!$res) {
$this->err = array(TRUE,
sprintf("XML error: %s at line %d\n",
xml_error_string(xml_get_error_code($xml_parser)),
xml_get_current_line_number($xml_parser)
)
);
// var_dump($data);
}
xml_parser_free($xml_parser);
}
/**
* Parse XML file or string
*
* @param string $data
* local path to XML file or XML string
* @param string $loc
* location: 'file'|'string'
* @return array
* reference, parse result tree (or PEAR::error)
*/
function &parse($data='', $loc='file')
{
switch ($loc) {
case "file":
if (!is_file($data)) {
return PEAR::raiseError(
"XmlParser::parse: file not found ($data)"
);
}
if (!is_readable($data)) {
return PEAR::raiseError(
"XmlParser::parse: can't read file ($data)"
);
}
$data = file_get_contents($data);
case "string":
$parser = new XmlParser($data);
if ($parser->isError()) {
return PEAR::raiseError(
"XmlParser::parse: ".$parser->getError()
);
}
$tree = $parser->getTree();
break;
default:
return PEAR::raiseError(
"XmlParser::parse: unsupported source location ($loc)"
);
}
return $tree;
}
/**
* Start tag handler
*
* @param resource $parser
* reference to parser resource
* @param string $fullname
* element name
* @param array $attrs
* array of attributes
* @return none
*/
function startTag($parser, $fullname, $attrs) {
$nSpaces = array();
foreach ($attrs as $atn => $atv) {
$a = XML_Util::splitQualifiedName($atn);
$atns = $a['namespace'];
$atnm = $a['localPart'];
unset($attrs[$atn]);
if ($atns == 'xmlns') {
$nSpaces[$atnm] = $atv;
} else if ($atns == NULL && $atnm == 'xmlns') {
$nSpaces[''] = $atv;
} else {
$attrs[$atn] = new XmlAttrib($atns, $atnm, $atv);
}
}
$el = new XmlElement($fullname, $attrs, $nSpaces);
array_push($this->stack, $el);
}
/**
* End tag handler
*
* @param resource $parser
* reference to parser resource
* @param string $fullname
* element name
* @return none
*/
function endTag($parser, $fullname) {
$cnt = count($this->stack);
if ($cnt > 1) {
$this->stack[$cnt-2]->children[] = $this->stack[$cnt-1];
$lastEl = array_pop($this->stack);
} else {
$this->tree = $this->stack[0];
}
}
/**
* Character data handler
*
* @param resource $parser
* reference to parser resource
* @param string $data
* @return none
*/
function characterData($parser, $data) {
$cnt = count($this->stack);
if (trim($data)!='') {
$this->stack[$cnt-1]->content .= $data;
}
}
/**
* Default handler
*
* @param resource $parser
* reference to parser resource
* @param string $data
* @return none
*/
function defaultHandler($parser, $data)
{
$cnt = count($this->stack);
//if(substr($data, 0, 1) == "&" && substr($data, -1, 1) == ";"){
// $this->stack[$cnt-1]->content .= trim($data);
//}else{
$this->stack[$cnt-1]->content .= "*** $data ***";
//}
}
/**
* Return result tree
*
* @return array
* tree structure
*/
function getTree()
{
return $this->tree;
}
/**
* Return error string
*
* @return boolean
* whether error occured
*/
function isError()
{
return $this->err[0];
}
/**
* Return error string
*
* @return string
* error message
*/
function getError()
{
return $this->err[1];
}
/* ----------------------------------- auxiliary methos for serialization */
/**
* Serialize metadata of one file
*
* @return string, serialized XML
*/
function serialize()
{
$res = '<?xml version="1.0" encoding="utf-8"?>';
$res .= $this->serializeEl($this->tree);
$res .= "\n";
return $res;
}
/**
* Serialize one metadata element
*
* @param el object, element object
* @param lvl int, level for indentation
* @return string, serialized XML
*/
function serializeEl($el, $lvl=0)
{
$ind = str_repeat(" ", $lvl);
$elNs = $el->ns;
$elName = $el->name;
$attrs = XML_Util::attributesToString($el->attrs);
$fullName = ($elNs=='' ? '' : "$elNs:")."$elName";
$res = "\n{$ind}<{$fullName}{$attrs}>";
$haveCh = (count($el->children)>0);
foreach ($el->children as $ch) {
$res .= $this->serializeEl($ch, $lvl+1);
}
$res .= XML_Util::replaceEntities("{$el->content}");
if ($haveCh) {
$res .= "\n{$ind}";
}
$res .= "</{$fullName}>";
return $res;
}
/* -------------------------------------------------------- debug methods */
/**
* Debug dump of tree
*
* @return hash, tree structure
*/
function dump()
{
var_dump($this->tree);
}
}

View file

@ -1,136 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE options [
<!ELEMENT options (option*) >
<!ELEMENT option (label+) >
<!ELEMENT label (#PCDATA) >
<!ATTLIST option id CDATA #REQUIRED >
<!ATTLIST label xml:lang CDATA #IMPLIED >
]>
<options>
<option id="Blues"><label>Blues</label></option>
<option id="Classic Rock"><label>Classic Rock</label></option>
<option id="Country"><label>Country</label></option>
<option id="Dance"><label>Dance</label></option>
<option id="Disco"><label>Disco</label></option>
<option id="Funk"><label>Funk</label></option>
<option id="Grunge"><label>Grunge</label></option>
<option id="Hip-Hop"><label>Hip-Hop</label></option>
<option id="Jazz"><label>Jazz</label></option>
<option id="Metal"><label>Metal</label></option>
<option id="New Age"><label>New Age</label></option>
<option id="Oldies"><label>Oldies</label></option>
<option id="Other"><label>Other</label></option>
<option id="Pop"><label>Pop</label></option>
<option id="R&amp;B"><label>R&amp;B</label></option>
<option id="Rap"><label>Rap</label></option>
<option id="Reggae"><label>Reggae</label></option>
<option id="Rock"><label>Rock</label></option>
<option id="Techno"><label>Techno</label></option>
<option id="Industrial"><label>Industrial</label></option>
<option id="Alternative"><label>Alternative</label></option>
<option id="Ska"><label>Ska</label></option>
<option id="Death Metal"><label>Death Metal</label></option>
<option id="Pranks"><label>Pranks</label></option>
<option id="Soundtrack"><label>Soundtrack</label></option>
<option id="Euro-Techno"><label>Euro-Techno</label></option>
<option id="Ambient"><label>Ambient</label></option>
<option id="Trip-Hop"><label>Trip-Hop</label></option>
<option id="Vocal"><label>Vocal</label></option>
<option id="Jazz+Funk"><label>Jazz+Funk</label></option>
<option id="Fusion"><label>Fusion</label></option>
<option id="Trance"><label>Trance</label></option>
<option id="Classical"><label>Classical</label></option>
<option id="Instrumental"><label>Instrumental</label></option>
<option id="Acid"><label>Acid</label></option>
<option id="House"><label>House</label></option>
<option id="Game"><label>Game</label></option>
<option id="Sound Clip"><label>Sound Clip</label></option>
<option id="Gospel"><label>Gospel</label></option>
<option id="Noise"><label>Noise</label></option>
<option id="AlternRock"><label>AlternRock</label></option>
<option id="Bass"><label>Bass</label></option>
<option id="Soul"><label>Soul</label></option>
<option id="Punk"><label>Punk</label></option>
<option id="Space"><label>Space</label></option>
<option id="Meditative"><label>Meditative</label></option>
<option id="Instrumental Pop"><label>Instrumental Pop</label></option>
<option id="Instrumental Rock"><label>Instrumental Rock</label></option>
<option id="Ethnic"><label>Ethnic</label></option>
<option id="Gothic"><label>Gothic</label></option>
<option id="Darkwave"><label>Darkwave</label></option>
<option id="Techno-Industrial"><label>Techno-Industrial</label></option>
<option id="Electronic"><label>Electronic</label></option>
<option id="Pop-Folk"><label>Pop-Folk</label></option>
<option id="Eurodance"><label>Eurodance</label></option>
<option id="Dream"><label>Dream</label></option>
<option id="Southern Rock"><label>Southern Rock</label></option>
<option id="Comedy"><label>Comedy</label></option>
<option id="Cult"><label>Cult</label></option>
<option id="Gangsta"><label>Gangsta</label></option>
<option id="Top 40"><label>Top 40</label></option>
<option id="Christian Rap"><label>Christian Rap</label></option>
<option id="Pop/Funk"><label>Pop/Funk</label></option>
<option id="Jungle"><label>Jungle</label></option>
<option id="Native American"><label>Native American</label></option>
<option id="Cabaret"><label>Cabaret</label></option>
<option id="New Wave"><label>New Wave</label></option>
<option id="Psychadelic"><label>Psychadelic</label></option>
<option id="Rave"><label>Rave</label></option>
<option id="Showtunes"><label>Showtunes</label></option>
<option id="Trailer"><label>Trailer</label></option>
<option id="Lo-Fi"><label>Lo-Fi</label></option>
<option id="Tribal"><label>Tribal</label></option>
<option id="Acid Punk"><label>Acid Punk</label></option>
<option id="Acid Jazz"><label>Acid Jazz</label></option>
<option id="Polka"><label>Polka</label></option>
<option id="Retro"><label>Retro</label></option>
<option id="Musical"><label>Musical</label></option>
<option id="Rock &amp; Roll"><label>Rock &amp; Roll</label></option>
<option id="Hard Rock"><label>Hard Rock</label></option>
<option id="Folk"><label>Folk</label></option>
<option id="Folk-Rock"><label>Folk-Rock</label></option>
<option id="National Folk"><label>National Folk</label></option>
<option id="Swing"><label>Swing</label></option>
<option id="Fast Fusion"><label>Fast Fusion</label></option>
<option id="Bebob"><label>Bebob</label></option>
<option id="Latin"><label>Latin</label></option>
<option id="Revival"><label>Revival</label></option>
<option id="Celtic"><label>Celtic</label></option>
<option id="Bluegrass"><label>Bluegrass</label></option>
<option id="Avantgarde"><label>Avantgarde</label></option>
<option id="Gothic Rock"><label>Gothic Rock</label></option>
<option id="Progressive Rock"><label>Progressive Rock</label></option>
<option id="Psychedelic Rock"><label>Psychedelic Rock</label></option>
<option id="Symphonic Rock"><label>Symphonic Rock</label></option>
<option id="Slow Rock"><label>Slow Rock</label></option>
<option id="Big Band"><label>Big Band</label></option>
<option id="Chorus"><label>Chorus</label></option>
<option id="Easy Listening"><label>Easy Listening</label></option>
<option id="Acoustic"><label>Acoustic</label></option>
<option id="Humour"><label>Humour</label></option>
<option id="Speech"><label>Speech</label></option>
<option id="Chanson"><label>Chanson</label></option>
<option id="Opera"><label>Opera</label></option>
<option id="Chamber Music"><label>Chamber Music</label></option>
<option id="Sonata"><label>Sonata</label></option>
<option id="Symphony"><label>Symphony</label></option>
<option id="Booty Bass"><label>Booty Bass</label></option>
<option id="Primus"><label>Primus</label></option>
<option id="Porn Groove"><label>Porn Groove</label></option>
<option id="Satire"><label>Satire</label></option>
<option id="Slow Jam"><label>Slow Jam</label></option>
<option id="Club"><label>Club</label></option>
<option id="Tango"><label>Tango</label></option>
<option id="Samba"><label>Samba</label></option>
<option id="Folklore"><label>Folklore</label></option>
<option id="Ballad"><label>Ballad</label></option>
<option id="Power Ballad"><label>Power Ballad</label></option>
<option id="Rhythmic Soul"><label>Rhythmic Soul</label></option>
<option id="Freestyle"><label>Freestyle</label></option>
<option id="Duet"><label>Duet</label></option>
<option id="Punk Rock"><label>Punk Rock</label></option>
<option id="Drum Solo"><label>Drum Solo</label></option>
<option id="A capella"><label>A capella</label></option>
<option id="Euro-House"><label>Euro-House</label></option>
<option id="Dance Hall"><label>Dance Hall</label></option>
</options>