SHAREYOURCART_BUTTON_JS .= '?v='. $this->getConfigValue('api_version'); $this->SHAREYOURCART_BUTTON_URL .= '?client_id='. $this->getClientId(); //set the language SyC::setLanguage($this->getConfigValue('lang')); } /** * Execute NonQuery SQL * @param string action * @param string extra * @return boolean */ protected abstract function executeNonQuery($sql); /** * * Get the row returned from the SQL * * @return an associative array containing the data of the row OR NULL * if there is none */ protected abstract function getRow($sql); /** * Abstract getTableName * @param string key * */ protected abstract function getTableName($key); /** * Abstract setConfigValue * @param string option * @param string value * @return boolean */ protected abstract function setConfigValue($field, $value); /** * Abstract setConfigValue * @param string option * @param string value * @return string */ protected abstract function getConfigValue($field); /** * Description: This returns an array with the details of the product * displayed on this page. If it is not a product, it * will return FALSE * @remarks this will be mostly used by LITE integrations, so no need to make it mandatory * @param null * @return boolean / array */ protected function getCurrentProductDetails(){ return FALSE; } /** * * Return TRUE if this page describes a single product, otherwise FALSE * */ protected abstract function isSingleProduct(); /** * * Return the URL to be called when the button is pressed * */ protected abstract function getButtonCallbackURL(); /* * * Create url for the specified file. The file must be specified in relative path * to the base of the plugin */ protected abstract function createUrl($file); /** * * Called after the session has been reloaded * */ protected abstract function loadSessionData(); /** * * Returns the plugin's secret key. This should be overwritten only by the actual plugin * */ protected abstract function getSecretKey(); /** * * Insert a row in the table * @param string tableName * @param array data * */ protected abstract function insertRow($tableName, $data); /** * * Apply the coupon code * */ protected abstract function applyCoupon($coupon_code); /** * * Get the plugin version. * @return an integer * */ protected abstract function getPluginVersion(); /** * * Get the entire Version, including the SDK one * */ public function getVersion() { //make sure a developer enters only a number as a version if(!is_int($minor_version = $this->getPluginVersion())) throw new Exception(SyC::t('sdk','The Plugin Version must be an integer')); return self::$_SDK_VERSION.'.'.$minor_version; } /** * * Return TRUE if there is a newer version of the plugin * */ protected function hasNewerVersion() { return version_compare($this->getVersion(),$this->getConfigValue('latest_version'),'<'); } /** * * Check if this instance can load, or not! * This is ment so that at ALL times, only the latest plugin version will work * */ protected function canLoad() { $v = version_compare($this->getVersion(),$this->getConfigValue('plugin_current_version')); //first, check if this instance is the latest one, or not if($v < 0) return false; //save the latest version, for later reference if($v > 0 ) $this->setConfigValue('plugin_current_version',$this->getVersion()); return true; } /** * install the plugin * @param null * @return boolean */ public function install(&$message = null) { //this is a single call function if (!$this->isFirstCall(__FUNCTION__)) return; //create the tokens table $this->createTable($this->getTableName('shareyourcart_tokens'), array( 'id' => 'int(11)', 'token' => 'varchar(255)', 'session_id' => 'varchar(255)', ), 'id'); //create the coupon log table $this->createTable($this->getTableName('shareyourcart_coupons'), array( 'id' => 'int(11)', 'token' => 'varchar(255)', 'coupon_id' => 'varchar(255)', ), 'id'); //save the DB version, for later use $this->setConfigValue('db_version', self::$_DB_VERSION); //if we have credentials in the DB, try to activate the plugin //with them $activated = false; $appKey = $this->getAppKey(); $clientId = $this->getClientId(); if(!empty($appKey) && !empty($clientId)){ $activated = $this->activate($message); } return true; } /** * uninstall the plugin * @param null * @return boolean */ public function uninstall(&$message = null) { //this is a single call function if (!$this->isFirstCall(__FUNCTION__)) return; //first, make sure we deactivate the plugin $this->deactivate($message); //remove the tables $this->dropTable($this->getTableName('shareyourcart_tokens')); $this->dropTable($this->getTableName('shareyourcart_coupons')); //remove the db version $this->setConfigValue('db_version', null); return true; } /** * activate the plugin * @param null * @return boolean */ public function activate(&$message = null) { //this is a single call function if (!$this->isFirstCall(__FUNCTION__)) return; //active the API if ($this->setAccountStatus($this->getSecretKey(), $this->getClientID(), $this->getAppKey(), true, $message) === TRUE) { $this->setConfigValue("account_status", "active"); return true; } else { $this->setConfigValue("account_status", "inactive"); return false; } } /** * deactivate the plugin * @param null * @return boolean */ public function deactivate(&$message = null) { //send the notification to the API $this->setAccountStatus($this->getSecretKey(), $this->getClientID(), $this->getAppKey(), false, $message); //no matter what the API says, disable this plugin $this->setConfigValue("account_status", "inactive"); return true; } /** * getAppKey * @param null * @return appKey */ public function getAppKey() { return $this->getConfigValue('appKey'); } /** * getClientID * @param null * @return clientID */ public function getClientId() { return $this->getConfigValue('clientId'); } /** * Check if the plugin is active, or not * @param null * @return boolean */ public function isActive() { return ($this->getConfigValue('account_status') == "active"); } /** * startSession * @param string $params * @return boolean */ public function startSession($params) { //make sure the params contain the required entries if (!isset($params['app_key'])) $params['app_key'] = $this->getAppKey(); if (!isset($params['client_id'])) $params['client_id'] = $this->getClientId(); //create a new session $data = parent::startSession($params); //save session details $this->insertRow($this->getTableName('shareyourcart_tokens'), $data); //we can't rely on the fact that the row has been inserted, so check! if($this->getSessionId($data['token']) === null) throw new Exception(SyC::t('sdk','Token cannot be saved. Check your "{table_name}" table permissions.', array('{table_name}' => $this->getTableName('shareyourcart_tokens')))); return true; } /** * ensureCouponIsValid * @param string $params * @return boolean */ public function assertCouponIsValid($token, $coupon_code, $coupon_value, $coupon_type) { //first call the parent function parent::assertCouponIsValid($token, $coupon_code, $coupon_value, $coupon_type); //get the session_id associated with the token $session_id = $this->getSessionId($token); //make sure the session is valid if ($session_id === null) { throw new Exception(SyC::t('sdk','Token not found')); } //resume the session session_destroy(); session_id($session_id); session_start(); $this->loadSessionData(); } /** * simply show the button * @param null * @return boolean */ public function showButton() { echo $this->getButton(); } /** * * get the button code * */ public function getButton() { //make sure the API is active if(!$this->isActive()) return; return $this->renderButton($this->getButtonCallbackURL()); } /** * renderButton * @param null * @return boolean */ protected function renderButton($callback_url) { ob_start(); $current_button_type = $this->getConfigValue("button_type"); $button_html = $this->getConfigValue("button_html"); $button_img = $this->getConfigValue("btn-img"); $button_img_width = $this->getConfigValue("btn-img-width"); $button_img_height = $this->getConfigValue("btn-img-height"); $button_img_hover = $this->getConfigValue("btn-img-h"); $button_img_hover_width = $this->getConfigValue("btn-img-h-width"); $button_img_hover_height = $this->getConfigValue("btn-img-h-height"); switch ($current_button_type) { case '1': include(dirname(__FILE__) . '/views/button.php'); break; case '2': include(dirname(__FILE__) . '/views/button-img.php'); break; case '3': include(dirname(__FILE__) . '/views/button-custom.php'); break; default: include(dirname(__FILE__) . '/views/button.php'); break; } return ob_get_clean(); } /** * * show the button on a product page * */ public function showProductButton() { echo $this->getProductButton(); } /** * * get the button for a product page * */ public function getProductButton() { if($this->isSingleProduct() && !$this->getConfigValue('hide_on_product')){ return $this->getButton(); } //else return nothing return null; } /** * * show the button on a cart page * */ public function showCartButton() { echo $this->getCartButton(); } /** * * get the button for the cart page * */ public function getCartButton() { if(!$this->getConfigValue('hide_on_checkout')){ return $this->getButton(); } //return nothing return null; } /** * * Simply show the page header * */ public function showPageHeader() { echo $this->getPageHeader(); } /** * Get the page header code * @param null * @return boolean */ public function getPageHeader() { //this is a single call function if (!$this->isFirstCall(__FUNCTION__)) return; $data = $this->getCurrentProductDetails(); ob_start(); include(dirname(__FILE__) . '/views/page-header.php'); return ob_get_clean(); } /** * Show the admin header code * @param null * @return boolean */ public function showAdminHeader() { echo $this->getAdminHeader(); } /** * Get the admin header code * @param null * @return boolean */ public function getAdminHeader() { //this is a single call function if (!$this->isFirstCall(__FUNCTION__)) return; //check the SDK status $this->checkSDKStatus(true); //for a check, as the admin might have changed the language in the configure page, so we need to sync with it ob_start(); include(dirname(__FILE__) . '/views/admin-header.php'); return ob_get_clean(); } /** * show the admin page * @param null * @return boolean */ public function showAdminPage($html='',$show_header=TRUE,$show_footer=TRUE) { echo $this->getAdminPage($html,$show_header,$show_footer); } /** * * get the admin page * */ public function getAdminPage($html='',$show_header=TRUE,$show_footer=TRUE) { //this is a single call function if (!$this->isFirstCall(__FUNCTION__)) return; $status_message = ''; $refresh = false; //check if this is a post for this particular page if ($_SERVER['REQUEST_METHOD'] == 'POST' && !empty($_POST['syc-account-form'])) { $this->setConfigValue('appKey', $_POST['app_key']); $this->setConfigValue('clientId', $_POST['client_id']); //it is vital that we call the activation API here, to make sure, that the account is ACTIVE //call the account status function $message = ''; if ($this->activate($message) == true) { $status_message = SyC::t('sdk','Account settings successfully saved'); } else { //the account did not activate, so show the error $status_message = $message; } //since we might have changed the status, REFRESH $refresh = true; } //the user decided to disable the API else if ($_SERVER['REQUEST_METHOD'] == 'POST' && !empty($_POST['disable-API'])){ $this->deactivate($status_message); //since we might have changed the status, REFRESH $refresh = true; } //the user decided to activate the API else if ($_SERVER['REQUEST_METHOD'] == 'POST' && !empty($_POST['enable-API'])){ $this->activate($status_message); //since we might have changed the status, REFRESH $refresh = true; } //check if the user want's to recover his account else if (@$_REQUEST['syc-account'] === 'recover'){ //by default, show the form if we are here $show_form = true; if($_SERVER['REQUEST_METHOD'] == 'POST' && !empty($_POST['syc-recover-account'])) { //try to recover if the user posted the form $show_form = !$this->recover($this->getSecretKey(), @$_REQUEST['domain'], @$_REQUEST['email'], $status_message); } //if we need to show the form if($show_form) { //if there is a message, put the form on a new line if(!empty($status_message)) $status_message .= "

