├── .gitignore
├── README.md
├── TreeColumn.php
├── TreeGrid.php
├── TreeGridAsset.php
├── composer.json
└── composer.lock
/.gitignore:
--------------------------------------------------------------------------------
1 | # phpstorm project files
2 | .idea
3 |
4 | # netbeans project files
5 | nbproject
6 |
7 | # zend studio for eclipse project files
8 | .buildpath
9 | .project
10 | .settings
11 |
12 | # windows thumbnail cache
13 | Thumbs.db
14 |
15 | # composer vendor dir
16 | /vendor
17 |
18 | # composer itself is not needed
19 | composer.phar
20 |
21 | # Mac DS_Store Files
22 | .DS_Store
23 |
24 | # phpunit itself is not needed
25 | phpunit.phar
26 | # local phpunit config
27 | /phpunit.xml
28 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # jQuery TreeGrid Extension for Yii 2
2 |
3 | This is the [jQuery TreeGrid](https://github.com/maxazan/jquery-treegrid) extension for Yii 2. It encapsulates TreeGrid component in terms of Yii widgets,
4 | and thus makes using TreeGrid component in Yii applications extremely easy
5 |
6 | [](http://www.yiiframework.com/)
7 | [](https://packagist.org/packages/leandrogehlen/yii2-treegrid)
8 | [](https://packagist.org/packages/leandrogehlen/yii2-treegrid)
9 |
10 | ## Installation
11 |
12 | The preferred way to install this extension is through [composer](http://getcomposer.org/download/).
13 |
14 | Either run
15 |
16 | ```
17 | php composer.phar require --prefer-dist leandrogehlen/yii2-treegrid "*"
18 | ```
19 |
20 | or add
21 |
22 | ```
23 | "leandrogehlen/yii2-treegrid": "*"
24 | ```
25 |
26 | to the require section of your `composer.json` file.
27 |
28 | ## Usage
29 |
30 | **Model**
31 |
32 | ```php
33 |
34 | use yii\db\ActiveRecord;
35 |
36 | /**
37 | * @property string $description
38 | * @property integer $parent_id
39 | */
40 | class Tree extends ActiveRecord
41 | {
42 |
43 | /**
44 | * @inheritdoc
45 | */
46 | public static function tableName()
47 | {
48 | return 'tree';
49 | }
50 |
51 | /**
52 | * @inheritdoc
53 | */
54 | public function rules()
55 | {
56 | return [
57 | [['description'], 'required'],
58 | [['description'], 'string'],
59 | [['parent_id'], 'integer']
60 | ];
61 | }
62 | }
63 | ```
64 |
65 | **Controller**
66 |
67 | ```php
68 | use yii\web\Controller;
69 | use Yii;
70 | use yii\data\ActiveDataProvider;
71 |
72 | class TreeController extends Controller
73 | {
74 |
75 | /**
76 | * Lists all Tree models.
77 | * @return mixed
78 | */
79 | public function actionIndex()
80 | {
81 | $query = Tree::find();
82 | $dataProvider = new ActiveDataProvider([
83 | 'query' => $query,
84 | 'pagination' => false
85 | ]);
86 |
87 | return $this->render('index', [
88 | 'dataProvider' => $dataProvider
89 | ]);
90 | }
91 | ```
92 |
93 | **View**
94 |
95 | ```php
96 | use leandrogehlen\treegrid\TreeGrid;
97 |
98 | = TreeGrid::widget([
99 | 'dataProvider' => $dataProvider,
100 | 'keyColumnName' => 'id',
101 | 'parentColumnName' => 'parent_id',
102 | 'parentRootValue' => '0', //first parentId value
103 | 'pluginOptions' => [
104 | 'initialState' => 'collapsed',
105 | ],
106 | 'columns' => [
107 | 'name',
108 | 'id',
109 | 'parent_id',
110 | ['class' => 'yii\grid\ActionColumn']
111 | ]
112 | ]); ?>
113 | ```
114 |
115 | ## Adding resources
116 |
117 | When is necessary to add other resource files, then should be used the [Dependency Injection](http://www.yiiframework.com/doc-2.0/guide-concept-di-container.html#registering-dependencies) concept.
118 |
119 | To use the `saveState` option it's necessary to add `jquery.cookie.js`.
120 |
121 | ```php
122 | //config/web.php
123 |
124 | $config = [
125 | 'id' => 'my-app',
126 | 'components' => [
127 | ...
128 | ]
129 | ...
130 | ]
131 |
132 | Yii::$container->set('leandrogehlen\treegrid\TreeGridAsset',[
133 | 'js' => [
134 | 'js/jquery.cookie.js',
135 | 'js/jquery.treegrid.min.js',
136 | ]
137 | ]);
138 |
139 | return $config;
140 | ```
141 |
142 |
143 |
144 |
--------------------------------------------------------------------------------
/TreeColumn.php:
--------------------------------------------------------------------------------
1 |
19 | */
20 | class TreeColumn extends BaseObject
21 | {
22 | /**
23 | * @var TreeGrid the grid view object that owns this column.
24 | */
25 | public $grid;
26 |
27 | /**
28 | * @var string the header cell content. Note that it will not be HTML-encoded.
29 | */
30 | public $header;
31 |
32 | /**
33 | * @var string the footer cell content. Note that it will not be HTML-encoded.
34 | */
35 | public $footer;
36 |
37 | /**
38 | * @var callable This is a callable that will be used to generate the content of each cell.
39 | * The signature of the function should be the following: `function ($model, $key, $index, $column)`.
40 | * Where `$model`, `$key`, and `$index` refer to the model, key and index of the row currently being rendered
41 | * and `$column` is a reference to the [[TreeColumn]] object.
42 | */
43 | public $content;
44 |
45 | /**
46 | * @var bool whether this column is visible. Defaults to true.
47 | */
48 | public $visible = true;
49 |
50 | /**
51 | * @var array the HTML attributes for the column group tag.
52 | * @see \yii\helpers\Html::renderTagAttributes() for details on how attributes are being rendered.
53 | */
54 | public $options = [];
55 |
56 | /**
57 | * @var array the HTML attributes for the header cell tag.
58 | * @see \yii\helpers\Html::renderTagAttributes() for details on how attributes are being rendered.
59 | */
60 | public $headerOptions = [];
61 |
62 | /**
63 | * @var array|\Closure the HTML attributes for the data cell tag. This can either be an array of
64 | * attributes or an anonymous function ([[Closure]]) that returns such an array.
65 | * The signature of the function should be the following: `function ($model, $key, $index, $column)`.
66 | * Where `$model`, `$key`, and `$index` refer to the model, key and index of the row currently being rendered
67 | * and `$column` is a reference to the [[Column]] object.
68 | * A function may be used to assign different attributes to different rows based on the data in that row.
69 | *
70 | * @see \yii\helpers\Html::renderTagAttributes() for details on how attributes are being rendered.
71 | */
72 | public $contentOptions = [];
73 |
74 | /**
75 | * @var array the HTML attributes for the footer cell tag.
76 | * @see \yii\helpers\Html::renderTagAttributes() for details on how attributes are being rendered.
77 | */
78 | public $footerOptions = [];
79 |
80 | /**
81 | * @var string the attribute name associated with this column. When neither [[content]] nor [[value]]
82 | * is specified, the value of the specified attribute will be retrieved from each data model and displayed.
83 | *
84 | * Also, if [[label]] is not specified, the label associated with the attribute will be displayed.
85 | */
86 | public $attribute;
87 |
88 | /**
89 | * @var string label to be displayed in the [[header|header cell]] and also to be used as the sorting
90 | * link label when sorting is enabled for this column.
91 | * If it is not set and the models provided by the GridViews data provider are instances
92 | * of [[\yii\db\ActiveRecord]], the label will be determined using [[\yii\db\ActiveRecord::getAttributeLabel()]].
93 | * Otherwise [[\yii\helpers\Inflector::camel2words()]] will be used to get a label.
94 | */
95 | public $label;
96 |
97 | /**
98 | * @var bool whether the header label should be HTML-encoded.
99 | * @see label
100 | */
101 | public $encodeLabel = true;
102 |
103 | /**
104 | * @var string|\Closure an anonymous function or a string that is used to determine the value to display in the current column.
105 | *
106 | * If this is an anonymous function, it will be called for each row and the return value will be used as the value to
107 | * display for every data model. The signature of this function should be: `function ($model, $key, $index, $column)`.
108 | * Where `$model`, `$key`, and `$index` refer to the model, key and index of the row currently being rendered
109 | * and `$column` is a reference to the [[DataColumn]] object.
110 | *
111 | * You may also set this property to a string representing the attribute name to be displayed in this column.
112 | * This can be used when the attribute to be displayed is different from the [[attribute]] that is used for
113 | * sorting and filtering.
114 | *
115 | * If this is not set, `$model[$attribute]` will be used to obtain the value, where `$attribute` is the value of [[attribute]].
116 | */
117 | public $value;
118 |
119 | /**
120 | * @var string|array in which format should the value of each data model be displayed as (e.g. `"raw"`, `"text"`, `"html"`,
121 | * `['date', 'php:Y-m-d']`). Supported formats are determined by the [[GridView::formatter|formatter]] used by
122 | * the [[GridView]]. Default format is "text" which will format the value as an HTML-encoded plain text when
123 | * [[\yii\i18n\Formatter]] is used as the [[GridView::$formatter|formatter]] of the GridView.
124 | */
125 | public $format = 'text';
126 |
127 | /**
128 | * Renders the header cell.
129 | */
130 | public function renderHeaderCell()
131 | {
132 | return Html::tag('th', $this->renderHeaderCellContent(), $this->headerOptions);
133 | }
134 |
135 | /**
136 | * Renders the footer cell.
137 | */
138 | public function renderFooterCell()
139 | {
140 | return Html::tag('td', $this->renderFooterCellContent(), $this->footerOptions);
141 | }
142 |
143 | /**
144 | * Renders a data cell.
145 | * @param mixed $model the data model being rendered
146 | * @param mixed $key the key associated with the data model
147 | * @param int $index the zero-based index of the data item among the item array returned by [[GridView::dataProvider]].
148 | * @return string the rendering result
149 | */
150 | public function renderDataCell($model, $key, $index)
151 | {
152 | if ($this->contentOptions instanceof Closure) {
153 | $options = call_user_func($this->contentOptions, $model, $key, $index, $this);
154 | } else {
155 | $options = $this->contentOptions;
156 | }
157 | return Html::tag('td', $this->renderDataCellContent($model, $key, $index), $options);
158 | }
159 |
160 | /**
161 | * Renders the header cell content.
162 | * The default implementation simply renders [[header]].
163 | * This method may be overridden to customize the rendering of the header cell.
164 | * @return string the rendering result
165 | */
166 | protected function renderHeaderCellContent()
167 | {
168 | if ($this->header !== null || $this->label === null && $this->attribute === null) {
169 | return trim($this->header) !== '' ? $this->header : $this->grid->emptyCell;
170 | }
171 |
172 | $provider = $this->grid->dataProvider;
173 |
174 | if ($this->label === null) {
175 | if ($provider instanceof ActiveDataProvider && $provider->query instanceof ActiveQueryInterface) {
176 | /* @var $model Model */
177 | $model = new $provider->query->modelClass;
178 | $label = $model->getAttributeLabel($this->attribute);
179 | } else {
180 | $models = $provider->getModels();
181 | if (($model = reset($models)) instanceof Model) {
182 | /* @var $model Model */
183 | $label = $model->getAttributeLabel($this->attribute);
184 | } else {
185 | $label = Inflector::camel2words($this->attribute);
186 | }
187 | }
188 | } else {
189 | $label = $this->label;
190 | }
191 |
192 | return $this->encodeLabel ? Html::encode($label) : $label;
193 | }
194 |
195 | /**
196 | * Renders the footer cell content.
197 | * The default implementation simply renders [[footer]].
198 | * This method may be overridden to customize the rendering of the footer cell.
199 | * @return string the rendering result
200 | */
201 | protected function renderFooterCellContent()
202 | {
203 | return trim($this->footer) !== '' ? $this->footer : $this->grid->emptyCell;
204 | }
205 |
206 | /**
207 | * Renders the data cell content.
208 | * @param mixed $model the data model
209 | * @param mixed $key the key associated with the data model
210 | * @param int $index the zero-based index of the data model among the models array returned by [[GridView::dataProvider]].
211 | * @return string the rendering result
212 | */
213 | protected function renderDataCellContent($model, $key, $index)
214 | {
215 | if ($this->content === null) {
216 | return $this->grid->formatter->format($this->getDataCellValue($model, $key, $index), $this->format);
217 | } else {
218 | if ($this->content !== null) {
219 | return call_user_func($this->content, $model, $key, $index, $this);
220 | } else {
221 | return $this->grid->emptyCell;
222 | }
223 | }
224 | }
225 |
226 | /**
227 | * Returns the data cell value.
228 | * @param mixed $model the data model
229 | * @param mixed $key the key associated with the data model
230 | * @param int $index the zero-based index of the data model among the models array returned by [[GridView::dataProvider]].
231 | * @return string the data cell value
232 | */
233 | public function getDataCellValue($model, $key, $index)
234 | {
235 | if ($this->value !== null) {
236 | if (is_string($this->value)) {
237 | return ArrayHelper::getValue($model, $this->value);
238 | } else {
239 | return call_user_func($this->value, $model, $key, $index, $this);
240 | }
241 | } elseif ($this->attribute !== null) {
242 | return ArrayHelper::getValue($model, $this->attribute);
243 | }
244 | return null;
245 | }
246 | }
247 |
--------------------------------------------------------------------------------
/TreeGrid.php:
--------------------------------------------------------------------------------
1 |
21 | */
22 | class TreeGrid extends Widget
23 | {
24 | /**
25 | * @var \yii\data\DataProviderInterface|\yii\data\BaseDataProvider the data provider for the view. This property is required.
26 | */
27 | public $dataProvider;
28 |
29 | /**
30 | * @var string the default data column class if the class name is not explicitly specified when configuring a data column.
31 | * Defaults to 'leandrogehlen\treegrid\TreeColumn'.
32 | */
33 | public $dataColumnClass;
34 |
35 | /**
36 | * @var array the HTML attributes for the container tag of the grid view.
37 | * @see \yii\helpers\Html::renderTagAttributes() for details on how attributes are being rendered.
38 | */
39 | public $options = ['class' => 'table table-striped table-bordered'];
40 |
41 | /**
42 | * @var array The plugin options
43 | */
44 | public $pluginOptions = [];
45 |
46 | /**
47 | * @var array the HTML attributes for the table header row.
48 | * @see \yii\helpers\Html::renderTagAttributes() for details on how attributes are being rendered.
49 | */
50 | public $headerRowOptions = [];
51 | /**
52 | * @var array the HTML attributes for the table footer row.
53 | * @see \yii\helpers\Html::renderTagAttributes() for details on how attributes are being rendered.
54 | */
55 | public $footerRowOptions = [];
56 |
57 | /**
58 | * @var string the HTML display when the content of a cell is empty
59 | */
60 | public $emptyCell = ' ';
61 |
62 | /**
63 | * @var string the HTML content to be displayed when [[dataProvider]] does not have any data.
64 | */
65 | public $emptyText;
66 |
67 | /**
68 | * @var array the HTML attributes for the emptyText of the list view.
69 | * The "tag" element specifies the tag name of the emptyText element and defaults to "div".
70 | * @see \yii\helpers\Html::renderTagAttributes() for details on how attributes are being rendered.
71 | */
72 | public $emptyTextOptions = ['class' => 'empty'];
73 |
74 | /**
75 | * @var bool whether to show the header section of the grid table.
76 | */
77 | public $showHeader = true;
78 | /**
79 | * @var bool whether to show the footer section of the grid table.
80 | */
81 | public $showFooter = false;
82 | /**
83 | * @var bool whether to show the grid view if [[dataProvider]] returns no data.
84 | */
85 | public $showOnEmpty = true;
86 |
87 | /**
88 | * @var array|Formatter the formatter used to format model attribute values into displayable texts.
89 | * This can be either an instance of [[Formatter]] or an configuration array for creating the [[Formatter]]
90 | * instance. If this property is not set, the "formatter" application component will be used.
91 | */
92 | public $formatter;
93 |
94 | /**
95 | * @var array|Closure the HTML attributes for the table body rows. This can be either an array
96 | * specifying the common HTML attributes for all body rows, or an anonymous function that
97 | * returns an array of the HTML attributes. The anonymous function will be called once for every
98 | * data model returned by [[dataProvider]]. It should have the following signature:
99 | *
100 | * ```php
101 | * function ($model, $key, $index, $grid)
102 | * ```
103 | *
104 | * - `$model`: the current data model being rendered
105 | * - `$key`: the key value associated with the current data model
106 | * - `$index`: the zero-based index of the data model in the model array returned by [[dataProvider]]
107 | * - `$grid`: the GridView object
108 | *
109 | * @see \yii\helpers\Html::renderTagAttributes() for details on how attributes are being rendered.
110 | */
111 | public $rowOptions = [];
112 |
113 | /**
114 | * @var Closure an anonymous function that is called once BEFORE rendering each data model.
115 | * It should have the similar signature as [[rowOptions]]. The return result of the function
116 | * will be rendered directly.
117 | */
118 | public $beforeRow;
119 |
120 | /**
121 | * @var Closure an anonymous function that is called once AFTER rendering each data model.
122 | * It should have the similar signature as [[rowOptions]]. The return result of the function
123 | * will be rendered directly.
124 | */
125 | public $afterRow;
126 |
127 | /**
128 | * @var string name of key column used to build tree
129 | */
130 | public $keyColumnName;
131 |
132 | /**
133 | * @var string name of parent column used to build tree
134 | */
135 | public $parentColumnName;
136 |
137 | /**
138 | * @var mixed parent column value of root elements from data
139 | */
140 | public $parentRootValue = null;
141 |
142 | /**
143 | * @var array grid column configuration. Each array element represents the configuration
144 | * for one particular grid column.
145 | * @see \yii\grid::$columns for details.
146 | */
147 | public $columns = [];
148 | /**
149 | * Initializes the grid view.
150 | * This method will initialize required property values and instantiate [[columns]] objects.
151 | */
152 | public function init()
153 | {
154 | if ($this->dataProvider === null) {
155 | throw new InvalidConfigException('The "dataProvider" property must be set.');
156 | }
157 | if ($this->emptyText === null) {
158 | $this->emptyText = Yii::t('yii', 'No results found.');
159 | }
160 | if (!isset($this->options['id'])) {
161 | $this->options['id'] = $this->getId();
162 | }
163 |
164 | if ($this->formatter == null) {
165 | $this->formatter = Yii::$app->getFormatter();
166 | } elseif (is_array($this->formatter)) {
167 | $this->formatter = Yii::createObject($this->formatter);
168 | }
169 | if (!$this->formatter instanceof Formatter) {
170 | throw new InvalidConfigException('The "formatter" property must be either a Format object or a configuration array.');
171 | }
172 |
173 | if (!$this->keyColumnName) {
174 | throw new InvalidConfigException('The "keyColumnName" property must be specified"');
175 | }
176 | if (!$this->parentColumnName) {
177 | throw new InvalidConfigException('The "parentColumnName" property must be specified"');
178 | }
179 |
180 | $this->initColumns();
181 | }
182 |
183 | /**
184 | * Runs the widget.
185 | */
186 | public function run()
187 | {
188 | $id = $this->options['id'];
189 | $options = Json::htmlEncode($this->pluginOptions);
190 |
191 | $view = $this->getView();
192 | TreeGridAsset::register($view);
193 |
194 | $view->registerJs("jQuery('#$id').treegrid($options);");
195 |
196 | if ($this->showOnEmpty || $this->dataProvider->getCount() > 0) {
197 | $header = $this->showHeader ? $this->renderTableHeader() : false;
198 | $body = $this->renderItems();
199 | $footer = $this->showFooter ? $this->renderTableFooter() : false;
200 |
201 | $content = array_filter([
202 | $header,
203 | $body,
204 | $footer
205 | ]);
206 |
207 | return Html::tag('table', implode("\n", $content), $this->options);
208 | } else {
209 | return $this->renderEmpty();
210 | }
211 | }
212 |
213 | /**
214 | * Renders the HTML content indicating that the list view has no data.
215 | * @return string the rendering result
216 | * @see emptyText
217 | */
218 | public function renderEmpty()
219 | {
220 | $options = $this->emptyTextOptions;
221 | $tag = ArrayHelper::remove($options, 'tag', 'div');
222 | return Html::tag($tag, ($this->emptyText === null ? Yii::t('yii', 'No results found.') : $this->emptyText), $options);
223 | }
224 |
225 | /**
226 | * Renders a table row with the given data model and key.
227 | * @param mixed $model the data model to be rendered
228 | * @param mixed $key the key associated with the data model
229 | * @param integer $index the zero-based index of the data model among the model array returned by [[dataProvider]].
230 | * @return string the rendering result
231 | */
232 | public function renderTableRow($model, $key, $index)
233 | {
234 | $cells = [];
235 | /* @var $column TreeColumn */
236 | foreach ($this->columns as $column) {
237 | $cells[] = $column->renderDataCell($model, $key, $index);
238 | }
239 | if ($this->rowOptions instanceof Closure) {
240 | $options = call_user_func($this->rowOptions, $model, $key, $index, $this);
241 | } else {
242 | $options = $this->rowOptions;
243 | }
244 | $options['data-key'] = is_array($key) ? json_encode($key) : (string) $key;
245 |
246 | $id = ArrayHelper::getValue($model, $this->keyColumnName);
247 | Html::addCssClass($options, "treegrid-$id");
248 |
249 | $parentId = ArrayHelper::getValue($model, $this->parentColumnName);
250 | if ($parentId) {
251 | if(ArrayHelper::getValue($this->pluginOptions, 'initialState') == 'collapsed'){
252 | Html::addCssStyle($options, 'display: none;');
253 | }
254 | Html::addCssClass($options, "treegrid-parent-$parentId");
255 | }
256 |
257 | return Html::tag('tr', implode('', $cells), $options);
258 | }
259 |
260 | /**
261 | * Renders the table header.
262 | * @return string the rendering result.
263 | */
264 | public function renderTableHeader()
265 | {
266 | $cells = [];
267 | foreach ($this->columns as $column) {
268 | /* @var $column TreeColumn */
269 | $cells[] = $column->renderHeaderCell();
270 | }
271 | $content = Html::tag('tr', implode('', $cells), $this->headerRowOptions);
272 | return "\n" . $content . "\n";
273 | }
274 |
275 | /**
276 | * Renders the table footer.
277 | * @return string the rendering result.
278 | */
279 | public function renderTableFooter()
280 | {
281 | $cells = [];
282 | foreach ($this->columns as $column) {
283 | /* @var $column TreeColumn */
284 | $cells[] = $column->renderFooterCell();
285 | }
286 | $content = Html::tag('tr', implode('', $cells), $this->footerRowOptions);
287 | return "
\n" . $content . "\n";
288 | }
289 |
290 | /**
291 | * Renders the data models for the grid view.
292 | */
293 | public function renderItems()
294 | {
295 | $rows = [];
296 | $this->dataProvider->setKeys([]);
297 | $models = array_values($this->dataProvider->getModels());
298 | $models = $this->normalizeData($models, $this->parentRootValue);
299 | $this->dataProvider->setModels($models);
300 | $this->dataProvider->setKeys(null);
301 | $this->dataProvider->prepare();
302 | $keys = $this->dataProvider->getKeys();
303 | foreach ($models as $index => $model) {
304 | $key = $keys[$index];
305 | if ($this->beforeRow !== null) {
306 | $row = call_user_func($this->beforeRow, $model, $key, $index, $this);
307 | if (!empty($row)) {
308 | $rows[] = $row;
309 | }
310 | }
311 |
312 | $rows[] = $this->renderTableRow($model, $key, $index);
313 |
314 | if ($this->afterRow !== null) {
315 | $row = call_user_func($this->afterRow, $model, $key, $index, $this);
316 | if (!empty($row)) {
317 | $rows[] = $row;
318 | }
319 | }
320 | }
321 |
322 | if (empty($rows)) {
323 | $colspan = count($this->columns);
324 | return "" . $this->renderEmpty() . " |
";
325 | } else {
326 | return implode("\n", $rows);
327 | }
328 | }
329 |
330 | /**
331 | * Creates column objects and initializes them.
332 | */
333 | protected function initColumns()
334 | {
335 | if (empty($this->columns)) {
336 | $this->guessColumns();
337 | }
338 | foreach ($this->columns as $i => $column) {
339 | if (is_string($column)) {
340 | $column = $this->createDataColumn($column);
341 | } else {
342 | $column = Yii::createObject(array_merge([
343 | 'class' => $this->dataColumnClass ? : TreeColumn::className(),
344 | 'grid' => $this,
345 | ], $column));
346 | }
347 | if (!$column->visible) {
348 | unset($this->columns[$i]);
349 | continue;
350 | }
351 | $this->columns[$i] = $column;
352 | }
353 | }
354 |
355 | /**
356 | * Creates a [[DataColumn]] object based on a string in the format of "attribute:format:label".
357 | * @param string $text the column specification string
358 | * @return DataColumn the column instance
359 | * @throws InvalidConfigException if the column specification is invalid
360 | */
361 | protected function createDataColumn($text)
362 | {
363 | if (!preg_match('/^([^:]+)(:(\w*))?(:(.*))?$/', $text, $matches)) {
364 | throw new InvalidConfigException('The column must be specified in the format of "attribute", "attribute:format" or "attribute:format:label"');
365 | }
366 |
367 | return Yii::createObject([
368 | 'class' => $this->dataColumnClass ? : TreeColumn::className(),
369 | 'grid' => $this,
370 | 'attribute' => $matches[1],
371 | 'format' => isset($matches[3]) ? $matches[3] : 'text',
372 | 'label' => isset($matches[5]) ? $matches[5] : null,
373 | ]);
374 | }
375 |
376 | /**
377 | * This function tries to guess the columns to show from the given data
378 | * if [[columns]] are not explicitly specified.
379 | */
380 | protected function guessColumns()
381 | {
382 | $models = $this->dataProvider->getModels();
383 | $model = reset($models);
384 | if (is_array($model) || is_object($model)) {
385 | foreach ($model as $name => $value) {
386 | $this->columns[] = $name;
387 | }
388 | }
389 | }
390 |
391 | /**
392 | * Normalize tree data
393 | * @param array $data
394 | * @param string $parentId
395 | * @return array
396 | */
397 | protected function normalizeData(array $data, $parentId = null) {
398 | $result = [];
399 | foreach ($data as $element) {
400 | if (ArrayHelper::getValue($element, $this->parentColumnName) == $parentId) {
401 | $result[] = $element;
402 | $children = $this->normalizeData($data, ArrayHelper::getValue($element, $this->keyColumnName));
403 | if ($children) {
404 | $result = array_merge($result, $children);
405 | }
406 | }
407 | }
408 | return $result;
409 | }
410 | }
411 |
--------------------------------------------------------------------------------
/TreeGridAsset.php:
--------------------------------------------------------------------------------
1 |
11 | */
12 | class TreeGridAsset extends AssetBundle {
13 |
14 | public $sourcePath = '@bower/jquery-treegrid';
15 |
16 | public $js = [
17 | 'js/jquery.treegrid.min.js',
18 | ];
19 |
20 | public $css = [
21 | 'css/jquery.treegrid.css',
22 | ];
23 |
24 | public $depends = [
25 | 'yii\web\JqueryAsset'
26 | ];
27 |
28 | }
--------------------------------------------------------------------------------
/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "leandrogehlen/yii2-treegrid",
3 | "description": "Extension for Yii2 Framework to work with jQuery TreeGrid",
4 | "keywords": ["yii2", "tree", "treeview", "treegrid", "interface"],
5 | "type": "yii2-extension",
6 | "license": "BSD-3-Clause",
7 | "support": {
8 | "issues": "https://github.com/leandrogehlen/yii2-treegrid/issues",
9 | "source": "https://github.com/leandrogehlen/yii2-treegrid"
10 | },
11 | "authors": [
12 | {
13 | "name": "Leandro Guindani Gehlen",
14 | "email": "leandrogehlen@gmail.com"
15 | }
16 | ],
17 | "require": {
18 | "yiisoft/yii2": "~2.0.13",
19 | "bower-asset/jquery-treegrid": "0.3.0"
20 | },
21 | "require-dev": {
22 | "phpunit/phpunit": "3.7.*"
23 | },
24 | "autoload": {
25 | "psr-4": { "leandrogehlen\\treegrid\\": "" }
26 | },
27 | "extra": {
28 | "branch-alias": {
29 | "dev-master": "1.0.x-dev"
30 | }
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/composer.lock:
--------------------------------------------------------------------------------
1 | {
2 | "_readme": [
3 | "This file locks the dependencies of your project to a known state",
4 | "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
5 | "This file is @generated automatically"
6 | ],
7 | "content-hash": "7ff1235f9821ce2739dc8cd9299a4773",
8 | "packages": [
9 | {
10 | "name": "bower-asset/inputmask",
11 | "version": "3.3.11",
12 | "source": {
13 | "type": "git",
14 | "url": "https://github.com/RobinHerbots/Inputmask.git",
15 | "reference": "5e670ad62f50c738388d4dcec78d2888505ad77b"
16 | },
17 | "dist": {
18 | "type": "zip",
19 | "url": "https://api.github.com/repos/RobinHerbots/Inputmask/zipball/5e670ad62f50c738388d4dcec78d2888505ad77b",
20 | "reference": "5e670ad62f50c738388d4dcec78d2888505ad77b",
21 | "shasum": ""
22 | },
23 | "require": {
24 | "bower-asset/jquery": ">=1.7"
25 | },
26 | "type": "bower-asset-library",
27 | "extra": {
28 | "bower-asset-main": [
29 | "./dist/inputmask/inputmask.js",
30 | "./dist/inputmask/inputmask.extensions.js",
31 | "./dist/inputmask/inputmask.date.extensions.js",
32 | "./dist/inputmask/inputmask.numeric.extensions.js",
33 | "./dist/inputmask/inputmask.phone.extensions.js",
34 | "./dist/inputmask/jquery.inputmask.js",
35 | "./dist/inputmask/global/document.js",
36 | "./dist/inputmask/global/window.js",
37 | "./dist/inputmask/phone-codes/phone.js",
38 | "./dist/inputmask/phone-codes/phone-be.js",
39 | "./dist/inputmask/phone-codes/phone-nl.js",
40 | "./dist/inputmask/phone-codes/phone-ru.js",
41 | "./dist/inputmask/phone-codes/phone-uk.js",
42 | "./dist/inputmask/dependencyLibs/inputmask.dependencyLib.jqlite.js",
43 | "./dist/inputmask/dependencyLibs/inputmask.dependencyLib.jquery.js",
44 | "./dist/inputmask/dependencyLibs/inputmask.dependencyLib.js",
45 | "./dist/inputmask/bindings/inputmask.binding.js"
46 | ],
47 | "bower-asset-ignore": [
48 | "**/*",
49 | "!dist/*",
50 | "!dist/inputmask/*",
51 | "!dist/min/*",
52 | "!dist/min/inputmask/*"
53 | ]
54 | },
55 | "license": [
56 | "http://opensource.org/licenses/mit-license.php"
57 | ],
58 | "description": "Inputmask is a javascript library which creates an input mask. Inputmask can run against vanilla javascript, jQuery and jqlite.",
59 | "keywords": [
60 | "form",
61 | "input",
62 | "inputmask",
63 | "jquery",
64 | "mask",
65 | "plugins"
66 | ],
67 | "time": "2017-11-21T11:46:23+00:00"
68 | },
69 | {
70 | "name": "bower-asset/jquery",
71 | "version": "3.2.1",
72 | "source": {
73 | "type": "git",
74 | "url": "https://github.com/jquery/jquery-dist.git",
75 | "reference": "77d2a51d0520d2ee44173afdf4e40a9201f5964e"
76 | },
77 | "dist": {
78 | "type": "zip",
79 | "url": "https://api.github.com/repos/jquery/jquery-dist/zipball/77d2a51d0520d2ee44173afdf4e40a9201f5964e",
80 | "reference": "77d2a51d0520d2ee44173afdf4e40a9201f5964e",
81 | "shasum": ""
82 | },
83 | "type": "bower-asset-library",
84 | "extra": {
85 | "bower-asset-main": "dist/jquery.js",
86 | "bower-asset-ignore": [
87 | "package.json"
88 | ]
89 | },
90 | "license": [
91 | "MIT"
92 | ],
93 | "keywords": [
94 | "browser",
95 | "javascript",
96 | "jquery",
97 | "library"
98 | ],
99 | "time": "2017-03-20T19:02:00+00:00"
100 | },
101 | {
102 | "name": "bower-asset/jquery-treegrid",
103 | "version": "0.3.0",
104 | "source": {
105 | "type": "git",
106 | "url": "https://github.com/maxazan/jquery-treegrid.git",
107 | "reference": "c8ba9e9604620002155d01a947cceffe18d4428c"
108 | },
109 | "dist": {
110 | "type": "zip",
111 | "url": "https://api.github.com/repos/maxazan/jquery-treegrid/zipball/c8ba9e9604620002155d01a947cceffe18d4428c",
112 | "reference": "c8ba9e9604620002155d01a947cceffe18d4428c",
113 | "shasum": ""
114 | },
115 | "require": {
116 | "bower-asset/jquery": ">=1.9.1",
117 | "bower-asset/jquery.cookie": ">=1.4.1"
118 | },
119 | "type": "bower-asset-library",
120 | "extra": {
121 | "bower-asset-ignore": [
122 | "examples",
123 | "tests",
124 | "**/.*",
125 | "composer.json",
126 | "index.html",
127 | "params.json",
128 | "style.css",
129 | "test.html",
130 | "treegrid.jquery.json"
131 | ]
132 | },
133 | "license": [
134 | "MIT"
135 | ],
136 | "description": "TreeGrid plugin for jQuery.",
137 | "keywords": [
138 | "bootstrap",
139 | "javascript",
140 | "jquery",
141 | "plugin",
142 | "treegrid",
143 | "treeview"
144 | ],
145 | "time": "2015-02-03T14:17:28+00:00"
146 | },
147 | {
148 | "name": "bower-asset/jquery.cookie",
149 | "version": "v1.4.1",
150 | "source": {
151 | "type": "git",
152 | "url": "https://github.com/carhartl/jquery-cookie.git",
153 | "reference": "7f88a4e631aba8a8c688fd8999ce6b9bcfd50718"
154 | },
155 | "dist": {
156 | "type": "zip",
157 | "url": "https://api.github.com/repos/carhartl/jquery-cookie/zipball/7f88a4e631aba8a8c688fd8999ce6b9bcfd50718",
158 | "reference": "7f88a4e631aba8a8c688fd8999ce6b9bcfd50718",
159 | "shasum": ""
160 | },
161 | "require": {
162 | "bower-asset/jquery": ">=1.2"
163 | },
164 | "type": "bower-asset-library",
165 | "extra": {
166 | "bower-asset-main": [
167 | "./jquery.cookie.js"
168 | ],
169 | "bower-asset-ignore": [
170 | "test",
171 | ".*",
172 | "*.json",
173 | "*.md",
174 | "*.txt",
175 | "Gruntfile.js"
176 | ]
177 | },
178 | "time": "2014-04-27T20:07:15+00:00"
179 | },
180 | {
181 | "name": "bower-asset/punycode",
182 | "version": "v1.3.2",
183 | "source": {
184 | "type": "git",
185 | "url": "https://github.com/bestiejs/punycode.js.git",
186 | "reference": "38c8d3131a82567bfef18da09f7f4db68c84f8a3"
187 | },
188 | "dist": {
189 | "type": "zip",
190 | "url": "https://api.github.com/repos/bestiejs/punycode.js/zipball/38c8d3131a82567bfef18da09f7f4db68c84f8a3",
191 | "reference": "38c8d3131a82567bfef18da09f7f4db68c84f8a3",
192 | "shasum": ""
193 | },
194 | "type": "bower-asset-library",
195 | "extra": {
196 | "bower-asset-main": "punycode.js",
197 | "bower-asset-ignore": [
198 | "coverage",
199 | "tests",
200 | ".*",
201 | "component.json",
202 | "Gruntfile.js",
203 | "node_modules",
204 | "package.json"
205 | ]
206 | },
207 | "time": "2014-10-22T12:02:42+00:00"
208 | },
209 | {
210 | "name": "bower-asset/yii2-pjax",
211 | "version": "2.0.7.1",
212 | "source": {
213 | "type": "git",
214 | "url": "https://github.com/yiisoft/jquery-pjax.git",
215 | "reference": "aef7b953107264f00234902a3880eb50dafc48be"
216 | },
217 | "dist": {
218 | "type": "zip",
219 | "url": "https://api.github.com/repos/yiisoft/jquery-pjax/zipball/aef7b953107264f00234902a3880eb50dafc48be",
220 | "reference": "aef7b953107264f00234902a3880eb50dafc48be",
221 | "shasum": ""
222 | },
223 | "require": {
224 | "bower-asset/jquery": ">=1.8"
225 | },
226 | "type": "bower-asset-library",
227 | "extra": {
228 | "bower-asset-main": "./jquery.pjax.js",
229 | "bower-asset-ignore": [
230 | ".travis.yml",
231 | "Gemfile",
232 | "Gemfile.lock",
233 | "CONTRIBUTING.md",
234 | "vendor/",
235 | "script/",
236 | "test/"
237 | ]
238 | },
239 | "license": [
240 | "MIT"
241 | ],
242 | "time": "2017-10-12T10:11:14+00:00"
243 | },
244 | {
245 | "name": "cebe/markdown",
246 | "version": "1.2.1",
247 | "source": {
248 | "type": "git",
249 | "url": "https://github.com/cebe/markdown.git",
250 | "reference": "9bac5e971dd391e2802dca5400bbeacbaea9eb86"
251 | },
252 | "dist": {
253 | "type": "zip",
254 | "url": "https://api.github.com/repos/cebe/markdown/zipball/9bac5e971dd391e2802dca5400bbeacbaea9eb86",
255 | "reference": "9bac5e971dd391e2802dca5400bbeacbaea9eb86",
256 | "shasum": ""
257 | },
258 | "require": {
259 | "lib-pcre": "*",
260 | "php": ">=5.4.0"
261 | },
262 | "require-dev": {
263 | "cebe/indent": "*",
264 | "facebook/xhprof": "*@dev",
265 | "phpunit/phpunit": "4.1.*"
266 | },
267 | "bin": [
268 | "bin/markdown"
269 | ],
270 | "type": "library",
271 | "extra": {
272 | "branch-alias": {
273 | "dev-master": "1.2.x-dev"
274 | }
275 | },
276 | "autoload": {
277 | "psr-4": {
278 | "cebe\\markdown\\": ""
279 | }
280 | },
281 | "notification-url": "https://packagist.org/downloads/",
282 | "license": [
283 | "MIT"
284 | ],
285 | "authors": [
286 | {
287 | "name": "Carsten Brandt",
288 | "email": "mail@cebe.cc",
289 | "homepage": "http://cebe.cc/",
290 | "role": "Creator"
291 | }
292 | ],
293 | "description": "A super fast, highly extensible markdown parser for PHP",
294 | "homepage": "https://github.com/cebe/markdown#readme",
295 | "keywords": [
296 | "extensible",
297 | "fast",
298 | "gfm",
299 | "markdown",
300 | "markdown-extra"
301 | ],
302 | "time": "2018-03-26T11:24:36+00:00"
303 | },
304 | {
305 | "name": "ezyang/htmlpurifier",
306 | "version": "v4.13.0",
307 | "source": {
308 | "type": "git",
309 | "url": "https://github.com/ezyang/htmlpurifier.git",
310 | "reference": "08e27c97e4c6ed02f37c5b2b20488046c8d90d75"
311 | },
312 | "dist": {
313 | "type": "zip",
314 | "url": "https://api.github.com/repos/ezyang/htmlpurifier/zipball/08e27c97e4c6ed02f37c5b2b20488046c8d90d75",
315 | "reference": "08e27c97e4c6ed02f37c5b2b20488046c8d90d75",
316 | "shasum": ""
317 | },
318 | "require": {
319 | "php": ">=5.2"
320 | },
321 | "require-dev": {
322 | "simpletest/simpletest": "dev-master#72de02a7b80c6bb8864ef9bf66d41d2f58f826bd"
323 | },
324 | "type": "library",
325 | "autoload": {
326 | "psr-0": {
327 | "HTMLPurifier": "library/"
328 | },
329 | "files": [
330 | "library/HTMLPurifier.composer.php"
331 | ],
332 | "exclude-from-classmap": [
333 | "/library/HTMLPurifier/Language/"
334 | ]
335 | },
336 | "notification-url": "https://packagist.org/downloads/",
337 | "license": [
338 | "LGPL-2.1-or-later"
339 | ],
340 | "authors": [
341 | {
342 | "name": "Edward Z. Yang",
343 | "email": "admin@htmlpurifier.org",
344 | "homepage": "http://ezyang.com"
345 | }
346 | ],
347 | "description": "Standards compliant HTML filter written in PHP",
348 | "homepage": "http://htmlpurifier.org/",
349 | "keywords": [
350 | "html"
351 | ],
352 | "time": "2020-06-29T00:56:53+00:00"
353 | },
354 | {
355 | "name": "yiisoft/yii2",
356 | "version": "2.0.38",
357 | "source": {
358 | "type": "git",
359 | "url": "https://github.com/yiisoft/yii2-framework.git",
360 | "reference": "fd01e747cc66a049ec105048f0ab8dfbdf60bf4b"
361 | },
362 | "dist": {
363 | "type": "zip",
364 | "url": "https://api.github.com/repos/yiisoft/yii2-framework/zipball/fd01e747cc66a049ec105048f0ab8dfbdf60bf4b",
365 | "reference": "fd01e747cc66a049ec105048f0ab8dfbdf60bf4b",
366 | "shasum": ""
367 | },
368 | "require": {
369 | "bower-asset/inputmask": "~3.2.2 | ~3.3.5",
370 | "bower-asset/jquery": "3.5.*@stable | 3.4.*@stable | 3.3.*@stable | 3.2.*@stable | 3.1.*@stable | 2.2.*@stable | 2.1.*@stable | 1.11.*@stable | 1.12.*@stable",
371 | "bower-asset/punycode": "1.3.*",
372 | "bower-asset/yii2-pjax": "~2.0.1",
373 | "cebe/markdown": "~1.0.0 | ~1.1.0 | ~1.2.0",
374 | "ext-ctype": "*",
375 | "ext-mbstring": "*",
376 | "ezyang/htmlpurifier": "~4.6",
377 | "lib-pcre": "*",
378 | "php": ">=5.4.0",
379 | "yiisoft/yii2-composer": "~2.0.4"
380 | },
381 | "bin": [
382 | "yii"
383 | ],
384 | "type": "library",
385 | "extra": {
386 | "branch-alias": {
387 | "dev-master": "2.0.x-dev"
388 | }
389 | },
390 | "autoload": {
391 | "psr-4": {
392 | "yii\\": ""
393 | }
394 | },
395 | "notification-url": "https://packagist.org/downloads/",
396 | "license": [
397 | "BSD-3-Clause"
398 | ],
399 | "authors": [
400 | {
401 | "name": "Qiang Xue",
402 | "email": "qiang.xue@gmail.com",
403 | "homepage": "http://www.yiiframework.com/",
404 | "role": "Founder and project lead"
405 | },
406 | {
407 | "name": "Alexander Makarov",
408 | "email": "sam@rmcreative.ru",
409 | "homepage": "http://rmcreative.ru/",
410 | "role": "Core framework development"
411 | },
412 | {
413 | "name": "Maurizio Domba",
414 | "homepage": "http://mdomba.info/",
415 | "role": "Core framework development"
416 | },
417 | {
418 | "name": "Carsten Brandt",
419 | "email": "mail@cebe.cc",
420 | "homepage": "http://cebe.cc/",
421 | "role": "Core framework development"
422 | },
423 | {
424 | "name": "Timur Ruziev",
425 | "email": "resurtm@gmail.com",
426 | "homepage": "http://resurtm.com/",
427 | "role": "Core framework development"
428 | },
429 | {
430 | "name": "Paul Klimov",
431 | "email": "klimov.paul@gmail.com",
432 | "role": "Core framework development"
433 | },
434 | {
435 | "name": "Dmitry Naumenko",
436 | "email": "d.naumenko.a@gmail.com",
437 | "role": "Core framework development"
438 | },
439 | {
440 | "name": "Boudewijn Vahrmeijer",
441 | "email": "info@dynasource.eu",
442 | "homepage": "http://dynasource.eu",
443 | "role": "Core framework development"
444 | }
445 | ],
446 | "description": "Yii PHP Framework Version 2",
447 | "homepage": "http://www.yiiframework.com/",
448 | "keywords": [
449 | "framework",
450 | "yii2"
451 | ],
452 | "funding": [
453 | {
454 | "url": "https://github.com/yiisoft",
455 | "type": "github"
456 | },
457 | {
458 | "url": "https://opencollective.com/yiisoft",
459 | "type": "open_collective"
460 | },
461 | {
462 | "url": "https://tidelift.com/funding/github/packagist/yiisoft/yii2",
463 | "type": "tidelift"
464 | }
465 | ],
466 | "time": "2020-09-14T21:52:10+00:00"
467 | },
468 | {
469 | "name": "yiisoft/yii2-composer",
470 | "version": "2.0.10",
471 | "source": {
472 | "type": "git",
473 | "url": "https://github.com/yiisoft/yii2-composer.git",
474 | "reference": "94bb3f66e779e2774f8776d6e1bdeab402940510"
475 | },
476 | "dist": {
477 | "type": "zip",
478 | "url": "https://api.github.com/repos/yiisoft/yii2-composer/zipball/94bb3f66e779e2774f8776d6e1bdeab402940510",
479 | "reference": "94bb3f66e779e2774f8776d6e1bdeab402940510",
480 | "shasum": ""
481 | },
482 | "require": {
483 | "composer-plugin-api": "^1.0 | ^2.0"
484 | },
485 | "require-dev": {
486 | "composer/composer": "^1.0 | ^2.0@dev",
487 | "phpunit/phpunit": "<7"
488 | },
489 | "type": "composer-plugin",
490 | "extra": {
491 | "class": "yii\\composer\\Plugin",
492 | "branch-alias": {
493 | "dev-master": "2.0.x-dev"
494 | }
495 | },
496 | "autoload": {
497 | "psr-4": {
498 | "yii\\composer\\": ""
499 | }
500 | },
501 | "notification-url": "https://packagist.org/downloads/",
502 | "license": [
503 | "BSD-3-Clause"
504 | ],
505 | "authors": [
506 | {
507 | "name": "Qiang Xue",
508 | "email": "qiang.xue@gmail.com"
509 | },
510 | {
511 | "name": "Carsten Brandt",
512 | "email": "mail@cebe.cc"
513 | }
514 | ],
515 | "description": "The composer plugin for Yii extension installer",
516 | "keywords": [
517 | "composer",
518 | "extension installer",
519 | "yii2"
520 | ],
521 | "funding": [
522 | {
523 | "url": "https://github.com/yiisoft",
524 | "type": "github"
525 | },
526 | {
527 | "url": "https://opencollective.com/yiisoft",
528 | "type": "open_collective"
529 | },
530 | {
531 | "url": "https://tidelift.com/funding/github/packagist/yiisoft/yii2-composer",
532 | "type": "tidelift"
533 | }
534 | ],
535 | "time": "2020-06-24T00:04:01+00:00"
536 | }
537 | ],
538 | "packages-dev": [
539 | {
540 | "name": "phpunit/php-code-coverage",
541 | "version": "1.2.18",
542 | "source": {
543 | "type": "git",
544 | "url": "https://github.com/sebastianbergmann/php-code-coverage.git",
545 | "reference": "fe2466802556d3fe4e4d1d58ffd3ccfd0a19be0b"
546 | },
547 | "dist": {
548 | "type": "zip",
549 | "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/fe2466802556d3fe4e4d1d58ffd3ccfd0a19be0b",
550 | "reference": "fe2466802556d3fe4e4d1d58ffd3ccfd0a19be0b",
551 | "shasum": ""
552 | },
553 | "require": {
554 | "php": ">=5.3.3",
555 | "phpunit/php-file-iterator": ">=1.3.0@stable",
556 | "phpunit/php-text-template": ">=1.2.0@stable",
557 | "phpunit/php-token-stream": ">=1.1.3,<1.3.0"
558 | },
559 | "require-dev": {
560 | "phpunit/phpunit": "3.7.*@dev"
561 | },
562 | "suggest": {
563 | "ext-dom": "*",
564 | "ext-xdebug": ">=2.0.5"
565 | },
566 | "type": "library",
567 | "extra": {
568 | "branch-alias": {
569 | "dev-master": "1.2.x-dev"
570 | }
571 | },
572 | "autoload": {
573 | "classmap": [
574 | "PHP/"
575 | ]
576 | },
577 | "notification-url": "https://packagist.org/downloads/",
578 | "include-path": [
579 | ""
580 | ],
581 | "license": [
582 | "BSD-3-Clause"
583 | ],
584 | "authors": [
585 | {
586 | "name": "Sebastian Bergmann",
587 | "email": "sb@sebastian-bergmann.de",
588 | "role": "lead"
589 | }
590 | ],
591 | "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.",
592 | "homepage": "https://github.com/sebastianbergmann/php-code-coverage",
593 | "keywords": [
594 | "coverage",
595 | "testing",
596 | "xunit"
597 | ],
598 | "time": "2014-09-02T10:13:14+00:00"
599 | },
600 | {
601 | "name": "phpunit/php-file-iterator",
602 | "version": "1.4.5",
603 | "source": {
604 | "type": "git",
605 | "url": "https://github.com/sebastianbergmann/php-file-iterator.git",
606 | "reference": "730b01bc3e867237eaac355e06a36b85dd93a8b4"
607 | },
608 | "dist": {
609 | "type": "zip",
610 | "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/730b01bc3e867237eaac355e06a36b85dd93a8b4",
611 | "reference": "730b01bc3e867237eaac355e06a36b85dd93a8b4",
612 | "shasum": ""
613 | },
614 | "require": {
615 | "php": ">=5.3.3"
616 | },
617 | "type": "library",
618 | "extra": {
619 | "branch-alias": {
620 | "dev-master": "1.4.x-dev"
621 | }
622 | },
623 | "autoload": {
624 | "classmap": [
625 | "src/"
626 | ]
627 | },
628 | "notification-url": "https://packagist.org/downloads/",
629 | "license": [
630 | "BSD-3-Clause"
631 | ],
632 | "authors": [
633 | {
634 | "name": "Sebastian Bergmann",
635 | "email": "sb@sebastian-bergmann.de",
636 | "role": "lead"
637 | }
638 | ],
639 | "description": "FilterIterator implementation that filters files based on a list of suffixes.",
640 | "homepage": "https://github.com/sebastianbergmann/php-file-iterator/",
641 | "keywords": [
642 | "filesystem",
643 | "iterator"
644 | ],
645 | "time": "2017-11-27T13:52:08+00:00"
646 | },
647 | {
648 | "name": "phpunit/php-text-template",
649 | "version": "1.2.1",
650 | "source": {
651 | "type": "git",
652 | "url": "https://github.com/sebastianbergmann/php-text-template.git",
653 | "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686"
654 | },
655 | "dist": {
656 | "type": "zip",
657 | "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/31f8b717e51d9a2afca6c9f046f5d69fc27c8686",
658 | "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686",
659 | "shasum": ""
660 | },
661 | "require": {
662 | "php": ">=5.3.3"
663 | },
664 | "type": "library",
665 | "autoload": {
666 | "classmap": [
667 | "src/"
668 | ]
669 | },
670 | "notification-url": "https://packagist.org/downloads/",
671 | "license": [
672 | "BSD-3-Clause"
673 | ],
674 | "authors": [
675 | {
676 | "name": "Sebastian Bergmann",
677 | "email": "sebastian@phpunit.de",
678 | "role": "lead"
679 | }
680 | ],
681 | "description": "Simple template engine.",
682 | "homepage": "https://github.com/sebastianbergmann/php-text-template/",
683 | "keywords": [
684 | "template"
685 | ],
686 | "time": "2015-06-21T13:50:34+00:00"
687 | },
688 | {
689 | "name": "phpunit/php-timer",
690 | "version": "1.0.9",
691 | "source": {
692 | "type": "git",
693 | "url": "https://github.com/sebastianbergmann/php-timer.git",
694 | "reference": "3dcf38ca72b158baf0bc245e9184d3fdffa9c46f"
695 | },
696 | "dist": {
697 | "type": "zip",
698 | "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/3dcf38ca72b158baf0bc245e9184d3fdffa9c46f",
699 | "reference": "3dcf38ca72b158baf0bc245e9184d3fdffa9c46f",
700 | "shasum": ""
701 | },
702 | "require": {
703 | "php": "^5.3.3 || ^7.0"
704 | },
705 | "require-dev": {
706 | "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.0"
707 | },
708 | "type": "library",
709 | "extra": {
710 | "branch-alias": {
711 | "dev-master": "1.0-dev"
712 | }
713 | },
714 | "autoload": {
715 | "classmap": [
716 | "src/"
717 | ]
718 | },
719 | "notification-url": "https://packagist.org/downloads/",
720 | "license": [
721 | "BSD-3-Clause"
722 | ],
723 | "authors": [
724 | {
725 | "name": "Sebastian Bergmann",
726 | "email": "sb@sebastian-bergmann.de",
727 | "role": "lead"
728 | }
729 | ],
730 | "description": "Utility class for timing",
731 | "homepage": "https://github.com/sebastianbergmann/php-timer/",
732 | "keywords": [
733 | "timer"
734 | ],
735 | "time": "2017-02-26T11:10:40+00:00"
736 | },
737 | {
738 | "name": "phpunit/php-token-stream",
739 | "version": "1.2.2",
740 | "source": {
741 | "type": "git",
742 | "url": "https://github.com/sebastianbergmann/php-token-stream.git",
743 | "reference": "ad4e1e23ae01b483c16f600ff1bebec184588e32"
744 | },
745 | "dist": {
746 | "type": "zip",
747 | "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/ad4e1e23ae01b483c16f600ff1bebec184588e32",
748 | "reference": "ad4e1e23ae01b483c16f600ff1bebec184588e32",
749 | "shasum": ""
750 | },
751 | "require": {
752 | "ext-tokenizer": "*",
753 | "php": ">=5.3.3"
754 | },
755 | "type": "library",
756 | "extra": {
757 | "branch-alias": {
758 | "dev-master": "1.2-dev"
759 | }
760 | },
761 | "autoload": {
762 | "classmap": [
763 | "PHP/"
764 | ]
765 | },
766 | "notification-url": "https://packagist.org/downloads/",
767 | "include-path": [
768 | ""
769 | ],
770 | "license": [
771 | "BSD-3-Clause"
772 | ],
773 | "authors": [
774 | {
775 | "name": "Sebastian Bergmann",
776 | "email": "sb@sebastian-bergmann.de",
777 | "role": "lead"
778 | }
779 | ],
780 | "description": "Wrapper around PHP's tokenizer extension.",
781 | "homepage": "https://github.com/sebastianbergmann/php-token-stream/",
782 | "keywords": [
783 | "tokenizer"
784 | ],
785 | "abandoned": true,
786 | "time": "2014-03-03T05:10:30+00:00"
787 | },
788 | {
789 | "name": "phpunit/phpunit",
790 | "version": "3.7.38",
791 | "source": {
792 | "type": "git",
793 | "url": "https://github.com/sebastianbergmann/phpunit.git",
794 | "reference": "38709dc22d519a3d1be46849868aa2ddf822bcf6"
795 | },
796 | "dist": {
797 | "type": "zip",
798 | "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/38709dc22d519a3d1be46849868aa2ddf822bcf6",
799 | "reference": "38709dc22d519a3d1be46849868aa2ddf822bcf6",
800 | "shasum": ""
801 | },
802 | "require": {
803 | "ext-ctype": "*",
804 | "ext-dom": "*",
805 | "ext-json": "*",
806 | "ext-pcre": "*",
807 | "ext-reflection": "*",
808 | "ext-spl": "*",
809 | "php": ">=5.3.3",
810 | "phpunit/php-code-coverage": "~1.2",
811 | "phpunit/php-file-iterator": "~1.3",
812 | "phpunit/php-text-template": "~1.1",
813 | "phpunit/php-timer": "~1.0",
814 | "phpunit/phpunit-mock-objects": "~1.2",
815 | "symfony/yaml": "~2.0"
816 | },
817 | "require-dev": {
818 | "pear-pear.php.net/pear": "1.9.4"
819 | },
820 | "suggest": {
821 | "phpunit/php-invoker": "~1.1"
822 | },
823 | "bin": [
824 | "composer/bin/phpunit"
825 | ],
826 | "type": "library",
827 | "extra": {
828 | "branch-alias": {
829 | "dev-master": "3.7.x-dev"
830 | }
831 | },
832 | "autoload": {
833 | "classmap": [
834 | "PHPUnit/"
835 | ]
836 | },
837 | "notification-url": "https://packagist.org/downloads/",
838 | "include-path": [
839 | "",
840 | "../../symfony/yaml/"
841 | ],
842 | "license": [
843 | "BSD-3-Clause"
844 | ],
845 | "authors": [
846 | {
847 | "name": "Sebastian Bergmann",
848 | "email": "sebastian@phpunit.de",
849 | "role": "lead"
850 | }
851 | ],
852 | "description": "The PHP Unit Testing framework.",
853 | "homepage": "http://www.phpunit.de/",
854 | "keywords": [
855 | "phpunit",
856 | "testing",
857 | "xunit"
858 | ],
859 | "time": "2014-10-17T09:04:17+00:00"
860 | },
861 | {
862 | "name": "phpunit/phpunit-mock-objects",
863 | "version": "1.2.3",
864 | "source": {
865 | "type": "git",
866 | "url": "https://github.com/sebastianbergmann/phpunit-mock-objects.git",
867 | "reference": "5794e3c5c5ba0fb037b11d8151add2a07fa82875"
868 | },
869 | "dist": {
870 | "type": "zip",
871 | "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/5794e3c5c5ba0fb037b11d8151add2a07fa82875",
872 | "reference": "5794e3c5c5ba0fb037b11d8151add2a07fa82875",
873 | "shasum": ""
874 | },
875 | "require": {
876 | "php": ">=5.3.3",
877 | "phpunit/php-text-template": ">=1.1.1@stable"
878 | },
879 | "suggest": {
880 | "ext-soap": "*"
881 | },
882 | "type": "library",
883 | "autoload": {
884 | "classmap": [
885 | "PHPUnit/"
886 | ]
887 | },
888 | "notification-url": "https://packagist.org/downloads/",
889 | "include-path": [
890 | ""
891 | ],
892 | "license": [
893 | "BSD-3-Clause"
894 | ],
895 | "authors": [
896 | {
897 | "name": "Sebastian Bergmann",
898 | "email": "sb@sebastian-bergmann.de",
899 | "role": "lead"
900 | }
901 | ],
902 | "description": "Mock Object library for PHPUnit",
903 | "homepage": "https://github.com/sebastianbergmann/phpunit-mock-objects/",
904 | "keywords": [
905 | "mock",
906 | "xunit"
907 | ],
908 | "abandoned": true,
909 | "time": "2013-01-13T10:24:48+00:00"
910 | },
911 | {
912 | "name": "symfony/yaml",
913 | "version": "v2.8.33",
914 | "source": {
915 | "type": "git",
916 | "url": "https://github.com/symfony/yaml.git",
917 | "reference": "be720fcfae4614df204190d57795351059946a77"
918 | },
919 | "dist": {
920 | "type": "zip",
921 | "url": "https://api.github.com/repos/symfony/yaml/zipball/be720fcfae4614df204190d57795351059946a77",
922 | "reference": "be720fcfae4614df204190d57795351059946a77",
923 | "shasum": ""
924 | },
925 | "require": {
926 | "php": ">=5.3.9"
927 | },
928 | "type": "library",
929 | "extra": {
930 | "branch-alias": {
931 | "dev-master": "2.8-dev"
932 | }
933 | },
934 | "autoload": {
935 | "psr-4": {
936 | "Symfony\\Component\\Yaml\\": ""
937 | },
938 | "exclude-from-classmap": [
939 | "/Tests/"
940 | ]
941 | },
942 | "notification-url": "https://packagist.org/downloads/",
943 | "license": [
944 | "MIT"
945 | ],
946 | "authors": [
947 | {
948 | "name": "Fabien Potencier",
949 | "email": "fabien@symfony.com"
950 | },
951 | {
952 | "name": "Symfony Community",
953 | "homepage": "https://symfony.com/contributors"
954 | }
955 | ],
956 | "description": "Symfony Yaml Component",
957 | "homepage": "https://symfony.com",
958 | "time": "2018-01-03T07:36:31+00:00"
959 | }
960 | ],
961 | "aliases": [],
962 | "minimum-stability": "stable",
963 | "stability-flags": [],
964 | "prefer-stable": false,
965 | "prefer-lowest": false,
966 | "platform": [],
967 | "platform-dev": [],
968 | "plugin-api-version": "1.1.0"
969 | }
970 |
--------------------------------------------------------------------------------