public function testCheckin()
 {
     $stateManager = new DIM_StateManager();
     $stateManager->checkIn();
     $this->assertTrue($stateManager->isCheckedIn());
     $this->assertFalse($stateManager->isCheckedOut());
 }
 public function testHandleCheckout()
 {
     $server = new DIM_Server();
     // should fail authentication
     $failRet = $server->handleRequest(array("action" => "checkout", "email" => "test", "auth-key" => "test"));
     $this->assertEquals("0:unauthed", $failRet);
     $mockAuthenticator = $this->getMock("DIM_Authenticator", array("getConfiguration"));
     $mockAuthenticator->expects($this->any())->method("getConfiguration")->will($this->returnValue(array("server" => array("users" => array(array("email" => "test", "auth-key" => "test"))))));
     $server->authenticator = $mockAuthenticator;
     $stateManager = new DIM_StateManager();
     $stateManager->checkIn();
     // should successfully check out
     $successRet = $server->handleRequest(array("action" => "checkout", "email" => "test", "auth-key" => "test"));
     $this->assertEquals("1", $successRet);
     $this->assertTrue($stateManager->isCheckedOut());
 }
 public function logNewQuery($query)
 {
     $stateManager = new DIM_StateManager("client");
     if ($this->getExtensionMode() == "client" && $stateManager->isCheckedOut()) {
         $tblPrefix = $this->databaseInfo["tbl_prefix"];
         /* FILTERS */
         //Shamelessly stolen from: https://github.com/remie/CDI/blob/master/lib/class.cdilogquery.php
         // do not register changes to tbl_database_migrations
         if (preg_match("/{$tblPrefix}database_migrations/i", $query)) {
             return true;
         }
         // only structural changes, no SELECT statements
         if (!preg_match('/^(insert|update|delete|create|drop|alter|rename)/i', $query)) {
             return true;
         }
         // un-tracked tables (sessions, cache, authors)
         if (preg_match("/{$tblPrefix}(authors|cache|forgotpass|sessions|tracker_activity|symphony_cart)/i", $query)) {
             return true;
         }
         // content updates in tbl_entries (includes tbl_entries_fields_*)
         if (preg_match('/^(insert|delete|update)/i', $query) && preg_match("/({$tblPrefix}entries)/i", $query)) {
             return true;
         }
         //content update in search index / similar
         if (preg_match("/{$tblPrefix}(search_index|search_index_entry_keywords|search_index_keywords|search_index_logs)/i", $query) && preg_match('/^(insert|delete|update)/i', $query)) {
             return true;
         }
         // append query delimeter if it doesn't exist
         if (!preg_match('/;$/', $query)) {
             $query .= ";";
         }
         if ($query != "") {
             file_put_contents($this->getQueryCacheFilename(), $query . "\r\n", FILE_APPEND);
         }
     }
 }
    private function __indexPage()
    {
        $link = new XMLElement('link');
        $this->addElementToHead($link, 500);
        $this->setPageType('form');
        $this->appendSubheading(__('Database Integration Manager'));
        // Checkout/in?
        if (isset($_GET["try"])) {
            $client = new DIM_Client();
            $errorStr = "";
            switch ($_GET["try"]) {
                case "checkout":
                    if ($client->requestCheckout($errorStr)) {
                        redirect('?message=checkout-success');
                    } else {
                        $this->pageAlert(__("Checkout Failed - '{$errorStr}'"), Alert::ERROR);
                    }
                    break;
            }
        }
        if (isset($_GET["message"])) {
            switch ($_GET['message']) {
                case "checkout-success":
                    $this->pageAlert(__('Database Checkout Out Successfully'), Alert::SUCCESS);
                    break;
                case "commit-success":
                    $this->pageAlert(__('Database Checked In Successfully'), Alert::SUCCESS);
                    break;
                case "update-success":
                    $this->pageAlert(__('Database Updated Successfully'), Alert::SUCCESS);
                    break;
            }
        }
        // Get the saved settings from the file - this will populate $savedSettings
        $savedSettings = $this->config->getConfiguration();
        /***************************************
        		
        			!Mode Selector
        			
        		***************************************/
        // The mode is the 'picker' - nice UI and also necessary for validation functioning
        //Should the mode be locked or not
        $modeLocked = $savedSettings && ($savedSettings['mode']['mode'] == $_POST['settings']['mode']['mode'] || !isset($_POST['settings']['mode']['mode']));
        // Build the 'Mode' fieldset
        $modeFieldset = new XMLElement('fieldset', '', array('class' => 'settings picker'));
        $modeFieldset->appendChild(new XMLElement('legend', __("Mode")));
        $modeSelectorLabel = Widget::Label("Mode");
        //fill with POST data if possible
        $modeSelected = '';
        if (isset($_POST['settings']['mode']['mode'])) {
            $modeSelected = $_POST['settings']['mode']['mode'];
        } elseif (isset($savedSettings['mode']['mode'])) {
            $modeSelected = $savedSettings['mode']['mode'];
        }
        $modeSelectorOptions = array(array("disabled", $modeSelected == "disabled", "Disabled"), array("client", $modeSelected == "client", "Client"), array("server", $modeSelected == "server", "Server"));
        $selectOptions = array("id" => "mode-selector");
        if ($modeLocked) {
            $selectOptions["disabled"] = "disabled";
        }
        $modeSelectorLabel->appendChild(Widget::Select("settings[mode][mode]", $modeSelectorOptions, $selectOptions));
        $modeWrapper = new XMLElement('div', new XMLElement('div', $modeSelectorLabel, array('class' => 'column')), array('class' => 'two columns'));
        if ($modeLocked) {
            // The enabler button
            $modeChangerLabel = Widget::Label("Mode Currently Locked");
            $modeChangerLabel->appendChild(new XMLElement('br'));
            $modeChangerLabel->appendChild(Widget::Input("mode-enabler", "Allow Mode to Be Changed", "button", array("id" => "mode-enabler", "class" => "button")));
            $modeWrapper->appendChild(new XMLElement('div', $modeChangerLabel, array('class' => 'column')));
            // The enabler script
            $this->Form->appendChild(new XMLElement('script', 'jQuery(document).ready(function(){jQuery("#mode-enabler").click(function() {  jQuery("#mode-selector").removeAttr("disabled"); jQuery(this).parent().hide(); });});'));
        }
        $modeFieldset->appendChild($modeWrapper);
        $this->Form->appendChild($modeFieldset);
        $this->Form->appendChild(new XMLElement('script', 'jQuery(document).ready(function(){jQuery("#mode-selector").symphonyPickable();});'));
        // These below are the 'pickable' blocks
        /***************************************
        		
        			!Client Settings
        			
        		***************************************/
        //Build an array of settings so that the form can be prepopulated with settings || $_POST
        if (is_array($savedSettings['client'])) {
            $clientSettings = $savedSettings['client'];
        } else {
            $clientSettings = array();
        }
        //fill the form with post data if possible
        if (is_array($_POST['settings']['client'])) {
            foreach ($_POST['settings']['client'] as $cKey => $cVal) {
                if (!array_key_exists($cKey, $clientSettings)) {
                    $clientSettings[$cKey] = $cVal;
                }
            }
        }
        //an encompassing object for the entire client settings
        $clientWrapper = new XMLElement('div', '', array('id' => 'client', "class" => "pickable", 'style' => 'border-top: 1px solid rgba(0, 0, 0, 0.1);'));
        //Check in / out interface
        if ($savedSettings && $savedSettings['mode']['mode'] == 'client') {
            $clientActionFieldset = new XMLElement('fieldset', '', array('class' => 'settings'));
            $clientActionFieldset->appendChild(new XMLElement('legend', __('Status')));
            $stateManager = new DIM_StateManager("client");
            $stateText = "";
            $linkText = "";
            if ($stateManager->isCheckedOut()) {
                $stateText = "Checked Out";
                $linkText = "<a class='button' href='" . SYMPHONY_URL . "/extension/database_integration_manager/commit'>Check In</a>";
            } else {
                $stateText = "Checked In";
                $linkText = "<a class='button' href='?try=checkout'>Check Out</a>";
            }
            $clientActionFieldset->appendChild(new XMLElement('div', "{$linkText} &nbsp;&nbsp;&nbsp;&nbsp; Current State: <strong>{$stateText}</strong>", array("class" => "frame")));
            $clientWrapper->appendChild($clientActionFieldset);
        }
        //Client Authentication Settings
        $clientFieldset = new XMLElement('fieldset', '', array('class' => 'settings'));
        $clientFieldset->appendChild(new XMLElement('legend', __('Client')));
        $liveServerUrlLabel = Widget::Label("Live Server Host or IP (can append a subdirectory if required)");
        $liveServerUrlLabel->appendChild(Widget::Input("settings[client][server-host]", $clientSettings["server-host"]));
        $emailAddressLabel = Widget::Label("Email Address");
        $emailAddressLabel->appendChild(Widget::Input("settings[client][user-email]", $clientSettings["user-email"]));
        $authKeyLabel = Widget::Label("Authentication Key");
        $authKeyLabel->appendChild(Widget::Input("settings[client][auth-key]", $clientSettings["auth-key"]));
        $clientFieldWrapper = new XMLElement('div');
        $clientFieldWrapper->appendChild($liveServerUrlLabel);
        $clientCredentials = new XMLElement('div', '', array('class' => 'two columns'));
        $clientCredentials->appendChild(new XMLElement('div', $emailAddressLabel, array('class' => 'column', 'style' => 'margin-bottom: 0px;')));
        $clientCredentials->appendChild(new XMLElement('div', $authKeyLabel, array('class' => 'column', 'style' => 'margin-bottom: 0px;')));
        $clientFieldWrapper->appendChild($clientCredentials);
        //see if error
        if (isset($_POST['error']) && $_POST['settings']['mode']['mode'] == 'client') {
            $clientFieldWrapper->setAttribute('class', 'invalid');
            $clientFieldWrapper->appendChild(new XMLElement('p', 'Invalid Settings: Please reconfigure'));
        }
        $clientFieldset->appendChild($clientFieldWrapper);
        $clientWrapper->appendChild($clientFieldset);
        $this->Form->appendChild($clientWrapper);
        /***************************************
        		
        			!Server Settings
        			
        		***************************************/
        $serverFieldset = new XMLElement('fieldset');
        $serverFieldset->setAttribute("class", "settings pickable");
        $serverFieldset->setAttribute("id", "server");
        $stateManager = new DIM_StateManager("server");
        $stateText = $stateManager->isCheckedOut() ? "Checked Out" : "Checked In";
        $serverFieldset->appendChild(new XMLElement('div', "<a class='button' href='log'>View Log</a> &nbsp;&nbsp;&nbsp;&nbsp; Current State: <strong>{$stateText}</strong>", array("class" => "frame", "style" => "padding: 20px;")));
        $this->Form->appendChild(new XMLElement('script', 'jQuery(document).ready(function(){
					jQuery("#users-duplicator").symphonyDuplicator({
						orderable: true, 
						collapsible: true
					});
					
					//jQuery("li.field-user.instance").addClass("collapsed").find("div.content").hide();
					
				});				
			'));
        $serverUserFrame = new XMLElement('div');
        $usersWrapper = new XMLElement('div', null, array('class' => 'frame', 'id' => 'users-duplicator'));
        $usersWrapper->setAttribute('data-add', __('Add User'));
        $usersWrapper->setAttribute('data-remove', __('Remove User'));
        $ol = new XMLElement('ol');
        if (is_array($savedSettings["server"]["users"])) {
            foreach ($savedSettings["server"]["users"] as $u) {
                $ol->appendChild($this->__getUserInputBlock($u));
            }
        }
        // append the template
        $ol->appendChild($this->__getUserInputBlock(array(), true));
        $usersWrapper->appendChild($ol);
        $serverUserFrame->appendChild($usersWrapper);
        $serverFieldset->appendChild($serverUserFrame);
        $this->Form->appendChild($serverFieldset);
        /***************************************
        		
        			!Default Settings
        			
        		***************************************/
        // Default/Disabled Settings Block
        $disabledFieldset = new XMLElement('div', '', array('class' => 'pickable', 'id' => 'disabled'));
        $this->Form->appendChild($disabledFieldset);
        // Add the 'Save' button
        $saveDiv = new XMLElement('div');
        $saveDiv->setAttribute('class', 'actions');
        $saveDiv->appendChild(Widget::Input('action[save]', __('Save Settings'), 'submit', array('accesskey' => 's')));
        $this->Form->appendChild($saveDiv);
    }
 public function modifyNavigation(&$navigation)
 {
     if ($this->config->isExtensionConfigured()) {
         switch ($this->config->getExtensionMode()) {
             case "client":
                 $stateManager = new DIM_StateManager("client");
                 if (!$stateManager->isCheckedOut()) {
                     // clear out the blueprints
                     $navigation["navigation"][200] = array();
                     //remove extensions menu item
                     foreach ($navigation["navigation"][100]['children'] as $key => $val) {
                         if ($val['link'] == '/system/extensions/') {
                             $navigation["navigation"][100]['children'][$key]['visible'] = 'no';
                         }
                     }
                 }
                 break;
             case "server":
                 // clear out the blueprints
                 $navigation["navigation"][200] = array();
                 //remove extensions menu item
                 foreach ($navigation["navigation"][100]['children'] as $key => $val) {
                     if ($val['link'] == '/system/extensions/') {
                         $navigation["navigation"][100]['children'][$key]['visible'] = 'no';
                     }
                 }
                 break;
             case "disabled":
                 // we're disabled - don't do anything!
                 break;
         }
     } else {
         // clear all navigation items - the user will be able to get to the config via the alert.
         $navigation["navigation"] = array();
     }
 }