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 Lucene.
  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='" . addslashes($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 Lucene, if enabled for this website. */
  511.  
  512. function index() {
  513. global $CONTEXT, $LIBDIR;
  514. // Deal with Lucene indexing if enabled. In this case we then
  515. // use the unique story_id as the index ID, and index the story
  516. // heading and body text. We also categorise it..
  517. if ( isset($CONTEXT) && $CONTEXT->configvalue("Lucene Site Indexing") ) {
  518. include_once("lucene-defs.php");
  519. $allcontent[] = $this->story_headline;
  520. $allcontent[] = $this->story_precis;
  521. $allcontent[] = $this->story_content;
  522. $I = new lucene_indexmsg();
  523. $I->index_field("category:Text", "news");
  524. $I->index_field("title:Text", $this->story_headline);
  525. $I->index_field("story_date:Date", $this->story_date_ts);
  526. $I->index_field("story_author:Text", $this->story_author);
  527. $I->index_field("story_lang:Text", $this->language);
  528. $I->index_field("story_category:Text", $this->story_category);
  529. $I->index_field("story_type:Text", $this->story_type);
  530. if ($this->story_url != "") {
  531. $I->index_field("story_url:Text", $this->story_url);
  532. }
  533. $I->index_content($this->story_id, strip_tags(implode(" ", $allcontent)));
  534. $I->send();
  535. }
  536. } // story index
  537. // .....................................................................
  538. /** Un-Index this story from Lucene, if enabled for this website. */
  539.  
  540. function unindex() {
  541. global $CONTEXT, $LIBDIR;
  542. if ( isset($CONTEXT) && $CONTEXT->configvalue("Lucene Site Indexing") ) {
  543. include_once("lucene-defs.php");
  544. $UI = new lucene_unindexmsg();
  545. $UI->unindex($this->story_id);
  546. $UI->send();
  547. }
  548. } // unindex
  549. // .....................................................................
  550. /** Routine to save the story to the database. */
  551.  
  552. function save_story() {
  553. if ($this->story_id) {
  554. if ($this->newstory) {
  555. $sup = new dbinsert("ax_story");
  556. $sup->set("story_id", $this->story_id);
  557. }
  558. else {
  559. $sup = new dbupdate("ax_story");
  560. }
  561. $sup->set("lang_id", $this->language);
  562. $sup->set("story_headline", $this->story_headline);
  563. $sup->set("story_precis", $this->story_precis);
  564. $sup->set("story_content", $this->story_content);
  565. $sup->set("story_author", ($this->story_author != "") ? $this->story_author : NULLVALUE);
  566. $sup->set("story_type", $this->story_type);
  567. $sup->set("story_icon_url", $this->story_icon_url);
  568. $sup->set("category_id", ($this->story_category !== false) ? $this->story_category : NULLVALUE);
  569. if (isset($this->story_icon) && $this->story_icon !== "") {
  570. $sup->set("story_icon", $this->story_icon->catalogitem->cat_id);
  571. }
  572. else {
  573. $sup->set("story_icon", NULLVALUE);
  574. }
  575. if ($this->story_date_ts == 0) {
  576. $sup->set("story_date", NULLVALUE);
  577. }
  578. else {
  579. $sup->set("story_date", timestamp_to_datetime($this->story_date_ts));
  580. }
  581. if ($this->expiry_date_ts == 0) {
  582. $sup->set("expiry_date", NULLVALUE);
  583. }
  584. else {
  585. $sup->set("expiry_date", timestamp_to_datetime($this->expiry_date_ts));
  586. }
  587. $sup->set("last_modified", 'now()');
  588. $sup->set("visible", $this->visible);
  589. $sup->set("deleted", $this->deleted);
  590. $sup->where("story_id=$this->story_id");
  591. if ($sup->execute()) {
  592. // Index to Lucene..
  593. $this->index();
  594. $this->newstory = false;
  595. }
  596. }
  597. } // save_story
  598. // .....................................................................
  599. /** Remove the story from the system. We actually just flag it as
  600. * deleted on the database, and keep the record.
  601. */
  602. function delete_story() {
  603. global $RESPONSE, $CONTEXT;
  604. if ($this->valid && !$this->deleted) {
  605. $del = new dbupdate("ax_story");
  606. $del->set("deleted", true);
  607. $del->where("story_id=$this->story_id");
  608. $this->deleted = $del->execute();
  609. if ($this->deleted) {
  610. if ($RESPONSE->microsites_mode == MICROSITES_ENABLED) {
  611. $msdel = new dbdelete("ax_microsite_story");
  612. $msdel->where("story_id=$this->story_id");
  613. $msdel->execute();
  614. }
  615. $this->unindex();
  616. $this->info_msg = "Story has been marked as deleted";
  617. }
  618. }
  619. } // delete_story
  620. // .....................................................................
  621. /** Process the POST from form. This method deals with POSTed content
  622. * from the edit form.
  623. */
  624. function POSTprocess() {
  625. global $RESPONSE;
  626. global $storysave_x; // Clicked save
  627. global $storyedit_x; // Clicked edit
  628. global $storycancel_x; // Clicked cancel
  629. global $translate_x; // Clicked translate
  630. global $story_headline; // Story headline
  631. global $story_precis; // Story precis/lead-in
  632. global $story_content; // Story content
  633. global $story_media; // Reference to picture, movie etc.
  634. global $story_icon; // Reference to icon catalog item
  635. global $story_icon_url; // URL for story icon
  636. global $uploadmedia; // Uploaded media file present
  637. global $story_locs; // List of locations to publish to
  638. global $caption; // New image caption
  639. global $media_justify; // Image justify setting 'left' or 'right'
  640. global $media_width; // Image width px
  641. global $media_height; // Image height px
  642. global $story_author; // Story author
  643. global $story_type; // Story type
  644. global $story_date; // Story date setting
  645. global $story_language; // Story language setting
  646. global $new_language; // New story langauage - translated
  647. global $expiry_date; // Expiry date setting
  648. global $visible; // Visible flag
  649.  
  650. debugbr("POSTprocess: storymode initial: $this->storymode", DBG_DEBUG);
  651. debugbr("story microsite: '$this->microsite_name'");
  652.  
  653. // Save story
  654. if (isset($storysave_x)) {
  655. if (isset($story_headline)) $this->story_headline = $story_headline;
  656. if (isset($story_precis)) $this->story_precis = $story_precis;
  657. if (isset($story_content)) $this->story_content = $story_content;
  658. if (isset($story_author)) $this->story_author = $story_author;
  659. if (isset($story_type)) $this->story_type = $story_type;
  660. if (isset($story_icon_url)) $this->story_icon_url = $story_icon_url;
  661. if ($this->has_multilang && isset($story_language)) {
  662. $this->language = $story_language;
  663. }
  664.  
  665. // Story dates..
  666. if (isset($story_date)) {
  667. $this->story_date = $story_date;
  668. if ($story_date != "") {
  669. // Convert user-supplied date-time..
  670. $this->story_date_ts = displaydate_to_timestamp($story_date);
  671. }
  672. else {
  673. // Supply default of 'now'. Story date must have a value..
  674. $this->story_date_ts = time();
  675. }
  676. $this->story_date = timestamp_to_displaydate(DISPLAY_DATE_FORMAT, $this->story_date_ts);
  677. }
  678. if ($this->has_expiry && isset($expiry_date)) {
  679. $this->expiry_date = $expiry_date;
  680. if ($expiry_date != "") {
  681. $this->expiry_date_ts = displaydate_to_timestamp($expiry_date);
  682. $this->expiry_date = timestamp_to_displaydate(DISPLAY_DATE_FORMAT, $this->expiry_date_ts);
  683. }
  684. else {
  685. $this->expiry_date_ts = 0;
  686. }
  687. }
  688.  
  689. // Visible flag..
  690. $this->visible = isset($visible);
  691.  
  692. // Story icon
  693. if (isset($story_icon) && $story_icon != "") {
  694. $icon_bits = explode("|", $story_icon);
  695. $cat_id = $icon_bits[0];
  696. $newci = new catalogitem($cat_id);
  697. if ($newci->valid) {
  698. $this->story_icon = new story_media($this->story_id, $newci);
  699. }
  700. }
  701. else {
  702. unset($this->story_icon);
  703. }
  704.  
  705. // Save it if changed..
  706. $this->save_story();
  707.  
  708. // Microsite story link for new stories..
  709. if ($this->storymode == "adding" && isset($this->microsite_name)) {
  710. $mssin = new dbinsert("ax_microsite_story");
  711. $mssin->set("microsite_name", $this->microsite_name);
  712. $mssin->set("story_id", $this->story_id);
  713. $mssin->execute();
  714. }
  715.  
  716. // Media data POSTings..
  717. if ($this->has_media) {
  718. // Some defaults..
  719. if ($media_width == "") $media_width = 0;
  720. if ($media_height == "") $media_height = 0;
  721.  
  722. // Deal with a new media file upload. In this case we
  723. // assume we are just adding, if we have multimedia set
  724. // otherwise we will clear out pre-existing media first..
  725. $smdel = new dbdelete("ax_story_media");
  726. $smdel->where("story_id=$this->story_id");
  727. $smdel->execute();
  728. $this->story_media = array();
  729. if (isset($uploadmedia) && $uploadmedia != "none" && $uploadmedia != "") {
  730. $newci = new catalogitem();
  731. $errmsgs = $newci->upload($caption, $this->category);
  732. if ($newci->valid) {
  733. $smin = new dbinsert("ax_story_media");
  734. $smin->set("story_id", $this->story_id);
  735. $smin->set("cat_id", $newci->cat_id);
  736. $smin->set("caption", $caption);
  737. $smin->set("justify", $media_justify);
  738. $smin->set("width", $media_width);
  739. $smin->set("height", $media_height);
  740. $smin->execute();
  741. $media = new story_media($this->story_id, $newci);
  742. $media->caption = $caption;
  743. $media->justify = $media_justify;
  744. $media->width = $media_width;
  745. $media->height = $media_height;
  746. $this->story_media[$newci->cat_id] = $media;
  747. }
  748. else {
  749. if (count($errmsgs) > 0) {
  750. $this->info_msg = implode("<br>", $errmsgs);
  751. }
  752. }
  753. }
  754. // Otherwise, just re-create the media refs..
  755. else {
  756. $smdel = new dbdelete("ax_story_media");
  757. $smdel->where("story_id=$this->story_id");
  758. $smdel->execute();
  759. // Turn incoming value(s) into an array..
  760. $new_story_media = array();
  761. if (is_array($story_media)) {
  762. $new_story_media = $story_media;
  763. }
  764. elseif ($story_media != "") {
  765. $new_story_media = array($story_media);
  766. }
  767. // Start from scratch and rebuild media array..
  768. $this->story_media = array();
  769. foreach ($new_story_media as $cat_info) {
  770. if ($cat_info != "") {
  771. $cat_bits = explode("|", $cat_info);
  772. $cat_id = $cat_bits[0];
  773. $newci = new catalogitem($cat_id);
  774. if ($newci->valid) {
  775. // Save it to database..
  776. $ssin = new dbinsert("ax_story_media");
  777. $ssin->set("story_id", $this->story_id);
  778. $ssin->set("cat_id", $cat_id);
  779. $ssin->set("caption", $caption);
  780. $ssin->set("justify", $media_justify);
  781. $ssin->set("width", $media_width);
  782. $ssin->set("height", $media_height);
  783. $ssin->execute();
  784. // Save it to local media array too..
  785. $media = new story_media($this->story_id, $newci);
  786. $media->caption = $caption;
  787. $media->justify = $media_justify;
  788. $media->width = $media_width;
  789. $media->height = $media_height;
  790. $this->story_media[$cat_id] = $media;
  791. }
  792. }
  793. } // foreach
  794. }
  795. } // has_media
  796.  
  797. // Story publish to locations..
  798. $sldel = new dbdelete("ax_story_location");
  799. $sldel->where("story_id=$this->story_id");
  800. $sldel->execute();
  801. $this->story_locs = array();
  802. if (isset($story_locs)) {
  803. foreach ($story_locs as $loc_id) {
  804. if ($loc_id != "") {
  805. $slin = new dbinsert("ax_story_location");
  806. $slin->set("story_id", $this->story_id);
  807. $slin->set("location_id", $loc_id);
  808. $slin->execute();
  809. }
  810. }
  811. $this->story_locs = $story_locs;
  812. }
  813. $this->info_msg = "Story was saved";
  814. $this->storymode = "viewagain";
  815. } // storysave_x
  816.  
  817. // Edit story
  818. elseif (isset($storyedit_x)) {
  819. $this->storymode = "edit";
  820. } // storyedit_x
  821.  
  822. // Cancel current mode
  823. elseif (isset($storycancel_x)) {
  824. $this->storymode = "viewagain";
  825. } // storycancel_x
  826.  
  827. // Translate current story into new language.
  828. elseif (isset($translate_x)) {
  829. $translation = $this->get_translation($new_language);
  830. if ($translation !== false) {
  831. $this->get_story($translation);
  832. }
  833. } // translate_x
  834.  
  835. // Remove story
  836. elseif ($this->storymode == "remove") {
  837. $this->delete_story();
  838. $this->storymode = "viewagain";
  839. } // remove
  840. debugbr("POSTprocess: storymode final: $this->storymode", DBG_DEBUG);
  841. } // story POSTprocess
  842. // .....................................................................
  843. /**
  844. * Returns the story_id of a translation of the current story in the
  845. * given language. If it already exists, then it just returns the story
  846. * ID. If it doesn't exist, then it simply makes a copy of this story,
  847. * assigns it the language it _will_ be translated into, and records a
  848. * relationship to the other associated translations in the database table
  849. * 'story_tranlsation'. This latter table allows us to put a list of
  850. * languages (or little country flags) on any stories which have alternatives
  851. * in another language.
  852. * @param integer $language Language to get translated story in
  853. */
  854. function get_translation($language) {
  855. // Check if this story already has a translation available, and
  856. // we just return the translated story id if so..
  857. $this->get_story_translations();
  858. foreach ($this->story_translations as $translated_storyid => $chklang) {
  859. if ($chklang == $language) {
  860. return $translated_storyid;
  861. break;
  862. }
  863. }
  864.  
  865. // Preserve some info for use later on..
  866. $original_story_id = $this->story_id;
  867. $original_translations = $this->story_translations;
  868.  
  869. // Create new story..
  870. start_transaction();
  871. $this->story_id = get_next_sequencevalue("seq_story_id", "ax_story", "story_id");
  872. // Set the new language..
  873. $this->language = $language;
  874. $this->story_date_ts = time();
  875. $this->story_date = timestamp_to_displaydate(DISPLAY_DATE_FORMAT, $this->story_date_ts);
  876. $this->newstory = true;
  877. $this->valid = true;
  878. $this->save_story();
  879.  
  880. // Duplicate media..
  881. $ord = 1;
  882. foreach ($this->story_media as $cat_id => $media) {
  883. $in = new dbinsert("ax_story_media");
  884. $in->set("story_id", $this->story_id);
  885. $in->set("cat_id", $cat_id);
  886. $in->set("caption", $media->caption);
  887. $in->set("width", $media->width);
  888. $in->set("height", $media->height);
  889. $in->set("justify", $media->justify);
  890. $in->set("display_order", $ord++);
  891. $in->execute();
  892. }
  893. // Duplicate sports..
  894. foreach ($this->story_sports as $sport_id) {
  895. $in = new dbinsert("ax_story_sport");
  896. $in->set("story_id", $this->story_id);
  897. $in->set("sport_id", $sport_id);
  898. $in->execute();
  899. }
  900. // Duplicate locations..
  901. $ord = 1;
  902. foreach ($this->story_locs as $loc_id) {
  903. $in = new dbinsert("ax_story_location");
  904. $in->set("story_id", $this->story_id);
  905. $in->set("location_id", $loc_id);
  906. $in->set("display_order", $ord++);
  907. $in->execute();
  908. }
  909. if (commit()) {
  910. // Create translated story relationship..
  911. if ($this->root_translation_id == -1) {
  912. $root_trans_id = $original_story_id;
  913. }
  914. else {
  915. $root_trans_id = $this->root_translation_id;
  916. }
  917. $in = new dbinsert("ax_story_translation");
  918. $in->set("story_id", $root_trans_id);
  919. $in->set("translated_story_id", $this->story_id);
  920. $in->execute();
  921. }
  922. return $this->story_id;
  923. } // translate_into
  924. // .....................................................................
  925. /** Do a re-count of the story words. Set our local variable
  926. * and also return the value as a by-product..
  927. * @return integer Count of words in the story
  928. */
  929. function word_count() {
  930. $words = explode(" ",
  931. $this->story_headline . " "
  932. . $this->story_precis . " "
  933. . $this->story_content
  934. );
  935. return count($words);
  936. } // word_count
  937. // .....................................................................
  938. /** Generate a precis from the story content.
  939. * @param integer $maxwords Maximum number of words for the precis
  940. * @param integer $minwords Minimum number of words for the precis
  941. * @return string The precis
  942. */
  943. function make_precis($maxwords=50, $minwords=5) {
  944. $precis = "";
  945. $patt = "(([\S]+[\s]+){" . $minwords . "," . $maxwords . "})";
  946. preg_match("/$patt/", strip_tags($this->story_content), $matches);
  947. if (isset($matches[1])) {
  948. $precis = $matches[1];
  949. }
  950. $precis = str_replace("\x0d\x0a", " ", $precis);
  951. return $precis;
  952. } // make_precis
  953. // .....................................................................
  954. /**
  955. * Return the rendering of the story icon (if one exists) either as a
  956. * standard HTML anchor tag if an icon URL exists, or as an image.
  957. * @return string HTML for anchor or image of the story icon
  958. */
  959. function render_story_icon() {
  960. $s = "";
  961. if (isset($this->story_icon) && is_object($this->story_icon)) {
  962. $s = $this->story_icon->catalogitem->Insitu();
  963. if ($this->story_icon_url != "") {
  964. $a = new anchor($this->story_icon_url, $s);
  965. if (stristr($this->story_icon_url, "http")) {
  966. $a->settarget("_new");
  967. }
  968. $s = $a->render();
  969. }
  970. }
  971. return $s;
  972. } // render_story_icon
  973. // .....................................................................
  974. /** Render the story details as an edit form.
  975. * @return string The editform complete.
  976. */
  977. function editform() {
  978. global $RESPONSE;
  979. global $LIBDIR, $CMDIR, $IMAGESDIR;
  980. global $width, $width_img_preview;
  981. global $widthpx, $smlwidthpx, $stdwidthpx, $bigwidthpx;
  982.  
  983. // CONTROL BUTTONS
  984. $s = "";
  985. if ($this->user_can_edit()) {
  986. $savb = new form_imagebutton("storysave", "Save", "", "$LIBDIR/img/_save.gif", "Save changes", 57, 15);
  987. $canb = new form_imagebutton("storycancel", "Cancel", "", "$LIBDIR/img/_cancel.gif", "Cancel", 57, 15);
  988. if ($this->newstory) {
  989. $canb->set_onclick("window.close()");
  990. }
  991. $s .= $savb->render() . "&nbsp;&nbsp;" . $canb->render();
  992. }
  993. $CONTROL_BUTTONS = $s;
  994.  
  995. $Tst = new table("story");
  996. $Tst->setpadding(4);
  997.  
  998. $rowbg = "axbglite";
  999.  
  1000. // EDITOR HEADER
  1001. $Thd = new table("editor heading");
  1002. $Thd->tr($rowbg);
  1003. $title = "$this->story_category_desc ";
  1004. if ($this->newstory) {
  1005. $title .= "New Article";
  1006. }
  1007. else {
  1008. $title .= "Editor";
  1009. }
  1010. $Thd->td("<h3>$title</h3>", "axfg");
  1011. $Thd->td($CONTROL_BUTTONS);
  1012. $Thd->td_alignment("right");
  1013. $Tst->tr($rowbg);
  1014. $Tst->td($Thd->render(), "border-bottom:1px solid black");
  1015. $Tst->td_colspan(2);
  1016.  
  1017. // ERRMSG
  1018. if ($this->info_msg != "") {
  1019. $rowbg = ($rowbg == "axbglite") ? "axbgdark" : "axbglite";
  1020. $Tst->tr($rowbg);
  1021. $Tst->td($this->info_msg, "axerror");
  1022. $Tst->td_colspan(2);
  1023. $Tst->td_alignment("center");
  1024. }
  1025.  
  1026. // MICROSITE
  1027. if (isset($this->microsite_name)) {
  1028. $Fld = new form_labelfield("story_microsite", $this->microsite_name);
  1029. $rowbg = ($rowbg == "axbglite") ? "axbgdark" : "axbglite";
  1030. $Tst->tr($rowbg);
  1031. $Tst->td("Microsite:", "axfg");
  1032. $Tst->td($Fld->render());
  1033. }
  1034.  
  1035. // HEADLINE
  1036. $Fld = new form_textfield("story_headline", "Headline", $this->story_headline);
  1037. $Fld->setclass("axtxtbox");
  1038. $Fld->setstyle("width:$widthpx;");
  1039. $rowbg = ($rowbg == "axbglite") ? "axbgdark" : "axbglite";
  1040. $Tst->tr($rowbg);
  1041. $Tst->td("Headline:", "axfg");
  1042. $Tst->td_css("padding-top:10px;");
  1043. $Tst->td($Fld->render());
  1044. $Tst->td_css("padding-top:10px;");
  1045.  
  1046. // PRECIS/LEAD IN
  1047. if ($this->has_precis) {
  1048. $Fld = new form_wysiwygfield("story_precis", "Lead In", $this->story_precis);
  1049. $Fld->setclass("axmemo");
  1050. $Fld->setstyle("width:$widthpx;height:120px;");
  1051. $Fld->set_statusbar(false);
  1052. $Fld->set_toolbar("basic");
  1053. $rowbg = ($rowbg == "axbglite") ? "axbgdark" : "axbglite";
  1054. $Tst->tr($rowbg);
  1055. $Tst->td("Lead In:", "axfg");
  1056. $Tst->td_css("vertical-align:top;padding-top:5px;");
  1057. $Tst->td($Fld->render());
  1058. }
  1059.  
  1060. // STORY AUTHOR
  1061. if ($RESPONSE->ismemberof_group("Editor")) {
  1062. // Editors can change the author..
  1063. $Fld = new form_combofield("story_author", "Author", $this->story_author);
  1064. $Fld->setclass("axcombo");
  1065. $Fld->setstyle("width:$stdwidthpx;");
  1066. $Fld->additem("");
  1067. $q = "SELECT * FROM ax_user u, ax_user_group ug, ax_group g";
  1068. $q .= " WHERE ug.user_id=u.user_id";
  1069. $q .= " AND g.group_id=ug.group_id";
  1070. $q .= " AND g.group_desc IN ('Editor','Author')";
  1071. $q .= " AND u.enabled";
  1072. $q .= " ORDER BY u.full_name";
  1073. $authors = dbrecordset($q);
  1074. if ($authors->hasdata) {
  1075. $Fld->add_querydata($authors, "user_id", "full_name");
  1076. }
  1077. $rowbg = ($rowbg == "axbglite") ? "axbgdark" : "axbglite";
  1078. $Tst->tr($rowbg);
  1079. $Tst->td("Author:", "axfg");
  1080. $Tst->td($Fld->render());
  1081. }
  1082. else {
  1083. // Standard authors can't change by-line..
  1084. $Fld = new form_labelfield("story_author", "<b>$this->story_author_name ($this->story_author)</b>");
  1085. $hid = new form_hiddenfield("story_author", $this->story_author);
  1086. $rowbg = ($rowbg == "axbglite") ? "axbgdark" : "axbglite";
  1087. $Tst->tr($rowbg);
  1088. $Tst->td("Author:", "axfg");
  1089. $Tst->td($Fld->render() . $hid->render());
  1090. }
  1091.  
  1092. // STORY CONTENT
  1093. $Fld = new form_wysiwygfield("story_content", "Article", $this->story_content);
  1094. $Fld->setclass("axmemo");
  1095. $Fld->setstyle("width:$widthpx;height:350px;");
  1096. $Fld->register_plugins("all");
  1097. $Fld->set_toolbar("full");
  1098. $Fld->set_statusbar(false);
  1099. $rowbg = ($rowbg == "axbglite") ? "axbgdark" : "axbglite";
  1100. $Tst->tr($rowbg);
  1101. $Tst->td("Content:", "axfg");
  1102. $Tst->td_css("vertical-align:top;padding-top:5px;");
  1103. $Tst->td($Fld->render());
  1104.  
  1105. // STORY MEDIA
  1106. if ($this->has_media) {
  1107. // CATALOG
  1108. $catalog = new catalog();
  1109. $catalog->search("", array("image"));
  1110.  
  1111. // Media details table..
  1112. $Tmed = new table("storymedia");
  1113. $Tmed->tr();
  1114. $Tmed->setwidth("100%");
  1115.  
  1116. // Find the first (selected) media object $selmedia_first. This object
  1117. // is used extensively below to populate the various form fields. We
  1118. // currently only properly support one object (the first one).
  1119. if (count($this->story_media) > 0) {
  1120. reset($this->story_media);
  1121. list($catid, $selmedia_first) = each($this->story_media);
  1122. }
  1123. else {
  1124. $selmedia_first = new story_media();
  1125. }
  1126. // Media selector..
  1127. $Fld = new form_combofield("story_media", "Media", $selmedia_first->keyinfo());
  1128. $Fld->setclass("axcombo");
  1129. $Fld->setstyle("width:$bigwidthpx;");
  1130. $Fld->additem("", "None");
  1131. foreach ($catalog->catalogitems as $catid => $catitem) {
  1132. if (isset($this->story_media[$catid])) {
  1133. $media = $this->story_media[$catid];
  1134. }
  1135. else {
  1136. $media = new story_media($this->story_id, $catitem);
  1137. $media->caption = $catitem->cat_name;
  1138. }
  1139. $key = $media->keyinfo();
  1140. $label = $media->catalogitem->cat_name;
  1141. if ($label == "") {
  1142. $label = $media->catalogitem->filepath;
  1143. }
  1144. $Fld->additem($key, $label);
  1145. }
  1146. $Fld->set_onchange("imgPreview(this.options[this.selectedIndex].value)");
  1147. $rowbg = ($rowbg == "axbglite") ? "axbgdark" : "axbglite";
  1148. $Tmed->tr($rowbg);
  1149. $Tmed->td($Fld->render());
  1150. $Tmed->td_alignment("", "top");
  1151.  
  1152. // Create a preview image..
  1153. $imgFld = new img(
  1154. $selmedia_first->catalogitem->filepath,
  1155. "preview",
  1156. "Preview",
  1157. $width_img_preview,
  1158. $height_img_preview
  1159. );
  1160. $imgFld->setalign("right");
  1161. $imgFld->sethspace(4);
  1162. $Tmed->td($imgFld->render());
  1163. $Tmed->td_alignment("right", "top");
  1164. $Tmed->td_rowspan(4);
  1165.  
  1166. // Width and Height override fields
  1167. $sizes_defaulted = ($selmedia_first->width == 0 || $selmedia_first->height == 0);
  1168. if ($sizes_defaulted) {
  1169. $width = $selmedia_first->catalogitem->width;
  1170. $height = $selmedia_first->catalogitem->height;
  1171. }
  1172. else {
  1173. $width = $selmedia_first->width;
  1174. $height = $selmedia_first->height;
  1175. }
  1176. $Tin = new table();
  1177. $Tin->tr();
  1178. $wFld = new form_textfield("media_width", "Width", $width);
  1179. $wFld->setclass("axnumbox");
  1180. $wFld->setstyle("width:50px");
  1181. $hFld = new form_textfield("media_height", "Height", $height);
  1182. $hFld->setclass("axnumbox");
  1183. $hFld->setstyle("width:50px");
  1184. $dFld = new form_checkbox("media_size_default");
  1185. $dFld->setclass("axchkbox");
  1186. $dFld->checked = ($sizes_defaulted === true);
  1187. if ($sizes_defaulted) {
  1188. $wFld->disabled = true;
  1189. $hFld->disabled = true;
  1190. }
  1191. $dFld->set_onclick("defSizingToggle(this)");
  1192. $Tin->td("Sizing:", "axfg");
  1193. $Tin->td($wFld->render() . "&nbsp;x&nbsp;" . $hFld->render() . "&nbsp;&nbsp;Default&nbsp;" . $dFld->render(), "axfg");
  1194. $Tin->set_width_profile("20%,80%");
  1195. $Tmed->tr($rowbg);
  1196. $Tmed->td($Tin->render());
  1197.  
  1198. // Image justify setting
  1199. $Fld = new form_combofield("media_justify", "Justify", $selmedia_first->justify);
  1200. $Fld->setclass("axcombo");
  1201. $Fld->setstyle("width:100px");
  1202. $Fld->additem("", "default");
  1203. $Fld->additem("left", "Left");
  1204. $Fld->additem("right", "Right");
  1205. $Tin = new table();
  1206. $Tin->td("Justify:", "axfg");
  1207. $Tin->td($Fld->render());
  1208. $Tin->set_width_profile("20%,80%");
  1209. $Tmed->tr($rowbg);
  1210. $Tmed->td($Tin->render());
  1211.  
  1212. // File upload field - allows them to add media on the
  1213. // fly to go with a story..
  1214. $Fld = new form_fileuploadfield("uploadmedia", "Upload");
  1215. $Fld->setclass("axtxtbox");
  1216. $Fld->setstyle("width:$smlwidthpx;");
  1217. $Tmed->tr($rowbg);
  1218. $Tmed->td($Fld->render());
  1219.  
  1220. // Now we render the above sub-table $Tmed inside the main table..
  1221. $Tst->tr($rowbg);
  1222. $Tst->td("Image:", "axfg");
  1223. $Tst->td_css("vertical-align:top;padding-top:5px;");
  1224. $Tst->td($Tmed->render());
  1225.  
  1226. // CAPTION
  1227. // NB: We kinda support multiple media, but the issue of them
  1228. // each having a separate caption is not resolved in this current
  1229. // implementation - recommend using a recmaintainer for that
  1230. // when the time comes.
  1231. $Fld = new form_textfield("caption", "Caption", $selmedia_first->caption);
  1232. $Fld->setclass("axtxtbox");
  1233. $Fld->setstyle("width:$stdwidthpx;");
  1234. $Tst->tr($rowbg);
  1235. $Tst->td("Image Caption:", "axfg");
  1236. $Tst->td($Fld->render());
  1237.  
  1238. $Tmed = new table("storyicon");
  1239. $Tmed->tr();
  1240. $Tmed->setwidth("100%");
  1241. if (isset($this->story_icon)) {
  1242. $selicon_first = $this->story_icon;
  1243. }
  1244. else {
  1245. $selicon_first = new story_media();
  1246. }
  1247. // Icon selector..
  1248. $Fld = new form_combofield("story_icon", "Icon", $selicon_first->keyinfo());
  1249. $Fld->setclass("axcombo");
  1250. $Fld->setstyle("width:$bigwidthpx;");
  1251. $Fld->additem("", "None");
  1252. foreach ($catalog->catalogitems as $catid => $catitem) {
  1253. $icon = new story_media($this->story_id, $catitem);
  1254. $icon->caption = $catitem->cat_name;
  1255. $key = $icon->keyinfo();
  1256. $label = $icon->catalogitem->cat_name;
  1257. if ($label == "") {
  1258. $label = $icon->catalogitem->filepath;
  1259. }
  1260. $Fld->additem($key, $label);
  1261. }
  1262. $Fld->set_onchange("iconPreview(this.options[this.selectedIndex].value)");
  1263. $rowbg = ($rowbg == "axbglite") ? "axbgdark" : "axbglite";
  1264. $Tmed->tr($rowbg);
  1265. $Tmed->td($Fld->render());
  1266. $Tmed->td_alignment("", "top");
  1267. // Create a preview icon..
  1268. $imgFld = new img(
  1269. $selicon_first->catalogitem->filepath,
  1270. "iconpreview",
  1271. "Icon Preview",
  1272. $width_icon_preview,
  1273. $height_icon_preview
  1274. );
  1275. $imgFld->setalign("right");
  1276. $imgFld->sethspace(4);
  1277. $Tmed->td($imgFld->render());
  1278. $Tmed->td_alignment("right", "top");
  1279. $Tmed->td_rowspan(2);
  1280. // Now we render the above sub-table $Tmed inside the main table..
  1281. $Tst->tr($rowbg);
  1282. $Tst->td("Icon:", "axfg");
  1283. $Tst->td($Tmed->render());
  1284. // Icon URL entry field
  1285. $Fld = new form_textfield("story_icon_url", "Url", $this->story_icon_url);
  1286. $Fld->setclass("axtxtbox");
  1287. $Fld->setstyle("width:$stdwidthpx");
  1288. $Tst->tr($rowbg);
  1289. $Tst->td("Link to:", "axfg");
  1290. $Tst->td($Fld->render());
  1291.  
  1292. // This allows us to preview images without refresh..
  1293. $RESPONSE->head->add_script(
  1294. "function imgPreview(key) {\n"
  1295. . " var keyparts=key.split('|');\n"
  1296. . " var imgfile=keyparts[1];\n"
  1297. . " if (imgfile!='') {\n"
  1298. . " document.$this->formname.preview.src=imgfile;\n"
  1299. . " }\n"
  1300. . "}\n"
  1301. . "function iconPreview(key) {\n"
  1302. . " var keyparts=key.split('|');\n"
  1303. . " var iconfile=keyparts[1];\n"
  1304. . " if (iconfile!='') {\n"
  1305. . " document.$this->formname.iconpreview.src=iconfile;\n"
  1306. . " }\n"
  1307. . "}\n"
  1308. . "function defSizingToggle(chkbox) {\n"
  1309. . " if (chkbox.checked) {\n"
  1310. . " document.$this->formname.media_width.value='';\n"
  1311. . " document.$this->formname.media_width.disabled=true;\n"
  1312. . " document.$this->formname.media_height.value='';\n"
  1313. . " document.$this->formname.media_height.disabled=true;\n"
  1314. . " }\n"
  1315. . " else {\n"
  1316. . " document.$this->formname.media_width.disabled=false;\n"
  1317. . " document.$this->formname.media_height.disabled=false;\n"
  1318. . " }\n"
  1319. . "}\n"
  1320. );
  1321. }
  1322.  
  1323. // STORY DATE
  1324. $Fld = new form_textfield("story_date", "Article date", $this->story_date);
  1325. $Fld->setclass("axdatetime");
  1326. $Fld->setstyle("width:$smlwidthpx;");
  1327. $Fld->set_onblur("isNonBlank(this, 'Please fill in a story date.');");
  1328. $rowbg = ($rowbg == "axbglite") ? "axbgdark" : "axbglite";
  1329. $Tst->tr($rowbg);
  1330. $Tst->td("Article Date:", "axfg");
  1331. $Tst->td($Fld->render() . "&nbsp;<small><i>eg: dd/mm/yyyy [hh:mm]</i></small>");
  1332.  
  1333. // EXPIRY DATE
  1334. if ($this->has_expiry) {
  1335. $Fld = new form_textfield("expiry_date", "Expiry date", $this->expiry_date);
  1336. $Fld->setclass("axdatetime");
  1337. $Fld->setstyle("width:$smlwidthpx;");
  1338. $rowbg = ($rowbg == "axbglite") ? "axbgdark" : "axbglite";
  1339. $Tst->tr($rowbg);
  1340. $Tst->td("Expiry Date:", "axfg");
  1341. $Tst->td($Fld->render());
  1342. }
  1343.  
  1344. // STORY TYPE
  1345. $Fld = new form_combofield("story_type", "Article type", $this->story_type);
  1346. $Fld->setclass("axcombo");
  1347. $Fld->setstyle("width:$smlwidthpx;");
  1348. $Fld->additem("n", "News item");
  1349. $rowbg = ($rowbg == "axbglite") ? "axbgdark" : "axbglite";
  1350. $Tst->tr($rowbg);
  1351. $Tst->td("Article Type:", "axfg");
  1352. $Tst->td($Fld->render());
  1353.  
  1354. // LANGUAGE
  1355. if ($this->has_multilang) {
  1356. $this->get_story_translations();
  1357. $Tlng = new table("language");
  1358.  
  1359. $Fld = new form_combofield("story_language", "", $this->language);
  1360. $Fld->setclass("axcombo");
  1361. $Fld->setstyle("width:$smlwidthpx;");
  1362.  
  1363. // Fill the dropdown selector with all possibilities..
  1364. $q = "SELECT * FROM ax_language";
  1365. $q .= " WHERE enabled=TRUE";
  1366. $q .= " ORDER BY display_order";
  1367. $langs = dbrecordset($q);
  1368. if ($langs->hasdata) {
  1369. $Fld->add_querydata($langs, "lang_id", "lang_desc");
  1370. }
  1371. $rowbg = ($rowbg == "axbglite") ? "axbgdark" : "axbglite";
  1372. $Tlng->tr($rowbg);
  1373. $Tlng->td($Fld->render());
  1374.  
  1375. $Fld = new form_combofield("new_language");
  1376. $Fld->setclass("axcombo");
  1377. $Fld->setstyle("width:$smlwidthpx;");
  1378. $Fld->additem("", "&mdash; Translate into &mdash;");
  1379. // Determine languages already translated..
  1380. $already_translated = array($this->language);
  1381. foreach ($this->story_translations as $sid => $langid) {
  1382. $already_translated[] = $langid;
  1383. }
  1384. $q = "SELECT * FROM ax_language WHERE enabled=TRUE";
  1385. if (count($already_translated) > 0) {
  1386. $langlist = implode(",", $already_translated);
  1387. if ($langlist != "") {
  1388. $q .= " AND NOT lang_id IN (" . implode(",", $already_translated) . ")";
  1389. }
  1390. }
  1391. $q .= " ORDER BY display_order";
  1392. $tlangs = dbrecordset($q);
  1393. if ($tlangs->hasdata) {
  1394. $Fld->add_querydata($tlangs, "lang_id", "lang_desc");
  1395. }
  1396. $transbtn = new form_imagebutton("translate", "", "", "$LIBDIR/img/_translate.gif", "Translate", 77, 15);
  1397. $Tlng->td($Fld->render());
  1398. $Tlng->td_alignment("right");
  1399. $Tlng->td($transbtn->render());
  1400. $Tlng->td_alignment("left");
  1401.  
  1402. if (count($this->story_translations) > 0) {
  1403. $translist = array();
  1404. foreach ($this->story_translations as $trans_story_id => $trans_lang_id) {
  1405. $lq = dbrecordset("SELECT * FROM ax_language WHERE lang_id=$trans_lang_id");
  1406. if ($lq->hasdata) {
  1407. $translist[] = ucfirst($lq->field("lang_desc"));
  1408. }
  1409. }
  1410. if (count($translist) > 0) {
  1411. $Tlng->tr($rowbg);
  1412. $Tlng->td("Existing Translations: " . implode("&nbsp;|&nbsp;", $translist));
  1413. $Tlng->td_colspan(2);
  1414. }
  1415. }
  1416. $Tst->tr($rowbg);
  1417. $Tst->td("Language:", "axfg");
  1418. $Tst->td_alignment("", "top");
  1419. $Tst->td($Tlng->render());
  1420. }
  1421.  
  1422. // VISIBLE
  1423. $Fld = new form_checkbox("visible", "Visible");
  1424. $Fld->checked = $this->visible;
  1425. $Fld->setclass("axchkbox");
  1426. $rowbg = ($rowbg == "axbglite") ? "axbgdark" : "axbglite";
  1427. $Tst->tr($rowbg);
  1428. $Tst->td("Visible:", "axfg");
  1429. $Tst->td($Fld->render());
  1430.  
  1431. // STORY LOCATIONS
  1432. $Fld = new form_combofield("story_locs", "", $this->story_locs);
  1433. $Fld->multiselect = true;
  1434. $Fld->setclass("axlistbox");
  1435. $Fld->size = 6;
  1436. $Fld->setstyle("width:$stdwidthpx;");
  1437. $q = "SELECT * FROM ax_content_location";
  1438. $q .= " WHERE enabled=TRUE";
  1439. $q .= " ORDER BY location_name";
  1440. $locs = dbrecordset($q);
  1441. if ($locs->hasdata) {
  1442. $Fld->add_querydata($locs, "location_id", "location_name");
  1443. }
  1444. $rowbg = ($rowbg == "axbglite") ? "axbgdark" : "axbglite";
  1445. $Tst->tr($rowbg);
  1446. $Tst->td("Publish to:", "axfg");
  1447. $Tst->td_alignment("", "top");
  1448. $Tst->td($Fld->render());
  1449.  
  1450. // LAST MODIFIED
  1451. $rowbg = ($rowbg == "axbglite") ? "axbgdark" : "axbglite";
  1452. $Tst->tr($rowbg);
  1453. $Tst->td("Last modified:", "axfg");
  1454. $Tst->td($this->lastmodified);
  1455.  
  1456. // Rule-off row..
  1457. $Tst->tr("axfoot");
  1458. $Tst->td("", "axfoot");
  1459. $Tst->td_colspan(2);
  1460.  
  1461. $Tst->set_width_profile("20%,80%");
  1462.  
  1463. // Add field validation scripts..
  1464. $RESPONSE->add_scriptsrc("$LIBDIR/js/fieldvalidation.js");
  1465.  
  1466. return $Tst->render();
  1467. } // editform
  1468. // .....................................................................
  1469. /** Render the story as a maintainer reader would view it. Note that this
  1470. * is not a fully dressed-up story viewer. It is designed as a view that
  1471. * a story administrator would see, showing all the technical bits and
  1472. * pieces such as story byte-size etc. You should create your own viewer
  1473. * for rendering stories 'prettily' on your website.
  1474. * @return string The HTML for the view story content.
  1475. */
  1476. function view() {
  1477. global $RESPONSE;
  1478. global $LIBDIR;
  1479.  
  1480. // CONTROL BUTTONS
  1481. $s = "";
  1482. // Buttons for administrators and editors only..
  1483. $doneb = new form_imagebutton("closewin", "Close", "", "$LIBDIR/img/_done.gif", "Close viewer", 57, 15);
  1484. $doneb->set_onclick("window.close()");
  1485. if ($this->user_can_edit()) {
  1486. $editb = new form_imagebutton("storyedit", "Edit", "", "$LIBDIR/img/_edit.gif", "Edit this article", 42, 15);
  1487. $remvb = new form_imagebutton("storyremove", "Delete", "", "$LIBDIR/img/_delete.gif", "Delete this article", 57, 15);
  1488. $remvb->set_onclick("remove_confirm()");
  1489. $s .= $editb->render() . "&nbsp;&nbsp;" . $remvb->render();
  1490. // Removal protection..
  1491. $RESPONSE->head->add_script(
  1492. "function remove_confirm() {\n"
  1493. . " var msg = '\\n\\nWARNING: Do you really want to delete\\n';\n"
  1494. . " msg += 'the article. This is irrevocable.\\n';"
  1495. . " rc = confirm(msg);\n"
  1496. . " if (rc) {\n"
  1497. . " document.$this->formname.storymode.value='remove';\n"
  1498. . " document.$this->formname.submit();\n"
  1499. . " }\n"
  1500. . " else alert('Delete is cancelled.');\n"
  1501. . "}\n"
  1502. );
  1503. }
  1504. if ($s != "") $s .= "&nbsp;&nbsp;";
  1505. $s .= $doneb->render();
  1506. $CONTROL_BUTTONS = $s;
  1507.  
  1508. $Tvw = new table("storyviewer");
  1509. $Tvw->setpadding(3);
  1510.  
  1511. $rowbg = "axbgdark";
  1512.  
  1513. // EDITOR HEADER
  1514. $Thd = new table("viewerhead");
  1515. $Thd->tr($rowbg);
  1516. $title = $this->story_category_desc;
  1517. if (isset($this->microsite_name)) {
  1518. $title .= "<br><small>(Microsite $this->microsite_name)</small>";
  1519. }
  1520. $Thd->td("<h3>$title</h3>", "axfg");
  1521. $Thd->td($CONTROL_BUTTONS);
  1522. $Thd->td_alignment("right", "bottom");
  1523.  
  1524. if ($this->language != 0) {
  1525. $lq = dbrecordset("SELECT * FROM ax_language WHERE lang_id=$this->language");
  1526. if ($lq->hasdata) {
  1527. $Thd->tr($rowbg);
  1528. $Thd->td("in " . $lq->field("lang_desc"));
  1529. $Thd->td_colspan(2);
  1530. }
  1531. }
  1532.  
  1533. $Tvw->tr($rowbg);
  1534. $Tvw->td($Thd->render(), "border-bottom:1px solid black");
  1535. $Tvw->td_colspan(2);
  1536.  
  1537. if ($this->info_msg != "") {
  1538. $Tvw->tr($rowbg);
  1539. $Tvw->td($this->info_msg, "axerror");
  1540. $Tvw->td_colspan(2);
  1541. $Tvw->td_alignment("center");
  1542. }
  1543.  
  1544. // HEADLINE, BY-LINE, STORY TYPE & WORDCOUNT
  1545. // STORY TYPE
  1546. switch ($this->story_type) {
  1547. case "n":
  1548. $type = "News article";
  1549. break;
  1550. default:
  1551. $type = "";
  1552. }
  1553.  
  1554. $Thd = new table("masthead");
  1555. $Thd->tr($rowbg);
  1556. $Thd->td("<h2>" . $this->story_headline . "</h2>",
  1557. "vertical-align:bottom;padding-bottom:0px;margin-bottom:0px;"
  1558. );
  1559. $Thd->td($type);
  1560. $Thd->td_alignment("right");
  1561. $Thd->tr($rowbg);
  1562. $byline = "by ";
  1563. $byline .= ($this->story_author_name != "") ? $this->story_author_name : "(anonymous)";
  1564. $Thd->td("<h6>$byline</h6>",
  1565. "vertical-align:top;padding-bottom:5px;"
  1566. );
  1567. $Thd->td($this->wordcount . " words (" . nicebytesize($this->bytesize) . ")");
  1568. $Thd->td_alignment("right");
  1569. if (isset($this->story_icon)) {
  1570. $Thd->tr();
  1571. $Thd->td($this->render_story_icon());
  1572. $Thd->td_colspan(2);
  1573. }
  1574. $Tvw->tr($rowbg);
  1575. $Tvw->td($Thd->render());
  1576. $Tvw->td_colspan(2);
  1577.  
  1578. // STORY DATE & EXPIRY DATE
  1579. $Tvw->tr($rowbg);
  1580. $Tvw->td( timestamp_to_displaydate(NICE_FULLDATETIME, $this->story_date_ts) );
  1581. if ($this->has_expiry && $this->expiry_date != "") {
  1582. if ($this->expiry_date_ts - $this->story_date_ts > 0) {
  1583. $Tvw->td("expires on " . timestamp_to_displaydate(NICE_FULLDATETIME, $this->expiry_date_ts));
  1584. }
  1585. else {
  1586. $Tvw->td("expired as of " . timestamp_to_displaydate(NICE_FULLDATETIME, $this->expiry_date_ts), "axhl");
  1587. }
  1588. $Tvw->td_alignment("right");
  1589. }
  1590. else {
  1591. $Tvw->td("&nbsp;");
  1592. }
  1593.  
  1594. // PUBLISHING STATUS
  1595. $status = "<b>Published to:</b>&nbsp;";
  1596. if (!$this->visible) {
  1597. $status .= "Currently hidden";
  1598. }
  1599. else {
  1600. if (count($this->story_locs) == 0) {
  1601. $status .= "No location is selected";
  1602. }
  1603. else {
  1604. $q .= "SELECT * FROM ax_content_location";
  1605. $q .= " WHERE location_id in (" . implode(",", $this->story_locs) . ")";
  1606. $locs = dbrecordset($q);
  1607. if ($locs->hasdata) {
  1608. $locnames = array();
  1609. do {
  1610. $locnames[] = $locs->field("location_name");
  1611. } while ($locs->get_next());
  1612. $status .= implode(", ", $locnames);
  1613. }
  1614. }
  1615. }
  1616. $Tvw->tr($rowbg);
  1617. $Tvw->td($status, "padding-top:5px;padding-bottom:5px;border-top:1px solid black");
  1618. $Tvw->td_colspan(2);
  1619.  
  1620. // LEAD-IN & STORY CONTENT
  1621. $rowbg = ($rowbg == "axbglite") ? "axbgdark" : "axbglite";
  1622. $Tvw->tr($rowbg);
  1623. //$content = $this->story_precis . " " . $this->story_content;
  1624. $media_content = "";
  1625. if ($this->has_media) {
  1626. if (count($this->story_media) > 0) {
  1627. foreach ($this->story_media as $cat_id => $media) {
  1628. $width = ($media->width > 0) ? $media->width : $media->catalogitem->width;
  1629. $height = ($media->height > 0) ? $media->height : $media->catalogitem->height;
  1630. $caption = ($media->caption != "") ? $media->caption : $media->catalogitem->cat_name;
  1631. $pic = new img(
  1632. $media->catalogitem->filepath,
  1633. $caption,
  1634. $caption,
  1635. ($width > 0 ? $width : false),
  1636. ($height > 0 ? $height : false)
  1637. );
  1638. $pic->setalign(($media->justify != "") ? $media->justify : "right");
  1639. $pic->setstyle("padding:2px");
  1640. $media_content .= $pic->render();
  1641. } // foreach
  1642. }
  1643. }
  1644. // Content..
  1645. if (trim($this->story_precis) != "") {
  1646. $content .= str_replace("\r\n\r\n", "<p>", trim($this->story_precis));
  1647. }
  1648. if (trim($media_content) != "") {
  1649. $content .= $media_content;
  1650. }
  1651. if (trim($this->story_content) != "") {
  1652. $content .= str_replace("\r\n\r\n", "<p>", trim($this->story_content));
  1653. }
  1654. $Tvw->td($content, "padding-top:20px;padding-bottom:50px;border-top:1px solid black");
  1655. $Tvw->td_colspan(2);
  1656.  
  1657. // TRANSLATIONS
  1658. $this->get_story_translations();
  1659. if (count($this->story_translations) > 0) {
  1660. $RESPONSE->head->add_script(
  1661. "function reloadViewer(url) {\n"
  1662. . " document.location=url;\n"
  1663. . "}\n"
  1664. );
  1665. $translinks = array();
  1666. foreach ($this->story_translations as $trans_story_id => $trans_lang_id) {
  1667. $lq = dbrecordset("SELECT * FROM ax_language WHERE lang_id=$trans_lang_id");
  1668. if ($lq->hasdata) {
  1669. $auth_code = $RESPONSE->get_auth_code();
  1670. $shref = "/story-viewer.php";
  1671. $shref = href_addparm($shref, "story_id", $trans_story_id);
  1672. $shref = href_addparm($shref, "auth_code", $auth_code);
  1673. $href = "javascript:reloadViewer('$shref')";
  1674. $translink = new anchor($href, ucfirst($lq->field("lang_desc")));
  1675. $translinks[] = $translink->render();
  1676. }
  1677. }
  1678. if (count($translinks) > 0) {
  1679. $rowbg = ($rowbg == "axbglite") ? "axbgdark" : "axbglite";
  1680. $Tvw->tr($rowbg);
  1681. $Tvw->td("Translations: " . implode("&nbsp;|&nbsp;", $translinks), "border-top:1px solid black");
  1682. $Tvw->td_colspan(2);
  1683. }
  1684. }
  1685.  
  1686. // LAST MODIFIED
  1687. $rowbg = ($rowbg == "axbglite") ? "axbgdark" : "axbglite";
  1688. $Tvw->tr($rowbg);
  1689. $Tvw->td("Last modified:&nbsp;$this->lastmodified",
  1690. "border-top:1px solid black"
  1691. );
  1692. $Tvw->td("#$this->story_id", "border-top:1px solid black");
  1693. $Tvw->td_alignment("right");
  1694.  
  1695. // Rule-off row..
  1696. $Tvw->tr("axfoot");
  1697. $Tvw->td("", "axfoot");
  1698. $Tvw->td_colspan(2);
  1699.  
  1700. return $Tvw->render();
  1701. } // view
  1702. // .....................................................................
  1703. /**
  1704. * Return the content of this story formatted for plaintext display
  1705. * @param integer $wrapchars Number of characters to wrap the lines at
  1706. */
  1707. function plaintext_content($wrapchars=0) {
  1708. // Join all hard-breaks into single lines..
  1709. $content = str_replace("\n", " ", $this->story_content);
  1710. // Split into paragraphs..
  1711. $paras = explode("<p>", $content);
  1712. // Wrap each paragrph if required..
  1713. if ($wrapchars > 0) {
  1714. $newparas = array();
  1715. foreach ($paras as $para) {
  1716. $para = wordwrap($para, $wrapchars, "\r\n");
  1717. $newparas[] = $para;
  1718. }
  1719. $paras = $newparas;
  1720. }
  1721. // Join up into multiple paragraphs split by CRLF..
  1722. $content = strip_tags( implode("\r\n\r\n", $paras) );
  1723. return $content;
  1724. } // plaintext_content
  1725. // .....................................................................
  1726. /** Render the story. We render the story as a table within a form containing all
  1727. * the form elements required to manipulate the story content, email it to
  1728. * someone, save it, and delete it etc...
  1729. * @return string The HTML for edit or view.
  1730. */
  1731. function html() {
  1732. global $RESPONSE;
  1733. // HIDDEN FIELDS
  1734. $cathid = new form_hiddenfield("cat", $this->story_category);
  1735. $authhid = new form_hiddenfield("auth_code", $RESPONSE->auth_code);
  1736. $modehid = new form_hiddenfield("storymode", $this->storymode);
  1737. $sidhid = new form_hiddenfield("story_id", $this->story_id);
  1738.  
  1739. // STORY FORM, VIEW or EDIT..
  1740.  
  1741. switch ($this->storymode) {
  1742. case "edit":
  1743. case "adding":
  1744. $story_form = new multipart_form($this->formname);
  1745. $story_form->add_text($this->editform());
  1746. break;
  1747. default:
  1748. $story_form = new form($this->formname);
  1749. $story_form->add_text($this->view());
  1750. } // switch
  1751.  
  1752. // Render hidden fields too..
  1753. $story_form->add($cathid);
  1754. $story_form->add($authhid);
  1755. $story_form->add($modehid);
  1756. $story_form->add($sidhid);
  1757.  
  1758. return $story_form->render();
  1759. } // story html
  1760.  
  1761.  
  1762.  
  1763. } // story class
  1764. // -----------------------------------------------------------------------
  1765.  
  1766. /**
  1767. * A container class for media item associated with a story. Contains
  1768. * a single piece of media which is associated with this story.
  1769. * @package cm
  1770. */
  1771. class story_media {
  1772. /** ID of story this media belongs to */
  1773.  
  1774. var $story_id = false;
  1775. /** The catalogitem object */
  1776.  
  1777. var $catalogitem;
  1778. /** The caption for this item */
  1779.  
  1780. var $caption = "";
  1781. /** The way to justify this item */
  1782.  
  1783. var $justify = "";
  1784. /** Local override width */
  1785.  
  1786. var $width = 0;
  1787. /** Local override height */
  1788.  
  1789. var $height = 0;
  1790. // .....................................................................
  1791. /**
  1792. * Create a new piece of story media. This comprises a catalogitem
  1793. * object, and a set of methods to access it.
  1794. * @param mixed $id Story ID, or false if not known
  1795. * @param mixed $item Object catalogitem, or false if initially undefined
  1796. */
  1797. function story_media($story_id=false, $item=false) {
  1798. if ($story_id !== false) {
  1799. $this->story_id = $story_id;
  1800. }
  1801. if ($item !== false && is_object($item)) {
  1802. $this->catalogitem = $item;
  1803. }
  1804. else {
  1805. $this->catalogitem = new catalogitem();
  1806. }
  1807. } // story_media
  1808. // .....................................................................
  1809. /**
  1810. * Define this story media object from the given catalog item key. This
  1811. * will obtain the given piece of catalog media from the database and
  1812. * assign the object variables accordingly.
  1813. * @param integer $catid Catalog item ID to obtain
  1814. */
  1815. function get_catalogitem($catid) {
  1816. $this->catalogitem = new catalogitem($catid);
  1817. } // get_catalogitem
  1818. // .....................................................................
  1819. /**
  1820. * Return the keyinfo string for this media item. This is encoded
  1821. * as follows, and is used in select combos:
  1822. * 'cat_id|filepath|width|height|justify'
  1823. */
  1824. function keyinfo() {
  1825. $info = array();
  1826. if (isset($this->catalogitem)) {
  1827. $info[] = $this->catalogitem->cat_id;
  1828. $info[] = $this->catalogitem->filepath;
  1829. $info[] = ($this->width != 0) ? $this->width : $this->catalogitem->width;
  1830. $info[] = ($this->height != 0) ? $this->height : $this->catalogitem->height;
  1831. $info[] = $this->justify;
  1832. }
  1833. return implode("|", $info);
  1834. } // keyinfo
  1835.  
  1836. } // story_media class
  1837. // -----------------------------------------------------------------------
  1838.  
  1839. ?>

Documentation generated by phpDocumentor 1.3.0RC3