Skip to content

Commit c24c2c0

Browse files
authored
Merge pull request #300 from schmunk42/feature/dev-elias
Features
2 parents 000a425 + 38b96a8 commit c24c2c0

40 files changed

+1096
-693
lines changed

.github/workflows/docker-image.yml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,3 +19,9 @@ jobs:
1919
cd tests
2020
make all
2121
make test
22+
23+
- name: 'Upload Test Report'
24+
uses: actions/upload-artifact@v4
25+
with:
26+
path: tests/_output
27+
retention-days: 7

src/commands/BatchController.php

Lines changed: 44 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,16 @@ class BatchController extends Controller
161161
*/
162162
public $enableI18N = true;
163163

164+
/**
165+
* @var bool whether to enable or disable the pluralization of the models name
166+
*/
167+
public $disablePluralization = false;
168+
169+
/**
170+
* @var string prefix to prepend to the many many relation methods
171+
*/
172+
public $modelManyManyRelationSuffix = '';
173+
164174
/**
165175
* @var bool whether the entity names will be singular or the same as the table name
166176
*/
@@ -299,13 +309,26 @@ class BatchController extends Controller
299309
* @var bool This indicates whether the generator should generate attribute hints by using the comments of the corresponding DB columns
300310
*/
301311
public $modelGenerateHintsFromComments = true;
312+
313+
/**
314+
* @var bool Generate Relations from Current Schema
315+
*/
316+
public $modelGenerateRelationsFromCurrentSchema = true;
317+
318+
public $modelTranslationTableAdditions = ['name' => 'meta', 'fallbackLanguage' => false];
319+
320+
/**
321+
* Whether the copy functionality for a crud should be created or not
322+
*/
323+
public $crudEnableCopy = true;
324+
302325
/**
303326
* @var array application configuration for creating temporary applications
304327
*/
305328
protected $appConfig;
306329

307330
/**
308-
* @var instance of class schmunk42\giiant\generators\model\Generator
331+
* @var \schmunk42\giiant\generators\model\Generator instance of class schmunk42\giiant\generators\model\Generator
309332
*/
310333
protected $modelGenerator;
311334

@@ -345,6 +368,8 @@ public function options($id)
345368
'modelRemoveDuplicateRelations',
346369
'modelCacheRelationsData',
347370
'modelGenerateRelations',
371+
'modelGenerateRelationsFromCurrentSchema',
372+
'modelTranslationTableAdditions',
348373
'modelGenerateJunctionRelationMode',
349374
'modelGenerateQuery',
350375
'modelQueryNamespace',
@@ -367,7 +392,9 @@ public function options($id)
367392
'crudOverwriteSearchModelClass',
368393
'crudOverwriteRestControllerClass',
369394
'crudOverwriteControllerClass',
370-
'generateAccessFilterMigrations'
395+
'generateAccessFilterMigrations',
396+
'disablePluralization',
397+
'crudEnableCopy'
371398
]
372399
);
373400
}
@@ -463,13 +490,17 @@ public function actionModels()
463490
'removeDuplicateRelations' => $this->modelRemoveDuplicateRelations,
464491
'cacheRelationsData' => $this->modelCacheRelationsData,
465492
'generateRelations' => $this->modelGenerateRelations,
493+
'generateRelationsFromCurrentSchema' => $this->modelGenerateRelationsFromCurrentSchema,
494+
'translationTableAdditions' => $this->modelTranslationTableAdditions,
466495
'generateJunctionRelationMode' => $this->modelGenerateJunctionRelationMode,
467496
'tableNameMap' => $this->tableNameMap,
468497
'generateQuery' => $this->modelGenerateQuery,
469498
'queryNs' => $this->modelQueryNamespace,
470499
'queryBaseClass' => $this->modelQueryBaseClass,
471500
'generateLabelsFromComments' => $this->modelGenerateLabelsFromComments,
472501
'generateHintsFromComments' => $this->modelGenerateHintsFromComments,
502+
'disablePluralization' => $this->disablePluralization,
503+
'manyManyRelationSuffix' => $this->modelManyManyRelationSuffix
473504
];
474505
$route = 'gii/giiant-model';
475506

