com.lokorin.lokorin.lib
[ class tree: com.lokorin.lokorin.lib ] [ index: com.lokorin.lokorin.lib ] [ all elements ]

Source for file lib_projects.php

Documentation is available at lib_projects.php

  1. <?php
  2. /*
  3. * Lokorin.com
  4. * Copyright 2004-2006
  5. * Licensed under the GNU LGPL. See COPYING for full terms.
  6. */
  7. /**
  8. * A library that contains everything that has to do with the site's project
  9. * system.
  10. * @author Andreas Launila
  11. * @version $Revision: 1.32 $
  12. * @package com.lokorin.lokorin.lib
  13. * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
  14. */
  15.  
  16. /**
  17. * For access to common constants and functions.
  18. */
  19. require_once('common.php');
  20.  
  21. /**
  22. * The total width, in pixels, that the menu is allowed to occupy.
  23. * @var integer
  24. * @access private
  25. */
  26. define('TOTAL_WIDTH', 650);
  27. /**
  28. * The width, in pixels, that each menu link should be represented with.
  29. * @var integer
  30. * @access private
  31. */
  32. define('MENU_ITEM_WIDTH', 124);
  33.  
  34. /**
  35. * Gets a project based on the current directory. If the current directory is
  36. * one of the projects' home directories then one of those projects are
  37. * returned.
  38. * @return Project A Project instance that is connected with the current
  39. * directory. If there are no such then null will be returned.
  40. * @throws NoSuchElementException If no project for the directory is found.
  41. * @access public
  42. */
  43. function getProjectBasedOnDir() {
  44. global $db;
  45. doInclude('lib_util');
  46. $dir = getCurrentDirectory();
  47. try {
  48. return new Project($db->querySelectFirst(TABLE_PROJECTS, 'id',
  49. "WHERE relative_path = ".$db->escape($dir)));
  50. } catch(Exception $e) {
  51. throw new NoSuchElementException("No project was found for the " .
  52. "directory (".$dir.")");
  53. }
  54. }
  55.  
  56. /**
  57. * Gets the names of all available projects.
  58. * @return array The project names as values with the unique identifier for
  59. * the corresponding project as key.
  60. * @access public
  61. */
  62. function getAllProjectNames() {
  63. global $db;
  64. $rows = $db->querySelect(TABLE_PROJECTS, array('id', 'name'),
  65. "ORDER BY timestamp DESC");
  66. $names = array();
  67. foreach($rows as $row) {
  68. $names[$row['id']] = $row['name'];
  69. }
  70. return($names);
  71. }
  72.  
  73. /**
  74. * Get the descriptions for all available project stages.
  75. * @return array The stage descriptions as value with the unique identifier
  76. * for the corresponding project as key.
  77. * @access public
  78. */
  79. function getAllStageDescriptions() {
  80. global $db;
  81. $rows = $db->querySelect(TABLE_PROJECT_STAGES, array('id', 'description'),
  82. "ORDER BY id DESC");
  83. $names = array();
  84. foreach($rows as $row) {
  85. $names[$row['id']] = $row['description'];
  86. }
  87. return($names);
  88. }
  89.  
  90. /**
  91. * Gets all available projects.
  92. * @return array Each avaialable project represented as a Project instance.
  93. * @access public
  94. */
  95. function getAllProjects() {
  96. return getProjects("ORDER BY timestamp DESC");
  97. }
  98.  
  99. /**
  100. * Gets all projects that match a specified sql selector statement.
  101. * @param string $sqlSelector The sql statement that specifies the project that
  102. * should be retrieved.
  103. * @return array An array containing Project instances representing the
  104. * retrieved projects.
  105. * @access public
  106. */
  107. function getProjects($sqlSelector) {
  108. global $db;
  109. $rows = $db->querySelect(TABLE_PROJECTS, array('id'), $sqlSelector);
  110. $projects = array();
  111. foreach($rows as $row) {
  112. $projects[] = new Project($row['id']);
  113. }
  114. return $projects;
  115. }
  116.  
  117. /**
  118. * Gets the number of projects available.
  119. * @return integer A number of projects.
  120. * @access public
  121. */
  122. function getProjectCount() {
  123. global $db;
  124. return $db->queryCount(TABLE_PROJECTS);
  125. }
  126.  
  127. /**
  128. * Describes a project.
  129. * @author Andreas Launila
  130. * @package com.lokorin.lokorin.lib
  131. */
  132. class Project extends TableEntry {
  133. /**
  134. * The name of the project.
  135. * @var string
  136. */
  137. private $name;
  138. /**
  139. * The unique identifier of the programming language that represents the
  140. * project.
  141. * @var integer
  142. */
  143. private $langId;
  144. /**
  145. * The language version that the project usues.
  146. * @var string
  147. */
  148. private $langVersion;
  149. /**
  150. * The path from the root to the projects directory. Alternativly an
  151. * absolute url starting with 'http://' can be specified.
  152. * @var string
  153. */
  154. private $path;
  155. /**
  156. * Whether or not the project has any projects associated with it. True if
  157. * the project has downloads, false otherwise.
  158. * @var boolean
  159. */
  160. private $hasDownloads;
  161. /**
  162. * Whether or not the project's source is available for download. True if
  163. * the project has source available for download, false otherwise. If it is
  164. * false then it's assumed that the source can be gotten through contact.
  165. * @var boolean
  166. */
  167. private $hasSource;
  168. /**
  169. * The name of the icon image used to represent the project.
  170. * @var string
  171. */
  172. private $iconName;
  173. /**
  174. * Whether or not the project should be shown in the site's menu. True if
  175. * the project should be shown, false otherwise.
  176. * @var boolean
  177. */
  178. private $doDisplayInMenu;
  179. /**
  180. * The unique identifier for the stage that the project is currently at.
  181. * @var integer
  182. */
  183. private $stageId;
  184. /**
  185. * The unix timestamp that represents when the project was added.
  186. * @var integer
  187. */
  188. private $timestamp;
  189. /**
  190. * The license if any that the project is released under. The license
  191. * information should be in the form of XHTML code.
  192. * @var string
  193. */
  194. private $license;
  195. /**
  196. * A processed description in XHTML of what the project is about, it's
  197. * goals and so on.
  198. * @var string
  199. */
  200. private $description;
  201. /**
  202. * The timestamp describing the point in time when the description was
  203. * last processed.
  204. * @var integer
  205. */
  206. private $timeProcessed;
  207. /**
  208. * The description that the project pages should have.
  209. * @var string
  210. */
  211. private $pageDescription;
  212. /**
  213. * Constructor for Project.
  214. * @param integer $id The unique identifier for the project.
  215. */
  216. function __construct($id) {
  217. $fields = array(
  218. 'name',
  219. 'lang_id',
  220. 'lang_ver',
  221. 'relative_path',
  222. 'has_downloads',
  223. 'has_source',
  224. 'icon_name',
  225. 'display_menulink',
  226. 'stage_id',
  227. 'timestamp',
  228. 'processed_description',
  229. 'license',
  230. 'timestamp_description_processed',
  231. 'page_description'
  232. );
  233. parent::__construct(TABLE_PROJECTS, $id, $fields);
  234. }
  235. /**
  236. * @see com.lokorin.lokorin.includes.TableEntry.readRow($row)
  237. */
  238. protected function readRow($row) {
  239. $this->name = $row['name'];
  240. $this->langId = $row['lang_id'];
  241. $this->langVersion = $row['lang_ver'];
  242. $this->path = $row['relative_path'];
  243. $this->hasDownloads = $row['has_downloads'];
  244. $this->hasSource = $row['has_source'];
  245. $this->iconName = $row['icon_name'];
  246. $this->doDisplayInMenu = $row['display_menulink'];
  247. $this->stageId = $row['stage_id'];
  248. $this->timestamp = $row['timestamp'];
  249. $this->description = $row['processed_description'];
  250. $this->license = $row['license'];
  251. $this->timeProcessed = $row['timestamp_description_processed'];
  252. $this->pageDescription = $row['page_description'];
  253. if($this->pageDescription == '') {
  254. //Use the first sentence in the description instead.
  255. $description = preg_replace("/<.*?>/", "", $this->getDescriptionAsHtml());
  256. $description = preg_replace("/<.*?$/", "", $description);
  257. $this->pageDescription = substr($description, 0, strpos($description, '.') + 1);
  258. }
  259. }
  260. /**
  261. * Gets the link representation for the project. If the project has an
  262. * icon then it is used to represent the project, otherwise a text link is
  263. * used.
  264. * @return string An XHTML compliant link representation.
  265. */
  266. public function getLink() {
  267. global $db;
  268.  
  269. $projPath = $this->path;
  270. if(strpos($projPath, 'http://') === false) {
  271. $projPath = PAGE_ROOT.$projPath;
  272. }
  273. $output = '<a href="'.$projPath.'">';
  274. if($this->iconName != '') {
  275. doInclude('lib_images');
  276. $iconPath = FOLDER_ICONS.$this->iconName;
  277. if(!file_exists(DOC_ROOT.$iconPath)) {
  278. doInclude('lib_errors');
  279. logException(new FileNotFoundException('Project Icon ('.$iconPath.
  280. ') is missing.'));
  281. return '';
  282. }
  283. $output .= getImageCode($iconPath, $this->name, $this->name, 'icon');
  284. } else {
  285. $output .= $this->name;
  286. }
  287. return $output.'</a>';
  288. }
  289. /**
  290. * Gets the programming language used in the project.
  291. * @return ProgrammingLanguage The ProgrammingLanguage instance that
  292. * represents the used language.
  293. */
  294. public function getProgrammingLanguage() {
  295. doInclude('lib_languages');
  296. return new ProgrammingLanguage($this->langId);
  297. }
  298. /**
  299. * Gets the stage that the project is currently at.
  300. * @return Stage The Stage instance that represents the current Stage.
  301. */
  302. public function getStage() {
  303. return new Stage($this->stageId);
  304. }
  305. /**
  306. * Gets a short synopsis of the project. The synopsis consists of the name
  307. * and link to the project along with a list with the following
  308. * information: language (and version), when it was started, current stage
  309. * and a short description.
  310. * @return string XHTML compliant code representing a short synopsis of
  311. * the project.
  312. */
  313. public function getSynopsis() {
  314. $stage = $this->getStage();
  315. //Get the first sentence of the description and use it as description.
  316. $output = '<a href="'.PAGE_ROOT.$this->path.'">'.$this->name.'</a>' .
  317. '<ul>';
  318. try {
  319. $lang = $this->getProgrammingLanguage();
  320. $output .= '<li><i>Language</i>: '.$lang->getLink().' '.
  321. $this->langVersion.'</li>';
  322. } catch(Exception $e) {}
  323. $output .= '<li><i>Started</i>: '.date(DATE_LONG, $this->timestamp).'</li>' .
  324. '<li><i>Status</i>: '.$stage->getDescription().'</li>' .
  325. '<li><i>Short description</i>: '.$this->pageDescription.'</li>' .
  326. '</ul>';
  327. return $output;
  328. }
  329. /**
  330. * Gets the name of the project.
  331. * @return string A name.
  332. */
  333. public function getName() {
  334. return $this->name;
  335. }
  336. /**
  337. * Gets a summary of all information available on the project.
  338. * @return string XHTML compliant code representing all information on the
  339. * project.
  340. */
  341. public function getInfo() {
  342. //Construct the icon info.
  343. $icon = '';
  344. if($this->iconName != '') {
  345. doInclude('lib_images');
  346. $iconPath = ROOT.FOLDER_ICONS.$this->iconName;
  347. $icon = '<li><i>Icon</i>: '.
  348. getImageCode($iconPath, 'Project icon', '', 'icon').'</li>';
  349. }
  350. //Construct additional info.
  351. $additional = '';
  352. if($this->hasDownloads == 1) {
  353. $additional .= 'This project has downloadable items.<br />';
  354. }
  355. if($this->hasSource == 1) {
  356. $additional .= 'This project\'s source code is available for ' .
  357. 'download.<br />';
  358. } else {
  359. $additional .= 'This project\'s source code is available through ' .
  360. '<a href="'.PAGE_ROOT.'contact">contact</a>.<br />';
  361. }
  362. //Get the language and stage.
  363. $lang = $this->getProgrammingLanguage();
  364. $stage = $this->getStage();
  365.  
  366. //Get the license information.
  367. $license = "";
  368. if(strlen($this->license) != 0) {
  369. $license = "<li><i>License</i>: ".$this->license."</li>";
  370. }
  371.  
  372. //Construct the output.
  373. return $this->getDescriptionAsHtml().
  374. '<h2>Project information</h2>' .
  375. '<ul>' .
  376. '<li><i>Name</i>: '.$this->name.'</li>'.
  377. $icon.
  378. '<li><i>Started</i>: '.date(DATE_LONG, $this->timestamp).'</li>' .
  379. '<li><i>Language</i>: '.$lang->getLink().' '.
  380. $this->langVersion.'</li>' .
  381. $license.
  382. '<li><i>Status</i>: '.$stage->getDescription().'</li>
  383. </ul>'."\n".
  384. '<p>'.$additional.'</p>';
  385. }
  386. /**
  387. * Gets the submenu connected with the project, i.e. a menu for all
  388. * pages in the project.
  389. * @return string XHTML compliant code representing the menu.
  390. */
  391. public function getMenu() {
  392. doInclude('lib_menu');
  393. $projectMenu = new ProjectMenu(parent::$this->getId());
  394. $destinations = $projectMenu->getDestinations();
  395. /*
  396. * Calculate how the menu should look. I'm making a small exception from
  397. * seperating form and function, there was no other simple way.
  398. */
  399. if(count($destinations) > 5) {
  400. $menuCount = 5;
  401. } else {
  402. $menuCount = count($destinations);
  403. }
  404. $offsetRow1 = (TOTAL_WIDTH / MENU_ITEM_WIDTH - $menuCount) *
  405. MENU_ITEM_WIDTH / 2;
  406. $offsetRow2 = (TOTAL_WIDTH / MENU_ITEM_WIDTH -
  407. (sizeof($destinations) - 5)) * MENU_ITEM_WIDTH / 2;
  408. //Calculate the output class="firstRow"
  409. $output = '<ul style="margin-left: '.$offsetRow1.'px;">';
  410. $rowCount = 0;
  411. foreach($destinations as $name => $path) {
  412. if($rowCount == 5) {
  413. //The first row is filled, start a second. There's only support
  414. //for two rows at the moment.
  415. $output .= '</ul><ul style="margin-left: '.
  416. $offsetRow2.'px;">';
  417. }
  418. $output .= '<li><a href="';
  419. if(strpos($path, 'http://') === false) {
  420. $output .= PAGE_ROOT;
  421. }
  422. $output .= $path.'">'.$name.'</a></li>'."\n";
  423. $rowCount++;
  424. }
  425. $output .= '</ul>';
  426. return $output;
  427. }
  428. /**
  429. * Whether or not the project has a menu.
  430. * @return boolean True if the project has a menu, false otherwise.
  431. */
  432. public function hasMenu() {
  433. doInclude('lib_menu');
  434. $menu = new ProjectMenu(parent::$this->getId());
  435. $destinations = $menu->getDestinations();
  436. return is_array($destinations) && count($destinations) > 0;
  437. }
  438. /**
  439. * Gets the path from the site's root to the home directory of the project.
  440. * @return string A path relative to the root.
  441. */
  442. public function getPath() {
  443. return $this->path;
  444. }
  445. /**
  446. * Gets all download items that are connected to the project. The items
  447. * are grouped by their respective category. The categories should if
  448. * possible be displayed in the order that they are given.
  449. * @return array An array where the key is a DownloadCategory instance and
  450. * the corresponding value is an array of DownloadItem instances,
  451. * where each such instance represents a downloadable item in the
  452. * category.
  453. */
  454. public function getDownloadsGroupedByCategory() {
  455. global $db;
  456. doInclude('lib_downloads');
  457. $idFields = array('project_id' => parent::$this->getId());
  458. return getDownloadsGroupedByCategory($db->buildSqlSelector($idFields));
  459. }
  460. /**
  461. * Gets all images, and their descriptions, that are connected to the
  462. * project.
  463. * @return array The name of the image as key and the description that is
  464. * connected to the image as value.
  465. */
  466. public function getImages() {
  467. global $db;
  468. $rows = $db->querySelect(TABLE_PROJECT_IMAGES,
  469. array('image_name', 'description'),
  470. "WHERE project_id=".$db->escape(parent::$this->getId())." ORDER BY id DESC");
  471. $images = array();
  472. foreach($rows as $row) {
  473. $images[$row['image_name']] = $row['description'];
  474. }
  475. return $images;
  476. }
  477. /**
  478. * Gets all news entries that are connected to the project.
  479. * @return array Each entry represents a news item. The items are ordered
  480. * so that the news item with the timestamp is first.
  481. */
  482. public function getNews() {
  483. doInclude('lib_news');
  484. return getNews($this->getNewsSqlSelector()." ORDER BY timestamp DESC");
  485. }
  486. /**
  487. * Gets an sql selector that selects all news that are connected to the
  488. * project from the news table.
  489. * @return string An sql selector. */
  490. public function getNewsSqlSelector() {
  491. global $db;
  492. $id = $db->escape(parent::$this->getId());
  493. return "WHERE (project_id1=".$id.") OR (project_id2=".$id.") " .
  494. "OR (project_id3=".$id.")";
  495. }
  496. /**
  497. * Gets the header link to the RSS page for the project's news.
  498. * @return string XHTML compliant code that describes a header link (which should
  499. * only be placed in the header portion of the page).
  500. * @access public
  501. */
  502. public function getRssHeaderLink() {
  503. return '<link rel="alternate" href="'.$this->getRssPath().'" ' .
  504. 'type="application/rss+xml" title="'.$this->name.' progress" />';
  505. }
  506. /**
  507. * Gets the path to the RSS feed for the project's news.
  508. * @return string A path, relative to the site's root, to the project's
  509. * news RSS feed.
  510. */
  511. public function getRssPath() {
  512. return PAGE_ROOT.'news/rss?project_id='.parent::$this->getId();
  513. }
  514. /**
  515. * Gets the submenu of the project.
  516. * @return ProjectMenu A project submenu.
  517. */
  518. public function getSubmenu() {
  519. doInclude('lib_menu');
  520. return new ProjectMenu(parent::$this->getId());
  521. }
  522. /**
  523. * Checks if the project should be displayed in the menu.
  524. * @return boolean True if the project should be displayed in the
  525. * navigational menu, false otherwise.
  526. */
  527. public function isMenuDisplayable() {
  528. return $this->doDisplayInMenu;
  529. }
  530. /**
  531. * Gets information about the license under which the project is released.
  532. * @return string The license information as valid XHTML code.
  533. */
  534. public function getLicense() {
  535. return $this->license;
  536. }
  537. /**
  538. * Gets the project's description as valid XHTML code.
  539. * @return string XHTML compliant code.
  540. */
  541. private function getDescriptionAsHtml() {
  542. if(strlen($this->description) == 0) {
  543. $this->updateProcessedDescription();
  544. }
  545. return $this->description;
  546. }
  547. /**
  548. * Processes the raw form of the descripiton and updates the processed form
  549. * with the new version. This should be done whenever the description
  550. * changes.
  551. */
  552. public function updateProcessedDescription() {
  553. global $db;
  554. doInclude("lib_markup");
  555. $description= $db->querySelectFirst(TABLE_PROJECTS, 'description',
  556. $db->buildSqlSelector(array('id' => parent::$this->getId())));
  557. $description = convertMarkupToHTML($description);
  558. //Update the last time that the description was processed.
  559. $this->timeProcessed = time();
  560. //Store the new processed version.
  561. $vars = array(
  562. 'processed_description' => $description,
  563. 'timestamp_description_processed' => $this->timeProcessed
  564. );
  565. $db->queryUpdate(TABLE_PROJECTS, $vars,
  566. $db->buildSqlSelector(array('id' => parent::$this->getId())));
  567. $this->description = $description;
  568. }
  569. /**
  570. * Gets the project, and all its subpages, as a sitemap entries.
  571. * @return string A number of well-formed XML url entry as specified by the
  572. * google sitemap schema.
  573. */
  574. public function getAsSitemapEntries() {
  575. doInclude('lib_sitemap');
  576. doInclude('lib_menu');
  577. $output = '';
  578. $submenu = new ProjectMenu(parent::$this->getId());
  579. foreach($submenu->getDestinations() as $destination) {
  580. if(strpos($destination, 'http://') === 0) {
  581. //The destination is not on the same domain, skip it.
  582. continue;
  583. }
  584. $output .= formatSitemapElement($destination, false, 1);
  585. }
  586. return $output;
  587. }
  588. /**
  589. * Gets the page description that should be used when displaying a page
  590. * that is related to this project.
  591. * @return string A brief description.
  592. */
  593. public function getPageDescription() {
  594. return $this->pageDescription;
  595. }
  596. }
  597.  
  598. /**
  599. * Describes a project stage. Each stage represents a part of the deveolpment
  600. * process of a project.
  601. * @author Andreas Launila
  602. * @package com.lokorin.lokorin.lib
  603. */
  604. class Stage extends TableEntry {
  605. /**
  606. * A description of the stage. The descriptions should be rather short i.e.
  607. * "Finished", they should not be explaining exactly what the stage is in
  608. * detail.
  609. * @var string
  610. */
  611. private $description;
  612. /**
  613. * Constructor for Stage.
  614. * @param integer $id The unique identifier for the stage.
  615. */
  616. public function Stage($id) {
  617. $fields = array('description');
  618. parent::__construct(TABLE_PROJECT_STAGES, $id, $fields);
  619. }
  620. /**
  621. * @see com.lokorin.lokorin.includes.TableEntry.readRow($row)
  622. */
  623. protected function readRow($row) {
  624. $this->description = $row['description'];
  625. }
  626. /**
  627. * Gets the description of the stage.
  628. * @return string A short description.
  629. * @access public
  630. */
  631. function getDescription() {
  632. return $this->description;
  633. }
  634. }
  635. ?>

Documentation generated on Sun, 16 Apr 2006 21:03:48 +0200 by phpDocumentor 1.3.0RC4