예제 #1
0
		/**
		 * The rollback() function removes the query either from file (MASTER) or from the CDI log (SLAVE)
		 * @param String $hash The MD5 hash created using the SQL statement, the timestamp and the execution order
		 * @param Timestamp $timestamp The UNIX timestamp on which the query was originally logged
		 * @param Integer $order The execution order of the query (in case of multiple executions with the same timestamp)
		 */
		public static function rollback($hash,$timestamp,$order) {
			// do not rollback erronous changes to tbl_cdi_log
			$tbl_prefix = Symphony::Configuration()->get('tbl_prefix', 'database');
			if (preg_match("/{$tbl_prefix}cdi_log/i", $query)) return true;
			
			try {
				if(CdiUtil::isCdiSlave()) {
					// On the SLAVE instance we need to remove the execution log entry from the database
					Symphony::Database()->query("DELETE FROM `tbl_cdi_log` WHERE `query_hash` LIKE '" . $hash . "'");
				} else if(CdiUtil::isCdiMaster()) {
					// On the MASTER instance we need to remove the persisted SQL Statement from disk (if it exists)
					$entries = self::getCdiLogEntries();
					unset($entries[$hash]);
					file_put_contents(CDI_FILE, json_encode($entries));
				} else {
					throw new Exception("Invalid value for the CDI 'mode' configuration option, 'CdiMaster' or 'CdiSlave' expected.");
				}
			} catch(Exception $e) {
				//TODO: think of some smart way of dealing with errors, perhaps through the preference screen or a CDI Status content page?
				//In this case it is perhaps better to simply throw the exception because the rollback failed.
				throw $e;
			}
		}