@@ -540,6 +571,9 @@ public function actionCruds()
540571
'gridMaxColumns' => $this->crudGridMaxColumns,
541572
'generateAccessFilterMigrations' => $this->generateAccessFilterMigrations,
542573
'actionButtonColumnPosition' => $this->crudActionButtonColumnPosition,
574+
'disablePluralization' => $this->disablePluralization,
575+
'gridMaxColumns' => $this->crudGridMaxColumns,
576+
'enableCopy' => $this->crudEnableCopy
543577
];
544578
$route = 'gii/giiant-crud';
545579
$app = \Yii::$app;
@@ -612,9 +646,14 @@ private function closeTempAppConnections(Application $app)
612646
// since we don't know if there are any other than the "known" modelDb
613647
if (isset($app->components)) {
614648
foreach ($app->components as $cid => $component) {
615-
$cObj = $app->get($cid);
616-
if ($cObj instanceof \yii\db\Connection) {
617-
$cObj->close();
649+
try {
650+
$cObj = $app->get($cid);
651+
if ($cObj instanceof \yii\db\Connection) {
652+
$cObj->close();
653+
}
654+
} catch (\Throwable $e) {
655+
// ignore because we don't know if the component is a db connection
656+
Yii::warning($e->getMessage());
618657
}
619658
}
620659
}

src/generators/crud/Generator.php

Lines changed: 109 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,11 @@ class Generator extends \yii\gii\generators\crud\Generator
138138
*/
139139
public $fixOptions = '';
140140

141+
/**
142+
* @var bool whether to enable or disable the pluralization of the models name
143+
*/
144+
public $disablePluralization = false;
145+
141146
/**
142147
* @var string form field for selecting and loading saved gii forms
143148
*/
@@ -158,6 +163,10 @@ class Generator extends \yii\gii\generators\crud\Generator
158163

159164
private $_p = [];
160165

166+
public $translateRelations = ['translation', 'translation_meta'];
167+
168+
public $enableCopy = true;
169+
161170
/**
162171
* {@inheritdoc}
163172
*/
@@ -230,6 +239,7 @@ public function rules()
230239
'generateAccessFilterMigrations',
231240
'singularEntities',
232241
'modelMessageCategory',
242+
'enableCopy'
233243
],
234244
'safe',
235245
],
@@ -270,6 +280,7 @@ public function formAttributes()
270280
'accessFilter',
271281
'singularEntities',
272282
'modelMessageCategory',
283+
'enableCopy'
273284
];
274285
}
275286

@@ -305,20 +316,20 @@ public function getControllerID()
305316
public function getModuleId()
306317
{
307318
if (!$this->moduleNs) {
308-
$controllerNs = \yii\helpers\StringHelper::dirname(ltrim($this->controllerClass, '\\'));
309-
$this->moduleNs = \yii\helpers\StringHelper::dirname(ltrim($controllerNs, '\\'));
319+
$controllerNs = StringHelper::dirname(ltrim($this->controllerClass, '\\'));
320+
$this->moduleNs = StringHelper::dirname(ltrim($controllerNs, '\\'));
310321
}
311322

312-
return \yii\helpers\StringHelper::basename($this->moduleNs);
323+
return StringHelper::basename($this->moduleNs);
313324
}
314325

