@@ -14,6 +14,27 @@ public function __construct()
1414 parent ::__construct (self ::$ defaultName );
1515 }
1616
17+ public function generate (string $ source ) : string
18+ {
19+ $ beans = $ this ->getBeans ($ source );
20+ $ sorter = new \CoolBeans \Utils \TableSorter ($ beans );
21+
22+ $ sortedBeans = $ sorter ->sort ();
23+
24+ $ ddl = '' ;
25+ $ lastBean = \array_key_last ($ sortedBeans );
26+
27+ foreach ($ sortedBeans as $ key => $ bean ) {
28+ $ ddl .= $ this ->generateBean ($ bean );
29+
30+ if ($ lastBean !== $ key ) {
31+ $ ddl .= \PHP_EOL . \PHP_EOL ;
32+ }
33+ }
34+
35+ return $ ddl ;
36+ }
37+
1738 protected function configure () : void
1839 {
1940 $ this ->setName (self ::$ defaultName );
@@ -40,30 +61,16 @@ protected function execute(
4061 return 0 ;
4162 }
4263
43- public function generate ( string $ source ) : string
64+ private static function hasPrimaryKeyAttribute ( \ ReflectionClass $ bean ) : bool
4465 {
45- $ beans = $ this ->getBeans ($ source );
46- $ sorter = new \CoolBeans \Utils \TableSorter ($ beans );
47-
48- $ sortedBeans = $ sorter ->sort ();
49-
50- $ ddl = '' ;
51- $ lastBean = \array_key_last ($ sortedBeans );
52-
53- foreach ($ sortedBeans as $ key => $ bean ) {
54- $ ddl .= $ this ->generateBean ($ bean );
55-
56- if ($ lastBean !== $ key ) {
57- $ ddl .= \PHP_EOL . \PHP_EOL ;
58- }
59- }
60-
61- return $ ddl ;
66+ return \count ($ bean ->getAttributes (\CoolBeans \Attribute \PrimaryKey::class)) > 0
67+ && \count ($ bean ->getAttributes (\CoolBeans \Attribute \PrimaryKey::class)[0 ]->newInstance ()->columns ) > 0 ;
6268 }
6369
6470 private function generateBean (string $ className ) : string
6571 {
6672 $ bean = new \ReflectionClass ($ className );
73+ $ this ->validateBean ($ bean );
6774
6875 $ beanName = \Infinityloop \Utils \CaseConverter::toSnakeCase ($ bean ->getShortName ());
6976 $ toReturn = 'CREATE TABLE ` ' . $ beanName . '`( ' . \PHP_EOL ;
@@ -83,11 +90,11 @@ private function generateBean(string $className) : string
8390 'name ' => $ this ->getPropertyName ($ property ),
8491 'dataType ' => $ this ->getDataType ($ property ),
8592 'notNull ' => $ this ->getNotNull ($ property ),
86- 'default ' => $ this ->getDefault ($ property ),
93+ 'default ' => $ this ->getDefault ($ property, $ bean ),
8794 'comment ' => $ this ->getComment ($ property ),
8895 ];
8996
90- $ foreignKey = $ this ->getForeignKey ($ property );
97+ $ foreignKey = $ this ->getForeignKey ($ property, $ bean );
9198 $ uniqueConstraint = $ this ->getUnique ($ property , $ beanName );
9299
93100 if (\is_string ($ uniqueConstraint )) {
@@ -192,9 +199,17 @@ private function getTableCollation(\ReflectionClass $bean) : string
192199 return 'COLLATE = ` ' . $ collationAttribute [0 ]->newInstance ()->collation . '` ' ;
193200 }
194201
195- private function getDefault (\ReflectionProperty $ property ) : string
202+ private function getDefault (\ReflectionProperty $ property, \ ReflectionClass $ bean ) : string
196203 {
197- if ($ property ->getName () === 'id ' ) {
204+ $ hasPrimaryKeyAttribute = self ::hasPrimaryKeyAttribute ($ bean );
205+ $ attributeColumns = $ hasPrimaryKeyAttribute
206+ ? $ bean ->getAttributes (\CoolBeans \Attribute \PrimaryKey::class)[0 ]->newInstance ()->columns
207+ : [];
208+
209+ if (
210+ ($ hasPrimaryKeyAttribute && $ attributeColumns [0 ] === $ property ->getName ())
211+ || (!$ hasPrimaryKeyAttribute && $ property ->getName () === 'id ' )
212+ ) {
198213 return ' AUTO_INCREMENT PRIMARY KEY ' ;
199214 }
200215
@@ -450,12 +465,49 @@ private function printSection(array $data) : string
450465 return ', ' . \PHP_EOL . \PHP_EOL . \implode (', ' . \PHP_EOL , $ data );
451466 }
452467
453- private function getForeignKey (\ReflectionProperty $ property ) : ?string
468+ private function validateBean (\ReflectionClass $ bean ) : void
469+ {
470+ $ hasPrimaryKeyAttribute = self ::hasPrimaryKeyAttribute ($ bean );
471+ $ attributeColumns = $ hasPrimaryKeyAttribute
472+ ? $ bean ->getAttributes (\CoolBeans \Attribute \PrimaryKey::class)[0 ]->newInstance ()->columns
473+ : [];
474+ $ hasId = false ;
475+
476+ foreach ($ bean ->getProperties (\ReflectionProperty::IS_PUBLIC ) as $ property ) {
477+ if ($ property ->getName () === 'id ' ) {
478+ $ hasId = true ;
479+ }
480+
481+ foreach ($ attributeColumns as $ key => $ column ) {
482+ if ($ column === $ property ->getName ()) {
483+ $ hasId = true ;
484+ unset($ attributeColumns [$ key ]);
485+ }
486+ }
487+ }
488+
489+ if ($ hasPrimaryKeyAttribute && \count ($ attributeColumns ) > 0 ) {
490+ throw new \CoolBeans \Exception \PrimaryKeyColumnDoesntExist (
491+ 'PrimaryKey attribute column(s) ' . \implode (', ' , $ attributeColumns ) . ' doesn \'t exist in Bean ' . $ bean ->getShortName () . '. ' ,
492+ );
493+ }
494+
495+ if (!$ hasPrimaryKeyAttribute && !$ hasId ) {
496+ throw new \CoolBeans \Exception \MissingPrimaryKey ('Bean ' . $ bean ->getShortName () . ' has no primary key. ' );
497+ }
498+ }
499+
500+ private function getForeignKey (\ReflectionProperty $ property , \ReflectionClass $ bean ) : ?string
454501 {
455502 $ type = $ property ->getType ();
456503 \assert ($ type instanceof \ReflectionNamedType);
457504
458- if ($ type ->getName () !== \CoolBeans \PrimaryKey \IntPrimaryKey::class || $ property ->getName () === 'id ' ) {
505+ $ hasPrimaryKeyAttribute = self ::hasPrimaryKeyAttribute ($ bean );
506+ $ attributeColumns = $ hasPrimaryKeyAttribute
507+ ? $ bean ->getAttributes (\CoolBeans \Attribute \PrimaryKey::class)[0 ]->newInstance ()->columns
508+ : [];
509+
510+ if ($ property ->getName () === 'id ' || ($ this ->hasPrimaryKeyAttribute ($ bean ) && \in_array ($ property ->getName (), $ attributeColumns , true ))) {
459511 return null ;
460512 }
461513
@@ -484,9 +536,11 @@ private function getForeignKey(\ReflectionProperty $property) : ?string
484536
485537 $ table = $ foreignKey ->table ;
486538 $ column = $ foreignKey ->column ;
487- } else {
539+ } elseif ( \str_contains ( $ property -> getName (), ' _id ' )) {
488540 $ table = \str_replace ('_id ' , '' , $ property ->getName ());
489541 $ column = 'id ' ;
542+ } else {
543+ return null ;
490544 }
491545
492546 return self ::INDENTATION . 'FOREIGN KEY (` ' . $ property ->getName () . '`) REFERENCES ` ' . $ table . '`(` ' . $ column . '`) '
0 commit comments