PageRenderTime 46ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 1ms

/src/Forms/GridField/GridFieldDataColumns.php

https://gitlab.com/djpmedia/silverstripe-framework
PHP | 313 lines | 144 code | 32 blank | 137 comment | 19 complexity | 9b84bcbb83cc9d73405b6e95074edd0a MD5 | raw file
  1. <?php
  2. namespace SilverStripe\Forms\GridField;
  3. use SilverStripe\Core\Convert;
  4. use InvalidArgumentException;
  5. use SilverStripe\ORM\DataObject;
  6. /**
  7. * @see GridField
  8. */
  9. class GridFieldDataColumns implements GridField_ColumnProvider
  10. {
  11. /**
  12. * @var array
  13. */
  14. public $fieldCasting = array();
  15. /**
  16. * @var array
  17. */
  18. public $fieldFormatting = array();
  19. /**
  20. * This is the columns that will be visible
  21. *
  22. * @var array
  23. */
  24. protected $displayFields = array();
  25. /**
  26. * Modify the list of columns displayed in the table.
  27. * See {@link GridFieldDataColumns->getDisplayFields()} and {@link GridFieldDataColumns}.
  28. *
  29. * @param GridField $gridField
  30. * @param array - List reference of all column names.
  31. */
  32. public function augmentColumns($gridField, &$columns)
  33. {
  34. $baseColumns = array_keys($this->getDisplayFields($gridField));
  35. foreach ($baseColumns as $col) {
  36. $columns[] = $col;
  37. }
  38. $columns = array_unique($columns);
  39. }
  40. /**
  41. * Names of all columns which are affected by this component.
  42. *
  43. * @param GridField $gridField
  44. * @return array
  45. */
  46. public function getColumnsHandled($gridField)
  47. {
  48. return array_keys($this->getDisplayFields($gridField));
  49. }
  50. /**
  51. * Override the default behaviour of showing the models summaryFields with
  52. * these fields instead
  53. * Example: array( 'Name' => 'Members name', 'Email' => 'Email address')
  54. *
  55. * @param array $fields
  56. * @return $this
  57. */
  58. public function setDisplayFields($fields)
  59. {
  60. if (!is_array($fields)) {
  61. throw new InvalidArgumentException(
  62. 'Arguments passed to GridFieldDataColumns::setDisplayFields() must be an array'
  63. );
  64. }
  65. $this->displayFields = $fields;
  66. return $this;
  67. }
  68. /**
  69. * Get the DisplayFields
  70. *
  71. * @param GridField $gridField
  72. * @return array
  73. * @see GridFieldDataColumns::setDisplayFields
  74. */
  75. public function getDisplayFields($gridField)
  76. {
  77. if (!$this->displayFields) {
  78. return singleton($gridField->getModelClass())->summaryFields();
  79. }
  80. return $this->displayFields;
  81. }
  82. /**
  83. * Specify castings with fieldname as the key, and the desired casting as value.
  84. * Example: array("MyCustomDate"=>"Date","MyShortText"=>"Text->FirstSentence")
  85. *
  86. * @param array $casting
  87. * @return $this
  88. */
  89. public function setFieldCasting($casting)
  90. {
  91. $this->fieldCasting = $casting;
  92. return $this;
  93. }
  94. /**
  95. * @return array
  96. */
  97. public function getFieldCasting()
  98. {
  99. return $this->fieldCasting;
  100. }
  101. /**
  102. * Specify custom formatting for fields, e.g. to render a link instead of pure text.
  103. *
  104. * Caution: Make sure to escape special php-characters like in a normal php-statement.
  105. * Example: "myFieldName" => '<a href=\"custom-admin/$ID\">$ID</a>'.
  106. *
  107. * Alternatively, pass a anonymous function, which takes two parameters:
  108. * The value and the original list item.
  109. *
  110. * Formatting is applied after field casting, so if you're modifying the string
  111. * to include further data through custom formatting, ensure it's correctly escaped.
  112. *
  113. * @param array $formatting
  114. * @return $this
  115. */
  116. public function setFieldFormatting($formatting)
  117. {
  118. $this->fieldFormatting = $formatting;
  119. return $this;
  120. }
  121. /**
  122. * @return array
  123. */
  124. public function getFieldFormatting()
  125. {
  126. return $this->fieldFormatting;
  127. }
  128. /**
  129. * HTML for the column, content of the <td> element.
  130. *
  131. * @param GridField $gridField
  132. * @param DataObject $record Record displayed in this row
  133. * @param string $columnName
  134. * @return string HTML for the column. Return NULL to skip.
  135. */
  136. public function getColumnContent($gridField, $record, $columnName)
  137. {
  138. // Find the data column for the given named column
  139. $columns = $this->getDisplayFields($gridField);
  140. $columnInfo = $columns[$columnName];
  141. // Allow callbacks
  142. if (is_array($columnInfo) && isset($columnInfo['callback'])) {
  143. $method = $columnInfo['callback'];
  144. $value = $method($record);
  145. // This supports simple FieldName syntax
  146. } else {
  147. $value = $gridField->getDataFieldValue($record, $columnName);
  148. }
  149. // Turn $value, whatever it is, into a HTML embeddable string
  150. $value = $this->castValue($gridField, $columnName, $value);
  151. // Make any formatting tweaks
  152. $value = $this->formatValue($gridField, $record, $columnName, $value);
  153. // Do any final escaping
  154. $value = $this->escapeValue($gridField, $value);
  155. return $value;
  156. }
  157. /**
  158. * Attributes for the element containing the content returned by {@link getColumnContent()}.
  159. *
  160. * @param GridField $gridField
  161. * @param DataObject $record displayed in this row
  162. * @param string $columnName
  163. * @return array
  164. */
  165. public function getColumnAttributes($gridField, $record, $columnName)
  166. {
  167. return array('class' => 'col-' . preg_replace('/[^\w]/', '-', $columnName));
  168. }
  169. /**
  170. * Additional metadata about the column which can be used by other components,
  171. * e.g. to set a title for a search column header.
  172. *
  173. * @param GridField $gridField
  174. * @param string $column
  175. * @return array Map of arbitrary metadata identifiers to their values.
  176. */
  177. public function getColumnMetadata($gridField, $column)
  178. {
  179. $columns = $this->getDisplayFields($gridField);
  180. $title = null;
  181. if (is_string($columns[$column])) {
  182. $title = $columns[$column];
  183. } elseif (is_array($columns[$column]) && isset($columns[$column]['title'])) {
  184. $title = $columns[$column]['title'];
  185. }
  186. return array(
  187. 'title' => $title,
  188. );
  189. }
  190. /**
  191. * Translate a Object.RelationName.ColumnName $columnName into the value that ColumnName returns
  192. *
  193. * @param DataObject $record
  194. * @param string $columnName
  195. * @return string|null - returns null if it could not found a value
  196. */
  197. protected function getValueFromRelation($record, $columnName)
  198. {
  199. $fieldNameParts = explode('.', $columnName);
  200. $tmpItem = clone($record);
  201. for ($idx = 0; $idx < sizeof($fieldNameParts); $idx++) {
  202. $methodName = $fieldNameParts[$idx];
  203. // Last mmethod call from $columnName return what that method is returning
  204. if ($idx == sizeof($fieldNameParts) - 1) {
  205. return $tmpItem->XML_val($methodName);
  206. }
  207. // else get the object from this $methodName
  208. $tmpItem = $tmpItem->$methodName();
  209. }
  210. return null;
  211. }
  212. /**
  213. * Casts a field to a string which is safe to insert into HTML
  214. *
  215. * @param GridField $gridField
  216. * @param string $fieldName
  217. * @param string $value
  218. * @return string
  219. */
  220. protected function castValue($gridField, $fieldName, $value)
  221. {
  222. // If a fieldCasting is specified, we assume the result is safe
  223. if (array_key_exists($fieldName, $this->fieldCasting)) {
  224. $value = $gridField->getCastedValue($value, $this->fieldCasting[$fieldName]);
  225. } elseif (is_object($value)) {
  226. // If the value is an object, we do one of two things
  227. if (method_exists($value, 'Nice')) {
  228. // If it has a "Nice" method, call that & make sure the result is safe
  229. $value = Convert::raw2xml($value->Nice());
  230. } else {
  231. // Otherwise call forTemplate - the result of this should already be safe
  232. $value = $value->forTemplate();
  233. }
  234. } else {
  235. // Otherwise, just treat as a text string & make sure the result is safe
  236. $value = Convert::raw2xml($value);
  237. }
  238. return $value;
  239. }
  240. /**
  241. *
  242. * @param GridField $gridField
  243. * @param DataObject $item
  244. * @param string $fieldName
  245. * @param string $value
  246. * @return string
  247. */
  248. protected function formatValue($gridField, $item, $fieldName, $value)
  249. {
  250. if (!array_key_exists($fieldName, $this->fieldFormatting)) {
  251. return $value;
  252. }
  253. $spec = $this->fieldFormatting[$fieldName];
  254. if (!is_string($spec) && is_callable($spec)) {
  255. return $spec($value, $item);
  256. } else {
  257. $format = str_replace('$value', "__VAL__", $spec);
  258. $format = preg_replace('/\$([A-Za-z0-9-_]+)/', '$item->$1', $format);
  259. $format = str_replace('__VAL__', '$value', $format);
  260. eval('$value = "' . $format . '";');
  261. return $value;
  262. }
  263. }
  264. /**
  265. * Remove values from a value using FieldEscape setter
  266. *
  267. * @param GridField $gridField
  268. * @param string $value
  269. * @return string
  270. */
  271. protected function escapeValue($gridField, $value)
  272. {
  273. if (!$escape = $gridField->FieldEscape) {
  274. return $value;
  275. }
  276. foreach ($escape as $search => $replace) {
  277. $value = str_replace($search, $replace, $value);
  278. }
  279. return $value;
  280. }
  281. }