PageRenderTime 25ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 0ms

/extensions/SemanticForms/includes/SF_TemplateInForm.php

https://github.com/ChuguluGames/mediawiki-svn
PHP | 204 lines | 155 code | 14 blank | 35 comment | 24 complexity | 68a61c4dfae1c8acaedc16facea506b8 MD5 | raw file
  1. <?php
  2. /**
  3. * Represents a template in a user-defined form.
  4. * @author Yaron Koren
  5. * @file
  6. * @ingroup SF
  7. */
  8. class SFTemplateInForm {
  9. private $mTemplateName;
  10. private $mLabel;
  11. private $mAllowMultiple;
  12. private $mMaxAllowed;
  13. private $mFields;
  14. /**
  15. * For a field name and its attached property name located in the
  16. * template text, create an SFTemplateField object out of it, and
  17. * add it to the $templateFields array.
  18. */
  19. function handlePropertySettingInTemplate( $fieldName, $propertyName, $isList, &$templateFields, $templateText ) {
  20. global $wgContLang;
  21. $templateField = SFTemplateField::create( $fieldName, $wgContLang->ucfirst( $fieldName ), $propertyName, $isList );
  22. $cur_pos = stripos( $templateText, $fieldName );
  23. $templateFields[$cur_pos] = $templateField;
  24. }
  25. /**
  26. * Get the fields of the template, along with the semantic property
  27. * attached to each one (if any), by parsing the text of the template.
  28. */
  29. function getAllFields() {
  30. global $wgContLang;
  31. $templateFields = array();
  32. $fieldNamesArray = array();
  33. // The way this works is that fields are found and then stored
  34. // in an array based on their location in the template text, so
  35. // that they can be returned in the order in which they appear
  36. // in the template, not the order in which they were found.
  37. // Some fields can be found more than once (especially if
  38. // they're part of an "#if" statement), so they're only
  39. // recorded the first time they're found.
  40. $template_title = Title::makeTitleSafe( NS_TEMPLATE, $this->mTemplateName );
  41. $template_article = null;
  42. if ( isset( $template_title ) ) $template_article = new Article( $template_title, 0 );
  43. if ( isset( $template_article ) ) {
  44. $templateText = $template_article->getContent();
  45. // Ignore 'noinclude' sections and 'includeonly' tags.
  46. $templateText = StringUtils::delimiterReplace( '<noinclude>', '</noinclude>', '', $templateText );
  47. $templateText = strtr( $templateText, array( '<includeonly>' => '', '</includeonly>' => '' ) );
  48. // First, look for "arraymap" parser function calls
  49. // that map a property onto a list.
  50. if ( $ret = preg_match_all( '/{{#arraymap:{{{([^|}]*:?[^|}]*)[^\[]*\[\[([^:]*:?[^:]*)::/mis', $templateText, $matches ) ) {
  51. foreach ( $matches[1] as $i => $field_name ) {
  52. if ( ! in_array( $field_name, $fieldNamesArray ) ) {
  53. $propertyName = $matches[2][$i];
  54. $this->handlePropertySettingInTemplate( $field_name, $propertyName, true, $templateFields, $templateText );
  55. $fieldNamesArray[] = $field_name;
  56. }
  57. }
  58. } elseif ( $ret === false ) {
  59. // There was an error in the preg_match_all()
  60. // call - let the user know about it.
  61. if ( preg_last_error() == PREG_BACKTRACK_LIMIT_ERROR ) {
  62. print 'Semantic Forms error: backtrace limit exceeded during parsing! Please increase the value of <a href="http://www.php.net/manual/en/pcre.configuration.php#ini.pcre.backtrack-limit">pcre.backtrack-limit</a> in the PHP settings.';
  63. }
  64. }
  65. // Second, look for normal property calls.
  66. if ( preg_match_all( '/\[\[([^:|\[\]]*:*?[^:|\[\]]*)::{{{([^\]\|}]*).*?\]\]/mis', $templateText, $matches ) ) {
  67. foreach ( $matches[1] as $i => $propertyName ) {
  68. $field_name = trim( $matches[2][$i] );
  69. if ( ! in_array( $field_name, $fieldNamesArray ) ) {
  70. $propertyName = trim( $propertyName );
  71. $this->handlePropertySettingInTemplate( $field_name, $propertyName, false, $templateFields, $templateText );
  72. $fieldNamesArray[] = $field_name;
  73. }
  74. }
  75. }
  76. // Then, get calls to #set and #set_internal
  77. // (thankfully, they have basically the same syntax).
  78. if ( preg_match_all( '/#(set|set_internal):(.*?}}})\s*}}/mis', $templateText, $matches ) ) {
  79. foreach ( $matches[2] as $i => $match ) {
  80. if ( preg_match_all( '/([^|{]*?)=\s*{{{([^|}]*)/mis', $match, $matches2 ) ) {
  81. foreach ( $matches2[1] as $i => $propertyName ) {
  82. $fieldName = trim( $matches2[2][$i] );
  83. if ( ! in_array( $fieldName, $fieldNamesArray ) ) {
  84. $propertyName = trim( $propertyName );
  85. $this->handlePropertySettingInTemplate( $fieldName, $propertyName, false, $templateFields, $templateText );
  86. $fieldNamesArray[] = $fieldName;
  87. }
  88. }
  89. }
  90. }
  91. }
  92. // Then, get calls to #declare.
  93. if ( preg_match_all( '/#declare:(.*?)}}/mis', $templateText, $matches ) ) {
  94. foreach ( $matches[1] as $i => $match ) {
  95. $setValues = explode( '|', $match );
  96. foreach( $setValues as $valuePair ) {
  97. $keyAndVal = explode( '=', $valuePair );
  98. if ( count( $keyAndVal ) == 2) {
  99. $propertyName = trim( $keyAndVal[0] );
  100. $fieldName = trim( $keyAndVal[1] );
  101. if ( ! in_array( $fieldName, $fieldNamesArray ) ) {
  102. $this->handlePropertySettingInTemplate( $fieldName, $propertyName, false, $templateFields, $templateText );
  103. $fieldNamesArray[] = $fieldName;
  104. }
  105. }
  106. }
  107. }
  108. }
  109. // Finally, get any non-semantic fields defined.
  110. if ( preg_match_all( '/{{{([^|}]*)/mis', $templateText, $matches ) ) {
  111. foreach ( $matches[1] as $i => $fieldName ) {
  112. $fieldName = trim( $fieldName );
  113. if ( !empty( $fieldName ) && ( ! in_array( $fieldName, $fieldNamesArray ) ) ) {
  114. $cur_pos = stripos( $templateText, $fieldName );
  115. $templateFields[$cur_pos] = SFTemplateField::create( $fieldName, $wgContLang->ucfirst( $fieldName ) );
  116. $fieldNamesArray[] = $fieldName;
  117. }
  118. }
  119. }
  120. }
  121. ksort( $templateFields );
  122. return $templateFields;
  123. }
  124. static function create( $name, $label = null, $allowMultiple = null, $maxAllowed = null ) {
  125. $tif = new SFTemplateInForm();
  126. $tif->mTemplateName = str_replace( '_', ' ', $name );
  127. $tif->mFields = array();
  128. $fields = $tif->getAllFields();
  129. $field_num = 0;
  130. foreach ( $fields as $field ) {
  131. $tif->mFields[] = SFFormField::create( $field_num++, $field );
  132. }
  133. $tif->mLabel = $label;
  134. $tif->mAllowMultiple = $allowMultiple;
  135. $tif->mMaxAllowed = $maxAllowed;
  136. return $tif;
  137. }
  138. function getTemplateName() {
  139. return $this->mTemplateName;
  140. }
  141. function getFields() {
  142. return $this->mFields;
  143. }
  144. function creationHTML( $template_num ) {
  145. $checked_str = ( $this->mAllowMultiple ) ? "checked" : "";
  146. $template_str = wfMsg( 'sf_createform_template' );
  147. $template_label_input = wfMsg( 'sf_createform_templatelabelinput' );
  148. $allow_multiple_text = wfMsg( 'sf_createform_allowmultiple' );
  149. $text = <<<END
  150. <input type="hidden" name="template_$template_num" value="$this->mTemplateName">
  151. <div class="templateForm">
  152. <h2>$template_str '$this->mTemplateName'</h2>
  153. <p>$template_label_input <input size=25 name="label_$template_num" value="$this->mLabel"></p>
  154. <p><input type="checkbox" name="allow_multiple_$template_num" $checked_str> $allow_multiple_text</p>
  155. <hr>
  156. END;
  157. foreach ( $this->mFields as $field ) {
  158. $text .= $field->creationHTML( $template_num );
  159. }
  160. $removeTemplateButton = Xml::element( 'input', array(
  161. 'type' => 'submit',
  162. 'name' => 'del_' . $template_num,
  163. 'value' => wfMsg( 'sf_createform_removetemplate' )
  164. ) );
  165. $text .= "\t" . Xml::tags( 'p', null, $removeTemplateButton ) . "\n";
  166. $text .= " </div>\n";
  167. return $text;
  168. }
  169. function createMarkup() {
  170. $text = "{{{for template|" . $this->mTemplateName;
  171. if ( $this->mAllowMultiple ) {
  172. $text .= "|multiple";
  173. }
  174. if ( $this->mLabel != '' ) {
  175. $text .= "|label=" . $this->mLabel;
  176. }
  177. $text .= "}}}\n";
  178. // For now, HTML for templates differs for multiple-instance
  179. // templates; this may change if handling of form definitions
  180. // gets more sophisticated.
  181. if ( ! $this->mAllowMultiple ) { $text .= "{| class=\"formtable\"\n"; }
  182. foreach ( $this->mFields as $i => $field ) {
  183. $is_last_field = ( $i == count( $this->mFields ) - 1 );
  184. $text .= $field->createMarkup( $this->mAllowMultiple, $is_last_field );
  185. }
  186. if ( ! $this->mAllowMultiple ) { $text .= "|}\n"; }
  187. $text .= "{{{end template}}}\n";
  188. return $text;
  189. }
  190. }