예제 #2
0
	require_once(EXTENSIONS . '/cdi/lib/class.cdidbsync.php');
	require_once(EXTENSIONS . '/cdi/lib/class.cdidumpdb.php');
	require_once(EXTENSIONS . '/cdi/lib/class.cdilogquery.php');
	require_once(EXTENSIONS . '/cdi/lib/class.cdipreferences.php');
	
	// We should not be processing any queries when the extension is disabled or when we are the Master instance
	if((!class_exists('Administration')) || !CdiUtil::isEnabled()) {
	   	$result["status"] = "error";
	   	$result["message"] = "You can only execute actions from within Symphony and when the CDI extension is enabled";
		Symphony::Log()->pushToLog('[CDI] You can only execute actions from within Symphony and when the CDI extension is enabled', E_NOTICE, true);
	} 
	
	// Clean the database and log files when the cdi_clear action is called
	if(isset($_POST["action"]["cdi_clear"])) {
		try {
			if(CdiUtil::isCdiMaster()) {
				CdiMaster::uninstall();
				CdiMaster::install();
			} else if (CdiUtil::isCdiSlave()) {
				CdiSlave::uninstall();
				CdiSlave::install();
			} else if(CdiUtil::isCdiDBSync()) {
				CdiDBSync::uninstall();
				CdiDBSync::install();
			}
			$result["status"] = 'success';
		} catch(Exception $e) {
			$result["status"] = "error";
			$result["message"] = $e->getMessage();
			Symphony::Log()->pushToLog('[CDI] ' . $e->getMessage(), E_ERROR, true);
		}
예제 #3
0
		public static function appendInstanceMode() {
			$div = new XMLElement('div', NULL, array('class' => 'instanceMode'));
			$div->appendChild(new XMLElement('h3','Instance Mode',array('style' => 'margin: 5px 0;')));
			$label = Widget::Label();
			if(!CdiUtil::isCdiSlave() && !CdiUtil::isCdiDBSyncSlave()) {
				$label->setAttribute('style','position:relative;padding-left:18px;');
			} else {
				$label->setAttribute('style','margin-bottom: 2px;position:relative;padding-left:18px;');
			}
			$input = Widget::Input('settings[cdi][is-slave]', 'yes', 'checkbox');
			$input->setAttribute('style','position:absolute;left:0px;');
			$input->setAttribute('class','instance-mode');
			if(CdiUtil::canBeMasterInstance()) {
				if(CdiUtil::isCdiSlave() || CdiUtil::isCdiDBSyncSlave()) { $input->setAttribute('checked', 'checked'); }
				$label->setValue($input->generate() . ' This is a "Slave" instance (no structural changes will be registered)');
			} else {
				$input->setAttribute('checked', 'checked');
				$input->setAttribute('disabled', 'disabled');
				$label->setValue($input->generate() . ' This can only be a "Slave" instance due to insufficient write permissions.');
			}
			$div->appendChild($label);
			if(CdiUtil::isCdiSlave() || CdiUtil::isCdiDBSyncSlave())
			{
				$label = Widget::Label();
				$label->setAttribute('style','position:relative;padding-left:18px;');
				$input = Widget::Input('settings[cdi][disable_blueprints]', 'yes', 'checkbox');
				$input->setAttribute('style','position:absolute;left:0px;');
				if(CdiUtil::hasDisabledBlueprints()) {
					$input->setAttribute('checked', 'checked');
				}
				$label->setValue($input->generate() . ' Disable structural changes on this instance.');
				$div->appendChild($label);
			}
			if(CdiUtil::isCdiMaster() || CdiUtil::isCdiSlave()) {
				$div->appendChild(new XMLElement('p', 'The extension is designed to allow automatic propagation of structural changes between environments in a DTAP setup.
													   It is imperitive that you have a single "Master" instance (usually your development environment). This is important because the auto-increment values need to be exactly the same on each database table in every environment. 
													   Switching between modes is therefore not recommended. If needed, make sure you only switch instance mode after you have ensured that you have restored all databases from the same source and cleared the CDI logs on all instances.', array('class' => 'help')));
			} else if (CdiUtil::isCdiDBSync()) {
				$div->appendChild(new XMLElement('p', 'The extension is designed to allow manual propagation of structural changes between environments in a DTAP setup.
													   It is imperitive that you have a single "Master" instance (usually your development environment). This is important because the auto-increment values need to be exactly the same on each database table in every environment. 
													   Switching between modes is therefore not recommended. If needed, make sure you only switch instance mode after you have ensured that you have restored all databases from the same source.', array('class' => 'help')));
			}
			$div->appendChild(new XMLElement('p', 'You need to save your changes before you can configure this instance, or reload the page to cancel.<br />Be advised: changing instances mode will reset any instance specific configuration settings', array('class' => 'cdiInstanceRestart', 'style' => 'display:none;')));
			return $div;
		}
예제 #4
0
		public function savePreferences($context){
			if(CdiPreferences::save()) {
				// apply config changes
				if(CdiUtil::isCdiSlave()) { CdiSlave::install(); } 
				else if (CdiUtil::isCdiMaster()) { CdiMaster::install(); }
				else { CdiDBSync::install(); }
			} else {
				Administration::instance()->Page->pageAlert(_('An unknown error occurred while saving preferences for CDI. Your changes have not been saved.'));
				return false;
			}
		}
예제 #5
0
<?php 
	require_once(EXTENSIONS . '/cdi/lib/class.cdiutil.php');
	require_once(EXTENSIONS . '/cdi/lib/class.cdislave.php');

	// We should not be processing any queries when the extension is disabled or when we are the Master instance
	if((!class_exists('Administration')) || !CdiUtil::isEnabled() || (CdiUtil::isCdiMaster() || CdiUtil::isCdiDBSync())) {
		echo "WARNING: You are not calling this page from Symphony, the CDI extension is disabled or you are running the queryies on the Master instance. No queries have been executed.";
	} else {
		$callback = Administration::getPageCallback();
		if(Symphony::Configuration()->get('api_key','cdi') !== $callback['context'][0]){
			echo "WARNING: Invalid API key. The correct key can be found in the configuration page.";
			die();
		}
		else{
			CdiSlave::update();
		}
	}
	
	die();