Form.php 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233
  1. <?php
  2. /* vim: set expandtab sw=4 ts=4 sts=4: */
  3. /**
  4. * Form handling code.
  5. *
  6. * @package PhpMyAdmin
  7. */
  8. namespace PhpMyAdmin\Config;
  9. use PhpMyAdmin\Config\ConfigFile;
  10. /**
  11. * Base class for forms, loads default configuration options, checks allowed
  12. * values etc.
  13. *
  14. * @package PhpMyAdmin
  15. */
  16. class Form
  17. {
  18. /**
  19. * Form name
  20. * @var string
  21. */
  22. public $name;
  23. /**
  24. * Arbitrary index, doesn't affect class' behavior
  25. * @var int
  26. */
  27. public $index;
  28. /**
  29. * Form fields (paths), filled by {@link readFormPaths()}, indexed by field name
  30. * @var array
  31. */
  32. public $fields;
  33. /**
  34. * Stores default values for some fields (eg. pmadb tables)
  35. * @var array
  36. */
  37. public $default;
  38. /**
  39. * Caches field types, indexed by field names
  40. * @var array
  41. */
  42. private $_fieldsTypes;
  43. /**
  44. * ConfigFile instance
  45. * @var ConfigFile
  46. */
  47. private $_configFile;
  48. /**
  49. * Constructor, reads default config values
  50. *
  51. * @param string $form_name Form name
  52. * @param array $form Form data
  53. * @param ConfigFile $cf Config file instance
  54. * @param int $index arbitrary index, stored in Form::$index
  55. */
  56. public function __construct(
  57. $form_name, array $form, ConfigFile $cf, $index = null
  58. ) {
  59. $this->index = $index;
  60. $this->_configFile = $cf;
  61. $this->loadForm($form_name, $form);
  62. }
  63. /**
  64. * Returns type of given option
  65. *
  66. * @param string $option_name path or field name
  67. *
  68. * @return string|null one of: boolean, integer, double, string, select, array
  69. */
  70. public function getOptionType($option_name)
  71. {
  72. $key = ltrim(
  73. mb_substr(
  74. $option_name,
  75. mb_strrpos($option_name, '/')
  76. ),
  77. '/'
  78. );
  79. return isset($this->_fieldsTypes[$key])
  80. ? $this->_fieldsTypes[$key]
  81. : null;
  82. }
  83. /**
  84. * Returns allowed values for select fields
  85. *
  86. * @param string $option_path Option path
  87. *
  88. * @return array
  89. */
  90. public function getOptionValueList($option_path)
  91. {
  92. $value = $this->_configFile->getDbEntry($option_path);
  93. if ($value === null) {
  94. trigger_error("$option_path - select options not defined", E_USER_ERROR);
  95. return array();
  96. }
  97. if (!is_array($value)) {
  98. trigger_error("$option_path - not a static value list", E_USER_ERROR);
  99. return array();
  100. }
  101. // convert array('#', 'a', 'b') to array('a', 'b')
  102. if (isset($value[0]) && $value[0] === '#') {
  103. // remove first element ('#')
  104. array_shift($value);
  105. // $value has keys and value names, return it
  106. return $value;
  107. }
  108. // convert value list array('a', 'b') to array('a' => 'a', 'b' => 'b')
  109. $has_string_keys = false;
  110. $keys = array();
  111. for ($i = 0, $nb = count($value); $i < $nb; $i++) {
  112. if (!isset($value[$i])) {
  113. $has_string_keys = true;
  114. break;
  115. }
  116. $keys[] = is_bool($value[$i]) ? (int)$value[$i] : $value[$i];
  117. }
  118. if (! $has_string_keys) {
  119. $value = array_combine($keys, $value);
  120. }
  121. // $value has keys and value names, return it
  122. return $value;
  123. }
  124. /**
  125. * array_walk callback function, reads path of form fields from
  126. * array (see docs for \PhpMyAdmin\Config\Forms\BaseForm::getForms)
  127. *
  128. * @param mixed $value Value
  129. * @param mixed $key Key
  130. * @param mixed $prefix Prefix
  131. *
  132. * @return void
  133. */
  134. private function _readFormPathsCallback($value, $key, $prefix)
  135. {
  136. static $group_counter = 0;
  137. if (is_array($value)) {
  138. $prefix .= $key . '/';
  139. array_walk($value, array($this, '_readFormPathsCallback'), $prefix);
  140. return;
  141. }
  142. if (!is_int($key)) {
  143. $this->default[$prefix . $key] = $value;
  144. $value = $key;
  145. }
  146. // add unique id to group ends
  147. if ($value == ':group:end') {
  148. $value .= ':' . $group_counter++;
  149. }
  150. $this->fields[] = $prefix . $value;
  151. }
  152. /**
  153. * Reads form paths to {@link $fields}
  154. *
  155. * @param array $form Form
  156. *
  157. * @return void
  158. */
  159. protected function readFormPaths(array $form)
  160. {
  161. // flatten form fields' paths and save them to $fields
  162. $this->fields = array();
  163. array_walk($form, array($this, '_readFormPathsCallback'), '');
  164. // $this->fields is an array of the form: [0..n] => 'field path'
  165. // change numeric indexes to contain field names (last part of the path)
  166. $paths = $this->fields;
  167. $this->fields = array();
  168. foreach ($paths as $path) {
  169. $key = ltrim(
  170. mb_substr($path, mb_strrpos($path, '/')),
  171. '/'
  172. );
  173. $this->fields[$key] = $path;
  174. }
  175. // now $this->fields is an array of the form: 'field name' => 'field path'
  176. }
  177. /**
  178. * Reads fields' types to $this->_fieldsTypes
  179. *
  180. * @return void
  181. */
  182. protected function readTypes()
  183. {
  184. $cf = $this->_configFile;
  185. foreach ($this->fields as $name => $path) {
  186. if (mb_strpos($name, ':group:') === 0) {
  187. $this->_fieldsTypes[$name] = 'group';
  188. continue;
  189. }
  190. $v = $cf->getDbEntry($path);
  191. if ($v !== null) {
  192. $type = is_array($v) ? 'select' : $v;
  193. } else {
  194. $type = gettype($cf->getDefault($path));
  195. }
  196. $this->_fieldsTypes[$name] = $type;
  197. }
  198. }
  199. /**
  200. * Reads form settings and prepares class to work with given subset of
  201. * config file
  202. *
  203. * @param string $form_name Form name
  204. * @param array $form Form
  205. *
  206. * @return void
  207. */
  208. public function loadForm($form_name, array $form)
  209. {
  210. $this->name = $form_name;
  211. $this->readFormPaths($form);
  212. $this->readTypes();
  213. }
  214. }