From: Ivan H. <iv...@us...> - 2004-05-24 23:03:02
|
Update of /cvsroot/phpwebsite-comm/modules/ras/class In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv12433 Added Files: RasArchiver.php RasBackend.php RasBase.php RasFeedParser.php RasFormManager.php RemoteAppSyndication.php Log Message: Initial create --- NEW FILE: RasBase.php --- <?php /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. */ /** * Remote App Syndication - Ras Base class * * @version 0.0.4 * @author Bruno Desthuilliers <br...@mo...> * * base class to factor out some common helper functions */ class RasBase { /** * @var string $_lastError error message, read it via getLastError() */ var $_lastError = ''; //---------------------------------------------------------------------------- /** * Return the last error message * * @return string the last error message */ function getLastError() { return $this->_lastError . "<br>\n"; } //---------------------------------------------------------------------------- /** * Set the last error and always returns false * * By default, actually prepend the argument to the actuel value of $_lastError. * This method always return FALSE, so you can use it like : * <pre>return $this->setLastError('error message');</pre> * Note that you can alse ignore the return value !-) * * @param string $errMsg the error message * @param boolean $prepend prepend the error instead of replacing (default true) * @return boolean always false */ function setLastError($errMsg, $prepend=true) { if ($prepend) { $this->_lastError = $errMsg . "<br>\n" . $this->_lastError; } else { $this->_lastError = $errMsg; } return false; } } ?> --- NEW FILE: RemoteAppSyndication.php --- <?php /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. */ /** * Remote App Syndication - Main class * * @version 0.0.4 * @author Bruno Desthuilliers <br...@mo...> * * The 'master' class. Handles some logic, and delegate most of the work * * TODO : (pardon my french...) * - traductions * - forms pour les infos manquantes sur les modules et themes * - exports data * - repérer les resources à mettre à jour * - validation des entrées, sécurité etc * - ménage et doc * * - Filtrer les feeds sur appli et version * - régler ce filtre dans les master settings * - créer une interface pour supprimer une archive */ // ----------------------------------------------------------------------------- require_once(PHPWS_SOURCE_DIR . "core/Array.php"); require_once(PHPWS_SOURCE_DIR . "core/Text.php"); require_once(PHPWS_SOURCE_DIR . "mod/boost/class/Boost.php"); require_once(PHPWS_SOURCE_DIR . "mod/ras/class/RasFormManager.php"); // create html forms & content require_once(PHPWS_SOURCE_DIR . "mod/ras/class/RasArchiver.php"); // create and extract tar archives require_once(PHPWS_SOURCE_DIR . "mod/ras/class/RasFeedParser.php"); // parse XML Ras Feeds from channels require_once(PHPWS_SOURCE_DIR . "mod/ras/class/RasBackend.php"); // generate XML ras feeds // ----------------------------------------------------------------------------- class PHPWS_RemoteAppSyndication { // --------------------------------------------------------------------------- function PHPWS_RemoteAppSyndication() { $this->_initSettings(); /* create the forms etc */ $this->formManager =& new RasFormManager; /* import and export resources */ $this->archiver =& new RasArchiver; } // HELPERS ------------------------------------------------------------------- // --------------------------------------------------------------------------- /** * return a timestamp formated as a "Y-m-d H:i:s" datetime * * just an helper fun, can be call as a class method. If the * timestamp parameter is null, should use the current timestamp (not tested !) * * @param integer $timestamp the timestamp to format or null * @return string the formatted timestamp */ function timestampToDatetime($timestamp=null) { return date("Y-m-d H:i:s", $timestamp); } // --------------------------------------------------------------------------- /** * returns the modification time of the most recently modified file in the given path * * just an helper fun, can be call as a class method. * * @param string $path the path to explore * @return integer timestamp of the most recently modified file in the path */ function lastmtime($path) { $files = PHPWS_File::readDirectory($path, FALSE, TRUE, TRUE, NULL, TRUE); $lastmod = -1; foreach($files as $file) { $fmtime = filemtime($file); if ($fmtime > $lastmod) { $lastmod = $fmtime; } } return $lastmod; } // --------------------------------------------------------------------------- function error($msg, $opBack) { $GLOBALS['CNT_ras']['content'] = $this->formManager->formInfo($_SESSION['translate']->it("Error"), $msg, $opBack); return false; } // --------------------------------------------------------------------------- function info($msg, $opBack) { $GLOBALS['CNT_ras']['content'] = $this->formManager->formInfo($_SESSION['translate']->it("Done"), $msg, $opBack); return true; } // SETTINGS -------------------------------------------------------------------- // --------------------------------------------------------------------------- /** * display the 'edit settings' form. */ function editsettings() { $this->_initSettings(); $GLOBALS['CNT_ras']['content'] = $this->formManager->formSettings($this->settings); } // --------------------------------------------------------------------------- /** * Update the settings and save them * * Callback for the 'edit settings' form. */ function updatemastersettings() { if (isset($_POST['ras_update_settings'])) { $this->_initSettings(); /* TODO sanity check */ if (isset($_POST['ras_ismaster'])) { $this->_settings['is_master'] = $_POST['ras_ismaster']; } if (isset($_POST['ras_anonymous'])) { $this->_settings['accept_anonymous'] = $_POST['ras_ismaster']; } if (! $this->_saveSettings()) { /* _saveSettings sets the error */ return; } } if (isset($_POST['ras_from']) && method_exists($this, $_POST['ras_from'])) { $this->$_POST['ras_from'](); } else { $this->viewfeeds(); } } // --------------------------------------------------------------------------- /** * Pretty obvious... * TODO : check for error when accessing db */ function _initSettings() { $this->_settings = $GLOBALS['core']->sqlSelect('mod_ras_settings'); $this->_settings = $this->_settings[0]; return true; } // --------------------------------------------------------------------------- /** * Pretty obvious too... */ function _saveSettings() { if ($GLOBALS['core']->sqlUpdate($this->_settings, 'mod_ras_settings')) { return $this->_initSettings(); } else { /* TODO : check why we failed */ return $this->error($_SESSION['translate']->it("Could not save settings")); } } // PUBLISH -------------------------------------------------------------------- // --------------------------------------------------------------------------- /** * display the 'view resources' form */ function viewresources() { $GLOBALS['CNT_ras']['content'] = $this->formManager->formResourceList(); } // --------------------------------------------------------------------------- /** * try to 'export' a module resource (code, lang or data) */ function exportmodule() { if (isset($_POST['ras_export_module'])) { $itemType = 'code'; list($item) = each($_POST['ras_export_module']); } elseif (isset($_POST['ras_export_lang'])) { $itemType = 'lang'; list($item) = each($_POST['ras_export_lang']); } elseif (isset($_POST['ras_export_data'])) { $itemType = 'data'; list($item) = each($_POST['ras_export_data']); /* TODO */ return $this->error($_SESSION['translate']->it("Data export not yet implemented"), 'viewresources'); } else { return $this->error($_SESSION['translate']->it("Unknown export type"), 'viewresources'); } if ($this->archiver->exportModule($item, $itemType)) { return $this->info($_SESSION['translate']->it("Module succesfully exported : ") . "$item<br>\n", 'viewresources'); } else { return $this->error($_SESSION['translate']->it("Could not export module : ") . " $item :" . $this->archiver->getLastError(), 'viewresources'); } } // --------------------------------------------------------------------------- /** * try to 'export' a theme resource (code, lang or data) * Not yet implemented */ function exporttheme() { //echo "export theme called"; //return $this->error("TEST :<br> " . PHPWS_Array::testRequest() . "<br>" . PHPWS_Array::testPost()) ; if (isset($_POST['ras_export_tpl'])) { $itemType = 'tpl'; list($item) = each($_POST['ras_export_tpl']); } elseif (isset($_POST['ras_export_img'])) { $itemType = 'img'; list($item) = each($_POST['ras_export_img']); } else { return $this->error($_SESSION['translate']->it("Unknown export type"), 'viewresources'); } //echo "we are here : item = '$item', type = '$itemType'"; if ($this->archiver->exportTheme($item, $itemType)) { return $this->info($_SESSION['translate']->it("Theme succesfully exported : ") . "$item", 'viewresources'); } else { return $this->error($_SESSION['translate']->it("Could not export theme : ") . "$item<br>\n" . $this->archiver->getLastError(), 'viewresources'); } } // FEEDS ----------------------------------------------------------------------- // --------------------------------------------------------------------------- /** * display the 'view resources' form (some more useless doc ?) */ function viewfeeds() { $this->_initSettings(); /* check if we have any channel, else say so */ $channels = unserialize($this->_settings['channels']); if (! is_array($channels)) { return $this->error($_SESSION['translate']->it("No channels found, please check your settings"), 'createchannel'); } /* ok, proceed */ $GLOBALS['CNT_ras']['content'] = $this->formManager->formFeedList($channels); } // --------------------------------------------------------------------------- /** * display a 'confirm' message when asked to import a resource */ function checkimport() { $caption = $_SESSION['translate']->it("Please confirm"); $msg = $_SESSION['translate']->it("Download and install resource:") . "<br>\n" . $_REQUEST['ras_itm_url'] . "<br>"; $kwargs['ras_itm_url'] = $_REQUEST['ras_itm_url']; $kwargs['ras_res_type'] = $_REQUEST['ras_res_type']; $GLOBALS['CNT_ras']['content'] = $this->formManager->formConfirm($caption, $msg, 'import', $kwargs, 'viewfeeds'); } // --------------------------------------------------------------------------- /** * try to import a resource * does not work yet */ function import() { if (! isset($_REQUEST['ras_itm_url'])) { return $this->error( $_SESSION['translate']->it("Internal error : url not set"), 'viewfeeds'); } if (! isset($_REQUEST['ras_res_type'])) { return $this->error( $_SESSION['translate']->it("Internal error : resource type not set"), 'viewfeeds'); } /* TODO sanity check */ $url = $_REQUEST['ras_itm_url']; $type = $_REQUEST['ras_res_type']; if ($this->archiver->import($url, $type)) { $msg = $_SESSION['translate']->it("Resource imported : ") . "$url<br>\n"; if (strcmp($type, 'module') == 0) { $msg .= $_SESSION['translate']->it("You may want to update with boost") . "<br>\n"; } return $this->info($msg, 'viewfeeds'); } else { $msg = $_SESSION['translate']->it("Import of resource failed : ") . "$url<br>\n"; $msg .= $this->archiver->getLastError(); return $this->error($msg, 'viewfeeds'); } } // BACKEND --------------------------------------------------------------------- // --------------------------------------------------------------------------- /** * Call back for clients asking to view Ras Feeds */ function createRasFeed() { $backend =& new RasBackend(); return $backend->createFeed(); } // CHANNEL ---------------------------------------------------------------------- // --------------------------------------------------------------------------- /** * display the 'edit channel' form in creation mode */ function createchannel() { $GLOBALS['CNT_ras']['content'] = $this->formManager->formChannel(); } // --------------------------------------------------------------------------- /** * display the 'edit channel' form in edit mode */ function editchannel() { /* TODO factor this out */ $this->_initSettings(); $channels = unserialize($this->_settings['channels']); if (! isset($_REQUEST['ras_chan_id'])) { /* TODO */ return $this->error($_SESSION['translate']->it("no channel id to edit")); } $channelId = $_REQUEST['ras_chan_id']; if (! isset($channels[$channelId])) { /* TODO */ return $this->error( $_SESSION['translate']->it("channel not found : $channelId")); } $channelData = $channels[$channelId]; $GLOBALS['CNT_ras']['content'] = $this->formManager->formChannel($channelId, $channelData); } // --------------------------------------------------------------------------- /** * display a 'confirm' message when asked to delete a channel */ function checkdeletechannel() { $channelName = $_REQUEST['ras_chan_id']; $msg = "Delete channel " . $channelName . "?"; $kwargs = Array('ras_chan_id'=>$channelName); $GLOBALS['CNT_ras']["content"] = $this->formManager->formConfirm("Confirm", $msg, 'deletechannel', $kwargs, 'viewfeeds'); } // --------------------------------------------------------------------------- /** * save channel settings */ function updatechannel() { if (isset($_POST['ras_chan_ok'])) { /* TODO factor this out */ $this->_initSettings(); $channels = unserialize($this->_settings['channels']); $msg = ''; $channelId = PHPWS_Text::parseInput($_POST['ras_chan_id']); $channelName = PHPWS_Text::parseInput($_POST['ras_chan_name']); $channelUrl = PHPWS_Text::parseInput($_POST['ras_chan_url']); $channelActive = PHPWS_Text::parseInput($_POST['ras_chan_active']); $channelNew = PHPWS_Text::parseInput($_POST['ras_chan_new']); /* TODO : sanity check values*/ if ($channelId == null || strlen($channelId) == 0) { $channelId = $channelName; } if ($channelName == null || strlen($channelName) == 0) { /* TODO resend other data to editchannel form ?*/ return $this->error( $_SESSION['translate']->it("No channel name !"), 'viewfeeds'); } /* ok, let's proceed */ $channels[$channelId] = Array('name'=>$channelName, 'url'=>$channelUrl, 'active'=>$channelActive); $this->_settings['channels'] = serialize($channels); if (! $this->_saveSettings()) { /* _saveSettings sets the error */ return; }; } // Go back to channels & feeds list $this->viewfeeds(); } // --------------------------------------------------------------------------- /** * remove a channel from the settings */ function deletechannel() { $this->_initSettings(); $channels = unserialize($this->_settings['channels']); $channelId = $_REQUEST['ras_chan_id']; if (isset($channels[$channelId])) { unset($channels[$channelId]); $this->_settings['channels'] = $channels; if (!$this->_saveSettings()) { /* _saveSettings sets the error */ return; } } // Go back to channels & feeds list $this->viewfeeds(); } } ?> --- NEW FILE: RasArchiver.php --- <?php /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. */ /** * Remote App Syndication - Archiver * * @version 0.0.4 * @author Bruno Desthuilliers <br...@mo...> * * Handle resources export and import * On export, get the appropriate files, create the archive, and update the * DB tables used to generate ras-feed. * On import, retrieve the archive and expand it locally. * Tar creation is delegated to PEAR/Archive_Tar * * TODO : * - module data * - form for resource and items missing infos ? * - refactor exportTheme and exportModule, too much duplicated code */ //- includes ------------------------------------------------------------------- require_once PHPWS_SOURCE_DIR . 'lib/pear/Archive/Tar.php'; require_once PHPWS_SOURCE_DIR . 'mod/ras/class/RasBase.php'; //- Globals && CONST ----------------------------------------------------------- define('PHPWS_RAS_EXPORTDIR', PHPWS_SOURCE_DIR . 'files/ras/resources/'); define('PHPWS_RAS_IMPORTDIR', PHPWS_SOURCE_DIR . 'files/ras/imports/'); //- RasArchiver ---------------------------------------------------------------- class RasArchiver extends RasBase { //---------------------------------------------------------------------------- /** * callback function for PEAR errors (used by PEAR/Archive_Tar) * * @param mixed $errObject PEAR_Error object or string */ function onError($errObject) { if (PEAR::isError($errObject)) { $this->setLastError($errObject->getMessage()); } elseif (is_string($errObject)) { $this->setLastError($errObject); } } //- MASTER --------------------------------------------------------------------- /** * TODO : export data, separate langs... */ function exportModule($modTitle, $exportType) { $this->setLastError('', false, false); /* get directory etc */ if (! $moduleInfo = $GLOBALS["core"]->getModuleInfo($modTitle)) { return $this->setLastError($_SESSION["translate"]->it("Could not get module infos for module: ") . $modTitle); } $basepath = PHPWS_SOURCE_DIR . "mod/"; $srcDir = $basepath . $moduleInfo['mod_directory'] . '/'; /* get module version * format : Array ( [mod_title] => boost [version] => 1.5.2 [update_link] => [branch_allow] => 1 ) */ $versionInfo = PHPWS_boost::getVersionInfo($modTitle); if (! $versionInfo) { return $this->setLastError($_SESSION["translate"]->it("could not get version info for module : ") . $modTitle); } /* create the archive */ switch ($exportType) { case 'code': $files = PHPWS_File::readDirectory($srcDir, TRUE, FALSE, FALSE, null, TRUE); $files = array_flip($files); /* We don't want the langs here */ unset($files[$srcDir . 'lang']); $files = array_flip($files); break; case 'lang': $files = $srcDir . 'lang'; break; case 'data': $ok = $this->_exportData($modTitle, $versionInfo, $srcDir); break; default: return $this->setLastError($_SESSION["translate"]->it("Unknown module export type : ") . $exportType); break; } $timestamp = time(); $tarName = $modTitle . '-' . $versionInfo[version] . '-' . $timestamp . '-' . $exportType . '.tar.gz'; if (! $this->_makeArchive($tarName, $files, $basepath)) { return $this->setLastError($_SESSION["translate"]->it("Could not create archive for module : ") . $modTitle); } /* store the RAS feed infos in the db * TODO : une form pour saisir les infos manuqantes dans resource et item */ $feedData = Array('itm_version'=>$versionInfo[version], 'itm_type'=>$exportType, 'itm_url'=> "http://" . $_SERVER['HTTP_HOST'] . dirname($_SERVER['PHP_SELF']) . "/files/ras/resources/" . $tarName, 'itm_date'=> PHPWS_RemoteAppSyndication::timestampToDatetime($timestamp), 'itm_lang'=> '', 'itm_changes'=> "no se", 'itm_md5'=> '' /* TODO md5 sum of the tarball */ ); $backend =& new RasBackend; if (! $backend->storeFeed('module', $modTitle, $feedData)) { return $this->setLastError($_SESSION["translate"]->it("Could not create feed for module : ") . $mod_title . "<br>" . $backend->getLastError()); } return true; } //---------------------------------------------------------------------------- /** * TODO : not yet implemented */ function _exportData($modTitle, $versionInfo, $srcDir) { return $this->setLastError($_SESSION["translate"]->it("Module data export not yet implemented")); } //---------------------------------------------------------------------------- /** * Try and export a theme * * first problem : there is no standard image directory. * most store images in themename/image/, some in themename/img, * and some anywhere else. * So we try the first two solutions, and fail else * * second problem : we have no version info for themes. * Note for the Theme developpers : add a VERSION file with only the version number * in your theme dir, else you will get bogus version number */ function exportTheme($themeName, $itemType) { //return $this->setLastError("NIY YOU DUMMY"); $basepath = PHPWS_SOURCE_DIR . 'themes/'; $srcDir = $basepath . $themeName .'/'; switch ($itemType) { case 'tpl': $files = PHPWS_File::readDirectory($srcDir, TRUE, FALSE, FALSE, null, TRUE); $files = array_flip($files); /* we don't want images here */ unset($files[$srcDir . 'images']); unset($files[$srcDir . 'image']); unset($files[$srcDir . 'img']); $files = array_flip($files); //echo "tpl : <br>" . PHPWS_Array::testArray($files); break; case 'img': if (file_exists($srcDir . 'images') && is_dir($srcDir . 'images')) { $files = $srcDir . 'images'; } elseif (file_exists($srcDir . 'image') && is_dir($srcDir . 'image')) { $files = $srcDir . 'image'; } elseif (file_exists($srcDir . 'img') && is_dir($srcDir . 'img')) { $files = $srcDir . 'img'; } else { return $this->setLastError($_SESSION["translate"]->it("no 'image' or 'images' or 'img' directory found for theme : ") . $item); } break; default: return $this->setLastError($_SESSION["translate"]->it("Unknown theme export type : ") . $itemType); break; } /* version info ? */ if (file_exists($srcDir . "VERSION") && is_file($srcDir . "VERSION")) { $version = @file($srcDir . "VERSION"); if (is_array($version)) { $version = $version[0]; } else { return $this->setLastError($_SESSION["translate"]->it("Invalid theme version info")); } } else { /* bogus version number, you were warned */ /* and YES I KNOW, this may pose problem when inserting feed data in the db */ /* PLEASE add a VERSION file in each theme */ $version = '42'; } $timestamp = time(); $tarName = $themeName . '-' . $version . '-' . $timestamp . '-' . $itemType . '.tar.gz'; if (! $this->_makeArchive($tarName, $files, $basepath)) { return $this->setLastError($_SESSION["translate"]->it("Could not create archive for theme : ") . $themeName); } /* store the RAS feed infos in the db * TODO : une form pour saisir les infos manquantes dans resource et item */ $feedData = Array('itm_version'=>$version, 'itm_type'=>$itemType, 'itm_url'=>$tarName, /* TODO : url complète ? sinon renommer en itm_tar_name */ 'itm_date'=> PHPWS_RemoteAppSyndication::timestampToDatetime($timestamp), 'itm_lang'=> '', 'itm_changes'=> "no se", 'itm_md5'=> '' /* TODO md5 sum of the tarball */ ); $backend =& new RasBackend; if (! $backend->storeFeed('theme', $themeName, $feedData)) { return $this->setLastError($_SESSION["translate"]->it("Could not create feed for theme : ") . $themeName . "<br>\n" . $backend->getLastError()); } return true; } //---------------------------------------------------------------------------- /** * Create the tar archive * * @param string $tarName the name of the arhive * @param mixed $files path or array of paththe name of the archive * @param string $removedir path to remove from archived files * @return boolean guess what ?-) */ function _makeArchive($tarName, $files, $removedir) { $tar =& new Archive_Tar(PHPWS_RAS_EXPORTDIR . $tarName, true); $tar->setErrorHandling(PEAR_ERROR_CALLBACK, Array(&$this, 'onError')); return $tar->createModify($files, '', $removedir); } //- CLIENT -------------------------------------------------------------------- /** * Download an archive from a master site and try to expand it in the right place * * TODO : this function is Q&D and actually doesnt works * (can't expand the archive, wrong user/group) * * @params string $url the url of the archive to download * @param string $type the type of resource ('module' or 'theme') * @return boolean guess what ? */ function import($url, $type) { $this->setLastError('', false, false); // Q&D, to be redone cleanly with parse_url and pathinfo or likes ? $dest = explode("/", $url); $dest = array_pop($dest); $dest = PHPWS_RAS_IMPORTDIR . $dest; if (file_exists($dest)) { return $this->setLastError($_SESSION["translate"]->it("Destination file already exists : ") . $dest); } if (! copy($url, $dest)) { return $this->setLastError($_SESSION["translate"]->it("Copy of remote file failed")); } /* TODO : * - check if is code, lang or whatever, or a theme, etc */ // MARCHE PAS pour le moment... // probleme de droits $tar = new Archive_Tar($dest); $tar->setErrorHandling(PEAR_ERROR_CALLBACK, Array(&$this, 'onError')); switch ($type) { case 'module': $basepath = PHPWS_SOURCE_DIR . 'mod/'; break; case 'theme': $basepath = PHPWS_SOURCE_DIR . 'themes/'; break; default: /* TODO */ return $ths->setLastError($_SESSION['translate']->it("unknown resource type : ") . $type); break; } if ( ! $tar->extract($basepath) ) { return $this->setLastError($_SESSION['translate']->it("Error while extracting archive, just pray that your PhpWebiste install is still working...")); } return true; } } ?> --- NEW FILE: RasFeedParser.php --- <?php /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. */ /** * Remote App Syndication - Ras Feed Parser * * @version 0.0.4 * @author Bruno Desthuilliers <br...@mo...> * * Read and Parse a ras-feed (SAX parser) */ /* internal doc : * source XML exemple : <ras-feed> <application name='phpwebsite' version='0.9.3.2'> <resource type='module' name='NomModule'> <description>Description du module</description> <item type='code'> <version>0.0.1</version> <date>AAMMJJhhmm</date> <url>http://www.modulix.org/somewhere/nommodule-0.0.1-code.tgz</url> <changes>Changements depuis la dernière version</changes> </item> <item type='code'> <version>0.0.0</version> <date>AAMMJJhhmm</date> <url>http://www.modulix.org/somewhere/nommodule-0.0.0-code.tgz</url> <changes>Changements depuis la dernière version</changes> </item> <item type='lang'> <lang>fr</lang> <version>0.0.0</version> <date>AAMMJJhhmm</date> <url>http://www.modulix.org/somewhere/nommodule-fr.AA.MM.JJ.HH-lang.tgz</url> <changes>Changements depuis la dernière version</changes> </item> <item type='data'> <version>0.0.0</version> <date>AAMMJJhhmm</date> <url>http://www.modulix.org/somewhere/nommodule-AA.MM.JJ.HH-data.tgz</url> <changes>Changements depuis la dernière version</changes> </item> </resource> <resource type='theme' name='nomTheme'> <description>Description du thème</description> <item type='templates'> <version>>AAMMJJHH</version> <date>AAMMJJhhmm</date> <url>http://www.modulix.org/somewhere/nomtheme-AA.MM.JJ.HH-tpl.tgz</url> <changes>Changements depuis la dernière version</changes> </item> <item type='images'> <version>>AAMMJJHH</version> <date>AAMMJJhhmm</date> <url>http://www.modulix.org/somewhere/nomtheme-AA.MM.JJ.HH-img.tgz</url> <changes>Changements depuis la dernière version</changes> </item> </resource> </application> </ras-feed> * * result exemple : [ [app_name=>name, app_version=>version, app_resources=> [resource_name=>name, resource_type=>type, resource_desc=>description, resource_items=> [item_type=>type, item_version=>version, item_date=>date, item_lang=>lang, item_changes=>changes, item_url=>url ] ] ] [app_name=>name, app_version=>version, app_resources=> [resource_name=>name, resource_type=>type, resource_desc=>description, resource_items=> [item_type=>type, item_version=>version, item_date=>date, item_lang=>lang, item_changes=>changes, item_url=>url ] ] ] ] */ //------------------------------------------------------------------------------ require_once PHPWS_SOURCE_DIR . 'mod/ras/class/RasBase.php'; //------------------------------------------------------------------------------ class RasFeedParser extends RasBase { // VARS ---------------------------------------------------------------------- /** * @var resource $_parser the SAX parser */ var $_parser = null; /** * @var array $_content stores content while parsing */ var $_content; /** * @var string $_currentApp the current app section */ var $_currentApp; /** * @var $string $_currentResource the current resource section */ var $_currentResource; /** * @var string $_currentItem the current item section */ var $_currentItem; // --------------------------------------------------------------------------- /** * init all resources before parsing */ function _init() { /* parser */ if ($this->_parser != null) { $this->_free(); } $this->_parser = xml_parser_create(); if (! is_resource($this->_parser)) { return $this->setLastError($_SESSION['translate']->it("Could not create the XML SAX Parser")); } xml_parser_set_option($this->_parser, XML_OPTION_CASE_FOLDING, 0); xml_set_object($this->_parser, &$this); xml_set_element_handler($this->_parser, "onTagOpen", "onTagClose"); xml_set_character_data_handler($this->_parser, "onData"); return true; } // --------------------------------------------------------------------------- /** * free the parser resource when done */ function _cleanUp() { if ($this->_parser != null) { xml_parser_free($this->_parser); $this->_parser = null; } } // --------------------------------------------------------------------------- /** * read the ras-feed from the given url and parse it as an array * * @param string $url the url of the channel * @return mixed the parsed content as an array, or FALSE */ function parse($url) { /* init everything */ $this->_lastError = ''; if (! $this->_init()) { return false; } $this->_content = Array(); /* read data from channel's url (well, from any file in fact !-) */ $fp = @fopen($url, 'rb'); if (! $fp) { /* TODO : how to get more info about the error ?*/ $this->_cleanUp(); return $this->setLastError($_SESSION['translate']->it("Could not read channel : ") . $url); } $xmldata = ""; do { $buffer = fread($fp, 8192); if (strlen($buffer) == 0) { break; } $xmldata .= $buffer; } while (true); fclose($fp); /* parse feed */ $ok = xml_parse($this->_parser, $xmldata, true); if (! $ok) { $this->setLastError(xml_error_string(xml_get_error_code($this->_parser))); $this->setLastError($_SESSION['translate']->it("Error while parsing Ras Feed from ") . $url); } $this->_cleanUp(); /* and returns */ if ($ok) { return $this->_content; } else { return false; } } // --------------------------------------------------------------------------- /** * standard element open SAX event handler */ function onTagOpen($parser, $tagName, $attribs) { $this->_currentTag = $tagName; switch($tagName) { case "channel": if (isset($this->_content['chan_name'])) { /* TODO */ //return $this->setLastError("invalid feed : 2 channel tags in the same feed"); $this->setLastError("invalid feed : 2 channel tags in the same feed"); } $this->_content['chan_name'] = $attribs['name']; $this->_content['chan_url'] = $attribs['url']; $this->_content['chan_resources'] = Array(); break; case "application": $this->_currentApp = Array(); $this->_currentApp['app_name'] = $attribs['name']; $this->_currentApp['app_version'] = $attribs['version']; break; case "resource": $this->_currentResource = Array(); $this->_currentResource['res_name'] = $attribs['name']; $this->_currentResource['res_type'] = $attribs['type']; $this->_currentResource['res_desc'] = ''; break; case "item": $this->_currentItem = Array(); $this->_currentItem['item_type'] = $attribs['type']; $this->_currentItem['item_version'] = ''; $this->_currentItem['item_date'] = ''; $this->_currentItem['item_url'] = ''; $this->_currentItem['item_lang'] = ''; $this->_currentItem['item_changes'] = ''; break; } } // --------------------------------------------------------------------------- /** * standard element close SAX event handler */ function onTagClose($parser, $tagName) { switch ($tagName) { case "application": $this->_content['channel_resources'][] = $this->_currentApp; break; case "resource": $this->_currentApp['app_resources'][] = $this->_currentResource; break; case "item": $this->_currentResource['res_items'][] = $this->_currentItem; break; } $this->_currentTag=''; } // --------------------------------------------------------------------------- /** * standard cdata SAX event handler */ function onData($parser, $data) { $data = trim($data); if (strlen($data)) { switch ($this->_currentTag) { case "description": $this->_currentResource['res_desc'] .= $data; break; case "version": $this->_currentItem['item_version'] = $data; break; case "date": $this->_currentItem['item_date'] = $data; break; case "url": $this->_currentItem['item_url'] = $data; break; case "lang": $this->_currentItem['item_lang'] = $data; break; case "changes": $this->_currentItem['item_changes'] = $data; break; } } } } ?> --- NEW FILE: RasFormManager.php --- <?php /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. */ /** * Remote App Syndication - form manager * * @version 0.0.4 * @author Bruno Desthuilliers <br...@mo...> * * creates all HTML content. */ class RasFormManager { // --------------------------------------------------------------------------- /** * return an html link for the Ras module * * @param string $caption link's caption * @param string $RAS_op the op to pass to the query part of the url * @param array $kwargs array of key=>values to add to the query * @return string the link as an html tag */ function _rasLink($caption, $ras_op, $kwargs=null) { $link = "<a href='index.php?module=ras&RAS_op=" . $ras_op; if (is_array($kwargs)) { foreach($kwargs as $key=>$arg) { $link .= "&{$key}={$arg}"; } } $link .= "'>{$caption}</a>"; return $link; } // DIALOG BOXES -------------------------------------------------------------- /** * return a 'confirm' dialogBox-like form * * @param string $caption caption of the dialog * @param string $question the text of the dialog * @param string $opYes the RAS_op code for the 'yes' link * @param array $kwYes array of additionnal key-value pair for the 'yes' link * @param string $opNo the RAS_op code for the 'no' link * @param string $opBack the RAS_op code for the 'go back' (ie : cancel) link */ function formConfirm($caption, $question, $opYes, $kwYes, $opNo, $opBack=null) { $vars['CAPTION'] = $caption; $vars['QUESTION'] = $question; $vars['YES'] = $this->_rasLink($_SESSION['translate']->it("Yes"), $opYes, $kwYes); $vars['NO'] = $this->_rasLink($_SESSION['translate']->it("No"), $opNo); if ($opBack != null) { $vars['LINKBACK'] = $this->_rasLink($_SESSION['translate']->it("Go back"), $opBack); } return PHPWS_Template::processTemplate($vars, "ras", "confirm.tpl"); } // --------------------------------------------------------------------------- /** * return a 'info' dialogBox-like form * * @param string $caption caption of the dialog * @param string $msg the text of the dialog * @param string $op the RAS_op code for the 'ok' link * @param array $kwargs array of additionnal key-value pair for the 'ok' link */ function formInfo($caption, $msg, $op, $kwargs=null) { $vars['CAPTION'] = $caption; $vars['MSG'] = $msg; $vars['OK'] = $this->_rasLink($_SESSION['translate']->it('Ok'), $op, $kwargs); return PHPWS_Template::processTemplate($vars, "ras", "info.tpl"); } // SETTINGS ------------------------------------------------------------------ /** * return the 'edit/create settings' form */ function formSettings() { $form = "<form action=\"index.php\" method=\"post\">\n"; $form .= PHPWS_Form::formHidden(array("module"=>"ras", "RAS_op"=>"updatemastersettings")); if (isset($_REQUEST['ras_from'])) { $form .= PHPWS_Form::formHidden('ras_from', $_REQUEST['ras_from']); } $template['TITLE'] = $_SESSION['translate']->it("Remote Applicative Syndication : Settings"); $template['CMD_VIEW_FEEDS'] = $this->_rasLink($_SESSION['translate']->it("Channels"), 'viewfeeds'); $template['CMD_VIEW_RES'] = $this->_rasLink($_SESSION['translate']->it('Publish Resources'), 'viewresources'); $template['IS_MASTER'] = PHPWS_Form::formCheckBox("ras_ismaster", "1", $settings['is_master'], NULL, $_SESSION['translate']->it('This site can be master')); $template['ALLOW_ANONYMOUS'] = PHPWS_Form::formCheckBox("ras_anonymous", "1", $settings['accept_anonymous'], NULL, $_SESSION['translate']->it('Allow anonymous downloads')); $template['CMD_SAVE'] = PHPWS_Form::formSubmit($_SESSION['translate']->it("save settings"), "ras_update_settings"); $template['CMD_CANCEL'] = PHPWS_Form::formSubmit($_SESSION['translate']->it("cancel"), "ras_cancel_settings"); $form .= PHPWS_Template::processTemplate($template, "ras", "resources/settings.tpl"); $form .= "</form>"; PHPWS_Template::refreshTemplate("ras"); return $form; } // RESOURCES ----------------------------------------------------------------- /** * return the 'viewresource' form */ function formResourceList() { $template['TITLE'] = $_SESSION['translate']->it("Remote Applicative Syndication"); $template['CMD_EDIT_SETTINGS'] = $this->_rasLink($_SESSION['translate']->it('Master Settings'), 'editsettings', Array('ras_from'=>'viewresources')); $template['CMD_VIEW_FEEDS'] = $this->_rasLink($_SESSION['translate']->it('Channels'), 'viewfeeds'); $template['MODULES'] = $this->formModuleList(); $template['THEMES'] = $this->formThemeList(); $form = PHPWS_Template::processTemplate($template, "ras", "viewresources.tpl"); PHPWS_Template::refreshTemplate("ras"); return $form; } // --------------------------------------------------------------------------- /** * return the 'module' part of the 'viewresource' form */ function formModuleList() { $form = "<form action=\"index.php\" method=\"post\">\n" . PHPWS_Form::formHidden(array("module"=>"ras", "RAS_op"=>"exportmodule")); $template['LBL_MOD_TITLE'] = "Module"; $template['LBL_MOD_PNAME'] = "..."; $template['LBL_MOD_VERSION'] = "Version"; $template['LBL_CODE_COMMAND'] = "Code"; $template['LBL_LANG_COMMAND'] = "Lang"; $template['LBL_DATA_COMMAND'] = "Data"; $mods = $GLOBALS['core']->listModules(); $is_pair = 0; foreach($mods as $modTitle) { $rowTemplate = Array(); $moduleInfo = $GLOBALS["core"]->getModuleInfo($modTitle); if (! $moduleInfo ) { $rowTemplate['MOD_PNAME'] = $_SESSION['translate']->it("Could not get module info for module : ") . $modTitle; } else { $versionInfo = phpws_boost::getVersionInfo($modTitle); if (! $versionInfo) { $rowTemplate['MOD_PNAME'] = $_SESSION['translate']->it("Could not get version info for module : ") . $modTitle; } else { $rowTemplate['MOD_TITLE'] = $modTitle; $rowTemplate['MOD_PNAME'] = $moduleInfo['mod_pname']; $rowTemplate['MOD_VERSION'] = $versionInfo['version']; $rowTemplate['MOD_COMMAND'] = PHPWS_Form::formSubmit("export", "ras_export_module[$modTitle]"); $rowTemplate['LANG_COMMAND'] = PHPWS_Form::formSubmit("export", "ras_export_lang[$modTitle]"); $rowTemplate['DATA_COMMAND'] = PHPWS_Form::formSubmit("export", "ras_export_data[$modTitle]"); } } $is_pair ? $rowTemplate["TOG2"] = " " : $rowTemplate["TOG1"] = " "; $is_pair = ! $is_pair; $moduleRows[] = PHPWS_Template::processTemplate($rowTemplate, "ras", "resources/modulerows.tpl"); } $template["MODULE_ROWS"] = implode("", $moduleRows); $form .= PHPWS_Template::processTemplate($template, "ras", "resources/modules.tpl"); $form .= "</form>"; return $form; } // --------------------------------------------------------------------------- /** * return the 'themes' part of the 'viewresource' form * TODO : this is Q&D, could be smarter */ function formThemeList() { $dir = PHPWS_File::readDirectory(PHPWS_HOME_DIR . "themes/", 1); if (! is_array($dir)) { /* TODO */ exit("Error - no themes found."); } foreach($dir as $themeName) { $themePath = PHPWS_HOME_DIR . "themes/$themeName/"; if (file_exists($themePath . "theme.tpl")) { $lastModStamp = PHPWS_RemoteAppSyndication::lastmtime($themePath); $lastModDate = PHPWS_RemoteAppSyndication::timestampToDatetime($lastModStamp); $themes[$themeName] = Array('THEME_NAME'=>$themeName, 'THEME_PATH'=>$themePath, 'LASTMOD_DATE'=>$lastModDate, 'LASTMOD_STAMP'=>$lastModStamp); } } natcasesort($themes); $form = "<form action=\"index.php\" method=\"post\">\n"; $form .= PHPWS_Form::formHidden(array("module"=>"ras", "RAS_op"=>"exporttheme")); $template['LBL_THEME_NAME'] = $_SESSION['translate']->it("Theme"); $template['LBL_THEME_PATH'] = $_SESSION['translate']->it("Path"); $template['LBL_LASTMOD_DATE'] = $_SESSION['translate']->it("Last modification"); $template['LBL_TPL_COMMAND'] = $_SESSION['translate']->it("Template"); $template['LBL_IMG_COMMAND'] = $_SESSION['translate']->it("Images"); $is_pair = 0; foreach($themes as $themeName=>$theme) { $rowTemplate = $theme; $rowTemplate['TPL_COMMAND'] = PHPWS_Form::formSubmit("export", "ras_export_tpl[$themeName]"); $rowTemplate['IMG_COMMAND'] = PHPWS_Form::formSubmit("export", "ras_export_img[$themeName]"); $is_pair ? $rowTemplate["TOG2"] = " " : $rowTemplate["TOG1"] = " "; $is_pair = ! $is_pair; $themeRows[] = PHPWS_Template::processTemplate($rowTemplate, "ras", "resources/themerows.tpl"); } $template['THEME_ROWS'] = implode("", $themeRows); $form .= PHPWS_Template::processTemplate($template, "ras", "resources/themes.tpl"); $form .= "</form>"; return $form; } // FEEDS --------------------------------------------------------------------- /** * return the 'viewfeeds' form */ function formFeedList($channels) { // assert (is_array($channel)) or die("no channels"); /* get channel list from the db */ $template['TITLE'] = $_SESSION['translate']->it("Remote Applicative Syndication : channels"); $template['CMD_NEW_CHAN'] = $this->_rasLink($_SESSION['translate']->it('New channel'),'createchannel'); $template['CMD_VIEW_RES'] = $this->_rasLink($_SESSION['translate']->it('Publish Resources'), 'viewresources'); $template['CMD_EDIT_SETTINGS'] = "<a href='index.php?module=ras&RAS_op=editsettings&ras_from=viewfeeds'>Master Settings</a>"; $template['CMD_EDIT_SETTINGS'] = $this->_rasLink( $_SESSION['translate']->it('Master Settings'), 'editsettings', Array('ras_from'=>'viewfeeds')); /* read and parse channels */ $feedParser =& new RasFeedParser; $chanRows = Array(); /* * $channels : array (id => array('name'=>name, 'url'=>'http://www.exemple.org', active=>[0|1]) * [,...]): */ foreach($channels as $channelName=>$channelData) { $chanTemplate = Array(); $chanTemplate['CHAN_NAME'] = $channelName; $chanTemplate['CHAN_EDIT_CMD'] = $this->_rasLink($_SESSION['translate']->it('Edit'), 'editchannel', Array('ras_chan_id'=>$channelName)); $chanTemplate['CHAN_DEL_CMD'] = $this->_rasLink ($_SESSION['translate']->it('Delete'), 'checkdeletechannel', Array('ras_chan_id'=>$channelName)); /* format resources from the feed */ if ($channelData['active']) { $feed = $feedParser->parse($channelData['url']); if ($feed != false) { $chanTemplate['CHAN_RESOURCES'] = $this->formFeedResources($feed['channel_resources']); } else { $chanTemplate['CHAN_RESOURCES'] = $_SESSION['translate']->it('Could not parse feed :') . "<br>\n" . $feedParser->getLastError(); } } $chanRows[] = PHPWS_Template::processTemplate($chanTemplate,'ras', 'channels/channelfeed.tpl'); } $template['CHANNELS'] = implode("", $chanRows); return PHPWS_Template::processTemplate($template, "ras", "viewfeeds.tpl"); } // --------------------------------------------------------------------------- /** * called for each channel */ function formFeedResources($channel_resources) { $resRows = Array(); foreach($channel_resources as $app) { foreach($app['app_resources'] as $res) { $resTemplate['APP_NAME'] = $app['app_name']; $resTemplate['APP_VERSION'] = $app['app_version']; $resTemplate['RES_NAME'] = $res['res_name']; $resTemplate['RES_TYPE'] = $res['res_type']; $resTemplate['RES_DESC'] = $res['res_desc']; /* feed's items */ $itemRows = Array(); foreach($res['res_items'] as $item) { $itemTemplate['ITEM_TYPE'] = $item['item_type']; $itemTemplate['ITEM_VERSION'] = $item['item_version']; $itemTemplate['ITEM_DATE'] = $item['item_date']; $itemTemplate['ITEM_CHANGES'] = $item['item_changes']; $itemTemplate['ITEM_LINK'] = $this->_rasLink($_SESSION['translate']->it("Import"), 'checkimport' , Array('ras_itm_url'=>$item['item_url'], 'ras_res_type'=>$res['res_type'])); $itemRows[] = PHPWS_Template::processTemplate($itemTemplate,'ras', 'channels/chanitem.tpl'); } $resTemplate['RES_ITEMS'] = implode("", $itemRows); $resRows[] = PHPWS_Template::processTemplate($resTemplate,'ras', 'channels/chanresource.tpl'); } } return implode("", $resRows); } // --------------------------------------------------------------------------- /** * called for each resource */ function formFeedItems($items) { $itemRows = Array(); foreach($items as $item) { $itemTemplate['ITEM_TYPE'] = $item['item_type']; $itemTemplate['ITEM_VERSION'] = $item['item_version']; $itemTemplate['ITEM_DATE'] = $item['item_date']; $itemTemplate['ITEM_CHANGES'] = $item['item_changes']; $itemTemplate['ITEM_LINK'] = $this->_rasLink($_SESSION['translate']->it("Get item"), 'checkgetitem' , Array('ras_itm_url'=>$item['item_url'])); $itemRows[] = PHPWS_Template::processTemplate($itemTemplate,'ras', 'channels/chanitem.tpl'); } return implode("", $itemRows); } // CHANNEL ------------------------------------------------------------------- /** * return the 'edit/create channel' form * * @param string $channelId the Id (actually the name of) the channel * @param array $channelData the datas for this channel (name, url, activeYN) * @param string $msg can't remember why I added this ??? */ function formChannel($channelId='', $channelData=null, $msg=null) { $hiddenData = array("module"=>"ras", "RAS_op"=>"updatechannel", "ras_chan_id"=>$channelId, "ras_channel_new"=> strlen($channelId) ? 0 : 1 ); $form = "<form action=\"index.php\" method=\"post\">\n" . PHPWS_Form::formHidden($hiddenData); $tplVars = Array(); if ($msg != null) { $tplvars['CHAN_MSG'] = $msg; } $tplVars['TITLE'] = $_SESSION['translate']->it("Remote Applicative Syndication : edit channel"); $tplVars['CHAN_NAME'] = $channelData['name']; $tplVars['LBL_CHAN_NAME'] = $_SESSION['translate']->it("Channel Name : "); $tplVars['LBL_CHAN_ACTIVE'] = $_SESSION['translate']->it("Activate channel"); $tplVars['LBL_CHAN_URL'] = $_SESSION['translate']->it("Channel Url : "); /* edit an existing channel */ if ($channelId) { $tplVars['TXT_CHAN_NAME'] = PHPWS_Form::formTextField('ras_chan_name', $channelData['name'], 30); $tplVars['TXT_CHAN_URL'] = PHPWS_Form::formTextField('ras_chan_url', $channelData['url'], 80); $tplVars['CHK_CHAN_ACTIVE'] = PHPWS_Form::formCheckBox('ras_chan_active', '1', $channelData['active']); } /* create a new channel */ else { $tplVars['TXT_CHAN_NAME'] = PHPWS_Form::formTextField('ras_chan_name', '', 30); $tplVars['TXT_CHAN_URL'] = PHPWS_Form::formTextField('ras_chan_url', 'http://', 80); $tplVars['CHK_CHAN_ACTIVE'] = PHPWS_Form::formCheckBox('ras_chan_active', '1', '1'); } $tplVars['SUB_CHANNEL_OK'] = PHPWS_Form::formSubmit($_SESSION['translate']->it('Ok'), 'ras_chan_ok'); $tplVars['SUB_CHANNEL_CANCEL'] = PHPWS_Form::formSubmit($_SESSION['translate']->it('Cancel'), 'ras_chan_cancel'); $form .= PHPWS_Template::processTemplate($tplVars, "ras", "channels/chanedit.tpl"); $form .= "</form>"; return $form; } } ?> --- NEW FILE: RasBackend.php --- <?php /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. */ /** * Remote App Syndication - Ras Feed backend * * @version 0.0.4 * @author Bruno Desthuilliers <br...@mo...> * * Generate the ras-feeds for clients * TODO : * - DTD * - more documentation ? */ //------------------------------------------------------------------------------ require_once PHPWS_SOURCE_DIR . 'mod/ras/class/RasBase.php'; //------------------------------------------------------------------------------ class RasBackend extends RasBase { //---------------------------------------------------------------------------- /** * read feed datas from the db and returns a ras-feed xml as string * * @return string a ras-feed xml */ function createFeed() { $content = Array(); $content[] = "<?xml version='1.0' encoding='iso-8859-1'?>"; /* TODO : DTD */ //$content[] = '<!DOCTYPE ras PUBLIC "-//Modulix//DTD RAS 0.1//EN http://modulix.org/publish/formats/ras-0.1.dtd">'; $content[] = "<ras-feed>"; $apps = $GLOBALS['core']->getAssoc('select * from mod_ras_apps'); foreach($apps as $appId=>$app) { $content[] = "<application name='" . $app['app_name'] ."' version='" . $app['app_version'] . "'>"; $content[] = $this->_feedResources($appId); $content[] = "</application>"; } $content[] = "</ras-feed>"; return implode("\n", $content); } //---------------------------------------------------------------------------- /** * called for each app */ function _feedResources($appId) { $content = Array(); $content[] = "<resources>"; $resources = $GLOBALS['core']->getAssoc("select * from mod_ras_resources where app_id=$appId"); foreach ($resources as $resId=>$res) { $content[] = "<resource type='" . $res['res_type'] . "' name='" . $res['res_name'] . "'>"; $content[] = "<description>" . $res['res_description'] . "</description>"; $content[] = $this->_feedItems($resId); $content[] = "</resource>"; } $content[] = "</resources>"; return implode("\n", $content); } //---------------------------------------------------------------------------- /** * called for each resource */ function _feedItems($resId) { $content = Array(); $items = $GLOBALS['core']->getAssoc("select * from mod_ras_items where res_id=$resId"); foreach ($items as $item) { $content[] = "<item type='" . $item['itm_type'] . "'>"; $content[] = "<version>" . $item['itm_version'] . "</version>"; //$content[] = "<url>" . "http://localhost/phpws/files/ras/resources/" . $item['itm_url'] . "</url>"; $content[] = "<url>" . $item['itm_url'] . "</url>"; $content[] = "<changes>" . $item['itm_changes'] . "</changes>"; $content[] = "<date>" . $item['itm_date'] . "</date>"; $content[] = "<lang>" . $item['itm_lang'] . "</lang>"; $content[] = "<md5>" . $item['itm_md5'] . "</md5>"; $content[] = "</item>"; } return implode("\n", $content); } //---------------------------------------------------------------------------- /** * store the RAS feed datas in the DB * * @param string $resType the type of resource ('module' or 'theme' actually) * @param string $resName the name of the resource * @param array $feedData associative array of data to insert in mod_ras_items * @return boolean guess what ? * * TODO : * - versions themes ? * - what about missing data ? */ function storeFeed($resType, $resName, $feedData) { $core =& $GLOBALS['core']; /* check if we have the app, else create it */ /* TODO : appId is returned as a string ? */ $appVersion = $core->version; $appName = 'phpWebSite'; $row = $core->getRow("select app_id from mod_ras_apps where app_name='$appName' and app_version='$appVersion'"); if ($row == null) { $data = Array('app_name'=>$appName, 'app_version'=>$appVersion); $appId = $core->sqlInsert($data, 'mod_ras_apps', TRUE, TRUE, FALSE, TRUE); if ($appId == null) { /* TODO : more error info */ return $this->setLastError($_SESSION['translate']->it("Could not add application to the database :") . "$appName - $appVersion"); } } else { $appId = $row['app_id']; } $appId = (int)$appId; /* check if resource exists, else create it */ $row = $core->getRow("select * from mod_ras_resources where app_id=$appId and res_name='$resName' and res_type='$resType'"); if ($row == null) { $data = Array('app_id'=>$appId, 'res_name'=>$resName, 'res_type'=>$resType); $resId = $core->sqlInsert($data, 'mod_ras_resources', TRUE, TRUE, FALSE, TRUE); if ($resId == null) { /* TODO : more error info */ return $this->setLastError($_SESSION['translate']->it("Could not add resource to the database : ") . "$resName - $resType"); } } else { $resId = $row['res_id']; } /* store feed data */ $feedData['res_id'] = (int)$resId; // function sqlInsert ($db_array, $table_name, $check_dup=FALSE, $returnId=FALSE, $show_sql=FALSE, $autoIncrement=TRUE) { if (! $core->sqlInsert($feedData, 'mod_ras_items', TRUE, FALSE, FALSE, TRUE)) { /* TODO : more error info */ return $this->setLastError($_SESSION['translate']->it("Could not add feed data to the database : ") . "$resName - $resType"); } return true; } } ?> |