Completed
Push — master ( 4e6026...e0b9fa )
by Jean-Christophe
01:30
created

ModelsCreator::connect()   A

Complexity

Conditions 2
Paths 4

Size

Total Lines 13
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

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