Source for file story-defs.php

Documentation is available at story-defs.php

  1. <?php
  2. /* ******************************************************************** */
  3. /* CATALYST PHP Source Code */
  4. /* -------------------------------------------------------------------- */
  5. /* This program is free software; you can redistribute it and/or modify */
  6. /* it under the terms of the GNU General Public License as published by */
  7. /* the Free Software Foundation; either version 2 of the License, or */
  8. /* (at your option) any later version. */
  9. /* */
  10. /* This program is distributed in the hope that it will be useful, */
  11. /* but WITHOUT ANY WARRANTY; without even the implied warranty of */
  12. /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
  13. /* GNU General Public License for more details. */
  14. /* */
  15. /* You should have received a copy of the GNU General Public License */
  16. /* along with this program; if not, write to: */
  17. /* The Free Software Foundation, Inc., 59 Temple Place, Suite 330, */
  18. /* Boston, MA 02111-1307 USA */
  19. /* -------------------------------------------------------------------- */
  20. /* */
  21. /* Filename: story-defs.php */
  22. /* Author: Paul Waite */
  23. /* Description: Definitions for managing and using Axyl stories/news */
  24. /* */
  25. /* ******************************************************************** */
  26. /** @package cm */
  27. include_once("catalog-defs.php");
  28. /** HTMLArea wysiwyg */
  29. ("htmlarea-defs.php");
  30.  
  31. // HTMLArea settings..
  32. htmlarea_plugins("CSS,ContextMenu,ListType,CharacterMap");
  33.  
  34. // Some global widths for form elements etc..
  35. $width = 590;
  36. $width_img_preview = 125;
  37. $height_img_preview = 125;
  38. $width_icon_preview = 90;
  39. $height_icon_preview = 50;
  40. $widthpx = $width . "px";
  41. $smlwidthpx = ceil($width/3) . "px";
  42. $stdwidthpx = ceil($width/2) . "px";
  43. $bigwidthpx = ceil((2 * $width)/3) . "px";
  44.  
  45. /** New story ID indicator */
  46. ("NEW_STORY", -1);
  47.  
  48. /**
  49. * A class which encapsulates a story or article item. Provides methods
  50. * to get/save to database, edit the story in a popup window, and view it.
  51. * Also provides methods to index/unindex to the search engine.
  52. * @package cm
  53. */
  54. class story extends RenderableObject {
  55. var $story_id = NEW_STORY; // Our unique DB key for the story
  56. var $story_category = false; // The group of stories this belongs to
  57. var $story_category_desc = ""; // Wordy descriptive version of above
  58. var $has_media = true; // By category: associated media
  59. var $has_multimedia = false; // By category: more then one assoc. media
  60. var $has_precis = true; // By category: has a precis
  61. var $has_expiry = true; // By category: has an expiry option
  62. var $has_multilang = true; // By category: can be translated
  63. var $language = 0; // Language this story is in
  64. var $story_headline = ""; // Headline of this story (0 = default)
  65. var $story_precis = ""; // The lead-in section of this story
  66. var $story_content = ""; // The main story body content
  67. var $story_author = ""; // The story author - FK from ax_user.user_id
  68. var $story_author_name = ""; // The story author full name
  69. var $story_type = ""; // The story type - 'a' - Article, 'f' - Feature
  70. var $story_date = ""; // Datetime written, DISPLAY_DATE_FORMAT format
  71. var $story_date_ts = 0; // Unix timestamp of datetime story was written
  72. var $expiry_date = ""; // Datetime to expire, DISPLAY_DATE_FORMAT format
  73. var $expiry_date_ts = 0; // Unix timestamp of datetime story should expire
  74. var $lastmodified = ""; // Datetime last modified, NICE_FULLDATETIME format
  75. var $lastmodified_ts = 0; // Unix timestamp of datetime story last modified
  76. var $story_media = array(); // An array of media associated with this story
  77. var $story_icon; // The catalogitem object of the icon image for this story
  78. var $story_icon_url; // The URL for the icon image for this story
  79. var $visible = false; // True if story is visible on the website
  80. var $story_locs = array(); // An array of locations this story is published to
  81. var $story_translations = array(); // An array of media associated with this story
  82. var $root_translation_id = -1; // Story ID of root (original) of translated stories
  83. var $root_translation_lang; // Language of root (original) of translated stories
  84.  
  85. // Internal Flags and Vars..
  86. var $deleted = false; // True if story has been flagged as deleted
  87. var $info_msg = ""; // Contains info/error message as appropriate
  88. var $newstory = false; // True if we just created this story
  89. var $valid = false; // True if story was retreived successfully
  90. var $storymode = ""; // Mode of action on this story
  91. var $formname = ""; // Name of the form we use
  92. var $bytesize = 0; // Size of article + media in bytes
  93. var $wordcount = 0; // Number of words written
  94. var $microsite_name; // Microsite this story is for (if any)
  95. // .....................................................................
  96. /** Constructor
  97. * @param mixed $id Story ID, or false if not known
  98. * @param mixed $category String category identifier, or false if unknown
  99. * @param mixed $language Integer language code, or false if default
  100. */
  101. function story($id=false, $category=false, $language=false) {
  102. global $RESPONSE;
  103. global $storymode;
  104. global $story_id, $cat, $lang;
  105.  
  106. // Set up our vars..
  107. $this->initialise();
  108.  
  109. // Form..
  110. $this->formname = "storyfm";
  111.  
  112. // Default the mode..
  113. if (!isset($storymode)) $this->storymode = "view";
  114. else $this->storymode = $storymode;
  115.  
  116. // Set the story ID..
  117. if ($id === false) {
  118. if (isset($story_id)) {
  119. $this->story_id = $story_id;
  120. }
  121. }
  122. else {
  123. $this->story_id = $id;
  124. }
  125.  
  126. // Set the category..
  127. if ($category === false) {
  128. if (isset($cat)) {
  129. $this->story_category = $cat;
  130. }
  131. }
  132. else {
  133. $this->story_category = $category;
  134. }
  135.  
  136. // Set the language..
  137. if ($language === false) {
  138. if (isset($lang)) {
  139. $this->language = $lang;
  140. }
  141. }
  142. else {
  143. $this->language = $language;
  144. }
  145.  
  146. // Detect new story creation..
  147. if ($this->story_id === false || $this->story_id == NEW_STORY) {
  148. // Create a brand new one
  149. $this->story_id = get_next_sequencevalue("seq_story_id", "ax_story", "story_id");
  150. $this->story_date_ts = time();
  151. $this->story_date = timestamp_to_displaydate(DISPLAY_DATE_FORMAT, $this->story_date_ts);
  152. $this->newstory = true;
  153. $this->valid = true;
  154. $this->get_author_info();
  155. $this->get_category_info();
  156. $this->get_default_locations();
  157. $this->storymode = "adding";
  158. // Also deal with possible microsite story creation..
  159. if ($RESPONSE->microsites_mode == MICROSITES_ENABLED
  160. && $RESPONSE->microsite_detected != "") {
  161. $this->microsite_name = $RESPONSE->microsite_detected;
  162. debugbr("setting microsite name for new story: $this->microsite_name");
  163. }
  164. }
  165. // Further processing for existing stories..
  166. if (!$this->newstory) {
  167. if ($this->storymode == "adding") {
  168. $this->newstory = true;
  169. $this->valid = true;
  170. // Also deal with possible microsite story creation..
  171. if ($RESPONSE->microsites_mode == MICROSITES_ENABLED
  172. && $RESPONSE->microsite_detected != "") {
  173. $this->microsite_name = $RESPONSE->microsite_detected;
  174. debugbr("setting microsite name for new story: $this->microsite_name");
  175. }
  176. }
  177. else {
  178. // Attempt to get the story
  179. $this->get_story();
  180. }
  181. // Process POST from form..
  182. $this->POSTprocess();
  183.  
  184. // Final get for display..
  185. $this->get_story();
  186. }
  187. } // story
  188. // .....................................................................
  189. /** Initialise local vars.. */
  190.  
  191. function initialise() {
  192. global $RESPONSE;
  193. $this->language = 0;
  194. $this->story_headline = "";
  195. $this->story_content = "";
  196. $this->story_precis = "";
  197. if (isset($RESPONSE)) {
  198. $this->story_author = $RESPONSE->userid;
  199. $this->story_author_name = $RESPONSE->name;
  200. }
  201. else {
  202. $this->story_author = "";
  203. $this->story_author_name = "";
  204. }
  205. $this->story_type = "a";
  206. $this->story_date = "";
  207. $this->story_date_ts = 0;
  208. $this->expiry_date = "";
  209. $this->expiry_date_ts = 0;
  210. $this->lastmodified = "";
  211. $this->lastmodified_ts = 0;
  212. $this->deleted = false;
  213. $this->visible = true;
  214. $this->newstory = false;
  215. $this->info_msg = "";
  216. $this->valid = false;
  217. } // story initialise
  218. // .....................................................................
  219. /**
  220. * Get a story in total. We always access stories by their ID.
  221. * @param mixed $id Story ID, or false if not known
  222. */
  223. function get_story($id=false) {
  224. global $RESPONSE;
  225. $res = false;
  226. if ($id !== false) $this->story_id = $id;
  227. if ($this->story_id !== false) {
  228. $q = "SELECT * FROM ax_story s";
  229. $q .= " WHERE story_id=$this->story_id";
  230. $storyQ = dbrecordset($q);
  231. if ($storyQ->hasdata) {
  232. // Main story content..
  233. $this->language = $storyQ->field("lang_id");
  234. $this->story_category = $storyQ->field("category_id");
  235. $this->story_headline = $storyQ->field("story_headline");
  236. $this->story_precis = $storyQ->field("story_precis");
  237. $this->story_content = $storyQ->field("story_content");
  238. $this->story_author = $storyQ->field("story_author");
  239. $this->story_type = $storyQ->field("story_type");
  240. $this->story_icon_url = $storyQ->field("story_icon_url");
  241. if ($storyQ->field("story_icon") != "") {
  242. $iconitem = new catalogitem($storyQ->field("story_icon"));
  243. if ($iconitem->valid) {
  244. $this->story_icon = new story_media($this->story_id, $iconitem);
  245. }
  246. }
  247. // Dates and flags..
  248. $story_date = $storyQ->field("story_date");
  249. if ($story_date != "") {
  250. $this->story_date = datetime_to_displaydate(DISPLAY_DATE_FORMAT, $story_date);
  251. $this->story_date_ts = datetime_to_timestamp($story_date);
  252. }
  253. $expiry_date = $storyQ->field("expiry_date");
  254. if ($expiry_date != "") {
  255. $this->expiry_date = datetime_to_displaydate(DISPLAY_DATE_FORMAT, $expiry_date);
  256. $this->expiry_date_ts = datetime_to_timestamp($expiry_date);
  257. }
  258. $this->lastmodified = datetime_to_displaydate(NICE_FULLDATETIME, $storyQ->field("last_modified"));
  259. $this->lastmodified_ts = datetime_to_timestamp($storyQ->field("last_modified"));
  260. $this->deleted = $storyQ->istrue("deleted");
  261. $this->visible = $storyQ->istrue("visible");
  262. $res = true;
  263.  
  264. // Now go grab sundry other associated story info..
  265. $this->get_author_info();
  266. $this->get_category_info();
  267. if ($this->has_media) {
  268. $this->get_story_media();
  269. }
  270. $this->get_story_locations();
  271. $this->get_story_metrics();
  272. $this->get_story_microsite();
  273. }
  274. else {
  275. $this->info_msg = "No record of story ID: $this->story_id";
  276. }
  277. }
  278. else {
  279. $this->info_msg = "No story ID given";
  280. }
  281. // Did we succeed..?
  282. $this->valid = $res;
  283. return $res;
  284. } // story get_story
  285. // .....................................................................
  286. /**
  287. * Determine wwhether user can edit this story.
  288. * @return boolean True if user can edit the story, else false.
  289. */
  290. function user_can_edit() {
  291. global $RESPONSE;
  292. $can = false;
  293. if ($RESPONSE->ismemberof_group("Editor")
  294. || ($RESPONSE->ismemberof_group("Author") && $this->story_author == $RESPONSE->userid)
  295. ) {
  296. $can = true;
  297. }
  298. return $can;
  299. } // user_can_edit
  300. // .....................................................................
  301. /**
  302. * Get story author info. Allow override of user id via argument
  303. * passed in, otherwise use the resident story author ID.
  304. * @param string $userid Override user_id to use to get info
  305. * @access private
  306. */
  307. function get_author_info($userid=false) {
  308. if ($userid !== false) {
  309. $story_author = $userid;
  310. }
  311. else {
  312. $story_author = $this->story_author;
  313. }
  314. if ($story_author != "" && $story_author !== false) {
  315. $su = dbrecordset("SELECT * FROM ax_user WHERE user_id='" . escape_string($story_author) . "'");
  316. if ($su->hasdata) {
  317. $this->story_author_name = $su->field("full_name");
  318. $this->story_author = $story_author;
  319. }
  320. }
  321. } // get_author_info
  322. // .....................................................................
  323. /**
  324. * Get story category info. Allow override of category id via argument
  325. * passed in, otherwise use the resident story category ID.
  326. * @param integer $catid Override category_id to use to get info
  327. * @access private
  328. */
  329. function get_category_info($catid=false) {
  330. if ($catid !== false) {
  331. $story_category = $catid;
  332. }
  333. else {
  334. $story_category = $this->story_category;
  335. }
  336. if ($story_category != "" && $story_category !== false) {
  337. $cat = dbrecordset("SELECT * FROM ax_story_category WHERE category_id=$story_category");
  338. if ($cat->hasdata) {
  339. $this->story_category_desc = $cat->field("category_desc");
  340. $this->has_media = $cat->istrue("has_media");
  341. $this->has_multimedia = $cat->istrue("has_multimedia");
  342. $this->has_precis = $cat->istrue("has_precis");
  343. $this->has_expiry = $cat->istrue("has_expiry");
  344. $this->has_multilang = $cat->istrue("has_multilang");
  345. $this->story_category = $story_category;
  346. }
  347. }
  348. } // get_category_info
  349. // .....................................................................
  350. /**
  351. * Get media associated with this story. This should be called after the
  352. * story category info has been ascertained. This method populates the
  353. * class variable 'story_media', an array which contains media catalog
  354. * ID and the filename separated by "|".
  355. * @access private
  356. */
  357. function get_story_media() {
  358. $this->story_media = array();
  359. $q = "SELECT * FROM ax_story_media";
  360. $q .= " WHERE story_id=$this->story_id";
  361. $q .= " ORDER BY display_order";
  362. $sm = dbrecordset($q);
  363. if ($sm->hasdata) {
  364. do {
  365. $cat_id = $sm->field("cat_id");
  366. $media = new story_media($this->story_id);
  367. $media->get_catalogitem($cat_id);
  368. $media->justify = $sm->field("justify");
  369. $media->caption = $sm->field("caption");
  370. $media->width = $sm->field("width");
  371. $media->height = $sm->field("height");
  372. $this->story_media[$cat_id] = $media;
  373. debugbr("adding story media: $cat_id " . $media->catalogitem->filepath, DBG_DEBUG);
  374. } while ($sm->get_next());
  375. }
  376. } // get_story_media
  377. // .....................................................................
  378. /**
  379. * Get the story locations defined for this story. This method
  380. * is an internal one designed to be used to populate the current
  381. * locations to publish the story in.
  382. * @access private
  383. */
  384. function get_story_locations() {
  385. $this->story_locs = array();
  386. $q = "SELECT * FROM ax_story_location";
  387. $q .= " WHERE story_id=$this->story_id";
  388. $loc = dbrecordset($q);
  389. if ($loc->hasdata) {
  390. do {
  391. $locid = $loc->field("location_id");
  392. $this->story_locs[] = $locid;
  393. } while ($loc->get_next());
  394. }
  395. } // get_story_locations
  396. // .....................................................................
  397. /**
  398. * Get the microsite associated with this story, if any. If none, then
  399. * we leave the 'microsite_name' local class variable unset.
  400. * @access private
  401. */
  402. function get_story_microsite() {
  403. global $RESPONSE;
  404. if ($RESPONSE->microsites_mode == MICROSITES_ENABLED) {
  405. if (isset($this->microsite_name)) {
  406. unset($this->microsite_name);
  407. }
  408. $q = "SELECT * FROM ax_microsite_story";
  409. $q .= " WHERE story_id=$this->story_id";
  410. $ms = dbrecordset($q);
  411. if ($ms->hasdata) {
  412. $this->microsite_name = $ms->field("microsite_name");
  413. }
  414. }
  415. } // get_story_microsite
  416. // .....................................................................
  417. /**
  418. * Get the default locations for this story category. This method
  419. * is an internal one designed to be used to populate the initial
  420. * locations to publish a new story to.
  421. * @access private
  422. */
  423. function get_default_locations() {
  424. $this->story_locs = array();
  425. $q = "SELECT * FROM ax_story_category_locs";
  426. $q .= " WHERE category_id=$this->story_category";
  427. $loc = dbrecordset($q);
  428. if ($loc->hasdata) {
  429. do {
  430. $locid = $loc->field("location_id");
  431. $this->story_locs[] = $locid;
  432. } while ($loc->get_next());
  433. }
  434. } // get_default_locations
  435. // .....................................................................
  436. /**
  437. * Get the story locations defined for this story. This method
  438. * is an internal one designed to be used to populate the current
  439. * locations to publish the story in.
  440. * @access private
  441. */
  442. function get_story_metrics() {
  443. global $RESPONSE;
  444. $words = $this->story_headline . $this->story_precis . $this->story_content;
  445. $bytesize = strlen($words);
  446. if (count($this->story_media) > 0) {
  447. foreach ($this->story_media as $media) {
  448. if (isset($media->catalogitem) && $media->catalogitem->filepath != "") {
  449. if (file_exists($RESPONSE->site_docroot . $media->catalogitem->filepath)) {
  450. $bytesize += filesize($RESPONSE->site_docroot . $media->catalogitem->filepath);
  451. }
  452. }
  453. } // foreach
  454. }
  455. $this->bytesize = $bytesize;
  456. $this->wordcount = $this->word_count();
  457. } // get_story_metrics
  458. // .....................................................................
  459. /**
  460. * Get the stories which are translated versions of this one.
  461. * @access private
  462. */
  463. function get_story_translations() {
  464. $this->story_translations = array();
  465. // Find root story info for this set of translations..
  466. debugbr("translation family: this story ID is $this->story_id");
  467. $this->root_translation_id = -1;
  468. $q = "SELECT st.story_id as sid, s.lang_id as lang";
  469. $q .= " FROM ax_story_translation st, ax_story s";
  470. $q .= " WHERE st.translated_story_id=$this->story_id";
  471. $q .= " AND s.story_id=st.story_id";
  472. $q .= " AND s.deleted=FALSE";
  473. $q .= " UNION ";
  474. $q .= "SELECT st.story_id as sid, s.lang_id as lang";
  475. $q .= " FROM ax_story_translation st, ax_story s";
  476. $q .= " WHERE st.story_id=$this->story_id";
  477. $q .= " AND s.story_id=st.story_id";
  478. $q .= " AND s.deleted=FALSE";
  479. $trans = dbrecordset($q);
  480. if ($trans->hasdata) {
  481. $this->root_translation_id = $trans->field("sid");
  482. $this->root_translation_lang = $trans->field("lang");
  483. debugbr("translation story id root = $this->root_translation_id");
  484. // Add root story if it's not us..
  485. if ($this->root_translation_id != $this->story_id) {
  486. debugbr("ADDING translation story id (root)=$this->root_translation_id lang=$this->root_translation_lang");
  487. $this->story_translations[$this->root_translation_id] = $this->root_translation_lang;
  488. }
  489. }
  490. // Now get all translations of the root..
  491. $q = "SELECT st.translated_story_id as sid, s.lang_id as lang";
  492. $q .= " FROM ax_story_translation st, ax_story s";
  493. $q .= " WHERE st.story_id=$this->root_translation_id";
  494. $q .= " AND s.story_id=st.translated_story_id";
  495. $q .= " AND s.deleted=FALSE";
  496. $trans = dbrecordset($q);
  497. if ($trans->hasdata) {
  498. do {
  499. $storyid = $trans->field("sid");
  500. $langid = $trans->field("lang");
  501. // Add story if it's not us..
  502. if ($storyid != $this->story_id) {
  503. debugbr("ADDING translation story id=$storyid lang=$langid");
  504. $this->story_translations[$storyid] = $langid;
  505. }
  506. } while ($trans->get_next());
  507. }
  508. } // get_story_translations
  509. // .....................................................................
  510. /** Index this story to the search engine, if enabled for this website. */
  511.  
  512. function index() {
  513. global $SE_AVAILABLE;
  514. // Deal with indexing if enabled. In this case we then use the unique
  515. // story_id as the index ID, and index the story heading and body text.
  516. // We also categorise it.
  517. if ($SE_AVAILABLE) {
  518. include_once("search-lucene-defs.php");
  519. include_once("search-index-defs.php");
  520. $allcontent[] = $this->story_headline;
  521. $allcontent[] = $this->story_precis;
  522. $allcontent[] = $this->story_content;
  523. $I = new searchengine_indexer();
  524. $I->index_field("category:Text", "news");
  525. $I->index_field("title:Text", $this->story_headline);
  526. $I->index_field("story_date:Date", $this->story_date_ts);
  527. $I->index_field("story_author:Text", $this->story_author);
  528. $I->index_field("story_lang:Text", $this->language);
  529. $I->index_field("story_category:Text", $this->story_category);
  530. $I->index_field("story_type:Text", $this->story_type);
  531. if ($this->story_url != "") {
  532. $I->index_field("story_url:Text", $this->story_url);
  533. }
  534. $I->index_content($this->story_id, strip_tags(implode(" ", $allcontent)));
  535. $I->execute();
  536. }
  537. } // story index
  538. // .....................................................................
  539. /** Un-Index this story from the search engine, if enabled for this website. */
  540.  
  541. function unindex() {
  542. global $SE_AVAILABLE;
  543. if ($SE_AVAILABLE) {
  544. include_once("search-lucene-defs.php");
  545. include_once("search-index-defs.php");
  546. $UI = new searchengine_unindexer();
  547. $UI->unindex($this->story_id);
  548. $UI->execute();
  549. }
  550. } // unindex
  551. // .....................................................................
  552. /** Routine to save the story to the database. */
  553.  
  554. function save_story() {
  555. if ($this->story_id) {
  556. if ($this->newstory) {
  557. $sup = new dbinsert("ax_story");
  558. $sup->set("story_id", $this->story_id);
  559. }
  560. else {
  561. $sup = new dbupdate("ax_story");
  562. }
  563. $sup->set("lang_id", $this->language);
  564. $sup->set("story_headline", $this->story_headline);
  565. $sup->set("story_precis", $this->story_precis);
  566. $sup->set("story_content", $this->story_content);
  567. $sup->set("story_author", ($this->story_author != "") ? $this->story_author : NULLVALUE);
  568. $sup->set("story_type", $this->story_type);
  569. $sup->set("story_icon_url", $this->story_icon_url);
  570. $sup->set("category_id", ($this->story_category !== false) ? $this->story_category : NULLVALUE);
  571. if (isset($this->story_icon) && $this->story_icon !== "") {
  572. $sup->set("story_icon", $this->story_icon->catalogitem->cat_id);
  573. }
  574. else {
  575. $sup->set("story_icon", NULLVALUE);
  576. }
  577. if ($this->story_date_ts == 0) {
  578. $sup->set("story_date", NULLVALUE);
  579. }
  580. else {
  581. $sup->set("story_date", timestamp_to_datetime($this->story_date_ts));
  582. }
  583. if ($this->expiry_date_ts == 0) {
  584. $sup->set("expiry_date", NULLVALUE);
  585. }
  586. else {
  587. $sup->set("expiry_date", timestamp_to_datetime($this->expiry_date_ts));
  588. }
  589. $sup->set("last_modified", 'now()');
  590. $sup->set("visible", $this->visible);
  591. $sup->set("deleted", $this->deleted);
  592. $sup->where("story_id=$this->story_id");
  593. if ($sup->execute()) {
  594. // Index to search engine..
  595. $this->index();
  596. $this->newstory = false;
  597. }
  598. }
  599. } // save_story
  600. // .....................................................................
  601. /** Remove the story from the system. We actually just flag it as
  602. * deleted on the database, and keep the record.
  603. */
  604. function delete_story() {
  605. global $RESPONSE, $CONTEXT;
  606. if ($this->valid && !$this->deleted) {
  607. $del = new dbupdate("ax_story");
  608. $del->set("deleted", true);
  609. $del->where("story_id=$this->story_id");
  610. $this->deleted = $del->execute();
  611. if ($this->deleted) {
  612. if ($RESPONSE->microsites_mode == MICROSITES_ENABLED) {
  613. $msdel = new dbdelete("ax_microsite_story");
  614. $msdel->where("story_id=$this->story_id");
  615. $msdel->execute();
  616. }
  617. $this->unindex();
  618. $this->info_msg = "Story has been marked as deleted";
  619. }
  620. }
  621. } // delete_story
  622. // .....................................................................
  623. /** Process the POST from form. This method deals with POSTed content
  624. * from the edit form.
  625. */
  626. function POSTprocess() {
  627. global $RESPONSE;
  628. global $storysave_x; // Clicked save
  629. global $storyedit_x; // Clicked edit
  630. global $storycancel_x; // Clicked cancel
  631. global $translate_x; // Clicked translate
  632. global $story_headline; // Story headline
  633. global $story_precis; // Story precis/lead-in
  634. global $story_content; // Story content
  635. global $story_media; // Reference to picture, movie etc.
  636. global $story_icon; // Reference to icon catalog item
  637. global $story_icon_url; // URL for story icon
  638. global $uploadmedia; // Uploaded media file present
  639. global $story_locs; // List of locations to publish to
  640. global $caption; // New image caption
  641. global $media_justify; // Image justify setting 'left' or 'right'
  642. global $media_width; // Image width px
  643. global $media_height; // Image height px
  644. global $story_author; // Story author
  645. global $story_type; // Story type
  646. global $story_date; // Story date setting
  647. global $story_language; // Story language setting
  648. global $new_language; // New story langauage - translated
  649. global $expiry_date; // Expiry date setting
  650. global $visible; // Visible flag
  651.  
  652. debugbr("POSTprocess: storymode initial: $this->storymode", DBG_DEBUG);
  653. debugbr("story microsite: '$this->microsite_name'");
  654.  
  655. // Save story
  656. if (isset($storysave_x)) {
  657. if (isset($story_headline)) $this->story_headline = $story_headline;
  658. if (isset($story_precis)) $this->story_precis = $story_precis;
  659. if (isset($story_content)) $this->story_content = $story_content;
  660. if (isset($story_author)) $this->story_author = $story_author;
  661. if (isset($story_type)) $this->story_type = $story_type;
  662. if (isset($story_icon_url)) $this->story_icon_url = $story_icon_url;
  663. if ($this->has_multilang && isset($story_language)) {
  664. $this->language = $story_language;
  665. }
  666.  
  667. // Story dates..
  668. if (isset($story_date)) {
  669. $this->story_date = $story_date;
  670. if ($story_date != "") {
  671. // Convert user-supplied date-time..
  672. $this->story_date_ts = displaydate_to_timestamp($story_date);
  673. }
  674. else {
  675. // Supply default of 'now'. Story date must have a value..
  676. $this->story_date_ts = time();
  677. }
  678. $this->story_date = timestamp_to_displaydate(DISPLAY_DATE_FORMAT, $this->story_date_ts);
  679. }
  680. if ($this->has_expiry && isset($expiry_date)) {
  681. $this->expiry_date = $expiry_date;
  682. if ($expiry_date != "") {
  683. $this->expiry_date_ts = displaydate_to_timestamp($expiry_date);
  684. $this->expiry_date = timestamp_to_displaydate(DISPLAY_DATE_FORMAT, $this->expiry_date_ts);
  685. }
  686. else {
  687. $this->expiry_date_ts = 0;
  688. }
  689. }
  690.  
  691. // Visible flag..
  692. $this->visible = isset($visible);
  693.  
  694. // Story icon
  695. if (isset($story_icon) && $story_icon != "") {
  696. $icon_bits = explode("|", $story_icon);
  697. $cat_id = $icon_bits[0];
  698. $newci = new catalogitem($cat_id);
  699. if ($newci->valid) {
  700. $this->story_icon = new story_media($this->story_id, $newci);
  701. }
  702. }
  703. else {
  704. unset($this->story_icon);
  705. }
  706.  
  707. // Save it if changed..
  708. $this->save_story();
  709.  
  710. // Microsite story link for new stories..
  711. if ($this->storymode == "adding" && isset($this->microsite_name)) {
  712. $mssin = new dbinsert("ax_microsite_story");
  713. $mssin->set("microsite_name", $this->microsite_name);
  714. $mssin->set("story_id", $this->story_id);
  715. $mssin->execute();
  716. }
  717.  
  718. // Media data POSTings..
  719. if ($this->has_media) {
  720. // Some defaults..
  721. if ($media_width == "") $media_width = 0;
  722. if ($media_height == "") $media_height = 0;
  723.  
  724. // Deal with a new media file upload. In this case we
  725. // assume we are just adding, if we have multimedia set
  726. // otherwise we will clear out pre-existing media first..
  727. $smdel = new dbdelete("ax_story_media");
  728. $smdel->where("story_id=$this->story_id");
  729. $smdel->execute();
  730. $this->story_media = array();
  731. if (isset($uploadmedia) && $uploadmedia != "none" && $uploadmedia != "") {
  732. $newci = new catalogitem();
  733. $errmsgs = $newci->upload($caption, $this->category);
  734. if ($newci->valid) {
  735. $smin = new dbinsert("ax_story_media");
  736. $smin->set("story_id", $this->story_id);
  737. $smin->set("cat_id", $newci->cat_id);
  738. $smin->set("caption", $caption);
  739. $smin->set("justify", $media_justify);
  740. $smin->set("width", $media_width);
  741. $smin->set("height", $media_height);
  742. $smin->execute();
  743. $media = new story_media($this->story_id, $newci);
  744. $media->caption = $caption;
  745. $media->justify = $media_justify;
  746. $media->width = $media_width;
  747. $media->height = $media_height;
  748. $this->story_media[$newci->cat_id] = $media;
  749. }
  750. else {
  751. if (count($errmsgs) > 0) {
  752. $this->info_msg = implode("<br>", $errmsgs);
  753. }
  754. }
  755. }
  756. // Otherwise, just re-create the media refs..
  757. else {
  758. $smdel = new dbdelete("ax_story_media");
  759. $smdel->where("story_id=$this->story_id");
  760. $smdel->execute();
  761. // Turn incoming value(s) into an array..
  762. $new_story_media = array();
  763. if (is_array($story_media)) {
  764. $new_story_media = $story_media;
  765. }
  766. elseif ($story_media != "") {
  767. $new_story_media = array($story_media);
  768. }
  769. // Start from scratch and rebuild media array..
  770. $this->story_media = array();
  771. foreach ($new_story_media as $cat_info) {
  772. if ($cat_info != "") {
  773. $cat_bits = explode("|", $cat_info);
  774. $cat_id = $cat_bits[0];
  775. $newci = new catalogitem($cat_id);
  776. if ($newci->valid) {
  777. // Save it to database..
  778. $ssin = new dbinsert("ax_story_media");
  779. $ssin->set("story_id", $this->story_id);
  780. $ssin->set("cat_id", $cat_id);
  781. $ssin->set("caption", $caption);
  782. $ssin->set("justify", $media_justify);
  783. $ssin->set("width", $media_width);
  784. $ssin->set("height", $media_height);
  785. $ssin->execute();
  786. // Save it to local media array too..
  787. $media = new story_media($this->story_id, $newci);
  788. $media->caption = $caption;
  789. $media->justify = $media_justify;
  790. $media->width = $media_width;
  791. $media->height = $media_height;
  792. $this->story_media[$cat_id] = $media;
  793. }
  794. }
  795. } // foreach
  796. }
  797. } // has_media
  798.  
  799. // Story publish to locations..
  800. $sldel = new dbdelete("ax_story_location");
  801. $sldel->where("story_id=$this->story_id");
  802. $sldel->execute();
  803. $this->story_locs = array();
  804. if (isset($story_locs)) {
  805. foreach ($story_locs as $loc_id) {
  806. if ($loc_id != "") {
  807. $slin = new dbinsert("ax_story_location");
  808. $slin->set("story_id", $this->story_id);
  809. $slin->set("location_id", $loc_id);
  810. $slin->execute();
  811. }
  812. }
  813. $this->story_locs = $story_locs;
  814. }
  815. $this->info_msg = "Story was saved";
  816. $this->storymode = "viewagain";
  817. } // storysave_x
  818.  
  819. // Edit story
  820. elseif (isset($storyedit_x)) {
  821. $this->storymode = "edit";
  822. } // storyedit_x
  823.  
  824. // Cancel current mode
  825. elseif (isset($storycancel_x)) {
  826. $this->storymode = "viewagain";
  827. } // storycancel_x
  828.  
  829. // Translate current story into new language.
  830. elseif (isset($translate_x)) {
  831. $translation = $this->get_translation($new_language);
  832. if ($translation !== false) {
  833. $this->get_story($translation);
  834. }
  835. } // translate_x
  836.  
  837. // Remove story
  838. elseif ($this->storymode == "remove") {
  839. $this->delete_story();
  840. $this->storymode = "viewagain";
  841. } // remove
  842. debugbr("POSTprocess: storymode final: $this->storymode", DBG_DEBUG);
  843. } // story POSTprocess
  844. // .....................................................................
  845. /**
  846. * Returns the story_id of a translation of the current story in the
  847. * given language. If it already exists, then it just returns the story
  848. * ID. If it doesn't exist, then it simply makes a copy of this story,
  849. * assigns it the language it _will_ be translated into, and records a
  850. * relationship to the other associated translations in the database table
  851. * 'story_tranlsation'. This latter table allows us to put a list of
  852. * languages (or little country flags) on any stories which have alternatives
  853. * in another language.
  854. * @param integer $language Language to get translated story in
  855. */
  856. function get_translation($language) {
  857. // Check if this story already has a translation available, and
  858. // we just return the translated story id if so..
  859. $this->get_story_translations();
  860. foreach ($this->story_translations as $translated_storyid => $chklang) {
  861. if ($chklang == $language) {
  862. return $translated_storyid;
  863. break;
  864. }
  865. }
  866.  
  867. // Preserve some info for use later on..
  868. $original_story_id = $this->story_id;
  869. $original_translations = $this->story_translations;
  870.  
  871. // Create new story..
  872. start_transaction();
  873. $this->story_id = get_next_sequencevalue("seq_story_id", "ax_story", "story_id");
  874. // Set the new language..
  875. $this->language = $language;
  876. $this->story_date_ts = time();
  877. $this->story_date = timestamp_to_displaydate(DISPLAY_DATE_FORMAT, $this->story_date_ts);
  878. $this->newstory = true;
  879. $this->valid = true;
  880. $this->save_story();
  881.  
  882. // Duplicate media..
  883. $ord = 1;
  884. foreach ($this->story_media as $cat_id => $media) {
  885. $in = new dbinsert("ax_story_media");
  886. $in->set("story_id", $this->story_id);
  887. $in->set("cat_id", $cat_id);
  888. $in->set("caption", $media->caption);
  889. $in->set("width", $media->width);
  890. $in->set("height", $media->height);
  891. $in->set("justify", $media->justify);
  892. $in->set("display_order", $ord++);
  893. $in->execute();
  894. }
  895. // Duplicate sports..
  896. foreach ($this->story_sports as $sport_id) {
  897. $in = new dbinsert("ax_story_sport");
  898. $in->set("story_id", $this->story_id);
  899. $in->set("sport_id", $sport_id);
  900. $in->execute();
  901. }
  902. // Duplicate locations..
  903. $ord = 1;
  904. foreach ($this->story_locs as $loc_id) {
  905. $in = new dbinsert("ax_story_location");
  906. $in->set("story_id", $this->story_id);
  907. $in->set("location_id", $loc_id);
  908. $in->set("display_order", $ord++);
  909. $in->execute();
  910. }
  911. if (commit()) {
  912. // Create translated story relationship..
  913. if ($this->root_translation_id == -1) {
  914. $root_trans_id = $original_story_id;
  915. }
  916. else {
  917. $root_trans_id = $this->root_translation_id;
  918. }
  919. $in = new dbinsert("ax_story_translation");
  920. $in->set("story_id", $root_trans_id);
  921. $in->set("translated_story_id", $this->story_id);
  922. $in->execute();
  923. }
  924. return $this->story_id;
  925. } // translate_into
  926. // .....................................................................
  927. /** Do a re-count of the story words. Set our local variable
  928. * and also return the value as a by-product..
  929. * @return integer Count of words in the story
  930. */
  931. function word_count() {
  932. $words = explode(" ",
  933. $this->story_headline . " "
  934. . $this->story_precis . " "
  935. . $this->story_content
  936. );
  937. return count($words);
  938. } // word_count
  939. // .....................................................................
  940. /** Generate a precis from the story content.
  941. * @param integer $maxwords Maximum number of words for the precis
  942. * @param integer $minwords Minimum number of words for the precis
  943. * @return string The precis
  944. */
  945. function make_precis($maxwords=50, $minwords=5) {
  946. $precis = "";
  947. $patt = "(([\S]+[\s]+){" . $minwords . "," . $maxwords . "})";
  948. $matches = array();
  949. preg_match("/$patt/", strip_tags($this->story_content), $matches);
  950. if (isset($matches[1])) {
  951. $precis = $matches[1];
  952. }
  953. $precis = str_replace("\x0d\x0a", " ", $precis);
  954. return $precis;
  955. } // make_precis
  956. // .....................................................................
  957. /**
  958. * Return the rendering of the story icon (if one exists) either as a
  959. * standard HTML anchor tag if an icon URL exists, or as an image.
  960. * @return string HTML for anchor or image of the story icon
  961. */
  962. function render_story_icon() {
  963. $s = "";
  964. if (isset($this->story_icon) && is_object($this->story_icon)) {
  965. $s = $this->story_icon->catalogitem->Insitu();
  966. if ($this->story_icon_url != "") {
  967. $a = new anchor($this->story_icon_url, $s);
  968. if (stristr($this->story_icon_url, "http")) {
  969. $a->settarget("_new");
  970. }
  971. $s = $a->render();
  972. }
  973. }
  974. return $s;
  975. } // render_story_icon
  976. // .....................................................................
  977. /** Render the story details as an edit form.
  978. * @return string The editform complete.
  979. */
  980. function editform() {
  981. global $RESPONSE;
  982. global $LIBDIR, $CMDIR, $IMAGESDIR;
  983. global $width, $width_img_preview, $height, $height_img_preview;
  984. global $width_icon_preview, $height_icon_preview;
  985. global $widthpx, $smlwidthpx, $stdwidthpx, $bigwidthpx;
  986.  
  987. // CONTROL BUTTONS
  988. $s = "";
  989. if ($this->user_can_edit()) {
  990. $savb = new form_imagebutton("storysave", "Save", "", "$LIBDIR/img/_save.gif", "Save changes", 57, 15);
  991. $canb = new form_imagebutton("storycancel", "Cancel", "", "$LIBDIR/img/_cancel.gif", "Cancel", 57, 15);
  992. if ($this->newstory) {
  993. $canb->set_onclick("window.close()");
  994. }
  995. $s .= $savb->render() . "&nbsp;&nbsp;" . $canb->render();
  996. }
  997. $CONTROL_BUTTONS = $s;
  998.  
  999. $Tst = new table("story");
  1000. $Tst->setpadding(4);
  1001.  
  1002. $rowbg = "axbglite";
  1003.  
  1004. // EDITOR HEADER
  1005. $Thd = new table("editor heading");
  1006. $Thd->tr($rowbg);
  1007. $title = "$this->story_category_desc ";
  1008. if ($this->newstory) {
  1009. $title .= "New Article";
  1010. }
  1011. else {
  1012. $title .= "Editor";
  1013. }
  1014. $Thd->td("<h3>$title</h3>", "axfg");
  1015. $Thd->td($CONTROL_BUTTONS);
  1016. $Thd->td_alignment("right");
  1017. $Tst->tr($rowbg);
  1018. $Tst->td($Thd->render(), "border-bottom:1px solid black");
  1019. $Tst->td_colspan(2);
  1020.  
  1021. // ERRMSG
  1022. if ($this->info_msg != "") {
  1023. $rowbg = ($rowbg == "axbglite") ? "axbgdark" : "axbglite";
  1024. $Tst->tr($rowbg);
  1025. $Tst->td($this->info_msg, "axerror");
  1026. $Tst->td_colspan(2);
  1027. $Tst->td_alignment("center");
  1028. }
  1029.  
  1030. // MICROSITE
  1031. if (isset($this->microsite_name)) {
  1032. $Fld = new form_labelfield("story_microsite", $this->microsite_name);
  1033. $rowbg = ($rowbg == "axbglite") ? "axbgdark" : "axbglite";
  1034. $Tst->tr($rowbg);
  1035. $Tst->td("Microsite:", "axfg");
  1036. $Tst->td($Fld->render());
  1037. }
  1038.  
  1039. // HEADLINE
  1040. $Fld = new form_textfield("story_headline", "Headline", $this->story_headline);
  1041. $Fld->setclass("axtxtbox");
  1042. $Fld->setstyle("width:$widthpx;");
  1043. $rowbg = ($rowbg == "axbglite") ? "axbgdark" : "axbglite";
  1044. $Tst->tr($rowbg);
  1045. $Tst->td("Headline:", "axfg");
  1046. $Tst->td_css("padding-top:10px;");
  1047. $Tst->td($Fld->render());
  1048. $Tst->td_css("padding-top:10px;");
  1049.  
  1050. // PRECIS/LEAD IN
  1051. if ($this->has_precis) {
  1052. $Fld = new form_wysiwygfield("story_precis", "Lead In", $this->story_precis);
  1053. $Fld->setclass("axmemo");
  1054. $Fld->setstyle("width:$widthpx;height:120px;");
  1055. $Fld->set_statusbar(false);
  1056. $Fld->set_toolbar("basic");
  1057. $rowbg = ($rowbg == "axbglite") ? "axbgdark" : "axbglite";
  1058. $Tst->tr($rowbg);
  1059. $Tst->td("Lead In:", "axfg");
  1060. $Tst->td_css("vertical-align:top;padding-top:5px;");
  1061. $Tst->td($Fld->render());
  1062. }
  1063.  
  1064. // STORY AUTHOR
  1065. if ($RESPONSE->ismemberof_group("Editor")) {
  1066. // Editors can change the author..
  1067. $Fld = new form_combofield("story_author", "Author", $this->story_author);
  1068. $Fld->setclass("axcombo");
  1069. $Fld->setstyle("width:$stdwidthpx;");
  1070. $Fld->additem("");
  1071. $q = "SELECT * FROM ax_user u, ax_user_group ug, ax_group g";
  1072. $q .= " WHERE ug.user_id=u.user_id";
  1073. $q .= " AND g.group_id=ug.group_id";
  1074. $q .= " AND g.group_desc IN ('Editor','Author')";
  1075. $q .= " AND u.enabled";
  1076. $q .= " ORDER BY u.full_name";
  1077. $authors = dbrecordset($q);
  1078. if ($authors->hasdata) {
  1079. $Fld->add_querydata($authors, "user_id", "full_name");
  1080. }
  1081. $rowbg = ($rowbg == "axbglite") ? "axbgdark" : "axbglite";
  1082. $Tst->tr($rowbg);
  1083. $Tst->td("Author:", "axfg");
  1084. $Tst->td($Fld->render());
  1085. }
  1086. else {
  1087. // Standard authors can't change by-line..
  1088. $Fld = new form_labelfield("story_author", "<b>$this->story_author_name ($this->story_author)</b>");
  1089. $hid = new form_hiddenfield("story_author", $this->story_author);
  1090. $rowbg = ($rowbg == "axbglite") ? "axbgdark" : "axbglite";
  1091. $Tst->tr($rowbg);
  1092. $Tst->td("Author:", "axfg");
  1093. $Tst->td($Fld->render() . $hid->render());
  1094. }
  1095.  
  1096. // STORY CONTENT
  1097. $Fld = new form_wysiwygfield("story_content", "Article", $this->story_content);
  1098. $Fld->setclass("axmemo");
  1099. $Fld->setstyle("width:$widthpx;height:350px;");
  1100. $Fld->register_plugins("all");
  1101. $Fld->set_toolbar("full");
  1102. $Fld->set_statusbar(false);
  1103. $rowbg = ($rowbg == "axbglite") ? "axbgdark" : "axbglite";
  1104. $Tst->tr($rowbg);
  1105. $Tst->td("Content:", "axfg");
  1106. $Tst->td_css("vertical-align:top;padding-top:5px;");
  1107. $Tst->td($Fld->render());
  1108.  
  1109. // STORY MEDIA
  1110. if ($this->has_media) {
  1111. // CATALOG
  1112. $catalog = new catalog();
  1113. $catalog->search("", array("image"));
  1114.  
  1115. // Media details table..
  1116. $Tmed = new table("storymedia");
  1117. $Tmed->tr();
  1118. $Tmed->setwidth("100%");
  1119.  
  1120. // Find the first (selected) media object $selmedia_first. This object
  1121. // is used extensively below to populate the various form fields. We
  1122. // currently only properly support one object (the first one).
  1123. if (count($this->story_media) > 0) {
  1124. reset($this->story_media);
  1125. list($catid, $selmedia_first) = each($this->story_media);
  1126. }
  1127. else {
  1128. $selmedia_first = new story_media();
  1129. }
  1130. // Media selector..
  1131. $Fld = new form_combofield("story_media", "Media", $selmedia_first->keyinfo());
  1132. $Fld->setclass("axcombo");
  1133. $Fld->setstyle("width:$bigwidthpx;");
  1134. $Fld->additem("", "None");
  1135. foreach ($catalog->catalogitems as $catid => $catitem) {
  1136. if (isset($this->story_media[$catid])) {
  1137. $media = $this->story_media[$catid];
  1138. }
  1139. else {
  1140. $media = new story_media($this->story_id, $catitem);
  1141. $media->caption = $catitem->cat_name;
  1142. }
  1143. $key = $media->keyinfo();
  1144. $label = $media->catalogitem->cat_name;
  1145. if ($label == "") {
  1146. $label = $media->catalogitem->filepath;
  1147. }
  1148. $Fld->additem($key, $label);
  1149. }
  1150. $Fld->set_onchange("imgPreview(this.options[this.selectedIndex].value)");
  1151. $rowbg = ($rowbg == "axbglite") ? "axbgdark" : "axbglite";
  1152. $Tmed->tr($rowbg);
  1153. $Tmed->td($Fld->render());
  1154. $Tmed->td_alignment("", "top");
  1155.  
  1156. // Create a preview image..
  1157. $imgFld = new img(
  1158. $selmedia_first->catalogitem->filepath,
  1159. "preview",
  1160. "Preview",
  1161. $width_img_preview,
  1162. $height_img_preview
  1163. );
  1164. $imgFld->setalign("right");
  1165. $imgFld->sethspace(4);
  1166. $Tmed->td($imgFld->render());
  1167. $Tmed->td_alignment("right", "top");
  1168. $Tmed->td_rowspan(4);
  1169.  
  1170. // Width and Height override fields
  1171. $sizes_defaulted = ($selmedia_first->width == 0 || $selmedia_first->height == 0);
  1172. if ($sizes_defaulted) {
  1173. $width = $selmedia_first->catalogitem->width;
  1174. $height = $selmedia_first->catalogitem->height;
  1175. }
  1176. else {
  1177. $width = $selmedia_first->width;
  1178. $height = $selmedia_first->height;
  1179. }
  1180. $Tin = new table();
  1181. $Tin->tr();
  1182. $wFld = new form_textfield("media_width", "Width", $width);
  1183. $wFld->setclass("axnumbox");
  1184. $wFld->setstyle("width:50px");
  1185. $hFld = new form_textfield("media_height", "Height", $height);
  1186. $hFld->setclass("axnumbox");
  1187. $hFld->setstyle("width:50px");
  1188. $dFld = new form_checkbox("media_size_default");
  1189. $dFld->setclass("axchkbox");
  1190. $dFld->checked = ($sizes_defaulted === true);
  1191. if ($sizes_defaulted) {
  1192. $wFld->disabled = true;
  1193. $hFld->disabled = true;
  1194. }
  1195. $dFld->set_onclick("defSizingToggle(this)");
  1196. $Tin->td("Sizing:", "axfg");
  1197. $Tin->td($wFld->render() . "&nbsp;x&nbsp;" . $hFld->render() . "&nbsp;&nbsp;Default&nbsp;" . $dFld->render(), "axfg");
  1198. $Tin->set_width_profile("20%,80%");
  1199. $Tmed->tr($rowbg);
  1200. $Tmed->td($Tin->render());
  1201.  
  1202. // Image justify setting
  1203. $Fld = new form_combofield("media_justify", "Justify", $selmedia_first->justify);
  1204. $Fld->setclass("axcombo");
  1205. $Fld->setstyle("width:100px");
  1206. $Fld->additem("", "default");
  1207. $Fld->additem("left", "Left");
  1208. $Fld->additem("right", "Right");
  1209. $Tin = new table();
  1210. $Tin->td("Justify:", "axfg");
  1211. $Tin->td($Fld->render());
  1212. $Tin->set_width_profile("20%,80%");
  1213. $Tmed->tr($rowbg);
  1214. $Tmed->td($Tin->render());
  1215.  
  1216. // File upload field - allows them to add media on the
  1217. // fly to go with a story..
  1218. $Fld = new form_fileuploadfield("uploadmedia", "Upload");
  1219. $Fld->setclass("axtxtbox");
  1220. $Fld->setstyle("width:$smlwidthpx;");
  1221. $Tmed->tr($rowbg);
  1222. $Tmed->td($Fld->render());
  1223.  
  1224. // Now we render the above sub-table $Tmed inside the main table..
  1225. $Tst->tr($rowbg);
  1226. $Tst->td("Image:", "axfg");
  1227. $Tst->td_css("vertical-align:top;padding-top:5px;");
  1228. $Tst->td($Tmed->render());
  1229.  
  1230. // CAPTION
  1231. // NB: We kinda support multiple media, but the issue of them
  1232. // each having a separate caption is not resolved in this current
  1233. // implementation - recommend using a recmaintainer for that
  1234. // when the time comes.
  1235. $Fld = new form_textfield("caption", "Caption", $selmedia_first->caption);
  1236. $Fld->setclass("axtxtbox");
  1237. $Fld->setstyle("width:$stdwidthpx;");
  1238. $Tst->tr($rowbg);
  1239. $Tst->td("Image Caption:", "axfg");
  1240. $Tst->td($Fld->render());
  1241.  
  1242. $Tmed = new table("storyicon");
  1243. $Tmed->tr();
  1244. $Tmed->setwidth("100%");
  1245. if (isset($this->story_icon)) {
  1246. $selicon_first = $this->story_icon;
  1247. }
  1248. else {
  1249. $selicon_first = new story_media();
  1250. }
  1251. // Icon selector..
  1252. $Fld = new form_combofield("story_icon", "Icon", $selicon_first->keyinfo());
  1253. $Fld->setclass("axcombo");
  1254. $Fld->setstyle("width:$bigwidthpx;");
  1255. $Fld->additem("", "None");
  1256. foreach ($catalog->catalogitems as $catid => $catitem) {
  1257. $icon = new story_media($this->story_id, $catitem);
  1258. $icon->caption = $catitem->cat_name;
  1259. $key = $icon->keyinfo();
  1260. $label = $icon->catalogitem->cat_name;
  1261. if ($label == "") {
  1262. $label = $icon->catalogitem->filepath;
  1263. }
  1264. $Fld->additem($key, $label);
  1265. }
  1266. $Fld->set_onchange("iconPreview(this.options[this.selectedIndex].value)");
  1267. $rowbg = ($rowbg == "axbglite") ? "axbgdark" : "axbglite";
  1268. $Tmed->tr($rowbg);
  1269. $Tmed->td($Fld->render());
  1270. $Tmed->td_alignment("", "top");
  1271. // Create a preview icon..
  1272. $imgFld = new img(
  1273. $selicon_first->catalogitem->filepath,
  1274. "iconpreview",
  1275. "Icon Preview",
  1276. $width_icon_preview,
  1277. $height_icon_preview
  1278. );
  1279. $imgFld->setalign("right");
  1280. $imgFld->sethspace(4);
  1281. $Tmed->td($imgFld->render());
  1282. $Tmed->td_alignment("right", "top");
  1283. $Tmed->td_rowspan(2);
  1284. // Now we render the above sub-table $Tmed inside the main table..
  1285. $Tst->tr($rowbg);
  1286. $Tst->td("Icon:", "axfg");
  1287. $Tst->td($Tmed->render());
  1288. // Icon URL entry field
  1289. $Fld = new form_textfield("story_icon_url", "Url", $this->story_icon_url);
  1290. $Fld->setclass("axtxtbox");
  1291. $Fld->setstyle("width:$stdwidthpx");
  1292. $Tst->tr($rowbg);
  1293. $Tst->td("Link to:", "axfg");
  1294. $Tst->td($Fld->render());
  1295.  
  1296. // This allows us to preview images without refresh..
  1297. $RESPONSE->head->add_script(
  1298. "function imgPreview(key) {\n"
  1299. . " var keyparts=key.split('|');\n"
  1300. . " var imgfile=keyparts[1];\n"
  1301. . " if (imgfile!='') {\n"
  1302. . " document.$this->formname.preview.src=imgfile;\n"
  1303. . " }\n"
  1304. . "}\n"
  1305. . "function iconPreview(key) {\n"
  1306. . " var keyparts=key.split('|');\n"
  1307. . " var iconfile=keyparts[1];\n"
  1308. . " if (iconfile!='') {\n"
  1309. . " document.$this->formname.iconpreview.src=iconfile;\n"
  1310. . " }\n"
  1311. . "}\n"
  1312. . "function defSizingToggle(chkbox) {\n"
  1313. . " if (chkbox.checked) {\n"
  1314. . " document.$this->formname.media_width.value='';\n"
  1315. . " document.$this->formname.media_width.disabled=true;\n"
  1316. . " document.$this->formname.media_height.value='';\n"
  1317. . " document.$this->formname.media_height.disabled=true;\n"
  1318. . " }\n"
  1319. . " else {\n"
  1320. . " document.$this->formname.media_width.disabled=false;\n"
  1321. . " document.$this->formname.media_height.disabled=false;\n"
  1322. . " }\n"
  1323. . "}\n"
  1324. );
  1325. }
  1326.  
  1327. // STORY DATE
  1328. $Fld = new form_textfield("story_date", "Article date", $this->story_date);
  1329. $Fld->setclass("axdatetime");
  1330. $Fld->setstyle("width:$smlwidthpx;");
  1331. $Fld->set_onblur("isNonBlank(this, 'Please fill in a story date.');");
  1332. $rowbg = ($rowbg == "axbglite") ? "axbgdark" : "axbglite";
  1333. $Tst->tr($rowbg);
  1334. $Tst->td("Article Date:", "axfg");
  1335. $Tst->td($Fld->render() . "&nbsp;<small><i>eg: dd/mm/yyyy [hh:mm]</i></small>");
  1336.  
  1337. // EXPIRY DATE
  1338. if ($this->has_expiry) {
  1339. $Fld = new form_textfield("expiry_date", "Expiry date", $this->expiry_date);
  1340. $Fld->setclass("axdatetime");
  1341. $Fld->setstyle("width:$smlwidthpx;");
  1342. $rowbg = ($rowbg == "axbglite") ? "axbgdark" : "axbglite";
  1343. $Tst->tr($rowbg);
  1344. $Tst->td("Expiry Date:", "axfg");
  1345. $Tst->td($Fld->render());
  1346. }
  1347.  
  1348. // STORY TYPE
  1349. $Fld = new form_combofield("story_type", "Article type", $this->story_type);
  1350. $Fld->setclass("axcombo");
  1351. $Fld->setstyle("width:$smlwidthpx;");
  1352. $Fld->additem("n", "News item");
  1353. $rowbg = ($rowbg == "axbglite") ? "axbgdark" : "axbglite";
  1354. $Tst->tr($rowbg);
  1355. $Tst->td("Article Type:", "axfg");
  1356. $Tst->td($Fld->render());
  1357.  
  1358. // LANGUAGE
  1359. if ($this->has_multilang) {
  1360. $this->get_story_translations();
  1361. $Tlng = new table("language");
  1362.  
  1363. $Fld = new form_combofield("story_language", "", $this->language);
  1364. $Fld->setclass("axcombo");
  1365. $Fld->setstyle("width:$smlwidthpx;");
  1366.  
  1367. // Fill the dropdown selector with all possibilities..
  1368. $q = "SELECT * FROM ax_language";
  1369. $q .= " WHERE enabled=TRUE";
  1370. $q .= " ORDER BY display_order";
  1371. $langs = dbrecordset($q);
  1372. if ($langs->hasdata) {
  1373. $Fld->add_querydata($langs, "lang_id", "lang_desc");
  1374. }
  1375. $rowbg = ($rowbg == "axbglite") ? "axbgdark" : "axbglite";
  1376. $Tlng->tr($rowbg);
  1377. $Tlng->td($Fld->render());
  1378.  
  1379. $Fld = new form_combofield("new_language");
  1380. $Fld->setclass("axcombo");
  1381. $Fld->setstyle("width:$smlwidthpx;");
  1382. $Fld->additem("", "&mdash; Translate into &mdash;");
  1383. // Determine languages already translated..
  1384. $already_translated = array($this->language);
  1385. foreach ($this->story_translations as $sid => $langid) {
  1386. $already_translated[] = $langid;
  1387. }
  1388. $q = "SELECT * FROM ax_language WHERE enabled=TRUE";
  1389. if (count($already_translated) > 0) {
  1390. $langlist = implode(",", $already_translated);
  1391. if ($langlist != "") {
  1392. $q .= " AND NOT lang_id IN (" . implode(",", $already_translated) . ")";
  1393. }
  1394. }
  1395. $q .= " ORDER BY display_order";
  1396. $tlangs = dbrecordset($q);
  1397. if ($tlangs->hasdata) {
  1398. $Fld->add_querydata($tlangs, "lang_id", "lang_desc");
  1399. }
  1400. $transbtn = new form_imagebutton("translate", "", "", "$LIBDIR/img/_translate.gif", "Translate", 77, 15);
  1401. $Tlng->td($Fld->render());
  1402. $Tlng->td_alignment("right");
  1403. $Tlng->td($transbtn->render());
  1404. $Tlng->td_alignment("left");
  1405.  
  1406. if (count($this->story_translations) > 0) {
  1407. $translist = array();
  1408. foreach ($this->story_translations as $trans_story_id => $trans_lang_id) {
  1409. $lq = dbrecordset("SELECT * FROM ax_language WHERE lang_id=$trans_lang_id");
  1410. if ($lq->hasdata) {
  1411. $translist[] = ucfirst($lq->field("lang_desc"));
  1412. }
  1413. }
  1414. if (count($translist) > 0) {
  1415. $Tlng->tr($rowbg);
  1416. $Tlng->td("Existing Translations: " . implode("&nbsp;|&nbsp;", $translist));
  1417. $Tlng->td_colspan(2);
  1418. }
  1419. }
  1420. $Tst->tr($rowbg);
  1421. $Tst->td("Language:", "axfg");
  1422. $Tst->td_alignment("", "top");
  1423. $Tst->td($Tlng->render());
  1424. }
  1425.  
  1426. // VISIBLE
  1427. $Fld = new form_checkbox("visible", "Visible");
  1428. $Fld->checked = $this->visible;
  1429. $Fld->setclass("axchkbox");
  1430. $rowbg = ($rowbg == "axbglite") ? "axbgdark" : "axbglite";
  1431. $Tst->tr($rowbg);
  1432. $Tst->td("Visible:", "axfg");
  1433. $Tst->td($Fld->render());
  1434.  
  1435. // STORY LOCATIONS
  1436. $Fld = new form_combofield("story_locs", "", $this->story_locs);
  1437. $Fld->multiselect = true;
  1438. $Fld->setclass("axlistbox");
  1439. $Fld->size = 6;
  1440. $Fld->setstyle("width:$stdwidthpx;");
  1441. $q = "SELECT * FROM ax_content_location";
  1442. $q .= " WHERE enabled=TRUE";
  1443. $q .= " ORDER BY location_name";
  1444. $locs = dbrecordset($q);
  1445. if ($locs->hasdata) {
  1446. $Fld->add_querydata($locs, "location_id", "location_name");
  1447. }
  1448. $rowbg = ($rowbg == "axbglite") ? "axbgdark" : "axbglite";
  1449. $Tst->tr($rowbg);
  1450. $Tst->td("Publish to:", "axfg");
  1451. $Tst->td_alignment("", "top");
  1452. $Tst->td($Fld->render());
  1453.  
  1454. // LAST MODIFIED
  1455. $rowbg = ($rowbg == "axbglite") ? "axbgdark" : "axbglite";
  1456. $Tst->tr($rowbg);
  1457. $Tst->td("Last modified:", "axfg");
  1458. $Tst->td($this->lastmodified);
  1459.  
  1460. // Rule-off row..
  1461. $Tst->tr("axfoot");
  1462. $Tst->td("", "axfoot");
  1463. $Tst->td_colspan(2);
  1464.  
  1465. $Tst->set_width_profile("20%,80%");
  1466.  
  1467. // Add field validation scripts..
  1468. $RESPONSE->add_scriptsrc("$LIBDIR/js/fieldvalidation.js");
  1469.  
  1470. return $Tst->render();
  1471. } // editform
  1472. // .....................................................................
  1473. /** Render the story as a maintainer reader would view it. Note that this
  1474. * is not a fully dressed-up story viewer. It is designed as a view that
  1475. * a story administrator would see, showing all the technical bits and
  1476. * pieces such as story byte-size etc. You should create your own viewer
  1477. * for rendering stories 'prettily' on your website.
  1478. * @return string The HTML for the view story content.
  1479. */
  1480. function view() {
  1481. global $RESPONSE;
  1482. global $LIBDIR;
  1483.  
  1484. // CONTROL BUTTONS
  1485. $s = "";
  1486. // Buttons for administrators and editors only..
  1487. $doneb = new form_imagebutton("closewin", "Close", "", "$LIBDIR/img/_done.gif", "Close viewer", 57, 15);
  1488. $doneb->set_onclick("window.close()");
  1489. if ($this->user_can_edit()) {
  1490. $editb = new form_imagebutton("storyedit", "Edit", "", "$LIBDIR/img/_edit.gif", "Edit this article", 42, 15);
  1491. $remvb = new form_imagebutton("storyremove", "Delete", "", "$LIBDIR/img/_delete.gif", "Delete this article", 57, 15);
  1492. $remvb->set_onclick("remove_confirm()");
  1493. $s .= $editb->render() . "&nbsp;&nbsp;" . $remvb->render();
  1494. // Removal protection..
  1495. $RESPONSE->head->add_script(
  1496. "function remove_confirm() {\n"
  1497. . " var msg = '\\n\\nWARNING: Do you really want to delete\\n';\n"
  1498. . " msg += 'the article. This is irrevocable.\\n';"
  1499. . " rc = confirm(msg);\n"
  1500. . " if (rc) {\n"
  1501. . " document.$this->formname.storymode.value='remove';\n"
  1502. . " document.$this->formname.submit();\n"
  1503. . " }\n"
  1504. . " else alert('Delete is cancelled.');\n"
  1505. . "}\n"
  1506. );
  1507. }
  1508. if ($s != "") $s .= "&nbsp;&nbsp;";
  1509. $s .= $doneb->render();
  1510. $CONTROL_BUTTONS = $s;
  1511.  
  1512. $Tvw = new table("storyviewer");
  1513. $Tvw->setpadding(3);
  1514.  
  1515. $rowbg = "axbgdark";
  1516.  
  1517. // EDITOR HEADER
  1518. $Thd = new table("viewerhead");
  1519. $Thd->tr($rowbg);
  1520. $title = $this->story_category_desc;
  1521. if (isset($this->microsite_name)) {
  1522. $title .= "<br><small>(Microsite $this->microsite_name)</small>";
  1523. }
  1524. $Thd->td("<h3>$title</h3>", "axfg");
  1525. $Thd->td($CONTROL_BUTTONS);
  1526. $Thd->td_alignment("right", "bottom");
  1527.  
  1528. if ($this->language != 0) {
  1529. $lq = dbrecordset("SELECT * FROM ax_language WHERE lang_id=$this->language");
  1530. if ($lq->hasdata) {
  1531. $Thd->tr($rowbg);
  1532. $Thd->td("in " . $lq->field("lang_desc"));
  1533. $Thd->td_colspan(2);
  1534. }
  1535. }
  1536.  
  1537. $Tvw->tr($rowbg);
  1538. $Tvw->td($Thd->render(), "border-bottom:1px solid black");
  1539. $Tvw->td_colspan(2);
  1540.  
  1541. if ($this->info_msg != "") {
  1542. $Tvw->tr($rowbg);
  1543. $Tvw->td($this->info_msg, "axerror");
  1544. $Tvw->td_colspan(2);
  1545. $Tvw->td_alignment("center");
  1546. }
  1547.  
  1548. // HEADLINE, BY-LINE, STORY TYPE & WORDCOUNT
  1549. // STORY TYPE
  1550. switch ($this->story_type) {
  1551. case "n":
  1552. $type = "News article";
  1553. break;
  1554. default:
  1555. $type = "";
  1556. }
  1557.  
  1558. $Thd = new table("masthead");
  1559. $Thd->tr($rowbg);
  1560. $Thd->td("<h2>" . $this->story_headline . "</h2>",
  1561. "vertical-align:bottom;padding-bottom:0px;margin-bottom:0px;"
  1562. );
  1563. $Thd->td($type);
  1564. $Thd->td_alignment("right");
  1565. $Thd->tr($rowbg);
  1566. $byline = "by ";
  1567. $byline .= ($this->story_author_name != "") ? $this->story_author_name : "(anonymous)";
  1568. $Thd->td("<h6>$byline</h6>",
  1569. "vertical-align:top;padding-bottom:5px;"
  1570. );
  1571. $Thd->td($this->wordcount . " words (" . nicebytesize($this->bytesize) . ")");
  1572. $Thd->td_alignment("right");
  1573. if (isset($this->story_icon)) {
  1574. $Thd->tr();
  1575. $Thd->td($this->render_story_icon());
  1576. $Thd->td_colspan(2);
  1577. }
  1578. $Tvw->tr($rowbg);
  1579. $Tvw->td($Thd->render());
  1580. $Tvw->td_colspan(2);
  1581.  
  1582. // STORY DATE & EXPIRY DATE
  1583. $Tvw->tr($rowbg);
  1584. $Tvw->td( timestamp_to_displaydate(NICE_FULLDATETIME, $this->story_date_ts) );
  1585. if ($this->has_expiry && $this->expiry_date != "") {
  1586. if ($this->expiry_date_ts - $this->story_date_ts > 0) {
  1587. $Tvw->td("expires on " . timestamp_to_displaydate(NICE_FULLDATETIME, $this->expiry_date_ts));
  1588. }
  1589. else {
  1590. $Tvw->td("expired as of " . timestamp_to_displaydate(NICE_FULLDATETIME, $this->expiry_date_ts), "axhl");
  1591. }
  1592. $Tvw->td_alignment("right");
  1593. }
  1594. else {
  1595. $Tvw->td("&nbsp;");
  1596. }
  1597.  
  1598. // PUBLISHING STATUS
  1599. $status = "<b>Published to:</b>&nbsp;";
  1600. if (!$this->visible) {
  1601. $status .= "Currently hidden";
  1602. }
  1603. else {
  1604. if (count($this->story_locs) == 0) {
  1605. $status .= "No location is selected";
  1606. }
  1607. else {
  1608. $q .= "SELECT * FROM ax_content_location";
  1609. $q .= " WHERE location_id in (" . implode(",", $this->story_locs) . ")";
  1610. $locs = dbrecordset($q);
  1611. if ($locs->hasdata) {
  1612. $locnames = array();
  1613. do {
  1614. $locnames[] = $locs->field("location_name");
  1615. } while ($locs->get_next());
  1616. $status .= implode(", ", $locnames);
  1617. }
  1618. }
  1619. }
  1620. $Tvw->tr($rowbg);
  1621. $Tvw->td($status, "padding-top:5px;padding-bottom:5px;border-top:1px solid black");
  1622. $Tvw->td_colspan(2);
  1623.  
  1624. // LEAD-IN & STORY CONTENT
  1625. $rowbg = ($rowbg == "axbglite") ? "axbgdark" : "axbglite";
  1626. $Tvw->tr($rowbg);
  1627. //$content = $this->story_precis . " " . $this->story_content;
  1628. $media_content = "";
  1629. if ($this->has_media) {
  1630. if (count($this->story_media) > 0) {
  1631. foreach ($this->story_media as $cat_id => $media) {
  1632. $width = ($media->width > 0) ? $media->width : $media->catalogitem->width;
  1633. $height = ($media->height > 0) ? $media->height : $media->catalogitem->height;
  1634. $caption = ($media->caption != "") ? $media->caption : $media->catalogitem->cat_name;
  1635. $pic = new img(
  1636. $media->catalogitem->filepath,
  1637. $caption,
  1638. $caption,
  1639. ($width > 0 ? $width : false),
  1640. ($height > 0 ? $height : false)
  1641. );
  1642. $pic->setalign(($media->justify != "") ? $media->justify : "right");
  1643. $pic->setstyle("padding:2px");
  1644. $media_content .= $pic->render();
  1645. } // foreach
  1646. }
  1647. }
  1648. // Content..
  1649. if (trim($this->story_precis) != "") {
  1650. $content .= str_replace("\r\n\r\n", "<p>", trim($this->story_precis));
  1651. }
  1652. if (trim($media_content) != "") {
  1653. $content .= $media_content;
  1654. }
  1655. if (trim($this->story_content) != "") {
  1656. $content .= str_replace("\r\n\r\n", "<p>", trim($this->story_content));
  1657. }
  1658. $Tvw->td($content, "padding-top:20px;padding-bottom:50px;border-top:1px solid black");
  1659. $Tvw->td_colspan(2);
  1660.  
  1661. // TRANSLATIONS
  1662. $this->get_story_translations();
  1663. if (count($this->story_translations) > 0) {
  1664. $RESPONSE->head->add_script(
  1665. "function reloadViewer(url) {\n"
  1666. . " document.location=url;\n"
  1667. . "}\n"
  1668. );
  1669. $translinks = array();
  1670. foreach ($this->story_translations as $trans_story_id => $trans_lang_id) {
  1671. $lq = dbrecordset("SELECT * FROM ax_language WHERE lang_id=$trans_lang_id");
  1672. if ($lq->hasdata) {
  1673. $auth_code = $RESPONSE->get_auth_code();
  1674. $shref = "/story-viewer.php";
  1675. $shref = href_addparm($shref, "story_id", $trans_story_id);
  1676. $shref = href_addparm($shref, "auth_code", $auth_code);
  1677. $href = "javascript:reloadViewer('$shref')";
  1678. $translink = new anchor($href, ucfirst($lq->field("lang_desc")));
  1679. $translinks[] = $translink->render();
  1680. }
  1681. }
  1682. if (count($translinks) > 0) {
  1683. $rowbg = ($rowbg == "axbglite") ? "axbgdark" : "axbglite";
  1684. $Tvw->tr($rowbg);
  1685. $Tvw->td("Translations: " . implode("&nbsp;|&nbsp;", $translinks), "border-top:1px solid black");
  1686. $Tvw->td_colspan(2);
  1687. }
  1688. }
  1689.  
  1690. // LAST MODIFIED
  1691. $rowbg = ($rowbg == "axbglite") ? "axbgdark" : "axbglite";
  1692. $Tvw->tr($rowbg);
  1693. $Tvw->td("Last modified:&nbsp;$this->lastmodified",
  1694. "border-top:1px solid black"
  1695. );
  1696. $Tvw->td("#$this->story_id", "border-top:1px solid black");
  1697. $Tvw->td_alignment("right");
  1698.  
  1699. // Rule-off row..
  1700. $Tvw->tr("axfoot");
  1701. $Tvw->td("", "axfoot");
  1702. $Tvw->td_colspan(2);
  1703.  
  1704. return $Tvw->render();
  1705. } // view
  1706. // .....................................................................
  1707. /**
  1708. * Return the content of this story formatted for plaintext display
  1709. * @param integer $wrapchars Number of characters to wrap the lines at
  1710. */
  1711. function plaintext_content($wrapchars=0) {
  1712. // Join all hard-breaks into single lines..
  1713. $content = str_replace("\n", " ", $this->story_content);
  1714. // Split into paragraphs..
  1715. $paras = explode("<p>", $content);
  1716. // Wrap each paragrph if required..
  1717. if ($wrapchars > 0) {
  1718. $newparas = array();
  1719. foreach ($paras as $para) {
  1720. $para = wordwrap($para, $wrapchars, "\r\n");
  1721. $newparas[] = $para;
  1722. }
  1723. $paras = $newparas;
  1724. }
  1725. // Join up into multiple paragraphs split by CRLF..
  1726. $content = strip_tags( implode("\r\n\r\n", $paras) );
  1727. return $content;
  1728. } // plaintext_content
  1729. // .....................................................................
  1730. /** Render the story. We render the story as a table within a form containing all
  1731. * the form elements required to manipulate the story content, email it to
  1732. * someone, save it, and delete it etc...
  1733. * @return string The HTML for edit or view.
  1734. */
  1735. function html() {
  1736. global $RESPONSE;
  1737. // HIDDEN FIELDS
  1738. $cathid = new form_hiddenfield("cat", $this->story_category);
  1739. $authhid = new form_hiddenfield("auth_code", $RESPONSE->auth_code);
  1740. $modehid = new form_hiddenfield("storymode", $this->storymode);
  1741. $sidhid = new form_hiddenfield("story_id", $this->story_id);
  1742.  
  1743. // STORY FORM, VIEW or EDIT..
  1744.  
  1745. switch ($this->storymode) {
  1746. case "edit":
  1747. case "adding":
  1748. $story_form = new multipart_form($this->formname);
  1749. $story_form->add_text($this->editform());
  1750. break;
  1751. default:
  1752. $story_form = new form($this->formname);
  1753. $story_form->add_text($this->view());
  1754. } // switch
  1755.  
  1756. // Render hidden fields too..
  1757. $story_form->add($cathid);
  1758. $story_form->add($authhid);
  1759. $story_form->add($modehid);
  1760. $story_form->add($sidhid);
  1761.  
  1762. return $story_form->render();
  1763. } // story html
  1764.  
  1765.  
  1766.  
  1767. } // story class
  1768. // -----------------------------------------------------------------------
  1769.  
  1770. /**
  1771. * A container class for media item associated with a story. Contains
  1772. * a single piece of media which is associated with this story.
  1773. * @package cm
  1774. */
  1775. class story_media {
  1776. /** ID of story this media belongs to */
  1777.  
  1778. var $story_id = false;
  1779. /** The catalogitem object */
  1780.  
  1781. var $catalogitem;
  1782. /** The caption for this item */
  1783.  
  1784. var $caption = "";
  1785. /** The way to justify this item */
  1786.  
  1787. var $justify = "";
  1788. /** Local override width */
  1789.  
  1790. var $width = 0;
  1791. /** Local override height */
  1792.  
  1793. var $height = 0;
  1794. // .....................................................................
  1795. /**
  1796. * Create a new piece of story media. This comprises a catalogitem
  1797. * object, and a set of methods to access it.
  1798. * @param mixed $id Story ID, or false if not known
  1799. * @param mixed $item Object catalogitem, or false if initially undefined
  1800. */
  1801. function story_media($story_id=false, $item=false) {
  1802. if ($story_id !== false) {
  1803. $this->story_id = $story_id;
  1804. }
  1805. if ($item !== false && is_object($item)) {
  1806. $this->catalogitem = $item;
  1807. }
  1808. else {
  1809. $this->catalogitem = new catalogitem();
  1810. }
  1811. } // story_media
  1812. // .....................................................................
  1813. /**
  1814. * Define this story media object from the given catalog item key. This
  1815. * will obtain the given piece of catalog media from the database and
  1816. * assign the object variables accordingly.
  1817. * @param integer $catid Catalog item ID to obtain
  1818. */
  1819. function get_catalogitem($catid) {
  1820. $this->catalogitem = new catalogitem($catid);
  1821. } // get_catalogitem
  1822. // .....................................................................
  1823. /**
  1824. * Return the keyinfo string for this media item. This is encoded
  1825. * as follows, and is used in select combos:
  1826. * 'cat_id|filepath|width|height|justify'
  1827. */
  1828. function keyinfo() {
  1829. $info = array();
  1830. if (isset($this->catalogitem)) {
  1831. $info[] = $this->catalogitem->cat_id;
  1832. $info[] = $this->catalogitem->filepath;
  1833. $info[] = ($this->width != 0) ? $this->width : $this->catalogitem->width;
  1834. $info[] = ($this->height != 0) ? $this->height : $this->catalogitem->height;
  1835. $info[] = $this->justify;
  1836. }
  1837. return implode("|", $info);
  1838. } // keyinfo
  1839.  
  1840. } // story_media class
  1841. // -----------------------------------------------------------------------
  1842.  
  1843. ?>

Documentation generated by phpDocumentor 1.3.0RC3