315326
public function generate()
316327
{
317328
$accessDefinitions = require $this->getTemplatePath().'/access_definition.php';
318329

319-
$this->controllerNs = \yii\helpers\StringHelper::dirname(ltrim($this->controllerClass, '\\'));
320-
$this->moduleNs = \yii\helpers\StringHelper::dirname(ltrim($this->controllerNs, '\\'));
321-
$controllerName = substr(\yii\helpers\StringHelper::basename($this->controllerClass), 0, -10);
330+
$this->controllerNs = StringHelper::dirname(ltrim($this->controllerClass, '\\'));
331+
$this->moduleNs = StringHelper::dirname(ltrim($this->controllerNs, '\\'));
332+
$controllerName = substr(StringHelper::basename($this->controllerClass), 0, -10);
322333

323334
if ($this->singularEntities) {
324335
$this->modelClass = Inflector::singularize($this->modelClass);
@@ -345,7 +356,7 @@ public function generate()
345356
}
346357

347358
$files[] = new CodeFile($baseControllerFile, $this->render('controller.php', ['accessDefinitions' => $accessDefinitions]));
348-
$params['controllerClassName'] = \yii\helpers\StringHelper::basename($this->controllerClass);
359+
$params['controllerClassName'] = StringHelper::basename($this->controllerClass);
349360

350361
if ($this->overwriteControllerClass || !is_file($controllerFile)) {
351362
$files[] = new CodeFile($controllerFile, $this->render('controller-extended.php', $params));
@@ -365,12 +376,32 @@ public function generate()
365376
$viewPath = $this->getViewPath();
366377
$templatePath = $this->getTemplatePath().'/views';
367378

379+
$model = Yii::createObject($this->modelClass);
380+
if (array_key_exists('crud-form', $model->scenarios())) {
381+
$model->setScenario('crud-form');
382+
} else {
383+
$model->setScenario('crud');
384+
}
385+
386+
$safeAttributes = $model->safeAttributes();
387+
if (empty($safeAttributes)) {
388+
$model->setScenario('default');
389+
$safeAttributes = $model->safeAttributes();
390+
}
391+
if (empty($safeAttributes)) {
392+
$safeAttributes = $model::getTableSchema()->columnNames;
393+
}
394+
368395
foreach (scandir($templatePath) as $file) {
369-
if (empty($this->searchModelClass) && $file === '_search.php') {
396+
if ($file === '_search.php' && !$this->getRenderWithSearch()) {
370397
continue;
371398
}
372399
if (is_file($templatePath.'/'.$file) && pathinfo($file, PATHINFO_EXTENSION) === 'php') {
373-
$files[] = new CodeFile("$viewPath/$file", $this->render("views/$file", ['permisions' => $permisions]));
400+
$files[] = new CodeFile("$viewPath/$file", $this->render("views/$file", [
401+
'model' => $model,
402+
'safeAttributes' => $safeAttributes,
403+
'accessDefinitions' => $accessDefinitions
404+
]));
374405
}
375406
}
376407

@@ -462,4 +493,73 @@ public function var_export54($var, $indent = '')
462493
return var_export($var, true);
463494
}
464495
}
496+
497+
/**
498+
* @return array
499+
* @throws \yii\base\InvalidConfigException
500+
*/
501+
public function generateSearchRules()
502+
{
503+
504+
$rules = parent::generateSearchRules();
505+
$model = \Yii::createObject($this->modelClass);
506+
foreach ($model->behaviors() as $key => $behavior) {
507+
if (!empty($behavior['translationAttributes'])) {
508+
$rules[] = "[['" . implode("', '", $behavior['translationAttributes']) . "'], 'safe']";
509+
}
510+
}
511+
return $rules;
512+
}
513+
514+
/**
515+
* @return array
516+
* @throws \yii\base\InvalidConfigException
517+
*/
518+
public function generateSearchConditions()
519+
{
520+
521+
$searchConditions = parent::generateSearchConditions();
522+
$model = \Yii::createObject($this->modelClass);
523+
foreach ($model->behaviors() as $key => $behavior) {
524+
if (!empty($behavior['translationAttributes'])) {
525+
foreach ($behavior['translationAttributes'] as $translationAttribute) {
526+
$searchConditions[] = "\$query->andFilterWhere(['like','{$translationAttribute}', \$this->$translationAttribute]);";
527+
}
528+
}
529+
}
530+
return $searchConditions;
531+
}
532+
533+
534+
/**
535+
* @return array
536+
*/
537+
public function getTranslationRelationModels()
538+
{
539+
$translationRelationModels = [];
540+
foreach ($this->translateRelations as $translateRelation) {
541+
$translationRelationModels[] = $this->modelClass . Inflector::camelize($translateRelation);
542+
}
543+
return $translationRelationModels;
544+
}
545+
546+
/**
547+
* @return string
548+
*/
549+
public function getTranslationModelClass() {
550+
return '\\' . $this->modelClass . Inflector::camelize('translation');
551+
}
552+
553+
/**
554+
* @return bool
555+
* @throws \yii\base\InvalidConfigException
556+
*/
557+
public function getHasTranslationRelation() {
558+
return isset(\Yii::createObject($this->modelClass)->behaviors()['translation']);
559+
}
560+
561+
public function getRenderWithSearch()
562+
{
563+
return $this->indexWidgetType !== 'grid' && $this->searchModelClass !== '';
564+
}
465565
}

