%PDF- %PDF-
Direktori : /home/tradesc/www/relax/wp-content/plugins/elementskit-lite/libs/xs-migration/ |
Current File : /home/tradesc/www/relax/wp-content/plugins/elementskit-lite/libs/xs-migration/data-migration.php |
<?php namespace ElementsKit_Lite\Libs\Xs_Migration; abstract class Data_Migration implements Migration_Contract { const SUB_ROUTINE_STATUS_INCOMPLETE = '__incomplete'; const SUB_ROUTINE_STATUS_DONE = '__done'; const GENERIC_STATUS_YES = 'yes'; const GENERIC_STATUS_NO = 'no'; const STATUS_DONE = 'done'; const STATUS_QUEUED = 'queued'; const STATUS_RUNNING = 'running'; const STATUS_FINISHED = 'finished'; const STATUS_INITIATED = 'initiated'; const STATUS_METHOD_PAUSED = 'paused'; const STATUS_METHOD_EXECUTED = 'executed'; const STATUS_METHOD_EXECUTING = 'executing'; private $new_text_domain = 'elementskit-lite'; private $text_domain = 'elementskit-lite'; private $max_iteration = 10; /** * @param $txtDomain * @param $versionFrom * @param $versionTo * * @return mixed */ public function input( $txtDomain, $versionFrom, $versionTo ) { #$versionFrom = '1.1.9'; #$versionTo = '1.2.0'; $optionKey = 'data_migration_' . $txtDomain . '_log'; $from = str_replace( '.', '_', trim( $versionFrom ) ); $to = str_replace( '.', '_', trim( $versionTo ) ); $frm = $this->makeFullVersionKey( $from ); $trm = $this->makeFullVersionKey( $to ); $existingOption = get_option( $optionKey ); if ( empty( $existingOption ) ) { $log = array(); $log[] = 'Migration never has been done for this domain.'; $log[] = 'Initiating migration for version ' . $versionFrom . ' to ' . $versionTo . ' at ' . gmdate( 'Y-m-d H:i:s' ) . ' .'; $log[] = 'Scanning migration file for conversion methods.'; $cStack = $this->getCallStacks( array(), $frm, $trm ); $fn = array(); foreach ( $cStack['stack'] as $item ) { $fn[ $item ] = self::STATUS_QUEUED; } $log[] = 'Execution plan prepared.'; $log[] = 'Execution plan saved into database.'; $existingOption['_func'] = $fn; $existingOption['_log'] = $log; $existingOption['_status'] = self::STATUS_INITIATED; update_option( $optionKey, $existingOption ); return array( 'status' => 'success', 'log' => $existingOption, 'log2' => $cStack, ); } /** * Now we have something saved into database * lets check the status first * */ if ( $existingOption['_status'] == self::STATUS_FINISHED ) { $log = $existingOption['_log']; /** * Now we have to check up-to which version this migration is done */ $up_to = $this->makeFullVersionKey( $existingOption['_last_version_scanned'] ); if ( $up_to < $trm ) { /** * New version released of this plugin * check if anything new need to migrate */ $cStack = $this->getCallStacks( array(), $frm, $trm ); $fn = $existingOption['_func']; $log[] = 'A new version update detected.'; $log[] = 'Scanning for new migration method.'; $found = false; foreach ( $cStack['stack'] as $item ) { if ( isset( $fn[ $item ] ) ) { continue; } $fn[ $item ] = self::STATUS_QUEUED; $found = true; } if ( $found ) { $log[] = 'New conversion method detected.'; $log[] = 'Preparing execution plan.'; $log[] = 'Execution plan saved into database.'; $existingOption['_func'] = $fn; $existingOption['_log'] = $log; $existingOption['_status'] = self::STATUS_INITIATED; update_option( $optionKey, $existingOption ); return array( 'status' => 'success', 'log' => $existingOption, 'log2' => $cStack, ); } else { $log[] = 'No new conversion method detected.'; $log[] = 'Updating the migration plan as finished for version ' . $versionTo . ' at ' . gmdate( 'Y-m-d H:i:s' ) . '.'; $existingOption['_func'] = $fn; $existingOption['_log'] = $log; $existingOption['_status'] = self::STATUS_FINISHED; $existingOption['_last_version_scanned'] = $versionTo; $existingOption['_plan_up_to'] = $trm; update_option( $optionKey, $existingOption ); return array( 'status' => 'success', 'log' => $existingOption, 'log2' => $cStack, ); } } /** * As status is finished and last scanned version is same as the current plugin version * code execution should not come here * If any case it come to this point we are updating the settings */ $log[] = 'In no scenario, execution pointer should not come here [something is wrong...].'; $existingOption['_log'] = $log; $existingOption['_last_version_scanned'] = $versionTo; $existingOption['_plan_up_to'] = $trm; update_option( $optionKey, $existingOption ); return array( 'status' => 'success', 'log' => $existingOption, ); } /** * At this point status of the execution plan is not finished * lets do the work * */ $curExecMethod = ''; $mtdStat = ''; foreach ( $existingOption['_func'] as $mtd => $stat ) { if ( $stat == self::STATUS_METHOD_EXECUTED ) { continue; } $curExecMethod = $mtd; $mtdStat = $stat; break; } if ( empty( $curExecMethod ) ) { /** * All methods has been executed */ $log = $existingOption['_log']; $log[] = 'All conversion method has been executed.'; $log[] = 'Setting the migration plan as finished for version ' . $versionTo . ' at ' . gmdate( 'Y-m-d H:i:s' ) . '.'; $existingOption['_log'] = $log; $existingOption['_status'] = self::STATUS_FINISHED; $existingOption['_last_version_scanned'] = $versionTo; $existingOption['_plan_up_to'] = $trm; update_option( $optionKey, $existingOption ); return array( 'status' => 'success', 'log' => $existingOption, ); } /** * We have a conversion method to run whose status is not executed * */ if ( $mtdStat == self::STATUS_QUEUED ) { $log = $existingOption['_log']; $log[] = 'Conversion method ' . $curExecMethod . ' entered into queue at ' . gmdate( 'Y-m-d H:i:s' ) . '.'; $log[] = '- Conversion method ' . $curExecMethod . ' has entered into execution phase at ' . gmdate( 'Y-m-d H:i:s' ); $fn = $existingOption['_func']; $fn[ $curExecMethod ] = self::STATUS_METHOD_EXECUTING; $existingOption['_func'] = $fn; $existingOption['_log'] = $log; update_option( $optionKey, $existingOption ); return $this->$curExecMethod( $optionKey, $existingOption ); } if ( $mtdStat == self::STATUS_METHOD_EXECUTING ) { return array( 'status' => 'failed', 'msg' => 'Another person already initiated the execution.', 'log' => $existingOption['_log'], ); } if ( $mtdStat == self::STATUS_METHOD_PAUSED ) { $log = $existingOption['_log']; $log[] = '- Conversion method ' . $curExecMethod . ' has entered into executing phase at ' . gmdate( 'Y-m-d H:i:s' ); $fn = $existingOption['_func']; $fn[ $curExecMethod ] = self::STATUS_METHOD_EXECUTING; $existingOption['_func'] = $fn; $existingOption['_log'] = $log; update_option( $optionKey, $existingOption ); return $this->$curExecMethod( $optionKey, $existingOption ); } /** * This is the scenario that never ever should occur */ return array( 'status' => 'failed', 'msg' => 'Overflow', 'log' => array( 'Exiting...data is corrupted.', ), ); } /** * * @param array $data */ public function output( array $data ) { if ( ! empty( $data['option'] ) ) { foreach ( $data['option'] as $opKey => $opVal ) { update_option( $opKey, $opVal ); } } } /** * * @param $versionMap * @param $frm * @param $trm * * @return array */ private function getCallStacks( $versionMap, $frm, $trm ) { $callStack = array(); $conversionMethods = array(); $methods = get_class_methods( $this ); foreach ( $methods as $method ) { if ( substr( $method, 0, 13 ) === 'convert_from_' ) { $conversionMethods[] = $method; $tmp = str_replace( 'convert_from_', '', $method ); $tmp = explode( '_to_', $tmp ); $vl = $this->makeFullVersionKey( $tmp[0] ); $vh = $this->makeFullVersionKey( $tmp[1] ); $versionMap[ $vl ] = $tmp[0]; $versionMap[ $vh ] = $tmp[1]; } } ksort( $versionMap ); foreach ( $versionMap as $k => $v ) { if ( $k >= $frm && $k < $trm ) { $fnc = ''; foreach ( $conversionMethods as $conversionMethod ) { if ( strpos( $conversionMethod, 'convert_from_' . $v ) !== false ) { $fnc = $conversionMethod; break; } } if ( ! empty( $fnc ) ) { $callStack[] = $fnc; } } } return array( 'map' => $versionMap, 'func' => $conversionMethods, 'stack' => $callStack, ); } /** * * @param $string * * @return string */ public function makeFullVersionKey( $string ) { $fr = explode( '_', $string ); $frm = array_map( function( $item ) { return str_pad( $item, 3, '0', STR_PAD_LEFT ); }, $fr ); return implode( '', $frm ); } /** * @return string */ public function getNewTextDomain() { return $this->new_text_domain; } /** * @return string */ public function getTextDomain() { return $this->text_domain; } /** * @return int */ public function getMaxIteration() { return $this->max_iteration; } }