Completed
Push — master ( 707e60...bec0f5 )
by Jean-Christophe
01:22
created

ModelsCreator::getJoinTableArray()   B

Complexity

Conditions 5
Paths 3

Size

Total Lines 10
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 10
rs 8.8571
cc 5
eloc 8
nc 3
nop 2
1
<?php
2
namespace micro\orm\creator;
3
4
use micro\orm\creator\Model;
5
use micro\orm\creator\Member;
6
use micro\annotations\JoinColumnAnnotation;
7
use micro\cache\CacheManager;
8
use micro\controllers\Startup;
9
use micro\utils\FsUtils;
10
11
12
class ModelsCreator {
13
	private static $config;
14
	private static $pdoObject;
15
	private static $tables=array();
16
	private static $classes=array();
17
18
	private static function init($config){
19
		self::$config=$config["database"];
20
		self::connect($config["database"]);
21
	}
22
	/**
23
	 * Réalise la connexion à la base de données
24
	 */
25
	private static function connect($config) {
26
		try {
27
			self::$pdoObject = new \PDO(
28
					$config["type"].':host=' . $config["serverName"] . ';dbname='
29
					. $config["dbName"] . ';port:' . $config["port"],
30
					$config["user"], $config["password"]);
31
			self::$pdoObject->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION);
32
			self::$pdoObject->exec("SET CHARACTER SET utf8");
33
34
		} catch (\PDOException $e) {
35
			print "Error!: " . $e->getMessage() . "<br/>";
36
			die();
0 ignored issues
show
Coding Style Compatibility introduced by
The method connect() contains an exit expression.

An exit expression should only be used in rare cases. For example, if you write a short command line script.

In most cases however, using an exit expression makes the code untestable and often causes incompatibilities with other libraries. Thus, unless you are absolutely sure it is required here, we recommend to refactor your code to avoid its usage.

Loading history...
37
		}
38
	}
39
40
	public static function create($config,$initCache=true,$singleTable=null){
41
		self::init($config);
42
		$modelsDir=Startup::getModelsCompletePath();
43
		if(FsUtils::safeMkdir($modelsDir)){
44
			self::$tables=self::getTablesName();
45
			CacheManager::checkCache($config);
46
47
			foreach (self::$tables as $table){
48
				$class=new Model($table,$config["mvcNS"]["models"]);
49
				$fieldsInfos=self::getFieldsInfos($table);
50
				$keys=self::getPrimaryKeys($table);
51
				foreach ($fieldsInfos as $field=>$info){
52
					$member=new Member($field);
53
					if(in_array($field, $keys)){
54
						$member->setPrimary();
55
					}
56
					$member->setDbType($info);
57
					$class->addMember($member);
58
				}
59
				self::$classes[$table]=$class;
60
			}
61
			self::createRelations();
62
			if(isset($singleTable)){
63
				self::createOneClass($singleTable,$modelsDir);
64
			}else{
65
				foreach (self::$classes as $table=>$class){
66
					$name=$class->getSimpleName();
67
					echo "Creating the {$name} class\n";
68
					self::writeFile($modelsDir.DS.$name.".php", $class);
69
				}
70
			}
71
			if($initCache===true){
72
				CacheManager::initCache($config,"models");
73
			}
74
		}
75
	}
76
77
	private static function createOneClass($singleTable,$modelsDir){
78
		if(isset(self::$classes[$singleTable])){
79
			$class=self::$classes[$singleTable];
80
			echo "Creating the {$class->getName()} class\n";
81
			self::writeFile($modelsDir.DS.$singleTable.".php", $class);
82
		}else{
83
			echo "The {$singleTable} table does not exist in the database\n";
84
		}
85
	}
86
87
	private static function createRelations(){
88
		foreach (self::$classes as $table=>$class){
89
			$keys=self::getPrimaryKeys($table);
90
			foreach ($keys as $key){
91
				$fks=self::getForeignKeys($table, $key);
92
				foreach ($fks as $fk){
93
					$field=strtolower($table);
94
					$fkTable=$fk["TABLE_NAME"];
95
					self::$classes[$table]->addOneToMany($fkTable."s",$table, self::$classes[$fkTable]->getName());
96
					self::$classes[$fkTable]->addManyToOne($field, $fk["COLUMN_NAME"], $class->getName());
97
				}
98
			}
99
		}
100
		self::createManyToMany();
101
	}
