template.class.inc.php 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253
  1. <?php
  2. // Copyright (C) 2010 Combodo SARL
  3. //
  4. // This program is free software; you can redistribute it and/or modify
  5. // it under the terms of the GNU General Public License as published by
  6. // the Free Software Foundation; version 3 of the License.
  7. //
  8. // This program is distributed in the hope that it will be useful,
  9. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. // GNU General Public License for more details.
  12. //
  13. // You should have received a copy of the GNU General Public License
  14. // along with this program; if not, write to the Free Software
  15. // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  16. /**
  17. * Class DisplayTemplate
  18. *
  19. * @author Erwan Taloc <erwan.taloc@combodo.com>
  20. * @author Romain Quetiez <romain.quetiez@combodo.com>
  21. * @author Denis Flaven <denis.flaven@combodo.com>
  22. * @license http://www.opensource.org/licenses/gpl-3.0.html LGPL
  23. */
  24. require_once(APPROOT.'/application/displayblock.class.inc.php');
  25. /**
  26. * This class manages the special template format used internally to build the iTop web pages
  27. */
  28. class DisplayTemplate
  29. {
  30. protected $m_sTemplate;
  31. protected $m_aTags;
  32. static protected $iBlockCount = 0;
  33. public function __construct($sTemplate)
  34. {
  35. $this->m_aTags = array('itopblock', 'itopcheck', 'itoptabs', 'itoptab', 'itoptoggle', 'itopstring');
  36. $this->m_sTemplate = $sTemplate;
  37. }
  38. public function Render(WebPage $oPage, $aParams = array())
  39. {
  40. $this->m_sTemplate = MetaModel::ApplyParams($this->m_sTemplate, $aParams);
  41. $iStart = 0;
  42. $iEnd = strlen($this->m_sTemplate);
  43. $iCount = 0;
  44. $iBeforeTagPos = $iStart;
  45. $iAfterTagPos = $iStart;
  46. while($sTag = $this->GetNextTag($iStart, $iEnd))
  47. {
  48. $sContent = $this->GetTagContent($sTag, $iStart, $iEnd);
  49. $iAfterTagPos = $iEnd + strlen('</'.$sTag.'>');
  50. $sOuterTag = substr($this->m_sTemplate, $iStart, $iAfterTagPos - $iStart);
  51. $oPage->add(substr($this->m_sTemplate, $iBeforeTagPos, $iStart - $iBeforeTagPos));
  52. if ($sTag == DisplayBlock::TAG_BLOCK)
  53. {
  54. try
  55. {
  56. $oBlock = DisplayBlock::FromTemplate($sOuterTag);
  57. if (is_object($oBlock))
  58. {
  59. $oBlock->Display($oPage, 'block_'.self::$iBlockCount, $aParams);
  60. }
  61. }
  62. catch(OQLException $e)
  63. {
  64. $oPage->p('Error in template (please contact your administrator) - Invalid query<!--'.$sOuterTag.'-->');
  65. }
  66. catch(Exception $e)
  67. {
  68. $oPage->p('Error in template (please contact your administrator)<!--'.$e->getMessage().'--><!--'.$sOuterTag.'-->');
  69. }
  70. self::$iBlockCount++;
  71. }
  72. else
  73. {
  74. $aAttributes = $this->GetTagAttributes($sTag, $iStart, $iEnd);
  75. //$oPage->p("Tag: $sTag - ($iStart, $iEnd)");
  76. $this->RenderTag($oPage, $sTag, $aAttributes, $sContent);
  77. }
  78. $iAfterTagPos = $iEnd + strlen('</'.$sTag.'>');
  79. $iBeforeTagPos = $iAfterTagPos;
  80. $iStart = $iEnd;
  81. $iEnd = strlen($this->m_sTemplate);
  82. $iCount++;
  83. }
  84. $oPage->add(substr($this->m_sTemplate, $iAfterTagPos));
  85. }
  86. public function GetNextTag(&$iStartPos, &$iEndPos)
  87. {
  88. $iChunkStartPos = $iStartPos;
  89. $sNextTag = null;
  90. $iStartPos = $iEndPos;
  91. foreach($this->m_aTags as $sTag)
  92. {
  93. // Search for the opening tag
  94. $iOpeningPos = stripos($this->m_sTemplate, '<'.$sTag.' ', $iChunkStartPos);
  95. if ($iOpeningPos === false)
  96. {
  97. $iOpeningPos = stripos($this->m_sTemplate, '<'.$sTag.'>', $iChunkStartPos);
  98. }
  99. if ($iOpeningPos !== false)
  100. {
  101. $iClosingPos = stripos($this->m_sTemplate, '</'.$sTag.'>', $iOpeningPos);
  102. }
  103. if ( ($iOpeningPos !== false) && ($iClosingPos !== false))
  104. {
  105. if ($iOpeningPos < $iStartPos)
  106. {
  107. // This is the next tag
  108. $iStartPos = $iOpeningPos;
  109. $iEndPos = $iClosingPos;
  110. $sNextTag = $sTag;
  111. }
  112. }
  113. }
  114. return $sNextTag;
  115. }
  116. public function GetTagContent($sTag, $iStartPos, $iEndPos)
  117. {
  118. $sContent = "";
  119. $iContentStart = strpos($this->m_sTemplate, '>', $iStartPos); // Content of tag start immediatly after the first closing bracket
  120. if ($iContentStart !== false)
  121. {
  122. $sContent = substr($this->m_sTemplate, 1+$iContentStart, $iEndPos - $iContentStart - 1);
  123. }
  124. return $sContent;
  125. }
  126. public function GetTagAttributes($sTag, $iStartPos, $iEndPos)
  127. {
  128. $aAttr = array();
  129. $iAttrStart = strpos($this->m_sTemplate, ' ', $iStartPos); // Attributes start just after the first space
  130. $iAttrEnd = strpos($this->m_sTemplate, '>', $iStartPos); // Attributes end just before the first closing bracket
  131. if ( ($iAttrStart !== false) && ($iAttrEnd !== false) && ($iAttrEnd > $iAttrStart))
  132. {
  133. $sAttributes = substr($this->m_sTemplate, 1+$iAttrStart, $iAttrEnd - $iAttrStart - 1);
  134. $aAttributes = explode(' ', $sAttributes);
  135. foreach($aAttributes as $sAttr)
  136. {
  137. if ( preg_match('/(.+) *= *"(.+)"$/', $sAttr, $aMatches) )
  138. {
  139. $aAttr[strtolower($aMatches[1])] = $aMatches[2];
  140. }
  141. }
  142. }
  143. return $aAttr;
  144. }
  145. protected function RenderTag($oPage, $sTag, $aAttributes, $sContent)
  146. {
  147. static $iTabContainerCount = 0;
  148. switch($sTag)
  149. {
  150. case 'itoptabs':
  151. $oPage->AddTabContainer('Tabs_'.$iTabContainerCount);
  152. $oPage->SetCurrentTabContainer('Tabs_'.$iTabContainerCount);
  153. $iTabContainerCount++;
  154. //$oPage->p('Content:<pre>'.htmlentities($sContent, ENT_QUOTES, 'UTF-8').'</pre>');
  155. $oTemplate = new DisplayTemplate($sContent);
  156. $oTemplate->Render($oPage, array()); // no params to apply, they have already been applied
  157. $oPage->SetCurrentTabContainer('');
  158. break;
  159. case 'itopcheck':
  160. $sClassName = $aAttributes['class'];
  161. if (MetaModel::IsValidClass($sClassName) && UserRights::IsActionAllowed($sClassName, UR_ACTION_READ))
  162. {
  163. $oTemplate = new DisplayTemplate($sContent);
  164. $oTemplate->Render($oPage, array()); // no params to apply, they have already been applied
  165. }
  166. else
  167. {
  168. // Leave a trace for those who'd like to understand why nothing is displayed
  169. $oPage->add("<!-- class $sClassName does not exist, skipping some part of the template -->\n");
  170. }
  171. break;
  172. case 'itoptab':
  173. $oPage->SetCurrentTab(Dict::S(str_replace('_', ' ', $aAttributes['name'])));
  174. $oTemplate = new DisplayTemplate($sContent);
  175. $oTemplate->Render($oPage, array()); // no params to apply, they have already been applied
  176. //$oPage->p('iTop Tab Content:<pre>'.htmlentities($sContent, ENT_QUOTES, 'UTF-8').'</pre>');
  177. $oPage->SetCurrentTab('');
  178. break;
  179. case 'itoptoggle':
  180. $sName = isset($aAttributes['name']) ? $aAttributes['name'] : 'Tagada';
  181. $bOpen = isset($aAttributes['open']) ? $aAttributes['open'] : true;
  182. $oPage->StartCollapsibleSection(Dict::S($sName), $bOpen);
  183. $oTemplate = new DisplayTemplate($sContent);
  184. $oTemplate->Render($oPage, array()); // no params to apply, they have already been applied
  185. //$oPage->p('iTop Tab Content:<pre>'.htmlentities($sContent, ENT_QUOTES, 'UTF-8').'</pre>');
  186. $oPage->EndCollapsibleSection();
  187. break;
  188. case 'itopstring':
  189. $oPage->add(Dict::S($sContent));
  190. break;
  191. case 'itopblock': // No longer used, handled by DisplayBlock::FromTemplate see above
  192. $oPage->add("<!-- Application Error: should be handled by DisplayBlock::FromTemplate -->");
  193. break;
  194. default:
  195. // Unknown tag, just ignore it or now -- output an HTML comment
  196. $oPage->add("<!-- unsupported tag: $sTag -->");
  197. }
  198. }
  199. /**
  200. * Unit test
  201. */
  202. static public function UnitTest()
  203. {
  204. require_once(APPROOT.'/application/startup.inc.php');
  205. require_once(APPROOT."/application/itopwebpage.class.inc.php");
  206. $sTemplate = '<div class="page_header">
  207. <div class="actions_details"><a href="#"><span>Actions</span></a></div>
  208. <h1>$class$: <span class="hilite">$name$</span></h1>
  209. <itopblock blockclass="HistoryBlock" type="toggle" encoding="text/oql">SELECT CMDBChangeOp WHERE objkey = $id$ AND objclass = \'$class$\'</itopblock>
  210. </div>
  211. <img src="../../images/connect_to_network.png" style="margin-top:-10px; margin-right:10px; float:right">
  212. <itopblock blockclass="DisplayBlock" asynchronous="false" type="bare_details" encoding="text/oql">SELECT NetworkDevice AS d WHERE d.id = $id$</itopblock>
  213. <itoptabs>
  214. <itoptab name="Interfaces">
  215. <itopblock blockclass="DisplayBlock" type="list" encoding="text/oql">SELECT Interface AS i WHERE i.device_id = $id$</itopblock>
  216. </itoptab>
  217. <itoptab name="Contacts">
  218. <itopblock blockclass="DisplayBlock" type="list" encoding="text/oql">SELECT Contact AS c JOIN lnkContactToCI AS l ON l.contact_id = c.id WHERE l.ci_id = $id$</itopblock>
  219. </itoptab>
  220. <itoptab name="Documents">
  221. <itopblock blockclass="DisplayBlock" type="list" encoding="text/oql">SELECT Document AS d JOIN lnkDocumentToCI as l ON l.document_id = d.id WHERE l.ci_id = $id$)</itopblock>
  222. </itoptab>
  223. </itoptabs>';
  224. $oPage = new iTopWebPage('Unit Test');
  225. //$oPage->add("Template content: <pre>".htmlentities($sTemplate, ENT_QUOTES, 'UTF-8')."</pre>\n");
  226. $oTemplate = new DisplayTemplate($sTemplate);
  227. $oTemplate->Render($oPage, array('class'=>'Network device','pkey'=> 271, 'name' => 'deliversw01.mecanorama.fr', 'org_id' => 3));
  228. $oPage->output();
  229. }
  230. }
  231. //DisplayTemplate::UnitTest();
  232. ?>