/lib/eztemplate/classes/eztemplatestringoperator.php

https://github.com/lserwatka/ezpublish · PHP · 754 lines · 678 code · 25 blank · 51 comment · 14 complexity · 86b601a72bd9e261862a1b05429187b0 MD5 · raw file

  1. <?php
  2. //
  3. // Definition of eZTemplateStringOperator class
  4. //
  5. // Created on: <17-Jul-2003 13:00:18 bh>
  6. //
  7. // ## BEGIN COPYRIGHT, LICENSE AND WARRANTY NOTICE ##
  8. // SOFTWARE NAME: eZ Publish
  9. // SOFTWARE RELEASE: 4.1.x
  10. // COPYRIGHT NOTICE: Copyright (C) 1999-2010 eZ Systems AS
  11. // SOFTWARE LICENSE: GNU General Public License v2.0
  12. // NOTICE: >
  13. // This program is free software; you can redistribute it and/or
  14. // modify it under the terms of version 2.0 of the GNU General
  15. // Public License as published by the Free Software Foundation.
  16. //
  17. // This program is distributed in the hope that it will be useful,
  18. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  19. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  20. // GNU General Public License for more details.
  21. //
  22. // You should have received a copy of version 2.0 of the GNU General
  23. // Public License along with this program; if not, write to the Free
  24. // Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
  25. // MA 02110-1301, USA.
  26. //
  27. //
  28. // ## END COPYRIGHT, LICENSE AND WARRANTY NOTICE ##
  29. //
  30. /*!
  31. \class eZTemplateStringOperator eztemplatestringoperator.php
  32. \ingroup eZTemplateOperators
  33. \code
  34. \endcode
  35. */
  36. class eZTemplateStringOperator
  37. {
  38. /*!
  39. Constructor.
  40. */
  41. function eZTemplateStringOperator()
  42. {
  43. $this->Operators = array( 'upcase', 'downcase',
  44. 'count_words', 'count_chars',
  45. 'trim', 'break', 'wrap', 'shorten', 'pad',
  46. 'upfirst', 'upword',
  47. 'simplify', 'wash',
  48. 'chr', 'ord');
  49. foreach ( $this->Operators as $operator )
  50. {
  51. $name = $operator . 'Name';
  52. $name[0] = $name[0] & "\xdf";
  53. $this->$name = $operator;
  54. }
  55. $this->phpMap = array ('upcase' => 'mb_strtoupper,strtoupper',
  56. 'downcase' => 'mb_strtolower,strtolower',
  57. 'break' => 'nl2br',
  58. 'count_chars' => 'mb_strlen,strlen');
  59. $this->customMap = array ( 'count_words' => array( 'return' => 'int',
  60. 'code' => '$result = preg_match_all( "#(\w+)#", $staticValues[0], $dummy );'
  61. ),
  62. 'chr' => array( 'return' => 'string',
  63. 'code' => '$codec = eZTextCodec::instance( "unicode", false );' . "\n" .
  64. '$result = $codec->convertString( $staticValues[0] );'
  65. ),
  66. 'ord' => array( 'return' => 'string',
  67. 'code' => '$codec = eZTextCodec::instance( false, "unicode" );' . "\n" .
  68. '$result = $codec->convertString( $staticValues[0] );'
  69. ),
  70. 'pad' => array( 'return' => 'string',
  71. 'code' => '$result = $paramCount == 2 ? str_pad( $staticValues[0], $staticValues[1] ) : str_pad ( $staticValues[0], $staticValues[1], $staticValues[2] );',
  72. 'code2' => '$result = str_pad( $staticValues[0], $staticValues[1] );',
  73. 'code3' => '$result = str_pad( $staticValues[0], $staticValues[1], $staticValues[2] );',
  74. ),
  75. 'trim' => array( 'return' => 'string',
  76. 'code' => '$result = $paramCount == 1 ? trim( $staticValues[0] ) : trim ( $staticValues[0], $staticValues[1] );',
  77. 'code1' => '$result = trim( $staticValues[0] );',
  78. 'code2' => '$result = trim( $staticValues[0], $staticValues[1] );',
  79. ),
  80. 'wrap' => array( 'return' => 'string',
  81. 'code1' => '$result = wordwrap( $staticValues[0] );',
  82. 'code2' => '$result = wordwrap( $staticValues[0], $staticValues[1] );',
  83. 'code3' => '$result = wordwrap( $staticValues[0], $staticValues[1], $staticValues[2] );',
  84. 'code4' => '$result = wordwrap( $staticValues[0], $staticValues[1], $staticValues[2], $staticValues[3] );',
  85. ),
  86. 'simplify' => array( 'return' => 'string',
  87. 'code' => 'if ( $paramCount == 1 )
  88. {
  89. $replacer = " ";
  90. }
  91. else
  92. {
  93. $replacer = $staticValues[1];
  94. }
  95. $result = preg_replace( "/".$replacer."{2,}/", $replacer, $staticValues[0] );',
  96. 'code1' => '$result = preg_replace( "/ {2,}/", " ", $staticValues[0] );',
  97. 'code2' => '$result = preg_replace( "/".$staticValues[1]."{2,}/", $staticValues[1], $staticValues[0] );',
  98. ),
  99. 'shorten' => array( 'return' => 'string',
  100. 'code' => '$length = 80; $seq = "..."; $trimType = "right";
  101. if ( $paramCount > 1 )
  102. {
  103. $length = $staticValues[1];
  104. }
  105. if ( $paramCount > 2 )
  106. {
  107. $seq = $staticValues[2];
  108. }
  109. if ( $paramCount > 3 )
  110. {
  111. $trimType = $staticValues[3];
  112. }
  113. if ( $trimType === "middle" )
  114. {
  115. $appendedStrLen = $strlenFunc( $seq );
  116. if ( $length > $appendedStrLen && ( $strlenFunc( $staticValues[0] ) > $length ) )
  117. {
  118. $operatorValueLength = $strlenFunc( $staticValues[0] );
  119. $chop = $length - $appendedStrLen;
  120. $middlePos = (int)($chop / 2);
  121. $leftPartLength = $middlePos;
  122. $rightPartLength = $chop - $middlePos;
  123. $result = trim( $substrFunc( $staticValues[0], 0, $leftPartLength ) . $seq . $substrFunc( $staticValues[0], $operatorValueLength - $rightPartLength, $rightPartLength ) );
  124. }
  125. else
  126. {
  127. $result = $staticValues[0];
  128. }
  129. }
  130. else // default: trim_type === "right"
  131. {
  132. $maxLength = $length - $strlenFunc( $seq );
  133. if ( ( $strlenFunc( $staticValues[0] ) > $length ) && $strlenFunc( $staticValues[0] ) > $maxLength )
  134. {
  135. $result = trim( $substrFunc( $staticValues[0], 0, $maxLength) ) . $seq;
  136. }
  137. else
  138. {
  139. $result = $staticValues[0];
  140. }
  141. }'
  142. ),
  143. 'upfirst' => array( 'return' => 'string',
  144. 'code' => '$i18nIni = eZINI::instance( \'i18n.ini\' );
  145. $hasMBString = ( $i18nIni->variable( \'CharacterSettings\', \'MBStringExtension\' ) == \'enabled\' and
  146. function_exists( "mb_strtoupper" ) and
  147. function_exists( "mb_substr" ) and
  148. function_exists( "mb_strlen" ) );
  149. if ( $hasMBString )
  150. {
  151. $encoding = eZTextCodec::internalCharset();
  152. $firstLetter = mb_strtoupper( mb_substr( $staticValues[0], 0, 1, $encoding ), $encoding );
  153. $remainingText = mb_substr( $staticValues[0], 1, mb_strlen( $staticValues[0], $encoding ), $encoding );
  154. $result = $firstLetter . $remainingText;
  155. }
  156. else
  157. {
  158. $result = ucfirst( $staticValues[0] );
  159. }'
  160. ),
  161. 'upword' => array( 'return' => 'string',
  162. 'code' => ' $i18nIni = eZINI::instance( \'i18n.ini\' );
  163. $hasMBString = ( $i18nIni->variable( \'CharacterSettings\', \'MBStringExtension\' ) == \'enabled\' and
  164. function_exists( "mb_strtoupper" ) and
  165. function_exists( "mb_substr" ) and
  166. function_exists( "mb_strlen" ) );
  167. if ( $hasMBString )
  168. {
  169. $encoding = eZTextCodec::internalCharset();
  170. $words = explode( " ", $staticValues[0] );
  171. $newString = array();
  172. foreach ( $words as $word )
  173. {
  174. $firstLetter = mb_strtoupper( mb_substr( $word, 0, 1, $encoding ), $encoding );
  175. $remainingText = mb_substr( $word, 1, mb_strlen( $word, $encoding ), $encoding );
  176. $newString[] = $firstLetter . $remainingText;
  177. }
  178. $result = implode( " ", $newString );
  179. unset( $newString, $words );
  180. }
  181. else
  182. {
  183. $result = ucwords( $staticValues[0] );
  184. }'
  185. )
  186. );
  187. }
  188. /*!
  189. Returns the template operators.
  190. */
  191. function operatorList()
  192. {
  193. return $this->Operators;
  194. }
  195. function operatorTemplateHints()
  196. {
  197. $hints = array(
  198. $this->BreakName => array( 'parameters' => false, 'element-transformation-func' => 'phpMapTransformation' ),
  199. $this->Count_charsName => array( 'parameters' => false, 'element-transformation-func' => 'phpMapTransformation' ),
  200. $this->DowncaseName => array( 'parameters' => false, 'element-transformation-func' => 'phpMapTransformation' ),
  201. $this->UpcaseName => array( 'parameters' => false, 'element-transformation-func' => 'phpMapTransformation' ),
  202. $this->UpfirstName => array( 'parameters' => false, 'element-transformation-func' => 'customMapTransformation' ),
  203. $this->UpwordName => array( 'parameters' => false, 'element-transformation-func' => 'customMapTransformation' ),
  204. $this->Count_wordsName => array( 'parameters' => false, 'element-transformation-func' => 'customMapTransformation' ),
  205. $this->ChrName => array( 'parameters' => false, 'element-transformation-func' => 'customMapTransformation' ),
  206. $this->OrdName => array( 'parameters' => false, 'element-transformation-func' => 'customMapTransformation' ),
  207. $this->PadName => array( 'parameters' => false, 'element-transformation-func' => 'customMapTransformation' ),
  208. $this->ShortenName => array( 'parameters' => 3 , 'element-transformation-func' => 'customMapTransformation' ),
  209. $this->SimplifyName => array( 'parameters' => false, 'element-transformation-func' => 'customMapTransformation' ),
  210. $this->TrimName => array( 'parameters' => 1 , 'element-transformation-func' => 'customMapTransformation' ),
  211. $this->WrapName => array( 'parameters' => false, 'element-transformation-func' => 'customMapTransformation' ),
  212. $this->WashName => array( 'parameters' => 1, 'element-transformation-func' => 'washTransformation' ),
  213. );
  214. foreach ( $this->Operators as $operator )
  215. {
  216. $hints[$operator]['input'] = true;
  217. $hints[$operator]['output'] = true;
  218. $hints[$operator]['element-transformation'] = true;
  219. $hints[$operator]['transform-parameters'] = true;
  220. if ( !isset( $hints[$operator]['input-as-parameter'] ) )
  221. $hints[$operator]['input-as-parameter'] = 'always';
  222. }
  223. return $hints;
  224. }
  225. /*!
  226. \return true to tell the template engine that the parameter list exists per operator type.
  227. */
  228. function namedParameterPerOperator()
  229. {
  230. return true;
  231. }
  232. /*!
  233. See eZTemplateOperator::namedParameterList()
  234. */
  235. function namedParameterList()
  236. {
  237. return array( $this->TrimName => array( 'chars_to_remove' => array( "type" => "string",
  238. "required" => false,
  239. "default" => false ) ),
  240. $this->WrapName => array( 'wrap_at_position' => array( "type" => "integer",
  241. "required" => false,
  242. "default" => false ),
  243. 'break_sequence' => array( "type" => "string",
  244. "required" => false,
  245. "default" => false ),
  246. 'cut' => array( "type" => "boolean",
  247. "required" => false,
  248. "default" => false ) ),
  249. $this->WashName => array( 'type' => array( "type" => "string",
  250. "required" => false,
  251. "default" => "xhtml" ) ),
  252. $this->ShortenName => array( 'chars_to_keep' => array( "type" => "integer",
  253. "required" => false,
  254. "default" => 80 ),
  255. 'str_to_append' => array( "type" => "string",
  256. "required" => false,
  257. "default" => "..." ),
  258. 'trim_type' => array( "type" => "string",
  259. "required" => false,
  260. "default" => "right" ) ),
  261. $this->PadName => array( 'desired_length' => array( "type" => "integer",
  262. "required" => false,
  263. "default" => 80 ),
  264. 'pad_sequence' => array( "type" => "string",
  265. "required" => false,
  266. "default" => " " ) ),
  267. $this->SimplifyName => array ( 'char' => array( "type" => "string",
  268. "required" => false,
  269. "default" => false ) ) );
  270. }
  271. function phpMapTransformation( $operatorName, $node, $tpl, $resourceData,
  272. $element, $lastElement, $elementList, $elementTree, &$parameters )
  273. {
  274. $values = array();
  275. $phpFunctionList = explode( ',', $this->phpMap[$operatorName] );
  276. foreach ( $phpFunctionList as $element )
  277. {
  278. if ( function_exists( $element ) )
  279. {
  280. $phpFunction = $element;
  281. break;
  282. }
  283. }
  284. $newElements = array();
  285. if ( count ( $parameters ) != 1 )
  286. {
  287. return false;
  288. }
  289. if ( eZTemplateNodeTool::isStaticElement( $parameters[0] ) )
  290. {
  291. $text = eZTemplateNodeTool::elementStaticValue( $parameters[0] );
  292. $text = $phpFunction( $text );
  293. $text = str_replace( array( "'" ), array( "\\'" ), $text );
  294. $code = "%output% = '" . $text . "' ;\n";
  295. }
  296. else
  297. {
  298. $values[] = $parameters[0];
  299. $code = "%output% = $phpFunction( %1% );\n";
  300. }
  301. $newElements[] = eZTemplateNodeTool::createCodePieceElement( $code, $values );
  302. return $newElements;
  303. }
  304. function customMapTransformation( $operatorName, $node, $tpl, $resourceData,
  305. $element, $lastElement, $elementList, $elementTree, &$parameters )
  306. {
  307. $values = array();
  308. $newElements = array();
  309. $mapEntry = $this->customMap[$operatorName];
  310. $paramCount = count( $parameters );
  311. $strlenFunc = 'strlen';
  312. $substrFunc = 'substr';
  313. $code = "\$strlenFunc = 'strlen'; \$substrFunc = 'substr';\n";
  314. if ( function_exists( 'mb_strlen' ) )
  315. {
  316. $strlenFunc = 'mb_strlen';
  317. $substrFunc = 'mb_substr';
  318. $code = "\$strlenFunc = 'mb_strlen'; \$substrFunc = 'mb_substr';\n";
  319. }
  320. if ( $paramCount < 1 )
  321. {
  322. return false;
  323. }
  324. $allStatic = true;
  325. $staticValues = array();
  326. $replaceMap = array('$result');
  327. $replacementMap = array('%output%');
  328. for ($i = 0; $i < $paramCount; $i++)
  329. {
  330. if ( eZTemplateNodeTool::isStaticElement( $parameters[$i] ) )
  331. {
  332. $staticValues[$i] = eZTemplateNodeTool::elementStaticValue( $parameters[$i] );
  333. }
  334. else
  335. {
  336. $allStatic = false;
  337. }
  338. }
  339. if ( $allStatic )
  340. {
  341. $result = false;
  342. if ( isset( $mapEntry['code'. $paramCount] ) )
  343. {
  344. eval( $mapEntry['code' . $paramCount] );
  345. }
  346. else
  347. {
  348. eval( $mapEntry['code'] );
  349. }
  350. return array( eZTemplateNodeTool::createStaticElement( $result ) );
  351. }
  352. else
  353. {
  354. $replaceMap = array( '$result', '$paramCount' );
  355. $replacementMap = array( '%output%', $paramCount );
  356. for ( $i = 0; $i < $paramCount; $i++ )
  357. {
  358. $values[] = $parameters[$i];
  359. $replaceMap[] = "\$staticValues[$i]";
  360. $replacementMap[] = '%' . ( $i + 1 ) . '%';
  361. }
  362. if ( isset( $mapEntry['code'. $paramCount] ) )
  363. {
  364. $code .= str_replace( $replaceMap, $replacementMap, $mapEntry['code' . $paramCount] ) . "\n";
  365. }
  366. else
  367. {
  368. $code .= str_replace( $replaceMap, $replacementMap, $mapEntry['code'] ) . "\n";
  369. }
  370. }
  371. $newElements[] = eZTemplateNodeTool::createCodePieceElement( $code, $values );
  372. return $newElements;
  373. }
  374. /*!
  375. * \private
  376. */
  377. function wash( $operatorValue, $tpl, $type = 'xhtml' )
  378. {
  379. switch ( $type )
  380. {
  381. case "xhtml":
  382. {
  383. $operatorValue = htmlspecialchars( $operatorValue );
  384. } break;
  385. case "email":
  386. {
  387. $ini = $tpl->ini();
  388. $dotText = $ini->variable( 'WashSettings', 'EmailDotText' );
  389. $atText = $ini->variable( 'WashSettings', 'EmailAtText' );
  390. $operatorValue = str_replace( array( '.',
  391. '@' ),
  392. array( $dotText,
  393. $atText ),
  394. $operatorValue );
  395. } break;
  396. case 'pdf':
  397. {
  398. $operatorValue = str_replace( array( ' ', // use default callback functions in ezpdf library
  399. "\r\n",
  400. "\t" ),
  401. array( '<C:callSpace>',
  402. '<C:callNewLine>',
  403. '<C:callTab>' ),
  404. $operatorValue );
  405. $operatorValue = str_replace( "\n", '<C:callNewLine>', $operatorValue );
  406. } break;
  407. case 'javascript':
  408. {
  409. $operatorValue = str_replace( array( "\\", "\"", "'"),
  410. array( "\\\\", "\\042", "\\047" ) , $operatorValue );
  411. } break;
  412. }
  413. return $operatorValue;
  414. }
  415. function washTransformation( $operatorName, $node, $tpl, $resourceData,
  416. $element, $lastElement, $elementList, $elementTree, &$parameters )
  417. {
  418. $values = array();
  419. $tmpVarCount = 0;
  420. $newElements = array();
  421. $paramCount = count( $parameters );
  422. if ( $paramCount > 2 )
  423. {
  424. return false;
  425. }
  426. $allStatic = true;
  427. $staticValues = array();
  428. for ($i = 0; $i < $paramCount; $i++)
  429. {
  430. if ( eZTemplateNodeTool::isStaticElement( $parameters[$i] ) )
  431. {
  432. $staticValues[$i] = eZTemplateNodeTool::elementStaticValue( $parameters[$i] );
  433. }
  434. else
  435. {
  436. $allStatic = false;
  437. }
  438. }
  439. /* Do optimalizations for 'xhtml' case */
  440. if ( $allStatic ) {
  441. if ( $paramCount == 1 )
  442. {
  443. $type = 'xhtml';
  444. }
  445. else
  446. {
  447. $type = $staticValues[1];
  448. }
  449. $code = "%output% = '" . addcslashes( $this->wash( $staticValues[0], $tpl, $type ), "'\\" ) . "' ;\n";
  450. }
  451. /* XHTML: Type is static, input is not */
  452. else if ( ( $paramCount == 1 ) || ( ( $paramCount == 2 ) && isset( $staticValues[1] ) && ( $staticValues[1] == 'xhtml' ) ) )
  453. {
  454. $values[] = $parameters[0];
  455. $code = "%output% = htmlspecialchars( %1% );\n";
  456. }
  457. /* PDF: Type is static, input is not static */
  458. else if ( ( $paramCount == 2 ) && isset( $staticValues[1] ) && ( $staticValues[1] == 'pdf' ) )
  459. {
  460. $values[] = $parameters[0];
  461. $tmpVarCount = 1;
  462. $code = '%tmp1% = str_replace( array( " ", "\r\n", "\t" ), array( "<C:callSpace>", "<C:callNewLine>", "<C:callTab>" ), %1% );'. "\n";
  463. $code .= '%output% = str_replace( "\n", "<C:callNewLine>", %tmp1% );'."\n";
  464. }
  465. /* MAIL: Type is static, input is not static */
  466. else if ( ( $paramCount == 2 ) && isset( $staticValues[1] ) && ( $staticValues[1] == 'email' ) )
  467. {
  468. $ini = $tpl->ini();
  469. $dotText = addcslashes( $ini->variable( 'WashSettings', 'EmailDotText' ), "'" );
  470. $atText = addcslashes( $ini->variable( 'WashSettings', 'EmailAtText' ), "'" );
  471. $values[] = $parameters[0];
  472. $code = "%output% = str_replace( array( '.', '@' ), array( '$dotText', '$atText' ), %1% );\n";
  473. }
  474. /* JAVASCRIPT: Type is static, input is not static */
  475. else if ( ( $paramCount == 2 ) && isset( $staticValues[1] ) && ( $staticValues[1] == 'javascript' ) )
  476. {
  477. $values[] = $parameters[0];
  478. $code = '%output% = str_replace( array( "\\\\", "\"", "\'" ),
  479. array( "\\\\\\\\", "\\\\042", "\\\\047" ) , %1% ); ';
  480. }
  481. else /* No compiling for the rest cases */
  482. {
  483. return false;
  484. }
  485. $newElements[] = eZTemplateNodeTool::createCodePieceElement( $code, $values, false, $tmpVarCount );
  486. return $newElements;
  487. }
  488. /*
  489. The modify function takes care of the various operations.
  490. */
  491. function modify( $tpl,
  492. $operatorName,
  493. $operatorParameters,
  494. $rootNamespace,
  495. $currentNamespace,
  496. &$operatorValue,
  497. $namedParameters,
  498. $placement )
  499. {
  500. switch ( $operatorName )
  501. {
  502. // Convert all alphabetical chars of operatorvalue to uppercase.
  503. case $this->UpcaseName:
  504. {
  505. $funcName = function_exists( 'mb_strtoupper' ) ? 'mb_strtoupper' : 'strtoupper';
  506. $operatorValue = $funcName( $operatorValue );
  507. } break;
  508. // Convert all alphabetical chars of operatorvalue to lowercase.
  509. case $this->DowncaseName:
  510. {
  511. $funcName = function_exists( 'mb_strtolower' ) ? 'mb_strtolower' : 'strtolower';
  512. $operatorValue = $funcName( $operatorValue );
  513. } break;
  514. // Count and return the number of words in operatorvalue.
  515. case $this->Count_wordsName:
  516. {
  517. $operatorValue = preg_match_all( "#(\w+)#", $operatorValue, $dummy_match );
  518. }break;
  519. // Count and return the number of chars in operatorvalue.
  520. case $this->Count_charsName:
  521. {
  522. $funcName = function_exists( 'mb_strlen' ) ? 'mb_strlen' : 'strlen';
  523. $operatorValue = $funcName( $operatorValue );
  524. }break;
  525. // Insert HTML line breaks before newlines.
  526. case $this->BreakName:
  527. {
  528. $operatorValue = nl2br( $operatorValue );
  529. }break;
  530. // Wrap line (insert newlines).
  531. case $this->WrapName:
  532. {
  533. $parameters = array( $operatorValue );
  534. if ( $namedParameters['wrap_at_position'] )
  535. {
  536. $parameters[] = $namedParameters['wrap_at_position'];
  537. if ( $namedParameters['break_sequence'] )
  538. {
  539. $parameters[] = $namedParameters['break_sequence'];
  540. if ( $namedParameters['cut'] )
  541. {
  542. $parameters[] = $namedParameters['cut'];
  543. }
  544. }
  545. }
  546. $operatorValue = call_user_func_array( 'wordwrap', $parameters );
  547. }break;
  548. // Convert the first character to uppercase.
  549. case $this->UpfirstName:
  550. {
  551. $i18nIni = eZINI::instance( 'i18n.ini' );
  552. $hasMBString = ( $i18nIni->variable( 'CharacterSettings', 'MBStringExtension' ) == 'enabled' and
  553. function_exists( "mb_strtoupper" ) and
  554. function_exists( "mb_substr" ) and
  555. function_exists( "mb_strlen" ) );
  556. if ( $hasMBString )
  557. {
  558. $encoding = eZTextCodec::internalCharset();
  559. $firstLetter = mb_strtoupper( mb_substr( $operatorValue, 0, 1, $encoding ), $encoding );
  560. $remainingText = mb_substr( $operatorValue, 1, mb_strlen( $operatorValue, $encoding ), $encoding );
  561. $operatorValue = $firstLetter . $remainingText;
  562. }
  563. else
  564. {
  565. $operatorValue = ucfirst( $operatorValue );
  566. }
  567. }break;
  568. // Simplify / transform multiple consecutive characters into one.
  569. case $this->SimplifyName:
  570. {
  571. $simplifyCharacter = $namedParameters['char'];
  572. if ( $namedParameters['char'] === false )
  573. {
  574. $replace_this = "/ {2,}/";
  575. $simplifyCharacter = ' ';
  576. }
  577. else
  578. {
  579. $replace_this = "/". $simplifyCharacter ."{2,}/";
  580. }
  581. $operatorValue = preg_replace( $replace_this, $simplifyCharacter, $operatorValue );
  582. }break;
  583. // Convert all first characters [in all words] to uppercase.
  584. case $this->UpwordName:
  585. {
  586. $i18nIni = eZINI::instance( 'i18n.ini' );
  587. $hasMBString = ( $i18nIni->variable( 'CharacterSettings', 'MBStringExtension' ) == 'enabled' and
  588. function_exists( "mb_strtoupper" ) and
  589. function_exists( "mb_substr" ) and
  590. function_exists( "mb_strlen" ) );
  591. if ( $hasMBString )
  592. {
  593. $encoding = eZTextCodec::internalCharset();
  594. $words = explode( " ", $operatorValue );
  595. $newString = array();
  596. foreach ( $words as $word )
  597. {
  598. $firstLetter = mb_strtoupper( mb_substr( $word, 0, 1, $encoding ), $encoding );
  599. $remainingText = mb_substr( $word, 1, mb_strlen( $word, $encoding ), $encoding );
  600. $newString[]= $firstLetter . $remainingText;
  601. }
  602. $operatorValue = implode( " ", $newString );
  603. unset( $newString, $words );
  604. }
  605. else
  606. {
  607. $operatorValue = ucwords( $operatorValue );
  608. }
  609. }break;
  610. // Strip whitespace from the beginning and end of a string.
  611. case $this->TrimName:
  612. {
  613. if ( $namedParameters['chars_to_remove'] === false )
  614. $operatorValue = trim( $operatorValue );
  615. else
  616. $operatorValue = trim( $operatorValue, $namedParameters['chars_to_remove'] );
  617. }break;
  618. // Pad...
  619. case $this->PadName:
  620. {
  621. if (strlen( $operatorValue ) < $namedParameters['desired_length'])
  622. {
  623. $operatorValue = str_pad( $operatorValue,
  624. $namedParameters['desired_length'],
  625. $namedParameters['pad_sequence'] );
  626. }
  627. }break;
  628. // Shorten string [default or specified length, length=text+"..."] and add '...'
  629. case $this->ShortenName:
  630. {
  631. $strlenFunc = function_exists( 'mb_strlen' ) ? 'mb_strlen' : 'strlen';
  632. $substrFunc = function_exists( 'mb_substr' ) ? 'mb_substr' : 'substr';
  633. if ( $strlenFunc( $operatorValue ) > $namedParameters['chars_to_keep'] )
  634. {
  635. $operatorLength = $strlenFunc( $operatorValue );
  636. if ( $namedParameters['trim_type'] === 'middle' )
  637. {
  638. $appendedStrLen = $strlenFunc( $namedParameters['str_to_append'] );
  639. if ( $namedParameters['chars_to_keep'] > $appendedStrLen )
  640. {
  641. $chop = $namedParameters['chars_to_keep'] - $appendedStrLen;
  642. $middlePos = (int)($chop / 2);
  643. $leftPartLength = $middlePos;
  644. $rightPartLength = $chop - $middlePos;
  645. $operatorValue = trim( $substrFunc( $operatorValue, 0, $leftPartLength ) . $namedParameters['str_to_append'] . $substrFunc( $operatorValue, $operatorLength - $rightPartLength, $rightPartLength ) );
  646. }
  647. else
  648. {
  649. $operatorValue = $namedParameters['str_to_append'];
  650. }
  651. }
  652. else // default: trim_type === 'right'
  653. {
  654. $chop = $namedParameters['chars_to_keep'] - $strlenFunc( $namedParameters['str_to_append'] );
  655. $operatorValue = $substrFunc( $operatorValue, 0, $chop );
  656. $operatorValue = trim( $operatorValue );
  657. if ( $operatorLength > $chop )
  658. $operatorValue = $operatorValue.$namedParameters['str_to_append'];
  659. }
  660. }
  661. }break;
  662. // Wash (translate strings to non-spammable text):
  663. case $this->WashName:
  664. {
  665. $type = $namedParameters['type'];
  666. $operatorValue = $this->wash( $operatorValue, $tpl, $type );
  667. }break;
  668. // Ord (translate a unicode string to actual unicode id/numbers):
  669. case $this->OrdName:
  670. {
  671. $codec = eZTextCodec::instance( false, 'unicode' );
  672. $output = $codec->convertString( $operatorValue );
  673. $operatorValue = $output;
  674. }break;
  675. // Chr (generate unicode characters based on input):
  676. case $this->ChrName:
  677. {
  678. $codec = eZTextCodec::instance( 'unicode', false );
  679. $output = $codec->convertString( $operatorValue );
  680. $operatorValue = $output;
  681. }break;
  682. // Default case: something went wrong - unknown things...
  683. default:
  684. {
  685. $tpl->warning( $operatorName, "Unknown string type '$type'", $placement );
  686. } break;
  687. }
  688. }
  689. /// The array of operators, used for registering operators
  690. public $Operators;
  691. }
  692. ?>