| Conditions | 8 |
| Paths | 34 |
| Total Lines | 146 |
| Code Lines | 95 |
| Lines | 0 |
| Ratio | 0 % |
| Changes | 10 | ||
| Bugs | 0 | Features | 0 |
Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.
For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.
Commonly applied refactorings include:
If many parameters/temporary variables are present:
| 1 | <?php |
||
| 38 | public function upgrade(): void |
||
| 39 | { |
||
| 40 | // It is simpler to create a new table than to update the existing one. |
||
| 41 | |||
| 42 | if (!DB::schema()->hasTable('place_location')) { |
||
| 43 | DB::schema()->create('place_location', static function (Blueprint $table): void { |
||
| 44 | $table->integer('id', true); |
||
| 45 | $table->integer('parent_id')->nullable(); |
||
| 46 | $table->string('place', 120); |
||
| 47 | $table->double('latitude')->nullable(); |
||
| 48 | $table->double('longitude')->nullable(); |
||
| 49 | |||
| 50 | $table->unique(['parent_id', 'place']); |
||
| 51 | $table->unique(['place', 'parent_id']); |
||
| 52 | |||
| 53 | $table->index(['latitude']); |
||
| 54 | $table->index(['longitude']); |
||
| 55 | }); |
||
| 56 | |||
| 57 | DB::schema()->table('place_location', static function (Blueprint $table): void { |
||
| 58 | $table->foreign(['parent_id']) |
||
| 59 | ->references(['id']) |
||
| 60 | ->on('place_location') |
||
| 61 | ->onDelete('CASCADE') |
||
| 62 | ->onUpdate('CASCADE'); |
||
| 63 | }); |
||
| 64 | } |
||
| 65 | |||
| 66 | if (DB::schema()->hasTable('placelocation')) { |
||
| 67 | DB::table('placelocation') |
||
| 68 | ->where('pl_lati', '=', '') |
||
| 69 | ->orWhere('pl_long', '=', '') |
||
| 70 | ->update([ |
||
| 71 | 'pl_lati' => null, |
||
| 72 | 'pl_long' => null, |
||
| 73 | ]); |
||
| 74 | |||
| 75 | // Missing/invalid parents? Move them to the top level |
||
| 76 | DB::table('placelocation AS pl1') |
||
| 77 | ->leftJoin('placelocation AS pl2', 'pl1.pl_parent_id', '=', 'pl2.pl_id') |
||
| 78 | ->whereNull('pl2.pl_id') |
||
| 79 | ->update([ |
||
| 80 | 'pl1.pl_parent_id' => 0, |
||
| 81 | ]); |
||
| 82 | |||
| 83 | // Remove invalid values. |
||
| 84 | if (DB::connection()->getDriverName() === 'mysql') { |
||
| 85 | DB::table('placelocation') |
||
| 86 | ->where('pl_lati', 'NOT REGEXP', '[^NS][0-9]+[.]?[0-9]*$') |
||
| 87 | ->orWhere('pl_long', 'NOT REGEXP', '[^EW][0-9]+[.]?[0-9]*$') |
||
| 88 | ->update([ |
||
| 89 | 'pl_lati' => '', |
||
| 90 | 'pl_long' => '', |
||
| 91 | ]); |
||
| 92 | } |
||
| 93 | |||
| 94 | // The existing data may have placenames that only differ after the first 120 chars. |
||
| 95 | // Need to remove the constraint before we truncate/merge them. |
||
| 96 | try { |
||
| 97 | DB::schema()->table('placelocation', static function (Blueprint $table): void { |
||
| 98 | $table->dropUnique(['pl_parent_id', 'pl_place']); |
||
| 99 | }); |
||
| 100 | } catch (PDOException $ex) { |
||
| 101 | // Already deleted, or does not exist; |
||
| 102 | } |
||
| 103 | |||
| 104 | DB::table('placelocation') |
||
| 105 | ->update([ |
||
| 106 | 'pl_place' => new Expression('SUBSTR(pl_place, 1, 120)'), |
||
| 107 | ]); |
||
| 108 | |||
| 109 | // The lack of unique key constraints means that there may be duplicates... |
||
| 110 | while (true) { |
||
| 111 | // Two places with the same name and parent... |
||
| 112 | $row = DB::table('placelocation') |
||
| 113 | ->select([ |
||
| 114 | new Expression('MIN(pl_id) AS min'), |
||
| 115 | new Expression('MAX(pl_id) AS max'), |
||
| 116 | ]) |
||
| 117 | ->groupBy(['pl_parent_id', 'pl_place']) |
||
| 118 | ->having(new Expression('COUNT(*)'), '>', '1') |
||
| 119 | ->first(); |
||
| 120 | |||
| 121 | if ($row === null) { |
||
| 122 | break; |
||
| 123 | } |
||
| 124 | |||
| 125 | // ...move children to the first |
||
| 126 | DB::table('placelocation') |
||
| 127 | ->where('pl_parent_id', '=', $row->max) |
||
| 128 | ->update(['pl_parent_id' => $row->min]); |
||
| 129 | |||
| 130 | // ...delete the second |
||
| 131 | DB::table('placelocation') |
||
| 132 | ->where('pl_id', '=', $row->max) |
||
| 133 | ->delete(); |
||
| 134 | } |
||
| 135 | |||
| 136 | // This is the SQL standard. It works with Postgres, Sqlite and MySQL 8 |
||
| 137 | $select1 = DB::table('placelocation') |
||
| 138 | ->leftJoin('place_location', 'id', '=', 'pl_id') |
||
| 139 | ->whereNull('id') |
||
| 140 | ->orderBy('pl_level') |
||
| 141 | ->orderBy('pl_id') |
||
| 142 | ->select([ |
||
| 143 | 'pl_id', |
||
| 144 | new Expression('CASE pl_parent_id WHEN 0 THEN NULL ELSE pl_parent_id END'), |
||
| 145 | 'pl_place', |
||
| 146 | new Expression("CAST(REPLACE(REPLACE(pl_lati, 'S', '-'), 'N', '') AS FLOAT)"), |
||
| 147 | new Expression("CAST(REPLACE(REPLACE(pl_long, 'W', '-'), 'E', '') AS FLOAT)"), |
||
| 148 | ]); |
||
| 149 | |||
| 150 | // This works for MySQL 5.7 and lower, which cannot cast to FLOAT |
||
| 151 | $select2 = DB::table('placelocation') |
||
| 152 | ->leftJoin('place_location', 'id', '=', 'pl_id') |
||
| 153 | ->whereNull('id') |
||
| 154 | ->orderBy('pl_level') |
||
| 155 | ->orderBy('pl_id') |
||
| 156 | ->select([ |
||
| 157 | 'pl_id', |
||
| 158 | new Expression('CASE pl_parent_id WHEN 0 THEN NULL ELSE pl_parent_id END'), |
||
| 159 | 'pl_place', |
||
| 160 | new Expression("REPLACE(REPLACE(pl_lati, 'S', '-'), 'N', '')"), |
||
| 161 | new Expression("REPLACE(REPLACE(pl_long, 'W', '-'), 'E', '')"), |
||
| 162 | ]); |
||
| 163 | |||
| 164 | try { |
||
| 165 | DB::table('place_location') |
||
| 166 | ->insertUsing(['id', 'parent_id', 'place', 'latitude', 'longitude'], $select1); |
||
| 167 | } catch (PDOException $ex) { |
||
| 168 | DB::table('place_location') |
||
| 169 | ->insertUsing(['id', 'parent_id', 'place', 'latitude', 'longitude'], $select2); |
||
| 170 | } |
||
| 171 | |||
| 172 | DB::schema()->drop('placelocation'); |
||
| 173 | } |
||
| 174 | |||
| 175 | // Earlier versions of webtrees used 0 and NULL interchangeably. |
||
| 176 | // Assume 0 at the country-level and NULL at lower levels. |
||
| 177 | DB::table('place_location') |
||
| 178 | ->whereNotNull('parent_id') |
||
| 179 | ->where('latitude', '=', 0) |
||
| 180 | ->where('longitude', '=', 0) |
||
| 181 | ->update([ |
||
| 182 | 'latitude' => null, |
||
| 183 | 'longitude' => null, |
||
| 184 | ]); |
||
| 187 |