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