Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.
Common duplication problems, and corresponding solutions are:
| 1 | <?php |
||
| 23 | class DB implements Insert, Query { |
||
| 24 | use CachesReferences; |
||
| 25 | use CompilesVars; |
||
| 26 | |||
| 27 | /** |
||
| 28 | * @var Connection |
||
| 29 | */ |
||
| 30 | protected $connection; |
||
| 31 | |||
| 32 | 55 | public function __construct(Connection $connection) { |
|
| 35 | |||
| 36 | /** |
||
| 37 | * @return \Doctrine\DBAL\Query\Builder |
||
| 38 | */ |
||
| 39 | 55 | public function builder() { |
|
| 42 | |||
| 43 | // Implementation of Insert interface. |
||
| 44 | |||
| 45 | /** |
||
| 46 | * @inheritdoc |
||
| 47 | */ |
||
| 48 | 49 | public function source_file($name, $content) { |
|
| 49 | 49 | assert('is_string($name)'); |
|
| 50 | 49 | assert('is_string($content)'); |
|
| 51 | 49 | $stmt = $this->builder() |
|
| 52 | 49 | ->insert($this->source_file_table()) |
|
| 53 | 49 | ->values(array |
|
| 54 | ( "name" => "?" |
||
| 55 | 49 | , "line" => "?" |
|
| 56 | 49 | , "source" => "?" |
|
| 57 | 49 | )) |
|
| 58 | 49 | ->setParameter(0, $name); |
|
| 59 | 49 | $line = 1; |
|
| 60 | 49 | foreach (explode("\n", $content) as $source) { |
|
| 61 | $stmt |
||
| 62 | 49 | ->setParameter(1, $line) |
|
| 63 | 49 | ->setParameter(2, $source) |
|
| 64 | 49 | ->execute(); |
|
| 65 | 49 | $line++; |
|
| 66 | 49 | } |
|
| 67 | 49 | } |
|
| 68 | |||
| 69 | /** |
||
| 70 | * @inheritdoc |
||
| 71 | */ |
||
| 72 | 52 | View Code Duplication | public function entity($type, $name, $file, $start_line, $end_line) { |
|
|
|||
| 73 | 52 | assert('\\Lechimp\\Dicto\\Variables\\Variable::is_type($type)'); |
|
| 74 | 52 | assert('is_string($name)'); |
|
| 75 | 52 | assert('is_string($file)'); |
|
| 76 | 52 | assert('is_int($start_line)'); |
|
| 77 | 52 | assert('is_int($end_line)'); |
|
| 78 | 52 | $this->builder() |
|
| 79 | 52 | ->insert($this->entity_table()) |
|
| 80 | 52 | ->values(array |
|
| 81 | ( "type" => "?" |
||
| 82 | 52 | , "name" => "?" |
|
| 83 | 52 | , "file" => "?" |
|
| 84 | 52 | , "start_line" => "?" |
|
| 85 | 52 | , "end_line" => "?" |
|
| 86 | 52 | )) |
|
| 87 | 52 | ->setParameter(0, $type) |
|
| 88 | 52 | ->setParameter(1, $name) |
|
| 89 | 52 | ->setParameter(2, $file) |
|
| 90 | 52 | ->setParameter(3, $start_line) |
|
| 91 | 52 | ->setParameter(4, $end_line) |
|
| 92 | 52 | ->execute(); |
|
| 93 | 52 | return (int)$this->connection->lastInsertId(); |
|
| 94 | } |
||
| 95 | |||
| 96 | /** |
||
| 97 | * @inheritdoc |
||
| 98 | */ |
||
| 99 | 40 | public function reference($type, $name, $file, $line) { |
|
| 100 | 40 | assert('\\Lechimp\\Dicto\\Variables\\Variable::is_type($type)'); |
|
| 101 | 40 | assert('is_string($name)'); |
|
| 102 | 40 | assert('is_string($file)'); |
|
| 103 | 40 | assert('is_int($line)'); |
|
| 104 | 40 | $this->builder() |
|
| 105 | 40 | ->insert($this->reference_table()) |
|
| 106 | 40 | ->values(array |
|
| 107 | ( "type" => "?" |
||
| 108 | 40 | , "name" => "?" |
|
| 109 | 40 | , "file" => "?" |
|
| 110 | 40 | , "line" => "?" |
|
| 111 | 40 | )) |
|
| 112 | 40 | ->setParameter(0, $type) |
|
| 113 | 40 | ->setParameter(1, $name) |
|
| 114 | 40 | ->setParameter(2, $file) |
|
| 115 | 40 | ->setParameter(3, $line) |
|
| 116 | 40 | ->execute(); |
|
| 117 | 40 | return (int)$this->connection->lastInsertId(); |
|
| 118 | } |
||
| 119 | |||
| 120 | /** |
||
| 121 | * @inheritdoc |
||
| 122 | */ |
||
| 123 | 30 | View Code Duplication | public function relation($name, $entity_id, $reference_id, $file, $line) { |
| 124 | 30 | assert('is_string($name)'); |
|
| 125 | 30 | assert('is_int($entity_id)'); |
|
| 126 | 30 | assert('is_int($reference_id)'); |
|
| 127 | 30 | assert('is_string($file)'); |
|
| 128 | 30 | assert('is_int($line)'); |
|
| 129 | 30 | $this->builder() |
|
| 130 | 30 | ->insert($this->relations_table()) |
|
| 131 | 30 | ->values(array |
|
| 132 | ( "name" => "?" |
||
| 133 | 30 | , "entity_id" => "?" |
|
| 134 | 30 | , "reference_id" => "?" |
|
| 135 | 30 | , "file" => "?" |
|
| 136 | 30 | , "line" => "?" |
|
| 137 | 30 | )) |
|
| 138 | 30 | ->setParameter(0, $name) |
|
| 139 | 30 | ->setParameter(1, $entity_id) |
|
| 140 | 30 | ->setParameter(2, $reference_id) |
|
| 141 | 30 | ->setParameter(3, $file) |
|
| 142 | 30 | ->setParameter(4, $line) |
|
| 143 | 30 | ->execute(); |
|
| 144 | 30 | } |
|
| 145 | |||
| 146 | // Naming |
||
| 147 | |||
| 148 | 55 | public function source_file_table() { |
|
| 149 | 55 | return "files"; |
|
| 150 | } |
||
| 151 | |||
| 152 | 55 | public function entity_table() { |
|
| 153 | 55 | return "entities"; |
|
| 154 | } |
||
| 155 | |||
| 156 | 55 | public function reference_table() { |
|
| 157 | 55 | return "refs"; |
|
| 158 | } |
||
| 159 | |||
| 160 | 55 | public function relations_table() { |
|
| 161 | 55 | return "relations"; |
|
| 162 | } |
||
| 163 | |||
| 164 | /** |
||
| 165 | * Initialize REGEXP for sqlite. |
||
| 166 | */ |
||
| 167 | 49 | public function init_sqlite_regexp() { |
|
| 168 | 49 | $pdo = $this->connection->getWrappedConnection(); |
|
| 169 | 49 | if (!($pdo instanceof \PDO)) { |
|
| 170 | throw new \RuntimeException( |
||
| 171 | "Expected wrapped connection to be PDO-object."); |
||
| 172 | } |
||
| 173 | 49 | $pdo->sqliteCreateFunction("regexp", function($pattern, $data) { |
|
| 174 | 25 | return preg_match("%$pattern%", $data) > 0; |
|
| 175 | 49 | }); |
|
| 176 | 49 | } |
|
| 177 | |||
| 178 | // Creation of database. |
||
| 179 | |||
| 180 | 49 | public function maybe_init_database_schema() { |
|
| 191 | |||
| 192 | 55 | public function init_database_schema() { |
|
| 193 | 55 | $schema = new Schema\Schema(); |
|
| 194 | |||
| 195 | 55 | $file_table = $schema->createTable($this->source_file_table()); |
|
| 196 | 55 | $file_table->addColumn |
|
| 197 | 55 | ( "name", "string" |
|
| 198 | 55 | , array("notnull" => true) |
|
| 199 | 55 | ); |
|
| 200 | 55 | $file_table->addColumn |
|
| 295 | } |
||
| 296 |
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.