102
103
	private static function getTableName($classname){
104
		$posSlash=strrpos($classname, '\\');
105
		$tablename=substr($classname,  $posSlash+ 1);
106
		return lcfirst($tablename);
107
	}
108
109
	private static function createManyToMany(){
110
		foreach (self::$classes as $table=>$class){
111
			if($class->isAssociation()===true){
112
				$members=$class->getManyToOneMembers();
113
				if(sizeof($members)==2){
114
					$manyToOne1=$members[0]->getManyToOne();
115
					$manyToOne2=$members[1]->getManyToOne();
116
					$table1=self::getTableName($manyToOne1->className);
117
					$table2=self::getTableName($manyToOne2->className);
118
					$class1=self::$classes[$table1];
119
					$class2=self::$classes[$table2];
120
					$joinTable1=self::getJoinTableArray($class1, $manyToOne1);
121
					$joinTable2=self::getJoinTableArray($class2, $manyToOne2);
122
					$class1->addManyToMany($table2."s", $manyToOne2->className, $table1."s", $table,$joinTable1,$joinTable2);
123
					$class1->removeMember($table."s");
124
125
					$class2->addManyToMany($table1."s", $manyToOne1->className, $table2."s", $table,$joinTable2,$joinTable1);
126
					$class2->removeMember($table."s");
127
					unset(self::$classes[$table]);
128
				}else{
129
					return;
130
				}
131
			}
132
		}
133
	}
134
135
	private static function getJoinTableArray(Model $class,JoinColumnAnnotation $joinColumn){
136
		$pk=$class->getPrimaryKey();
137
		$fk=$joinColumn->name;
138
		$dFk=$class->getDefaultFk();
139
		if($fk!==$dFk){
140
			if($pk!==null && $fk!==null && $pk!==null)
141
				return ["name"=>$fk, "referencedColumnName"=>$pk];
142
		}
143
		return [];
144
	}
145
146
	private static function getTablesName(){
147
		$sql = 'SHOW TABLES';
148
			$query = self::$pdoObject->query($sql);
149
			return $query->fetchAll(\PDO::FETCH_COLUMN);
150
	}
151
152
	private static function getFieldsInfos($tableName) {
153
		$fieldsInos=array();
154
		$recordset = self::$pdoObject->query("SHOW COLUMNS FROM `{$tableName}`");
155
		$fields = $recordset->fetchAll(\PDO::FETCH_ASSOC);
156
		foreach ($fields as $field) {
157
			$fieldsInos[$field['Field']] = ["Type"=>$field['Type'],"Nullable"=>$field["Null"]];
158
		}
159
		return $fieldsInos;
160
	}
161
162
	private static function getPrimaryKeys($tableName){
163
		$fieldkeys=array();
164
		$recordset = self::$pdoObject->query("SHOW KEYS FROM `{$tableName}` WHERE Key_name = 'PRIMARY'");
165
		$keys = $recordset->fetchAll(\PDO::FETCH_ASSOC);
166
		foreach ($keys as $key) {
167
			$fieldkeys[] = $key['Column_name'];
168
		}
169
		return $fieldkeys;
170
	}
171
172
	private static function getForeignKeys($tableName,$pkName){
173
		$recordset = self::$pdoObject->query("SELECT *
174
												FROM
175
												 information_schema.KEY_COLUMN_USAGE
176
												WHERE
177
												 REFERENCED_TABLE_NAME = '".$tableName."'
178
												 AND REFERENCED_COLUMN_NAME = '".$pkName."'
179
												 AND TABLE_SCHEMA = '".self::$config["dbName"]."';");
180
		return $recordset->fetchAll(\PDO::FETCH_ASSOC);
181
	}
182
183
	private static function writeFile($filename,$data){
184
		return file_put_contents($filename,$data);
185
	}
186
}
187