Source for file block-defs.php

Documentation is available at block-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: block-defs.php */
  22. /* Author: Paul Waite */
  23. /* Description: Definitions for content block management in webpages. */
  24. /* */
  25. /* ******************************************************************** */
  26. /** @package cm */
  27. include_once("form-defs.php");
  28.  
  29. // ......................................................................
  30. // DEFINITIONS
  31.  
  32. /** Identity value signifying new block
  33. @access private */
  34. define("NEW_BLOCK", -1);
  35. /** Identity value signifying new blocklet
  36. @access private */
  37. define("NEW_BLOCKLET", -1);
  38.  
  39. /** Block/layout version undefined
  40. @access private */
  41. define("VERSION_UNDEFINED", -1);
  42. /** Block/layout version is pending
  43. @access private */
  44. define("VERSION_PENDING", 0);
  45. /** Block/layout version is live
  46. @access private */
  47. define("VERSION_LIVE", 1);
  48. /** Block/layout version is previous
  49. @access private */
  50. define("VERSION_PREVIOUS", 2);
  51.  
  52. /** Layout cell content: empty
  53. @access private */
  54. define("EMPTY_CELL", "" );
  55. /** Layout cell content: standard block
  56. @access private */
  57. define("BLOCK_CONTENT", "b");
  58. /** Layout cell content: HTMLArea wysiwyg editor
  59. @access private */
  60. define("WYSIWYG_EDITOR", "w");
  61. /** Layout cell content: plain cell
  62. @access private */
  63. define("PLAIN_CELL", "p");
  64.  
  65. // ......................................................................
  66. /**
  67. * Block
  68. * We define a class called a 'block'. This can contain multiple
  69. * 'blocklet' elements which fill up a block top-to-bottom. A block
  70. * can be divided into multiple columns, and blocklets fill these
  71. * left-to-right.
  72. * Blocklets can be of several defined blocklet_types:
  73. * Text, List, Ordered list, Bullets, and Table
  74. * A blocklet can also have a heading and a ruler defined for it,
  75. * with various formatting properties. Provision is also made for
  76. * inserting special 'tags' into the blocklet content which are
  77. * translated by the system accordingly. These are:
  78. * Data - tags to access database information
  79. * Images - reference to a resident image
  80. * Links - A clickable link (url)
  81. * Doc links - A link to a resident document file
  82. * @package cm
  83. */
  84. class block extends RenderableObject {
  85. // Public
  86. /** Whether the block exists in database or not */
  87.  
  88. var $exists = false;
  89. /** The id of the current block */
  90.  
  91. var $blockid = 0;
  92. /** The description of the current block */
  93.  
  94. var $block_desc;
  95. /** The language of the block (0 = default) */
  96.  
  97. var $language = 0;
  98. /** The language encoding code */
  99.  
  100. var $lang_encoding = "";
  101. /** The language text direction */
  102.  
  103. var $lang_direction = "";
  104. /** The number of columns in this block */
  105.  
  106. var $cols = 1;
  107. /** Width of inter-column gutter in pixels */
  108.  
  109. var $gutter_width = 0;
  110. /** Colour of inter-column gutter */
  111.  
  112. var $gutter_colour = "";
  113. /** Vertical separation of blocklets in pixels */
  114.  
  115. var $blocklet_sep = 0;
  116. /** Width of border in pixels */
  117.  
  118. var $border_width = 0;
  119. /** Colour of border */
  120.  
  121. var $border_colour = "";
  122. /** Colour of block background */
  123.  
  124. var $background_colour = "";
  125. /** Background image - ID from ax_catalog table, if defined */
  126.  
  127. var $background_img = NULLVALUE;
  128. /** Justification: 'left', 'center', 'right' */
  129.  
  130. var $justify = "";
  131. /** Vertical alignment: 'top', 'middle', 'bottom' */
  132.  
  133. var $valign = "";
  134. /** Manual style entered by user */
  135.  
  136. var $block_style = "";
  137. /** If true, then an EXPORT button will be provided for CSV dump */
  138.  
  139. var $exportable = false;
  140. /** Array of blocklet objects in this block */
  141.  
  142. var $blocklets = array();
  143. /** The layout this block belongs to */
  144.  
  145. var $layoutid;
  146. /** Version of layout this block belongs to (optional). If present
  147. then the version is included in forms as a hidden field. */
  148. var $layout_version = VERSION_UNDEFINED;
  149. /** Count of layout versions in existence. */
  150.  
  151. var $layout_version_count = 0;
  152. /** The language encoding for the containing layout */
  153.  
  154. var $layout_lang_encoding = "";
  155. /** The language direction for the containing layout */
  156.  
  157. var $layout_lang_direction = "";
  158. /** Type of block, ""=empty, "b"=block content, "w"=wysiwyg, "p"=plain cell */
  159.  
  160. var $block_type = "";
  161.  
  162. // Private
  163. /** The form name for the current block @access private */
  164.  
  165. var $blockfm = "";
  166. /** Mode of operation, 'viewing', 'editing', 'saving' @access private */
  167.  
  168. var $mode = "viewing";
  169. // ....................................................................
  170. /**
  171. * Constructor
  172. * Create a new block object.
  173. * Blocks are self-contained entities, and so this constructor is written
  174. * to return the rendered block content. This just allows you to avoid
  175. * having to make the render() call, and use the constructor to return
  176. * the block content in one hit.
  177. * @param string $id The unique name/identity of the block.
  178. * $return string The block content, whatever that may be.
  179. */
  180. function block($id=NEW_BLOCK) {
  181. // Deal with new block requirement..
  182. if ($id == NEW_BLOCK) {
  183. $id = get_next_sequencevalue("seq_block_id", "ax_block", "block_id");
  184. }
  185.  
  186. // Save block ID..
  187. $this->blockid = $id;
  188.  
  189. // Define a unique form name..
  190. $this->blockfm = "blockfm_$id";
  191.  
  192. // Process anything POSTed via form..
  193. $this->POSTprocess();
  194.  
  195. // Read it all from disk
  196. $this->get($id);
  197.  
  198. } // block
  199. // ....................................................................
  200. /**
  201. * Provide a blockeditor. This is used to instantiate a blockeditor
  202. * object for when we need to change this block somewhow. We only
  203. * need one, so we check if it's already been done first.
  204. */
  205. function activate_editing() {
  206. if (!isset($this->blockeditor)) {
  207. global $RESPONSE, $LIBDIR;
  208. include_once("block-editor-defs.php");
  209. $this->blockeditor = new blockeditor($this);
  210. }
  211. } // activate_editing
  212. // ....................................................................
  213. /**
  214. * Set the layout info for the layout which contains this block. If
  215. * defined the version is included in the block edit form as a hidden
  216. * field so that the layout can be kept across block form submission.
  217. * Both bits of data are also used to determine what happens regarding
  218. * for example indexing saved block content etc.
  219. * @param string $lver The version of the layout containing this block
  220. * @param integer $vercount The # versions of the layout
  221. * @param integer $lang The language ID of the layout
  222. * @param string $lang_enc The language encoding of the layout
  223. * @param string $lang_dir The language direction of the layout
  224. * @access private
  225. */
  226. function set_layout_info($ver=VERSION_UNDEFINED, $vercount=0, $lang=0, $lang_enc="", $lang_dir="") {
  227. $this->layout_version = $ver;
  228. $this->layout_version_count = $vercount;
  229. $this->layout_language = $lang;
  230. $this->layout_lang_encoding = $lang_enc;
  231. $this->layout_lang_direction = $lang_dir;
  232. } // set_layout_info
  233. // ....................................................................
  234. /**
  235. * Return true if the current user is permitted to edit block details.
  236. * We allow editing only for versions VERSION_PENDING and VERSION_LIVE
  237. * and the latter only for Editors.
  238. * @return boolean True if editing is permitted by current user.
  239. */
  240. function user_can_edit($required_version=VERSION_UNDEFINED) {
  241. global $RESPONSE;
  242. if ($this->layout_version == VERSION_UNDEFINED) {
  243. return true;
  244. }
  245. $perm = false;
  246. if ($required_version == VERSION_UNDEFINED ||
  247. $required_version == $this->layout_version) {
  248. // Pending version
  249. if ($this->layout_version == VERSION_PENDING ||
  250. $this->layout_version_count == 1) {
  251. if ($RESPONSE->ismemberof_group_in("Editor,Author")) {
  252. $perm = true;
  253. }
  254. }
  255. // Live version
  256. elseif ($this->layout_version == VERSION_LIVE) {
  257. if ($RESPONSE->ismemberof_group_in("Editor")) {
  258. $perm = true;
  259. }
  260. }
  261. }
  262. return $perm;
  263. } // user_can_edit
  264. // ....................................................................
  265. /**
  266. * Get the block.
  267. * Retrieves the specified block from database.
  268. * @param string $id The unique name/identity of the block to get
  269. */
  270. function get($id="") {
  271. global $RESPONSE;
  272. debug_trace($this);
  273. $this->exists = false;
  274.  
  275. // Assign the ID if given..
  276. if ($id != "") $this->blockid = $id;
  277.  
  278. // Try and find it..
  279. if ($RESPONSE->multilang) {
  280. $q = "SELECT * FROM ax_block, ax_language";
  281. $q .= " WHERE ax_block.block_id='" . addslashes($this->blockid) . "'";
  282. $q .= " AND ax_language.lang_id=ax_block.lang_id";
  283. }
  284. else {
  285. $q = "SELECT * FROM ax_block";
  286. $q .= " WHERE ax_block.block_id='" . addslashes($this->blockid) . "'";
  287. }
  288. $frq = dbrecordset($q);
  289. if ($frq->hasdata) {
  290. $this->layoutid = $frq->field("layout_id");
  291. $this->block_desc = $frq->field("block_desc");
  292. $this->cols = $frq->field("cols");
  293. if ($this->cols == "" || $this->cols <= 0) {
  294. $this->cols = 1;
  295. }
  296. if ($RESPONSE->multilang) {
  297. $this->language = $frq->field("lang_id");
  298. $this->lang_encoding = $frq->field("char_encoding");
  299. $this->lang_direction = $frq->field("direction");
  300. }
  301. $this->gutter_width = $frq->field("gutter_width");
  302. $this->gutter_colour = $frq->field("gutter_colour");
  303. $this->blocklet_sep = $frq->field("blocklet_sep");
  304. $this->background_colour = $frq->field("background_colour");
  305. $this->background_img = $frq->field("background_img");
  306. if ($this->background_img == "") {
  307. $this->background_img = NULLVALUE;
  308. }
  309. $this->justify = $frq->field("justify");
  310. $this->valign = $frq->field("valign");
  311. $this->border_width = $frq->field("border_width");
  312. $this->border_colour = $frq->field("border_colour");
  313. $this->block_style = $frq->field("block_style");
  314. $this->block_type = $frq->field("block_type");
  315. $this->exportable = $frq->istrue("exportable");
  316. $this->wysiwyg = $frq->istrue("wysiwyg");
  317. $this->exists = true;
  318.  
  319. // Get any defined blocklets. We do this here in one query
  320. // rather than using the blocklet class get() method, which
  321. // would be very inefficient..
  322. $q = "SELECT *";
  323. $q .= " FROM ax_block_blocklet bb, ax_blocklet b";
  324. $q .= " WHERE bb.block_id='" . addslashes($this->blockid) . "'";
  325. $q .= " AND b.blocklet_id=bb.blocklet_id";
  326. $q .= " ORDER BY bb.display_order";
  327. $frq = dbrecordset($q);
  328. if ($frq->hasdata) {
  329. do {
  330. $blockletid = $frq->field("blocklet_id");
  331. $blocklet = new blocklet();
  332. $blocklet->blockletid = $blockletid;
  333. $blocklet->visible = $frq->istrue("visible");
  334. $blocklet->display_order = $frq->field("display_order");
  335. $blocklet->blocklet_desc = $frq->field("blocklet_desc");
  336. $blocklet->type = $frq->field("blocklet_type");
  337. $blocklet->width = $frq->field("blocklet_width");
  338. $blocklet->justify = $frq->field("justify");
  339. $blocklet->heading = $frq->field("heading");
  340. $blocklet->heading_level = $frq->field("heading_level");
  341. $blocklet->heading_colour = $frq->field("heading_colour");
  342. $blocklet->ruler = $frq->field("ruler");
  343. $blocklet->ruler_width = $frq->field("ruler_width");
  344. $blocklet->ruler_size = $frq->field("ruler_size");
  345. $blocklet->ruler_colour = $frq->field("ruler_colour");
  346. $blocklet->content = $frq->field("content");
  347. $blocklet->content_size = $frq->field("content_size");
  348. $blocklet->content_colour = $frq->field("content_colour");
  349. $blocklet->blocklet_style = $frq->field("blocklet_style");
  350. $blocklet->table_style = $frq->field("table_style");
  351. $blocklet->table_autojustify = $frq->istrue("table_autojustify");
  352. $blocklet->table_rowstripes = $frq->istrue("table_rowstripes");
  353. // Stash blocklet..
  354. $this->blocklets[$blockletid] = $blocklet;
  355. } while ($frq->get_next());
  356. }
  357. }
  358. debug_trace();
  359. // Return true if at least the block exists..
  360. return $this->exists;
  361. } // get
  362. // ....................................................................
  363. /**
  364. * Save the block.
  365. * Save this block to the database. Create a new one if it
  366. * doesn't already exist.
  367. */
  368. function put() {
  369. debug_trace($this);
  370. // Deal with brand new block..
  371. start_transaction();
  372. if ($this->exists) {
  373. $frq = new dbupdate("ax_block");
  374. $frq->where("block_id=$this->blockid");
  375. }
  376. else {
  377. $frq = new dbinsert("ax_block");
  378. $frq->set("block_id", $this->blockid);
  379. }
  380. $frq->set("layout_id", $this->layoutid);
  381. $frq->set("block_desc", $this->block_desc);
  382. $frq->set("lang_id", $this->language);
  383. $frq->set("cols", $this->cols);
  384. $frq->set("gutter_width", $this->gutter_width);
  385. $frq->set("gutter_colour", $this->gutter_colour);
  386. $frq->set("background_colour", $this->background_colour);
  387. $frq->set("background_img", $this->background_img);
  388. $frq->set("justify", $this->justify);
  389. $frq->set("valign", $this->valign);
  390. $frq->set("border_width", $this->border_width);
  391. $frq->set("border_colour", $this->border_colour);
  392. $frq->set("blocklet_sep", $this->blocklet_sep);
  393. $frq->set("block_style", $this->block_style);
  394. $frq->set("block_type", $this->block_type);
  395. $frq->set("exportable", $this->exportable);
  396. $frq->set("last_modified", 'now()');
  397. $this->exists = $frq->execute();
  398.  
  399. // Save any blocklets..
  400. if (isset($this->blocklets)) {
  401. foreach ($this->blocklets as $blocklet) {
  402. $blockletexists = $blocklet->exists;
  403. $blocklet->put();
  404. if ($blockletexists) {
  405. $frq = new dbupdate("ax_block_blocklet");
  406. $frq->where("block_id=$this->blockid");
  407. $frq->where("AND blocklet_id=$blocklet->blockletid");
  408. }
  409. else {
  410. $frq = new dbinsert("ax_block_blocklet");
  411. $frq->set("block_id", $this->blockid);
  412. $frq->set("blocklet_id", $blocklet->blockletid);
  413. }
  414. $frq->set("visible", $blocklet->visible);
  415. $frq->set("display_order", $blocklet->display_order);
  416. $frq->execute();
  417. } // foreach
  418. }
  419. commit();
  420. debug_trace();
  421. } // put
  422. // ....................................................................
  423. /**
  424. * Replicate this block into a new block with a new set of blocklets
  425. * as a complete content copy of this original block.
  426. * NOTE: We end up with this current block as the replicated one.
  427. */
  428. function replicate($layoutname="") {
  429. $this->activate_editing();
  430. $this->blockeditor->replicate($layoutname);
  431. } // replicate
  432. // ....................................................................
  433. /**
  434. * Add a new blocklet to the block.
  435. * This adds a new blocklet to the list, but does not add any records
  436. * to the database.
  437. */
  438. function add_blocklet() {
  439. debug_trace($this);
  440. $blocklet = new blocklet();
  441. $blocklet->blockletid = get_next_sequencevalue("seq_blocklet_id", "ax_blocklet", "blocklet_id");
  442. $blocklet->display_order = 999;
  443. $this->blocklets[$blocklet->blockletid] = $blocklet;
  444. debug_trace();
  445. } // add_blocklet
  446. // ....................................................................
  447. /**
  448. * Remove blocklet from the block.
  449. * We remove the entry from the block_blocklet link table, and, if it
  450. * is the last link involving the blocklet we delete the blocklet record.
  451. */
  452. function remove_blocklet($id) {
  453. debug_trace($this);
  454. if (isset($this->blocklets[$id])) {
  455. $q = "DELETE FROM ax_block_blocklet";
  456. $q .= " WHERE block_id=$this->blockid";
  457. $q .= " AND blocklet_id=$id";
  458. dbcommand($q);
  459. $chkq = "SELECT * FROM ax_block_blocklet WHERE blocklet_id=$id";
  460. if (!$chkq->hasdata) {
  461. $blocklet = $this->blocklets[$id];
  462. $blocklet->delete();
  463. }
  464. // Remove it from our list..
  465. unset($this->blocklets[$id]);
  466. }
  467. debug_trace();
  468.  
  469. } // remove_blocklet
  470. // ....................................................................
  471. /**
  472. * Delete this block from the database. NB: we do not rely on RI to do
  473. * this since various versions of Postgres don't support this nicely.
  474. * All related entities are explicitly deleted in a transaction.
  475. */
  476. function delete() {
  477. $this->activate_editing();
  478. $this->blockeditor->delete();
  479. } // delete
  480. // ....................................................................
  481. /**
  482. * Index the block.
  483. * Index all blocklets of this block using Lucene, if Lucene indexing is
  484. * enabled (via the configvalue 'Lucene Site Indexing'). This has no effect
  485. * unless you are using the Axyl framework.
  486. * Notes: This method indexes the blocklets in this block which are at
  487. * the present time in the database, ie. not the blocklets as defined in
  488. * this block object. This method is usually called from the POSTprocess()
  489. * method, just after saving any changes to the database.
  490. * @param string $path The relative path to the webpage this block is in
  491. * @param string $title The title of the webpage this block is in
  492. * @param string $category The category string to index content with
  493. * @param string $metadata Metadata object containing metadata to index
  494. */
  495. function index($path, $title, $category="", $metadata=false) {
  496. global $RESPONSE, $CONTEXT;
  497. debug_trace($this);
  498. if ( isset($CONTEXT) && $CONTEXT->configvalue("Lucene Site Indexing") ) {
  499. include_once("lucene-defs.php");
  500. // Read content from DB since it may have just been saved..
  501. $q = "SELECT b.heading, b.content";
  502. $q .= " FROM ax_block_blocklet bb, ax_blocklet b";
  503. $q .= " WHERE bb.block_id=$this->blockid";
  504. $q .= " AND b.blocklet_id=bb.blocklet_id";
  505. $bQ = dbrecordset($q);
  506. $allcontent = array();
  507. $allcontent[] = $RESPONSE->head->title;
  508. if ($bQ->hasdata) {
  509. do {
  510. $allcontent[] = $bQ->field("heading");
  511. $allcontent[] = $bQ->field("content");
  512. } while ($bQ->get_next());
  513. }
  514. $I = new lucene_indexmsg();
  515. $I->index_field("category:Text", ($category == "" ? "sitecontent" : $category));
  516. $I->index_field("path:Text", $path);
  517. $I->index_field("title:Text", $title);
  518. $I->index_field("lastmodified:Date", time());
  519. if ($RESPONSE->multilang && $this->language > 0) {
  520. $I->index_field("language:Text", $this->language);
  521. }
  522. // Add in any metadata fields being supplied..
  523. if ($metadata !== false && count($metadata->metadata_elements) > 0) {
  524. foreach ($metadata->metadata_elements as $element_id => $element) {
  525. if ($element->tag_name != "" && $element->tag_value != "") {
  526. $I->index_field($element->tag_name . ":Text", $element->tag_value);
  527. }
  528. }
  529. }
  530. $I->index_content("AXYLBLOCKID_$this->blockid", implode(" ", $allcontent));
  531. $I->send();
  532. }
  533. debug_trace();
  534. } // index
  535. // ....................................................................
  536. /**
  537. * Un-index the block.
  538. * Un-index this block from Lucene, if Lucene indexing is enabled (via
  539. * the configvalue 'Lucene Site Indexing'). This has no effect if you are
  540. * not using the Axyl framework.
  541. */
  542. function unindex() {
  543. global $CONTEXT;
  544. debug_trace($this);
  545. // Deal with Lucene indexing if enabled. In this case we then
  546. // use the unique block_id as the index ID, and unindex from
  547. // Lucene so that references to this block are removed..
  548. if ( isset($CONTEXT) && $CONTEXT->configvalue("Lucene Site Indexing") ) {
  549. include_once("lucene-defs.php");
  550. $UI = new lucene_unindexmsg();
  551. $UI->unindex("AXYLBLOCKID_$this->blockid");
  552. $UI->send();
  553. }
  554. debug_trace();
  555. } // unindex
  556. // ....................................................................
  557. /**
  558. * Render the Wysiwyg editing suite.
  559. * @return string The HTML for the editing suite form etc.
  560. * @access private
  561. */
  562. function wysiwyg_editform($lang_encoding, $lang_direction) {
  563. $this->activate_editing();
  564. return $this->blockeditor->wysiwyg_editform($lang_encoding, $lang_direction);
  565. } // wysiwyg_editform
  566. // ....................................................................
  567. /**
  568. * Render the block editing suite.
  569. * @return string The HTML for the editing suite form etc.
  570. * @access private
  571. */
  572. function block_editform($lang_encoding, $lang_direction) {
  573. $this->activate_editing();
  574. return $this->blockeditor->block_editform($lang_encoding, $lang_direction);
  575. } // block_editform
  576. // ....................................................................
  577. /**
  578. * Render the block content.
  579. * @return string The HTML
  580. * @access private
  581. */
  582. function blockcontent($lang_encoding, $lang_direction) {
  583. debug_trace($this);
  584. global $LIBDIR;
  585. global $RESPONSE;
  586. $editing = false;
  587.  
  588. $s = "";
  589.  
  590. // Render the blocklets in a table..
  591. $Tvw = new table($this->blockid);
  592.  
  593. // Apply supplemental style, if given..
  594. if ($this->block_style != "") {
  595. $Tvw->setstyle($this->block_style);
  596. }
  597.  
  598. // Apply background image if there is one..
  599. if ($this->background_img != NULLVALUE) {
  600. $qQ = dbrecordset("SELECT * FROM ax_catalog WHERE cat_id=$this->background_img");
  601. if ($qQ->hasdata) {
  602. $src = $qQ->field("filepath");
  603. $Tvw->setbackground($src);
  604. }
  605. }
  606.  
  607. // Apply border styles, if we have a border..
  608. $bdrstyle = "";
  609. if ($this->border_width > 0) {
  610. $bdrstyle = "border-width:" . $this->border_width . "px;";
  611. $bdrstyle .= "border-color:" . $this->border_colour . ";";
  612. $bdrstyle .= "border-style:solid;";
  613. $Tvw->setstyle($bdrstyle);
  614. }
  615.  
  616. if ($this->mode != "previewing" && $RESPONSE->ismemberof_group_in("Editor,Author")) {
  617. $editor = true;
  618. if ($bdrstyle == "") {
  619. $Tvw->setstyle("border-width:1px;border-style:dotted;border-color:#ff0000;");
  620. }
  621. // Tools for the toolbar
  622. $toolbar = array();
  623. if ($this->user_can_edit()) {
  624. $toolbar[] = new form_imagebutton("_edit", "", "", "$LIBDIR/img/_edit.gif", "Edit block", 42, 15);
  625. }
  626.  
  627. // Toolbar table
  628. $Tbar = new table("toolbar");
  629. $Tbar->tr("axtitle");
  630. $Tbar->th("[B$this->blockid]", "axtitle");
  631. $tools = "";
  632. foreach ($toolbar as $tool) {
  633. $tools .= $tool->render();
  634. }
  635. $Tbar->th($tools, "axtitle");
  636. $Tbar->th_css("text-align:right");
  637.  
  638. // Put toolbar into table..
  639. $Tvw->tr("axtitle");
  640. $Tvw->td( $Tbar->render(), "axtitle" );
  641. }
  642.  
  643. // Generate an ordered array of our visible blocklets..
  644. if (isset($this->blocklets)) {
  645. $ordblocklets = array();
  646. foreach ($this->blocklets as $blocklet) {
  647. if ($blocklet->visible) {
  648. $ordblocklets[$blocklet->blockletid] = $blocklet->display_order;
  649. }
  650. }
  651. asort($ordblocklets, SORT_NUMERIC);
  652. $visible_blocklets = array();
  653. foreach($ordblocklets as $blockletid => $order) {
  654. $visible_blocklets[] = $blockletid;
  655. }
  656.  
  657. // Ascertain blocklet display metrics..
  658. $tot_blocklets = count($visible_blocklets);
  659. $tot_rows = ceil($tot_blocklets / $this->cols);
  660.  
  661. // Render the blocklets..
  662. $Tvw->tr();
  663. $Tvw->td();
  664. $Tvw->td_alignment("", "top");
  665.  
  666. $Tbl = new table("B" . $this->blockid);
  667. if ($this->background_colour != "") {
  668. $Tbl->setbgcolor($this->background_colour);
  669. }
  670. $Tbl->tr();
  671. $bc = 0;
  672. $col = 1;
  673. $widthpct = floor(100 / $this->cols);
  674. foreach ($visible_blocklets as $blockletid) {
  675. $blocklet = $this->blocklets[$blockletid];
  676. if ($bc++ % $tot_rows == 0) {
  677. if (isset($Tcol)) {
  678. // Put the last blocklets column in..
  679. $Tbl->td_content($Tcol->render());
  680. unset($Tcol);
  681.  
  682. // If multi-column and guttering enabled, make a
  683. // gutter column here..
  684. if ($this->cols > 1 && $this->gutter_width > 0) {
  685. $gutc = (($this->gutter_colour != "") ? $this->gutter_colour : "black");
  686. $Tbl->td();
  687. //$Tbl->td_metrics($this->gutter_width);
  688. $guts .= "border-right:" . $this->gutter_width . "px ";
  689. $guts .= " solid";
  690. $guts .= " $this->gutter_colour;";
  691. $Tbl->td_css($guts);
  692. }
  693. }
  694. // Make new cell for next column..
  695. $Tbl->td();
  696. $Tbl->td_alignment("", "top");
  697. if ($bc == $tot_blocklets) $widthpct += 1;
  698. $Tbl->td_metrics("$widthpct%");
  699. $Tcol = new table("B" . $this->blockid . "_" . $col++);
  700. }
  701. $Tcol->tr();
  702. $Tcol->td($blocklet->html());
  703. if ($this->blocklet_sep > 0 && $tot_blocklets > 1 && $bc < $tot_blocklets) {
  704. $Tcol->tr();
  705. $Tcol->td();
  706. $Tcol->td_height($this->blocklet_sep);
  707. }
  708. }
  709. if (isset($Tcol)) {
  710. $Tbl->td_content($Tcol->render());
  711. }
  712. $Tvw->td_content( $Tbl->render() );
  713. }
  714.  
  715. // Render the content table..
  716. $s .= $Tvw->render();
  717.  
  718. debug_trace();
  719. // Return the html..
  720. return $s;
  721. } // blockcontent
  722.  
  723. // ....................................................................
  724. /**
  725. * Render the block content as a CSV formatted stream. This is designed
  726. * to facilitate the exporting of complex tables of data as CSV format
  727. * for importing into spreadsheets, or databases etc.
  728. * @return string The content in CSV format.
  729. */
  730. function csv() {
  731. debug_trace($this);
  732. $s = "";
  733. // Generate an ordered array of our visible blocklets..
  734. if (isset($this->blocklets)) {
  735. $ordblocklets = array();
  736. foreach ($this->blocklets as $blocklet) {
  737. if ($blocklet->visible) {
  738. $ordblocklets[$blocklet->blockletid] = $blocklet->display_order;
  739. }
  740. }
  741. asort($ordblocklets, SORT_NUMERIC);
  742. $visible_blocklets = array();
  743. while (list($blockletid, $order) = each($ordblocklets)) {
  744. $visible_blocklets[] = $blockletid;
  745. }
  746. foreach ($visible_blocklets as $blockletid) {
  747. $blocklet = $this->blocklets[$blockletid];
  748. $s .= $blocklet->csv() . "\n";
  749. }
  750. }
  751. debug_trace();
  752. // Return the csv stream..
  753. return $s;
  754. } // csv
  755.  
  756. // ....................................................................
  757. /**
  758. * Render the block content according to the mode of operation
  759. * we are in. Possible modes: 'viewing', 'editing', 'saving'.
  760. * @return string The HTML
  761. */
  762. function html() {
  763. debug_trace($this);
  764. global $LIBDIR;
  765. global $RESPONSE;
  766. global $edit_blockid;
  767.  
  768. // Language details..
  769. $lang_encoding = "";
  770. $lang_direction = "";
  771. $language = $this->language;
  772. if ($RESPONSE->multilang) {
  773. if ($this->language != 0) {
  774. $lang_encoding = $this->lang_encoding;
  775. $lang_direction = $this->lang_direction;
  776. }
  777. else {
  778. if ($this->layout_language != 0) {
  779. $language = $this->layout_language;
  780. $lang_encoding = $this->layout_lang_encoding;
  781. $lang_direction = $this->layout_lang_direction;
  782. }
  783. }
  784. // Make sure RESPONSE takes note of language setting. If this
  785. // language was already added, it doesn't matter..
  786. if ($language != 0) {
  787. $RESPONSE->add_language($language);
  788. }
  789. }
  790.  
  791. $s = "";
  792. // Start form for editing..
  793. if ($this->exportable || $RESPONSE->ismemberof_group_in("Editor,Author")) {
  794. $s .= "<form name=\"$this->blockfm\" method=\"post\" enctype=\"multipart/form-data\">";
  795. }
  796.  
  797. switch($this->mode) {
  798. case "editing":
  799. // Make sure edit request is meant for us..
  800. if (!isset($edit_blockid) || $edit_blockid != $this->blockid) {
  801. return "";
  802. }
  803. // Deal with first block edit. In this case it won't yet
  804. // exist in the database, so we create it here..
  805. if (!$this->exists) {
  806. $this->put();
  807. }
  808. $this->mode = "saving";
  809. // Show the appropriate editing form..
  810. switch ($this->block_type) {
  811. case WYSIWYG_EDITOR:
  812. $s .= $this->wysiwyg_editform($lang_encoding, $lang_direction);
  813. break;
  814. default:
  815. $s .= $this->block_editform($lang_encoding, $lang_direction);
  816. } // switch
  817. break;
  818.  
  819. default:
  820. if ($this->mode != "viewing" && $this->mode != "previewing") {
  821. $this->mode = "viewing";
  822. }
  823. $s .= $this->blockcontent($lang_encoding, $lang_direction);
  824. if ($this->exportable) {
  825. $expbtn = new form_imagebutton("_exportblock");
  826. $expbtn->setimage("$LIBDIR/img/_export.gif", "Export this information in CSV format");
  827. $s .= "<p>" . $expbtn->render() . "</p>";
  828. }
  829. } // switch
  830.  
  831. // Finish the form..
  832. if ($this->exportable || $RESPONSE->ismemberof_group_in("Editor,Author")) {
  833. // Include action hidden field, and block ID
  834. $mode = new form_hiddenfield("blockmode", $this->mode);
  835. $blid = new form_hiddenfield("edit_blockid", $this->blockid);
  836. $s .= $mode->render() . $blid->render();
  837. // Layout version hidden field
  838. if ($this->layout_version != VERSION_UNDEFINED) {
  839. $lvers = new form_hiddenfield("layout_version", $this->layout_version);
  840. $lvcnt = new form_hiddenfield("layout_version_count", $this->layout_version_count);
  841. $s .= $lvers->render() . $lvcnt->render();
  842. }
  843. $s .= "</form>\n";
  844. }
  845.  
  846. return $s;
  847. } // html
  848. // ....................................................................
  849. /**
  850. * Process a block edit form POST.
  851. * Assume that the fields have been submitted in a form as named
  852. * in the config, and grab the POSTed values. This method is executed
  853. * from the constructor usually, before anything is read in from
  854. * the database. We get first shot to change data here.
  855. * @param text $id The identity of the set to update from POST
  856. * @access private
  857. */
  858. function POSTprocess() {
  859. debug_trace($this);
  860. global $CONTEXT, $RESPONSE, $LIBDIR;
  861. global $edit_blockid;
  862.  
  863. if (isset($edit_blockid) && $edit_blockid == $this->blockid) {
  864. global $_done_x, $_edit_x, $_exportblock_x, $blockmode;
  865. $this->mode = $blockmode;
  866. switch ($this->mode) {
  867. case "viewing":
  868. // Check for editing mode..
  869. if (isset($_edit_x)) {
  870. $this->mode = "editing";
  871. }
  872. // Check for user export button-press. In this
  873. // case we deliver CSV content, and exit..
  874. elseif (isset($_exportblock_x)) {
  875. $exptitle = $RESPONSE->body->title;
  876. if ($exptitle == "") {
  877. $exptitle = $this->blockid;
  878. }
  879. $this->get();
  880. $csv = $this->csv();
  881. $RESPONSE->discard();
  882. $RESPONSE->set_encoding("", "text/csv");
  883. header("Content-Disposition: attachment; filename=$exptitle.csv");
  884. echo $csv;
  885. exit;
  886. }
  887. break;
  888.  
  889. case "saving":
  890. if ($edit_blockid == $this->blockid) {
  891. global $_csvimport_x, $blocklet_id;
  892. global $_save_x, $_cancel_x, $_done_x;
  893. global $_wysiwygpost_form;
  894. global $_recmaintpost_form;
  895. global $_recmaintpost_data;
  896. global $_recmaintpost_flds;
  897. global $_recmaintpost_dels;
  898. global $_recmaintpost_order;
  899.  
  900. // Let me out of here..
  901. if (isset($_done_x) || isset($_cancel_x)) {
  902. // Drop through to viewing..
  903. $this->mode = "viewing";
  904. }
  905. // Posted record maintenance data..
  906. elseif ( isset($_recmaintpost_form)
  907. && $_recmaintpost_form == $this->blockfm) {
  908. // Posted CSV table data. This data is to be appended to
  909. // the blocklet content as a table..
  910. if (isset($_csvimport_x) && isset($blocklet_id)) {
  911. $up = new fileupload();
  912. if ($up->uploaded_count >= 1) {
  913. // Process a uploaded file(s)..
  914. $file_mime = $up->mimetype;
  915. if ($file_mime != CONTENT_CSV) {
  916. $file_mime = mimetype_from_filename($up->filename);
  917. }
  918. if ($file_mime == CONTENT_CSV) {
  919. // Process the file..
  920. $fup = new csv_inputfile($up->filepath);
  921. $tablerow = false;
  922. $newtable = "";
  923. if ($fup->opened) {
  924. do {
  925. $tablerow = $fup->readln();
  926. if ($tablerow) {
  927. $newtable .= implode("|", $tablerow) . "\n";
  928. }
  929. } while ($tablerow);
  930. $fup->closefile();
  931. if ($newtable != "") {
  932. $ob = dbrecordset("SELECT content FROM ax_blocklet WHERE blocklet_id=$blocklet_id");
  933. if ($ob->hasdata) {
  934. $orig_content = $ob->field("content");
  935. if ($orig_content != "") $orig_content .= "\n";
  936. $ub = new dbupdate("ax_blocklet");
  937. $ub->set("content", $orig_content . $newtable);
  938. $ub->set("blocklet_type", "table");
  939. $ub->where("blocklet_id=$blocklet_id");
  940. $ub->execute();
  941. }
  942. }
  943. }
  944. else {
  945. $emsg = "failed to open uploaded file: '$up->filename'";
  946. $errmsgs[] = $emsg;
  947. debugbr($emsg, DBG_DEBUG);
  948. }
  949. }
  950. else {
  951. $emsg = "Not a comma-separated variable (CSV) file: '$up->filename'";
  952. $errmsgs[] = $emsg;
  953. debugbr($emsg, DBG_DEBUG);
  954. }
  955. }
  956. else {
  957. $emsg = "Nothing was uploaded.";
  958. $errmsgs[] = $emsg;
  959. debugbr($emsg, DBG_DEBUG);
  960. }
  961. // Drop through to viewing..
  962. $this->mode = "editing";
  963.  
  964. } // if CSV import
  965.  
  966. else {
  967. // Deal with Save, Delete, Re-ordering etc..
  968. if (isset($_recmaintpost_dels) && $_recmaintpost_dels != "") {
  969. $blocklet_delids = explode(FIELD_DELIM, $_recmaintpost_dels);
  970. foreach ($blocklet_delids as $delblockletid) {
  971. dbcommand("DELETE FROM ax_blocklet WHERE blocklet_id=$delblockletid");
  972. }
  973. }
  974. // Blocklet adds and saves..
  975. if (isset($_recmaintpost_data) && $_recmaintpost_data != "") {
  976. $blockletrecs = explode(RECORD_DELIM, $_recmaintpost_data);
  977. $blocklet_fields = explode(",", $_recmaintpost_flds);
  978. foreach ($blockletrecs as $blockletrec) {
  979. $blocklet_values = explode(FIELD_DELIM, $blockletrec);
  980. $blockletid = array_shift($blocklet_values);
  981. // Cater for new creations..
  982. if (strstr($blockletid, "NEW_")) {
  983. $savedid = $blockletid;
  984. $blockletid = get_next_sequencevalue("seq_blocklet_id", "ax_blocklet", "blocklet_id");
  985. $ib = new dbinsert("ax_blocklet");
  986. $ib->set("blocklet_id", $blockletid);
  987. $ib->execute();
  988. $ibb = new dbinsert("ax_block_blocklet");
  989. $ibb->set("block_id", $this->blockid);
  990. $ibb->set("blocklet_id", $blockletid);
  991. $ibb->set("display_order", 99);
  992. $ibb->execute();
  993. // Fix up potential re-ordering id..
  994. if (isset($_recmaintpost_order)) {
  995. $_recmaintpost_order = str_replace("$savedid", "$blockletid", $_recmaintpost_order);
  996. }
  997. }
  998. // Update the blocklet data..
  999. $bu = new dbupdate("ax_blocklet");
  1000. $bu->where("blocklet_id=$blockletid");
  1001. $pos = 0;
  1002. foreach ($blocklet_fields as $blocklet_field) {
  1003. if ($blocklet_field == "visible") {
  1004. $visible_value = $blocklet_values[$pos++];
  1005. }
  1006. else {
  1007. $bu->set($blocklet_field, $blocklet_values[$pos++]);
  1008. }
  1009. }
  1010. $bu->execute();
  1011. // Now save the visibility flag..
  1012. if (isset($visible_value)) {
  1013. $bu = new dbupdate("ax_block_blocklet");
  1014. $bu->where("block_id=$this->blockid AND blocklet_id=$blockletid");
  1015. $bu->set("visible", ($visible_value == "t"));
  1016. $bu->execute();
  1017. }
  1018. } // foreach blockletrecs
  1019. }
  1020.  
  1021. // Save block properties..
  1022. global $block_desc, $language, $block_style;
  1023. global $cols, $gutter_width, $gutter_colour;
  1024. global $background_colour, $background_img;
  1025. global $block_justify, $block_valign;
  1026. global $block_border_width, $block_border_colour;
  1027. global $blocklet_sep, $block_exportable;
  1028. if (isset($cols) && $cols > 0) {
  1029. $bu = new dbupdate("ax_block");
  1030. $bu->where("block_id=$this->blockid");
  1031. $bu->set("block_desc", $block_desc);
  1032. $bu->set("lang_id", $language);
  1033. $bu->set("cols", $cols);
  1034. $bu->set("gutter_width", $gutter_width);
  1035. $bu->set("gutter_colour", $gutter_colour);
  1036. $bu->set("blocklet_sep", $blocklet_sep);
  1037. $bu->set("background_colour", $background_colour);
  1038. $bu->set("background_img", $background_img);
  1039. $bu->set("justify", $block_justify);
  1040. $bu->set("valign", $block_valign);
  1041. $bu->set("border_width", $block_border_width);
  1042. $bu->set("border_colour", $block_border_colour);
  1043. $bu->set("block_style", $block_style);
  1044. $bu->set("exportable", isset($block_exportable));
  1045. $bu->execute();
  1046. }
  1047.  
  1048. // Check/save blocklet ordering..
  1049. if (isset($_recmaintpost_order) && $_recmaintpost_order != "") {
  1050. $ord = 1;
  1051. $idlist = explode(FIELD_DELIM, $_recmaintpost_order);
  1052. foreach ($idlist as $blockletid) {
  1053. $upd = new dbupdate("ax_block_blocklet");
  1054. $upd->where("block_id=$this->blockid AND blocklet_id=$blockletid");
  1055. $upd->set("display_order", $ord);
  1056. $upd->execute();
  1057. $ord += 1;
  1058. }
  1059. }
  1060.  
  1061. // Index the block with current webpage path and title..
  1062. global $layout_version, $layout_version_count;
  1063. if (!isset($layout_version) ||
  1064. $layout_version == VERSION_LIVE ||
  1065. $layout_version_count == 1) {
  1066. debugbr("indexing saved block. Layout ver=$layout_version", DBG_DEBUG);
  1067. $this->index($RESPONSE->requested, $RESPONSE->head->title);
  1068. }
  1069.  
  1070. // Drop through to viewing..
  1071. $this->mode = "viewing";
  1072. }
  1073. }
  1074. // Is it a wysiwyg post..
  1075. elseif ( isset($_wysiwygpost_form)
  1076. && $_wysiwygpost_form == $this->blockfm) {
  1077. global $wysiwyg_content;
  1078. $this->get();
  1079. $bb = current($this->blocklets);
  1080. if (isset($bb) && isset($bb->blockletid)) {
  1081. // Remove any extraneous </object> tags that htmlarea might have inserted..
  1082. $wysiwyg_content = str_replace("</object>", "", $wysiwyg_content);
  1083. $bbup = new dbupdate("ax_blocklet");
  1084. $bbup->set("content", $wysiwyg_content);
  1085. $bbup->where("blocklet_id=$bb->blockletid");
  1086. $bbup->execute();
  1087. $this->blocklets[$bb->blockletid] = $bb;
  1088. }
  1089. // Also save some of the block properties..
  1090. global $block_desc, $block_style;
  1091. global $background_colour, $background_img;
  1092. global $block_justify, $block_valign;
  1093. global $block_border_width, $block_border_colour;
  1094. $bu = new dbupdate("ax_block");
  1095. $bu->where("block_id=$this->blockid");
  1096. $bu->set("block_desc", $block_desc);
  1097. $bu->set("background_colour", $background_colour);
  1098. $bu->set("background_img", $background_img);
  1099. $bu->set("justify", $block_justify);
  1100. $bu->set("valign", $block_valign);
  1101. $bu->set("border_width", $block_border_width);
  1102. $bu->set("border_colour", $block_border_colour);
  1103. $bu->set("block_style", $block_style);
  1104. $bu->execute();
  1105. }
  1106. }
  1107. break;
  1108. } // switch
  1109. }
  1110. // If the user preference says so, then set the mode to
  1111. // content preview mode..
  1112. $prefs = new configuration("preferences", $RESPONSE->userid);
  1113. if ($prefs->field_exists("Content Preview Mode")) {
  1114. if ($prefs->value("Content Preview Mode") === true) {
  1115. $this->mode = "previewing";
  1116. }
  1117. }
  1118. debug_trace();
  1119. } // POSTprocess
  1120.  
  1121.  
  1122.  
  1123. } // block class
  1124. // ----------------------------------------------------------------------
  1125.  
  1126. /**
  1127. * The blocklet is simply a part of a block. It is almost a 'paragraph' of
  1128. * content, excepting that a blocklet might have content of several text
  1129. * paragraphs, so it is something slightly different, hence the name. This
  1130. * class knows how to get, save and delete blocklets, and how to render
  1131. * them as html.
  1132. * @package cm
  1133. */
  1134. class blocklet extends RenderableObject {
  1135. /** blocklet ID */
  1136.  
  1137. var $blockletid;
  1138. /** Whether blocklet exists in database */
  1139.  
  1140. var $exists = false;
  1141. /** The description of the current blocklet */
  1142.  
  1143. var $desc = "";
  1144. /** The blocklet type: 'text', 'list', 'ordered', 'bullets', or 'table' */
  1145.  
  1146. var $type = "text";
  1147. /** The width % of the blocklet table */
  1148.  
  1149. var $width = 100;
  1150. /** Justification: 'left', 'right', 'centered' */
  1151.  
  1152. var $justify = "left";
  1153. /** blocklet heading */
  1154.  
  1155. var $heading;
  1156. /** blocklet heading level (1-6) */
  1157.  
  1158. var $heading_level = 3;
  1159. /** Heading colour */
  1160.  
  1161. var $heading_colour = "";
  1162. /** blocklet ruler: 'none', 'top', 'bottom' */
  1163.  
  1164. var $ruler = "none";
  1165. /** Ruler width percent: 0-100 */
  1166.  
  1167. var $ruler_width = 100;
  1168. /** Ruler pixel size */
  1169.  
  1170. var $ruler_size = 1;
  1171. /** Ruler colour */
  1172.  
  1173. var $ruler_colour = "";
  1174. /** Blocklet textual content */
  1175.  
  1176. var $content = "";
  1177. /** Content size adjustment -2 thru +2 */
  1178.  
  1179. var $content_size = 0;
  1180. /** Content colour */
  1181.  
  1182. var $content_colour = "";
  1183. /** Manual style to apply to content */
  1184.  
  1185. var $blocklet_style = "";
  1186. /** Table style to apply to content */
  1187.  
  1188. var $table_style = "";
  1189. /** True if we autojustify table */
  1190.  
  1191. var $table_autojustify = false;
  1192. /** True if we autojustify table */
  1193.  
  1194. var $table_rowstripes = false;
  1195. /** Whether blocklet is visible */
  1196.  
  1197. var $visible = true;
  1198. /** Display order of this blocklet */
  1199.  
  1200. var $display_order = 1;
  1201. // ....................................................................
  1202. /**
  1203. * Constructor
  1204. * Create a new blocklet object.
  1205. * @param string $id The unique identity of the blocklet.
  1206. */
  1207. function blocklet($id=NEW_BLOCKLET) {
  1208. $this->blockletid = $id;
  1209. $this->get($id);
  1210.  
  1211. } // blocklet
  1212. // ....................................................................
  1213. /**
  1214. * Get the blocklet.
  1215. * Retrieves the specified blocklet from database.
  1216. * @param string $id The unique integer identity of the blocklet to get.
  1217. */
  1218. function get($id) {
  1219. debug_trace($this);
  1220. $this->exists = false;
  1221. if ($id != NEW_BLOCKLET) {
  1222. // Try and read in existing blocklet info..
  1223. $q = "SELECT * FROM ax_blocklet";
  1224. $q .= " WHERE blocklet_id=$id";
  1225. $blq = dbrecordset($q);
  1226. if ($blq->hasdata) {
  1227. $this->blocklet_desc = $blq->field("blocklet_desc");
  1228. $this->type = $blq->field("blocklet_type");
  1229. $this->justify = $blq->field("justify");
  1230. $this->heading = $blq->field("heading");
  1231. $this->heading_level = $blq->field("heading_level");
  1232. $this->heading_colour = $blq->field("heading_colour");
  1233. $this->ruler = $blq->field("ruler");
  1234. $this->ruler_width = $blq->field("ruler_width");
  1235. $this->ruler_size = $blq->field("ruler_size");
  1236. $this->ruler_colour = $blq->field("ruler_colour");
  1237. $this->content = $blq->field("content");
  1238. $this->content_size = $blq->field("content_size");
  1239. $this->content_colour = $blq->field("content_colour");
  1240. $this->blocklet_style = $blq->field("blocklet_style");
  1241. $this->table_style = $blq->field("table_style");
  1242. $this->table_autojustify = $blq->istrue("table_autojustify");
  1243. $this->table_rowstripes = $blq->istrue("table_rowstripes");
  1244. $this->exists = true;
  1245. }
  1246. }
  1247. debug_trace();
  1248. // Return true if at least the blocklet exists..
  1249. return $this->exists;
  1250. } // get
  1251. // ....................................................................
  1252. /**
  1253. * Save the blocklet.
  1254. * Save this blocklet to the database. Create a new one if it
  1255. * doesn't already exist.
  1256. */
  1257. function put() {
  1258. debug_trace($this);
  1259. // Deal with brand new blocklet..
  1260. if (!$this->exists) {
  1261. // If we are in need of a new ID, then get one..
  1262. if ($this->blockletid == NEW_BLOCKLET) {
  1263. $this->blockletid = get_next_sequencevalue("seq_blocklet_id", "ax_blocklet", "blocklet_id");
  1264. }
  1265. $blq = new dbinsert("ax_blocklet");
  1266. $blq->set("blocklet_id", $this->blockletid);
  1267. }
  1268. else {
  1269. $blq = new dbupdate("ax_blocklet");
  1270. $blq->where("blocklet_id=$this->blockletid");
  1271. }
  1272. $blq->set("blocklet_desc", $this->blocklet_desc);
  1273. $blq->set("blocklet_type", $this->type);
  1274. $blq->set("justify", $this->justify);
  1275. $blq->set("heading", $this->heading);
  1276. $blq->set("heading_level", $this->heading_level);
  1277. $blq->set("heading_colour", $this->heading_colour);
  1278. $blq->set("ruler", $this->ruler);
  1279. $blq->set("ruler_width", $this->ruler_width);
  1280. $blq->set("ruler_size", $this->ruler_size);
  1281. $blq->set("ruler_colour", $this->ruler_colour);
  1282. $blq->set("content", $this->content);
  1283. $blq->set("content_size", $this->content_size);
  1284. $blq->set("content_colour", $this->content_colour);
  1285. $blq->set("blocklet_style", $this->blocklet_style);
  1286. $blq->set("table_style", $this->table_style);
  1287. $blq->set("table_autojustify", $this->table_autojustify);
  1288. $blq->set("table_rowstripes", $this->table_rowstripes);
  1289. $this->exists = $blq->execute();
  1290. debug_trace();
  1291. } // put
  1292. // ....................................................................
  1293. /**
  1294. * Delete the blocklet.
  1295. * Delete this blocklet from the database.
  1296. */
  1297. function delete() {
  1298. debug_trace($this);
  1299. // Don't assume RI wil delete the block_blocklets of this blocklet..
  1300. $del = new dbdelete("ax_block_blocklet");
  1301. $del->where("blocklet_id=$this->blockletid");
  1302. $del->execute();
  1303. $del = new dbdelete("ax_blocklet");
  1304. $del->where("blocklet_id=$this->blockletid");
  1305. $del->execute();
  1306. debug_trace();
  1307. } // delete
  1308. // ....................................................................
  1309. /**
  1310. * Content style.
  1311. * Returns an internal class style string based on the values of
  1312. * properties: content_colour and content_size. Returns the string
  1313. * as bare style specs 'font-size:0.8em;' etc.
  1314. * $access private
  1315. */
  1316. function content_css() {
  1317. $s = "";
  1318. if ($this->content_colour != "") {
  1319. $s .= "color:$this->content_colour;";
  1320. }
  1321. if ($this->content_size != 0) {
  1322. $em = number_format( (10 + $this->content_size)/10, 2);
  1323. $s .= "font-size:$em" . "em;";
  1324. }
  1325. if ($this->blocklet_style != "") {
  1326. $s .= $this->blocklet_style;
  1327. if (substr($this->blocklet_style, -1) != ";") {
  1328. $s .= ";";
  1329. }
  1330. }
  1331. return $s;
  1332. } // content_css
  1333. // ....................................................................
  1334. /**
  1335. * Content style.
  1336. * Returns an internal class style string based on the values of
  1337. * properties: content_colour and content_size. Returns the string
  1338. * as a full 'style="..." style, ready for a <span> tag etc..
  1339. * $access private
  1340. */
  1341. function content_style() {
  1342. $s = $this->content_css();
  1343. if ($s != "") $s = " style=\"$s\"";
  1344. return $s;
  1345. } // content_style
  1346. // ....................................................................
  1347. /**
  1348. * Format Content.
  1349. * Formats the given content according to the given content type.
  1350. * $access private
  1351. */
  1352. function format_content($content, $type="text", $css="") {
  1353. $s = "";
  1354. if (is_numeric($content)) $content = number_format($content);
  1355. switch ($type) {
  1356. // Vanilla list..
  1357. case "list":
  1358. $list = new vl($css);
  1359. $list->items = explode("\n", $content);
  1360. $s = $list->render();
  1361. break;
  1362. // Ordered list..
  1363. case "ordered":
  1364. $list = new ol($css);
  1365. $list->items = explode("\n", $content);
  1366. $s = $list->render();
  1367. break;
  1368. // Bullet points list..
  1369. case "bullets":
  1370. $list = new ul($css);
  1371. $list->items = explode("\n", $content);
  1372. $s = $list->render();
  1373. break;
  1374.  
  1375. case "table":
  1376. $t = new table("BKT_$this->blockletid");
  1377. if ($this->table_autojustify) {
  1378. $t->autojustify();
  1379. }
  1380. if ($this->table_rowstripes) {
  1381. $t->rowstripes("axyl_rowstripe_dark,axyl_rowstripe_lite");
  1382. }
  1383. $t->setpadding(2);
  1384. if ($this->table_style != "") {
  1385. $t->setcss($this->table_style);
  1386. }
  1387. // Assemble table..
  1388. $wprofile = "";
  1389. $rows = explode("\n", $content);
  1390. if (count($rows) > 0) {
  1391. foreach ($rows as $row) {
  1392. if (strstr($row, "~")) {
  1393. $wprofile = trim(str_replace("~", ",", $row));
  1394. }
  1395. else {
  1396. $t->tr();
  1397. // Heading rows use '^' separator..
  1398. if (strstr($row, "^")) {
  1399. $cells = explode("^", $row);
  1400. foreach ($cells as $cell) {
  1401. $t->th($cell);
  1402. $t->th_contentcss($css);
  1403. }
  1404. }
  1405. // Normal body rows use '|' separator..
  1406. else {
  1407. $cells = explode("|", $row);
  1408. foreach ($cells as $cell) {
  1409. $t->td($cell);
  1410. $t->td_alignment("", "top");
  1411. $t->td_contentcss($css);
  1412. }
  1413. }
  1414. }
  1415. } // foreach row
  1416. }
  1417. // Apply any width profile we got..
  1418. if ($wprofile != "") {
  1419. $t->set_width_profile($wprofile);
  1420. }
  1421. // Now put together the whole table..
  1422. $s .= $t->render();
  1423. break;
  1424.  
  1425. // Text content..
  1426. case "text":
  1427. // Paragraph content..
  1428. $style = $css;
  1429. if ($style != "") $style = " style=\"$style\"";
  1430. $para = "<p" . $style . ">";
  1431. $content = str_replace("\r\n\r\n", "$para", $content);
  1432. $s .= $sizetags . $para . $content . $sizeuntags;
  1433. break;
  1434.  
  1435. // Other content, raw content
  1436. default:
  1437. $s .= $sizetags . $content . $sizeuntags;
  1438. break;
  1439.  
  1440. } // switch
  1441.  
  1442. // Return content
  1443. return $s;
  1444. } // format_content
  1445.  
  1446. // ....................................................................
  1447. /**
  1448. * Render the blocklet as a CSV stream. We split the content types for
  1449. * this into 'table' and 'other'. For tables we use the "|" delimiter to
  1450. * determine where our commas go. For other content we basically just
  1451. * leave it as-is, only adding quotes.
  1452. * @return string The CSV formatted blocklet content.
  1453. */
  1454. function csv() {
  1455. debug_trace($this);
  1456. global $RESPONSE;
  1457.  
  1458. $content = strip_tags( $this->expanded_content() );
  1459. $content = str_replace("\r", "\n", $content);
  1460.  
  1461. // Format depending on type: 'text', 'list', 'ordered',
  1462. // 'bullets', or 'table'
  1463. switch ($this->type) {
  1464. case "table":
  1465. $rows = explode("\n", $content);
  1466. $content = "";
  1467. if (count($rows) > 0) {
  1468. foreach ($rows as $row) {
  1469. $csvrow = "";
  1470. if ($row != "" && $row != "\n" && !strstr($row, "~")) {
  1471. $row = str_replace("^", "|", $row);
  1472. $row = str_replace("\"", "\"\"", $row);
  1473. $bits = explode("|", $row);
  1474. $csvrow = "";
  1475. foreach ($bits as $bit) {
  1476. $csvrow .= "\"$bit\",";
  1477. }
  1478. $csvrow = substr($csvrow, 0, -1);
  1479. }
  1480. $content .= $csvrow;
  1481. if (substr($content, -1, 1) != "\n") {
  1482. $content .= "\n";
  1483. }
  1484. }
  1485. }
  1486. break;
  1487.  
  1488. default:
  1489. $content = str_replace("\"", "\"\"", $content);
  1490. $content = "\"$content\"";
  1491. break;
  1492. }
  1493. debug_trace();
  1494. // Return the CSV..
  1495. return $content;
  1496. } // csv
  1497. // ....................................................................
  1498. /**
  1499. * Process the current blocklet content for special tags. This effectively
  1500. * expands the special tags into 'real' content from database, or as image
  1501. * references etc. We return the expanded content as a string.
  1502. * @return string The new content, expanded as appropriate to the tags.
  1503. * $access private
  1504. */
  1505. function expanded_content() {
  1506. // Pre-process content for datasources..
  1507. $content = $this->content;
  1508. $matches = array();
  1509. //$datapat = "/(<MEDIA (.*?)>|<IMAGE (.*?)>|<DATA (.*?)>|<DOCUMENT (.*?)>)/i";
  1510. $datapat = "/(<object (.*?)>)/i";
  1511. while ( preg_match($datapat, $content, $matches) ) {
  1512. $datatag = $matches[0];
  1513. $dataparms = $matches[1];
  1514. $attributes = extractAttributes($datatag);
  1515. $new_content = "";
  1516. $type = strtolower($attributes["type"]);
  1517. if (count($attributes) > 0 && $type == "axyl/embedded-media") {
  1518. $mediatype = strtolower($attributes["codetype"]);
  1519. switch ($mediatype) {
  1520. // DATA
  1521. case "data":
  1522. $quid = $attributes["id"];
  1523. $format = $attributes["format"];
  1524. $where = $attributes["where"];
  1525. $tableheadings = (isset($attributes["tableheadings"]));
  1526. if ($quid != "") {
  1527. $qQ = dbrecordset("SELECT * FROM ax_query_resource WHERE quid=$quid");
  1528. if ($qQ->hasdata) {
  1529. // Datasource content..
  1530. if ($qQ->field("q_query") != "") {
  1531. $datasrc = unserialize($qQ->field("q_query"));
  1532. // Apply any block-level where clause..
  1533. if ($where != "") {
  1534. if ($datasrc->where->total > 0) {
  1535. if (strtolower(substr($where, 0, 3)) != "and") {
  1536. $where = "and $where";
  1537. }
  1538. }
  1539. $datasrc->where($where);
  1540. }
  1541. $raw_content = "";
  1542. // Handle table headings if required..
  1543. if ($format == "table" && $tableheadings) {
  1544. $fieldnames = explode(",", $datasrc->fields->listed());
  1545. $headings = array();
  1546. foreach ($fieldnames as $fieldname) {
  1547. if (strstr($fieldname, ".")) {
  1548. $bits = explode(".", $fieldname);
  1549. $fieldname = $bits[1];
  1550. }
  1551. $headings[] = ucfirst(str_replace("_", " ", $fieldname));
  1552. }
  1553. $raw_content .= implode("^", $headings) . "\n";
  1554. }
  1555. // Get datasource data..
  1556. $datasrc->execute();
  1557. if ($datasrc->hasdata) {
  1558. do {
  1559. $data = array();
  1560. for ($i=0; $i < $datasrc->fields->total; $i++) {
  1561. $data[] = $datasrc->current_row[$i];
  1562. }
  1563. switch ($format) {
  1564. case "list":
  1565. case "ordered":
  1566. case "bullets":
  1567. $raw_content .= implode(" ", $data) . "\n";
  1568. break;
  1569. case "table":
  1570. $raw_content .= implode("|", $data) . "\n";
  1571. break;
  1572. default:
  1573. $raw_content .= implode(" ", $data);
  1574. } // switch
  1575. } while ($datasrc->get_next());
  1576. $new_content = $this->format_content(
  1577. $raw_content,
  1578. $format,
  1579. $this->content_css()
  1580. );
  1581. }
  1582. }
  1583. // Script-generated content..
  1584. elseif ($qQ->field("q_script") != "") {
  1585. debugbr("execute script here.", DBG_DEBUG);
  1586. }
  1587. }
  1588. }
  1589. // case data
  1590. break;
  1591.  
  1592. // IMAGE
  1593. case "image":
  1594. $catid = $attributes["id"];
  1595. $align = $attributes["align"];
  1596. $pad = $attributes["pad"];
  1597. $tooltip = $attributes["title"];
  1598. $width = $attributes["width"];
  1599. $height = $attributes["height"];
  1600. $border = $attributes["border"];
  1601. $bdcolor = $attributes["bordercolor"];
  1602. if ($catid != "") {
  1603. $qQ = dbrecordset("SELECT * FROM ax_catalog WHERE cat_id=$catid");
  1604. if ($qQ->hasdata) {
  1605. $src = $qQ->field("filepath");
  1606. if ($width == 0 || $width == "") $width = $qQ->field("width");
  1607. if ($width == 0 || $width == "") $width = false;
  1608. if ($height == 0 || $height == "") $height = $qQ->field("height");
  1609. if ($height == 0 || $height == "") $height = false;
  1610. $img=new img($src, $catid, $tooltip, $width, $height);
  1611. if ($border != "") {
  1612. $img->setborder($border);
  1613. $img->setstyle("border-style:solid;border-width:" . $border . "px;");
  1614. if ($bdcolor != "") $img->setstyle("border-color:$bdcolor;");
  1615. }
  1616. if ($align != "") $img->setalign($align);
  1617. if ($pad != "") {
  1618. $img->sethspace($pad);
  1619. $img->setvspace($pad);
  1620. }
  1621. $new_content = $img->render();
  1622. }
  1623. }
  1624. break;
  1625.  
  1626. // MEDIA or DOCUMENT
  1627. case "media":
  1628. case "document":
  1629. $new_content = "";
  1630. $catid = $attributes["id"];
  1631. $display = $attributes["display"];
  1632. $width = $attributes["width"];
  1633. $height = $attributes["height"];
  1634. if ($mediatype == "media") {
  1635. $autostart = ($attributes["autostart"] == "yes");
  1636. $loop = ($attributes["loop"] == "yes");
  1637. $showcontrols = ($attributes["showcontrols"] == "yes");
  1638. }
  1639. if ($width == 0 || $width == "") $width = 200;
  1640. if ($height == 0 || $height == "") $height = 200;
  1641. $tooltip = $attributes["title"];
  1642. if ($catid != "") {
  1643. $qQ = dbrecordset("SELECT * FROM ax_catalog WHERE cat_id=$catid");
  1644. if ($qQ->hasdata) {
  1645. $src = $qQ->field("filepath");
  1646. $category = $qQ->field("mime_category");
  1647. switch ($category) {
  1648. case "movie":
  1649. $media = new MediaObject($src, $width, $height, $autostart, $loop, $showcontrols);
  1650. switch ($display) {
  1651. case "icon": $media->AsIcon($tooltip); break;
  1652. case "link": $media->AsLink($tooltip); break;
  1653. }
  1654. break;
  1655. case "audio":
  1656. $media = new MediaObject($src, $width, $height, $autostart, $loop, $showcontrols);
  1657. switch ($display) {
  1658. case "icon": $media->AsIcon($tooltip); break;
  1659. case "link": $media->AsLink($tooltip); break;
  1660. }
  1661. break;
  1662. case "flash":
  1663. $media = new FlashObject($src, $width, $height, $autostart, $loop);
  1664. switch ($display) {
  1665. case "icon": $media->AsIcon($tooltip); break;
  1666. case "link": $media->AsLink($tooltip); break;
  1667. }
  1668. break;
  1669. case "document":
  1670. $media = new DocumentObject($src, $width, $height);
  1671. switch ($display) {
  1672. case "icon": $media->AsIcon($tooltip); break;
  1673. case "link": $media->AsLink($tooltip, "_new"); break;
  1674. }
  1675. break;
  1676. } // switch
  1677. if (is_object($media)) {
  1678. $new_content = $media->render();
  1679. }
  1680. }
  1681. }
  1682. break;
  1683. }// switch
  1684. } // got attributes
  1685.  
  1686. // Replace data tag with new content..
  1687. $content = str_replace($datatag, $new_content, $content);
  1688. } // while
  1689.  
  1690. // Return the processed content..
  1691. return $content;
  1692.  
  1693. } // expanded_content
  1694. // ....................................................................
  1695. /**
  1696. * Render the blocklet.
  1697. * @return string The HTML
  1698. */
  1699. function html() {
  1700. debug_trace($this);
  1701.  
  1702. $s = "";
  1703.  
  1704. // Main Blocklet Table
  1705. $btable = new table("BKT_$this->blockletid");
  1706.  
  1707. // Set table width if specified..
  1708. if ($this->width != "") {
  1709. $btable->setwidth($this->width . "%");
  1710. }
  1711.  
  1712. if ($RESPONSE->browser != BROWSER_NETSCAPE) {
  1713. $btable->setalign($this->justify);
  1714. }
  1715.  
  1716. // TOP RULER
  1717. if ($this->ruler == "top") {
  1718. $btable->tr();
  1719. $rul = new hr("$this->ruler_width%", $this->ruler_size, $this->ruler_colour);
  1720. $btable->td( $rul->render() );
  1721. $btable->td_alignment($this->justify);
  1722. }
  1723.  
  1724. // HEADING
  1725. if ($this->heading != "") {
  1726. $HTAG = "h$this->heading_level";
  1727. $btable->tr();
  1728. $btable->td("<$HTAG>" . $this->heading . "</$HTAG>");
  1729. $btable->td_alignment($this->justify);
  1730. if ($this->heading_colour != "") {
  1731. $btable->td_contentcss("color:$this->heading_colour");
  1732. }
  1733. }
  1734.  
  1735. // CONTENT
  1736. // First, expand any special tags..
  1737. $content = $this->expanded_content();
  1738.  
  1739. // Now, render the content..
  1740. if ($content != "") {
  1741. $btable->tr();
  1742. // Format the content..
  1743. $scell = $this->format_content(
  1744. $content,
  1745. $this->type,
  1746. $this->content_css()
  1747. );
  1748. // Add the blocklet content to the table..
  1749. $btable->td($scell);
  1750. $btable->td_alignment($this->justify);
  1751. } // if got content
  1752.  
  1753. // BOTTOM RULER
  1754. if ($this->ruler == "bottom") {
  1755. $btable->tr();
  1756. $rul = new hr("$this->ruler_width%", $this->ruler_size, $this->ruler_colour);
  1757. $btable->td( $rul->render() );
  1758. $btable->td_alignment($this->justify);
  1759. }
  1760.  
  1761. // END TABLE DIV
  1762. $s .= $btable->render();
  1763.  
  1764. debug_trace();
  1765. // Return the HTML..
  1766. return $s;
  1767. } // html
  1768.  
  1769.  
  1770.  
  1771. } // blocklet class
  1772. // ----------------------------------------------------------------------
  1773.  
  1774. /** Utility function to extract content attributes from string.
  1775. * Incoming Format is:
  1776. * <tagname attrname="attrvalue" attrname="attrvalue" ... >
  1777. * Returns an associative array:
  1778. * An element 'tagname' will contain the tag name:
  1779. * returnedarray["tagname"] = tagname
  1780. * Other elements one for each attribute:
  1781. * returnedarray["attrname"] = attrvalue
  1782. * @access private
  1783. */
  1784. function extractAttributes($str){
  1785. $attrs = array();
  1786. if (preg_match("/<(.*?) (.*?)>/i", $str, $matches) ) {
  1787. $attrs["tagname"] = $matches[1];
  1788. $attributes = trim($matches[2]);
  1789. if (preg_match_all("/(.*?)=\"(.*?)\"/i", $attributes, $matches)) {
  1790. $total = count($matches[0]);
  1791. for ($tagno = 0; $tagno < $total; $tagno++) {
  1792. if (trim($matches[1][$tagno]) != "") {
  1793. $attrname = trim(strtolower($matches[1][$tagno]));
  1794. $attrval = trim($matches[2][$tagno]);
  1795. $attrs[$attrname] = $attrval;
  1796. }
  1797. }
  1798. }
  1799. }
  1800. return $attrs;
  1801. } // extractAttributes
  1802. // ----------------------------------------------------------------------
  1803.  
  1804. ?>

Documentation generated by phpDocumentor 1.3.0RC3