"; ob_start(); include(dirname(__FILE__) . '/views/account-recover-partial.php'); $status_message .= ob_get_clean(); } else { //Refresh in order to get rid of the GET parameter $refresh = true; } } else if (@$_REQUEST['syc-account'] === 'create'){ //by default, show the form if we are here $show_form = true; if($_SERVER['REQUEST_METHOD'] == 'POST' && !empty($_POST['syc-create-account'])) { //first, check if the user has agreed to the terms and conditions if(isset($_POST['syc-terms-agreement'])) { //try to create the account if the user posted the form if (!(($register = $this->register($this->getSecretKey(), @$_REQUEST['domain'], @$_REQUEST['email'], $status_message)) === false)) { $this->setConfigValue('appKey', @$register['app_key']); $this->setConfigValue('clientId', @$register['client_id']); $this->setConfigValue("account_status", "active"); $show_form = false; //no need to show the register form anymore //since we might have changed the status, REFRESH $refresh = true; } } else { $status_message = SyC::t('sdk',"Error. You must agree with the terms and conditions bellow"); } } //if we need to show the form if($show_form) { //if there is a message, put the form on a new line if(!empty($status_message)) $status_message .= "

"; ob_start(); include(dirname(__FILE__) . '/views/account-create-partial.php'); $status_message .= ob_get_clean(); } } //make sure there is a session variable setup session_start(); //since switching the API status has a great impact on how the UI looks, refresh the page //just to make sure the UI is using the latest value if($refresh) { //first, save the status message $_SESSION['_syc_status_message'] = $status_message; //recreate the url ( but before that make sure there is no syc-account parameter in it ) unset($_GET['syc-account']); $url = '?'.http_build_query($_GET,'','&'); @header("HTTP/1.1 302 Found"); @header("Location: $url"); echo ""; //it can happen that the headers have allready been sent, so use the html version as well exit; } //if there is a status message if(!empty($_SESSION['_syc_status_message'])) { $status_message = $_SESSION['_syc_status_message']; unset($_SESSION['_syc_status_message']); } // Display the view ob_start(); include(dirname(__FILE__) . '/views/admin-page.php'); return ob_get_clean(); } /** * * show page to customize the button * */ public function showButtonCustomizationPage($html='',$show_header=TRUE,$show_footer=TRUE) { echo $this->getButtonCustomizationPage($html,$show_header,$show_footer); } /** * * get the page to customize the button * */ public function getButtonCustomizationPage($html='',$show_header=TRUE,$show_footer=TRUE){ //if visual settings are submitted if ($_SERVER['REQUEST_METHOD'] == 'POST' && !empty($_POST['syc-visual-form'])) { //set the button declaration $this->setConfigValue("button_type", $_POST['button_type']); //set the button skin $this->setConfigValue("button_skin", $_POST['button_skin']); //set the button position $this->setConfigValue("button_position", $_POST['button_position']); //set the button height $this->setConfigValue("dont_set_height", empty($_POST['show_on_single_row'])); //set the button html $this->setConfigValue("button_html", rawurldecode($_POST['button_html'])); //set the show $this->setConfigValue("hide_on_product", empty($_POST['show_on_product'])); //set the show' $this->setConfigValue("hide_on_checkout", empty($_POST['show_on_checkout'])); if($_FILES["button-img"]["name"]!='') { $target_path = dirname(__FILE__). "/img/"; $target_path = $target_path . 'button-img.png'; if(file_exists($target_path)) unlink($target_path); list($width, $height, $type, $attr) = getimagesize($_FILES['button-img']['tmp_name']); if (move_uploaded_file($_FILES['button-img']['tmp_name'], $target_path)) { //set the button img $this->setConfigValue("btn-img", $this->createUrl($target_path)); $this->setConfigValue("btn-img-width", $width); $this->setConfigValue("btn-img-height", $height); } } if($_FILES["button-img-hover"]["name"]!='') { $target_path = dirname(__FILE__). "/img/"; $target_path = $target_path . 'btn-img-hover.png'; if(file_exists($target_path)) unlink($target_path); list($width, $height, $type, $attr) = getimagesize($_FILES['button-img-hover']['tmp_name']); if(move_uploaded_file($_FILES['button-img-hover']['tmp_name'], $target_path)) { //set the show' $this->setConfigValue("btn-img-h", $this->createUrl($target_path)); $this->setConfigValue("btn-img-h-width", $width); $this->setConfigValue("btn-img-h-height", $height); } } $status_message = SyC::t('sdk','Button settings successfully updated.'); } $current_button_type = $this->getConfigValue("button_type"); $current_skin = $this->getConfigValue("button_skin"); $current_position = $this->getConfigValue("button_position"); $show_on_checkout = !$this->getConfigValue("hide_on_checkout"); $show_on_product = !$this->getConfigValue("hide_on_product"); $show_on_single_row = !$this->getConfigValue("dont_set_height"); $button_html = $this->getConfigValue("button_html"); $button_img = $this->getConfigValue("btn-img"); $button_img_hover = $this->getConfigValue("btn-img-h"); //render the view ob_start(); include(dirname(__FILE__) . '/views/button-settings-page.php'); return ob_get_clean(); } /** * showDocumentation * @param null * @return boolean */ public function showDocumentationPage($html='',$show_header=TRUE,$show_footer=TRUE) { echo $this->getDocumentationPage($html,$show_header,$show_footer); } /** * get the documentation page * @param null * @return boolean */ public function getDocumentationPage($html='',$show_header=TRUE,$show_footer=TRUE) { //this is a single call function if (!$this->isFirstCall(__FUNCTION__)) return; $action_url = $this->getButtonCallbackURL(); //render the view ob_start(); include(dirname(__FILE__) . '/views/documentation.php'); return ob_get_clean(); } /** * show the update notification * @param null */ public function showUpdateNotification(){ echo $this->getUpdateNotification(); } /** * get the update notification * @param null */ public function getUpdateNotification(){ //render the view ob_start(); include(dirname(__FILE__) . '/views/update-notification-partial.php'); return ob_get_clean(); } /* * * Called when a new coupon is generated * */ public function couponCallback() { try { /* * ********* Check input parameters ******************************* */ if (!isset($_POST['token'], $_POST['coupon_code'], $_POST['coupon_value'], $_POST['coupon_type'])) { throw new Exception(SyC::t('sdk','At least one of the parameters is missing. Received: {data}', array('{data}' => print_r($_POST, true)))); } //make sure the coupon is valid $this->assertCouponIsValid($_POST['token'], $_POST['coupon_code'], $_POST['coupon_value'], $_POST['coupon_type']); //save the coupon $this->saveCoupon($_POST['token'], $_POST['coupon_code'], $_POST['coupon_value'], $_POST['coupon_type']); //check if the coupon is intended to be applied to the current cart if (empty($_POST['save_only'])) { $this->applyCoupon($_POST['coupon_code']); } } catch (Exception $e) { header("HTTP/1.0 403"); echo $e->getMessage(); } } /** * Save the coupon * @param null * @return boolean */ protected function saveCoupon($token, $coupon_code, $coupon_value, $coupon_type) { //add the coupon id in shareyourcart coupons table $data = array( 'token' => $token, 'coupon_id' => $coupon_code, ); $this->insertRow($this->getTableName('shareyourcart_coupons'), $data); } /** * * Based on the token, get the session_id * */ protected function getSessionId($token) { $result = $this->getRow("SELECT session_id FROM " . $this->getTableName('shareyourcart_tokens') . " WHERE token='$token'"); return isset($result) ? $result['session_id'] : null; } /** * * createTable * @param table * @param array columns * @param string @option */ protected function createTable($tableName, $columns, $primaryKey, $options=NULL) { $sql = "CREATE TABLE IF NOT EXISTS $tableName (\n "; foreach ($columns as $name => $type) { $sql .= "$name $type"; if ($name == $primaryKey) { $sql .= " NOT NULL AUTO_INCREMENT"; } $sql .= ",\n "; } $sql .= "PRIMARY KEY ($primaryKey));"; $this->executeNonQuery($sql); //we can't relly on the fact that the table has been properly created, so check it! if(!$this->existsTable($tableName)) throw new Exception(SyC::t('sdk','Cannot create table "{table_name}". Check your database permissions.', array('{table_name}' => $tableName))); } /** * * existsTable * @return TRUE if the table exists, otherwise false */ protected function existsTable($tableName){ $table_details = $this->getRow("show tables like '$tableName'"); //if there are table details, it means the table exists return !empty($table_details); } /** * Drop the specified table * * @param string tableName */ protected function dropTable($tableName) { $this->executeNonQuery("DROP TABLE $tableName"); //we can't relly on the fact that the table has been properly droped, so check it! if(!$this->existsTable($tableName)) throw new Exception(SyC::t('sdk','Cannot drop table "{table_name}". Check your database permissions.', array('{table_name}' => $tableName))); } /** * * Check the SDK status * @param $force. TRUE to check, no matter how soon the previous check was. This can have a great impact on the experience of the admin * */ protected function checkSDKStatus($force = false) { //call the API at most only once every 5 minutes, not sooner if(!$force && (time()-$this->getConfigValue('api_last_check')) < 5*60) return; //set the latest check time $this->setConfigValue('api_last_check',time()); //get an update from the API $message = ''; if(is_array($result = $this->getSDKStatus($this->getSecretKey(), $this->getClientId(), $this->getAppKey(), $message))) { //save the data $this->setConfigValue('api_version', @$result['api_version']); $this->setConfigValue('latest_version', @$result['plugin_latest_version']); $this->setConfigValue('download_url', @$result['plugin_download_url']); //set the current language the SDK should be displayed in if(isset($result['lang'])){ $this->setConfigValue('lang', $result['lang']); SyC::setLanguage($result['lang']); } }else{ //simply log the error, for now! error_log(print_r($message,true)); } } /* * * Call to see if the function was called once, or not * */ protected static function isFirstCall($functionName) { if (array_key_exists($functionName, self::$_SINGLE_FUNCTIONS_CALLS)) return false; self::$_SINGLE_FUNCTIONS_CALLS[$functionName] = true; return true; } /** * * User to catch any unhandled exceptions and print them nicelly * */ public function UncaughtExceptionHandler(Exception $e) { //@header("HTTP/1.0 403"); echo $e->getMessage(); } } } //END IF ?>