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

Documentation generated by phpDocumentor 1.3.0RC3