src/generators/crud/ModelTrait.php

Lines changed: 21 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ public function getModelByTableName($name)
6363
*
6464
* return values can be filtered by types 'belongs_to', 'many_many', 'has_many', 'has_one', 'pivot'
6565
*
66-
* @param ActiveRecord $modelClass
66+
* @param \yii\db\ActiveRecord $modelClass
6767
* @param array $types
6868
*
6969
* @return array
@@ -73,13 +73,15 @@ public function getModelRelations($modelClass, $types = [])
7373
$reflector = new \ReflectionClass($modelClass);
7474
$model = new $modelClass();
7575
$stack = [];
76-
$modelGenerator = new ModelGenerator();
76+
$modelGenerator = new ModelGenerator([
77+
'disablePluralization' => $this->disablePluralization
78+
]);
7779
foreach ($reflector->getMethods(\ReflectionMethod::IS_PUBLIC) as $method) {
78-
if (in_array(substr($method->name, 3), $this->skipRelations)) {
80+
if (in_array(substr($method->name, 3), $this->skipRelations, true)) {
7981
continue;
8082
}
8183
// look for getters
82-
if (substr($method->name, 0, 3) !== 'get') {
84+
if (strpos($method->name, 'get') !== 0) {
8385
continue;
8486
}
8587
// skip class specific getters
@@ -90,7 +92,7 @@ public function getModelRelations($modelClass, $types = [])
9092
'getAttribute',
9193
'getAttributeLabel',
9294
'getAttributeHint',
93-
'getOldAttribute',
95+
'getOldAttribute',
9496
'getErrorSummary',
9597
];
9698
if (in_array($method->name, $skipMethods)) {
@@ -117,13 +119,17 @@ public function getModelRelations($modelClass, $types = [])
117119
$relationType = 'has_many';
118120
}
119121
// if types is empty, return all types -> no filter
120-
if ((count($types) == 0) || in_array($relationType, $types)) {
121-
$name = $modelGenerator->generateRelationName(
122-
[$relation],
123-
$model->getTableSchema(),
124-
substr($method->name, 3),
125-
$relation->multiple
126-
);
122+
if ((count($types) === 0) || in_array($relationType, $types, true)) {
123+
if ($this->disablePluralization) {
124+
$name = str_replace('get','', $method->name);
125+
} else {
126+
$name = $modelGenerator->generateRelationName(
127+
[$relation],
128+
$model->getTableSchema(),
129+
substr($method->name, 3),
130+
$relation->multiple
131+
);
132+
}
127133
$stack[$name] = $relation;
128134
}
129135
}
@@ -146,6 +152,7 @@ public function getColumnByAttribute($attribute, $model = null)
146152
$model = $this;
147153
}
148154

155+
149156
// omit schema for NOSQL models
150157
if (method_exists($model,'getTableSchema') && $model->getTableSchema()) {
151158
return $model->getTableSchema()->getColumn($attribute);
@@ -164,12 +171,12 @@ public function getRelationByColumn($model, $column, $types = ['belongs_to', 'ma
164171
$relations = $this->getModelRelations($model, $types);
165172
foreach ($relations as $relation) {
166173
// TODO: check multiple link(s)
167-
if ($relation->link && reset($relation->link) == $column->name) {
174+
if ($relation->link && reset($relation->link) === $column->name) {
168175
return $relation;
169176
}
170177
}
171178

172-
return;
179+
return null;
173180
}
174181

175182
public function createRelationRoute($relation, $action)
@@ -179,7 +186,6 @@ public function createRelationRoute($relation, $action)
179186
'-',
180187
true
181188
).'/'.$action;
182-
183189
return $route;
184190
}
185191

0 commit comments

Comments
 (0)