PageRenderTime 49ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

/metadata/MetadataInfo.php

https://gitlab.com/nitm/yii2-widgets
PHP | 320 lines | 269 code | 23 blank | 28 comment | 36 complexity | 3c65b309f9a398573ed50e1feca05edf MD5 | raw file
  1. <?php
  2. /**
  3. * @link http://www.yiiframework.com/
  4. * @copyright Copyright (c) 2008 Yii Software LLC
  5. * @license http://www.yiiframework.com/license/
  6. */
  7. namespace nitm\widgets\metadata;
  8. use nitm\helpers\Html;
  9. use yii\helpers\ArrayHelper;
  10. use kartik\icons\Icon;
  11. /**
  12. * MetInfo widget renders the address of a short link and a modal view button
  13. */
  14. class MetadataInfo extends \yii\base\Widget
  15. {
  16. public $header;
  17. public $widgetOptions = [];
  18. public $itemOptions;
  19. public $index;
  20. public $priorityOptions = [];
  21. public $options = [
  22. 'class' => 'row'
  23. ];
  24. public $items = [];
  25. /*
  26. * 'attributes' => [
  27. 'attribute', // attribute (in plain text)
  28. 'description:html', // description attribute in HTML
  29. [
  30. 'label' => 'Label',
  31. 'value' => $value,
  32. ],
  33. * ]*/
  34. public $displayAs = 'list';
  35. public $valuesOnly;
  36. public $attributes = [];
  37. public function run()
  38. {
  39. $ret_val = '';
  40. if (isset($this->header) && is_string($this->header) && !is_bool($this->header)) {
  41. $ret_val = Html::tag('h2', $this->header);
  42. }
  43. switch ($this->displayAs) {
  44. case 'grid':
  45. $this->items = is_array($this->items) ? $this->items : [$this->items];
  46. $this->widgetOptions = array_merge([
  47. 'export' => false,
  48. 'summary' => false,
  49. 'layout' => '{items}',
  50. 'showHeader' => $this->header,
  51. 'dataProvider' => new \yii\data\ArrayDataProvider(['allModels' => $this->items]),
  52. 'columns' => $this->attributes,
  53. ], $this->widgetOptions);
  54. $ret_val .= \kartik\grid\GridView::widget($this->widgetOptions);
  55. break;
  56. case 'list':
  57. $this->widgetOptions = array_merge([
  58. 'itemOptions' => [
  59. 'tag' => false
  60. ],
  61. 'summary' => false,
  62. 'dataProvider' => new \yii\data\ArrayDataProvider([
  63. 'allModels' => $this->items
  64. ]),
  65. 'itemView' => function ($model, $key, $index, $widget) {
  66. return $this->renderListItem($model, $key, $index, $widget);
  67. }
  68. ], $this->widgetOptions);
  69. $ret_val .= \yii\widgets\ListView::widget($this->widgetOptions);
  70. break;
  71. case 'csv':
  72. $ret_val = [];
  73. foreach ($this->items as $index=>$item) {
  74. $ret_val[] = $this->renderCsvItem($item, $index);
  75. }
  76. $tag = ArrayHelper::remove($this->options, 'tag', false);
  77. if ($tag) {
  78. $ret_val = Html::tag($tag, implode(', ', $ret_val), $this->options);
  79. }
  80. break;
  81. case 'tags':
  82. foreach ($this->items as $index=>$item) {
  83. $ret_val .= $this->renderTagItem($item, $index);
  84. }
  85. $tag = ArrayHelper::remove($this->options, 'tag', false);
  86. if ($tag) {
  87. $ret_val = Html::tag($tag, $ret_val, $this->options);
  88. }
  89. break;
  90. default:
  91. $this->widgetOptions['class'] = isset($this->widgetOptions['class']) ? $this->widgetOptions['class'] : 'table';
  92. $this->widgetOptions = array_merge([
  93. 'model' => $this->items,
  94. 'attributes' => $this->attributes,
  95. 'options' => [
  96. 'class' => 'table'
  97. ]
  98. ], $this->widgetOptions);
  99. $ret_val .= \yii\widgets\DetailView::widget($this->widgetOptions);
  100. break;
  101. }
  102. return $ret_val;
  103. }
  104. public function renderCsvItem($model, $index)
  105. {
  106. $ret_val = '';
  107. $counter = $index+1;
  108. foreach ($this->attributes as $k=>$v) {
  109. list($title, $value, $priority, $options) = $this->getParts($model, $k, $v, $counter);
  110. ob_start();
  111. $tag = ArrayHelper::remove($options, 'tag', 'span');
  112. if (isset($priority) && !is_null($priority)) {
  113. echo $priority.' - ';
  114. }
  115. echo ucfirst($title).':&nbsp;'.$value;
  116. $item = ob_get_contents();
  117. ob_end_clean();
  118. $ret_val .= $item;
  119. }
  120. return $ret_val;
  121. }
  122. public function renderTagItem($model, $index)
  123. {
  124. $ret_val = '';
  125. $counter = $index+1;
  126. foreach ($this->attributes as $k=>$v) {
  127. list($title, $value, $priority, $options) = $this->getParts($model, $k, $v, $counter);
  128. ob_start();
  129. $tag = ArrayHelper::remove($options, 'tag', 'span');
  130. $before = ArrayHelper::remove($options, 'before', null);
  131. $after = ArrayHelper::remove($options, 'after', null);
  132. echo Html::beginTag($tag, $options);
  133. if (is_string($before)) {
  134. echo $before;
  135. }
  136. if (isset($priority) && !is_null($priority)) {
  137. echo Html::tag('strong', $priority).' - &nbsp;';
  138. }
  139. if (!$this->valuesOnly) {
  140. echo Html::tag('strong', ucfirst($title)).':&nbsp;';
  141. }
  142. echo Html::tag('em', $value);
  143. if (is_string($after)) {
  144. echo "&nbsp;".$after;
  145. }
  146. echo "</$tag>";
  147. $item = ob_get_contents();
  148. ob_end_clean();
  149. $ret_val .= $item;
  150. }
  151. return $ret_val;
  152. }
  153. public function renderListItem($model, $key, $index, $widget)
  154. {
  155. $ret_val = '';
  156. $counter = $index+1;
  157. foreach ($this->attributes as $k=>$v) {
  158. list($title, $value, $priority, $options) = $this->getParts($model, $k, $v, $counter);
  159. ob_start();
  160. $tag = ArrayHelper::remove($options, 'tag', 'a');
  161. echo "<$tag ".Html::renderTagAttributes($options).">";
  162. if (isset($priority) && !is_null($priority)) {
  163. echo Html::tag('div',
  164. Html::tag(ArrayHelper::getValue($this->priorityOptions, 'tag', 'h2'), $priority, [
  165. 'style' => 'line-height: '.($this->valuesOnly ? '.5' : '1.25').'; display: table-cell; vertical-align: middle;'
  166. ]),
  167. ['style' => 'float: left; min-width: 40px']
  168. );
  169. }
  170. echo Html::tag('div',
  171. (!$this->valuesOnly ? Html::tag('h4', ucfirst($title), ['class' => 'list-group-item-heading']) : '').
  172. Html::tag('p', $value, ['class' => 'list-group-item-text']),
  173. ['style' => isset($priority) ? 'margin-left: 40px; right: 15px' : 'right: 15px']
  174. );
  175. echo "</$tag>";
  176. $item = ob_get_contents();
  177. ob_end_clean();
  178. $ret_val .= $item;
  179. }
  180. return $ret_val;
  181. }
  182. /**
  183. * [getParts description]
  184. * @param model $model [description]
  185. * @param mixed $k [description]
  186. * @param mixed $v [description]
  187. * @param int $counter [description]
  188. * @return [type] [description]
  189. */
  190. private function getParts($model, $k, $v, $counter)
  191. {
  192. $value = is_string($k) ? $v : null;
  193. $attr = is_string($k) ? $k : $v;
  194. /**
  195. * Doing it this way to avoid including a href attribute in anchor
  196. */
  197. switch (is_callable($this->itemOptions)) {
  198. case true:
  199. $func = $this->itemOptions;
  200. $options = $this->getItemOptions($model, $func($model));
  201. break;
  202. default:
  203. $options = $this->getItemOptions($model);
  204. break;
  205. }
  206. $attrGetter = function ($model, $parts, $value, $valueIsPart) {
  207. $ret_val = '';
  208. switch (1) {
  209. case sizeof($parts) >= 1:
  210. if (is_array($model)) {
  211. $ret_val = ArrayHelper::getValue($model, implode('.', $parts), '(not found)');
  212. } elseif (is_object($model)) {
  213. foreach ($parts as $prop) {
  214. if (is_object($model) && $model->hasAttribute($prop) || $model->isRelationPopulated($prop)) {
  215. $model = ArrayHelper::getValue($model, $prop);
  216. } elseif (is_object($model) && method_exists($model, $prop)) {
  217. $obj = call_user_func([$model, $prop]);
  218. if (is_object($obj) || is_array($object)) {
  219. $model = $obj;
  220. } else {
  221. $ret_val = $obj;
  222. break;
  223. }
  224. } else {
  225. $ret_val = ArrayHelper::getValue($model, $prop, $model);
  226. }
  227. }
  228. $ret_val = $model;
  229. }
  230. break;
  231. default:
  232. switch (1) {
  233. case is_callable($value):
  234. $ret_val = $value($model);
  235. break;
  236. case !is_null($value):
  237. $ret_val = $value;
  238. break;
  239. default:
  240. if (method_exists($model, $parts[0])) {
  241. $ret_val = call_user_func([$model, $parts[0]]);
  242. } elseif (property_exists($model, $parts[0])) {
  243. $ret_val = $model->{$parts[0]};
  244. } else {
  245. $ret_val = $parts[0];
  246. }
  247. break;
  248. }
  249. break;
  250. }
  251. return $ret_val;
  252. };
  253. $attr = is_array($attr) ? $attr : explode(':', $attr);
  254. $titleAttr = array_shift($attr);
  255. $valueAttr = count($attr) ? array_pop($attr) : $titleAttr;
  256. $title = $attrGetter($model, explode('.', $titleAttr), $value, (strpos(':', $titleAttr) === false));
  257. if (is_callable($valueAttr)) {
  258. $value = $valueAttr($model);
  259. } else {
  260. $value = strlen($valueAttr) ? $attrGetter($model, explode('.', $valueAttr), $value, false) : null;
  261. }
  262. if ($this->index) {
  263. $priority = ($this->index===true) ? $counter : $model->getAttribute($this->index);
  264. $priority = $priority==0 ? $counter : $priority;
  265. } else {
  266. $priority = null;
  267. }
  268. return [$title, $value, $priority, $options];
  269. }
  270. private function getItemOptions($model, $options=[])
  271. {
  272. if (is_a($model, \nitm\models\Data::className())) {
  273. $unique = $model->isWhat().$model->getId();
  274. } else {
  275. $unique = uniqid();
  276. }
  277. switch ($this->displayAs) {
  278. case 'list':
  279. $defaultOptions = [
  280. 'class' => 'list-group-item list-group-item-default',
  281. 'id' => $unique
  282. ];
  283. break;
  284. case 'tags':
  285. $defaultOptions = [
  286. 'tag' => 'a',
  287. 'style' => 'border: solid thin #ccc; padding: 5px; margin: 5px 5px 0 0; text-decoration: none; border-radius: 6px; display: inline-block',
  288. 'id' => $unique
  289. ];
  290. break;
  291. default:
  292. $defaultOptions = [];
  293. break;
  294. }
  295. return array_merge($defaultOptions, $options);
  296. }
  297. }