From eec445fcf5e69309b50f65c97905bd7a5d511915 Mon Sep 17 00:00:00 2001 From: snipe Date: Thu, 18 Jul 2019 14:30:18 -0700 Subject: [PATCH] Command to fix custom field unicode conversion differences between PHP versions (#7263) --- .../Commands/ReEncodeCustomFieldNames.php | 126 ++++++++++++++++++ app/Console/Kernel.php | 2 + 2 files changed, 128 insertions(+) create mode 100644 app/Console/Commands/ReEncodeCustomFieldNames.php diff --git a/app/Console/Commands/ReEncodeCustomFieldNames.php b/app/Console/Commands/ReEncodeCustomFieldNames.php new file mode 100644 index 0000000000..14276b1bd3 --- /dev/null +++ b/app/Console/Commands/ReEncodeCustomFieldNames.php @@ -0,0 +1,126 @@ +convertUnicodeDbSlug() is + * - the actual db_column name in the customfields table + * - the physical column name that was created on the assets table + * + * For some people who upgraded their version of PHP, the unicode converter now behaves + * differently in than it did when their custom fields were first created, specifically as it + * relates to handling slashes, ampersands, etc. This can result in the field names no longer + * matching up, as an older version of the PHP extension simply dropped slashes, etc, while the + * newer version of the PHP extension will convert them to underscores. + * + * @return mixed + */ + public function handle() + { + + if ($this->confirm('This will regenerate all of the custom field database fieldnames in your database. THIS WILL CHANGE YOUR SCHEMA AND SHOULD NOT BE DONE WITHOUT MAKING A BACKUP FIRST. Do you wish to continue?')) + { + + /** Get all of the custom fields */ + $fields = CustomField::get(); + + $asset_columns = \DB::getSchemaBuilder()->getColumnListing('assets'); + $custom_field_columns = array(); + + /** Loop through the columns on the assets table */ + foreach ($asset_columns as $asset_column) { + + /** Add ones that start with _snipeit_ to an array for handling */ + if (strpos($asset_column, '_snipeit_') === 0) { + + /** + * Get the ID of the custom field based on the fieldname. + * For example, in _snipeit_mac_address_1, we grab the 1 because we know + * that's the ID of the custom field that created the column. + * Then use that ID as the array key for use comparing the actual assets field name + * and the db_column value from the custom fields table. + */ + $last_part = substr(strrchr($asset_column, "_snipeit_"), 1); + $custom_field_columns[$last_part] = $asset_column; + } + } + + foreach ($fields as $field) { + + $this->info($field->name .' ('.$field->id.') column should be '. $field->convertUnicodeDbSlug().''); + + /** The assets table has the column it should have, all is well */ + if (\Schema::hasColumn('assets', $field->convertUnicodeDbSlug())) + { + $this->info('-- ✓ This field exists - all good'); + + /** + * There is a mismatch between the fieldname on the assets table and + * what $field->convertUnicodeDbSlug() is *now* expecting. + */ + } else { + $this->warn('-- X Field mismatch: updating... '); + + /** Make sure the custom_field_columns array has the ID */ + if (array_key_exists($field->id, $custom_field_columns)) { + + /** + * Update the asset schema to the corrected fieldname that will be recognized by the + * system elsewhere that we use $field->convertUnicodeDbSlug() + */ + \Schema::table('assets', function($table) use ($custom_field_columns, $field) { + $table->renameColumn($custom_field_columns[$field->id], $field->convertUnicodeDbSlug()); + }); + + $this->warn('-- ✓ Field updated from '.$custom_field_columns[$field->id].' to '.$field->convertUnicodeDbSlug()); + + } else { + $this->warn('-- X WARNING: There is no field on the assets table ending in '.$field->id.'. This may require more in-depth investigation and may mean the schema was altered manually.'); + } + } + + /** Update the db_column property in the custom fields table, just in case it doesn't match the other + * things. + */ + $field->db_column = $field->convertUnicodeDbSlug(); + $field->save(); + + + } + + } + + + } +} diff --git a/app/Console/Kernel.php b/app/Console/Kernel.php index d5a97e932e..4de5512f59 100644 --- a/app/Console/Kernel.php +++ b/app/Console/Kernel.php @@ -2,6 +2,7 @@ namespace App\Console; +use App\Console\Commands\ImportLocations; use App\Console\Commands\RestoreDeletedUsers; use Illuminate\Console\Scheduling\Schedule; use Illuminate\Foundation\Console\Kernel as ConsoleKernel; @@ -34,6 +35,7 @@ class Kernel extends ConsoleKernel Commands\RestoreDeletedUsers::class, Commands\SendUpcomingAuditReport::class, Commands\ImportLocations::class, + Commands\ReEncodeCustomFieldNames::class, ]; /**