Source for file layout-defs.php

Documentation is available at layout-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: layout-defs.php */
  22. /* Author: Paul Waite */
  23. /* Description: Definitions for content layout management in webpages. */
  24. /* */
  25. /* ******************************************************************** */
  26. /** @package cm */
  27. include_once("block-defs.php");
  28.  
  29. // ----------------------------------------------------------------------
  30. /** New layout to be created */
  31. ("NEW_LAYOUT", -1);
  32.  
  33. // ......................................................................
  34. // Anything which is editing and uses layouts might need to save data.
  35.  
  36. $update_delim = "^~";
  37. $RESPONSE->body->add_script(
  38. "function sto(fld, fm) {\n"
  39. . " var datFld = eval('document.forms.' + fm + '._update_data');\n"
  40. . " if (datFld != null) {\n"
  41. . " fname = fld.name;\n"
  42. . " if (datFld.value != '') datFld.value += '$update_delim';\n"
  43. . " datFld.value += fname + '|' + escape(fld.value);\n"
  44. . " }\n"
  45. . "}\n"
  46. );
  47.  
  48. // ......................................................................
  49. /**
  50. * Find content layout tags in a string.
  51. * These are of the format: <!--LAYOUTID="my layout id"--> and there
  52. * may be any number (including zero) of these in the string.
  53. * Returns a string which is the passed-in string with the tags
  54. * replaced by the rendered layout content.
  55. * @param string The string to search for layout definitions
  56. * @return string The string with all layout content rendered into it
  57. */
  58. function render_layouts($s) {
  59. $mytimer = new microtimer();
  60. $rs = $s;
  61. if (stristr($rs, "LAYOUTID=")) {
  62. preg_match_all("/<!--LAYOUTID=\"(.+)\"-->/i", $rs, $matches);
  63. for ($i=0; $i< count($matches[0]); $i++) {
  64. $layouttag = $matches[0][$i];
  65. $layoutid = $matches[1][$i];
  66. debugbr("layout: rendering $layoutid", DBG_DEBUG);
  67. $mylayout = new named_layout($layoutid);
  68. $rs = str_replace($layouttag, $mylayout->render(), $rs);
  69. }
  70. }
  71. debug_trace();
  72. return $rs;
  73. } // render_layouts
  74. // ......................................................................
  75.  
  76. /**
  77. * Layout
  78. * A layout can be simply viewed as a table definition. The table cells
  79. * can contain blocks, and so this entity is provided to allow control
  80. * of how blocks of content can be arranged on a webpage.
  81. * @package cm
  82. */
  83. class layout extends RenderableObject {
  84. // Public
  85. /** The unique ID of this layout */
  86.  
  87. var $layoutid = 0;
  88. /** The name of the current layout */
  89.  
  90. var $layout_name = "";
  91. /** The language of the layout (0 = default) */
  92.  
  93. var $language = 0;
  94. /** The language encoding code */
  95.  
  96. var $lang_encoding = "";
  97. /** The language text direction */
  98.  
  99. var $lang_direction = "";
  100. /** True if we should display last modified date */
  101.  
  102. var $show_last_modified = false;
  103. /** The format string for last modified datetime */
  104.  
  105. var $format_last_modified = NICE_DATE;
  106. /** The prefix string for last modified datetime */
  107.  
  108. var $prefix_last_modified = "";
  109. /** The index category of the current layout - used with Lucene indexing */
  110.  
  111. var $index_category = "";
  112. /** Table width specification */
  113.  
  114. var $table_width = "";
  115. /** Table autojustify flag */
  116.  
  117. var $table_autojustify = false;
  118. /** Table rowstriping mode flag */
  119.  
  120. var $table_rowstripes = false;
  121. /** Whether the layout exists in database or not */
  122.  
  123. var $exists = false;
  124.  
  125. // Private
  126. /** The layout table itself
  127. @access private */
  128. var $layout_table;
  129. /** The name of the layout form
  130. @access private */
  131. var $layoutfm = "layoutform";
  132. /** The group privilege settings for this layout, as
  133. read from the database.
  134. @access private */
  135. var $privileges = array();
  136. /** The groups which have privilege settings for this layout, as
  137. read from the database.
  138. @access private */
  139. var $privilege_groups = array();
  140. /** The group membership for Editor privilege
  141. @access private */
  142. var $editor_groups = array(DEFAULT_EDITOR_GROUPS);
  143. /** The group membership for Authoring privilege
  144. @access private */
  145. var $author_groups = array(DEFAULT_AUTHOR_GROUPS);
  146. /** The group membership for Entry privilege
  147. @access private */
  148. var $entry_groups = array(DEFAULT_ENTRY_GROUPS);
  149. /** The layout blocks, keyed on 'row|col'
  150. @access private */
  151. var $layout_blocks = array();
  152. /** Supplemental layout table style
  153. @access private */
  154. var $layout_style = "";
  155. /** Total rows in layout
  156. @access private */
  157. var $tot_rows = 0;
  158. /** Total columns in layout
  159. @access private */
  160. var $tot_cols = 0;
  161. /** Total empty/undefined cells
  162. @access private */
  163. var $tot_empty = 0;
  164. /** Total cells containing a content block
  165. @access private */
  166. var $tot_block = 0;
  167. /** Total plain content cells
  168. @access private */
  169. var $tot_plain = 0;
  170. /** Total wysiwyg content cells
  171. @access private */
  172. var $tot_wysiwyg = 0;
  173. /** Total editable plain content cells
  174. @access private */
  175. var $tot_editable = 0;
  176. /** Total viewable plain content cells
  177. @access private */
  178. var $tot_viewable = 0;
  179. /** Array of layout blocks in edit mode
  180. @access private */
  181. var $edit_blocks = array();
  182. /** Array of layout cells with edit permission
  183. @access private */
  184. var $editable_cells = array();
  185. /** Array of layout cells with view permission
  186. @access private */
  187. var $viewable_cells = array();
  188. /** Last modified date/time string.
  189. Most recently modified block in layout.
  190. @access private */
  191. var $last_modified = "";
  192. /** Table style to apply for plain cells table
  193. @access private */
  194. var $table_style = "";
  195. /** Message to display (optional)
  196. @access private */
  197. var $message = "";
  198. /** Local layouteditor object, only instantiated if the
  199. layout requires editing services.
  200. @access private */
  201. var $layouteditor;
  202. // ....................................................................
  203. /**
  204. * Constructor
  205. * Create a new layout object. To create a new layout then just leave
  206. * leave the argument list empty.
  207. * @param string $id The unique name/identity of the layout.
  208. */
  209. function layout($id=NEW_LAYOUT) {
  210. // Creating new layout..
  211. if ($id == NEW_LAYOUT) {
  212. $id = get_next_sequencevalue("seq_layout_id", "ax_layout", "layout_id");
  213. }
  214.  
  215. // Save block ID..
  216. $this->layoutid = $id;
  217.  
  218. // Define a unique form name..
  219. $this->layoutfm = "layoutfm_$id";
  220.  
  221. // Read it from database
  222. $this->get($id);
  223. } // layout
  224. // ....................................................................
  225. /**
  226. * Provide a layouteditor. This is used to instantiate a layouteditor
  227. * object for when we need to change this layout somewhow. We only
  228. * need one, so we check if it's already been done first.
  229. */
  230. function activate_editing() {
  231. if (!isset($this->layouteditor)) {
  232. global $RESPONSE, $LIBDIR;
  233. include_once("layout-editor-defs.php");
  234. $this->layouteditor = new layouteditor($this);
  235. }
  236. } // activate_editing
  237. // ....................................................................
  238. /**
  239. * Get the layout.
  240. * Retrieves the specified layout from database.
  241. * @param string $name The name/identity of the layout to get
  242. */
  243. function get($id) {
  244. global $RESPONSE;
  245. debug_trace($this);
  246. $this->exists = false;
  247.  
  248. // Try and find it..
  249. if ($RESPONSE->multilang) {
  250. $q = "SELECT * FROM ax_layout, ax_language";
  251. $q .= " WHERE ax_layout.layout_id=$id";
  252. $q .= " AND ax_language.lang_id=ax_layout.lang_id";
  253. }
  254. else {
  255. $q = "SELECT * FROM ax_layout";
  256. $q .= " WHERE ax_layout.layout_id=$id";
  257. }
  258. // Privilege settings
  259. $this->privileges = array();
  260. $this->privilege_groups = array();
  261. $Lq = dbrecordset($q);
  262. if ($Lq->hasdata) {
  263. $this->layoutid = $id;
  264. // Check for editor & author groups overrides..
  265. $q = "SELECT * FROM ax_layout_set_group lg, ax_group g";
  266. $q .= " WHERE g.group_id=lg.group_id";
  267. $Lsec = dbrecordset($q);
  268. if ($Lsec->hasdata) {
  269. $editor = array();
  270. $author = array();
  271. $entry = array();
  272. do {
  273. $group_id = $Lsec->field("group_id");
  274. $group_desc = $Lsec->field("group_desc");
  275. $group_priv = $Lsec->field("cm_privilege");
  276. $this->privileges["$group_priv|$group_id"] = $group_desc;
  277. $this->privilege_groups[$group_id] = $group_desc;
  278. switch ($group_priv) {
  279. case "editor":
  280. $editor[] = $group_desc;
  281. break;
  282. case "author":
  283. $author[] = $group_desc;
  284. break;
  285. case "entry":
  286. $entry[] = $group_desc;
  287. break;
  288. } // switch
  289. } while ($Lsec->get_next());
  290. debugbr("layout privileges override:", DBG_DEBUG);
  291. if (count($editor) > 0) {
  292. $this->editor_groups = $editor;
  293. debugbr(" --> editor privilege: " . implode(",", $editor), DBG_DEBUG);
  294. }
  295. if (count($author) > 0) {
  296. $this->author_groups = $author;
  297. debugbr(" --> author privilege: " . implode(",", $author), DBG_DEBUG);
  298. }
  299. if (count($entry) > 0) {
  300. $this->entry_groups = $entry;
  301. debugbr(" --> entry privilege: " . implode(",", $entry), DBG_DEBUG);
  302. }
  303. }
  304. else {
  305. debugbr("default privilege settings apply");
  306. }
  307. // Back-fill with all non-privileged groups
  308. $Gp = dbrecordset("SELECT * FROM ax_group");
  309. if ($Gp->hasdata) {
  310. $unprivileged = array();
  311. do {
  312. $group_id = $Gp->field("group_id");
  313. $group_desc = $Gp->field("group_desc");
  314. if (!isset($this->privilege_groups[$group_id])) {
  315. $this->privileges["none|$group_id"] = $group_desc;
  316. $unprivileged[$group_id] = $group_desc;
  317. }
  318. } while ($Gp->get_next());
  319. foreach($unprivileged as $gid => $gdesc) {
  320. $this->privilege_groups[$gid] = $gdesc;
  321. }
  322. }
  323. // Continue populating layout data..
  324. $this->layout_name = $Lq->field("layout_name");
  325. if ($RESPONSE->multilang) {
  326. $this->language = $Lq->field("lang_id");
  327. $this->lang_encoding = $Lq->field("char_encoding");
  328. $this->lang_direction = $Lq->field("direction");
  329. }
  330. $this->layout_style = $Lq->field("layout_style");
  331. $this->index_category = $Lq->field("index_category");
  332. $sertable = $Lq->field("layout_table");
  333. if ($sertable != "") {
  334. $this->layout_table = unserialize($sertable);
  335. }
  336. $this->format_last_modified = $Lq->field("format_last_modified");
  337. if ($this->format_last_modified == "") {
  338. $this->format_last_modified = NICE_DATE;
  339. }
  340. $this->prefix_last_modified = $Lq->field("prefix_last_modified");
  341. $this->show_last_modified = ($Lq->field("show_last_modified") == "t");
  342. if ($this->show_last_modified) {
  343. $lmts = 0;
  344. $q = "SELECT MAX(last_modified) AS lastmod FROM ax_block";
  345. $q .= " WHERE layout_id=$id";
  346. $Lm = dbrecordset($q);
  347. if ($Lm->hasdata) {
  348. $lmdt = $Lm->field("lastmod");
  349. if ($lmdt != "") {
  350. $lmts = datetime_to_timestamp($lmdt);
  351. }
  352. }
  353. // Table modification time..
  354. if (isset($this->layout_table) && isset($this->layout_table->last_modified)) {
  355. $ts = $this->layout_table->last_modified;
  356. if ($ts > $lmts) $lmts = $ts;
  357. }
  358. // Save modstamp string..
  359. if ($lmts > 0) {
  360. $this->last_modified = timestamp_to_displaydate($this->format_last_modified, $lmts);
  361. if ($this->prefix_last_modified != "") {
  362. $this->last_modified = $this->prefix_last_modified . " " . $this->last_modified;
  363. }
  364. }
  365. }
  366. $this->exists = true;
  367. }
  368. // Ensure we have a table for layout..
  369. if (!isset($this->layout_table) || $this->layout_table->cellcount() == 0) {
  370. $this->layout_table = new matrix(1, 1, "&nbsp;");
  371. $this->layout_table->tablename = "layout:$this->layout_name";
  372. $this->layout_table->setwidth("100%");
  373. }
  374.  
  375. // Get the layout cell information..
  376. $this->tot_empty = 0;
  377. $this->tot_block = 0;
  378. $this->tot_plain = 0;
  379. $this->tot_wysiwyg = 0;
  380. $this->tot_editable = 0;
  381. $this->tot_viewable = 0;
  382. $this->editable_cells = array();
  383. $this->viewable_cells = array();
  384. $this->tot_rows = $this->layout_table->rowcount();
  385. $this->tot_cols = $this->layout_table->cellcount();
  386. if ($this->exists) {
  387. for ($row=0; $row < $this->tot_rows; $row++) {
  388. for ($col=0; $col < $this->tot_cols; $col++) {
  389. if ($this->layout_table->cell_exists($row, $col)) {
  390. $cell = $this->layout_table->get_cell($row, $col);
  391. $this->layout_blocks["$row|$col"] = $cell->blockid;
  392. if (!isset($cell->celltype)) {
  393. $this->tot_empty += 1;
  394. }
  395. else {
  396. switch ($cell->celltype) {
  397. case BLOCK_CONTENT: $this->tot_block += 1; break;
  398. case PLAIN_CELL: $this->tot_plain += 1; break;
  399. case WYSIWYG_EDITOR: $this->tot_wysiwyg += 1; break;
  400. }
  401. if (isset($cell->access) && isset($RESPONSE)) {
  402. if ($RESPONSE->ismemberof_group_in( array_merge($this->editor_groups, $this->author_groups) ) ||
  403. ($RESPONSE->ismemberof_group_in( $this->entry_groups ) && $this->is_pendingver())
  404. ) {
  405. if ($cell->access->anypermitted($RESPONSE->group_names_list(), PERM_UPDATE)) {
  406. $this->tot_editable += 1;
  407. $this->editable_cells["$row|$col"] = true;
  408. }
  409. }
  410. if ($cell->access->anypermitted($RESPONSE->group_names_list(), PERM_READ)) {
  411. $this->tot_viewable += 1;
  412. $this->viewable_cells["$row|$col"] = true;
  413. }
  414. }
  415. }
  416. }
  417. else {
  418. $this->tot_empty += 1;
  419. }
  420. }
  421. }
  422. }
  423. debug_trace();
  424. // Return true if at least the block exists..
  425. return $this->exists;
  426. } // get
  427. // ....................................................................
  428. /**
  429. * Save the layout.
  430. * Save this layout to the database. Create a new one if it
  431. * doesn't already exist.
  432. */
  433. function put() {
  434. debug_trace($this);
  435. // Timestamp the change in the table object itself..
  436. $this->layout_table->last_modified = time();
  437.  
  438. // Deal with brand new layout..
  439. if ($this->exists) {
  440. $Lq = new dbupdate("ax_layout");
  441. $Lq->where("layout_id=" . $this->layoutid);
  442. }
  443. else {
  444. $Lq = new dbinsert("ax_layout");
  445. $Lq->set("layout_id", $this->layoutid);
  446. }
  447. $Lq->set("layout_name", $this->layout_name);
  448. $Lq->set("lang_id", $this->language);
  449. $Lq->set("layout_style", $this->layout_style);
  450. $Lq->set("index_category", $this->index_category);
  451. $Lq->set("layout_table", serialize($this->layout_table));
  452. $Lq->set("show_last_modified", $this->show_last_modified);
  453. $Lq->set("format_last_modified", $this->format_last_modified);
  454. $Lq->set("prefix_last_modified", $this->prefix_last_modified);
  455. $this->exists = $Lq->execute();
  456. debug_trace();
  457. } // put
  458. // ....................................................................
  459. /**
  460. * Replicate the hosted layout as a new layout. Creates a brand new
  461. * layout in the database, with same data as this one. The end result
  462. * is that this current object becomes the new layout, and a duplicate
  463. * set of layout records exist in the database. The layout ID of this
  464. * new layout is, of course, updated to being a brand new one.
  465. * NOTES: The layout name is normally left null, which keeps the layout
  466. * in the same 'family' of layout versions. You can force the layout
  467. * name to be different, and this will create a new 'layout_set'
  468. * record of that name for you, if required.
  469. * @param string $layoutname New layout name. If null, keeps same name.
  470. */
  471. function replicate($layoutname="") {
  472. $this->activate_editing();
  473. $this->layouteditor->replicate($layoutname);
  474. } // replicate
  475. // ....................................................................
  476. /**
  477. * Delete the hosted layout from the database. Afterwards, the current object
  478. * still exists as it was before this method was executed, but the
  479. * $this->layout->exists flag will have been reset to false.
  480. */
  481. function delete() {
  482. $this->activate_editing();
  483. $this->layouteditor->delete();
  484. } // delete
  485. // ....................................................................
  486. /**
  487. * Paste the given layout into this layout, replacing the complete
  488. * definition as it currently stands, with the new one. To do this
  489. * we delete the current layout from the database, get() the new
  490. * layout from the database, and then replicate it, morphing this
  491. * object into the brand new layout. All layout and associated block
  492. * ID's are changed, and are brand new.
  493. */
  494. function paste_layout($layoutid) {
  495. $layoutname = $this->layout_name;
  496. $this->delete();
  497. $this->get($layoutid);
  498. $this->replicate($layoutname);
  499. } // paste_layout
  500. // ....................................................................
  501. /**
  502. * Index all blocks in this layout.
  503. * If Lucene indexing is enabled, then we call the indexer for all of
  504. * the blocks which are in the hosted layout, using the webpage path and title as
  505. * provided in the call to this method.
  506. * @param string $path The relative path to the webpage the hosted layout is in
  507. * @param string $title The title of the webpage the hosted layout is in
  508. */
  509. function index($path, $title) {
  510. global $RESPONSE;
  511. $lcq = dbrecordset("SELECT block_id FROM ax_block WHERE layout_id=" . $this->layoutid);
  512. if ($lcq->hasdata) {
  513. // Include metadata if there is any..
  514. $metadata = false;
  515. if ($RESPONSE->metadata_mode == METADATA_ENABLED) {
  516. include_once("metadata-defs.php");
  517. $metadata = new layout_metadata_elements($this->layoutid, "", true);
  518. }
  519. do {
  520. $blockid = $lcq->field("block_id");
  521. $b = new block($blockid);
  522. $b->index($path, $title, $this->index_category, $metadata);
  523. } while ($lcq->get_next());
  524. }
  525. } // index
  526. // ....................................................................
  527. /**
  528. * Un-Index all blocks in this layout. After calling this method all
  529. * the bloacks in the layout will have been removed from the Lucene
  530. * index.
  531. */
  532. function unindex() {
  533. $lcq = dbrecordset("SELECT block_id FROM ax_block WHERE layout_id=" . $this->layoutid);
  534. if ($lcq->hasdata) {
  535. do {
  536. $blockid = $lcq->field("block_id");
  537. $b = new block($blockid);
  538. $b->unindex();
  539. } while ($lcq->get_next());
  540. }
  541. } // unindex
  542. // ....................................................................
  543. /**
  544. * Return true if the current user is permitted to edit layout details.
  545. * We allow editing only for versions VERSION_PENDING and VERSION_LIVE
  546. * and the latter only for Editors.
  547. * @return boolean True if editing is permitted by current user.
  548. */
  549. function user_can_edit($required_version=VERSION_UNDEFINED) {
  550. global $RESPONSE;
  551. $perm = false;
  552. if ($required_version == VERSION_UNDEFINED ||
  553. $required_version == $this->version) {
  554. // Pending version
  555. if ($this->is_pendingver()) {
  556. if ($RESPONSE->ismemberof_group_in( array_merge($this->editor_groups, $this->author_groups) )) {
  557. $perm = true;
  558. }
  559. }
  560. // Live version
  561. elseif ($this->version == VERSION_LIVE) {
  562. if ($RESPONSE->ismemberof_group_in( $this->editor_groups )) {
  563. $perm = true;
  564. }
  565. }
  566. }
  567. return $perm;
  568. } // user_can_edit
  569. // ....................................................................
  570. /**
  571. * Return PENDING version status.
  572. * @return boolean True if current versin is PENDING, or only one version.
  573. */
  574. function is_pendingver() {
  575. return ($this->version == VERSION_PENDING || $this->version_count == 1);
  576. }
  577. // ....................................................................
  578. /**
  579. * Render the layout editing suite.
  580. * @return string The HTML for the editing suite form etc.
  581. * @access private
  582. */
  583. function editform() {
  584. $this->activate_editing();
  585. return $this->layouteditor->editform();
  586. } // editform
  587. // ....................................................................
  588. /**
  589. * Render the layout content.
  590. * @return string The HTML
  591. * @access private
  592. */
  593. function layoutcontent() {
  594. debug_trace($this);
  595. global $LIBDIR;
  596. global $RESPONSE;
  597.  
  598. $pwidth = "150px";
  599.  
  600. // Create a simple container table to view layout..
  601. $Tvw = new table($this->layout_name);
  602. $Tvw->tr();
  603. $Tvw->td();
  604.  
  605. // Make our layout table and populate it with our blocks..
  606. $Tlay = $this->layout_table;
  607.  
  608. // Apply supplemental style if defined..
  609. if ($this->layout_style != "") {
  610. $Tlay->setstyle($this->layout_style);
  611. }
  612.  
  613. // Ensure any blank cells return "&nbsp;"..
  614. $Tlay->setnbsp();
  615.  
  616. if ($this->tot_plain > 0) {
  617. $edbox = new form_textfield();
  618. $edbox->set_onchange("sto(this,'$this->layoutfm')");
  619. $group_names_list = $RESPONSE->group_names_list();
  620. $profile = $Tlay->get_width_profile();
  621. $tblwdth = $Tlay->width;
  622. }
  623. if ($this->tot_editable > 0) {
  624. $RESPONSE->set_style("input {background-color:#F9F7ED;}");
  625. }
  626. for ($r = 0; $r < $this->tot_rows; $r++) {
  627. for ($c = 0; $c < $this->tot_cols; $c++) {
  628. if (isset($this->layout_blocks["$r|$c"])) {
  629. $blockid = $this->layout_blocks["$r|$c"];
  630. if ($blockid != 0) {
  631. // Render as content block cell..
  632. $block = new block($blockid);
  633. if ($block->mode == "editing") {
  634. $this->edit_blocks[] = $block->blockid;
  635. }
  636. $block->set_layout_info(
  637. $this->version,
  638. $this->version_count,
  639. $this->language,
  640. $this->lang_encoding,
  641. $this->lang_direction,
  642. $this->editor_groups,
  643. $this->author_groups,
  644. $this->entry_groups
  645. );
  646. $cell = $Tlay->get_cell($r, $c);
  647. $cell->setcontent($block->render());
  648. $cell->setalignment($block->justify, $block->valign);
  649. // Apply supplemental style if defined..
  650. if ($this->layout_style != "") {
  651. $cell->setstyle($this->layout_style);
  652. }
  653. $Tlay->set_cell($r, $c, $cell);
  654. }
  655. else {
  656. if ($this->tot_editable > 0 && $this->mode != "previewing") {
  657. // Render as editable textfield, if update is permitted..
  658. $cell = $Tlay->get_cell($r, $c);
  659. if (isset($this->editable_cells["$r|$c"])) {
  660. // Try to ascertain a pixel width..
  661. $edbox->clearstyle();
  662. if (isset($profile[$c])) {
  663. $pwdth = $profile[$c];
  664. if (strstr($pwdth, "%")) {
  665. if ($tblwdth != "" && !strstr($tbldwdth, "%")) {
  666. $w = (int) ($tblwdth * $pwdth / 100);
  667. $edbox->setstyle("width:" . $w . "px;");
  668. }
  669. }
  670. else {
  671. if ($pwdth != "") {
  672. $edbox->setstyle("width:" . $pwdth . "px;");
  673. }
  674. }
  675. }
  676. $edbox->setvalue($cell->content->content);
  677. $cell->content->content = $edbox->render($cell->cellid);
  678. // Apply supplemental style if defined..
  679. if ($this->layout_style != "") {
  680. $cell->setstyle($this->layout_style);
  681. }
  682. $Tlay->set_cell($r, $c, $cell);
  683. }
  684. }
  685. // Overriding read permission blanking here. If it isn't
  686. // a viewable cell then they draw a blank..
  687. if (!isset($this->viewable_cells["$r|$c"])) {
  688. $cell = $Tlay->get_cell($r, $c);
  689. $cell->content->content = "";
  690. // Apply supplemental style if defined..
  691. if ($this->layout_style != "") {
  692. $cell->setstyle($this->layout_style);
  693. }
  694. $Tlay->set_cell($r, $c, $cell);
  695. }
  696. }
  697. }
  698. }
  699. }
  700.  
  701. // Add in editing tools if authorised..
  702. debugbr("layoutcontent: mode is $this->mode", DBG_DEBUG);
  703. if ($this->mode != "previewing") {
  704. $layedit = ($RESPONSE->ismemberof_group_in( array_merge($this->editor_groups, $this->author_groups, $this->entry_groups) ));
  705. $Tvw->td_content("<form name=\"$this->layoutfm\" method=\"post\">\n");
  706. $formcontent = "";
  707.  
  708. if ($layedit) {
  709. $Tvw->setstyle("border-width:1px;border-style:dotted;border-color:#0000ff;");
  710. $Tlay->setborder(1);
  711.  
  712. // Version selector
  713. $verCombo = new form_combofield("layout_version");
  714. $verCombo->setclass("axcombo");
  715. $verCombo->setstyle("width:$pwidth;font-size:85%;");
  716. $verCombo->additem(0, "Pending");
  717. $verCombo->additem(1, "Live");
  718. $verCombo->additem(2, "Previous");
  719. $verCombo->setvalue($this->version);
  720. $verCombo->set_onchange("document.forms.$this->layoutfm.submit()");
  721.  
  722. // Tools for the toolbar
  723. $toolbar = array();
  724. $toolbar[] = $verCombo;
  725.  
  726. // Tools only for edit-enabled users..
  727. if ($this->user_can_edit()) {
  728. if ($RESPONSE->metadata_mode == METADATA_ENABLED) {
  729. $btn = new image_button("_meta", "", "", "", "$LIBDIR/img/_meta.gif", 42, 15, "Edit metadata");
  730. $url = "/axyl-metadata-editor.php?layout_id=" . urlencode($this->layoutid);
  731. $btn->set_onclick("meta_edit('$url')");
  732. $RESPONSE->body->add_popup_script(
  733. "meta_edit",
  734. 600, 650, 50, 50,
  735. "toolbar=no,status=no,scrollbars=yes,resizable=yes"
  736. );
  737. $toolbar[] = $btn;
  738. }
  739. $toolbar[] = new image_button(
  740. "_edit",
  741. "", "", "",
  742. "$LIBDIR/img/_edit.gif",
  743. 42, 15,
  744. "Edit layout"
  745. );
  746. // Paste layout from clipboard button..
  747. $layconf = new configuration("layout", "clipboard");
  748. $copy_layoutid = $layconf->value("copy_layoutid");
  749. if ($copy_layoutid != "" && $copy_layoutid != $this->layoutid) {
  750. $bpaste = new image_button(
  751. "_paste",
  752. "", "", "",
  753. "$LIBDIR/img/_paste.gif",
  754. 57, 15,
  755. "Paste layout"
  756. );
  757. $bpaste->set_confirm_text("Overwrite this layout with the one on the clipboard?");
  758. $toolbar[] = $bpaste;
  759. }
  760. // Copy layout to clipboard button..
  761. $toolbar[] = new image_button(
  762. "_copy",
  763. "", "", "",
  764. "$LIBDIR/img/_copy.gif",
  765. 42, 15,
  766. "Copy layout to clipboard"
  767. );
  768. } // can edit
  769.  
  770. // Toolbar table
  771. $Tbar = new table("toolbar");
  772. $Tbar->tr("axtitle");
  773. if ($this->user_can_edit()) {
  774. //$Tbar->th("[$this->layout_name]", "axtitle");
  775. $Tbar->th("[Layout]", "axtitle");
  776. $Tbar->th_alignment("", "top");
  777. }
  778. else {
  779. $Tbar->th("&nbsp;", "axtitle");
  780. }
  781. $tools = "";
  782. foreach ($toolbar as $tool) {
  783. $tools .= $tool->render();
  784. }
  785. // Render tools, if any..
  786. $Tbar->th($tools, "axtitle");
  787. $Tbar->th_css("text-align:right");
  788. $Tvw->td_content( $Tbar->render(), "axtitle" );
  789.  
  790. // Hidden form fields..
  791. $update_data = new form_hiddenfield("_update_data", "");
  792. $update_flag = new form_hiddenfield("_update_flag", "false");
  793.  
  794. // Put hidden fields into the toolbar form..
  795. $form_content .=
  796. $update_data->render()
  797. . $update_flag->render();
  798.  
  799. } // if layedit
  800.  
  801. $layfm = new form_hiddenfield("edit_layoutform", $this->layoutfm);
  802. $mode = new form_hiddenfield("layoutmode", $this->mode);
  803. $elid = new form_hiddenfield("edit_layoutid", $this->layoutid);
  804. $export_flag = new form_hiddenfield("_export_flag", "false");
  805. $form_content .=
  806. $mode->render()
  807. . $layfm->render()
  808. . $elid->render()
  809. . $export_flag->render();
  810.  
  811. // Put hidden fields into the toolbar form..
  812. $Tvw->td_content( $form_content );
  813. $Tvw->td_content("</form>\n");
  814.  
  815. } // not previewing
  816.  
  817. // Put layout into viewer table..
  818. $Tvw->td_content( $Tlay->render() );
  819. $Tvw->td_alignment("", "top");
  820.  
  821. if ($this->show_last_modified && $this->last_modified != "") {
  822. $Tvw->tr();
  823. $Tvw->td($this->last_modified, "axyl_lastmod");
  824. }
  825.  
  826. $bottoolbar = array();
  827. // If editable content, give them a save button,
  828. // and remember the layout ID and the mode..
  829. if ($this->mode != "previewing"
  830. && $this->tot_editable > 0
  831. && count($this->edit_blocks) == 0
  832. ) {
  833. $bupdate = new form_imagebutton("_update", "", "", "$LIBDIR/img/_save.gif", "Save changes", 57, 15);
  834. $clkstr = "document.forms.$this->layoutfm._update_flag.value='true';";
  835. $clkstr .= "document.forms.$this->layoutfm.submit();";
  836. $bupdate->set_onclick($clkstr);
  837. $bottoolbar[] = $bupdate->render();
  838. }
  839. if ($this->mode != "previewing"
  840. && $this->tot_plain > 0
  841. && $this->tot_blocks == 0
  842. ) {
  843. $bexport = new form_imagebutton("_export", "", "", "$LIBDIR/img/_export.gif", "Export in CSV format", 57, 15);
  844. $clkstr = "document.forms.$this->layoutfm._export_flag.value='true';";
  845. $clkstr .= "document.forms.$this->layoutfm.submit();";
  846. $bexport->set_onclick($clkstr);
  847. $bottoolbar[] = $bexport->render();
  848. }
  849. if (count($bottoolbar > 0)) {
  850. $tools = implode("&nbsp;", $bottoolbar);
  851. $Tvw->tr();
  852. $Tvw->td( $tools );
  853. }
  854.  
  855. // Return the html..
  856. $s = $Tvw->render();
  857. debug_trace();
  858. return $s;
  859. } // layoutcontent
  860. // ....................................................................
  861. /**
  862. * Render the block content according to the mode of operation
  863. * we are in. Possible modes: 'viewing', 'editing', 'saving'.
  864. * @return string The HTML
  865. */
  866. function html() {
  867. debug_trace($this);
  868. global $LIBDIR;
  869. global $RESPONSE;
  870. global $edit_layoutid;
  871.  
  872. $s = "";
  873. if ($this->message != "") {
  874. $s .= "<center><span class=error>$this->message</span></center>";
  875. }
  876.  
  877. switch($this->mode) {
  878. case "editing":
  879. // Make sure edit request is meant for us..
  880. if (!isset($edit_layoutid) || $edit_layoutid != $this->layoutid) {
  881. return "";
  882. }
  883. // Deal with first layout edit. In this case it won't yet
  884. // exist in the database, so we create it here..
  885. if (!$this->exists) {
  886. $this->put();
  887. }
  888. $this->mode = "saving";
  889. $s .= $this->editform();
  890. break;
  891.  
  892. default:
  893. if ($this->mode != "viewing" && $this->mode != "previewing") {
  894. $this->mode = "viewing";
  895. }
  896. // Insert any layout metadata into the page..
  897. if ($RESPONSE->metadata_mode == METADATA_ENABLED) {
  898. include_once("metadata-defs.php");
  899. $laymeta = new layout_metadata_elements($this->layoutid, "", true);
  900. $laymeta->insert_metatags($RESPONSE);
  901. }
  902.  
  903. // Render this layout now..
  904. $s .= $this->layoutcontent();
  905.  
  906. } // switch
  907. return $s;
  908. } // html
  909. // ....................................................................
  910. /**
  911. * Assign the cell IDs to the layout. We iterate across all cells
  912. * assigning the unique ID. This is used when the table shape changes.
  913. * @access private
  914. */
  915. function assign_cellids() {
  916. for ($row=0; $row < $this->tot_rows; $row++) {
  917. for ($col=0; $col < $this->tot_cols; $col++) {
  918. if ($this->layout_table->cell_exists($row, $col)) {
  919. $cell = $this->layout_table->get_cell($row, $col);
  920. $cell->setcellid("_tcell|$row|$col|tbody");
  921. $this->layout_table->set_cell($row, $col, $cell);
  922. }
  923. }
  924. }
  925. } // assign_cellids
  926. // ....................................................................
  927. /**
  928. * Vacate the given layout cell. Removes any defined Plain cell
  929. * or Content Block cell from this cell position. Note: this will
  930. * also delete any defined blocks/blocklets and lose all the content
  931. * in these records.
  932. * @param integer $row The row number of the layout cell
  933. * @param integer $col The column number of the layout cell
  934. * @access private
  935. */
  936. function cell_vacate($row, $col) {
  937. if ($this->layout_table->cell_exists($row, $col)) {
  938. $cell = $this->layout_table->get_cell($row, $col);
  939. if (isset($cell->celltype)) unset($cell->celltype);
  940. if (isset($cell->blockid)) {
  941. if ($cell->blockid != "") {
  942. $b = new block($cell->blockid);
  943. $b->delete();
  944. }
  945. if (isset($cell->celltype)) unset($cell->celltype);
  946. if (isset($cell->blockid)) unset($cell->blockid);
  947. if (isset($cell->access)) unset($cell->access);
  948. }
  949. $this->layout_table->set_cell($row, $col, $cell);
  950. }
  951. } // cell_vacate
  952. // ....................................................................
  953. /**
  954. * Merge the settings of the two cells. We assume that cell1 is
  955. * going to be the surviving cell, having "absorbed" cell2.
  956. * Rules: If cell1 is defined already, then we just vacate cell2
  957. * and leave cell1 as-is. If cell1 is empty, and cell2 is
  958. * defined, then we copy cell2 to cell1 and unset cell2 without
  959. * removing any blocks.
  960. * @param integer $row1 The row number of the absorbing cell
  961. * @param integer $col1 The column number of the absorbing cell
  962. * @param integer $row2 The row number of the absorbed cell
  963. * @param integer $col2 The column number of the absorbed cell
  964. * @access private
  965. */
  966. function cell_merge($row1, $col1, $row2, $col2) {
  967. if ($this->layout_table->cell_exists($row1, $col1) &&
  968. $this->layout_table->cell_exists($row2, $col2)) {
  969. $cell1 = $this->layout_table->get_cell($row1, $col1);
  970. $cell2 = $this->layout_table->get_cell($row2, $col2);
  971. if (isset($cell1->celltype)) {
  972. $this->cell_vacate($row2, $col2);
  973. }
  974. else {
  975. if (isset($cell2->celltype)) {
  976. $cell1->celltype = $cell2->celltype;
  977. unset($cell2->celltype);
  978. if (isset($cell2->blockid)) {
  979. $cell1->blockid = $cell2->blockid;
  980. unset($cell2->blockid);
  981. }
  982. // Put absorbed cell back in place..
  983. $this->layout_table->set_cell($row2, $col2, $cell2);
  984. }
  985. }
  986. // Put resultant cell back in place..
  987. $this->layout_table->set_cell($row1, $col1, $cell1);
  988. }
  989. } //cell_merge
  990. // ....................................................................
  991. /**
  992. * Process a block edit form POST.
  993. * Assume that the fields have been submitted in a form as named
  994. * in the config, and grab the POSTed values. This method is executed
  995. * from the constructor usually, before anything is read in from
  996. * the database. We get first shot to change data here.
  997. * @param text $id The identity of the set to update from POST
  998. * @access private
  999. */
  1000. function POSTprocess() {
  1001. debug_trace($this);
  1002. global $HTTP_POST_VARS, $RESPONSE, $LIBDIR;
  1003. global $edit_layoutform, $edit_layoutid, $layoutmode;
  1004.  
  1005. // Only interested in our own postings..
  1006. if (isset($edit_layoutform) && $edit_layoutform == $this->layoutfm) {
  1007. if (isset($layoutmode) && isset($edit_layoutid)) {
  1008. $this->get($edit_layoutid);
  1009. if ($this->layoutid == $edit_layoutid) {
  1010. // Posted buttons, and hidden fields..
  1011. global $_done_x, $_edit_x, $_update_x, $_copy_x, $_paste_x;
  1012. global $_update_flag, $_update_data, $_export_flag, $update_delim;
  1013. global $layoutmode;
  1014.  
  1015. $this->mode = $layoutmode;
  1016. debugbr("layoutid $this->layoutid mode is $this->mode", DBG_DEBUG);
  1017. switch ($this->mode) {
  1018. case "viewing":
  1019. // Clicked Edit button
  1020. if (isset($_edit_x)) {
  1021. $this->mode = "editing";
  1022. }
  1023. elseif (isset($_copy_x)) {
  1024. $this->get($edit_layoutid);
  1025. $layconf = new configuration("layout", "clipboard");
  1026. if (!$layconf->field_exists("copy_layoutid")) {
  1027. $layconf->field_insert("copy_layoutid", "text");
  1028. }
  1029. $layconf->set_value("copy_layoutid", $this->layoutid);
  1030. $layconf->put();
  1031. }
  1032. elseif (isset($_paste_x) && isset($edit_layoutid)) {
  1033. $layconf = new configuration("layout", "clipboard");
  1034. $copy_layoutid = $layconf->value("copy_layoutid");
  1035. if ($copy_layoutid != "" && $edit_layoutid != "") {
  1036. $this->get($edit_layoutid);
  1037. debugbr("pasting layout $copy_layoutid", DBG_DEBUG);
  1038. $this->paste_layout($copy_layoutid);
  1039. $layconf->set_value("copy_layoutid", "");
  1040. $layconf->put();
  1041. }
  1042. }
  1043. // Updating plain cell content..
  1044. elseif (isset($_update_flag) && $_update_flag == "true") {
  1045. global $_update_data;
  1046. // Get layout table, so we can alter it..
  1047. $this->get($edit_layoutid);
  1048. $updated = false;
  1049. if (isset($_update_data) && $_update_data != "") {
  1050. $updates = explode($update_delim, $_update_data);
  1051. foreach ($updates as $update) {
  1052. $bits = explode("|", $update);
  1053. if ($bits[0] == "_tcell") {
  1054. $row = $bits[1];
  1055. $col = $bits[2];
  1056. $tgroup = $bits[3];
  1057. $postval = rawurldecode($bits[4]);
  1058. debugbr("POSTED cell: $row,$col = '$postval'", DBG_DEBUG);
  1059. $this->layout_table->poke_cell($row, $col, $postval, "", "", $tgroup);
  1060. $updated = true;
  1061. }
  1062. }
  1063. }
  1064. if ($updated) {
  1065. $this->put();
  1066. }
  1067. }
  1068. elseif (isset($_export_flag) && $_export_flag == "true") {
  1069. // Get layout table, so we can export it..
  1070. $this->get($edit_layoutid);
  1071. $RESPONSE->discard();
  1072. header("Content-Type: text/csv");
  1073. header("Content-Disposition: attachment; filename=$this->layout_name" . ".csv");
  1074. echo $this->layout_table->csv();
  1075. exit;
  1076. }
  1077. break;
  1078.  
  1079. // Save button clicked..
  1080. case "save":
  1081. global $index_category, $layout_rows, $layout_cols, $layout_padding;
  1082. global $background_colour, $width_profile, $layout_newcell;
  1083. global $show_last_modified, $format_last_modified;
  1084. global $prefix_last_modified, $table_style, $table_width;
  1085. global $table_autojustify, $table_rowstripes, $layout_style;
  1086. global $language;
  1087. global $privs_recmaintpost_data, $privs_recmaintpost_flds, $privs_recmaintpost_form;
  1088.  
  1089. // Get layout table, so we can alter it..
  1090. $this->get($edit_layoutid);
  1091.  
  1092. // Updated layout parameters..
  1093. if ($this->index_category != $index_category) {
  1094. $this->index_category = $index_category;
  1095. $this->index();
  1096. }
  1097. $this->language = $language;
  1098. $this->show_last_modified = isset($show_last_modified);
  1099. $this->format_last_modified = $format_last_modified;
  1100. $this->prefix_last_modified = $prefix_last_modified;
  1101. $this->layout_style = $layout_style;
  1102.  
  1103. // Table size changed flag..
  1104. $sizechanged = false;
  1105.  
  1106. // Set layout table parameters..
  1107. $this->layout_table->setcss("");
  1108. $this->layout_table->setclass($table_style);
  1109. $this->layout_table->setwidth($table_width);
  1110. if (isset($table_rowstripes)) {
  1111. $this->layout_table->rowstripes("axyl_rowstripe_lite,axyl_rowstripe_dark");
  1112. }
  1113. else {
  1114. $this->layout_table->rowstripes("");
  1115. }
  1116. $this->layout_table->autojustify(isset($table_autojustify));
  1117. $this->layout_table->setpadding($layout_padding);
  1118. $this->layout_table->setbgcolor($background_colour);
  1119. if (isset($width_profile)) {
  1120. $this->layout_table->set_width_profile($width_profile);
  1121. }
  1122. // Adjust row changes..
  1123. $Trows = $this->layout_table->rowcount();
  1124. if ($layout_rows != $Trows) {
  1125. $sizechanged = true;
  1126. if ($layout_rows < $Trows) {
  1127. $last = $Trows - 1;
  1128. for ($i = 0; $i < $Trows - $layout_rows; $i++) {
  1129. $this->layout_table->delete_row($last);
  1130. $last -= 1;
  1131. }
  1132. }
  1133. else {
  1134. for ($i = 0; $i < $layout_rows - $Trows; $i++) {
  1135. $this->layout_table->append_row( new tablecell("&nbsp;") );
  1136. }
  1137. }
  1138. }
  1139. // Adjust for column changes..
  1140. $Tcols = $this->layout_table->cellcount();
  1141. if ($layout_cols != $Tcols) {
  1142. $sizechanged = true;
  1143. if ($layout_cols < $Tcols) {
  1144. $last = $Tcols - 1;
  1145. for ($i = 0; $i < $Tcols - $layout_cols; $i++) {
  1146. $this->layout_table->delete_cols($last);
  1147. $last -= 1;
  1148. }
  1149. }
  1150. else {
  1151. $this->layout_table->append_cols($layout_cols - $Tcols, new tablecell("&nbsp;"));
  1152. }
  1153. }
  1154. // Look for new layout cells..
  1155. if (isset($layout_newcell)) {
  1156. foreach ($layout_newcell as $request) {
  1157. $bits = explode("|", $request);
  1158. $celltype = $bits[0];
  1159. $row = $bits[1];
  1160. $col = $bits[2];
  1161. // Get table cell to change it..
  1162. if ($this->layout_table->cell_exists($row, $col)) {
  1163. $cell = $this->layout_table->get_cell($row, $col);
  1164. // Block cells get new block, plain cells don't..
  1165. switch ($celltype) {
  1166. // Content Block or Wysiwyg cell..
  1167. case BLOCK_CONTENT:
  1168. case WYSIWYG_EDITOR:
  1169. $b = new block();
  1170. $b->layoutid = $this->layoutid;
  1171. $b->block_type = $celltype;
  1172. $b->put();
  1173. $cell->celltype = $celltype;
  1174. $cell->blockid = $b->blockid;
  1175. break;
  1176. // Plain cell..
  1177. case PLAIN_CELL:
  1178. $cell->celltype = PLAIN_CELL;
  1179. $cell->blockid = "";
  1180. // Set default cell permissions..
  1181. $cell->permit($this->editor_groups, PERM_ALL);
  1182. $cell->permit($this->author_groups, PERM_READ|PERM_UPDATE);
  1183. break;
  1184. } // switch
  1185. // Return cell to table..
  1186. $this->layout_table->set_cell($row, $col, $cell);
  1187. }
  1188. } // foreach
  1189. } // new layout cells
  1190. // Save the layout, stay in edit mode..
  1191. $this->assign_cellids();
  1192. $this->put();
  1193.  
  1194. // Privilege settings..
  1195. if (isset($privs_recmaintpost_form)) {
  1196. if (isset($privs_recmaintpost_data)
  1197. && $privs_recmaintpost_data != "") {
  1198. $recs = explode(RECORD_DELIM, $privs_recmaintpost_data);
  1199. foreach ($recs as $rec) {
  1200. $values = explode(FIELD_DELIM, $rec);
  1201. $group_id = array_shift($values);
  1202. $fields = explode(",", $privs_recmaintpost_flds);
  1203. $pos = 0;
  1204. foreach ($fields as $field) {
  1205. $privilege = str_replace("priv_", "", $field);
  1206. $priv_granted = $values[$pos];
  1207. switch ($priv_granted) {
  1208. case "t":
  1209. if (!isset($this->privileges["$privilege|$group_id"])) {
  1210. $pin = new dbinsert("ax_layout_set_group");
  1211. $pin->set("layout_name", $this->layout_name);
  1212. $pin->set("cm_privilege", "'" . $privilege . "'");
  1213. $pin->set("group_id", $group_id);
  1214. $pin->execute();
  1215. }
  1216. break;
  1217. case "f":
  1218. if (!isset($this->privileges["none|$group_id"])) {
  1219. $pdel = new dbdelete("ax_layout_set_group");
  1220. $pdel->where("group_id=$group_id");
  1221. $pdel->where("AND cm_privilege='$privilege'");
  1222. $pdel->execute();
  1223. }
  1224. break;
  1225. } // switch
  1226. $pos += 1;
  1227. } // foreach
  1228. } // foreach recs
  1229. }
  1230. }
  1231. $this->mode = "editing";
  1232. break;
  1233.  
  1234. case "saving":
  1235. // Get layout table, so we can alter it..
  1236. $this->get($edit_layoutid);
  1237.  
  1238. global $_new_x, $_save_x, $_cancel_x, $_done_x;
  1239. global $layout_action, $_perm_set_x, $_perm_unset_x;
  1240.  
  1241. // Let me out of here..
  1242. if (isset($_done_x) || isset($_cancel_x)) {
  1243. // Drop through to viewing..
  1244. $this->mode = "viewing";
  1245. }
  1246. // Blow away whole layout, and start again..
  1247. elseif (isset($_new_x)) {
  1248. start_transaction();
  1249. $blocks = dbrecordset("SELECT block_id FROM ax_block WHERE layout_id=$this->layoutid");
  1250. if ($blocks->hasdata) {
  1251. do {
  1252. $b = new block($blocks->field("block_id"));
  1253. $b->delete();
  1254. } while ($blocks->get_next());
  1255. }
  1256. $Lup = new dbupdate("ax_layout");
  1257. $Lup->set("layout_table", NULLVALUE);
  1258. $Lup->where("layout_id=$this->layoutid");
  1259. $Lup->execute();
  1260. commit();
  1261. if (isset($this->layout_table)) unset($this->layout_table);
  1262. if (isset($this->layout_blocks)) unset($this->layout_blocks);
  1263. $this->mode = "editing";
  1264. }
  1265. // Permissions setting activity..
  1266. elseif (isset($_perm_set_x) || isset($_perm_unset_x)) {
  1267. global $layout_cellsel, $perm_groups, $perm_perms;
  1268. if (isset($layout_cellsel) && isset($perm_groups) && isset($perm_perms)) {
  1269. foreach ($layout_cellsel as $cellsel) {
  1270. $bits = explode("|", $cellsel);
  1271. $row = $bits[0];
  1272. $col = $bits[1];
  1273. if ($this->layout_table->cell_exists($row, $col)) {
  1274. $setgroups = implode(",", $perm_groups);
  1275. $setperms = 0;
  1276. foreach ($perm_perms as $perm) {
  1277. $setperms |= $perm;
  1278. }
  1279. if (isset($_perm_set_x)) {
  1280. $this->layout_table->permit_cell($row, $col, $setgroups, $setperms);
  1281. }
  1282. else {
  1283. $this->layout_table->unpermit_cell($row, $col, $setgroups, $setperms);
  1284. }
  1285. }
  1286. }
  1287. $this->put();
  1288. }
  1289. $this->mode = "editing";
  1290. }
  1291. // Other layout management action..
  1292. elseif (isset($layout_action) && $layout_action != "") {
  1293. $req = explode("|", $layout_action);
  1294. $activity = $req[0];
  1295. switch ($activity) {
  1296. // Merging of rows or cols
  1297. case "merge":
  1298. $object = $req[1];
  1299. $row = $req[2]; $col = $req[3];
  1300. switch ($object) {
  1301. case "col":
  1302. $this->cell_merge($row, $col, $row, $col + 1);
  1303. $this->layout_table->merge_cols($row, $col, 2);
  1304. break;
  1305. case "row":
  1306. $this->cell_merge($row, $col, $row + 1, $col);
  1307. $this->layout_table->merge_rows($row, $col, 2);
  1308. break;
  1309. case "allcols":
  1310. $this->layout_table->merge_cols($row, $col, $this->tot_cols);
  1311. break;
  1312. } // switch
  1313. break;
  1314. // Splitting of merged rows or cols
  1315. case "split":
  1316. $object = $req[1];
  1317. $row = $req[2]; $col = $req[3];
  1318. switch ($object) {
  1319. case "col":
  1320. $this->layout_table->split_cols($row, $col);
  1321. break;
  1322. case "row":
  1323. $this->layout_table->split_rows($row, $col);
  1324. break;
  1325. } // switch
  1326. break;
  1327. // Delete content block or plain cell..
  1328. case "deletecell":
  1329. $row = $req[1];
  1330. $col = $req[2];
  1331. $this->cell_vacate($row, $col);
  1332. $this->layout_blocks = array();
  1333. break;
  1334. // Inserting a row
  1335. case "insrow":
  1336. $row = $req[1]; $col = $req[2];
  1337. $this->layout_table->insert_row($row);
  1338. $this->layout_blocks = array();
  1339. break;
  1340. // Inserting a column
  1341. case "inscol":
  1342. $row = $req[1]; $col = $req[2];
  1343. $this->layout_table->insert_cols($col);
  1344. $this->layout_blocks = array();
  1345. break;
  1346. case "delrow":
  1347. $row = $req[1]; $col = $req[2];
  1348. $this->layout_table->delete_row($row);
  1349. $this->layout_blocks = array();
  1350. break;
  1351. // Inserting a column
  1352. case "delcol":
  1353. $row = $req[1]; $col = $req[2];
  1354. $this->layout_table->delete_cols($col);
  1355. $this->layout_blocks = array();
  1356. break;
  1357. } // switch
  1358.  
  1359. // Save..
  1360. $this->assign_cellids();
  1361. $this->put();
  1362. // Stay in editing..
  1363. $this->mode = "editing";
  1364. }
  1365. break;
  1366. } // switch
  1367. } // layoutid is this one
  1368. } // got $layoutmode and $layoutid
  1369. } // layout form is us
  1370.  
  1371. // If the user preference says so, then set the mode to
  1372. // content preview mode..
  1373. $prefs = new configuration("preferences", $RESPONSE->userid);
  1374. if ($prefs->field_exists("Content Preview Mode")) {
  1375. if ($prefs->value("Content Preview Mode") === true) {
  1376. $this->mode = "previewing";
  1377. }
  1378. }
  1379. debugbr("mode now set to: $this->mode", DBG_DEBUG);
  1380. debug_trace();
  1381. } // POSTprocess
  1382.  
  1383. } // layout class
  1384. // ----------------------------------------------------------------------
  1385.  
  1386. /**
  1387. * Named Layout. A named layout is just another way of grabbing a layout,
  1388. * but by name, rather than by ID. A given "name" can have multiple
  1389. * versions in existence, if it has been published, and these will all
  1390. * have unique ID's, so this class is concerned with sorting out which
  1391. * version of a named layout is required, and acquiring the correct
  1392. * layout ID.
  1393. * @package cm
  1394. */
  1395. class named_layout extends layout {
  1396. // Public
  1397. /** The version of the layout we have */
  1398.  
  1399. var $version = VERSION_UNDEFINED;
  1400. /** Total versions of this layout in database */
  1401.  
  1402. var $version_count = 0;
  1403.  
  1404. // Private
  1405. /** Flag to indicate POST told us to publish */
  1406.  
  1407. var $posted_publish = false;
  1408. /** Flag to indicate POST told us to revert */
  1409.  
  1410. var $posted_revert = false;
  1411. // ....................................................................
  1412. /**
  1413. * Constructor
  1414. * Create a new named_layout object. A named layout is a layout which
  1415. * is identified by its name, and by the version. Versions are numbered
  1416. * from zero (0), which represents the most recent. The higher the
  1417. * version number, the further back in time you go. We define three
  1418. * special version numbers:
  1419. * VERSION_PENDING (0) The layout waiting to be made live
  1420. * VERSION_LIVE (1) The currently live layout
  1421. * VERSION_PREVIOUS (2) The version previously live
  1422. * Accordingly, these versions are the most recent three in the set of
  1423. * all versions of the layout.
  1424. * @param string $name Layout name
  1425. * @param integer $version Version number, (zero=most recent)
  1426. */
  1427. function named_layout($name="", $version=VERSION_UNDEFINED) {
  1428. global $RESPONSE;
  1429.  
  1430. // Initialise version..
  1431. if ($version != VERSION_UNDEFINED) {
  1432. $this->version = $version;
  1433. }
  1434.  
  1435. // Process any form submissions...
  1436. $this->POSTprocess();
  1437.  
  1438. // Fallback if required version still not defined..
  1439. if ($this->version == VERSION_UNDEFINED) {
  1440. if ($this->mode != "previewing"
  1441. && $RESPONSE->ismemberof_group_in( array_merge($this->editor_groups, $this->author_groups, $this->entry_groups) )) {
  1442. $this->version = VERSION_PENDING;
  1443. }
  1444. else {
  1445. $this->version = VERSION_LIVE;
  1446. }
  1447. }
  1448.  
  1449. // Process POSTs, and determine the layout ID..
  1450. if ($name != "") {
  1451.  
  1452. // How many versions do we have..
  1453. $q = "SELECT COUNT(*) AS vercnt FROM ax_layout";
  1454. $q .= " WHERE layout_name='". addslashes($name) . "'";
  1455. $Lcnt = dbrecordset($q);
  1456. if ($Lcnt->hasdata) {
  1457. $this->version_count = $Lcnt->field("vercnt");
  1458. }
  1459. debugbr("layout: version history of $this->version_count", DBG_DEBUG);
  1460.  
  1461. // Now, if there are no versions of this layout then we are
  1462. // accessing it for the very first time, so we create it,.
  1463. if ($this->version_count == 0) {
  1464. // Create new set if required..
  1465. $checkSet = dbrecordset("SELECT * FROM ax_layout_set WHERE layout_name='". addslashes($name) . "'");
  1466. if ($checkSet->rowcount == 0) {
  1467. $LSin = new dbinsert("ax_layout_set");
  1468. $LSin->set("layout_name", $name);
  1469. $LSin->execute();
  1470. }
  1471. // Create new layout..
  1472. $newlay = new layout();
  1473. $newlay->layout_name = $name;
  1474. $newlay->put();
  1475. $this->version_count = 1;
  1476. }
  1477.  
  1478. // Grab all relevant versions of the layout..
  1479. $LQ = new dbselect("ax_layout");
  1480. $LQ->where("layout_name='". addslashes($name) . "'");
  1481. $LQ->orderby("layout_id DESC");
  1482. $LQ->execute();
  1483. if ($LQ->hasdata) {
  1484. $row = false;
  1485. // NON-PENDING..
  1486. if ($this->version > 0) {
  1487. if ($LQ->rowexists($this->version)) {
  1488. debugbr("layout: going for version $this->version", DBG_DEBUG);
  1489. $row = $LQ->get_row($this->version);
  1490. }
  1491. else {
  1492. if ($this->mode != "previewing"
  1493. && $RESPONSE->ismemberof_group_in( array_merge($this->editor_groups, $this->author_groups, $this->entry_groups) )) {
  1494. $this->message = "Selected layout does not exist. Falling back to Pending.";
  1495. }
  1496. }
  1497. }
  1498. // PENDING..
  1499. if ($row === false) {
  1500. // Show pending, if no live..
  1501. $this->version = VERSION_PENDING;
  1502. debugbr("layout: falling back to version $this->version", DBG_DEBUG);
  1503. if ($LQ->rowexists($this->version)) {
  1504. $row = $LQ->get_row($this->version);
  1505. }
  1506. }
  1507. if ($row !== false) {
  1508. $this->layout( $LQ->field("layout_id") );
  1509. }
  1510. }
  1511.  
  1512. // Do parent POST processing..
  1513. layout::POSTprocess();
  1514.  
  1515. // Refresh local picture..
  1516. $this->get( $this->layoutid );
  1517.  
  1518. // Now do any of the actions, such as publishing
  1519. // which may have been specified by POST..
  1520. if ($this->posted_publish) {
  1521. $this->publish();
  1522. }
  1523. if ($this->posted_revert) {
  1524. $this->unpublish();
  1525. }
  1526. }
  1527. } // named_layout
  1528. // ....................................................................
  1529. /**
  1530. * Index the named layout. We only do this if the layout version
  1531. * is LIVE or there is only a single version in existence.
  1532. */
  1533. function index() {
  1534. // Find page we belong to..
  1535. $q = "SELECT * FROM ax_layout_set ls, ax_sitepage pg";
  1536. $q .= " WHERE ls.layout_name='" . addslashes($this->layout_name) . "'";
  1537. $q .= " AND pg.page_id=ls.page_id";
  1538. $sitepage = dbrecordset($q);
  1539. if ($sitepage->hasdata) {
  1540. $path = $sitepage->field("page_path");
  1541. $title = $sitepage->field("page_title");
  1542. layout::index($path, $title);
  1543. }
  1544. } // index
  1545. // ....................................................................
  1546. /**
  1547. * Un-Index the named layout. We only do this if the layout version
  1548. * is LIVE or there is only a single version in existence.
  1549. */
  1550. function unindex() {
  1551. if ($this->version_count == 1 || $this->version == VERSION_LIVE) {
  1552. layout::unindex();
  1553. }
  1554. } // unindex
  1555. // ....................................................................
  1556. /**
  1557. * Publish a pending named layout. All we do in fact, is to replicate
  1558. * the current pending version of the layout (this one) into a new
  1559. * version. That automatically makes this layout the current LIVE one,
  1560. * and the newly created version becomes the new PENDING one.
  1561. */
  1562. function publish() {
  1563. if ($this->version == VERSION_PENDING) {
  1564. debugbr("publishing this layout as LIVE", DBG_DEBUG);
  1565. $this->replicate();
  1566. $this->index();
  1567. }
  1568. } // publish
  1569. // ....................................................................
  1570. /**
  1571. * Un-Publish a live named layout. This simply deletes the current
  1572. * pending version of the layout. That makes the current LIVE version
  1573. * the new pending version.
  1574. */
  1575. function unpublish() {
  1576. if ($this->version == VERSION_LIVE) {
  1577. debugbr("unpublishing this layout, reverting previous layout to LIVE", DBG_DEBUG);
  1578. $pending = new named_layout($this->layout_name, VERSION_PENDING);
  1579. if ($pending->exists) {
  1580. debugbr("deleting layout ID $pending->layoutid", DBG_DEBUG);
  1581. $pending->unindex();
  1582. $pending->delete();
  1583. $this->version = VERSION_PENDING;
  1584. $this->index();
  1585. }
  1586. }
  1587. } // unpublish
  1588. // ....................................................................
  1589. /**
  1590. * Return HTML for this named layout.
  1591. */
  1592. function html() {
  1593. if ($this->exists) {
  1594. return layout::html();
  1595. }
  1596. else {
  1597. return "No such layout exists.";
  1598. }
  1599. } // html
  1600. // ....................................................................
  1601. /**
  1602. * Process a block edit form POST.
  1603. * access private
  1604. */
  1605. function POSTprocess() {
  1606. debug_trace($this);
  1607. global $layout_version, $edit_layoutid;
  1608. global $_publish_x, $_revert_x, $_copy_x, $_paste_x;
  1609. if (isset($layout_version)) {
  1610. if ($this->version == VERSION_UNDEFINED) {
  1611. debugbr("setting layout version to $layout_version", DBG_DEBUG);
  1612. $this->version = $layout_version;
  1613. }
  1614. }
  1615. // Buttons..
  1616. if (isset($_publish_x)) {
  1617. $this->posted_publish = true;
  1618. }
  1619. elseif (isset($_revert_x)) {
  1620. $this->posted_revert = true;
  1621. }
  1622.  
  1623. // Do parent POST processing..
  1624. //layout::POSTprocess();
  1625.  
  1626. debug_trace($this);
  1627. }
  1628. } // named_layout class
  1629. // ----------------------------------------------------------------------
  1630.  
  1631. ?>

Documentation generated by phpDocumentor 1.3.0RC3