added the incredible shopp plugin

This commit is contained in:
Kenneth Reitz
2010-03-23 09:15:23 -04:00
parent b2b0c7ce1c
commit 2f88dfe5ec
145 changed files with 30817 additions and 0 deletions
File diff suppressed because it is too large Load Diff
+423
View File
@@ -0,0 +1,423 @@
<?php
/**
* DB classes
* Database management classes
*
* @author Jonathan Davis
* @version 1.0
* @copyright Ingenesis Limited, 28 March, 2008
* @package Shopp
**/
define("AS_ARRAY",false);
define("SHOPP_DBPREFIX","shopp_");
if (!defined('SHOPP_QUERY_DEBUG')) define('SHOPP_QUERY_DEBUG',false);
// Make sure that compatibility mode is not enabled
if (ini_get('zend.ze1_compatibility_mode'))
ini_set('zend.ze1_compatibility_mode','Off');
class DB {
private static $instance;
// Define datatypes for MySQL
var $_datatypes = array("int" => array("int", "bit", "bool", "boolean"),
"float" => array("float", "double", "decimal", "real"),
"string" => array("char", "binary", "varbinary", "text", "blob"),
"list" => array("enum","set"),
"date" => array("date", "time", "year")
);
var $results = array();
var $queries = array();
var $dbh = false;
protected function DB () {
global $wpdb;
$this->dbh = $wpdb->dbh;
$this->version = mysql_get_server_info();
}
function __clone() { trigger_error('Clone is not allowed.', E_USER_ERROR); }
static function &get() {
if (!self::$instance instanceof self)
self::$instance = new self;
return self::$instance;
}
/*
* Connects to the database server */
function connect($user, $password, $database, $host) {
$this->dbh = @mysql_connect($host, $user, $password);
if (!$this->dbh) trigger_error("Could not connect to the database server '$host'.");
else $this->select($database);
}
/**
* Select the database to use for our connection */
function select($database) {
if(!@mysql_select_db($database,$this->dbh))
trigger_error("Could not select the '$database' database.");
}
/**
* Escape contents of data for safe insertion into the db */
function escape($data) {
// Prevent double escaping by stripping any existing escapes out
return addslashes(stripslashes($data));
}
function clean($data) {
if (is_array($data)) array_map(array(&$this,'clean'), $data);
if (is_string($data)) rtrim($data);
return $data;
}
/**
* Send a query to the database */
function query($query, $output=true, $errors=true) {
if (SHOPP_QUERY_DEBUG) $this->queries[] = $query;
$result = @mysql_query($query, $this->dbh);
if (SHOPP_QUERY_DEBUG && class_exists('ShoppError')) new ShoppError($query,'shopp_query_debug',SHOPP_DEBUG_ERR);
// Error handling
if ($this->dbh && $error = mysql_error($this->dbh))
new ShoppError(sprintf(__('Query failed: %s - DB Query: %s','Shopp'),$error, str_replace("\n","",$query)),'shopp_query_error',SHOPP_DB_ERR);
// Results handling
if ( preg_match("/^\\s*(create|drop|insert|delete|update|replace) /i",$query) ) {
$this->affected = mysql_affected_rows();
if ( preg_match("/^\\s*(insert|replace) /i",$query) ) {
$insert = @mysql_fetch_object(@mysql_query("SELECT LAST_INSERT_ID() AS id", $this->dbh));
return $insert->id;
}
if ($this->affected > 0) return $this->affected;
else return true;
} else {
if ($result === true) return true;
$this->results = array();
while ($row = @mysql_fetch_object($result)) {
$this->results[] = $row;
}
@mysql_free_result($result);
if ($output && sizeof($this->results) == 1) $this->results = $this->results[0];
return $this->results;
}
}
function datatype($type) {
foreach((array)$this->_datatypes as $datatype => $patterns) {
foreach((array)$patterns as $pattern) {
if (strpos($type,$pattern) !== false) return $datatype;
}
}
return false;
}
/**
* Prepare the data properties for entry into
* the database */
function prepare($object) {
$data = array();
// Go through each data property of the object
foreach(get_object_vars($object) as $property => $value) {
if (!isset($object->_datatypes[$property])) continue;
// If the property is has a _datatype
// it belongs in the database and needs
// to be prepared
// Process the data
switch ($object->_datatypes[$property]) {
case "string":
// Escape characters in strings as needed
if (is_array($value)) $value = serialize($value);
$data[$property] = "'".$this->escape($value)."'";
break;
case "list":
// If value is empty, skip setting the field
// so it inherits the default value in the db
if (!empty($value))
$data[$property] = "'$value'";
break;
case "date":
// If it's an empty date, set it to now()'s timestamp
if (is_null($value)) {
$data[$property] = "now()";
// If the date is an integer, convert it to an
// sql YYYY-MM-DD HH:MM:SS format
} elseif (!empty($value) && is_int(intval($value))) {
$data[$property] = "'".mkdatetime(intval($value))."'";
// Otherwise it's already ready, so pass it through
} else {
$data[$property] = "'$value'";
}
break;
case "int":
case "float":
$value = floatnum($value);
$data[$property] = "'$value'";
if (empty($value)) $data[$property] = "'0'";
// Special exception for id fields
if ($property == "id" && empty($value)) $data[$property] = "NULL";
break;
default:
// Anything not needing processing
// passes through into the object
$data[$property] = "'$value'";
}
}
return $data;
}
/**
* Get the list of possible values for an enum() or set() column */
function column_options($table = null, $column = null) {
if ( ! ($table && $column)) return array();
$r = $this->query("SHOW COLUMNS FROM $table LIKE '$column'");
if ( strpos($r[0]->Type,"enum('") )
$list = substr($r[0]->Type, 6, strlen($r[0]->Type) - 8);
if ( strpos($r[0]->Type,"set('") )
$list = substr($r[0]->Type, 5, strlen($r[0]->Type) - 7);
return explode("','",$list);
}
/**
* Send a large set of queries to the database. */
function loaddata ($queries) {
$queries = explode(";\n", $queries);
array_pop($queries);
foreach ($queries as $query) if (!empty($query)) $this->query($query);
return true;
}
} // END class DB
/* class DatabaseObject
* Generic database glueware between the database and the active data model */
class DatabaseObject {
function DatabaseObject () {
// Constructor
}
/**
* Initializes the db object by grabbing table schema
* so we know how to work with this table */
function init ($table,$key="id") {
global $Shopp;
$db = DB::get();
$this->_table = $this->tablename($table); // So we know what the table name is
$this->_key = $key; // So we know what the primary key is
$this->_datatypes = array(); // So we know the format of the table
$this->_lists = array(); // So we know the options for each list
$this->_defaults = array(); // So we know the default values for each field
if (isset($Shopp->Settings)) {
$Tables = $Shopp->Settings->get('data_model');
if (isset($Tables[$this->_table])) {
$this->_datatypes = $Tables[$this->_table]->_datatypes;
$this->_lists = $Tables[$this->_table]->_lists;
foreach($this->_datatypes as $property => $type) {
$this->{$property} = (isset($this->_defaults[$property]))?
$this->_defaults[$property]:'';
if (empty($this->{$property}) && $type == "date")
$this->{$property} = null;
}
return true;
}
}
if (!$r = $db->query("SHOW COLUMNS FROM $this->_table",true,false)) return false;
// Map out the table definition into our data structure
foreach($r as $object) {
$property = $object->Field;
$this->{$property} = $object->Default;
$this->_datatypes[$property] = $db->datatype($object->Type);
$this->_defaults[$property] = $object->Default;
// Grab out options from list fields
if ($db->datatype($object->Type) == "list") {
$values = str_replace("','", ",", substr($object->Type,strpos($object->Type,"'")+1,-2));
$this->_lists[$property] = explode(",",$values);
}
}
if (isset($Shopp->Settings)) {
$Tables[$this->_table] = new StdClass();
$Tables[$this->_table]->_datatypes = $this->_datatypes;
$Tables[$this->_table]->_lists = $this->_lists;
$Tables[$this->_table]->_defaults = $this->_defaults;
$Shopp->Settings->save('data_model',$Tables);
}
}
/**
* Load a single record by the primary key or a custom query
* @param $where - An array of key/values to be built into an SQL where clause
* or
* @param $id - A string containing the id for db object's predefined primary key
* or
* @param $id - A string containing the object's id value
* @param $key - A string of the name of the db object's primary key
**/
function load () {
$db = DB::get();
$args = func_get_args();
if (empty($args[0])) return false;
$where = "";
if (is_array($args[0]))
foreach ($args[0] as $key => $id)
$where .= ($where == ""?"":" AND ")."$key='".$db->escape($id)."'";
else {
$id = $args[0];
$key = $this->_key;
if (!empty($args[1])) $key = $args[1];
$where = $key."='".$db->escape($id)."'";
}
$r = $db->query("SELECT * FROM $this->_table WHERE $where LIMIT 1");
$this->populate($r);
if (!empty($this->id)) return true;
return false;
}
/**
* Processes a bulk string of semi-colon separated SQL queries */
function loaddata ($queries) {
$queries = explode(";\n", $queries);
array_pop($queries);
foreach ($queries as $query) if (!empty($query)) $this->query($query);
return true;
}
function tablename ($table) {
global $table_prefix;
return $table_prefix.SHOPP_DBPREFIX.$table;
}
/**
* Save a record, updating when we have a value for the primary key,
* inserting a new record when we don't */
function save () {
$db = DB::get();
$data = $db->prepare($this);
$id = $this->{$this->_key};
// Update record
if (!empty($id)) {
if (isset($data['modified'])) $data['modified'] = "now()";
$dataset = $this->dataset($data);
$db->query("UPDATE $this->_table SET $dataset WHERE $this->_key=$id");
return true;
// Insert new record
} else {
if (isset($data['created'])) $data['created'] = "now()";
if (isset($data['modified'])) $data['modified'] = "now()";
$dataset = $this->dataset($data);
//print "INSERT $this->_table SET $dataset";
$this->id = $db->query("INSERT $this->_table SET $dataset");
return $this->id;
}
}
/**
* Deletes the record associated with this object */
function delete () {
$db = DB::get();
// Delete record
$id = $this->{$this->_key};
if (!empty($id)) $db->query("DELETE FROM $this->_table WHERE $this->_key='$id'");
else return false;
}
/**
* Populate the object properties from a set of
* loaded results */
function populate($data) {
if(empty($data)) return false;
foreach(get_object_vars($data) as $property => $value) {
if (empty($this->_datatypes[$property])) continue;
// Process the data
switch ($this->_datatypes[$property]) {
case "date":
$this->{$property} = mktimestamp($value);
break;
case "int":
case "float":
case "string":
// If string has been serialized, unserialize it
if (preg_match("/^[sibNaO](?:\:.+?\{.*\}$|\:.+;$|;$)/s",$value)) $value = unserialize($value);
default:
// Anything not needing processing
// passes through into the object
$this->{$property} = $value;
}
}
}
/**
* Build an SQL-ready string of the prepared data
* for entry into the database */
function dataset($data) {
$query = "";
foreach($data as $property => $value) {
if (!empty($query)) $query .= ", ";
$query .= "$property=$value";
}
return $query;
}
/**
* Populate the object properties from a set of
* form post inputs */
function updates($data,$ignores = array()) {
$db = DB::get();
foreach ($data as $key => $value) {
if (!is_null($value) &&
!in_array($key,$ignores) &&
property_exists($this, $key) ) {
$this->{$key} = $db->clean($value);
}
}
}
/**
* Copy property values from a given (like) object to this object
* where the property names match */
function copydata ($Object,$prefix="") {
$db = DB::get();
$ignores = array("_datatypes","_table","_key","_lists","id","created","modified");
foreach(get_object_vars($Object) as $property => $value) {
$property = $prefix.$property;
if (property_exists($this,$property) &&
!in_array($property,$ignores))
$this->{$property} = $db->clean($value);
}
}
} // END class DatabaseObject
?>
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+214
View File
@@ -0,0 +1,214 @@
<?php
/**
* init.php
* Holds the initial datasets for location based information
*
* @author Jonathan Davis
* @version 1.0
* @copyright Ingenesis Limited, 4 April, 2008
* @package Shopp
**/
/**
* Index of global region names */
function get_global_regions () {
$regions = array();
$regions[0] = __("North America","Shopp");
$regions[1] = __("Central America","Shopp");
$regions[2] = __("South America","Shopp");
$regions[3] = __("Europe","Shopp");
$regions[4] = __("Middle East","Shopp");
$regions[5] = __("Africa","Shopp");
$regions[6] = __("Asia","Shopp");
$regions[7] = __("Oceania","Shopp");
return $regions;
}
/**
* Country data table
* 20 KB in the database, load only when absolutely necessary and unset() asap */
function get_countries () {
$countries = array();
$countries['CA'] = array('name'=>__('Canada','Shopp'),'currency'=>array('code'=>'CAD','format'=>'$#,###.##'),'units'=>'metric','region'=>0);
$countries['US'] = array('name'=>__('USA','Shopp'),'currency'=>array('code'=>'USD','format'=>'$#,###.##'),'units'=>'imperial','region'=>0);
$countries['GB'] = array('name'=>__('United Kingdom','Shopp'),'currency'=>array('code'=>'GBP','format'=>'£#,###.##'),'units'=>'metric','region'=>3);
$countries['AR'] = array('name'=>__('Argentina','Shopp'),'currency'=>array('code'=>'ARS','format'=>'$#.###,##'),'units'=>'metric','region'=>7);
$countries['AU'] = array('name'=>__('Australia','Shopp'),'currency'=>array('code'=>'AUD','format'=>'$# ###.##'),'units'=>'metric','region'=>7);
$countries['AT'] = array('name'=>__('Austria','Shopp'),'currency'=>array('code'=>'EUR','format'=>'€#,###.##'),'units'=>'metric','region'=>3);
$countries['BS'] = array('name'=>__('Bahamas','Shopp'),'currency'=>array('code'=>'BSD','format'=>'$#,###.##'),'units'=>'metric','region'=>0);
$countries['BE'] = array('name'=>__('Belgium','Shopp'),'currency'=>array('code'=>'EUR','format'=>'€#.###,##'),'units'=>'metric','region'=>3);
$countries['BR'] = array('name'=>__('Brazil','Shopp'),'currency'=>array('code'=>'BRL','format'=>'R$ #.###,##'),'units'=>'metric','region'=>2);
$countries['BG'] = array('name'=>__('Bulgaria','Shopp'),'currency'=>array('code'=>'BGN','format'=>'# ###,## лв.'),'units'=>'metric','region'=>3);
$countries['CL'] = array('name'=>__('Chile','Shopp'),'currency'=>array('code'=>'CLP','format'=>'$#.###'),'units'=>'metric','region'=>2);
$countries['CN'] = array('name'=>__('China','Shopp'),'currency'=>array('code'=>'CNY','format'=>'¥#,###.##'),'units'=>'metric','region'=>6);
$countries['CO'] = array('name'=>__('Colombia','Shopp'),'currency'=>array('code'=>'COP','format'=>'$#.###,##'),'units'=>'metric','region'=>2);
$countries['CR'] = array('name'=>__('Costa Rica','Shopp'),'currency'=>array('code'=>'CRC','format'=>'¢ #.###,##'),'units'=>'metric','region'=>1);
$countries['HR'] = array('name'=>__('Croatia','Shopp'),'currency'=>array('code'=>'HRK','format'=>'#.###,## kn'),'units'=>'metric','region'=>3);
$countries['CY'] = array('name'=>__('Cyprus','Shopp'),'currency'=>array('code'=>'CYP','format'=>'£#.###,##'),'units'=>'metric','region'=>3);
$countries['CZ'] = array('name'=>__('Czech Republic','Shopp'),'currency'=>array('code'=>'CZK','format'=>'#.###,## Kc'),'units'=>'metric','region'=>3);
$countries['DK'] = array('name'=>__('Denmark','Shopp'),'currency'=>array('code'=>'DKK','format'=>'DKK #.###,##'),'units'=>'metric','region'=>3);
$countries['EC'] = array('name'=>__('Ecuador','Shopp'),'currency'=>array('code'=>'ESC','format'=>'$#,###.##'),'units'=>'metric','region'=>2);
$countries['EE'] = array('name'=>__('Estonia','Shopp'),'currency'=>array('code'=>'EEK','format'=>'# ###,## EEK'),'units'=>'metric','region'=>3);
$countries['FI'] = array('name'=>__('Finland','Shopp'),'currency'=>array('code'=>'EUR','format'=>'€#,###.##'),'units'=>'metric','region'=>3);
$countries['FR'] = array('name'=>__('France','Shopp'),'currency'=>array('code'=>'EUR','format'=>'€#,###.##'),'units'=>'metric','region'=>3);
$countries['DE'] = array('name'=>__('Germany','Shopp'),'currency'=>array('code'=>'EUR','format'=>'€#,###.##'),'units'=>'metric','region'=>3);
$countries['GR'] = array('name'=>__('Greece','Shopp'),'currency'=>array('code'=>'EUR','format'=>'€#,###.##'),'units'=>'metric','region'=>3);
$countries['GP'] = array('name'=>__('Guadeloupe','Shopp'),'currency'=>array('code'=>'EUR','format'=>'€#,###.##'),'units'=>'metric','region'=>3);
$countries['HK'] = array('name'=>__('Hong Kong','Shopp'),'currency'=>array('code'=>'HKD','format'=>'HK$#,###.##'),'units'=>'metric','region'=>6);
$countries['HU'] = array('name'=>__('Hungary','Shopp'),'currency'=>array('code'=>'HUF','format'=>'#t.### Ft'),'units'=>'metric','region'=>3);
$countries['IS'] = array('name'=>__('Iceland','Shopp'),'currency'=>array('code'=>'ISK','format'=>'#t.### kr.'),'units'=>'metric','region'=>3);
$countries['IN'] = array('name'=>__('India','Shopp'),'currency'=>array('code'=>'INR','format'=>'Rs. #,##,###.##'),'units'=>'metric','region'=>6);
$countries['ID'] = array('name'=>__('Indonesia','Shopp'),'currency'=>array('code'=>'IDR','format'=>'Rp. #.###,##'),'units'=>'metric','region'=>7);
$countries['IE'] = array('name'=>__('Ireland','Shopp'),'currency'=>array('code'=>'EUR','format'=>'€#,###.##'),'units'=>'metric','region'=>3);
$countries['IL'] = array('name'=>__('Israel','Shopp'),'currency'=>array('code'=>'ILS','format'=>'#,###.## NIS'),'units'=>'metric','region'=>4);
$countries['IT'] = array('name'=>__('Italy','Shopp'),'currency'=>array('code'=>'EUR','format'=>'€#,###.##'),'units'=>'metric','region'=>3);
$countries['JM'] = array('name'=>__('Jamaica','Shopp'),'currency'=>array('code'=>'JMD','format'=>'$#,###.##'),'units'=>'metric','region'=>0);
$countries['JP'] = array('name'=>__('Japan','Shopp'),'currency'=>array('code'=>'JPY','format'=>'¥#,###'),'units'=>'metric','region'=>6);
$countries['LV'] = array('name'=>__('Latvia','Shopp'),'currency'=>array('code'=>'LVL','format'=>'Ls #,###.##'),'units'=>'metric','region'=>3);
$countries['LT'] = array('name'=>__('Lithuania','Shopp'),'currency'=>array('code'=>'LTL','format'=>'# ###,## Lt'),'units'=>'metric','region'=>3);
$countries['LU'] = array('name'=>__('Luxembourg','Shopp'),'currency'=>array('code'=>'EUR','format'=>'€#,###.##'),'units'=>'metric','region'=>3);
$countries['MY'] = array('name'=>__('Malaysia','Shopp'),'currency'=>array('code'=>'MYR','format'=>'RM#,###.##'),'units'=>'metric','region'=>6);
$countries['MT'] = array('name'=>__('Malta','Shopp'),'currency'=>array('code'=>'MTL','format'=>'Lm#,###.##'),'units'=>'metric','region'=>3);
$countries['MX'] = array('name'=>__('Mexico','Shopp'),'currency'=>array('code'=>'MXN','format'=>'$ #,###.##'),'units'=>'metric','region'=>0);
$countries['NL'] = array('name'=>__('Netherlands','Shopp'),'currency'=>array('code'=>'EUR','format'=>'€#.###,##'),'units'=>'metric','region'=>3);
$countries['NZ'] = array('name'=>__('New Zealand','Shopp'),'currency'=>array('code'=>'NZD','format'=>'$#,###.##'),'units'=>'metric','region'=>7);
$countries['NO'] = array('name'=>__('Norway','Shopp'),'currency'=>array('code'=>'NOK','format'=>'kr #.###,##'),'units'=>'metric','region'=>3);
$countries['PE'] = array('name'=>__('Peru','Shopp'),'currency'=>array('code'=>'PEN','format'=>'S/. #,###.##'),'units'=>'metric','region'=>2);
$countries['PH'] = array('name'=>__('Philippines','Shopp'),'currency'=>array('code'=>'PHP','format'=>'PHP#,###.##'),'units'=>'metric','region'=>6);
$countries['PL'] = array('name'=>__('Poland','Shopp'),'currency'=>array('code'=>'PLZ','format'=>'#.###,## zł'),'units'=>'metric','region'=>3);
$countries['PT'] = array('name'=>__('Portugal','Shopp'),'currency'=>array('code'=>'EUR','format'=>'€#,###.##'),'units'=>'metric','region'=>3);
$countries['PR'] = array('name'=>__('Puerto Rico','Shopp'),'currency'=>array('code'=>'USD','format'=>'$#,###.##'),'units'=>'imperial','region'=>0);
$countries['RO'] = array('name'=>__('Romania','Shopp'),'currency'=>array('code'=>'ROL','format'=>'#.###,## lei'),'units'=>'metric','region'=>3);
$countries['RU'] = array('name'=>__('Russia','Shopp'),'currency'=>array('code'=>'RUB','format'=>'RUB#.###,##'),'units'=>'metric','region'=>6);
$countries['SG'] = array('name'=>__('Singapore','Shopp'),'currency'=>array('code'=>'SGD','format'=>'$#,###.##'),'units'=>'metric','region'=>6);
$countries['SK'] = array('name'=>__('Slovakia','Shopp'),'currency'=>array('code'=>'EUR','format'=>'€#,###.##'),'units'=>'metric','region'=>3);
$countries['SI'] = array('name'=>__('Slovenia','Shopp'),'currency'=>array('code'=>'EUR','format'=>'€#,###.##'),'units'=>'metric','region'=>3);
$countries['ZA'] = array('name'=>__('South Africa','Shopp'),'currency'=>array('code'=>'ZAR','format'=>'R # ###.##'),'units'=>'metric','region'=>5);
$countries['KR'] = array('name'=>__('South Korea','Shopp'),'currency'=>array('code'=>'KRW','format'=>'₩#,###'),'units'=>'metric','region'=>6);
$countries['ES'] = array('name'=>__('Spain','Shopp'),'currency'=>array('code'=>'EUR','format'=>'€#,###.##'),'units'=>'metric','region'=>3);
$countries['VC'] = array('name'=>__('St. Vincent','Shopp'),'currency'=>array('code'=>'XCD','format'=>'$#,###.##'),'units'=>'metric','region'=>6);
$countries['SE'] = array('name'=>__('Sweden','Shopp'),'currency'=>array('code'=>'SEK','format'=>'#.###,## kr'),'units'=>'metric','region'=>3);
$countries['CH'] = array('name'=>__('Switzerland','Shopp'),'currency'=>array('code'=>'CHF','format'=>"SFr. #'###.##"),'units'=>'metric','region'=>3);
$countries['SY'] = array('name'=>__('Syria','Shopp'),'currency'=>array('code'=>'SYP','format'=>'#,###.## SYP'),'units'=>'metric','region'=>4);
$countries['TW'] = array('name'=>__('Taiwan','Shopp'),'currency'=>array('code'=>'TWD','format'=>'$#,###.##'),'units'=>'metric','region'=>6);
$countries['TH'] = array('name'=>__('Thailand','Shopp'),'currency'=>array('code'=>'THB','format'=>'#,###.## Bt'),'units'=>'metric','region'=>6);
$countries['TT'] = array('name'=>__('Trinidad and Tobago','Shopp'),'currency'=>array('code'=>'TTD','format'=>'TT$#,###.##'),'units'=>'metric','region'=>0);
$countries['TR'] = array('name'=>__('Turkey','Shopp'),'currency'=>array('code'=>'TRL','format'=>'#,###.## TL'),'units'=>'metric','region'=>4);
$countries['AE'] = array('name'=>__('United Arab Emirates','Shopp'),'currency'=>array('code'=>'AED','format'=>'Dhs. #,###.##'),'units'=>'metric','region'=>4);
$countries['UY'] = array('name'=>__('Uruguay','Shopp'),'currency'=>array('code'=>'UYP','format'=>'$#,###.##'),'units'=>'metric','region'=>2);
$countries['VE'] = array('name'=>__('Venezuela','Shopp'),'currency'=>array('code'=>'VUB','format'=>'Bs. #,###.##'),'units'=>'metric','region'=>2);
return $countries;
}
/**
* State/Province/Territory zone names
* 2 KB in the database */
function get_country_zones() {
$zones = array();
$zones['AU'] = array();
$zones['AU']['NSW'] = 'New South Wales';
$zones['AU']['NT'] = 'Northern Territory';
$zones['AU']['QLD'] = 'Queensland';
$zones['AU']['SA'] = 'South Australia';
$zones['AU']['TAS'] = 'Tasmania';
$zones['AU']['VIC'] = 'Victoria';
$zones['AU']['WA'] = 'Western Australia';
$zones['CA'] = array();
$zones['CA']['AB'] = 'Alberta';
$zones['CA']['BC'] = 'British Columbia';
$zones['CA']['MB'] = 'Manitoba';
$zones['CA']['NB'] = 'New Brunswick';
$zones['CA']['NF'] = 'Newfoundland';
$zones['CA']['NT'] = 'Northwest Territories';
$zones['CA']['NS'] = 'Nova Scotia';
$zones['CA']['NU'] = 'Nunavut';
$zones['CA']['ON'] = 'Ontario';
$zones['CA']['PE'] = 'Prince Edward Island';
$zones['CA']['PQ'] = 'Quebec';
$zones['CA']['SK'] = 'Saskatchewan';
$zones['CA']['YT'] = 'Yukon Territory';
$zones['US'] = array();
$zones['US']['AL'] = 'Alabama';
$zones['US']['AK'] = 'Alaska ';
$zones['US']['AZ'] = 'Arizona';
$zones['US']['AR'] = 'Arkansas';
$zones['US']['CA'] = 'California ';
$zones['US']['CO'] = 'Colorado';
$zones['US']['CT'] = 'Connecticut';
$zones['US']['DE'] = 'Delaware';
$zones['US']['DC'] = 'District Of Columbia ';
$zones['US']['FL'] = 'Florida';
$zones['US']['GA'] = 'Georgia ';
$zones['US']['HI'] = 'Hawaii';
$zones['US']['ID'] = 'Idaho';
$zones['US']['IL'] = 'Illinois';
$zones['US']['IN'] = 'Indiana';
$zones['US']['IA'] = 'Iowa';
$zones['US']['KS'] = 'Kansas';
$zones['US']['KY'] = 'Kentucky';
$zones['US']['LA'] = 'Louisiana';
$zones['US']['ME'] = 'Maine';
$zones['US']['MD'] = 'Maryland';
$zones['US']['MA'] = 'Massachusetts';
$zones['US']['MI'] = 'Michigan';
$zones['US']['MN'] = 'Minnesota';
$zones['US']['MS'] = 'Mississippi';
$zones['US']['MO'] = 'Missouri';
$zones['US']['MT'] = 'Montana';
$zones['US']['NE'] = 'Nebraska';
$zones['US']['NV'] = 'Nevada';
$zones['US']['NH'] = 'New Hampshire';
$zones['US']['NJ'] = 'New Jersey';
$zones['US']['NM'] = 'New Mexico';
$zones['US']['NY'] = 'New York';
$zones['US']['NC'] = 'North Carolina';
$zones['US']['ND'] = 'North Dakota';
$zones['US']['OH'] = 'Ohio';
$zones['US']['OK'] = 'Oklahoma';
$zones['US']['OR'] = 'Oregon';
$zones['US']['PA'] = 'Pennsylvania';
$zones['US']['RI'] = 'Rhode Island';
$zones['US']['SC'] = 'South Carolina';
$zones['US']['SD'] = 'South Dakota';
$zones['US']['TN'] = 'Tennessee';
$zones['US']['TX'] = 'Texas';
$zones['US']['UT'] = 'Utah';
$zones['US']['VT'] = 'Vermont';
$zones['US']['VA'] = 'Virginia';
$zones['US']['WA'] = 'Washington';
$zones['US']['WV'] = 'West Virginia';
$zones['US']['WI'] = 'Wisconsin';
$zones['US']['WY'] = 'Wyoming';
return $zones;
}
/**
* Domestic areas for US and Canada mapped by postcode
* 3 KB in the database */
function get_country_areas () {
$areas = array();
$areas['CA'] = array();
$areas['CA']['Northern Canada'] = array('YT'=>array('Y'),'NT'=>array('X'),'NU'=>array('X'));
$areas['CA']['Western Canada'] = array('BC'=>array('V'),'AB'=>array('T'),'SK'=>array('S'),'MB'=>array('R'));
$areas['CA']['Eastern Canada'] = array('OT'=>array('K','L','M','N','P'),'PQ'=>array('G','H','J'),'NB'=>array('E'),'PE'=>array('C'),'NS'=>array('B'),'NF'=>array('A'));
$areas['US'] = array();
$areas['US']['Northeast US'] = array('MA'=>array('01000','02799','05500','05599'),'RI'=>array('02800','02999'),'NH'=>array('03000','03999'),'ME'=>array('03900','04999'),'VT'=>array('05000','05999'),'CT'=>array('06000','06999'),'NJ'=>array('07000','08999'),'NY'=>array('09000','14999','00500','00599','06300','06399'),'PA'=>array('15000','19699'));
$areas['US']['Midwest US'] = array('OH'=>array('43000','45999'),'IN'=>array('46000','47999'),'MI'=>array('48000','49999'),'IA'=>array('50000','52899'),'WI'=>array('53000','54999'),'MN'=>array('55000','56799'),'SD'=>array('57000','57799'),'ND'=>array('58000','58899'),'IL'=>array('60000','62999'),'MO'=>array('63000','65899'),'KS'=>array('66000','67999'),'NE'=>array('68000','69399'));
$areas['US']['South US'] =array('DE'=>array('19700','19999'),'DC'=>array('20000','20599'),'MD'=>array('20600','21999'),'VA'=>array('22000','24699','20100','20199'),'WV'=>array('24700','26899'),'NC'=>array('26900','28999'),'SC'=>array('29000','29999'),'GA'=>array('30000','31999','39800','39999'),'FL'=>array('32000','34999'),'AL'=>array('35000','36999'),'TN'=>array('37000','38599'),'MS'=>array('38600','39799'),'KY'=>array('40000','42799'),'LA'=>array('70000','71499'),'AR'=>array('71600','72999','75500','75599'),'OK'=>array('73000','74999'),'TX'=>array('75000','79999','88500','88599'));
$areas['US']['West US'] =array('MT'=>array('59000','59999'),'CO'=>array('80000','81699'),'WY'=>array('82000','83199'),'ID'=>array('83200','83899'),'UT'=>array('84000','84799'),'AZ'=>array('85000','86599'),'NM'=>array('87000','88499'),'NV'=>array('88900','89899'),'CA'=>array('90000','96699'),'HI'=>array('96700','96899'),'OR'=>array('97000','97999'),'WA'=>array('98000','99499'),'AK'=>array('99500','99999'));
return $areas;
}
function get_vat_countries () {
$vat = array(
'BE','BG','CZ','DK','DE','EE','GR','ES','FR',
'IE','IT','CY','LV','LT','LU','HU','MT','NL',
'AT','PL','PT','RO','SI','SK','FI','SE','GB'
);
return $vat;
}
?>
@@ -0,0 +1,62 @@
<?php
/**
* install.php
* Performs the initial database setup
*
* @author Jonathan Davis
* @version 1.0
* @copyright Ingenesis Limited, 4 April, 2008
* @package Shopp
**/
global $wpdb,$wp_rewrite,$wp_version,$table_prefix;
$db = DB::get();
// Install tables
if (!file_exists(SHOPP_DBSCHEMA)) {
trigger_error("Could not install the shopp database tables because the table definitions file is missing: ".SHOPP_DBSCHEMA);
exit();
}
ob_start();
include(SHOPP_DBSCHEMA);
$schema = ob_get_contents();
ob_end_clean();
$db->loaddata($schema);
unset($schema);
$parent = 0;
foreach ($this->Flow->Pages as $key => &$page) {
if (!empty($this->Flow->Pages['catalog']['id'])) $parent = $this->Flow->Pages['catalog']['id'];
$query = "INSERT $wpdb->posts SET post_title='{$page['title']}',
post_name='{$page['name']}',
post_content='{$page['content']}',
post_parent='$parent',
post_author='1',
post_status='publish',
post_type='page',
post_date=now(),
post_date_gmt=utc_timestamp(),
post_modified=now(),
post_modified_gmt=utc_timestamp(),
comment_status='closed',
ping_status='closed',
post_excerpt='',
to_ping='',
pinged='',
post_content_filtered='',
menu_order=0";
$wpdb->query($query);
$page['id'] = $wpdb->insert_id;
$page['permalink'] = get_permalink($page['id']);
if ($key == "checkout") $page['permalink'] = str_replace("http://","https://",$page['permalink']);
$wpdb->query("UPDATE $wpdb->posts SET guid='{$page['permalink']}' WHERE ID={$page['id']}");
$page['permalink'] = preg_replace('|https?://[^/]+/|i','',$page['permalink']);
}
$this->Settings->save("pages",$this->Flow->Pages);
?>
@@ -0,0 +1,212 @@
<?php
/**
* Asset class
* Catalog product assets (metadata, images, downloads)
*
* @author Jonathan Davis
* @version 1.0
* @copyright Ingenesis Limited, 28 March, 2008
* @package shopp
**/
class Asset extends DatabaseObject {
static $table = "asset";
var $storage = "db";
var $path = "";
function Asset ($id=false,$key=false) {
$this->init(self::$table);
if ($this->load($id,$key)) return true;
else return false;
}
function setstorage ($type=false) {
global $Shopp;
if (!$type) $type = $this->datatype;
switch ($type) {
case "image":
case "small":
case "thumbnail":
$this->storage = $Shopp->Settings->get('image_storage');
$this->path = trailingslashit($Shopp->Settings->get('image_path'));
break;
case "download":
$this->storage = $Shopp->Settings->get('product_storage');
$this->path = trailingslashit($Shopp->Settings->get('products_path'));
break;
}
}
/**
* Save a record, updating when we have a value for the primary key,
* inserting a new record when we don't */
function save () {
$db =& DB::get();
$data = $db->prepare($this);
$id = $this->{$this->_key};
$this->setstorage();
// Hook for outputting files to filesystem
if ($this->storage == "fs") {
if (!$this->savefile()) return false;
unset($data['data']); // Keep from duplicating data in DB
}
// Update record
if (!empty($id)) {
if (isset($data['modified'])) $data['modified'] = "now()";
$dataset = $this->dataset($data);
$db->query("UPDATE $this->_table SET $dataset WHERE $this->_key=$id");
return true;
// Insert new record
} else {
if (isset($data['created'])) $data['created'] = "now()";
if (isset($data['modified'])) $data['modified'] = "now()";
$dataset = $this->dataset($data);
$this->id = $db->query("INSERT $this->_table SET $dataset");
return $this->id;
}
}
function savedata ($file) {
$db =& DB::get();
$id = $this->{$this->_key};
if (!$id) return false;
$handle = fopen($file, "r");
while (!feof($handle)) {
$buffer = mysql_real_escape_string(fread($handle, 65535));
$query = "UPDATE $this->_table SET data=CONCAT(data,'$buffer') WHERE $this->_key=$id";
$db->query($query);
}
fclose($handle);
}
function savefile () {
if (empty($this->data)) return true;
if (file_put_contents($this->path.$this->name,stripslashes($this->data)) > 0) return true;
return false;
}
function deleteset ($keys,$type="image") {
$db =& DB::get();
if ($type == "image") $this->setstorage('image');
if ($type == "download") $this->setstorage('download');
if ($this->storage == "fs") $this->deletefiles($keys);
$selection = "";
foreach ($keys as $value)
$selection .= ((!empty($selection))?" OR ":"")."{$this->_key}=$value OR src=$value";
$query = "DELETE LOW_PRIORITY FROM $this->_table WHERE $selection";
$db->query($query);
}
/**
* deletefiles ()
* Remove files from the file system only when 1 reference to the file exists
* in file references in the database, otherwise, leave them **/
function deletefiles ($keys) {
$db =& DB::get();
$selection = "";
foreach ($keys as $value)
$selection .= ((!empty($selection))?" OR ":"")."f.{$this->_key}=$value OR f.src=$value";
$query = "SELECT f.name,count(DISTINCT links.id) AS refs FROM $this->_table AS f LEFT JOIN $this->_table AS links ON f.name=links.name WHERE $selection GROUP BY links.name";
$files = $db->query($query,AS_ARRAY);
foreach ($files as $file)
if ($file->refs == 1 && file_exists($this->path.$file->name))
unlink($this->path.$file->name);
return true;
}
function download ($dkey=false) {
$this->setstorage('download');
// Close the session in case of long download
@session_write_close();
// Don't want interference from the server
if (function_exists('apache_setenv')) @apache_setenv('no-gzip', 1);
@ini_set('zlib.output_compression', 0);
set_time_limit(0); // Don't timeout on long downloads
ob_end_clean(); // End any automatic output buffering
header("Pragma: public");
header("Cache-Control: maxage=1");
header("Content-type: application/octet-stream");
header("Content-Disposition: attachment; filename=\"".$this->name."\"");
header("Content-Description: Delivered by WordPress/Shopp ".SHOPP_VERSION);
// File System based download - handles very large files, supports resumable downloads
if ($this->storage == "fs") {
if (!empty($this->value)) $filepath = join("/",array($this->path,$this->value,$this->name));
else $filepath = join("/",array($this->path,$this->name));
if (!is_file($filepath)) {
header("Status: 404 Forbidden"); // File not found?!
return false;
}
$size = @filesize($filepath);
// Handle resumable downloads
if (isset($_SERVER['HTTP_RANGE'])) {
list($units, $reqrange) = explode('=', $_SERVER['HTTP_RANGE'], 2);
if ($units == 'bytes') {
// Use first range - http://tools.ietf.org/id/draft-ietf-http-range-retrieval-00.txt
list($range, $extra) = explode(',', $reqrange, 2);
} else $range = '';
} else $range = '';
// Determine download chunk to grab
list($start, $end) = explode('-', $range, 2);
// Set start and end based on range (if set), or set defaults
// also check for invalid ranges.
$end = (empty($end)) ? ($size - 1) : min(abs(intval($end)),($size - 1));
$start = (empty($start) || $end < abs(intval($start))) ? 0 : max(abs(intval($start)),0);
// Only send partial content header if downloading a piece of the file (IE workaround)
if ($start > 0 || $end < ($size - 1)) header('HTTP/1.1 206 Partial Content');
header('Accept-Ranges: bytes');
header('Content-Range: bytes '.$start.'-'.$end.'/'.$size);
header('Content-length: '.($end-$start+1));
// WebKit/Safari resumable download support headers
header('Last-modified: '.date('D, d M Y H:i:s O',$this->modified));
if (isset($dkey)) header('ETag: '.$dkey);
$file = fopen($filepath, 'rb');
fseek($file, $start);
$packet = 1024*1024;
while(!feof($file)) {
if (connection_status() !== 0) return false;
$buffer = fread($file,$packet);
if (!empty($buffer)) echo $buffer;
ob_flush(); flush();
}
fclose($file);
return true;
} else {
// Database file download - short and sweet
header ("Content-length: ".$this->size);
echo $this->data;
return true;
}
}
} // end Asset class
?>
@@ -0,0 +1,35 @@
<?php
/**
* Billing class
* Billing information
*
* @author Jonathan Davis
* @version 1.0
* @copyright Ingenesis Limited, 28 March, 2008
* @package shopp
**/
class Billing extends DatabaseObject {
static $table = "billing";
function Billing ($id=false,$key=false) {
$this->init(self::$table);
if ($this->load($id,$key)) return true;
else return false;
}
function exportcolumns () {
$prefix = "b.";
return array(
$prefix.'address' => __('Billing Street Address','Shopp'),
$prefix.'xaddress' => __('Billing Street Address 2','Shopp'),
$prefix.'city' => __('Billing City','Shopp'),
$prefix.'state' => __('Billing State/Province','Shopp'),
$prefix.'country' => __('Billing Country','Shopp'),
$prefix.'postcode' => __('Billing Postal Code','Shopp'),
);
}
} // end Billing class
?>
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,612 @@
<?php
/**
* Catalog class
*
*
* @author Jonathan Davis
* @version 1.0
* @copyright Ingenesis Limited, 9 April, 2008
* @package shopp
**/
require_once("Category.php");
require_once("Tag.php");
class Catalog extends DatabaseObject {
static $table = "catalog";
var $smarts = array("FeaturedProducts","BestsellerProducts","NewProducts","OnSaleProducts");
var $categories = array();
var $outofstock = false;
function Catalog ($type="catalog") {
global $Shopp;
$this->init(self::$table);
$this->type = $type;
$this->outofstock = ($Shopp->Settings->get('outofstock_catalog') == "on");
}
function load_categories ($filtering=false,$showsmart=false,$results=false) {
$db = DB::get();
if (empty($filtering['columns'])) $filtering['columns'] = "cat.id,cat.parent,cat.name,cat.description,cat.uri,cat.slug,count(DISTINCT pd.id) AS total,IF(SUM(IF(pt.inventory='off',1,0) OR pt.inventory IS NULL)>0,'off','on') AS inventory, SUM(pt.stock) AS stock";
if (!empty($filtering['limit'])) $filtering['limit'] = "LIMIT ".$filtering['limit'];
else $filtering['limit'] = "";
// if (!$this->outofstock) $filtering['where'] .= (empty($filtering['where'])?"":" AND ")."(pt.inventory='off' OR (pt.inventory='on' AND pt.stock > 0))";
if (empty($filtering['where'])) $filtering['where'] = "true";
if (empty($filtering['orderby'])) $filtering['orderby'] = "name";
switch(strtolower($filtering['orderby'])) {
case "id": $orderby = "cat.id"; break;
case "slug": $orderby = "cat.slug"; break;
case "count": $orderby = "total"; break;
default: $orderby = "cat.name";
}
if (empty($filtering['order'])) $filtering['order'] = "ASC";
switch(strtoupper($filtering['order'])) {
case "DESC": $order = "DESC"; break;
default: $order = "ASC";
}
$category_table = DatabaseObject::tablename(Category::$table);
$product_table = DatabaseObject::tablename(Product::$table);
$price_table = DatabaseObject::tablename(Price::$table);
$query = "SELECT {$filtering['columns']} FROM $category_table AS cat LEFT JOIN $this->_table AS sc ON sc.category=cat.id LEFT JOIN $product_table AS pd ON sc.product=pd.id LEFT JOIN $price_table AS pt ON pt.product=pd.id AND pt.type != 'N/A' WHERE {$filtering['where']} GROUP BY cat.id ORDER BY cat.parent DESC,$orderby $order {$filtering['limit']}";
$categories = $db->query($query,AS_ARRAY);
if (count($categories) > 1) $categories = sort_tree($categories);
if ($results) return $categories;
foreach ($categories as $category) {
$category->outofstock = false;
if (isset($category->inventory)) {
if ($category->inventory == "on" && $category->stock == 0)
$category->outofstock = true;
if (!$this->outofstock && $category->outofstock) continue;
}
$this->categories[$category->id] = new Category();
$this->categories[$category->id]->populate($category);
if (isset($category->depth))
$this->categories[$category->id]->depth = $category->depth;
else $this->categories[$category->id]->depth = 0;
if (isset($category->total))
$this->categories[$category->id]->total = $category->total;
else $this->categories[$category->id]->total = 0;
if (isset($category->stock))
$this->categories[$category->id]->stock = $category->stock;
else $this->categories[$category->id]->stock = 0;
if (isset($category->outofstock))
$this->categories[$category->id]->outofstock = $category->outofstock;
$this->categories[$category->id]->children = false;
if ($category->total > 0 && isset($this->categories[$category->parent]))
$this->categories[$category->parent]->children = true;
}
if ($showsmart == "before" || $showsmart == "after")
$this->smart_categories($showsmart);
return true;
}
function smart_categories ($method) {
foreach ($this->smarts as $SmartCategory) {
$category = new $SmartCategory(array("noload" => true));
switch($method) {
case "before": array_unshift($this->categories,$category); break;
default: array_push($this->categories,$category);
}
}
}
function load_tags ($limits=false) {
$db = DB::get();
if ($limits) $limit = " LIMIT {$limits[0]},{$limits[1]}";
else $limit = "";
$tagtable = DatabaseObject::tablename(Tag::$table);
$query = "SELECT t.*,count(sc.product) AS products FROM $this->_table AS sc LEFT JOIN $tagtable AS t ON sc.tag=t.id WHERE sc.tag != 0 GROUP BY t.id ORDER BY t.name ASC$limit";
$this->tags = $db->query($query,AS_ARRAY);
return true;
}
function load_category ($category,$options=array()) {
switch ($category) {
case SearchResults::$_slug: return new SearchResults($options); break;
case TagProducts::$_slug: return new TagProducts($options); break;
case BestsellerProducts::$_slug: return new BestsellerProducts(); break;
case CatalogProducts::$_slug: return new CatalogProducts(); break;
case NewProducts::$_slug: return new NewProducts(); break;
case FeaturedProducts::$_slug: return new FeaturedProducts(); break;
case OnSaleProducts::$_slug: return new OnSaleProducts(); break;
case RandomProducts::$_slug: return new RandomProducts(); break;
default:
$key = "id";
if (!preg_match("/^\d+$/",$category)) $key = "uri";
return new Category($category,$key);
}
}
function tag ($property,$options=array()) {
global $Shopp;
$pages = $Shopp->Settings->get('pages');
if (SHOPP_PERMALINKS) $path = $Shopp->shopuri;
else $page = add_query_arg('page_id',$pages['catalog']['id'],$Shopp->shopuri);
switch ($property) {
case "url": return $Shopp->link('catalog'); break;
case "display":
case "type": return $this->type; break;
case "is-landing":
case "is-catalog": return (is_shopp_page('catalog') && $this->type == "catalog"); break;
case "is-category": return (is_shopp_page('catalog') && $this->type == "category"); break;
case "is-product": return (is_shopp_page('catalog') && $this->type == "product"); break;
case "is-cart": return (is_shopp_page('cart')); break;
case "is-checkout": return (is_shopp_page('checkout')); break;
case "is-account": return (is_shopp_page('account')); break;
case "tagcloud":
if (!empty($options['levels'])) $levels = $options['levels'];
else $levels = 7;
if (empty($this->tags)) $this->load_tags();
$min = -1; $max = -1;
foreach ($this->tags as $tag) {
if ($min == -1 || $tag->products < $min) $min = $tag->products;
if ($max == -1 || $tag->products > $max) $max = $tag->products;
}
if ($max == 0) $max = 1;
$string = '<ul class="shopp tagcloud">';
foreach ($this->tags as $tag) {
$level = floor((1-$tag->products/$max)*$levels)+1;
if (SHOPP_PERMALINKS) $link = $path.'tag/'.urlencode($tag->name).'/';
else $link = add_query_arg('shopp_tag',urlencode($tag->name),$page);
$string .= '<li class="level-'.$level.'"><a href="'.$link.'" rel="tag">'.$tag->name.'</a></li> ';
}
$string .= '</ul>';
return $string;
break;
case "has-categories":
if (empty($this->categories)) $this->load_categories(array('where'=>'true'),$options['showsmart']);
if (count($this->categories) > 0) return true; else return false; break;
case "categories":
if (!$this->categoryloop) {
reset($this->categories);
$Shopp->Category = current($this->categories);
$this->categoryloop = true;
} else {
$Shopp->Category = next($this->categories);
}
if (current($this->categories)) {
$Shopp->Category = current($this->categories);
return true;
} else {
$this->categoryloop = false;
return false;
}
break;
case "category-list":
$defaults = array(
'title' => '',
'before' => '',
'after' => '',
'class' => '',
'exclude' => '',
'orderby' => 'name',
'order' => 'ASC',
'depth' => 0,
'childof' => 0,
'parent' => false,
'showall' => false,
'linkall' => false,
'linkcount' => false,
'dropdown' => false,
'hierarchy' => false,
'products' => false,
'wraplist' => true,
'showsmart' => false
);
$options = array_merge($defaults,$options);
extract($options, EXTR_SKIP);
$this->load_categories(array("where"=>"(pd.published='on' OR pd.id IS NULL)","orderby"=>$orderby,"order"=>$order),$showsmart);
$string = "";
$depthlimit = $depth;
$depth = 0;
$exclude = explode(",",$exclude);
$classes = ' class="shopp_categories'.(empty($class)?'':' '.$class).'"';
$wraplist = value_is_true($wraplist);
if (value_is_true($dropdown)) {
if (!isset($default)) $default = __('Select category&hellip;','Shopp');
$string .= $title;
$string .= '<form><select name="shopp_cats" id="shopp-categories-menu"'.$classes.'>';
$string .= '<option value="">'.$default.'</option>';
foreach ($this->categories as &$category) {
if (!empty($category->id) && in_array($category->id,$exclude)) continue; // Skip excluded categories
if ($category->total == 0 && !isset($category->smart)) continue; // Only show categories with products
if ($depthlimit && $category->depth >= $depthlimit) continue;
if (value_is_true($hierarchy) && $category->depth > $depth) {
$parent = &$previous;
if (!isset($parent->path)) $parent->path = '/'.$parent->slug;
}
if (value_is_true($hierarchy))
$padding = str_repeat("&nbsp;",$category->depth*3);
if (SHOPP_PERMALINKS) $link = $Shopp->shopuri.'category/'.$category->uri;
else $link = add_query_arg('shopp_category',$category->id,$Shopp->shopuri);
$total = '';
if (value_is_true($products) && $category->total > 0) $total = ' ('.$category->total.')';
$string .= '<option value="'.$link.'">'.$padding.$category->name.$total.'</option>';
$previous = &$category;
$depth = $category->depth;
}
$string .= '</select></form>';
$string .= '<script type="text/javascript">';
$string .= 'var menu = document.getElementById(\'shopp-categories-menu\');';
$string .= 'if (menu) {';
$string .= ' menu.onchange = function () {';
$string .= ' document.location.href = this.options[this.selectedIndex].value;';
$string .= ' }';
$string .= '}';
$string .= '</script>';
} else {
$string .= $title;
if ($wraplist) $string .= '<ul'.$classes.'>';
foreach ($this->categories as &$category) {
if (!isset($category->total)) $category->total = 0;
if (!isset($category->depth)) $category->depth = 0;
if (!empty($category->id) && in_array($category->id,$exclude)) continue; // Skip excluded categories
if ($depthlimit && $category->depth >= $depthlimit) continue;
if (value_is_true($hierarchy) && $category->depth > $depth) {
$parent = &$previous;
if (!isset($parent->path)) $parent->path = $parent->slug;
$string = substr($string,0,-5); // Remove the previous </li>
$active = '';
if (isset($Shopp->Category) && !empty($parent->slug)
&& preg_match('/(^|\/)'.$parent->path.'(\/|$)/',$Shopp->Category->uri)) {
$active = ' active';
}
$subcategories = '<ul class="children'.$active.'">';
$string .= $subcategories;
}
if (value_is_true($hierarchy) && $category->depth < $depth) {
for ($i = $depth; $i > $category->depth; $i--) {
if (substr($string,strlen($subcategories)*-1) == $subcategories) {
// If the child menu is empty, remove the <ul> to avoid breaking standards
$string = substr($string,0,strlen($subcategories)*-1).'</li>';
} else $string .= '</ul></li>';
}
}
if (SHOPP_PERMALINKS) $link = $Shopp->shopuri.'category/'.$category->uri;
else $link = add_query_arg('shopp_category',(!empty($category->id)?$category->id:$category->uri),$Shopp->shopuri);
$total = '';
if (value_is_true($products) && $category->total > 0) $total = ' <span>('.$category->total.')</span>';
$current = '';
if (isset($Shopp->Category) && $Shopp->Category->slug == $category->slug)
$current = ' class="current"';
$listing = '';
if ($category->total > 0 || isset($category->smart) || $linkall)
$listing = '<a href="'.$link.'"'.$current.'>'.$category->name.($linkcount?$total:'').'</a>'.(!$linkcount?$total:'');
else $listing = $category->name;
if (value_is_true($showall) ||
$category->total > 0 ||
isset($category->smart) ||
$category->children)
$string .= '<li'.$current.'>'.$listing.'</li>';
$previous = &$category;
$depth = $category->depth;
}
if (value_is_true($hierarchy) && $depth > 0)
for ($i = $depth; $i > 0; $i--) {
if (substr($string,strlen($subcategories)*-1) == $subcategories) {
// If the child menu is empty, remove the <ul> to avoid breaking standards
$string = substr($string,0,strlen($subcategories)*-1).'</li>';
} else $string .= '</ul></li>';
}
if ($wraplist) $string .= '</ul>';
}
return $string;
break;
case "views":
if (isset($Shopp->Category->controls)) return false;
$string = "";
$string .= '<ul class="views">';
if (isset($options['label'])) $string .= '<li>'.$options['label'].'</li>';
$string .= '<li><button type="button" class="grid"></button></li>';
$string .= '<li><button type="button" class="list"></button></li>';
$string .= '</ul>';
return $string;
case "orderby-list":
if (isset($Shopp->Category->controls)) return false;
if (isset($Shopp->Category->smart)) return false;
$menuoptions = Category::sortoptions();
$title = "";
$string = "";
$default = $Shopp->Settings->get('default_product_order');
if (empty($default)) $default = "title";
if (isset($options['default'])) $default = $options['default'];
if (isset($options['title'])) $title = $options['title'];
if (value_is_true($options['dropdown'])) {
if (isset($Shopp->Cart->data->Category['orderby']))
$default = $Shopp->Cart->data->Category['orderby'];
$string .= $title;
$string .= '<form action="'.esc_url($_SERVER['REQUEST_URI']).'" method="get" id="shopp-'.$Shopp->Category->slug.'-orderby-menu">';
if (!SHOPP_PERMALINKS) {
foreach ($_GET as $key => $value)
if ($key != 'shopp_orderby') $string .= '<input type="hidden" name="'.$key.'" value="'.$value.'" />';
}
$string .= '<select name="shopp_orderby" class="shopp-orderby-menu">';
$string .= menuoptions($menuoptions,$default,true);
$string .= '</select>';
$string .= '</form>';
$string .= '<script type="text/javascript">';
$string .= "jQuery('#shopp-".$Shopp->Category->slug."-orderby-menu select.shopp-orderby-menu').change(function () { this.form.submit(); });";
$string .= '</script>';
} else {
if (strpos($_SERVER['REQUEST_URI'],"?") !== false)
list($link,$query) = explode("\?",$_SERVER['REQUEST_URI']);
$query = $_GET;
unset($query['shopp_orderby']);
$query = http_build_query($query);
if (!empty($query)) $query .= '&';
foreach($menuoptions as $value => $option) {
$label = $option;
$href = esc_url($link.'?'.$query.'shopp_orderby='.$value);
$string .= '<li><a href="'.$href.'">'.$label.'</a></li>';
}
}
return $string;
break;
case "breadcrumb":
if (isset($Shopp->Category->controls)) return false;
if (empty($this->categories)) $this->load_categories();
$separator = "&nbsp;&raquo; ";
if (isset($options['separator'])) $separator = $options['separator'];
$category = false;
if (isset($Shopp->Cart->data->breadcrumb))
$category = $Shopp->Cart->data->breadcrumb;
$trail = false;
$search = array();
if (isset($Shopp->Cart->data->Search)) $search = array('search'=>$Shopp->Cart->data->Search);
$path = explode("/",$category);
if ($path[0] == "tag") {
$category = "tag";
$search = array('tag'=>urldecode($path[1]));
}
$Category = Catalog::load_category($category,$search);
if (!empty($Category->uri)) {
$type = "category";
if (isset($Category->tag)) $type = "tag";
if (SHOPP_PERMALINKS)
$link = esc_url(add_query_arg($_GET,$Shopp->shopuri.$type.'/'.$Category->uri));
else {
if (isset($Category->smart))
$link = esc_url(add_query_arg(array_merge($_GET,
array('shopp_category'=>$Category->slug,'shopp_pid'=>null)),
$Shopp->shopuri));
else
$link = esc_url(add_query_arg(array_merge($_GET,
array('shopp_category'=>$Category->id,'shopp_pid'=>null)),
$Shopp->shopuri));
}
$filters = false;
if (!empty($Shopp->Cart->data->Category[$Category->slug]))
$filters = ' (<a href="?shopp_catfilters=cancel">'.__('Clear Filters','Shopp').'</a>)';
if (!empty($Shopp->Product))
$trail .= '<li><a href="'.$link.'">'.$Category->name.(!$trail?'':$separator).'</a></li>';
elseif (!empty($Category->name))
$trail .= '<li>'.$Category->name.$filters.(!$trail?'':$separator).'</li>';
// Build category names path by going from the target category up the parent chain
$parentkey = (!empty($Category->id))?$this->categories[$Category->id]->parent:0;
while ($parentkey != 0) {
$tree_category = $this->categories[$parentkey];
if (SHOPP_PERMALINKS) $link = $Shopp->shopuri.'category/'.$tree_category->uri;
else $link = esc_url(add_query_arg(array_merge($_GET,
array('shopp_category'=>$tree_category->id,'shopp_pid'=>null)),
$Shopp->shopuri));
$trail = '<li><a href="'.$link.'">'.$tree_category->name.'</a>'.
(empty($trail)?'':$separator).'</li>'.$trail;
$parentkey = $tree_category->parent;
}
}
$trail = '<li><a href="'.$Shopp->link('catalog').'">'.$pages['catalog']['title'].'</a>'.(empty($trail)?'':$separator).'</li>'.$trail;
return '<ul class="breadcrumb">'.$trail.'</ul>';
break;
case "search":
global $wp;
$type = "hidden";
if (isset($options['type'])) $type = $options['type'];
if ($type == "radio") {
$option = "shopp";
if (isset($options['option'])) $option = $options['option'];
$default = false;
if (isset($options['default'])) $default = value_is_true($options['default']);
$selected = '';
if ($default) $selected = ' checked="checked"';
if (!empty($wp->query_vars['st'])) {
$selected = '';
if ($wp->query_vars['st'] == $option) $selected = ' checked="checked"';
}
if ($option == "blog") return '<input type="radio" name="st" value="blog"'.$selected.' />';
else return '<input type="radio" name="st" value="shopp"'.$selected.' />';
} elseif ($type == "menu") {
if (empty($options['store'])) $options['store'] = __('Search the store','Shopp');
if (empty($options['blog'])) $options['blog'] = __('Search the blog','Shopp');
if (isset($wp->query_vars['st'])) $selected = $wp->query_vars['st'];
$menu = '<select name="st">';
if (isset($options['default']) && $options['default'] == "blog") {
$menu .= '<option value="blog"'.($selected == "blog"?' selected="selected"':'').'>'.$options['blog'].'</option>';
$menu .= '<option value="shopp"'.($selected == "shopp"?' selected="selected"':'').'>'.$options['store'].'</option>';
} else {
$menu .= '<option value="shopp"'.($selected == "shopp"?' selected="selected"':'').'>'.$options['store'].'</option>';
$menu .= '<option value="blog"'.($selected == "blog"?' selected="selected"':'').'>'.$options['blog'].'</option>';
}
$menu .= '</select>';
return $menu;
} else return '<input type="hidden" name="st" value="shopp" />';
break;
case "catalog-products":
if ($property == "catalog-products") $Shopp->Category = new CatalogProducts($options);
case "new-products":
if ($property == "new-products") $Shopp->Category = new NewProducts($options);
case "featured-products":
if ($property == "featured-products") $Shopp->Category = new FeaturedProducts($options);
case "onsale-products":
if ($property == "onsale-products") $Shopp->Category = new OnSaleProducts($options);
case "bestseller-products":
if ($property == "bestseller-products") $Shopp->Category = new BestsellerProducts($options);
case "random-products":
if ($property == "random-products") $Shopp->Category = new RandomProducts($options);
case "tag-products":
if ($property == "tag-products") $Shopp->Category = new TagProducts($options);
case "related-products":
if ($property == "related-products") $Shopp->Category = new RelatedProducts($options);
case "search-products":
if ($property == "search-products") $Shopp->Category = new SearchResults($options);
case "category":
if ($property == "category") {
if (isset($options['name'])) $Shopp->Category = new Category($options['name'],'name');
else if (isset($options['slug'])) $Shopp->Category = new Category($options['slug'],'slug');
else if (isset($options['id'])) $Shopp->Category = new Category($options['id']);
}
if (isset($options['reset'])) return ($Shopp->Category = false);
if (isset($options['title'])) $Shopp->Category->name = $options['title'];
if (isset($options['show'])) $Shopp->Category->loading['limit'] = $options['show'];
if (isset($options['pagination'])) $Shopp->Category->loading['pagination'] = $options['pagination'];
if (isset($options['order'])) $Shopp->Category->loading['order'] = $options['order'];
if (isset($options['load'])) return true;
if (isset($options['controls']) && !value_is_true($options['controls']))
$Shopp->Category->controls = false;
if (isset($options['view'])) {
if ($options['view'] == "grid") $Shopp->Category->view = "grid";
else $Shopp->Category->view = "list";
}
ob_start();
if (isset($Shopp->Category->smart) &&
file_exists(SHOPP_TEMPLATES."/category-{$Shopp->Category->slug}.php"))
include(SHOPP_TEMPLATES."/category-{$Shopp->Category->slug}.php");
elseif (isset($Shopp->Category->id) &&
file_exists(SHOPP_TEMPLATES."/category-{$Shopp->Category->id}.php"))
include(SHOPP_TEMPLATES."/category-{$Shopp->Category->id}.php");
else include(SHOPP_TEMPLATES."/category.php");
$content = ob_get_contents();
ob_end_clean();
$Shopp->Category = false; // Reset the current category
return $content;
break;
case "product":
if (isset($options['name'])) $Shopp->Product = new Product($options['name'],'name');
else if (isset($options['slug'])) $Shopp->Product = new Product($options['slug'],'slug');
else if (isset($options['id'])) $Shopp->Product = new Product($options['id']);
if (isset($options['load'])) return true;
ob_start();
if (file_exists(SHOPP_TEMPLATES."/product-{$Shopp->Product->id}.php"))
include(SHOPP_TEMPLATES."/product-{$Shopp->Product->id}.php");
else include(SHOPP_TEMPLATES."/product.php");
$content = ob_get_contents();
ob_end_clean();
return $content;
break;
case "sideproduct":
$content = false;
$source = $options['source'];
if ($source == "product" && isset($options['product'])) {
// Save original requested product
if ($Shopp->Product) $Requested = $Shopp->Product;
$products = explode(",",$options['product']);
if (!is_array($products)) $products = array($products);
foreach ($products as $product) {
$product = trim($product);
if (empty($product)) continue;
if (preg_match('/^[\d+]$/',$product))
$Shopp->Product = new Product($product);
else $Shopp->Product = new Product($product,'slug');
if (empty($Shopp->Product->id)) continue;
if (isset($options['load'])) return true;
ob_start();
if (file_exists(SHOPP_TEMPLATES."/sideproduct-{$Shopp->Product->id}.php"))
include(SHOPP_TEMPLATES."/sideproduct-{$Shopp->Product->id}.php");
else include(SHOPP_TEMPLATES."/sideproduct.php");
$content .= ob_get_contents();
ob_end_clean();
}
// Restore original requested category
if (!empty($Requested)) $Shopp->Product = $Requested;
else $Shopp->Product = false;
}
if ($source == "category" && isset($options['category'])) {
// Save original requested category
if ($Shopp->Category) $Requested = $Shopp->Category;
if (empty($options['category'])) return false;
$Shopp->Category = Catalog::load_category($options['category']);
$Shopp->Category->load_products($options);
if (isset($options['load'])) return true;
foreach ($Shopp->Category->products as $product) {
$Shopp->Product = $product;
ob_start();
if (file_exists(SHOPP_TEMPLATES."/sideproduct-{$Shopp->Product->id}.php"))
include(SHOPP_TEMPLATES."/sideproduct-{$Shopp->Product->id}.php");
else include(SHOPP_TEMPLATES."/sideproduct.php");
$content .= ob_get_contents();
ob_end_clean();
}
// Restore original requested category
if (!empty($Requested)) $Shopp->Category = $Requested;
else $Shopp->Category = false;
}
return $content;
break;
}
}
} // end Catalog class
?>
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,725 @@
<?php
/**
* Customer class
* Customer contact information
*
* @author Jonathan Davis
* @version 1.0
* @copyright Ingenesis Limited, 28 March, 2008
* @package shopp
**/
class Customer extends DatabaseObject {
static $table = "customer";
var $login;
var $looping = false;
var $management = array(
"account" => "account",
"downloads" => "downloads",
"history" => "history",
"status" => "status",
"logout" => "logout",
);
function Customer ($id=false,$key=false) {
$this->init(self::$table);
if ($this->load($id,$key)) return true;
else return false;
}
function management () {
global $Shopp;
if (isset($_GET['acct'])) {
switch ($_GET['acct']) {
case "receipt": break;
case "history": $this->load_orders(); break;
case "downloads": $this->load_downloads(); break;
// case "logout": $Shopp->Cart->logout(); break;
}
}
if (!empty($_POST['vieworder']) && !empty($_POST['purchaseid'])) {
$Purchase = new Purchase($_POST['purchaseid']);
if ($Purchase->email == $_POST['email']) {
$Shopp->Cart->data->Purchase = $Purchase;
$Purchase->load_purchased();
ob_start();
include(SHOPP_TEMPLATES."/receipt.php");
$content = ob_get_contents();
ob_end_clean();
return '<div id="shopp">'.$content.'</div>';
}
}
if (!empty($_GET['acct']) && !empty($_GET['id'])) {
$Purchase = new Purchase($_GET['id']);
if ($Purchase->customer != $this->id) {
new ShoppError(sprintf(__('Order number %s could not be found in your order history.','Shopp'),$Purchase->id),'customer_order_history',SHOPP_AUTH_ERR);
unset($_GET['acct']);
return false;
} else {
$Shopp->Cart->data->Purchase = $Purchase;
$Purchase->load_purchased();
ob_start();
include(SHOPP_TEMPLATES."/receipt.php");
$content = ob_get_contents();
ob_end_clean();
}
$management = apply_filters('shopp_account_management_url',
'<p><a href="'.$this->tag('url').'">&laquo; Return to Account Management</a></p>');
echo '<div id="shopp">'.$management.$content.$management.'</div>';
return false;
}
if (!empty($_POST['customer'])) {
$this->updates($_POST);
if ($_POST['password'] == $_POST['confirm-password'])
$this->password = wp_hash_password($_POST['password']);
$this->save();
}
}
function recovery () {
global $Shopp;
$authentication = $Shopp->Settings->get('account_system');
$errors = array();
// Check email or login supplied
if (empty($_POST['account-login'])) {
if ($authentication == "wordpress") $errors[] = new ShoppError(__('Enter an email address or login name','Shopp'));
else $errors[] = new ShoppError(__('Enter an email address','Shopp'));
} else {
// Check that the account exists
if (strpos($_POST['account-login'],'@') !== false) {
$RecoveryCustomer = new Customer($_POST['account-login'],'email');
if (!$RecoveryCustomer->id)
$errors[] = new ShoppError(__('There is no user registered with that email address.','Shopp'),'password_recover_noaccount',SHOPP_AUTH_ERR);
} else {
$user_data = get_userdatabylogin($_POST['account-login']);
$RecoveryCustomer = new Customer($user_data->ID,'wpuser');
if (empty($RecoveryCustomer->id))
$errors[] = new ShoppError(__('There is no user registered with that login name.','Shopp'),'password_recover_noaccount',SHOPP_AUTH_ERR);
}
}
// return errors
if (!empty($errors)) return;
// Generate new key
$RecoveryCustomer->activation = wp_generate_password(20, false);
do_action_ref_array('shopp_generate_password_key', array(&$RecoveryCustomer));
$RecoveryCustomer->save();
$subject = apply_filters('shopp_recover_password_subject', sprintf(__('[%s] Password Recovery Request','Shopp'),get_option('blogname')));
$_ = array();
$_[] = 'From: "'.get_option('blogname').'" <'.$Shopp->Settings->get('merchant_email').'>';
$_[] = 'To: '.$RecoveryCustomer->email;
$_[] = 'Subject: '.$subject;
$_[] = '';
$_[] = __('A request has beem made to reset the password for the following site and account:','Shopp');
$_[] = get_option('siteurl');
$_[] = '';
if (isset($_POST['email-login']))
$_[] = sprintf(__('Email: %s','Shopp'), $RecoveryCustomer->email);
if (isset($_POST['loginname-login']))
$_[] = sprintf(__('Login name: %s','Shopp'), $user_data->user_login);
$_[] = '';
$_[] = __('To reset your password visit the following address, otherwise just ignore this email and nothing will happen.');
$_[] = '';
$_[] = add_query_arg(array('acct'=>'rp','key'=>$RecoveryCustomer->activation),$Shopp->link('account'));
$message = apply_filters('shopp_recover_password_message',join("\r\n",$_));
if (!shopp_email($message)) {
new ShoppError(__('The e-mail could not be sent.'),'password_recovery_email',SHOPP_ERR);
shopp_redirect(add_query_arg('acct','recover',$Shopp->link('account')));
} else {
new ShoppError(__('Check your email address for instructions on resetting the password for your account.','Shopp'),'password_recovery_email',SHOPP_ERR);
}
}
function reset_password ($activation) {
global $Shopp;
$authentication = $Shopp->Settings->get('account_system');
$user_data = false;
$activation = preg_replace('/[^a-z0-9]/i', '', $activation);
$errors = array();
if (empty($activation) || !is_string($activation))
$errors[] = new ShoppError(__('Invalid key'));
$RecoveryCustomer = new Customer($activation,'activation');
if (empty($RecoveryCustomer->id))
$errors[] = new ShoppError(__('Invalid key'));
if (!empty($errors)) return false;
// Generate a new random password
$password = wp_generate_password();
do_action_ref_array('password_reset', array(&$RecoveryCustomer,$password));
$RecoveryCustomer->password = wp_hash_password($password);
if ($authentication == "wordpress") {
$user_data = get_userdata($RecoveryCustomer->wpuser);
wp_set_password($password, $user_data->ID);
}
$RecoveryCustomer->activation = '';
$RecoveryCustomer->save();
$subject = apply_filters('shopp_reset_password_subject', sprintf(__('[%s] New Password','Shopp'),get_option('blogname')));
$_ = array();
$_[] = 'From: "'.get_option('blogname').'" <'.$Shopp->Settings->get('merchant_email').'>';
$_[] = 'To: '.$RecoveryCustomer->email;
$_[] = 'Subject: '.$subject;
$_[] = '';
$_[] = sprintf(__('Your new password for %s:','Shopp'),get_option('siteurl'));
$_[] = '';
if ($user_data)
$_[] = sprintf(__('Login name: %s','Shopp'), $user_data->user_login);
$_[] = sprintf(__('Password: %s'), $password) . "\r\n";
$_[] = '';
$_[] = __('Click here to login:').' '.$Shopp->link('account');
$message = apply_filters('shopp_reset_password_message',join("\r\n",$_));
if (!shopp_email($message)) {
new ShoppError(__('The e-mail could not be sent.'),'password_reset_email',SHOPP_ERR);
shopp_redirect(add_query_arg('acct','recover',$Shopp->link('account')));
} else {
new ShoppError(__('Check your email address for your new password.','Shopp'),'password_reset_email',SHOPP_ERR);
}
unset($_GET['acct']);
}
function load_downloads () {
if (empty($this->id)) return false;
$db =& DB::get();
$orders = DatabaseObject::tablename(Purchase::$table);
$purchases = DatabaseObject::tablename(Purchased::$table);
$pricing = DatabaseObject::tablename(Price::$table);
$asset = DatabaseObject::tablename(Asset::$table);
$query = "SELECT p.*,f.name as filename,f.size,f.properties FROM $purchases AS p LEFT JOIN $orders AS o ON o.id=p.purchase LEFT JOIN $asset AS f ON f.parent=p.price WHERE o.customer=$this->id AND f.size > 0";
$this->downloads = $db->query($query,AS_ARRAY);
}
function load_orders ($filters=array()) {
if (empty($this->id)) return false;
global $Shopp;
$db =& DB::get();
$where = '';
if (isset($filters['where'])) $where = " AND {$filters['where']}";
$orders = DatabaseObject::tablename(Purchase::$table);
$purchases = DatabaseObject::tablename(Purchased::$table);
$query = "SELECT o.* FROM $orders AS o LEFT JOIN $purchases AS p ON p.purchase=o.id WHERE o.customer=$this->id $where ORDER BY created DESC";
$Shopp->purchases = $db->query($query,AS_ARRAY);
foreach($Shopp->purchases as &$p) {
$Purchase = new Purchase();
$Purchase->updates($p);
$p = $Purchase;
}
}
function new_wpuser () {
global $Shopp;
require_once(ABSPATH."/wp-includes/registration.php");
if (empty($this->login)) return false;
if (username_exists($this->login)){
new ShoppError(__('The login name you provided is already in use. Please choose another login name.','Shopp'),'login_exists',SHOPP_ERR);
return false;
}
if (empty($this->password)) $this->password = wp_generate_password(12,true);
// Create the WordPress account
$wpuser = wp_insert_user(array(
'user_login' => $this->login,
'user_pass' => $this->password,
'user_email' => $this->email,
'display_name' => $this->firstname.' '.$this->Customer->lastname,
'nickname' => $handle,
'first_name' => $this->firstname,
'last_name' => $this->lastname
));
if (!$wpuser) return false;
// Link the WP user ID to this customer record
$this->wpuser = $wpuser;
// Send email notification of the new account
wp_new_user_notification( $wpuser, $this->password );
$this->password = "";
if (SHOPP_DEBUG) new ShoppError('Successfully created the WordPress user for the Shopp account.',false,SHOPP_DEBUG_ERR);
return true;
}
function exportcolumns () {
$prefix = "c.";
return array(
$prefix.'firstname' => __('Customer\'s First Name','Shopp'),
$prefix.'lastname' => __('Customer\'s Last Name','Shopp'),
$prefix.'email' => __('Customer\'s Email Address','Shopp'),
$prefix.'phone' => __('Customer\'s Phone Number','Shopp'),
$prefix.'company' => __('Customer\'s Company','Shopp'),
$prefix.'info' => __('Customer\'s Custom Information','Shopp'),
$prefix.'created' => __('Customer Created Date','Shopp'),
$prefix.'modified' => __('Customer Last Updated Date','Shopp'),
);
}
function tag ($property,$options=array()) {
global $Shopp;
$menus = array(
"account" => __("My Account","Shopp"),
"downloads" => __("Downloads","Shopp"),
"history" => __("Order History","Shopp"),
"status" => __("Order Status","Shopp"),
"logout" => __("Logout","Shopp")
);
// Return strings with no options
switch ($property) {
case "url": return $Shopp->link('account');
case "recover-url": return add_query_arg('acct','recover',$Shopp->link('account'));
case "process":
if (isset($_GET['acct'])) return $_GET['acct'];
return false;
case "loggedin": return $Shopp->Cart->data->login; break;
case "notloggedin": return (!$Shopp->Cart->data->login && $Shopp->Settings->get('account_system') != "none"); break;
case "login-label":
$accounts = $Shopp->Settings->get('account_system');
$label = __('Email Address','Shopp');
if ($accounts == "wordpress") $label = __('Login Name','Shopp');
if (isset($options['label'])) $label = $options['label'];
return $label;
break;
case "email-login":
case "loginname-login":
case "account-login":
if (!empty($_POST['account-login']))
$options['value'] = $_POST['account-login'];
return '<input type="text" name="account-login" id="account-login"'.inputattrs($options).' />';
break;
case "password-login":
if (!empty($_POST['password-login']))
$options['value'] = $_POST['password-login'];
return '<input type="password" name="password-login" id="password-login"'.inputattrs($options).' />';
break;
case "recover-button":
if (!isset($options['value'])) $options['value'] = __('Get New Password','Shopp');
return '<input type="submit" name="recover-login" id="recover-button"'.inputattrs($options).' />';
break;
case "submit-login": // Deprecating
case "login-button":
if (!isset($options['value'])) $options['value'] = __('Login','Shopp');
if (is_shopp_page('account'))
$string = '<input type="hidden" name="process-login" id="process-login" value="true" />';
else $string = '<input type="hidden" name="process-login" id="process-login" value="false" />';
$string .= '<input type="submit" name="submit-login" id="submit-login"'.inputattrs($options).' />';
return $string;
break;
case "errors-exist":
$Errors =& ShoppErrors();
return ($Errors->exist(SHOPP_AUTH_ERR));
break;
case "login-errors":
$Errors =& ShoppErrors();
$result = "";
if (!$Errors->exist(SHOPP_AUTH_ERR)) return false;
$errors = $Errors->get(SHOPP_AUTH_ERR);
foreach ((array)$errors as $error)
if (!empty($error)) $result .= '<p class="error">'.$error->message().'</p>';
$Errors->reset();
return $result;
break;
case "menu":
if (!$this->looping) {
reset($this->management);
$this->looping = true;
} else next($this->management);
if (current($this->management)) return true;
else {
$this->looping = false;
reset($this->management);
return false;
}
break;
case "management":
if (array_key_exists('url',$options)) return add_query_arg('acct',key($this->management),$Shopp->link('account'));
if (array_key_exists('action',$options)) return key($this->management);
return $menus[key($this->management)];
case "accounts": return $Shopp->Settings->get('account_system'); break;
case "order-lookup":
$auth = $Shopp->Settings->get('account_system');
if ($auth != "none") return true;
if (!empty($_POST['vieworder']) && !empty($_POST['purchaseid'])) {
require_once("Purchase.php");
$Purchase = new Purchase($_POST['purchaseid']);
if ($Purchase->email == $_POST['email']) {
$Shopp->Cart->data->Purchase = $Purchase;
$Purchase->load_purchased();
ob_start();
include(SHOPP_TEMPLATES."/receipt.php");
$content = ob_get_contents();
ob_end_clean();
return '<div id="shopp">'.$content.'</div>';
}
}
ob_start();
include(SHOPP_ADMINPATH."/orders/account.php");
$content = ob_get_contents();
ob_end_clean();
return '<div id="shopp">'.$content.'</div>';
break;
case "firstname":
if ($options['mode'] == "value") return $this->firstname;
if (!empty($this->firstname))
$options['value'] = $this->firstname;
return '<input type="text" name="firstname" id="firstname"'.inputattrs($options).' />';
break;
case "lastname":
if ($options['mode'] == "value") return $this->lastname;
if (!empty($this->lastname))
$options['value'] = $this->lastname;
return '<input type="text" name="lastname" id="lastname"'.inputattrs($options).' />';
break;
case "company":
if ($options['mode'] == "value") return $this->company;
if (!empty($this->company))
$options['value'] = $this->company;
return '<input type="text" name="company" id="company"'.inputattrs($options).' />';
break;
case "email":
if ($options['mode'] == "value") return $this->email;
if (!empty($this->email))
$options['value'] = $this->email;
return '<input type="text" name="email" id="email"'.inputattrs($options).' />';
break;
case "loginname":
if ($options['mode'] == "value") return $this->loginname;
if (!empty($this->login))
$options['value'] = $this->login;
return '<input type="text" name="login" id="login"'.inputattrs($options).' />';
break;
case "password":
if ($options['mode'] == "value")
return strlen($this->password) == 34?str_pad('&bull;',8):$this->password;
if (!empty($this->password))
$options['value'] = $this->password;
return '<input type="password" name="password" id="password"'.inputattrs($options).' />';
break;
case "confirm-password":
if (!empty($this->confirm_password))
$options['value'] = $this->confirm_password;
return '<input type="password" name="confirm-password" id="confirm-password"'.inputattrs($options).' />';
break;
case "phone":
if ($options['mode'] == "value") return $this->phone;
if (!empty($this->phone))
$options['value'] = $this->phone;
return '<input type="text" name="phone" id="phone"'.inputattrs($options).' />';
break;
case "hasinfo":
case "has-info":
if (empty($this->info)) return false;
if (!$this->looping) {
reset($this->info);
$this->looping = true;
} else next($this->info);
if (current($this->info)) return true;
else {
$this->looping = false;
reset($this->info);
return false;
}
break;
case "info":
$info = current($this->info);
$name = key($this->info);
$allowed_types = array("text","password","hidden","checkbox","radio");
if (empty($options['type'])) $options['type'] = "hidden";
if (in_array($options['type'],$allowed_types)) {
if ($options['mode'] == "name") return $name;
if ($options['mode'] == "value") return $info;
$options['value'] = $info;
return '<input type="text" name="info['.$name.']" id="customer-info-'.$name.'"'.inputattrs($options).' />';
}
break;
case "save-button":
if (!isset($options['label'])) $options['label'] = __('Save','Shopp');
$result = '<input type="hidden" name="customer" value="true" />';
$result .= '<input type="submit" name="save" id="save-button"'.inputattrs($options).' />';
return $result;
break;
// Downloads UI tags
case "hasdownloads":
case "has-downloads": return (!empty($this->downloads)); break;
case "downloads":
if (empty($this->downloads)) return false;
if (!$this->looping) {
reset($this->downloads);
$this->looping = true;
} else next($this->downloads);
if (current($this->downloads)) return true;
else {
$this->looping = false;
reset($this->downloads);
return false;
}
break;
case "download":
$download = current($this->downloads);
$df = get_option('date_format');
$properties = unserialize($download->properties);
$string = '';
if (array_key_exists('id',$options)) $string .= $download->download;
if (array_key_exists('purchase',$options)) $string .= $download->purchase;
if (array_key_exists('name',$options)) $string .= $download->name;
if (array_key_exists('variation',$options)) $string .= $download->optionlabel;
if (array_key_exists('downloads',$options)) $string .= $download->downloads;
if (array_key_exists('key',$options)) $string .= $download->dkey;
if (array_key_exists('created',$options)) $string .= $download->created;
if (array_key_exists('total',$options)) $string .= money($download->total);
if (array_key_exists('filetype',$options)) $string .= $properties['mimetype'];
if (array_key_exists('size',$options)) $string .= readableFileSize($download->size);
if (array_key_exists('date',$options)) $string .= _d($df,mktimestamp($download->created));
if (array_key_exists('url',$options)) $string .= (SHOPP_PERMALINKS) ?
$Shopp->shopuri."download/".$download->dkey :
add_query_arg('shopp_download',$download->dkey,$Shopp->link('account'));
return $string;
break;
// Downloads UI tags
case "haspurchases":
case "has-purchases":
$filters = array();
if (isset($options['daysago']))
$filters['where'] = "UNIX_TIMESTAMP(o.created) > UNIX_TIMESTAMP()-".($options['daysago']*86400);
if (empty($Shopp->purchases)) $this->load_orders($filters);
return (!empty($Shopp->purchases));
break;
case "purchases":
if (!$this->looping) {
reset($Shopp->purchases);
$Shopp->Cart->data->Purchase = current($Shopp->purchases);
$this->looping = true;
} else {
$Shopp->Cart->data->Purchase = next($Shopp->purchases);
}
if (current($Shopp->purchases)) {
$Shopp->Cart->data->Purchase = current($Shopp->purchases);
return true;
}
else {
$this->looping = false;
return false;
}
break;
case "receipt":
return add_query_arg(
array(
'acct'=>'receipt',
'id'=>$Shopp->Cart->data->Purchase->id),
$Shopp->link('account'));
}
}
} // end Customer class
class CustomersExport {
var $sitename = "";
var $headings = false;
var $data = false;
var $defined = array();
var $customer_cols = array();
var $billing_cols = array();
var $shipping_cols = array();
var $selected = array();
var $recordstart = true;
var $content_type = "text/plain";
var $extension = "txt";
function CustomersExport () {
global $Shopp;
$this->customer_cols = Customer::exportcolumns();
$this->billing_cols = Billing::exportcolumns();
$this->shipping_cols = Shipping::exportcolumns();
$this->defined = array_merge($this->customer_cols,$this->billing_cols,$this->shipping_cols);
$this->sitename = get_bloginfo('name');
$this->headings = ($Shopp->Settings->get('customerexport_headers') == "on");
$this->selected = $Shopp->Settings->get('customerexport_columns');
$Shopp->Settings->save('customerexport_lastexport',mktime());
}
function query ($request=array()) {
$db =& DB::get();
if (empty($request)) $request = $_GET;
if (!empty($request['start'])) {
list($month,$day,$year) = explode("/",$request['start']);
$starts = mktime(0,0,0,$month,$day,$year);
}
if (!empty($request['end'])) {
list($month,$day,$year) = explode("/",$request['end']);
$ends = mktime(0,0,0,$month,$day,$year);
}
$where = "WHERE c.id IS NOT NULL ";
if (isset($request['s']) && !empty($request['s'])) $where .= " AND (id='{$request['s']}' OR firstname LIKE '%{$request['s']}%' OR lastname LIKE '%{$request['s']}%' OR CONCAT(firstname,' ',lastname) LIKE '%{$request['s']}%' OR transactionid LIKE '%{$request['s']}%')";
if (!empty($request['start']) && !empty($request['end'])) $where .= " AND (UNIX_TIMESTAMP(c.created) >= $starts AND UNIX_TIMESTAMP(c.created) <= $ends)";
$customer_table = DatabaseObject::tablename(Customer::$table);
$billing_table = DatabaseObject::tablename(Billing::$table);
$shipping_table = DatabaseObject::tablename(Shipping::$table);
$c = 0; $columns = array();
foreach ($this->selected as $column) $columns[] = "$column AS col".$c++;
$query = "SELECT ".join(",",$columns)." FROM $customer_table AS c LEFT JOIN $billing_table AS b ON c.id=b.customer LEFT JOIN $shipping_table AS s ON c.id=s.customer $where ORDER BY c.created ASC";
$this->data = $db->query($query,AS_ARRAY);
}
// Implement for exporting all the data
function output () {
if (!$this->data) $this->query();
if (!$this->data) return false;
header("Content-type: $this->content_type; charset=UTF-8");
header("Content-Disposition: attachment; filename=\"$this->sitename Customer Export.$this->extension\"");
header("Content-Description: Delivered by WordPress/Shopp ".SHOPP_VERSION);
header("Cache-Control: maxage=1");
header("Pragma: public");
$this->begin();
if ($this->headings) $this->heading();
$this->records();
$this->end();
}
function begin() {}
function heading () {
foreach ($this->selected as $name)
$this->export($this->defined[$name]);
$this->record();
}
function records () {
foreach ($this->data as $key => $record) {
foreach(get_object_vars($record) as $column)
$this->export($this->parse($column));
$this->record();
}
}
function parse ($column) {
if (preg_match("/^[sibNaO](?:\:.+?\{.*\}$|\:.+;$|;$)/",$column)) {
$list = unserialize($column);
$column = "";
foreach ($list as $name => $value)
$column .= (empty($column)?"":";")."$name:$value";
}
return $column;
}
function end() {}
// Implement for exporting a single value
function export ($value) {
echo ($this->recordstart?"":"\t").$value;
$this->recordstart = false;
}
function record () {
echo "\n";
$this->recordstart = true;
}
}
class CustomersTabExport extends CustomersExport {
function CustomersTabExport () {
parent::CustomersExport();
$this->output();
}
}
class CustomersCSVExport extends CustomersExport {
function CustomersCSVExport () {
parent::CustomersExport();
$this->content_type = "text/csv";
$this->extension = "csv";
$this->output();
}
function export ($value) {
$value = str_replace('"','""',$value);
if (preg_match('/^\s|[,"\n\r]|\s$/',$value)) $value = '"'.$value.'"';
echo ($this->recordstart?"":",").$value;
$this->recordstart = false;
}
}
class CustomersXLSExport extends CustomersExport {
function CustomersXLSExport () {
parent::CustomersExport();
$this->content_type = "application/vnd.ms-excel";
$this->extension = "xls";
$this->c = 0; $this->r = 0;
$this->output();
}
function begin () {
echo pack("ssssss", 0x809, 0x8, 0x0, 0x10, 0x0, 0x0);
}
function end () {
echo pack("ss", 0x0A, 0x00);
}
function export ($value) {
if (preg_match('/^[\d\.]+$/',$value)) {
echo pack("sssss", 0x203, 14, $this->r, $this->c, 0x0);
echo pack("d", $value);
} else {
$l = strlen($value);
echo pack("ssssss", 0x204, 8+$l, $this->r, $this->c, 0x0, $l);
echo $value;
}
$this->c++;
}
function record () {
$this->c = 0;
$this->r++;
}
}
?>
@@ -0,0 +1,273 @@
<?php
/**
* Error class
* Error message handler class
*
* @author Jonathan Davis
* @version 1.0
* @copyright Ingenesis Limited, 28 March, 2008
* @package shopp
**/
define('SHOPP_ERR',1);
define('SHOPP_TRXN_ERR',2);
define('SHOPP_AUTH_ERR',4);
define('SHOPP_ADDON_ERR',8);
define('SHOPP_COMM_ERR',16);
define('SHOPP_STOCK_ERR',32);
define('SHOPP_ADMIN_ERR',64);
define('SHOPP_DB_ERR',128);
define('SHOPP_PHP_ERR',256);
define('SHOPP_ALL_ERR',1024);
define('SHOPP_DEBUG_ERR',2048);
if (!defined('SHOPP_ERROR_REPORTING') && WP_DEBUG) define('SHOPP_ERROR_REPORTING',SHOPP_DEBUG_ERR);
if (!defined('SHOPP_ERROR_REPORTING')) define('SHOPP_ERROR_REPORTING',SHOPP_ALL_ERR);
class ShoppErrors {
var $errors = array();
var $notifications;
function ShoppErrors () {
$this->notifications = new CallbackSubscription();
$types = E_ALL ^ E_NOTICE;
if (defined('WP_DEBUG') && WP_DEBUG) $types = E_ALL;
// Handle PHP errors
if (SHOPP_ERROR_REPORTING >= SHOPP_PHP_ERR)
set_error_handler(array($this,'phperror'),$types);
}
function add ($ShoppError) {
$this->errors[$ShoppError->source] = $ShoppError;
$this->notifications->send($ShoppError);
}
function get ($level=SHOPP_DEBUG_ERR) {
$errors = array();
foreach ($this->errors as &$error)
if ($error->level <= $level) $errors[] = &$error;
return $errors;
}
function exist ($level=SHOPP_DEBUG_ERR) {
$errors = array();
foreach ($this->errors as &$error)
if ($error->level <= $level) $errors[] = &$error;
return (count($errors) > 0);
}
function reset () {
$this->errors = array();
}
function phperror ($number, $message, $file, $line) {
if (strpos($file,SHOPP_PATH) !== false)
new ShoppError($message,'php_error',SHOPP_PHP_ERR,
array('file'=>$file,'line'=>$line,'phperror'=>$number));
}
/* Provides functionality for shopp('error') tags */
function tag ($property,$options=array()) {
global $Shopp;
if (empty($options)) return false;
switch ($property) {
case "trxn": new ShoppError(key($options),'template_error',SHOPP_TRXN_ERR); break;
case "auth": new ShoppError(key($options),'template_error',SHOPP_AUTH_ERR); break;
case "addon": new ShoppError(key($options),'template_error',SHOPP_ADDON_ERR); break;
case "comm": new ShoppError(key($options),'template_error',SHOPP_COMM_ERR); break;
case "stock": new ShoppError(key($options),'template_error',SHOPP_STOCK_ERR); break;
case "admin": new ShoppError(key($options),'template_error',SHOPP_ADMIN_ERR); break;
case "db": new ShoppError(key($options),'template_error',SHOPP_DB_ERR); break;
case "debug": new ShoppError(key($options),'template_error',SHOPP_DEBUG_ERR); break;
default: new ShoppError(key($options),'template_error',SHOPP_ERR); break;
}
}
}
class ShoppError {
var $code;
var $source;
var $messages;
var $level;
var $data = array();
var $php = array(
E_ERROR => 'ERROR',
E_WARNING => 'WARNING',
E_PARSE => 'PARSE ERROR',
E_NOTICE => 'NOTICE',
E_CORE_ERROR => 'CORE ERROR',
E_CORE_WARNING => 'CORE WARNING',
E_COMPILE_ERROR => 'COMPILE ERROR',
E_COMPILE_WARNING => 'COMPILE WARNING',
E_USER_ERROR => 'USER ERROR',
E_USER_WARNING => 'USER WARNING',
E_USER_NOTICE => 'USER NOTICE',
E_STRICT => 'STRICT NOTICE',
E_RECOVERABLE_ERROR => 'RECOVERABLE ERROR'
);
function ShoppError($message='',$code='',$level=SHOPP_ERR,$data='') {
if ($level > SHOPP_ERROR_REPORTING) return;
if (empty($message)) return;
$debug = debug_backtrace();
$this->code = $code;
$this->messages[] = $message;
$this->level = $level;
$this->data = $data;
$this->debug = $debug[1];
// Handle template errors
if (isset($this->debug['class']) && $this->debug['class'] == "ShoppErrors")
$this->debug = $debug[2];
if (isset($data['file'])) $this->debug['file'] = $data['file'];
if (isset($data['line'])) $this->debug['line'] = $data['line'];
unset($this->debug['object'],$this->debug['args']);
$this->source = "Shopp";
if (isset($this->debug['class'])) $this->source = $this->debug['class'];
if (isset($this->data['phperror'])) $this->source = "PHP ".$this->php[$this->data['phperror']];
$Errors = &ShoppErrors();
if (!empty($Errors)) $Errors->add($this);
}
function message ($delimiter="\n") {
$string = "";
// Show source if debug is on, or not a general error message
if (((defined('WP_DEBUG') && WP_DEBUG) || $this->level > SHOPP_ERR) &&
!empty($this->source)) $string .= "$this->source: ";
$string .= join($delimiter,$this->messages);
return $string;
}
}
class ShoppErrorLogging {
var $dir;
var $file = "shopp_errors.log";
var $logfile;
var $log;
var $loglevel = 0;
function ShoppErrorLogging ($loglevel=0) {
$this->loglevel = $loglevel;
$this->dir = defined('SHOPP_TEMP_PATH') ? SHOPP_TEMP_PATH : sys_get_temp_dir();
$this->dir = str_replace('\\', '/', $this->dir); //Windows path sanitiation
$sitename = sanitize_title_with_dashes(get_bloginfo('sitename'));
$this->logfile = trailingslashit($this->dir).$sitename."-".$this->file;
$Errors = &ShoppErrors();
$Errors->notifications->subscribe($this,'log');
}
function log (&$error) {
if ($error->level > $this->loglevel) return;
$debug = "";
if (isset($error->debug['file'])) $debug = " [".basename($error->debug['file']).", line ".$error->debug['line']."]";
$message = date("Y-m-d H:i:s",mktime())." - ".$error->message().$debug."\n";
if ($this->log = @fopen($this->logfile,'at')) {
fwrite($this->log,$message);
fclose($this->log);
}
}
function reset () {
$this->log = fopen($this->logfile,'w');
fwrite($this->log,'');
fclose($this->log);
}
function tail($lines=100) {
if (!file_exists($this->logfile)) return;
$f = fopen($this->logfile, "r");
$c = $lines;
$pos = -2;
$beginning = false;
$text = array();
while ($c > 0) {
$t = "";
while ($t != "\n") {
if(fseek($f, $pos, SEEK_END) == -1) { $beginning = true; break; }
$t = fgetc($f);
$pos--;
}
$c--;
if($beginning) rewind($f);
$text[$lines-$c-1] = fgets($f);
if($beginning) break;
}
fclose($f);
return array_reverse($text);
}
}
class ShoppErrorNotification {
var $recipients;
var $types=0;
function ShoppErrorNotification ($recipients='',$types=array()) {
if (empty($recipients)) return;
$this->recipients = $recipients;
foreach ((array)$types as $type) $this->types += $type;
$Errors = &ShoppErrors();
$Errors->notifications->subscribe($this,'notify');
}
function notify (&$error) {
if (!($error->level & $this->types)) return;
$url = parse_url(get_bloginfo('url'));
$_ = array();
$_[] = 'From: "'.get_bloginfo('sitename').'" <shopp@'.$url['host'].'>';
$_[] = 'To: '.$this->recipients;
$_[] = 'Subject: '.__('Shopp Notification','Shopp');
$_[] = '';
$_[] = __('This is an automated message notification generated when the Shopp installation at '.get_bloginfo('url').' encountered the following:','Shopp');
$_[] = '';
$_[] = $error->message();
$_[] = '';
if (isset($error->debug['file']) && defined('WP_DEBUG'))
$_[] = 'DEBUG: '.basename($error->debug['file']).', line '.$error->debug['line'].'';
shopp_email(join("\r\n",$_));
}
}
class CallbackSubscription {
var $subscribers = array();
function subscribe ($target,$method) {
if (!isset($this->subscribers[get_class($target)]))
$this->subscribers[get_class($target)] = array(&$target,$method);
}
function send () {
$args = func_get_args();
foreach ($this->subscribers as $callback) {
if (version_compare(PHP_VERSION, '5.3.0') === -1) call_user_func_array($callback,$args);
else call_user_func_array($callback,&$args);
}
}
}
function &ShoppErrors () {
global $Shopp;
return $Shopp->Cart->data->Errors;
}
function is_shopperror ($e) {
return (get_class($e) == "ShoppError");
}
?>
@@ -0,0 +1,132 @@
<?php
/**
* Gateway classes
* Generic prototype classes for local and remote payment systems
*
* @author Jonathan Davis
* @version 1.0
* @copyright Ingenesis Limited, 17 March, 2009
* @package shopp
**/
class Gateway {
var $transaction = array();
var $settings = array();
var $Response = false;
var $cards = array("Visa", "MasterCard", "Amex", "Discover");
var $type = "local";
function Gateway (&$Order="") {
global $Shopp;
$this->classname = get_class($this);
$this->uid = strtolower($this->classname)."-settings";
$this->settings = $Shopp->Settings->get($this->classname);
$this->settings['merchant_email'] = $Shopp->Settings->get('merchant_email');
if (!isset($this->settings['cards'])) $this->settings['cards'] = $this->cards;
// $this->file = __FILE__;
// if (!empty($Order)) $this->build($Order);
// return true;
}
function build ($Order) {
$_ = array();
$this->transaction = join("",$_);
}
function process () {
$this->Response = $this->send();
$status = $this->Response; // Get the response status
if ($status == "APPROVED") return true;
else return false;
}
function transactionid () {
$transaction = $this->Response->transaction;
if (!empty($transaction)) return $transaction;
return false;
}
function error () {
if (empty($this->Response)) return false;
$message = __('Gateway response error.','Shopp');
if (class_exists('ShoppError')) {
if (empty($message)) return new ShoppError(__("An unknown error occurred while processing this transaction. Please contact the site administrator.","Shopp"),'gateway_trxn_error',SHOPP_TRXN_ERR);
return new ShoppError($message,'gateway_trxn_error',SHOPP_TRXN_ERR);
} else {
$Error = new stdClass();
$Error->code = 'gateway_trxn_error';
$Error->message = $message;
return $Error;
}
}
function send () {
$connection = curl_init();
curl_setopt($connection,CURLOPT_URL,$this->url);
curl_setopt($connection, CURLOPT_SSL_VERIFYPEER, 0);
curl_setopt($connection, CURLOPT_SSL_VERIFYHOST, 0);
curl_setopt($connection, CURLOPT_NOPROGRESS, 1);
curl_setopt($connection, CURLOPT_VERBOSE, 1);
curl_setopt($connection, CURLOPT_FOLLOWLOCATION,0);
curl_setopt($connection, CURLOPT_POST, 1);
curl_setopt($connection, CURLOPT_POSTFIELDS, $this->transaction);
curl_setopt($connection, CURLOPT_TIMEOUT, 30);
curl_setopt($connection, CURLOPT_USERAGENT, SHOPP_GATEWAY_USERAGENT);
curl_setopt($connection, CURLOPT_REFERER, "https://".$_SERVER['SERVER_NAME']);
curl_setopt($connection, CURLOPT_RETURNTRANSFER, 1);
$buffer = curl_exec($connection);
if ($error = curl_error($connection)) {
if (class_exists('ShoppError')) new ShoppError($error,'gateway_connection',SHOPP_COMM_ERR);
}
curl_close($connection);
$this->Response = $this->response($buffer);
return $this->Response;
}
function response ($string) {
return $string;
}
function settings () {
global $Shopp;
?>
<tr id="<?php echo $this->uid; ?>-settings" class="addon">
<th scope="row" valign="top">Gateway Name</th>
<td>
<div><input type="text" name="settings[<?php echo $this->classname; ?>][account]" id="<?php echo $this->uid; ?>_account" value="<?php echo $this->settings['account']; ?>" size="16" /><br /><label for="<?php echo $this->uid; ?>_account"><?php _e('Enter your Gateway account.'); ?></label></div>
<div><input type="password" name="settings[<?php echo $this->classname; ?>][password]" id="<?php echo $this->uid; ?>_password" value="<?php echo $this->settings['password']; ?>" size="24" /><br /><label for="<?php echo $this->uid; ?>_password"><?php _e('Enter your Gateway password.'); ?></label></div>
<div><input type="hidden" name="settings[<?php echo $this->classname; ?>][testmode]" value="off"><input type="checkbox" name="settings[<?php echo $this->classname; ?>][testmode]" id="<?php echo $this->uid; ?>_testmode" value="on"<?php echo ($this->settings['testmode'] == "on")?' checked="checked"':''; ?> /><label for="<?php echo $this->uid; ?>_testmode"> <?php _e('Enable test mode'); ?></label></div>
<div><strong>Accept these cards:</strong>
<ul class="cards"><?php foreach($this->cards as $id => $card):
$checked = "";
if (in_array($card,$this->settings['cards'])) $checked = ' checked="checked"';
?>
<li><input type="checkbox" name="settings[<?php echo $this->classname; ?>][cards][]" id="<?php echo $this->uid; ?>_cards_<?php echo $id; ?>" value="<?php echo $card; ?>" <?php echo $checked; ?> /><label for="<?php echo $this->uid; ?>_cards_<?php echo $id; ?>"> <?php echo $card; ?></label></li>
<?php endforeach; ?></ul></div>
<input type="hidden" name="module[<?php echo basename($this->file); ?>]" value="<?php echo $this->classname; ?>" />
</td>
</tr>
<?php
}
function registerSettings () {
?>
gatewayHandlers.register('<?php echo addslashes($this->file); ?>',
'<?php echo $this->uid; ?>-settings');<?php
}
function order () {
}
} // end Gateway class
?>
@@ -0,0 +1,260 @@
<?php
/**
* ImageProcessor class
*
*
* @author Jonathan Davis
* @version 1.0
* @copyright Ingenesis Limited, 17 April, 2008
* @package Shopp
**/
class ImageProcessor {
var $src;
var $Processed;
function ImageProcessor ($data,$width,$height) {
$this->src = new StdClass();
$this->src->width = $width;
$this->src->height = $height;
$this->src->image = imagecreatefromstring($data);
}
/**
* scaleToWidth()
* Determine the scale percentage by width of the image,
* height is variable to maintain image proportions
**/
function scaleToWidth($width) {
$scale = $width / $this->src->width;
$this->Processed = new StdClass();
$this->Processed->width = $width;
$this->Processed->height = ceil($this->src->height * $scale);
$this->Processed->image = ImageCreateTrueColor($this->Processed->width,$this->Processed->height);
ImageCopyResampled($this->Processed->image, $this->src->image,
0, 0, 0, 0,
$this->Processed->width, $this->Processed->height, $this->src->width, $this->src->height);
}
/**
* scaleToHeight()
* Determine the scale percentage by height of the image,
* width is variable to maintain image proportions
*/
function scaleToHeight($height) {
$scale = $height / $this->src->height;
$this->Processed = new StdClass();
$this->Processed->height = $height;
$this->Processed->width = ceil($this->src->width * $scale);
$this->Processed->image = ImageCreateTrueColor($this->Processed->width,$this->Processed->height);
ImageCopyResampled($this->Processed->image, $this->src->image,
0, 0, 0, 0,
$this->Processed->width, $this->Processed->height, $this->src->width, $this->src->height);
}
/**
* scaleToFit()
* Resize the image directly to the provided dimensions,
* do not maintain image proportions
*/
function scaleToFit($width,$height) {
$this->Processed = new StdClass();
if ($this->src->width > $this->src->height) { // Scale to width
$scale = $width / $this->src->width;
$this->Processed->width = $width;
$this->Processed->height = ceil($this->src->height * $scale);
} else { // Scale to height
$scale = $height / $this->src->height;
$this->Processed->height = $height;
$this->Processed->width = ceil($this->src->width * $scale);
}
$this->Processed->image = ImageCreateTrueColor($this->Processed->width,$this->Processed->height);
ImageCopyResampled($this->Processed->image, $this->src->image,
0, 0, 0, 0,
$this->Processed->width, $this->Processed->height, $this->src->width, $this->src->height);
}
/**
* scaleCrop()
* Scale based on the smallest dimension,
* cropping the extra on the other dimension to
* maintain image proportion and fit the provided
* dimensions exactly
*/
function scaleCrop($width,$height) {
$this->Processed = new StdClass();
$this->Processed->width = $width;
$this->Processed->height = $height;
$widthScale = $width / $this->src->width;
$heightScale = $height / $this->src->height;
$this->Processed->image = ImageCreateTrueColor($this->Processed->width,$this->Processed->height);
if ($heightScale > $widthScale) {
$scale = $height / $this->src->height; // Scale by height
$width = ceil($this->src->width * $scale); // Determine proportional width
$x = ($width - $this->Processed->width)*-0.5; // Center scaled image on the canvas
ImageCopyResampled($this->Processed->image, $this->src->image,
$x, 0, 0, 0,
$width, $this->Processed->height, $this->src->width, $this->src->height);
} else {
$scale = $width / $this->src->width; // Scale by width
$height = ceil($this->src->height * $scale); // Determine proportional height
$y = ($height - $this->Processed->height)*-0.5; // Center scaled image on the canvas
ImageCopyResampled($this->Processed->image, $this->src->image,
0, $y, 0, 0,
$this->Processed->width, $height, $this->src->width, $this->src->height);
}
}
/**
* Return the processed image
*/
function imagefile ($quality=80) {
if (!isset($this->Processed->image)) return false;
imageinterlace($this->Processed->image, true); // For progressive loading
ob_start(); // Start capturing output buffer stream
imagejpeg($this->Processed->image,NULL,$quality); // Output the image to the stream
$buffer = ob_get_contents(); // Get the bugger
ob_end_clean(); // Clear the buffer
return $buffer; // Send it back
}
/**
* UnsharpMask ()
* version 2.1.1
* Unsharp mask algorithm by Torstein Hansi <thoensi_at_netcom_dot_no>, July 2003
**/
function UnsharpMask ($amount=50, $radius=0.5, $threshold=3) {
if (!isset($this->Processed->image)) return false;
$image = $this->Processed->image;
// Attempt to calibrate the parameters to Photoshop
if ($amount > 500) $amount = 500;
$amount = $amount * 0.016;
if ($radius > 50) $radius = 50;
$radius = $radius * 2;
if ($threshold > 255) $threshold = 255;
$radius = abs(round($radius));
if ($radius == 0) return $image;
$w = imagesx($image); $h = imagesy($image);
$canvas = imagecreatetruecolor($w, $h);
$blur = imagecreatetruecolor($w, $h);
/**
* Gaussian blur matrix:
* 1 2 1
* 2 4 2
* 1 2 1
**/
if (function_exists('imageconvolution')) { // PHP >= 5.1
$matrix = array(
array( 1, 2, 1 ),
array( 2, 4, 2 ),
array( 1, 2, 1 )
);
imagecopy ($blur, $image, 0, 0, 0, 0, $w, $h);
imageconvolution($blur, $matrix, 16, 0);
} else {
// Move copies of the image around one pixel at the time and merge them with weight
// according to the matrix. The same matrix is simply repeated for higher radii.
for ($i = 0; $i < $radius; $i++) {
imagecopy ($blur, $image, 0, 0, 1, 0, $w - 1, $h); // left
imagecopymerge ($blur, $image, 1, 0, 0, 0, $w, $h, 50); // right
imagecopymerge ($blur, $image, 0, 0, 0, 0, $w, $h, 50); // center
imagecopy ($canvas, $blur, 0, 0, 0, 0, $w, $h);
imagecopymerge ($blur, $canvas, 0, 0, 0, 1, $w, $h - 1, 33.33333 ); // up
imagecopymerge ($blur, $canvas, 0, 1, 0, 0, $w, $h, 25); // down
}
}
if ($threshold > 0){
// Calculate the difference between the blurred pixels and the original
// and set the pixels
for ($x = 0; $x < $w-1; $x++) { // each row
for ($y = 0; $y < $h; $y++) { // each pixel
$rgbOrig = ImageColorAt($image, $x, $y);
$rOrig = (($rgbOrig >> 16) & 0xFF);
$gOrig = (($rgbOrig >> 8) & 0xFF);
$bOrig = ($rgbOrig & 0xFF);
$rgbBlur = ImageColorAt($blur, $x, $y);
$rBlur = (($rgbBlur >> 16) & 0xFF);
$gBlur = (($rgbBlur >> 8) & 0xFF);
$bBlur = ($rgbBlur & 0xFF);
// When the masked pixels differ less from the original
// than the threshold specifies, they are set to their original value.
$rNew = (abs($rOrig - $rBlur) >= $threshold)
? max(0, min(255, ($amount * ($rOrig - $rBlur)) + $rOrig))
: $rOrig;
$gNew = (abs($gOrig - $gBlur) >= $threshold)
? max(0, min(255, ($amount * ($gOrig - $gBlur)) + $gOrig))
: $gOrig;
$bNew = (abs($bOrig - $bBlur) >= $threshold)
? max(0, min(255, ($amount * ($bOrig - $bBlur)) + $bOrig))
: $bOrig;
if (($rOrig != $rNew) || ($gOrig != $gNew) || ($bOrig != $bNew)) {
$pixCol = ImageColorAllocate($image, $rNew, $gNew, $bNew);
ImageSetPixel($image, $x, $y, $pixCol);
}
}
}
} else {
for ($x = 0; $x < $w; $x++) { // each row
for ($y = 0; $y < $h; $y++) { // each pixel
$rgbOrig = ImageColorAt($image, $x, $y);
$rOrig = (($rgbOrig >> 16) & 0xFF);
$gOrig = (($rgbOrig >> 8) & 0xFF);
$bOrig = ($rgbOrig & 0xFF);
$rgbBlur = ImageColorAt($blur, $x, $y);
$rBlur = (($rgbBlur >> 16) & 0xFF);
$gBlur = (($rgbBlur >> 8) & 0xFF);
$bBlur = ($rgbBlur & 0xFF);
$rNew = ($amount * ($rOrig - $rBlur)) + $rOrig;
if ($rNew > 255) $rNew=255;
elseif($rNew < 0) $rNew=0;
$gNew = ($amount * ($gOrig - $gBlur)) + $gOrig;
if ($gNew > 255) $gNew=255;
elseif($gNew < 0) $gNew=0;
$bNew = ($amount * ($bOrig - $bBlur)) + $bOrig;
if($bNew > 255) $bNew=255;
elseif($bNew < 0) $bNew=0;
$rgbNew = ($rNew << 16) + ($gNew <<8) + $bNew;
ImageSetPixel($image, $x, $y, $rgbNew);
}
}
}
imagedestroy($canvas);
imagedestroy($blur);
$this->Processed->image = $image;
}
} // end Image class
?>
@@ -0,0 +1,351 @@
<?php
/**
* Item class
* Cart items
*
* @author Jonathan Davis
* @version 1.0
* @copyright Ingenesis Limited, 28 March, 2008
* @package shopp
**/
class Item {
var $product = false;
var $price = false;
var $category = false;
var $sku = false;
var $type = false;
var $name = false;
var $description = false;
var $optionlabel = false;
var $variation = array();
var $option = false;
var $menus = array();
var $options = array();
var $saved = 0;
var $savings = 0;
var $quantity = 0;
var $unitprice = 0;
var $total = 0;
var $weight = 0;
var $shipfee = 0;
var $tax = 0;
var $download = false;
var $shipping = false;
var $inventory = false;
var $taxable = false;
var $freeshipping = false;
function Item ($Product,$pricing,$category,$data=array()) {
global $Shopp; // To access settings
$Product->load_data(array('prices','images'));
// If product variations are enabled, disregard the first priceline
if ($Product->variations == "on") array_shift($Product->prices);
// If option ids are passed, lookup by option key, otherwise by id
if (is_array($pricing)) {
$Price = $Product->pricekey[$Product->optionkey($pricing)];
if (empty($Price)) $Price = $Product->pricekey[$Product->optionkey($pricing,true)];
} elseif ($pricing) $Price = $Product->priceid[$pricing];
else {
foreach ($Product->prices as &$Price)
if ($Price->type != "N/A" &&
(!$Price->stocked ||
($Price->stocked && $Price->stock > 0))) break;
}
if (isset($Product->id)) $this->product = $Product->id;
if (isset($Price->id)) $this->price = $Price->id;
$this->category = $category;
$this->option = $Price;
$this->name = $Product->name;
$this->slug = $Product->slug;
$this->description = $Product->summary;
if (isset($Product->thumbnail)) $this->thumbnail = $Product->thumbnail;
$this->menus = $Product->options;
if ($Product->variations == "on") $this->options = $Product->prices;
$this->sku = $Price->sku;
$this->type = $Price->type;
$this->sale = $Price->onsale;
$this->freeshipping = $Price->freeshipping;
$this->saved = ($Price->price - $Price->promoprice);
$this->savings = ($Price->price > 0)?percentage($this->saved/$Price->price)*100:0;
$this->unitprice = (($Price->onsale)?$Price->promoprice:$Price->price);
$this->optionlabel = (count($Product->prices) > 1)?$Price->label:'';
$this->donation = $Price->donation;
$this->data = stripslashes_deep(attribute_escape_deep($data));
// Map out the selected menu name and option
if ($Product->variations == "on") {
$selected = explode(",",$this->option->options); $s = 0;
foreach ($this->menus as $i => $menu) {
foreach($menu['options'] as $option) {
if ($option['id'] == $selected[$s]) {
$this->variation[$menu['name']] = $option['name']; break;
}
}
$s++;
}
}
if (!empty($Price->download)) $this->download = $Price->download;
if ($Price->type == "Shipped") {
$this->shipping = true;
if ($Price->shipping == "on") {
$this->weight = $Price->weight;
$this->shipfee = $Price->shipfee;
} else $this->freeshipping = true;
}
$this->inventory = ($Price->inventory == "on")?true:false;
$this->taxable = ($Price->tax == "on" && $Shopp->Settings->get('taxes') == "on")?true:false;
}
function valid () {
if (!$this->product || !$this->price) {
new ShoppError(__('The product could not be added to the cart because it could not be found.','cart_item_invalid',SHOPP_ERR));
return false;
}
if ($this->inventory && $this->option->stock == 0) {
new ShoppError(__('The product could not be added to the cart because it is not in stock.','cart_item_invalid',SHOPP_ERR));
return false;
}
return true;
}
function quantity ($qty) {
if ($this->type == "Donation" && $this->donation['var'] == "on") {
if ($this->donation['min'] == "on" && floatnum($qty) < $this->unitprice)
$this->unitprice = $this->unitprice;
else $this->unitprice = floatnum($qty);
$this->quantity = 1;
$qty = 1;
}
$qty = preg_replace('/[^\d+]/','',$qty);
if ($this->inventory) {
if ($qty > $this->option->stock) {
new ShoppError(__('Not enough of the product is available in stock to fulfill your request.','Shopp'),'item_low_stock');
$this->quantity = $this->option->stock;
}
else $this->quantity = $qty;
} else $this->quantity = $qty;
$this->total = $this->quantity * $this->unitprice;
}
function add ($qty) {
if ($this->type == "Donation" && $this->donation['var'] == "on") {
$qty = floatnum($qty);
$this->quantity = $this->unitprice;
}
$this->quantity($this->quantity+$qty);
}
function options ($selection = "",$taxrate=0) {
if (empty($this->options)) return "";
$string = "";
foreach($this->options as $option) {
if ($option->type == "N/A") continue;
$currently = ($option->onsale)?$option->promoprice:$option->price;
$difference = (float)($currently+($currently*$taxrate))-($this->unitprice+($this->unitprice*$taxrate));
// $difference = $currently-$this->unitprice;
$price = '';
if ($difference > 0) $price = ' (+'.money($difference).')';
if ($difference < 0) $price = ' (-'.money(abs($difference)).')';
$selected = "";
if ($selection == $option->id) $selected = ' selected="Selected"';
$disabled = "";
if ($option->inventory == "on" && $option->stock < $this->quantity)
$disabled = ' disabled="disabled"';
$string .= '<option value="'.$option->id.'"'.$selected.$disabled.'>'.$option->label.$price.'</option>';
}
return $string;
}
function unstock () {
if (!$this->inventory) return;
global $Shopp;
$db = DB::get();
// Update stock in the database
$table = DatabaseObject::tablename(Price::$table);
$db->query("UPDATE $table SET stock=stock-{$this->quantity} WHERE id='{$this->price}' AND stock > 0");
// Update stock in the model
$this->option->stock -= $this->quantity;
// Handle notifications
$product = $this->name.' ('.$this->option->label.')';
if ($this->option->stock == 0)
return new ShoppError(sprintf(__('%s is now out-of-stock!','Shopp'),$product),'outofstock_warning',SHOPP_STOCK_ERR);
if ($this->option->stock <= $Shopp->Settings->get('lowstock_level'))
return new ShoppError(sprintf(__('%s has low stock levels and should be re-ordered soon.','Shopp'),$product),'lowstock_warning',SHOPP_STOCK_ERR);
}
function shipping (&$Shipping) {
}
function tag ($id,$property,$options=array()) {
global $Shopp;
// Return strings with no options
switch ($property) {
case "id": return $id;
case "name": return $this->name;
case "link":
case "url":
return (SHOPP_PERMALINKS)?
$Shopp->shopuri.$this->slug:
add_query_arg('shopp_pid',$this->product,$Shopp->shopuri);
case "sku": return $this->sku;
}
$taxes = false;
if (isset($options['taxes'])) $taxes = $options['taxes'];
if ($property == "unitprice" || $property == "total" || $property == "options")
$taxrate = shopp_taxrate($taxes,$this->taxable);
// Handle currency values
$result = "";
switch ($property) {
case "unitprice": $result = (float)$this->unitprice+($this->unitprice*$taxrate); break;
case "total": $result = (float)$this->total+($this->total*$taxrate); break;
case "tax": $result = (float)$this->tax; break;
}
if (is_float($result)) {
if (isset($options['currency']) && !value_is_true($options['currency'])) return $result;
else return money($result);
}
// Handle values with complex options
switch ($property) {
case "quantity":
$result = $this->quantity;
if ($this->type == "Donation" && $this->donation['var'] == "on") return $result;
if (isset($options['input']) && $options['input'] == "menu") {
if (!isset($options['value'])) $options['value'] = $this->quantity;
if (!isset($options['options']))
$values = "1-15,20,25,30,35,40,45,50,60,70,80,90,100";
else $values = $options['options'];
if (strpos($values,",") !== false) $values = explode(",",$values);
else $values = array($values);
$qtys = array();
foreach ($values as $value) {
if (strpos($value,"-") !== false) {
$value = explode("-",$value);
if ($value[0] >= $value[1]) $qtys[] = $value[0];
else for ($i = $value[0]; $i < $value[1]+1; $i++) $qtys[] = $i;
} else $qtys[] = $value;
}
$result = '<select name="items['.$id.']['.$property.']">';
foreach ($qtys as $qty)
$result .= '<option'.(($qty == $this->quantity)?' selected="selected"':'').' value="'.$qty.'">'.$qty.'</option>';
$result .= '</select>';
} elseif (isset($options['input']) && valid_input($options['input'])) {
if (!isset($options['size'])) $options['size'] = 5;
if (!isset($options['value'])) $options['value'] = $this->quantity;
$result = '<input type="'.$options['input'].'" name="items['.$id.']['.$property.']" id="items-'.$id.'-'.$property.'" '.inputattrs($options).'/>';
} else $result = $this->quantity;
break;
case "remove":
$label = __("Remove");
if (isset($options['label'])) $label = $options['label'];
if (isset($options['class'])) $class = ' class="'.$options['class'].'"';
else $class = ' class="remove"';
if (isset($options['input'])) {
switch ($options['input']) {
case "button":
$result = '<button type="submit" name="remove['.$id.']" value="'.$id.'"'.$class.' tabindex="">'.$label.'</button>'; break;
case "checkbox":
$result = '<input type="checkbox" name="remove['.$id.']" value="'.$id.'"'.$class.' tabindex="" title="'.$label.'"/>'; break;
}
} else {
$result = '<a href="'.add_query_arg(array('cart'=>'update','item'=>$id,'quantity'=>0),$Shopp->link('cart')).'"'.$class.'>'.$label.'</a>';
}
break;
case "optionlabel": $result = $this->optionlabel; break;
case "options":
$class = "";
if (isset($options['show']) &&
strtolower($options['show']) == "selected")
return (!empty($this->optionlabel))?
$options['before'].$this->optionlabel.$options['after']:'';
if (isset($options['class'])) $class = ' class="'.$options['class'].'" ';
if (count($this->options) > 1) {
$result .= $options['before'];
$result .= '<input type="hidden" name="items['.$id.'][product]" value="'.$this->product.'"/>';
$result .= ' <select name="items['.$id.'][price]" id="items-'.$id.'-price"'.$class.'>';
$result .= $this->options($this->price,$taxrate);
$result .= '</select>';
$result .= $options['after'];
}
break;
case "hasinputs":
case "has-inputs": return (count($this->data) > 0); break;
case "inputs":
if (!$this->dataloop) {
reset($this->data);
$this->dataloop = true;
} else next($this->data);
if (current($this->data)) return true;
else {
$this->dataloop = false;
return false;
}
break;
case "input":
$data = current($this->data);
$name = key($this->data);
if (isset($options['name'])) return $name;
return $data;
break;
case "inputs-list":
case "inputslist":
if (empty($this->data)) return false;
$before = ""; $after = ""; $classes = ""; $excludes = array();
if (!empty($options['class'])) $classes = ' class="'.$options['class'].'"';
if (!empty($options['exclude'])) $excludes = explode(",",$options['exclude']);
if (!empty($options['before'])) $before = $options['before'];
if (!empty($options['after'])) $after = $options['after'];
$result .= $before.'<ul'.$classes.'>';
foreach ($this->data as $name => $data) {
if (in_array($name,$excludes)) continue;
$result .= '<li><strong>'.$name.'</strong>: '.$data.'</li>';
}
$result .= '</ul>'.$after;
return $result;
break;
case "thumbnail":
if (!empty($options['class'])) $options['class'] = ' class="'.$options['class'].'"';
if (isset($this->thumbnail)) {
$img = $this->thumbnail;
$width = (isset($options['width']))?$options['width']:$img->properties['height'];
$height = (isset($options['height']))?$options['height']:$img->properties['height'];
return '<img src="'.$Shopp->imguri.$img->id.'" alt="'.$this->name.' '.$img->datatype.'" width="'.$width.'" height="'.$height.'" '.$options['class'].' />'; break;
}
}
if (!empty($result)) return $result;
return false;
}
} // end Item class
?>
@@ -0,0 +1,64 @@
<?php
/**
* Price class
* Catalog product price variations
*
* @author Jonathan Davis
* @version 1.0
* @copyright Ingenesis Limited, 28 March, 2008
* @package shopp
**/
class Price extends DatabaseObject {
static $table = "price";
function Price ($id=false,$key=false) {
$this->init(self::$table);
if ($this->load($id,$key)) {
$this->load_download();
return true;
}
else return false;
}
/**
* Load a single record by a slug name */
function loadby_optionkey ($product,$key) {
$db = DB::get();
$r = $db->query("SELECT * FROM $this->_table WHERE product='$product' AND optionkey='$key'");
$this->populate($r);
if (!empty($this->id)) return true;
return false;
}
function load_download () {
if ($this->type != "Download") return false;
$db = DB::get();
$table = DatabaseObject::tablename(Asset::$table);
$this->download = $db->query("SELECT id,name,properties,size FROM $table WHERE parent='$this->id' AND context='price' AND datatype='download' LIMIT 1");
if (empty($this->download)) return false;
$this->download->properties = unserialize($this->download->properties);
return true;
}
function attach_download ($id) {
if (!$id) return false;
$db = DB::get();
$table = DatabaseObject::tablename(Asset::$table);
$db->query("DELETE FROM $table WHERE parent='$this->id' AND context='price' AND datatype='download'");
$db->query("UPDATE $table SET parent='$this->id',context='price',datatype='download' WHERE id='$id'");
do_action('attach_product_download',$id,$this->id);
return true;
}
} // end Price class
?>
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,177 @@
<?php
/**
* Promotion class
* Handles special promotion deals
*
* @author Jonathan Davis
* @version 1.0
* @copyright Ingenesis Limited, 2 September, 2008
* @package shopp
**/
class Promotion extends DatabaseObject {
static $table = "promo";
var $values = array(
"Name" => "text",
"Category" => "text",
"Variation" => "text",
"Price" => "price",
"Sale price" => "price",
"Type" => "text",
"In stock" => "text",
"Item name" => "text",
"Item quantity" => "text",
"Item amount" => "price",
"Total quantity" => "text",
"Shipping amount" => "price",
"Subtotal amount" => "price",
"Promo code" => "text"
);
function Promotion ($id=false) {
$this->init(self::$table);
if ($this->load($id)) return true;
else return false;
}
function build_discounts () {
$db = DB::get();
$discount_table = DatabaseObject::tablename(Discount::$table);
$product_table = DatabaseObject::tablename(Product::$table);
$price_table = DatabaseObject::tablename(Price::$table);
$catalog_table = DatabaseObject::tablename(Catalog::$table);
$category_table = DatabaseObject::tablename(Category::$table);
$where = "";
// Go through each rule to construct an SQL query
// that gets all applicable product & price ids
if (!empty($this->rules) && is_array($this->rules)) {
foreach ($this->rules as $rule) {
if ($this->values[$rule['property']] == "price")
$value = floatnum($rule['value']);
else $value = "'".$rule['value']."'";
switch($rule['logic']) {
case "Is equal to": $match = "=$value"; break;
case "Is not equal to": $match = "!=$value"; break;
case "Contains": $match = " LIKE '%$value%'"; break;
case "Does not contain": $match = " NOT LIKE '%$value%'"; break;
case "Begins with": $match = " LIKE '$value%'"; break;
case "Ends with": $match = " LIKE '%$value'"; break;
case "Is greater than": $match = "> $value"; break;
case "Is greater than or equal to": $match = ">= $value"; break;
case "Is less than": $match = "< $value"; break;
case "Is less than or equal to": $match = "<= $value"; break;
}
$where .= "AND ";
switch($rule['property']) {
case "Name": $where .= "p.name$match"; break;
case "Category": $where .= "cat.name$match"; break;
case "Variation": $where .= "prc.label$match"; break;
case "Price": $where .= "prc.price$match"; break;
case "Sale price": $where .= "(prc.onsale='on' AND prc.saleprice$match)"; break;
case "Type": $where .= "prc.type$match"; break;
case "In stock": $where .= "(prc.inventory='on' AND prc.stock$match)"; break;
}
}
}
$type = ($this->type == "Item")?'catalog':'cart';
// Delete previous discount records
$db->query("DELETE FROM $discount_table WHERE promo=$this->id");
$query = "INSERT INTO $discount_table (promo,product,price)
SELECT '$this->id' as promo,p.id AS product,prc.id AS price
FROM $product_table as p
LEFT JOIN $price_table AS prc ON prc.product=p.id
LEFT JOIN $catalog_table AS clog ON clog.product=p.id
LEFT JOIN $category_table AS cat ON clog.category=cat.id
WHERE TRUE $where
GROUP BY prc.id";
$db->query($query);
}
/**
* match_rule ()
* Determines if the value of a given subject matches the rule based
* on the specified operation */
function match_rule ($subject,$op,$value,$property=false) {
switch($op) {
// String or Numeric operations
case "Is equal to":
if($property && $this->values[$property] == 'price'){
return ( floatvalue($subject) != 0
&& floatvalue($value) != 0
&& floatvalue($subject) == floatvalue($value));
} else {
return ($subject === $value);
}
break;
case "Is not equal to":
return ($subject !== $value
|| (floatvalue($subject) != 0
&& floatvalue($value) != 0
&& floatvalue($subject) != floatvalue($value)));
break;
// String operations
case "Contains": return (stripos($subject,$value) !== false); break;
case "Does not contain": return (stripos($subject,$value) === false); break;
case "Begins with": return (stripos($subject,$value) === 0); break;
case "Ends with": return (stripos($subject,$value) === strlen($subject) - strlen($value)); break;
// Numeric operations
case "Is greater than":
return (floatvalue($subject,false) > floatvalue($value,false));
break;
case "Is greater than or equal to":
return (floatvalue($subject,false) >= floatvalue($value,false));
break;
case "Is less than":
return (floatvalue($subject,false) < floatvalue($value,false));
break;
case "Is less than or equal to":
return (floatvalue($subject,false) <= floatvalue($value,false));
break;
}
return false;
}
} // end Promotion class
// Discount table provides discount index for faster, efficient discount lookups
class Discount extends DatabaseObject {
static $table = "discount";
function Promotion ($id=false) {
$this->init(self::$table);
if ($this->load($id)) return true;
else return false;
}
function delete () {
$db = DB::get();
// Delete record
$id = $this->{$this->_key};
// Delete related discounts
$discount_table = DatabaseObject::tablename(Discount::$table);
if (!empty($id)) $db->query("DELETE LOW_PRIORITY FROM $discount_table WHERE promo='$id'");
if (!empty($id)) $db->query("DELETE FROM $this->_table WHERE $this->_key='$id'");
else return false;
}
} // end Discount class
?>
@@ -0,0 +1,561 @@
<?php
/**
* Purchase class
* Order invoice logging
*
* @author Jonathan Davis
* @version 1.0
* @copyright Ingenesis Limited, 28 March, 2008
* @package shopp
**/
require("Purchased.php");
class Purchase extends DatabaseObject {
static $table = "purchase";
var $purchased = array();
var $columns = array();
var $looping = false;
var $dataloop = false;
function Purchase ($id=false,$key=false) {
$this->init(self::$table);
if (!$id) return true;
if ($this->load($id,$key)) return true;
else return false;
}
function load_purchased () {
$db = DB::get();
$table = DatabaseObject::tablename(Purchased::$table);
if (empty($this->id)) return false;
$this->purchased = $db->query("SELECT * FROM $table WHERE purchase=$this->id",AS_ARRAY);
foreach ($this->purchased as &$purchase) $purchase->data = unserialize($purchase->data);
return true;
}
function notification ($addressee,$address,$subject,$template="order.html",$receipt="receipt.php") {
global $Shopp;
global $is_IIS;
$template = trailingslashit(SHOPP_TEMPLATES).$template;
if (!file_exists($template))
return new ShoppError(__('A purchase notification could not be sent because the template for it does not exist.','purchase_notification_template',SHOPP_ADMIN_ERR));
// // Send the e-mail receipt
$email = array();
$email['from'] = '"'.get_bloginfo("name").'"';
if ($Shopp->Settings->get('merchant_email'))
$email['from'] .= ' <'.$Shopp->Settings->get('merchant_email').'>';
if($is_IIS) $email['to'] = $address;
else $email['to'] = '"'.html_entity_decode($addressee,ENT_QUOTES).'" <'.$address.'>';
$email['subject'] = $subject;
$email['receipt'] = $Shopp->Flow->order_receipt($receipt);
$email['url'] = get_bloginfo('siteurl');
$email['sitename'] = get_bloginfo('name');
$email['orderid'] = $this->id;
$email = apply_filters('shopp_email_receipt_data',$email);
if (shopp_email($template,$email)) {
if (SHOPP_DEBUG) new ShoppError('A purchase notification was sent to "'.$addressee.'" &lt;'.$address.'&gt;',false,SHOPP_DEBUG_ERR);
return true;
}
if (SHOPP_DEBUG) new ShoppError('A purchase notification FAILED to be sent to "'.$addressee.'" &lt;'.$address.'&gt;',false,SHOPP_DEBUG_ERR);
return false;
}
function copydata ($Object,$prefix="") {
$ignores = array("_datatypes","_table","_key","_lists","id","created","modified");
foreach(get_object_vars($Object) as $property => $value) {
$property = $prefix.$property;
if (property_exists($this,$property) &&
!in_array($property,$ignores))
$this->{$property} = $value;
}
}
function exportcolumns () {
$prefix = "o.";
return array(
$prefix.'id' => __('Order ID','Shopp'),
$prefix.'ip' => __('Customer\'s IP Address','Shopp'),
$prefix.'firstname' => __('Customer\'s First Name','Shopp'),
$prefix.'lastname' => __('Customer\'s Last Name','Shopp'),
$prefix.'email' => __('Customer\'s Email Address','Shopp'),
$prefix.'phone' => __('Customer\'s Phone Number','Shopp'),
$prefix.'company' => __('Customer\'s Company','Shopp'),
$prefix.'card' => __('Credit Card Number','Shopp'),
$prefix.'cardtype' => __('Credit Card Type','Shopp'),
$prefix.'cardexpires' => __('Credit Card Expiration Date','Shopp'),
$prefix.'cardholder' => __('Credit Card Holder\'s Name','Shopp'),
$prefix.'address' => __('Billing Street Address','Shopp'),
$prefix.'xaddress' => __('Billing Street Address 2','Shopp'),
$prefix.'city' => __('Billing City','Shopp'),
$prefix.'state' => __('Billing State/Province','Shopp'),
$prefix.'country' => __('Billing Country','Shopp'),
$prefix.'postcode' => __('Billing Postal Code','Shopp'),
$prefix.'shipaddress' => __('Shipping Street Address','Shopp'),
$prefix.'shipxaddress' => __('Shipping Street Address 2','Shopp'),
$prefix.'shipcity' => __('Shipping City','Shopp'),
$prefix.'shipstate' => __('Shipping State/Province','Shopp'),
$prefix.'shipcountry' => __('Shipping Country','Shopp'),
$prefix.'shippostcode' => __('Shipping Postal Code','Shopp'),
$prefix.'shipmethod' => __('Shipping Method','Shopp'),
$prefix.'promos' => __('Promotions Applied','Shopp'),
$prefix.'subtotal' => __('Order Subtotal','Shopp'),
$prefix.'discount' => __('Order Discount','Shopp'),
$prefix.'freight' => __('Order Shipping Fees','Shopp'),
$prefix.'tax' => __('Order Taxes','Shopp'),
$prefix.'total' => __('Order Total','Shopp'),
$prefix.'fees' => __('Transaction Fees','Shopp'),
$prefix.'transactionid' => __('Transaction ID','Shopp'),
$prefix.'transtatus' => __('Transaction Status','Shopp'),
$prefix.'gateway' => __('Payment Gateway','Shopp'),
$prefix.'status' => __('Order Status','Shopp'),
$prefix.'data' => __('Order Data','Shopp'),
$prefix.'created' => __('Order Date','Shopp'),
$prefix.'modified' => __('Order Last Updated','Shopp')
);
}
function tag ($property,$options=array()) {
global $Shopp;
if ($property == "item-unitprice" || $property == "item-total")
$taxrate = shopp_taxrate($options['taxes']);
// Return strings with no options
switch ($property) {
case "url": return $Shopp->link('cart'); break;
case "id": return $this->id; break;
case "date":
if (empty($options['format'])) $options['format'] = get_option('date_format');
return _d($options['format'],((is_int($this->created))?$this->created:mktimestamp($this->created)));
break;
case "card": return (!empty($this->card))?sprintf("%'X16d",$this->card):''; break;
case "cardtype": return $this->cardtype; break;
case "transactionid": return $this->transactionid; break;
case "firstname": return $this->firstname; break;
case "lastname": return $this->lastname; break;
case "company": return $this->company; break;
case "email": return $this->email; break;
case "phone": return $this->phone; break;
case "address": return $this->address; break;
case "xaddress": return $this->xaddress; break;
case "city": return $this->city; break;
case "state":
if (strlen($this->state > 2)) return $this->state;
$regions = $Shopp->Settings->get('zones');
$states = $regions[$this->country];
return $states[$this->state];
break;
case "postcode": return $this->postcode; break;
case "country":
$countries = $Shopp->Settings->get('target_markets');
return $countries[$this->country]; break;
case "shipaddress": return $this->shipaddress; break;
case "shipxaddress": return $this->shipxaddress; break;
case "shipcity": return $this->shipcity; break;
case "shipstate":
if (strlen($this->shipstate > 2)) return $this->shipstate;
$regions = $Shopp->Settings->get('zones');
$states = $regions[$this->country];
return $states[$this->shipstate];
break;
case "shippostcode": return $this->shippostcode; break;
case "shipcountry":
$countries = $Shopp->Settings->get('target_markets');
return $countries[$this->shipcountry]; break;
case "shipmethod": return $this->shipmethod; break;
case "totalitems": return count($this->purchased); break;
case "hasitems": if (count($this->purchased) > 0) return true; else return false; break;
case "items":
if (!$this->looping) {
reset($this->purchased);
$this->looping = true;
} else next($this->purchased);
if (current($this->purchased)) return true;
else {
$this->looping = false;
reset($this->purchased);
return false;
}
case "item-id":
$item = current($this->purchased);
return $item->id; break;
case "item-product":
$item = current($this->purchased);
return $item->product; break;
case "item-price":
$item = current($this->purchased);
return $item->price; break;
case "item-name":
$item = current($this->purchased);
return $item->name; break;
case "item-description":
$item = current($this->purchased);
return $item->description; break;
case "item-options":
$item = current($this->purchased);
return (!empty($item->optionlabel))?$options['before'].$item->optionlabel.$options['after']:''; break;
case "item-sku":
$item = current($this->purchased);
return $item->sku; break;
case "item-download":
$item = current($this->purchased);
if (empty($item->download)) return "";
if (!isset($options['label'])) $options['label'] = __('Download','Shopp');
$classes = "";
if (isset($options['class'])) $classes = ' class="'.$options['class'].'"';
if (SHOPP_PERMALINKS) $url = $Shopp->shopuri."download/".$item->dkey;
else $url = add_query_arg('shopp_download',$item->dkey,$Shopp->link('account'));
return '<a href="'.$url.'"'.$classes.'>'.$options['label'].'</a>'; break;
case "item-quantity":
$item = current($this->purchased);
return $item->quantity; break;
case "item-unitprice":
$item = current($this->purchased);
return money($item->unitprice+($item->unitprice*$taxrate)); break;
case "item-total":
$item = current($this->purchased);
return money($item->total+($item->total*$taxrate)); break;
case "item-has-inputs":
case "item-hasinputs":
$item = current($this->purchased);
return (count($item->data) > 0); break;
case "item-inputs":
$item = current($this->purchased);
if (!$this->itemdataloop) {
reset($item->data);
$this->itemdataloop = true;
} else next($item->data);
if (current($item->data)) return true;
else {
$this->itemdataloop = false;
return false;
}
break;
case "item-input":
$item = current($this->purchased);
$data = current($item->data);
$name = key($item->data);
if (isset($options['name'])) return $name;
return $data;
break;
case "item-inputs-list":
case "item-inputslist":
case "item-inputs-list":
case "iteminputslist":
$item = current($this->purchased);
if (empty($item->data)) return false;
$before = ""; $after = ""; $classes = ""; $excludes = array();
if (!empty($options['class'])) $classes = ' class="'.$options['class'].'"';
if (!empty($options['exclude'])) $excludes = explode(",",$options['exclude']);
if (!empty($options['before'])) $before = $options['before'];
if (!empty($options['after'])) $after = $options['after'];
$result .= $before.'<ul'.$classes.'>';
foreach ($item->data as $name => $data) {
if (in_array($name,$excludes)) continue;
$result .= '<li><strong>'.$name.'</strong>: '.$data.'</li>';
}
$result .= '</ul>'.$after;
return $result;
break;
case "has-data":
case "hasdata": return (is_array($this->data) && count($this->data) > 0); break;
case "orderdata":
if (!$this->dataloop) {
reset($this->data);
$this->dataloop = true;
} else next($this->data);
if (current($this->data) !== false) return true;
else {
$this->dataloop = false;
return false;
}
break;
case "data":
if (!is_array($this->data)) return false;
$data = current($this->data);
$name = key($this->data);
if (isset($options['name'])) return $name;
return $data;
break;
case "has-promo":
case "haspromo":
if (empty($options['name'])) return false;
return (in_array($options['name'],$this->promos));
break;
case "subtotal": return money($this->subtotal); break;
case "hasfreight": return (!empty($this->shipmethod) || $this->freight > 0);
case "freight": return money($this->freight); break;
case "hasdiscount": return ($this->discount > 0);
case "discount": return money($this->discount); break;
case "hastax": return ($this->tax > 0)?true:false;
case "tax": return money($this->tax); break;
case "total": return money($this->total); break;
case "status":
$labels = $Shopp->Settings->get('order_status');
if (empty($labels)) $labels = array('');
return $labels[$this->status];
break;
}
}
} // end Purchase class
class PurchasesExport {
var $sitename = "";
var $headings = false;
var $data = false;
var $defined = array();
var $purchase_cols = array();
var $purchased_cols = array();
var $selected = array();
var $recordstart = true;
var $content_type = "text/plain";
var $extension = "txt";
var $date_format = 'F j, Y';
var $time_format = 'g:i:s a';
function PurchasesExport () {
global $Shopp;
$this->purchase_cols = Purchase::exportcolumns();
$this->purchased_cols = Purchased::exportcolumns();
$this->defined = array_merge($this->purchase_cols,$this->purchased_cols);
$this->sitename = get_bloginfo('name');
$this->headings = ($Shopp->Settings->get('purchaselog_headers') == "on");
$this->selected = $Shopp->Settings->get('purchaselog_columns');
$this->date_format = get_option('date_format');
$this->time_format = get_option('time_format');
$Shopp->Settings->save('purchaselog_lastexport',mktime());
}
function query ($request=array()) {
$db =& DB::get();
if (empty($request)) $request = $_GET;
if (!empty($request['start'])) {
list($month,$day,$year) = explode("/",$request['start']);
$starts = mktime(0,0,0,$month,$day,$year);
}
if (!empty($request['end'])) {
list($month,$day,$year) = explode("/",$request['end']);
$ends = mktime(0,0,0,$month,$day,$year);
}
$where = "WHERE o.id IS NOT NULL AND p.id IS NOT NULL ";
if (isset($request['status'])) $where .= "AND status='{$request['status']}'";
if (isset($request['s']) && !empty($request['s'])) $where .= " AND (id='{$request['s']}' OR firstname LIKE '%{$request['s']}%' OR lastname LIKE '%{$request['s']}%' OR CONCAT(firstname,' ',lastname) LIKE '%{$request['s']}%' OR transactionid LIKE '%{$request['s']}%')";
if (!empty($request['start']) && !empty($request['end'])) $where .= " AND (UNIX_TIMESTAMP(o.created) >= $starts AND UNIX_TIMESTAMP(o.created) <= $ends)";
$purchasetable = DatabaseObject::tablename(Purchase::$table);
$purchasedtable = DatabaseObject::tablename(Purchased::$table);
$c = 0; $columns = array();
foreach ($this->selected as $column) $columns[] = "$column AS col".$c++;
$query = "SELECT ".join(",",$columns)." FROM $purchasedtable AS p LEFT JOIN $purchasetable AS o ON o.id=p.purchase $where ORDER BY o.created ASC";
$this->data = $db->query($query,AS_ARRAY);
}
// Implement for exporting all the data
function output () {
if (!$this->data) $this->query();
if (!$this->data) return false;
header("Content-type: $this->content_type; charset=UTF-8");
header("Content-Disposition: attachment; filename=\"$this->sitename Purchase Log.$this->extension\"");
header("Content-Description: Delivered by WordPress/Shopp ".SHOPP_VERSION);
header("Cache-Control: maxage=1");
header("Pragma: public");
$this->begin();
if ($this->headings) $this->heading();
$this->records();
$this->end();
}
function begin() {}
function heading () {
foreach ($this->selected as $name)
$this->export($this->defined[$name]);
$this->record();
}
function records () {
foreach ($this->data as $key => $record) {
foreach(get_object_vars($record) as $column)
$this->export($this->parse($column));
$this->record();
}
}
function parse ($column) {
if (preg_match("/^[sibNaO](?:\:.+?\{.*\}$|\:.+;$|;$)/",$column)) {
$list = unserialize($column);
$column = "";
foreach ($list as $name => $value)
$column .= (empty($column)?"":";")."$name:$value";
}
return $column;
}
function end() {}
// Implement for exporting a single value
function export ($value) {
echo ($this->recordstart?"":"\t").$value;
$this->recordstart = false;
}
function record () {
echo "\n";
$this->recordstart = true;
}
function settings () {}
}
class PurchasesTabExport extends PurchasesExport {
function PurchasesTabExport () {
parent::PurchasesExport();
$this->output();
}
}
class PurchasesCSVExport extends PurchasesExport {
function PurchasesCSVExport () {
parent::PurchasesExport();
$this->content_type = "text/csv";
$this->extension = "csv";
$this->output();
}
function export ($value) {
$value = str_replace('"','""',$value);
if (preg_match('/^\s|[,"\n\r]|\s$/',$value)) $value = '"'.$value.'"';
echo ($this->recordstart?"":",").$value;
$this->recordstart = false;
}
}
class PurchasesXLSExport extends PurchasesExport {
function PurchasesXLSExport () {
parent::PurchasesExport();
$this->content_type = "application/vnd.ms-excel";
$this->extension = "xls";
$this->c = 0; $this->r = 0;
$this->output();
}
function begin () {
echo pack("ssssss", 0x809, 0x8, 0x0, 0x10, 0x0, 0x0);
}
function end () {
echo pack("ss", 0x0A, 0x00);
}
function export ($value) {
if (preg_match('/^[\d\.]+$/',$value)) {
echo pack("sssss", 0x203, 14, $this->r, $this->c, 0x0);
echo pack("d", $value);
} else {
$l = strlen($value);
echo pack("ssssss", 0x204, 8+$l, $this->r, $this->c, 0x0, $l);
echo $value;
}
$this->c++;
}
function record () {
$this->c = 0;
$this->r++;
}
}
class PurchasesIIFExport extends PurchasesExport {
function PurchasesIIFExport () {
global $Shopp;
parent::PurchasesExport();
$this->content_type = "application/qbooks";
$this->extension = "iif";
$account = $Shopp->Settings->get('purchaselog_iifaccount');
if (empty($account)) $account = "Merchant Account";
$this->selected = array(
"'\nTRNS'",
"DATE_FORMAT(o.created,'\"%m/%d/%Y\"')",
"'\"$account\"'",
"CONCAT('\"',o.firstname,' ',o.lastname,'\"')",
"'\"Shopp Payment Received\"'",
"o.total-o.fees",
"''",
"'\nSPL'",
"DATE_FORMAT(o.created,'\"%m/%d/%Y\"')",
"'\"Other Income\"'",
"CONCAT('\"',o.firstname,' ',o.lastname,'\"')",
"o.total*-1",
"'\nSPL'",
"DATE_FORMAT(o.created,'\"%m/%d/%Y\"')",
"'\"Other Expenses\"'",
"'Fee'",
"o.fees",
"''",
"'\nENDTRNS'"
);
$this->output();
}
function begin () {
echo "!TRNS\tDATE\tACCNT\tNAME\tCLASS\tAMOUNT\tMEMO\n!SPL\tDATE\tACCNT\tNAME\tAMOUNT\tMEMO\n!ENDTRNS";
}
function export ($value) {
echo (substr($value,0,1) != "\n")?"\t".$value:$value;
}
function record () { }
function settings () {
global $Shopp;
?>
<div id="iif-settings" class="hidden">
<input type="text" id="iif-account" name="settings[purchaselog_iifaccount]" value="<?php echo $Shopp->Settings->get('purchaselog_iifaccount'); ?>" size="30"/><br />
<label for="iif-account"><small><?php _e('QuickBooks account name for transactions','Shopp'); ?></small></label>
</div>
<script type="text/javascript">
jQuery(document).ready( function() {
var $=jQuery.noConflict();
$('#purchaselog-format').change(function () {
if ($(this).val() == "iif") {
$('#export-columns').hide();
$('#iif-settings').show();
$('#iif-account').focus();
} else {
$('#export-columns').show();
$('#iif-settings').hide();
}
}).change();
});
</script>
<?php
}
}
?>
@@ -0,0 +1,47 @@
<?php
/**
* Purchased class
* Purchased line items for orders
*
* @author Jonathan Davis
* @version 1.0
* @copyright Ingenesis Limited, 28 March, 2008
* @package shopp
**/
class Purchased extends DatabaseObject {
static $table = "purchased";
function Purchased ($id=false,$key=false) {
$this->init(self::$table);
if ($this->load($id,$key)) return true;
else return false;
}
function keygen() {
$message = $this->name.$this->purchase.$this->product.$this->price.$this->download;
$key = sha1($message);
if (empty($key)) $key = md5($message);
$this->dkey = $key;
do_action_ref_array('shopp_download_keygen',array(&$this));
}
function exportcolumns () {
$prefix = "p.";
return array(
$prefix.'id' => __('Line Item ID','Shopp'),
$prefix.'name' => __('Product Name','Shopp'),
$prefix.'optionlabel' => __('Product Variation Name','Shopp'),
$prefix.'description' => __('Product Description','Shopp'),
$prefix.'sku' => __('Product SKU','Shopp'),
$prefix.'quantity' => __('Product Quantity Purchased','Shopp'),
$prefix.'unitprice' => __('Product Unit Price','Shopp'),
$prefix.'total' => __('Product Total Price','Shopp'),
$prefix.'data' => __('Product Data','Shopp'),
$prefix.'downloads' => __('Product Downloads','Shopp')
);
}
} // end Purchased class
?>
@@ -0,0 +1,143 @@
<?php
/**
* Setting class
* Shopp settings
*
* @author Jonathan Davis
* @version 1.0
* @copyright Ingenesis Limited, 28 March, 2008
* @package shopp
**/
class Settings extends DatabaseObject {
static $table = "setting";
var $registry = array();
var $unavailable = false;
var $_table = "";
function Settings () {
$this->_table = $this->tablename(self::$table);
if (!$this->load()) {
if (!$this->init('setting')) {
$this->unavailable = true;
return false;
}
}
}
/**
* Load all settings from the database */
function load ($name="") {
$db = DB::get();
if (!empty($name)) $results = $db->query("SELECT name,value FROM $this->_table WHERE name='$name'",AS_ARRAY,false);
else $results = $db->query("SELECT name,value FROM $this->_table WHERE autoload='on'",AS_ARRAY,false);
if (!is_array($results) || sizeof($results) == 0) return false;
while(list($key,$entry) = each($results)) $settings[$entry->name] = $this->restore($entry->value);
if (!empty($settings)) $this->registry = array_merge($this->registry,$settings);
return true;
}
/**
* Add a new setting to the registry and store it in the database */
function add ($name, $value,$autoload = true) {
$db = DB::get();
$Setting = $this->setting();
$Setting->name = $name;
$Setting->value = $db->clean($value);
$Setting->autoload = ($autoload)?'on':'off';
$data = $db->prepare($Setting);
$dataset = DatabaseObject::dataset($data);
if ($db->query("INSERT $this->_table SET $dataset"))
$this->registry[$name] = $this->restore($db->clean($value));
else return false;
return true;
}
/**
* Updates the setting in the registry and the database */
function update ($name,$value) {
$db = DB::get();
if ($this->get($name) == $value) return true;
$Setting = $this->setting();
$Setting->name = $name;
$Setting->value = $db->clean($value);
unset($Setting->autoload);
$data = $db->prepare($Setting); // Prepare the data for db entry
$dataset = DatabaseObject::dataset($data); // Format the data in SQL
if ($db->query("UPDATE $this->_table SET $dataset WHERE name='$Setting->name'"))
$this->registry[$name] = $this->restore($value); // Update the value in the registry
else return false;
return true;
}
function save ($name,$value,$autoload=true) {
// Update or Insert as needed
if ($this->get($name) === false) $this->add($name,$value,$autoload);
else $this->update($name,$value);
}
/**
* Remove a setting from the registry and the database */
function delete ($name) {
$db = DB::get();
unset($this->registry[$name]);
if (!$db->query("DELETE FROM $this->_table WHERE name='$name'")) return false;
return true;
}
/**
* Get a specific setting from the registry */
function get ($name) {
global $Shopp;
$value = false;
if (isset($this->registry[$name])) {
return $this->registry[$name];
} elseif ($this->load($name)) {
$value = $this->registry[$name];
}
// Return false and add an entry to the registry
// to avoid repeat database queries
if (!isset($this->registry[$name])) {
$this->registry[$name] = false;
return false;
}
return $value;
}
function restore ($value) {
if (!is_string($value)) return $value;
// Return unserialized, if serialized value
if (preg_match("/^[sibNaO](?:\:.+?\{.*\}$|\:.+;$|;$)/s",$value)) {
$restored = unserialize($value);
if (!empty($restored)) return $restored;
$restored = unserialize(stripslashes($value));
if (!empty($restored)) return $restored;
}
return $value;
}
/**
* Return a blank setting object */
function setting () {
$setting->_datatypes = array("name" => "string", "value" => "string", "autoload" => "list",
"created" => "date", "modified" => "date");
$setting->name = null;
$setting->value = null;
$setting->autoload = null;
$setting->created = null;
$setting->modified = null;
return $setting;
}
} // END class Settings
?>
@@ -0,0 +1,95 @@
<?php
/**
* ShipCalcs class
* Manages shipping method calculators
*
* @author Jonathan Davis
* @version 1.0
* @copyright Ingenesis Limited, 29 April, 2008
* @package shopp
**/
class ShipCalcs {
var $modules = array();
var $methods = array();
var $path = "";
function ShipCalcs ($basepath) {
global $Shopp;
$this->path = $basepath.DIRECTORY_SEPARATOR."shipping";
$lastscan = $Shopp->Settings->get('shipcalc_lastscan');
$lastupdate = filemtime($this->path);
$modfiles = array();
if ($lastupdate > $lastscan) $modfiles = $this->scanmodules();
else {
$modfiles = $Shopp->Settings->get('shipcalc_modules');
if (empty($modfiles)) $modfiles = $this->scanmodules();
}
if (!empty($modfiles)) {
foreach ($modfiles as $ShipCalcClass => $file) {
if (!file_exists($this->path.$file)) continue;
include_once($this->path.$file);
$this->modules[$ShipCalcClass] = new $ShipCalcClass();
$this->modules[$ShipCalcClass]->methods($this);
}
if (count($this->modules) != count($modfiles))
$modfiles = $this->scanmodules();
}
}
function readmeta ($modfile) {
$metadata = array();
$meta = get_filemeta($this->path.$modfile);
if ($meta) {
$lines = explode("\n",substr($meta,1));
foreach($lines as $line) {
preg_match("/^(?:[\s\*]*?\b([^@\*\/]*))/",$line,$match);
if (!empty($match[1])) $data[] = $match[1];
preg_match("/^(?:[\s\*]*?@([^\*\/]+?)\s(.+))/",$line,$match);
if (!empty($match[1]) && !empty($match[2])) $tags[$match[1]] = $match[2];
}
$module = new stdClass();
$module->file = $modfile;
$module->name = $data[0];
$module->description = (!empty($data[1]))?$data[1]:"";
$module->tags = $tags;
return $module;
}
return false;
}
function scanmodules ($path=false) {
global $Shopp;
if (!$path) $path = $this->path;
$modfilescan = array();
find_files(".php",$path,$path,$modfilescan);
if (empty($modfilescan)) return $modfilescan;
foreach ($modfilescan as $file) {
if (! is_readable($path.$file)) continue;
$ShipCalcClass = substr(basename($file),0,-4);
$modfiles[$ShipCalcClass] = $file;
}
$Shopp->Settings->save('shipcalc_modules',addslashes(serialize($modfiles)));
$Shopp->Settings->save('shipcalc_lastscan',mktime());
return $modfiles;
}
function ui () {
foreach ($this->modules as $ShipCalcClass => &$module) $module->ui();
}
} // end ShipCalcs class
?>
@@ -0,0 +1,80 @@
<?php
/**
* Shipping class
* Shipping addresses
*
* @author Jonathan Davis
* @version 1.0
* @copyright Ingenesis Limited, 28 March, 2008
* @package shopp
**/
class Shipping extends DatabaseObject {
static $table = "shipping";
function Shipping ($id=false,$key=false) {
$this->init(self::$table);
if ($id && $this->load($id,$key)) return true;
else return false;
}
function exportcolumns () {
$prefix = "s.";
return array(
$prefix.'address' => __('Shipping Street Address','Shopp'),
$prefix.'xaddress' => __('Shipping Street Address 2','Shopp'),
$prefix.'city' => __('Shipping City','Shopp'),
$prefix.'state' => __('Shipping State/Province','Shopp'),
$prefix.'country' => __('Shipping Country','Shopp'),
$prefix.'postcode' => __('Shipping Postal Code','Shopp'),
);
}
/**
* postarea()
* Determines the domestic area name from a
* U.S. zip code or Canadian postal code */
function postarea () {
global $Shopp;
$code = $this->postcode;
$areas = $Shopp->Settings->get('areas');
// Skip if there are no areas for this country
if (!isset($areas[$this->country])) return false;
// If no postcode is provided, return the first regional column
if (empty($this->postcode)) return key($areas[$this->country]);
// Lookup US area name
if (preg_match("/\d{5}(\-\d{4})?/",$code)) {
foreach ($areas['US'] as $name => $states) {
foreach ($states as $id => $coderange) {
for($i = 0; $i<count($coderange); $i+=2) {
if ($code >= (int)$coderange[$i] && $code <= (int)$coderange[$i+1]) {
$this->state = $id;
return $name;
}
}
}
}
}
// Lookup Canadian area name
if (preg_match("/\w\d\w\s*\d\w\d/",$code)) {
foreach ($areas['CA'] as $name => $provinces) {
foreach ($provinces as $id => $fsas) {
if (in_array(substr($code,0,1),$fsas)) return $name;
}
}
return $name;
}
return false;
}
} // end Shipping class
?>
@@ -0,0 +1,23 @@
<?php
/**
* Spec class
* Catalog product spec table
*
* @author Jonathan Davis
* @version 1.0
* @copyright Ingenesis Limited, 26 July, 2008
* @package shopp
**/
class Spec extends DatabaseObject {
static $table = "spec";
function Spec ($id=false) {
$this->init(self::$table);
if ($this->load($id)) return true;
else return false;
}
} // end Spec class
?>
@@ -0,0 +1,23 @@
<?php
/**
* Tag class
* Catalog product tag table
*
* @author Jonathan Davis
* @version 1.0
* @copyright Ingenesis Limited, 9 October, 2008
* @package shopp
**/
class Tag extends DatabaseObject {
static $table = "tag";
function Tag ($id=false,$key=false) {
$this->init(self::$table);
if ($this->load($id,$key)) return true;
else return false;
}
} // end Tag class
?>
@@ -0,0 +1,206 @@
<?php
/**
* XMLdata
* Reads XML data into associative arrays and outputs them back to valid XML
*
* Credits for the parsing, markup and insert functions:
* http://mysrc.blogspot.com/2007/02/php-xml-to-array-and-backwards.html
*
* Adapted by Jon Davis, August 21, 2008
* Navigation functions developed by Jon Davis, August 21, 2008
*/
class XMLdata {
var $data = array();
function XMLdata ($data=false) {
if (!is_array($data)) $this->parse($data);
else $this->data = $data;
return true;
}
/**
* parse()
* Parses a string of XML markup into an associative array */
function parse (&$string) {
$parser = xml_parser_create();
xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, 0);
xml_parse_into_struct($parser, $string, $vals, $index);
xml_parser_free($parser);
$data = array();
$working = &$data;
foreach ($vals as $r) {
$t=$r['tag'];
if ($r['type'] == 'open') {
if (isset($working[$t])) {
if (isset($working[$t][0])) $working[$t][] = array();
else $working[$t]=array($working[$t], array());
$cv = &$working[$t][count($working[$t])-1];
} else $cv = &$working[$t];
if (isset($r['attributes'])) { foreach ($r['attributes'] as $k => $v) $cv['ATTRS'][$k] = $v; }
$cv['CHILDREN'] = array();
$cv['CHILDREN']['_p'] = &$working;
$working = &$cv['CHILDREN'];
} elseif ($r['type']=='complete') {
if (isset($working[$t])) { // same as open
if (isset($working[$t][0])) $working[$t][] = array();
else $working[$t] = array($working[$t], array());
$cv = &$working[$t][count($working[$t])-1];
} else $cv = &$working[$t];
if (isset($r['attributes'])) { foreach ($r['attributes'] as $k => $v) $cv['ATTRS'][$k] = $v; }
$cv['CONTENT'] = (isset($r['value']) ? $r['value'] : '');
} elseif ($r['type'] == 'close') {
$working = &$working['_p'];
}
}
$this->remove_p($data);
$this->data = $data;
return true;
}
/**
* remove_p()
* Removes recursive results in the tree */
private function remove_p(&$data) {
foreach ($data as $k => $v) {
if ($k === '_p') unset($data[$k]);
elseif (is_array($data[$k])) $this->remove_p($data[$k]);
}
}
/**
* markup()
* Uses recursion to build and returns XML-markup */
function markup ($data=false, $depth=0, $forcetag='') {
if (!$data) $data = $this->data;
$res=array('<?xml version="1.0" encoding="utf-8"?>'."\n");
foreach ($data as $tag=>$r) {
if (isset($r[0])) {
$res[]=$this->markup($r, $depth, $tag);
} else {
if ($forcetag) $tag=$forcetag;
$sp=str_repeat("\t", $depth);
$res[] = "$sp<$tag";
if (isset($r['ATTRS'])) { foreach ($r['ATTRS'] as $at => $av) $res[] = ' '.$at.'="'.htmlentities($av).'"'; }
$res[] = ">".((isset($r['CHILDREN'])) ? "\n" : '');
if (isset($r['CHILDREN'])) $res[] = $this->markup($r['CHILDREN'], $depth+1);
elseif (isset($r['CONTENT'])) $res[] = htmlentities($r['CONTENT']);
$res[] = (isset($r['CHILDREN']) ? $sp : '')."</$tag>\n";
}
}
return implode('', $res);
}
/**
* insert()
* Inserts a new element into the data tree */
function insert ($element, $pos) {
$working = array_slice($this->data, 0, $pos); $working[] = $element;
$this->data = array_merge($working, array_slice($this->data, $pos));
}
/**
* add()
* Adds a new element to the data tree as a child of the $target element */
function &add ($element,$target=false,$attrs=array(),$content=false) {
$working = array();
$working[$element] = array();
if (!empty($attrs) && is_array($attrs)) $working[$element]['ATTRS'] = $attrs;
if ($content) $working[$element]['CONTENT'] = $content;
if ($target) {
if (is_array($target)) $node = &$target;
else $node =& $this->search($target,false,true);
if (!isset($node['CHILDREN'])) $node['CHILDREN'][$element] = $working[$element];
else $node['CHILDREN'][$element] = $working[$element];
return $node['CHILDREN'][$element];
} else $this->data[$element] = $working[$element];
return $this->data[$element];
}
/**
* getRootElement()
* Returns the root element of the tree */
function getRootElement () {
reset($this->data);
return current($this->data);
}
/**
* getElementContent()
* Searches the tree for the target $element and returns
* the contents (the value between the tags) */
function getElementContent ($element) {
$found = $this->search($element);
if (!empty($found)) return $found[0]['CONTENT'];
else return false;
}
/**
* getElementAttrs()
* Searches the tree for the target $element and returns
* an associative array of attribute names and values (<tag attribute="value">) */
function getElementAttrs ($element) {
$found = $this->search($element);
if (!empty($found)) return $found[0]['ATTRS'];
else return false;
}
/**
* getElementAttr()
* Searches the tree for the target $element and returns
* value of a specific attribute for a specific element tag (<tag attribute="value">) */
function getElementAttr ($element,$attr) {
$found = $this->search($element);
if (!empty($found)) return $found[0]['ATTRS'][$attr];
else return false;
}
/**
* getElement()
* Searches the tree for the target $element and returns
* an array of the element attributes, content and any children */
function getElement ($element) {
$found = $this->search($element);
if (!empty($found)) return $found[0];
else return false;
}
/**
* getElements()
* Searches the tree for the target $element and returns
* an indexed array with each indice including matched elements
* as associative arrays including the element attribtues, content
* and any children */
function getElements($element) {
return $this->search($element);
}
/**
* search()
* Helper function to perform recursive searches in the tree
* for a $target and returns the structure */
private function search ($target,&$dom=false,$ref=false) {
if (!$dom) $dom = &$this->data;
if (!is_array($dom)) $dom = array($dom);
$results = array();
foreach($dom as $key => &$element) {
if (is_array($element) && $key == $target && $ref) return $element;
if (is_array($element) && $key == $target) array_push($results,$element);
if (isset($element['CHILDREN'])) {
$found = &$this->search($target,$element['CHILDREN'],$ref);
if ($ref) return $found;
else $results += $found;
}
}
return $results;
}
}
?>
@@ -0,0 +1,328 @@
<?php $setting = DatabaseObject::tablename('setting'); ?>
DROP TABLE IF EXISTS <?php echo $setting; ?>;
CREATE TABLE <?php echo $setting; ?> (
id bigint(20) unsigned NOT NULL auto_increment,
name varchar(255) NOT NULL default '',
value longtext NOT NULL,
autoload enum('on','off') NOT NULL,
created datetime NOT NULL default '0000-00-00 00:00:00',
modified datetime NOT NULL default '0000-00-00 00:00:00',
PRIMARY KEY id (id)
) ENGINE=MyIsAM DEFAULT CHARSET=utf8;
<?php $product = DatabaseObject::tablename('product'); ?>
DROP TABLE IF EXISTS <?php echo $product; ?>;
CREATE TABLE <?php echo $product; ?> (
id bigint(20) unsigned NOT NULL auto_increment,
name varchar(255) NOT NULL default '',
slug varchar(255) NOT NULL default '',
summary text NOT NULL,
description longtext NOT NULL,
published enum('on','off') NOT NULL,
featured enum('off','on') NOT NULL,
variations enum('off','on') NOT NULL,
options text NOT NULL,
created datetime NOT NULL default '0000-00-00 00:00:00',
modified datetime NOT NULL default '0000-00-00 00:00:00',
PRIMARY KEY id (id),
KEY published (published),
KEY featured (featured),
KEY slug (slug),
FULLTEXT search (name,summary,description)
) ENGINE=MyIsAM DEFAULT CHARSET=utf8;
<?php $price = DatabaseObject::tablename('price'); ?>
DROP TABLE IF EXISTS <?php echo $price; ?>;
CREATE TABLE <?php echo $price; ?> (
id bigint(20) unsigned NOT NULL auto_increment,
product bigint(20) unsigned NOT NULL default '0',
options text NOT NULL,
optionkey bigint(20) unsigned NOT NULL default '0',
label varchar(100) NOT NULL default '',
context enum('product','variation','addon') NOT NULL,
type enum('Shipped','Virtual','Download','Donation','N/A') NOT NULL,
sku varchar(100) NOT NULL default '',
price float(20,2) NOT NULL default '0.00',
saleprice float(20,2) NOT NULL default '0.00',
weight float(20,3) NOT NULL default '0',
shipfee float(20,2) NOT NULL default '0',
stock int(10) NOT NULL default '0',
inventory enum('off','on') NOT NULL,
sale enum('off','on') NOT NULL,
shipping enum('on','off') NOT NULL,
tax enum('on','off') NOT NULL,
donation varchar(255) NOT NULL default '',
sortorder int(10) unsigned NOT NULL default '0',
created datetime NOT NULL default '0000-00-00 00:00:00',
modified datetime NOT NULL default '0000-00-00 00:00:00',
PRIMARY KEY id (id),
KEY product (product),
KEY catalog (product,type,inventory,stock),
KEY context (context)
) ENGINE=MyIsAM DEFAULT CHARSET=utf8;
<?php $spec = DatabaseObject::tablename('spec'); ?>
DROP TABLE IF EXISTS <?php echo $spec; ?>;
CREATE TABLE <?php echo $spec; ?> (
id bigint(20) unsigned NOT NULL auto_increment,
product bigint(20) unsigned NOT NULL default '0',
name varchar(255) NOT NULL default '',
content text NOT NULL,
numeral float(20,4) NOT NULL default '0.0000',
sortorder int(10) unsigned NOT NULL default '0',
PRIMARY KEY id (id),
KEY product (product,name),
FULLTEXT name (name,content)
) ENGINE=MyIsAM DEFAULT CHARSET=utf8;
<?php $category = DatabaseObject::tablename('category'); ?>
DROP TABLE IF EXISTS <?php echo $category; ?>;
CREATE TABLE <?php echo $category; ?> (
id bigint(20) unsigned NOT NULL auto_increment,
parent bigint(20) unsigned NOT NULL default '0',
name varchar(255) NOT NULL default '',
slug varchar(64) NOT NULL default '',
uri varchar(255) NOT NULL default '',
description text NOT NULL,
spectemplate enum('off','on') NOT NULL,
facetedmenus enum('off','on') NOT NULL,
variations enum('off','on') NOT NULL,
pricerange enum('disabled','auto','custom') NOT NULL,
priceranges text NOT NULL,
specs text NOT NULL,
options text NOT NULL,
prices text NOT NULL,
created datetime NOT NULL default '0000-00-00 00:00:00',
modified datetime NOT NULL default '0000-00-00 00:00:00',
PRIMARY KEY id (id),
KEY parent (parent)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
<?php $tag = DatabaseObject::tablename('tag'); ?>
DROP TABLE IF EXISTS <?php echo $tag; ?>;
CREATE TABLE <?php echo $tag; ?> (
id bigint(20) unsigned NOT NULL auto_increment,
name varchar(255) NOT NULL default '',
created datetime NOT NULL default '0000-00-00 00:00:00',
modified datetime NOT NULL default '0000-00-00 00:00:00',
PRIMARY KEY id (id)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
<?php $catalog = DatabaseObject::tablename('catalog'); ?>
DROP TABLE IF EXISTS <?php echo $catalog; ?>;
CREATE TABLE <?php echo $catalog; ?> (
id bigint(20) unsigned NOT NULL auto_increment,
product bigint(20) unsigned NOT NULL default '0',
category bigint(20) unsigned NOT NULL default '0',
tag bigint(20) unsigned NOT NULL default '0',
created datetime NOT NULL default '0000-00-00 00:00:00',
modified datetime NOT NULL default '0000-00-00 00:00:00',
PRIMARY KEY id (id),
KEY product (product),
KEY category (category),
KEY tag (tag)
) ENGINE=MyIsAM DEFAULT CHARSET=utf8;
<?php $asset = DatabaseObject::tablename('asset'); ?>
DROP TABLE IF EXISTS <?php echo $asset; ?>;
CREATE TABLE <?php echo $asset; ?> (
id bigint(20) unsigned NOT NULL auto_increment,
parent bigint(20) unsigned NOT NULL default '0',
context enum('product','price','category') NOT NULL default 'product',
src bigint(20) unsigned NOT NULL default '0',
name varchar(255) NOT NULL default '',
value varchar(255) NOT NULL default '',
properties text NOT NULL,
size bigint(20) unsigned NOT NULL default '0',
data longblob NOT NULL,
datatype enum('metadata','image','small','thumbnail','download') NOT NULL default 'metadata',
sortorder int(10) unsigned NOT NULL default '0',
created datetime NOT NULL default '0000-00-00 00:00:00',
modified datetime NOT NULL default '0000-00-00 00:00:00',
PRIMARY KEY id (id),
KEY parent (parent,context),
KEY src (src)
) ENGINE=MyIsAM DEFAULT CHARSET=utf8;
<?php $cart = DatabaseObject::tablename('cart'); ?>
DROP TABLE IF EXISTS <?php echo $cart; ?>;
CREATE TABLE <?php echo $cart; ?> (
session varchar(32) NOT NULL,
customer bigint(20) unsigned NOT NULL default '0',
ip varchar(15) NOT NULL default '0.0.0.0',
data longtext NOT NULL,
contents longtext NOT NULL,
created datetime NOT NULL default '0000-00-00 00:00:00',
modified datetime NOT NULL default '0000-00-00 00:00:00',
PRIMARY KEY session (session),
KEY customer (customer)
) ENGINE=MyIsAM DEFAULT CHARSET=utf8;
<?php $customer = DatabaseObject::tablename('customer'); ?>
DROP TABLE IF EXISTS <?php echo $customer; ?>;
CREATE TABLE <?php echo $customer; ?> (
id bigint(20) unsigned NOT NULL auto_increment,
wpuser bigint(20) unsigned NOT NULL default '0',
password varchar(64) NOT NULL default '',
firstname varchar(32) NOT NULL default '',
lastname varchar(32) NOT NULL default '',
email varchar(96) NOT NULL default '',
phone varchar(24) NOT NULL default '',
company varchar(100) NOT NULL default '',
activation varchar(20) NOT NULL default '',
info longtext NOT NULL,
created datetime NOT NULL default '0000-00-00 00:00:00',
modified datetime NOT NULL default '0000-00-00 00:00:00',
PRIMARY KEY id (id)
) ENGINE=MyIsAM DEFAULT CHARSET=utf8;
<?php $shipping = DatabaseObject::tablename('shipping'); ?>
DROP TABLE IF EXISTS <?php echo $shipping; ?>;
CREATE TABLE <?php echo $shipping; ?> (
id bigint(20) unsigned NOT NULL auto_increment,
customer bigint(20) unsigned NOT NULL default '0',
address varchar(100) NOT NULL default '',
xaddress varchar(100) NOT NULL default '',
city varchar(100) NOT NULL default '',
state varchar(2) NOT NULL default '',
country varchar(2) NOT NULL default '',
postcode varchar(10) NOT NULL default '',
geocode varchar(16) NOT NULL default '',
created datetime NOT NULL default '0000-00-00 00:00:00',
modified datetime NOT NULL default '0000-00-00 00:00:00',
PRIMARY KEY id (id),
KEY customer (customer)
) ENGINE=MyIsAM DEFAULT CHARSET=utf8;
<?php $billing = DatabaseObject::tablename('billing'); ?>
DROP TABLE IF EXISTS <?php echo $billing; ?>;
CREATE TABLE <?php echo $billing; ?> (
id bigint(20) unsigned NOT NULL auto_increment,
customer bigint(20) unsigned NOT NULL default '0',
card varchar(4) NOT NULL default '',
cardtype varchar(32) NOT NULL default '',
cardexpires date NOT NULL default '0000-00-00',
cardholder varchar(96) NOT NULL default '',
address varchar(100) NOT NULL default '',
xaddress varchar(100) NOT NULL default '',
city varchar(100) NOT NULL default '',
state varchar(2) NOT NULL default '',
country varchar(2) NOT NULL default '',
postcode varchar(10) NOT NULL default '',
created datetime NOT NULL default '0000-00-00 00:00:00',
modified datetime NOT NULL default '0000-00-00 00:00:00',
PRIMARY KEY id (id),
KEY customer (customer)
) ENGINE=MyIsAM DEFAULT CHARSET=utf8;
<?php $purchase = DatabaseObject::tablename('purchase'); ?>
DROP TABLE IF EXISTS <?php echo $purchase; ?>;
CREATE TABLE <?php echo $purchase; ?> (
id bigint(20) unsigned NOT NULL auto_increment,
customer bigint(20) unsigned NOT NULL default '0',
shipping bigint(20) unsigned NOT NULL default '0',
billing bigint(20) unsigned NOT NULL default '0',
currency bigint(20) unsigned NOT NULL default '0',
ip varchar(15) NOT NULL default '0.0.0.0',
firstname varchar(32) NOT NULL default '',
lastname varchar(32) NOT NULL default '',
email varchar(96) NOT NULL default '',
phone varchar(24) NOT NULL default '',
company varchar(100) NOT NULL default '',
card varchar(4) NOT NULL default '',
cardtype varchar(32) NOT NULL default '',
cardexpires date NOT NULL default '0000-00-00',
cardholder varchar(96) NOT NULL default '',
address varchar(100) NOT NULL default '',
xaddress varchar(100) NOT NULL default '',
city varchar(100) NOT NULL default '',
state varchar(100) NOT NULL default '',
country varchar(2) NOT NULL default '',
postcode varchar(10) NOT NULL default '',
shipaddress varchar(100) NOT NULL default '',
shipxaddress varchar(100) NOT NULL default '',
shipcity varchar(100) NOT NULL default '',
shipstate varchar(100) NOT NULL default '',
shipcountry varchar(2) NOT NULL default '',
shippostcode varchar(10) NOT NULL default '',
geocode varchar(16) NOT NULL default '',
promos varchar(255) NOT NULL default '',
subtotal float(20,2) NOT NULL default '0.00',
freight float(20,2) NOT NULL default '0.00',
tax float(20,2) NOT NULL default '0.00',
total float(20,2) NOT NULL default '0.00',
discount float(20,2) NOT NULL default '0.00',
fees float(20,2) NOT NULL default '0.00',
transactionid varchar(64) NOT NULL default '',
transtatus varchar(64) NOT NULL default '',
gateway varchar(64) NOT NULL default '',
shipmethod varchar(100) NOT NULL default '',
shiptrack varchar(100) NOT NULL default '',
status tinyint(3) unsigned NOT NULL default '0',
data longtext NOT NULL,
created datetime NOT NULL default '0000-00-00 00:00:00',
modified datetime NOT NULL default '0000-00-00 00:00:00',
PRIMARY KEY id (id),
KEY customer (customer)
) ENGINE=MyIsAM DEFAULT CHARSET=utf8;
<?php $purchased = DatabaseObject::tablename('purchased'); ?>
DROP TABLE IF EXISTS <?php echo $purchased; ?>;
CREATE TABLE <?php echo $purchased; ?> (
id bigint(20) unsigned NOT NULL auto_increment,
purchase bigint(20) unsigned NOT NULL default '0',
product bigint(20) unsigned NOT NULL default '0',
price bigint(20) unsigned NOT NULL default '0',
download bigint(20) unsigned NOT NULL default '0',
dkey varchar(255) NOT NULL default '',
name varchar(255) NOT NULL default '',
description text NOT NULL,
optionlabel varchar(255) NOT NULL default '',
sku varchar(100) NOT NULL default '',
quantity int(10) unsigned NOT NULL default '0',
downloads int(10) unsigned NOT NULL default '0',
unitprice float(20,2) NOT NULL default '0.00',
shipping float(20,2) NOT NULL default '0.00',
total float(20,2) NOT NULL default '0.00',
variation text NOT NULL,
data longtext NOT NULL,
created datetime NOT NULL default '0000-00-00 00:00:00',
modified datetime NOT NULL default '0000-00-00 00:00:00',
PRIMARY KEY id (id),
KEY purchase (purchase),
KEY product (product),
KEY dkey (dkey(8))
) ENGINE=MyIsAM DEFAULT CHARSET=utf8;
<?php $promo = DatabaseObject::tablename('promo'); ?>
DROP TABLE IF EXISTS <?php echo $promo; ?>;
CREATE TABLE <?php echo $promo; ?> (
id bigint(20) unsigned NOT NULL auto_increment,
name varchar(255) NOT NULL default '',
status enum('disabled','enabled') default 'disabled',
type enum('Percentage Off','Amount Off','Free Shipping','Buy X Get Y Free') default 'Percentage Off',
scope enum('Catalog','Order') default 'Catalog',
discount float(20,2) NOT NULL default '0.00',
buyqty int(10) NOT NULL default '0',
getqty int(10) NOT NULL default '0',
search enum('all','any') default 'all',
code varchar(255) NOT NULL default '',
rules text NOT NULL,
starts datetime NOT NULL default '0000-00-00 00:00:00',
ends datetime NOT NULL default '0000-00-00 00:00:00',
created datetime NOT NULL default '0000-00-00 00:00:00',
modified datetime NOT NULL default '0000-00-00 00:00:00',
PRIMARY KEY id (id)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
<?php $discount = DatabaseObject::tablename('discount'); ?>
DROP TABLE IF EXISTS <?php echo $discount; ?>;
CREATE TABLE <?php echo $discount; ?> (
id bigint(20) unsigned NOT NULL auto_increment,
promo bigint(20) unsigned NOT NULL default '0',
product bigint(20) unsigned NOT NULL default '0',
price bigint(20) unsigned NOT NULL default '0',
PRIMARY KEY id (id),
KEY lookup (product,price)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
@@ -0,0 +1 @@
(function($){var validate=function(form){if(!form){return false}var inputs=form.getElementsByTagName("input");var selects=form.getElementsByTagName("select");var passed=true;var passwords=new Array();var error=new Array();for(var i=selects.length-1;i>=0;i--){if(selects[i].className.match(new RegExp("required"))&&!selects[i].disabled){if(selects[i].selectedIndex==0&&selects[i].options[0].value==""){error=new Array(CHECKOUT_REQUIRED_FIELD.replace(/%s/,selects[i].title),selects[i])}}}for(var i=inputs.length-1;i>=0;i--){if(inputs[i].className.match(new RegExp("required"))){if(inputs[i].type=="checkbox"){if(!inputs[i].checked){error=new Array(CHECKOUT_CHECKBOX_CHECKED.replace(/%s/,inputs[i].title),inputs[i])}}else{if(inputs[i].value==null||inputs[i].value==""){error=new Array(CHECKOUT_REQUIRED_FIELD.replace(/%s/,inputs[i].title),inputs[i])}}}if(inputs[i].className.match(new RegExp("email"))){if(!inputs[i].value.match(new RegExp("^[a-zA-Z0-9._-]+@([a-zA-Z0-9.-]+.)+[a-zA-Z0-9.-]{2,4}$"))){error=new Array(CHECKOUT_INVALID_EMAIL,inputs[i])}}if(chars=inputs[i].className.match(new RegExp("min(\\d+)"))){if(inputs[i].value.length<chars[1]){error=new Array(CHECKOUT_MIN_LENGTH.replace(/%s/,inputs[i].title).replace(/%d/,chars[1]),inputs[i])}}if(inputs[i].className.match(new RegExp("passwords"))){passwords.push(inputs[i]);if(passwords.length==2&&passwords[0].value!=passwords[1].value){error=new Array(CHECKOUT_PASSWORD_MISMATCH,passwords[1])}}}if(error.length>0){error[1].focus();alert(error[0]);passed=false}return passed};$(window).ready(function(){var sameshipping=$("#same-shipping");if(sameshipping.length>0){sameshipping.change(function(){if($("#same-shipping").attr("checked")){$("#billing-address-fields").removeClass("half");$("#shipping-address-fields").hide();$("#shipping-address-fields .required").removeClass("required")}else{$("#billing-address-fields").addClass("half");$("#shipping-address-fields input").not("#shipping-xaddress").addClass("required");$("#shipping-address-fields select").addClass("required");$("#shipping-address-fields").show()}}).change();sameshipping.click(function(){$(this).change()})}$("#submit-login").click(function(){$("#checkout.shopp").unbind("submit");$("#checkout.shopp").submit(function(){if($("#account-login").val()==""){alert(CHECKOUT_LOGIN_NAME);$("#account-login").focus();return false}if($("#password-login").val()==""){alert(CHECKOUT_LOGIN_PASSWORD);$("#password-login").focus();return false}$("#process-login").val("true");return true}).submit()});$("#checkout.shopp").submit(function(){if(validate(this)){return true}else{return false}});$("#shipping-country").change(function(){if($("#shipping-state").attr("type")=="text"){return true}$("#shipping-state").empty().attr("disabled",true);$("<option></option>").val("").html("").appendTo("#shipping-state");if(regions[this.value]){$.each(regions[this.value],function(value,label){option=$("<option></option>").val(value).html(label).appendTo("#shipping-state")});$("#shipping-state").attr("disabled",false)}});$("#billing-country").change(function(){if($("#billing-state").attr("type")=="text"){return true}$("#billing-state").empty().attr("disabled",true);$("<option></option>").val("").html("").appendTo("#billing-state");if(regions[this.value]){$.each(regions[this.value],function(value,label){option=$("<option></option>").val(value).html(label).appendTo("#billing-state")});$("#billing-state").attr("disabled",false)}});$("input.shipmethod").click(function(){$("#shipping, #total").html(SHIPCALC_STATUS);var url=$("#shopp form").attr("action");url+=(url.indexOf("?")==-1)?"?":"&";$.getJSON(url+"shopp_lookup=shipcost&method="+$(this).val(),function(result){var totals=eval(result);$("span.shopp_cart_shipping").html(asMoney(totals.shipping));$("span.shopp_cart_tax").html(asMoney(totals.tax));$("span.shopp_cart_total").html(asMoney(totals.total))})})})})(jQuery);
File diff suppressed because one or more lines are too long
@@ -0,0 +1 @@
(function(a){a.fn.upload=function(b){b=a.extend({name:"file",enctype:"multipart/form-data",action:"",autoSubmit:true,onSubmit:function(){},onComplete:function(){},onSelect:function(){},params:{}},b);return new a.ocupload(this,b)},a.ocupload=function(f,e){var d=this;var i=new Date().getTime().toString().substr(8);var g=a('<iframe id="iframe'+i+'" name="iframe'+i+'"></iframe>').css({display:"none"});var h=a('<form method="post" enctype="'+e.enctype+'" action="'+e.action+'" target="iframe'+i+'"></form>').css({margin:0,padding:0});var c=a('<input name="'+e.name+'" type="file" />').css({position:"relative",display:"block",marginLeft:-175+"px",opacity:0});f.wrap("<div></div>");h.append(c);f.after(h);f.after(g);elementHeight=f.outerHeight();elementWidth=f.outerWidth();var b=f.parent().css({position:"relative",height:(elementHeight+10)+"px",width:(elementWidth+10)+"px",overflow:"hidden",cursor:"pointer",margin:0,padding:0});c.css("marginTop",-b.height()-10+"px");b.mousemove(function(j){c.css({top:j.pageY-b.offset().top+"px",left:j.pageX-b.offset().left+"px"})});c.change(function(){d.onSelect();if(d.autoSubmit){d.submit()}});a.extend(this,{autoSubmit:true,onSubmit:e.onSubmit,onComplete:e.onComplete,onSelect:e.onSelect,filename:function(){return c.attr("value")},params:function(j){var j=j?j:false;if(j){e.params=a.extend(e.params,j)}else{return e.params}},name:function(j){var j=j?j:false;if(j){c.attr("name",value)}else{return c.attr("name")}},action:function(j){var j=j?j:false;if(j){h.attr("action",j)}else{return h.attr("action")}},enctype:function(j){var j=j?j:false;if(j){h.attr("enctype",j)}else{return h.attr("enctype")}},set:function(l,k){var k=k?k:false;function j(n,m){switch(n){default:throw new Error("[jQuery.ocupload.set] '"+n+"' is an invalid option.");break;case"name":d.name(m);break;case"action":d.action(m);break;case"enctype":d.enctype(m);break;case"params":d.params(m);break;case"autoSubmit":d.autoSubmit=m;break;case"onSubmit":d.onSubmit=m;break;case"onComplete":d.onComplete=m;break;case"onSelect":d.onSelect=m;break}}if(k){j(l,k)}else{a.each(l,function(m,n){j(m,n)})}},submit:function(){this.onSubmit();a.each(e.params,function(j,k){h.append(a('<input type="hidden" name="'+j+'" value="'+k+'" />'))});h.submit();g.unbind().load(function(){var k=document.getElementById(g.attr("name"));var j=a(k.contentWindow.document.body).text();d.onComplete(j)})}})}})(jQuery);
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1,17 @@
var currencyFormat = <?php echo json_encode($base_operations['currency']['format']); ?>;
var tb_pathToImage = '<?php echo force_ssl(WP_PLUGIN_URL); ?>/<?php echo $dir; ?>/core/ui/icons/loading.gif';
var UNSAVED_CHANGES_WARNING = '<?php echo addslashes(__('There are unsaved changes that will be lost if you continue.','Shopp')); ?>';
var CHECKOUT_LOGIN_NAME = '<?php echo addslashes(__('You did not enter a login.','Shopp')); ?>';
var CHECKOUT_LOGIN_PASSWORD = '<?php echo addslashes(__('You did not enter a password to login with.','Shopp')); ?>';
var CHECKOUT_REQUIRED_FIELD = '<?php echo addslashes(__('Your %s is required.','Shopp')); ?>';
var CHECKOUT_INVALID_EMAIL = '<?php echo addslashes(__('The e-mail address you provided does not appear to be a valid address.','Shopp')); ?>';
var CHECKOUT_MIN_LENGTH = '<?php echo addslashes(__('The %s you entered is too short. It must be at least %d characters long.','Shopp')); ?>';
var CHECKOUT_PASSWORD_MISMATCH = '<?php echo addslashes(__('The passwords you entered do not match. They must match in order to confirm you are correctly entering the password you want to use.','Shopp')); ?>';
var CHECKOUT_CHECKBOX_CHECKED = '<?php echo addslashes(__('%s must be checked before you can proceed.','Shopp')); ?>';
var SHOPP_TB_CLOSE = '<?php echo addslashes(__('Press Esc Key or','Shopp')); ?>';
var SHOPP_TB_IMAGE = '<?php echo addslashes(__('Image %d of %d','Shopp')); ?>';
var SHOPP_TB_NEXT = '<?php echo addslashes(__('Next','Shopp')); ?>';
var SHOPP_TB_BACK = '<?php echo addslashes(__('Back','Shopp')); ?>';
var MONTH_NAMES = new Array('','<?php echo addslashes(__('January','Shopp')) ?>','<?php echo addslashes(__('February','Shopp')) ?>','<?php echo addslashes(__('March','Shopp')) ?>','<?php echo addslashes(__('April','Shopp')) ?>','<?php echo addslashes(__('May','Shopp')) ?>','<?php echo addslashes(__('June','Shopp')) ?>','<?php echo addslashes(__('July','Shopp')) ?>','<?php echo addslashes(__('August','Shopp')) ?>','<?php echo addslashes(__('September','Shopp')) ?>','<?php echo addslashes(__('October','Shopp')) ?>','<?php echo addslashes(__('November','Shopp')) ?>','<?php echo addslashes(__('December','Shopp')) ?>');
var WEEK_DAYS = new Array('<?php echo addslashes(__('Sun','Shopp')) ?>','<?php echo addslashes(__('Mon','Shopp')) ?>','<?php echo addslashes(__('Tue','Shopp')) ?>','<?php echo addslashes(__('Wed','Shopp')) ?>','<?php echo addslashes(__('Thu','Shopp')) ?>','<?php echo addslashes(__('Fri','Shopp')) ?>','<?php echo addslashes(__('Sat','Shopp')) ?>');
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1,927 @@
/**
* SWFUpload: http://www.swfupload.org, http://swfupload.googlecode.com
*
* mmSWFUpload 1.0: Flash upload dialog - http://profandesign.se/swfupload/, http://www.vinterwebb.se/
*
* SWFUpload is (c) 2006-2007 Lars Huring, Olov Nilzén and Mammon Media and is released under the MIT License:
* http://www.opensource.org/licenses/mit-license.php
*
* SWFUpload 2 is (c) 2007-2008 Jake Roberts and is released under the MIT License:
* http://www.opensource.org/licenses/mit-license.php
*
*/
/* ******************* */
/* Constructor & Init */
/* ******************* */
var SWFUpload;
if (SWFUpload == undefined) {
SWFUpload = function (settings) {
this.initSWFUpload(settings);
};
}
SWFUpload.prototype.initSWFUpload = function (settings) {
try {
this.customSettings = {}; // A container where developers can place their own settings associated with this instance.
this.settings = settings;
this.eventQueue = [];
this.movieName = "SWFUpload_" + SWFUpload.movieCount++;
this.movieElement = null;
// Setup global control tracking
SWFUpload.instances[this.movieName] = this;
// Load the settings. Load the Flash movie.
this.initSettings();
this.loadFlash();
this.displayDebugInfo();
} catch (ex) {
delete SWFUpload.instances[this.movieName];
throw ex;
}
};
/* *************** */
/* Static Members */
/* *************** */
SWFUpload.instances = {};
SWFUpload.movieCount = 0;
SWFUpload.version = "2.2.0 Beta 2";
SWFUpload.QUEUE_ERROR = {
QUEUE_LIMIT_EXCEEDED : -100,
FILE_EXCEEDS_SIZE_LIMIT : -110,
ZERO_BYTE_FILE : -120,
INVALID_FILETYPE : -130
};
SWFUpload.UPLOAD_ERROR = {
HTTP_ERROR : -200,
MISSING_UPLOAD_URL : -210,
IO_ERROR : -220,
SECURITY_ERROR : -230,
UPLOAD_LIMIT_EXCEEDED : -240,
UPLOAD_FAILED : -250,
SPECIFIED_FILE_ID_NOT_FOUND : -260,
FILE_VALIDATION_FAILED : -270,
FILE_CANCELLED : -280,
UPLOAD_STOPPED : -290
};
SWFUpload.FILE_STATUS = {
QUEUED : -1,
IN_PROGRESS : -2,
ERROR : -3,
COMPLETE : -4,
CANCELLED : -5
};
SWFUpload.BUTTON_ACTION = {
SELECT_FILE : -100,
SELECT_FILES : -110,
START_UPLOAD : -120
};
SWFUpload.CURSOR = {
ARROW : -1,
HAND : -2
};
SWFUpload.WINDOW_MODE = {
WINDOW : "window",
TRANSPARENT : "transparent",
OPAQUE : "opaque"
};
/* ******************** */
/* Instance Members */
/* ******************** */
// Private: initSettings ensures that all the
// settings are set, getting a default value if one was not assigned.
SWFUpload.prototype.initSettings = function () {
this.ensureDefault = function (settingName, defaultValue) {
this.settings[settingName] = (this.settings[settingName] == undefined) ? defaultValue : this.settings[settingName];
};
// Upload backend settings
this.ensureDefault("upload_url", "");
this.ensureDefault("file_post_name", "Filedata");
this.ensureDefault("post_params", {});
this.ensureDefault("use_query_string", false);
this.ensureDefault("requeue_on_error", false);
this.ensureDefault("http_success", []);
// File Settings
this.ensureDefault("file_types", "*.*");
this.ensureDefault("file_types_description", "All Files");
this.ensureDefault("file_size_limit", 0); // Default zero means "unlimited"
this.ensureDefault("file_upload_limit", 0);
this.ensureDefault("file_queue_limit", 0);
// Flash Settings
this.ensureDefault("flash_url", "swfupload.swf");
this.ensureDefault("prevent_swf_caching", true);
// Button Settings
this.ensureDefault("button_image_url", "");
this.ensureDefault("button_width", 1);
this.ensureDefault("button_height", 1);
this.ensureDefault("button_text", "");
this.ensureDefault("button_text_style", "color: #000000; font-size: 16pt;");
this.ensureDefault("button_text_top_padding", 0);
this.ensureDefault("button_text_left_padding", 0);
this.ensureDefault("button_action", SWFUpload.BUTTON_ACTION.SELECT_FILES);
this.ensureDefault("button_disabled", false);
this.ensureDefault("button_placeholder_id", null);
this.ensureDefault("button_cursor", SWFUpload.CURSOR.ARROW);
this.ensureDefault("button_window_mode", SWFUpload.WINDOW_MODE.WINDOW);
// Debug Settings
this.ensureDefault("debug", false);
this.settings.debug_enabled = this.settings.debug; // Here to maintain v2 API
// Event Handlers
this.settings.return_upload_start_handler = this.returnUploadStart;
this.ensureDefault("swfupload_loaded_handler", null);
this.ensureDefault("file_dialog_start_handler", null);
this.ensureDefault("file_queued_handler", null);
this.ensureDefault("file_queue_error_handler", null);
this.ensureDefault("file_dialog_complete_handler", null);
this.ensureDefault("upload_start_handler", null);
this.ensureDefault("upload_progress_handler", null);
this.ensureDefault("upload_error_handler", null);
this.ensureDefault("upload_success_handler", null);
this.ensureDefault("upload_complete_handler", null);
this.ensureDefault("debug_handler", this.debugMessage);
this.ensureDefault("custom_settings", {});
// Other settings
this.customSettings = this.settings.custom_settings;
// Update the flash url if needed
if (this.settings.prevent_swf_caching) {
this.settings.flash_url = this.settings.flash_url + "?swfuploadrnd=" + Math.floor(Math.random() * 999999999);
}
delete this.ensureDefault;
};
SWFUpload.prototype.loadFlash = function () {
if (this.settings.button_placeholder_id !== "") {
this.replaceWithFlash();
} else {
this.appendFlash();
}
};
// Private: appendFlash gets the HTML tag for the Flash
// It then appends the flash to the body
SWFUpload.prototype.appendFlash = function () {
var targetElement, container;
// Make sure an element with the ID we are going to use doesn't already exist
if (document.getElementById(this.movieName) !== null) {
throw "ID " + this.movieName + " is already in use. The Flash Object could not be added";
}
// Get the body tag where we will be adding the flash movie
targetElement = document.getElementsByTagName("body")[0];
if (targetElement == undefined) {
throw "Could not find the 'body' element.";
}
// Append the container and load the flash
container = document.createElement("div");
container.style.width = "1px";
container.style.height = "1px";
container.style.overflow = "hidden";
targetElement.appendChild(container);
container.innerHTML = this.getFlashHTML(); // Using innerHTML is non-standard but the only sensible way to dynamically add Flash in IE (and maybe other browsers)
};
// Private: replaceWithFlash replaces the button_placeholder element with the flash movie.
SWFUpload.prototype.replaceWithFlash = function () {
var targetElement, tempParent;
// Make sure an element with the ID we are going to use doesn't already exist
if (document.getElementById(this.movieName) !== null) {
throw "ID " + this.movieName + " is already in use. The Flash Object could not be added";
}
// Get the element where we will be placing the flash movie
targetElement = document.getElementById(this.settings.button_placeholder_id);
if (targetElement == undefined) {
throw "Could not find the placeholder element.";
}
// Append the container and load the flash
tempParent = document.createElement("div");
tempParent.innerHTML = this.getFlashHTML(); // Using innerHTML is non-standard but the only sensible way to dynamically add Flash in IE (and maybe other browsers)
targetElement.parentNode.replaceChild(tempParent.firstChild, targetElement);
};
// Private: getFlashHTML generates the object tag needed to embed the flash in to the document
SWFUpload.prototype.getFlashHTML = function () {
// Flash Satay object syntax: http://www.alistapart.com/articles/flashsatay
return ['<object id="', this.movieName, '" type="application/x-shockwave-flash" data="', this.settings.flash_url, '" width="', this.settings.button_width, '" height="', this.settings.button_height, '" class="swfupload">',
'<param name="wmode" value="', this.settings.button_window_mode , '" />',
'<param name="movie" value="', this.settings.flash_url, '" />',
'<param name="quality" value="high" />',
'<param name="menu" value="false" />',
'<param name="allowScriptAccess" value="always" />',
'<param name="flashvars" value="' + this.getFlashVars() + '" />',
'</object>'].join("");
};
// Private: getFlashVars builds the parameter string that will be passed
// to flash in the flashvars param.
SWFUpload.prototype.getFlashVars = function () {
// Build a string from the post param object
var paramString = this.buildParamString();
var httpSuccessString = this.settings.http_success.join(",");
// Build the parameter string
return ["movieName=", encodeURIComponent(this.movieName),
"&amp;uploadURL=", encodeURIComponent(this.settings.upload_url),
"&amp;useQueryString=", encodeURIComponent(this.settings.use_query_string),
"&amp;requeueOnError=", encodeURIComponent(this.settings.requeue_on_error),
"&amp;httpSuccess=", encodeURIComponent(httpSuccessString),
"&amp;params=", encodeURIComponent(paramString),
"&amp;filePostName=", encodeURIComponent(this.settings.file_post_name),
"&amp;fileTypes=", encodeURIComponent(this.settings.file_types),
"&amp;fileTypesDescription=", encodeURIComponent(this.settings.file_types_description),
"&amp;fileSizeLimit=", encodeURIComponent(this.settings.file_size_limit),
"&amp;fileUploadLimit=", encodeURIComponent(this.settings.file_upload_limit),
"&amp;fileQueueLimit=", encodeURIComponent(this.settings.file_queue_limit),
"&amp;debugEnabled=", encodeURIComponent(this.settings.debug_enabled),
"&amp;buttonImageURL=", encodeURIComponent(this.settings.button_image_url),
"&amp;buttonWidth=", encodeURIComponent(this.settings.button_width),
"&amp;buttonHeight=", encodeURIComponent(this.settings.button_height),
"&amp;buttonText=", encodeURIComponent(this.settings.button_text),
"&amp;buttonTextTopPadding=", encodeURIComponent(this.settings.button_text_top_padding),
"&amp;buttonTextLeftPadding=", encodeURIComponent(this.settings.button_text_left_padding),
"&amp;buttonTextStyle=", encodeURIComponent(this.settings.button_text_style),
"&amp;buttonAction=", encodeURIComponent(this.settings.button_action),
"&amp;buttonDisabled=", encodeURIComponent(this.settings.button_disabled),
"&amp;buttonCursor=", encodeURIComponent(this.settings.button_cursor)
].join("");
};
// Public: getMovieElement retrieves the DOM reference to the Flash element added by SWFUpload
// The element is cached after the first lookup
SWFUpload.prototype.getMovieElement = function () {
if (this.movieElement == undefined) {
this.movieElement = document.getElementById(this.movieName);
}
if (this.movieElement === null) {
throw "Could not find Flash element";
}
return this.movieElement;
};
// Private: buildParamString takes the name/value pairs in the post_params setting object
// and joins them up in to a string formatted "name=value&amp;name=value"
SWFUpload.prototype.buildParamString = function () {
var postParams = this.settings.post_params;
var paramStringPairs = [];
if (typeof(postParams) === "object") {
for (var name in postParams) {
if (postParams.hasOwnProperty(name)) {
paramStringPairs.push(encodeURIComponent(name.toString()) + "=" + encodeURIComponent(postParams[name].toString()));
}
}
}
return paramStringPairs.join("&amp;");
};
// Public: Used to remove a SWFUpload instance from the page. This method strives to remove
// all references to the SWF, and other objects so memory is properly freed.
// Returns true if everything was destroyed. Returns a false if a failure occurs leaving SWFUpload in an inconsistant state.
SWFUpload.prototype.destroy = function () {
try {
// Make sure Flash is done before we try to remove it
this.stopUpload();
// Remove the SWFUpload DOM nodes
var movieElement = null;
try {
movieElement = this.getMovieElement();
} catch (ex) {
}
if (movieElement != undefined && movieElement.parentNode != undefined && typeof movieElement.parentNode.removeChild === "function") {
var container = movieElement.parentNode;
if (container != undefined) {
container.removeChild(movieElement);
if (container.parentNode != undefined && typeof container.parentNode.removeChild === "function") {
container.parentNode.removeChild(container);
}
}
}
// Destroy references
SWFUpload.instances[this.movieName] = null;
delete SWFUpload.instances[this.movieName];
delete this.movieElement;
delete this.settings;
delete this.customSettings;
delete this.eventQueue;
delete this.movieName;
delete window[this.movieName];
return true;
} catch (ex1) {
return false;
}
};
// Public: displayDebugInfo prints out settings and configuration
// information about this SWFUpload instance.
// This function (and any references to it) can be deleted when placing
// SWFUpload in production.
SWFUpload.prototype.displayDebugInfo = function () {
this.debug(
[
"---SWFUpload Instance Info---\n",
"Version: ", SWFUpload.version, "\n",
"Movie Name: ", this.movieName, "\n",
"Settings:\n",
"\t", "upload_url: ", this.settings.upload_url, "\n",
"\t", "flash_url: ", this.settings.flash_url, "\n",
"\t", "use_query_string: ", this.settings.use_query_string.toString(), "\n",
"\t", "requeue_on_error: ", this.settings.requeue_on_error.toString(), "\n",
"\t", "http_success: ", this.settings.http_success.join(", "), "\n",
"\t", "file_post_name: ", this.settings.file_post_name, "\n",
"\t", "post_params: ", this.settings.post_params.toString(), "\n",
"\t", "file_types: ", this.settings.file_types, "\n",
"\t", "file_types_description: ", this.settings.file_types_description, "\n",
"\t", "file_size_limit: ", this.settings.file_size_limit, "\n",
"\t", "file_upload_limit: ", this.settings.file_upload_limit, "\n",
"\t", "file_queue_limit: ", this.settings.file_queue_limit, "\n",
"\t", "debug: ", this.settings.debug.toString(), "\n",
"\t", "prevent_swf_caching: ", this.settings.prevent_swf_caching.toString(), "\n",
"\t", "button_placeholder_id: ", this.settings.button_placeholder_id.toString(), "\n",
"\t", "button_image_url: ", this.settings.button_image_url.toString(), "\n",
"\t", "button_width: ", this.settings.button_width.toString(), "\n",
"\t", "button_height: ", this.settings.button_height.toString(), "\n",
"\t", "button_text: ", this.settings.button_text.toString(), "\n",
"\t", "button_text_style: ", this.settings.button_text_style.toString(), "\n",
"\t", "button_text_top_padding: ", this.settings.button_text_top_padding.toString(), "\n",
"\t", "button_text_left_padding: ", this.settings.button_text_left_padding.toString(), "\n",
"\t", "button_action: ", this.settings.button_action.toString(), "\n",
"\t", "button_disabled: ", this.settings.button_disabled.toString(), "\n",
"\t", "custom_settings: ", this.settings.custom_settings.toString(), "\n",
"Event Handlers:\n",
"\t", "swfupload_loaded_handler assigned: ", (typeof this.settings.swfupload_loaded_handler === "function").toString(), "\n",
"\t", "file_dialog_start_handler assigned: ", (typeof this.settings.file_dialog_start_handler === "function").toString(), "\n",
"\t", "file_queued_handler assigned: ", (typeof this.settings.file_queued_handler === "function").toString(), "\n",
"\t", "file_queue_error_handler assigned: ", (typeof this.settings.file_queue_error_handler === "function").toString(), "\n",
"\t", "upload_start_handler assigned: ", (typeof this.settings.upload_start_handler === "function").toString(), "\n",
"\t", "upload_progress_handler assigned: ", (typeof this.settings.upload_progress_handler === "function").toString(), "\n",
"\t", "upload_error_handler assigned: ", (typeof this.settings.upload_error_handler === "function").toString(), "\n",
"\t", "upload_success_handler assigned: ", (typeof this.settings.upload_success_handler === "function").toString(), "\n",
"\t", "upload_complete_handler assigned: ", (typeof this.settings.upload_complete_handler === "function").toString(), "\n",
"\t", "debug_handler assigned: ", (typeof this.settings.debug_handler === "function").toString(), "\n"
].join("")
);
};
/* Note: addSetting and getSetting are no longer used by SWFUpload but are included
the maintain v2 API compatibility
*/
// Public: (Deprecated) addSetting adds a setting value. If the value given is undefined or null then the default_value is used.
SWFUpload.prototype.addSetting = function (name, value, default_value) {
if (value == undefined) {
return (this.settings[name] = default_value);
} else {
return (this.settings[name] = value);
}
};
// Public: (Deprecated) getSetting gets a setting. Returns an empty string if the setting was not found.
SWFUpload.prototype.getSetting = function (name) {
if (this.settings[name] != undefined) {
return this.settings[name];
}
return "";
};
// Private: callFlash handles function calls made to the Flash element.
// Calls are made with a setTimeout for some functions to work around
// bugs in the ExternalInterface library.
SWFUpload.prototype.callFlash = function (functionName, argumentArray) {
argumentArray = argumentArray || [];
var movieElement = this.getMovieElement();
var returnValue;
if (typeof movieElement[functionName] === "function") {
// We have to go through all this if/else stuff because the Flash functions don't have apply() and only accept the exact number of arguments.
if (argumentArray.length === 0) {
returnValue = movieElement[functionName]();
} else if (argumentArray.length === 1) {
returnValue = movieElement[functionName](argumentArray[0]);
} else if (argumentArray.length === 2) {
returnValue = movieElement[functionName](argumentArray[0], argumentArray[1]);
} else if (argumentArray.length === 3) {
returnValue = movieElement[functionName](argumentArray[0], argumentArray[1], argumentArray[2]);
} else {
throw "Too many arguments";
}
// Unescape file post param values
if (returnValue != undefined && typeof returnValue.post === "object") {
returnValue = this.unescapeFilePostParams(returnValue);
}
return returnValue;
} else {
throw "Invalid function name: " + functionName;
}
};
/* *****************************
-- Flash control methods --
Your UI should use these
to operate SWFUpload
***************************** */
// Public: selectFile causes a File Selection Dialog window to appear. This
// dialog only allows 1 file to be selected. WARNING: this function does not work in Flash Player 10
SWFUpload.prototype.selectFile = function () {
this.callFlash("SelectFile");
};
// Public: selectFiles causes a File Selection Dialog window to appear/ This
// dialog allows the user to select any number of files
// Flash Bug Warning: Flash limits the number of selectable files based on the combined length of the file names.
// If the selection name length is too long the dialog will fail in an unpredictable manner. There is no work-around
// for this bug. WARNING: this function does not work in Flash Player 10
SWFUpload.prototype.selectFiles = function () {
this.callFlash("SelectFiles");
};
// Public: startUpload starts uploading the first file in the queue unless
// the optional parameter 'fileID' specifies the ID
SWFUpload.prototype.startUpload = function (fileID) {
this.callFlash("StartUpload", [fileID]);
};
// Public: cancelUpload cancels any queued file. The fileID parameter may be the file ID or index.
// If you do not specify a fileID the current uploading file or first file in the queue is cancelled.
// If you do not want the uploadError event to trigger you can specify false for the triggerErrorEvent parameter.
SWFUpload.prototype.cancelUpload = function (fileID, triggerErrorEvent) {
if (triggerErrorEvent !== false) {
triggerErrorEvent = true;
}
this.callFlash("CancelUpload", [fileID, triggerErrorEvent]);
};
// Public: stopUpload stops the current upload and requeues the file at the beginning of the queue.
// If nothing is currently uploading then nothing happens.
SWFUpload.prototype.stopUpload = function () {
this.callFlash("StopUpload");
};
/* ************************
* Settings methods
* These methods change the SWFUpload settings.
* SWFUpload settings should not be changed directly on the settings object
* since many of the settings need to be passed to Flash in order to take
* effect.
* *********************** */
// Public: getStats gets the file statistics object.
SWFUpload.prototype.getStats = function () {
return this.callFlash("GetStats");
};
// Public: setStats changes the SWFUpload statistics. You shouldn't need to
// change the statistics but you can. Changing the statistics does not
// affect SWFUpload accept for the successful_uploads count which is used
// by the upload_limit setting to determine how many files the user may upload.
SWFUpload.prototype.setStats = function (statsObject) {
this.callFlash("SetStats", [statsObject]);
};
// Public: getFile retrieves a File object by ID or Index. If the file is
// not found then 'null' is returned.
SWFUpload.prototype.getFile = function (fileID) {
if (typeof(fileID) === "number") {
return this.callFlash("GetFileByIndex", [fileID]);
} else {
return this.callFlash("GetFile", [fileID]);
}
};
// Public: addFileParam sets a name/value pair that will be posted with the
// file specified by the Files ID. If the name already exists then the
// exiting value will be overwritten.
SWFUpload.prototype.addFileParam = function (fileID, name, value) {
return this.callFlash("AddFileParam", [fileID, name, value]);
};
// Public: removeFileParam removes a previously set (by addFileParam) name/value
// pair from the specified file.
SWFUpload.prototype.removeFileParam = function (fileID, name) {
this.callFlash("RemoveFileParam", [fileID, name]);
};
// Public: setUploadUrl changes the upload_url setting.
SWFUpload.prototype.setUploadURL = function (url) {
this.settings.upload_url = url.toString();
this.callFlash("SetUploadURL", [url]);
};
// Public: setPostParams changes the post_params setting
SWFUpload.prototype.setPostParams = function (paramsObject) {
this.settings.post_params = paramsObject;
this.callFlash("SetPostParams", [paramsObject]);
};
// Public: addPostParam adds post name/value pair. Each name can have only one value.
SWFUpload.prototype.addPostParam = function (name, value) {
this.settings.post_params[name] = value;
this.callFlash("SetPostParams", [this.settings.post_params]);
};
// Public: removePostParam deletes post name/value pair.
SWFUpload.prototype.removePostParam = function (name) {
delete this.settings.post_params[name];
this.callFlash("SetPostParams", [this.settings.post_params]);
};
// Public: setFileTypes changes the file_types setting and the file_types_description setting
SWFUpload.prototype.setFileTypes = function (types, description) {
this.settings.file_types = types;
this.settings.file_types_description = description;
this.callFlash("SetFileTypes", [types, description]);
};
// Public: setFileSizeLimit changes the file_size_limit setting
SWFUpload.prototype.setFileSizeLimit = function (fileSizeLimit) {
this.settings.file_size_limit = fileSizeLimit;
this.callFlash("SetFileSizeLimit", [fileSizeLimit]);
};
// Public: setFileUploadLimit changes the file_upload_limit setting
SWFUpload.prototype.setFileUploadLimit = function (fileUploadLimit) {
this.settings.file_upload_limit = fileUploadLimit;
this.callFlash("SetFileUploadLimit", [fileUploadLimit]);
};
// Public: setFileQueueLimit changes the file_queue_limit setting
SWFUpload.prototype.setFileQueueLimit = function (fileQueueLimit) {
this.settings.file_queue_limit = fileQueueLimit;
this.callFlash("SetFileQueueLimit", [fileQueueLimit]);
};
// Public: setFilePostName changes the file_post_name setting
SWFUpload.prototype.setFilePostName = function (filePostName) {
this.settings.file_post_name = filePostName;
this.callFlash("SetFilePostName", [filePostName]);
};
// Public: setUseQueryString changes the use_query_string setting
SWFUpload.prototype.setUseQueryString = function (useQueryString) {
this.settings.use_query_string = useQueryString;
this.callFlash("SetUseQueryString", [useQueryString]);
};
// Public: setRequeueOnError changes the requeue_on_error setting
SWFUpload.prototype.setRequeueOnError = function (requeueOnError) {
this.settings.requeue_on_error = requeueOnError;
this.callFlash("SetRequeueOnError", [requeueOnError]);
};
// Public: setHTTPSuccess changes the http_success setting
SWFUpload.prototype.setHTTPSuccess = function (http_status_codes) {
if (typeof http_status_codes === "string") {
http_status_codes = http_status_codes.replace(" ", "").split(",");
}
this.settings.http_success = http_status_codes;
this.callFlash("SetHTTPSuccess", [http_status_codes]);
};
// Public: setDebugEnabled changes the debug_enabled setting
SWFUpload.prototype.setDebugEnabled = function (debugEnabled) {
this.settings.debug_enabled = debugEnabled;
this.callFlash("SetDebugEnabled", [debugEnabled]);
};
// Public: setButtonImageURL loads a button image sprite
SWFUpload.prototype.setButtonImageURL = function (buttonImageURL) {
if (buttonImageURL == undefined) {
buttonImageURL = "";
}
this.settings.button_image_url = buttonImageURL;
this.callFlash("SetButtonImageURL", [buttonImageURL]);
};
// Public: setButtonDimensions resizes the Flash Movie and button
SWFUpload.prototype.setButtonDimensions = function (width, height) {
this.settings.button_width = width;
this.settings.button_height = height;
var movie = this.getMovieElement();
if (movie != undefined) {
movie.style.width = width + "px";
movie.style.height = height + "px";
}
this.callFlash("SetButtonDimensions", [width, height]);
};
// Public: setButtonText Changes the text overlaid on the button
SWFUpload.prototype.setButtonText = function (html) {
this.settings.button_text = html;
this.callFlash("SetButtonText", [html]);
};
// Public: setButtonTextPadding changes the top and left padding of the text overlay
SWFUpload.prototype.setButtonTextPadding = function (left, top) {
this.settings.button_text_top_padding = top;
this.settings.button_text_left_padding = left;
this.callFlash("SetButtonTextPadding", [left, top]);
};
// Public: setButtonTextStyle changes the CSS used to style the HTML/Text overlaid on the button
SWFUpload.prototype.setButtonTextStyle = function (css) {
this.settings.button_text_style = css;
this.callFlash("SetButtonTextStyle", [css]);
};
// Public: setButtonDisabled disables/enables the button
SWFUpload.prototype.setButtonDisabled = function (isDisabled) {
this.settings.button_disabled = isDisabled;
this.callFlash("SetButtonDisabled", [isDisabled]);
};
// Public: setButtonAction sets the action that occurs when the button is clicked
SWFUpload.prototype.setButtonAction = function (buttonAction) {
this.settings.button_action = buttonAction;
this.callFlash("SetButtonAction", [buttonAction]);
};
// Public: setButtonCursor changes the mouse cursor displayed when hovering over the button
SWFUpload.prototype.setButtonCursor = function (cursor) {
this.settings.button_cursor = cursor;
this.callFlash("SetButtonCursor", [cursor]);
};
/* *******************************
Flash Event Interfaces
These functions are used by Flash to trigger the various
events.
All these functions a Private.
Because the ExternalInterface library is buggy the event calls
are added to a queue and the queue then executed by a setTimeout.
This ensures that events are executed in a determinate order and that
the ExternalInterface bugs are avoided.
******************************* */
SWFUpload.prototype.queueEvent = function (handlerName, argumentArray) {
// Warning: Don't call this.debug inside here or you'll create an infinite loop
if (argumentArray == undefined) {
argumentArray = [];
} else if (!(argumentArray instanceof Array)) {
argumentArray = [argumentArray];
}
var self = this;
if (typeof this.settings[handlerName] === "function") {
// Queue the event
this.eventQueue.push(function () {
this.settings[handlerName].apply(this, argumentArray);
});
// Execute the next queued event
setTimeout(function () {
self.executeNextEvent();
}, 0);
} else if (this.settings[handlerName] !== null) {
throw "Event handler " + handlerName + " is unknown or is not a function";
}
};
// Private: Causes the next event in the queue to be executed. Since events are queued using a setTimeout
// we must queue them in order to garentee that they are executed in order.
SWFUpload.prototype.executeNextEvent = function () {
// Warning: Don't call this.debug inside here or you'll create an infinite loop
var f = this.eventQueue ? this.eventQueue.shift() : null;
if (typeof(f) === "function") {
f.apply(this);
}
};
// Private: unescapeFileParams is part of a workaround for a flash bug where objects passed through ExternalInterface cannot have
// properties that contain characters that are not valid for JavaScript identifiers. To work around this
// the Flash Component escapes the parameter names and we must unescape again before passing them along.
SWFUpload.prototype.unescapeFilePostParams = function (file) {
var reg = /[$]([0-9a-f]{4})/i;
var unescapedPost = {};
var uk;
if (file != undefined) {
for (var k in file.post) {
if (file.post.hasOwnProperty(k)) {
uk = k;
var match;
while ((match = reg.exec(uk)) !== null) {
uk = uk.replace(match[0], String.fromCharCode(parseInt("0x" + match[1], 16)));
}
unescapedPost[uk] = file.post[k];
}
}
file.post = unescapedPost;
}
return file;
};
SWFUpload.prototype.flashReady = function () {
// Check that the movie element is loaded correctly with its ExternalInterface methods defined
var movieElement = this.getMovieElement();
if (typeof movieElement.StartUpload !== "function") {
throw "ExternalInterface methods failed to initialize.";
}
// Fix IE Flash/Form bug
if (window[this.movieName] == undefined) {
window[this.movieName] = movieElement;
}
this.queueEvent("swfupload_loaded_handler");
};
/* This is a chance to do something before the browse window opens */
SWFUpload.prototype.fileDialogStart = function () {
this.queueEvent("file_dialog_start_handler");
};
/* Called when a file is successfully added to the queue. */
SWFUpload.prototype.fileQueued = function (file) {
file = this.unescapeFilePostParams(file);
this.queueEvent("file_queued_handler", file);
};
/* Handle errors that occur when an attempt to queue a file fails. */
SWFUpload.prototype.fileQueueError = function (file, errorCode, message) {
file = this.unescapeFilePostParams(file);
this.queueEvent("file_queue_error_handler", [file, errorCode, message]);
};
/* Called after the file dialog has closed and the selected files have been queued.
You could call startUpload here if you want the queued files to begin uploading immediately. */
SWFUpload.prototype.fileDialogComplete = function (numFilesSelected, numFilesQueued) {
this.queueEvent("file_dialog_complete_handler", [numFilesSelected, numFilesQueued]);
};
SWFUpload.prototype.uploadStart = function (file) {
file = this.unescapeFilePostParams(file);
this.queueEvent("return_upload_start_handler", file);
};
SWFUpload.prototype.returnUploadStart = function (file) {
var returnValue;
if (typeof this.settings.upload_start_handler === "function") {
file = this.unescapeFilePostParams(file);
returnValue = this.settings.upload_start_handler.call(this, file);
} else if (this.settings.upload_start_handler != undefined) {
throw "upload_start_handler must be a function";
}
// Convert undefined to true so if nothing is returned from the upload_start_handler it is
// interpretted as 'true'.
if (returnValue === undefined) {
returnValue = true;
}
returnValue = !!returnValue;
this.callFlash("ReturnUploadStart", [returnValue]);
};
SWFUpload.prototype.uploadProgress = function (file, bytesComplete, bytesTotal) {
file = this.unescapeFilePostParams(file);
this.queueEvent("upload_progress_handler", [file, bytesComplete, bytesTotal]);
};
SWFUpload.prototype.uploadError = function (file, errorCode, message) {
file = this.unescapeFilePostParams(file);
this.queueEvent("upload_error_handler", [file, errorCode, message]);
};
SWFUpload.prototype.uploadSuccess = function (file, serverData) {
file = this.unescapeFilePostParams(file);
this.queueEvent("upload_success_handler", [file, serverData]);
};
SWFUpload.prototype.uploadComplete = function (file) {
file = this.unescapeFilePostParams(file);
this.queueEvent("upload_complete_handler", file);
};
/* Called by SWFUpload JavaScript and Flash functions when debug is enabled. By default it writes messages to the
internal debug console. You can override this event and have messages written where you want. */
SWFUpload.prototype.debug = function (message) {
this.queueEvent("debug_handler", message);
};
/* **********************************
Debug Console
The debug console is a self contained, in page location
for debug message to be sent. The Debug Console adds
itself to the body if necessary.
The console is automatically scrolled as messages appear.
If you are using your own debug handler or when you deploy to production and
have debug disabled you can remove these functions to reduce the file size
and complexity.
********************************** */
// Private: debugMessage is the default debug_handler. If you want to print debug messages
// call the debug() function. When overriding the function your own function should
// check to see if the debug setting is true before outputting debug information.
SWFUpload.prototype.debugMessage = function (message) {
if (this.settings.debug) {
var exceptionMessage, exceptionValues = [];
// Check for an exception object and print it nicely
if (typeof message === "object" && typeof message.name === "string" && typeof message.message === "string") {
for (var key in message) {
if (message.hasOwnProperty(key)) {
exceptionValues.push(key + ": " + message[key]);
}
}
exceptionMessage = exceptionValues.join("\n") || "";
exceptionValues = exceptionMessage.split("\n");
exceptionMessage = "EXCEPTION: " + exceptionValues.join("\nEXCEPTION: ");
SWFUpload.Console.writeLine(exceptionMessage);
} else {
SWFUpload.Console.writeLine(message);
}
}
};
SWFUpload.Console = {};
SWFUpload.Console.writeLine = function (message) {
var console, documentForm;
try {
console = document.getElementById("SWFUpload_Console");
if (!console) {
documentForm = document.createElement("form");
document.getElementsByTagName("body")[0].appendChild(documentForm);
console = document.createElement("textarea");
console.id = "SWFUpload_Console";
console.style.fontFamily = "monospace";
console.setAttribute("wrap", "off");
console.wrap = "off";
console.style.overflow = "auto";
console.style.width = "700px";
console.style.height = "350px";
console.style.margin = "5px";
documentForm.appendChild(console);
}
console.value += message + "\n";
console.scrollTop = console.scrollHeight - console.clientHeight;
} catch (ex) {
alert("Exception: " + ex.name + " Message: " + ex.message);
}
};
File diff suppressed because one or more lines are too long
@@ -0,0 +1,116 @@
<?php
function find_filepath ($filename, $directory, $root, &$found) {
if (is_dir($directory)) {
$Directory = @dir($directory);
if ($Directory) {
while (( $file = $Directory->read() ) !== false) {
if (substr($file,0,1) == "." || substr($file,0,1) == "_") continue; // Ignore .dot files and _directories
if (is_dir($directory.DIRECTORY_SEPARATOR.$file) && $directory == $root) // Scan one deep more than root
find_filepath($filename,$directory.DIRECTORY_SEPARATOR.$file,$root, $found); // but avoid recursive scans
elseif ($file == $filename)
$found[] = substr($directory,strlen($root)).DIRECTORY_SEPARATOR.$file; // Add the file to the found list
}
return true;
}
}
return false;
}
$root = $_SERVER['DOCUMENT_ROOT'];
$found = array();
find_filepath('wp-load.php',$root,$root,$found);
if (empty($found[0])) exit();
require_once($root.$found[0]);
require_once(ABSPATH.'/wp-admin/admin.php');
if(!current_user_can('edit_posts')) die;
do_action('admin_init');
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>{#Shopp.title}</title>
<script language="javascript" type="text/javascript" src="<?php echo $Shopp->siteurl; ?>/wp-includes/js/tinymce/tiny_mce_popup.js"></script>
<script language="javascript" type="text/javascript" src="<?php echo $Shopp->siteurl; ?>/wp-includes/js/tinymce/utils/mctabs.js"></script>
<script language="javascript" type="text/javascript" src="<?php echo $Shopp->siteurl; ?>/wp-includes/js/tinymce/utils/form_utils.js"></script>
<script language="javascript" type="text/javascript" src="<?php echo $Shopp->siteurl; ?>/wp-includes/js/tinymce/utils/form_utils.js"></script>
<script language="javascript" type="text/javascript" src="<?php echo $Shopp->siteurl; ?>/wp-includes/js/jquery/jquery.js"></script>
<script language="javascript" type="text/javascript">
var _self = tinyMCEPopup;
function init () {
changeCategory();
}
function insertTag () {
var tag = '[category id="'+jQuery('#category-menu').val()+'"]';
var productid = jQuery('#product-menu').val();
if (productid != 0) tag = '[product id="'+productid+'"]';
if(window.tinyMCE) {
window.tinyMCE.execInstanceCommand('content', 'mceInsertContent', false, tag);
tinyMCEPopup.editor.execCommand('mceRepaint');
tinyMCEPopup.close();
}
}
function closePopup () {
tinyMCEPopup.close();
}
function changeCategory () {
var menu = jQuery('#category-menu');
var products = jQuery('#product-menu');
jQuery.get("<?php echo $Shopp->siteurl; ?>?shopp_lookup=category-products-menu",{category:menu.val()},function (results) {
products.empty().html(results);
},'string');
}
</script>
<style type="text/css">
table th { vertical-align: top; }
.panel_wrapper { border-top: 1px solid #909B9C; }
.panel_wrapper div.current { height:auto !important; }
#product-menu { width: 180px; }
</style>
</head>
<body onload="init()">
<div id="wpwrap">
<form onsubmit="insertTag();return false;" action="#">
<div class="panel_wrapper">
<table border="0" cellpadding="4" cellspacing="0">
<tr>
<th nowrap="nowrap"><label for="category-menu"><?php _e("Category", 'Shopp'); ?></label></th>
<td><select id="category-menu" name="category" onchange="changeCategory()"><?php echo $Shopp->Flow->category_menu(); ?></select></td>
</tr>
<tr id="product-selector">
<th nowrap="nowrap"><label for="product-menu"><?php _e("Product", 'Shopp'); ?></label></th>
<td><select id="product-menu" name="product" size="7"></select></td>
</tr>
</table>
</div>
<div class="mceActionPanel">
<div style="float: left">
<input type="button" id="cancel" name="cancel" value="{#cancel}" onclick="closePopup()"/>
</div>
<div style="float: right">
<input type="button" id="insert" name="insert" value="{#insert}" onclick="insertTag()" />
</div>
</div>
</form>
</div>
<script type="text/javascript">
</script>
</body>
</html>
@@ -0,0 +1,65 @@
/**
* Shopp TinyMCE Plugin
* @author Jonathan Davis
* @copyright Copyright © 2008, Ingenesis Limited, All rights reserved.
*/
(function() {
// Load plugin specific language pack
tinymce.PluginManager.requireLangPack('Shopp');
tinymce.create('tinymce.plugins.Shopp', {
/**
* Initializes the plugin, this will be executed after the plugin has been created.
* This call is done before the editor instance has finished it's initialization so use the onInit event
* of the editor instance to intercept that event.
*
* @param {tinymce.Editor} ed Editor instance that the plugin is initialized in.
* @param {string} url Absolute URL to where the plugin is located.
*/
init : function(ed, url) {
// Register the command so that it can be invoked by using tinyMCE.activeEditor.execCommand('mceExample');
ed.addCommand('mceShopp', function() {
ed.windowManager.open({
file : url + '/dialog.php',
width : 320,
height : 200,
inline : 1
}, {
plugin_url : url // Plugin absolute URL
});
});
// Register example button
ed.addButton('Shopp', {
title : 'Shopp.desc',
cmd : 'mceShopp',
image : url + '/shopp.png'
});
// Add a node change handler, selects the button in the UI when a image is selected
ed.onNodeChange.add(function(ed, cm, n) {
cm.setActive('Shopp', n.nodeName == 'IMG');
});
},
/**
* Returns information about the plugin as a name/value array.
* The current keys are longname, author, authorurl, infourl and version.
*
* @return {Object} Name/value array containing information about the plugin.
*/
getInfo : function() {
return {
longname : 'Shopp TinyMCE Plugin',
author : 'Jonathan Davis',
authorurl : 'http://insites.ingenesis.net',
infourl : 'http://shopplugin.net',
version : "1.0"
};
}
});
// Register plugin
tinymce.PluginManager.add('Shopp', tinymce.plugins.Shopp);
})();
@@ -0,0 +1,4 @@
tinyMCE.addI18n('en.Shopp',{
title : 'Insert a Shopp Product/Category',
desc : 'Insert a Shopp Product/Category'
});
Binary file not shown.

After

Width:  |  Height:  |  Size: 891 B

@@ -0,0 +1,111 @@
<div class="wrap shopp">
<h2><?php _e('Categories','Shopp'); ?></h2>
<?php if (!empty($Shopp->Flow->Notice)): ?><div id="message" class="updated fade"><p><?php echo $Shopp->Flow->Notice; ?></p></div><?php endif; ?>
<form action="" id="categories" method="get">
<div>
<input type="hidden" name="page" value="<?php echo $this->Admin->categories; ?>" />
</div>
<p id="post-search" class="search-box">
<input type="text" id="categories-search-input" class="search-input" name="s" value="<?php echo attribute_escape(stripslashes($s)); ?>" />
<input type="submit" value="<?php _e('Search Categories','Shopp'); ?>" class="button" />
</p>
<p><a href="<?php echo esc_url(add_query_arg(array_merge(stripslashes_deep($_GET),array('page'=>$this->Admin->editcategory,'id'=>'new')),$Shopp->wpadminurl."admin.php")); ?>" class="button"><?php _e('New Category','Shopp'); ?></a></p>
<div class="tablenav">
<?php if ($page_links) echo "<div class='tablenav-pages'>$page_links</div>"; ?>
<div class="alignleft actions"><button type="submit" id="delete-button" name="deleting" value="category" class="button-secondary"><?php _e('Delete','Shopp'); ?></button></div>
<div class="clear"></div>
</div>
<?php if (SHOPP_WP27): ?><div class="clear"></div>
<?php else: ?><br class="clear" /><?php endif; ?>
<table class="widefat" cellspacing="0">
<thead>
<tr><?php shopp_print_column_headers('shopp_page_shopp-categories'); ?></tr>
</thead>
<?php if (SHOPP_WP27): ?>
<tfoot>
<tr><?php shopp_print_column_headers('shopp_page_shopp-categories',false); ?></tr>
</tfoot>
<?php endif; ?>
<?php if (sizeof($Categories) > 0): ?>
<tbody id="categories-table" class="list categories">
<?php
$hidden = array();
if (SHOPP_WP27) $hidden = get_hidden_columns('shopp_page_shopp-categories');
$even = false;
foreach ($Categories as $Category):
$editurl = esc_url(attribute_escape(add_query_arg(array_merge(stripslashes_deep($_GET),
array('page'=>$this->Admin->editcategory,
'id'=>$Category->id)),
$Shopp->wpadminurl."admin.php")));
$CategoryName = empty($Category->name)?'('.__('no category name','Shopp').')':$Category->name;
?>
<tr<?php if (!$even) echo " class='alternate'"; $even = !$even; ?>>
<th scope='row' class='check-column'><input type='checkbox' name='delete[]' value='<?php echo $Category->id; ?>' /></th>
<td width="33%"><a class='row-title' href='<?php echo $editurl; ?>' title='<?php _e('Edit','Shopp'); ?> &quot;<?php echo $CategoryName; ?>&quot;'><?php echo str_repeat("&#8212; ",$Category->depth); echo $CategoryName; ?></a>
<div class="row-actions">
<span class='edit'><a href="<?php echo $editurl; ?>" title="<?php _e('Edit','Shopp'); ?> &quot;<?php echo $CategoryName; ?>&quot;"><?php _e('Edit','Shopp'); ?></a> | </span>
<span class='delete'><a class='submitdelete' title='<?php _e('Delete','Shopp'); ?> &quot;<?php echo $CategoryName; ?>&quot;' href='' rel="<?php echo $Category->id; ?>"><?php _e('Delete','Shopp'); ?></a> | </span>
<span class='view'><a href="<?php echo (SHOPP_PERMALINKS)?$Shopp->shopuri."category/$Category->uri":add_query_arg('shopp_category',$Category->id,$Shopp->shopuri); ?>" title="<?php _e('View','Shopp'); ?> &quot;<?php echo $CategoryName; ?>&quot;" rel="permalink" target="_blank"><?php _e('View','Shopp'); ?></a></span>
</div>
</td>
<td width="30%" class="description column-description<?php echo in_array('description',$hidden)?' hidden':''; ?>"><?php echo $Category->description; ?>&nbsp;</td>
<td class="num links column-links<?php echo in_array('links',$hidden)?' hidden':''; ?>"><?php echo $Category->total; ?></td>
<td width="5%" class="templates column-templates<?php echo ($Category->spectemplate == "on")?' spectemplates':''; echo in_array('templates',$hidden)?' hidden':''; ?>">&nbsp;</td>
<td width="5%" class="menus column-menus<?php echo ($Category->facetedmenus == "on")?' facetedmenus':''; echo in_array('menus',$hidden)?' hidden':''; ?>">&nbsp;</td>
</tr>
<?php endforeach; ?>
</tbody>
<?php else: ?>
<tbody><tr><td colspan="6"><?php _e('No categories found.','Shopp'); ?></td></tr></tbody>
<?php endif; ?>
</table>
</form>
<div class="tablenav">
<?php if ($page_links) echo "<div class='tablenav-pages'>$page_links</div>"; ?>
<div class="clear"></div>
</div>
</div>
<script type="text/javascript">
helpurl = "<?php echo SHOPP_DOCS; ?>Categories";
jQuery(document).ready( function() {
var $ = jQuery.noConflict();
$('#selectall').change( function() {
$('#categories-table th input').each( function () {
if (this.checked) this.checked = false;
else this.checked = true;
});
});
$('a.submitdelete').click(function () {
if (confirm("<?php _e('You are about to delete this category!\n \'Cancel\' to stop, \'OK\' to delete.','Shopp'); ?>")) {
$('<input type="hidden" name="delete[]" />').val($(this).attr('rel')).appendTo('#categories');
$('<input type="hidden" name="deleting" />').val('category').appendTo('#categories');
$('#categories').submit();
return false;
} else return false;
});
$('#delete-button').click(function() {
if (confirm("<?php echo addslashes(__('Are you sure you want to delete the selected categories?','Shopp')); ?>")) {
$('<input type="hidden" name="categories" value="list" />').appendTo($('#categories'));
return true;
} else return false;
});
<?php if (SHOPP_WP27): ?>
pagenow = 'shopp_page_shopp-categories';
columns.init(pagenow);
<?php endif; ?>
});
</script>
@@ -0,0 +1,452 @@
<?php if (SHOPP_WP27): ?>
<div class="wrap shopp">
<?php if (!empty($Shopp->Flow->Notice)): ?><div id="message" class="updated fade"><p><?php echo $Shopp->Flow->Notice; ?></p></div><?php endif; ?>
<h2><?php _e('Category Editor','Shopp'); ?></h2>
<div id="ajax-response"></div>
<form name="category" id="category" action="<?php echo $Shopp->wpadminurl; ?>admin.php" method="post">
<?php wp_nonce_field('shopp-save-category'); ?>
<div id="poststuff" class="metabox-holder has-right-sidebar">
<div id="side-info-column" class="inner-sidebar">
<?php
do_action('submitpage_box');
$side_meta_boxes = do_meta_boxes('admin_page_shopp-categories-edit', 'side', $Category);
?>
</div>
<div id="post-body" class="<?php echo $side_meta_boxes ? 'has-sidebar' : 'has-sidebar'; ?>">
<div id="post-body-content" class="has-sidebar-content">
<div id="titlediv">
<div id="titlewrap">
<input name="name" id="title" type="text" value="<?php echo attribute_escape($Category->name); ?>" size="30" tabindex="1" autocomplete="off" />
</div>
<div class="inside">
<?php if (SHOPP_PERMALINKS && !empty($Category->id)): ?>
<div id="edit-slug-box"><strong><?php _e('Permalink','Shopp'); ?>:</strong>
<span id="sample-permalink"><?php echo $permalink; ?><span id="editable-slug" title="<?php _e('Click to edit this part of the permalink','Shopp'); ?>"><?php echo attribute_escape($Category->slug); ?></span><span id="editable-slug-full"><?php echo attribute_escape($Category->slug); ?></span>/</span>
<span id="edit-slug-buttons"><button type="button" class="edit-slug button">Edit</button></span>
</div>
<?php endif; ?>
</div>
</div>
<div id="<?php echo user_can_richedit() ? 'postdivrich' : 'postdiv'; ?>" class="postarea">
<?php the_editor($Category->description,'content','Description', false); ?>
<?php wp_nonce_field( 'closedpostboxes', 'closedpostboxesnonce', false ); ?>
</div>
<?php
do_meta_boxes('admin_page_shopp-categories-edit', 'normal', $Category);
do_meta_boxes('admin_page_shopp-categories-edit', 'advanced', $Category);
?>
</div>
</div>
</div> <!-- #poststuff -->
</form>
</div>
<?php else: ?>
<div class="wrap shopp">
<h2><?php _e('Category Editor','Shopp'); ?></h2>
<?php if (!empty($Shopp->Flow->Notice)): ?><div id="message" class="updated fade"><p><?php echo $Shopp->Flow->Notice; ?></p></div><?php endif; ?>
<br class="clear" />
<?php $action = (!empty($Category->id))?$Category->id:'new'; ?>
<form name="category" id="category" method="post" action="<?php echo $Shopp->wpadminurl; ?>admin.php">
<?php wp_nonce_field('shopp-save-category'); ?>
<table class="form-table">
<tr class="form-required">
<th scope="row" valign="top"><label for="category_name"><?php _e('Category Name','Shopp'); ?></label></th>
<td><input type="text" name="name" value="<?php echo attribute_escape($Category->name); ?>" id="category_name" size="40" /><br />
<?php if (SHOPP_PERMALINKS && !empty($Category->id)): ?>
<div id="edit-slug-box"><strong><?php _e('Permalink','Shopp')?>:</strong>
<span id="sample-permalink"><?php echo $permalink; ?><span id="editable-slug" title="Click to edit this part of the permalink"><?php echo attribute_escape($Category->slug); ?></span><span id="editable-slug-full"><?php echo attribute_escape($Category->slug); ?></span>/</span>
<span id="edit-slug-buttons"><button type="button" class="edit-slug button">Edit</button></span>
</div>
<?php endif; ?>
</td>
</tr>
<tr class="form-required">
<th scope="row" valign="top"><label for="category_parent"><?php _e('Category Parent','Shopp'); ?></label></th>
<td><select name="parent" id="category_parent"><?php echo $categories_menu; ?></select><br />
<?php _e('Categories, unlike tags, can be or have nested sub-categories.','Shopp'); ?></td>
</tr>
<tr class="form-required">
<th scope="row" valign="top"><label for="category_description"><?php _e('Description','Shopp'); ?></label></th>
<td><textarea name="description" id="category_description" rows="5" cols="50" style="width: 97%;"><?php echo $Category->description; ?></textarea><br />
<?php _e('The description is not prominent by default, however some themes may show it.','Shopp'); ?></td>
</tr>
<tr id="category-images" class="form-required">
<th scope="row" valign="top"><label><?php _e('Category Images','Shopp'); ?></label>
<input type="hidden" name="category" value="<?php echo $_GET['id']; ?>" id="image-category-id" />
<input type="hidden" name="deleteImages" id="deleteImages" value="" />
<div id="swf-uploader-button"></div>
<div id="swf-uploader">
<button type="button" class="button-secondary" name="add-image" id="add-image" tabindex="10"><small><?php _e('Add New Image','Shopp'); ?></small></button></div>
<div id="browser-uploader">
<button type="button" name="image_upload" id="image-upload" class="button-secondary"><small><?php _e('Add New Image','Shopp'); ?></small></button><br class="clear"/>
</div>
</th>
<td>
<ul id="lightbox">
<?php foreach ($Images as $i => $thumbnail): $thumbnail->properties = unserialize($thumbnail->properties); ?>
<li id="image-<?php echo $thumbnail->src; ?>"><input type="hidden" name="images[]" value="<?php echo $thumbnail->src; ?>" />
<div id="image-<?php echo $thumbnail->src; ?>-details">
<img src="?shopp_image=<?php echo $thumbnail->id; ?>" width="96" height="96" />
<div class="details">
<input type="hidden" name="imagedetails[<?php echo $i; ?>][id]" value="<?php echo $thumbnail->id; ?>" />
<p><label>Title: </label><input type="text" name="imagedetails[<?php echo $i; ?>][title]" value="<?php echo $thumbnail->properties['title']; ?>" /></p>
<p><label>Alt: </label><input type="text" name="imagedetails[<?php echo $i; ?>][alt]" value="<?php echo $thumbnail->properties['alt']; ?>" /></p>
<p class="submit"><input type="button" name="close" value="Close" class="button close" /></p>
</div>
</div>
<button type="button" name="deleteImage" value="<?php echo $thumbnail->src; ?>" title="Delete category image&hellip;" class="deleteButton"><img src="<?php echo SHOPP_PLUGINURI; ?>/core/ui/icons/delete.png" alt="-" width="16" height="16" /></button></li>
<?php endforeach; ?>
</ul>
<div class="clear"></div>
<?php _e('The first image will be the default image. These thumbnails are out of proportion, but will be correctly sized for shoppers.','Shopp'); ?>
</td>
</tr>
<tr>
<th scope="row" valign="top"><label for="published"><?php _e('Settings','Shopp'); ?></label></th>
<td><p><input type="hidden" name="spectemplate" value="off" /><input type="checkbox" name="spectemplate" value="on" id="spectemplates-setting" tabindex="11" <?php if ($Category->spectemplate == "on") echo ' checked="checked"'?> /><label for="spectemplates-setting"> <?php _e('Product Details Template &mdash; Predefined details for products created in this category ','Shopp'); ?></label></p>
<p id="facetedmenus-setting"><input type="hidden" name="facetedmenus" value="off" /><input type="checkbox" name="facetedmenus" value="on" id="faceted-setting" tabindex="12" <?php if ($Category->facetedmenus == "on") echo ' checked="checked"'?> /><label for="faceted-setting"> <?php _e('Faceted Menus &mdash; Build drill-down filter menus based on the details template of this category','Shopp'); ?></label></p>
<p><input type="hidden" name="variations" value="off" /><input type="checkbox" name="variations" value="on" id="variations-setting" tabindex="13"<?php if ($Category->variations == "on") echo ' checked="checked"'?> /><label for="variations-setting"> <?php _e('Variations &mdash; Predefined selectable product options for products created in this category','Shopp'); ?></label></p>
</td>
</tr>
</table>
<div id="templates">
<h3><?php _e('Product Template Settings','Shopp'); ?></h3>
<p><?php _e('Setup template values that will be copied into new products that are created and assigned this category.','Shopp'); ?></p>
<table class="form-table pricing">
<tbody>
<tr id="price-ranges">
<th><label><?php _e('Price Range Search','Shopp'); ?></label></th>
<td>
<?php _e('Configure how you want price range options in this category to appear.','Shopp'); ?><br />
<select name="pricerange" id="pricerange-facetedmenu">
<?php echo menuoptions($pricerange_menu,$Category->pricerange,true); ?>
</select>
<ul class="details multipane">
<li><div id="pricerange-menu" class="multiple-select options"><ul class=""></ul></div>
<div class="controls">
<button type="button" id="addPriceLevel" class="button-secondary"><img src="<?php echo SHOPP_PLUGINURI; ?>/core/ui/icons/add.png" alt="-" width="16" height="16" /><small> <?php _e('Add Price Range','Shopp'); ?></small></button>
</div>
</li>
</ul>
<div class="clear"></div>
</td>
</tr>
<tr id="details-template">
<th><label><?php _e('Product Details','Shopp'); ?></label></th>
<td>
<?php _e('Create a set of predefined details for products created in this category.','Shopp'); ?>
<ul class="details multipane">
<li><input type="hidden" name="deletedSpecs" id="deletedSpecs" value="" />
<div id="details-menu" class="multiple-select options">
<ul></ul>
</div>
<div class="controls">
<button type="button" id="addDetail" class="button-secondary"><img src="<?php echo SHOPP_PLUGINURI; ?>/core/ui/icons/add.png" alt="+" width="16" height="16" /><small> <?php _e('Add Detail','Shopp'); ?></small></button>
</div>
</li>
<li id="details-facetedmenu">
<div id="details-list" class="multiple-select options">
<ul></ul>
</div>
<div class="controls">
<button type="button" id="addDetailOption" class="button-secondary"><img src="<?php echo SHOPP_PLUGINURI; ?>/core/ui/icons/add.png" alt="+" width="16" height="16" /><small> <?php _e('Add Option','Shopp'); ?></small></button>
</div>
</li>
</ul>
<div class="clear"></div>
</td>
</tr>
<tr id="variations-template">
<th><?php _e('Variation Options','Shopp'); ?></th>
<td>
<?php _e('Create a predefined set of variation options for products in this category.','Shopp'); ?><br />
<ul class="multipane">
<li><div id="variations-menu" class="multiple-select options menu"><ul></ul></div>
<div class="controls">
<button type="button" id="addVariationMenu" class="button-secondary"><img src="<?php echo SHOPP_PLUGINURI; ?>/core/ui/icons/add.png" alt="+" width="16" height="16" /><small> <?php _e('Add Option Menu','Shopp'); ?></small></button>
</div>
</li>
<li>
<div id="variations-list" class="multiple-select options"></div>
<div class="controls">
<button type="button" id="addVariationOption" class="button-secondary"><img src="<?php echo SHOPP_PLUGINURI; ?>/core/ui/icons/add.png" alt="+" width="16" height="16" /><small> <?php _e('Add Option','Shopp'); ?></small></button>
</div>
</li>
</ul>
</td>
</tr>
</tbody>
<tbody id="variations-pricing"></tbody>
</table>
</div>
<p class="submit"><input type="submit" class="button" name="save" value="<?php _e('Save Category','Shopp'); ?>" /> <select name="settings[workflow]" id="workflow">
<?php echo menuoptions($workflows,$Shopp->Settings->get('workflow'),true); ?>
</select></p>
</form>
</div>
<?php endif; ?>
<script type="text/javascript">
helpurl = "<?php echo SHOPP_DOCS; ?>Editing_a_Category";
var flashuploader = <?php echo ($uploader == 'flash' && !(false !== strpos(strtolower($_SERVER['HTTP_USER_AGENT']), 'mac') && apache_mod_loaded('mod_security')))?'true':'false'; ?>;
var wp26 = <?php global $wp_version; echo (version_compare($wp_version,"2.6.9","<"))?'true':'false'; ?>;
var category = <?php echo (!empty($Category->id))?$Category->id:'false'; ?>;
var details = <?php echo json_encode($Category->specs) ?>;
var priceranges = <?php echo json_encode($Category->priceranges) ?>;
var options = <?php echo json_encode($Category->options) ?>;
var prices = <?php echo json_encode($Category->prices) ?>;
var rsrcdir = '<?php echo SHOPP_PLUGINURI; ?>';
var siteurl = '<?php echo $Shopp->siteurl; ?>';
var adminurl = '<?php echo $Shopp->wpadminurl; ?>';
var ajaxurl = adminurl+'admin-ajax.php';
var addcategory_url = '<?php echo wp_nonce_url($Shopp->wpadminurl."admin-ajax.php", "shopp-ajax_add_category"); ?>';
var editslug_url = '<?php echo wp_nonce_url($Shopp->wpadminurl."admin-ajax.php", "shopp-ajax_edit_slug"); ?>';
var fileverify_url = '<?php echo wp_nonce_url($Shopp->wpadminurl."admin-ajax.php", "shopp-ajax_verify_file"); ?>';
var manager_page = '<?php echo $this->Admin->categories; ?>';
var editor_page = '<?php echo $this->Admin->editcategory; ?>';
var request = <?php echo json_encode(stripslashes_deep($_GET)); ?>;
var workflow = {'continue':editor_page, 'close':manager_page, 'new':editor_page, 'next':editor_page, 'previous':editor_page};
var worklist = <?php echo json_encode($this->categories_list(true)); ?>;
var filesizeLimit = <?php echo wp_max_upload_size(); ?>;
var priceTypes = <?php echo json_encode($priceTypes) ?>;
var weightUnit = '<?php echo $this->Settings->get('weight_unit'); ?>';
var storage = '<?php echo $this->Settings->get('product_storage'); ?>';
var productspath = '<?php echo addslashes(trailingslashit($this->Settings->get('products_path'))); ?>';
// Warning/Error Dialogs
var DELETE_IMAGE_WARNING = "<?php _e('Are you sure you want to delete this category image?','Shopp'); ?>";
var SERVER_COMM_ERROR = "<?php _e('There was an error communicating with the server.','Shopp'); ?>";
// Translatable dynamic interface labels
var NEW_DETAIL_DEFAULT = "<?php _e('Detail Name','Shopp'); ?>";
var NEW_OPTION_DEFAULT = "<?php _e('New Option','Shopp'); ?>";
var FACETED_DISABLED = "<?php _e('Faceted menu disabled','Shopp'); ?>";
var FACETED_AUTO = "<?php _e('Build faceted menu automatically','Shopp'); ?>";
var FACETED_RANGES = "<?php _e('Build as custom number ranges','Shopp'); ?>";
var FACETED_CUSTOM = "<?php _e('Build from preset options','Shopp'); ?>";
var ADD_IMAGE_BUTTON_TEXT = "<?php _e('Add New Image','Shopp'); ?>";
var SAVE_BUTTON_TEXT = "<?php _e('Save','Shopp'); ?>";
var CANCEL_BUTTON_TEXT = "<?php _e('Cancel','Shopp'); ?>";
var OPTION_MENU_DEFAULT = "<?php _e('Option Menu','Shopp'); ?>";
var NEW_OPTION_DEFAULT = "<?php _e('New Option','Shopp'); ?>";
var UPLOAD_FILE_BUTTON_TEXT = "<?php _e('Upload&nbsp;File','Shopp'); ?>";
var TYPE_LABEL = "<?php _e('Type','Shopp'); ?>";
var PRICE_LABEL = "<?php _e('Price','Shopp'); ?>";
var AMOUNT_LABEL = "<?php _e('Amount','Shopp'); ?>";
var SALE_PRICE_LABEL = "<?php _e('Sale Price','Shopp'); ?>";
var NOT_ON_SALE_TEXT = "<?php _e('Not on Sale','Shopp'); ?>";
var NOTAX_LABEL = "<?php _e('Not Taxed','Shopp'); ?>";
var SHIPPING_LABEL = "<?php _e('Shipping','Shopp'); ?>";
var FREE_SHIPPING_TEXT = "<?php _e('Free Shipping','Shopp'); ?>";
var WEIGHT_LABEL = "<?php _e('Weight','Shopp'); ?>";
var SHIPFEE_LABEL = "<?php _e('Handling Fee','Shopp'); ?>";
var INVENTORY_LABEL = "<?php _e('Inventory','Shopp'); ?>";
var NOT_TRACKED_TEXT = "<?php _e('Not Tracked','Shopp'); ?>";
var IN_STOCK_LABEL = "<?php _e('In Stock','Shopp'); ?>";
var SKU_LABEL = "<?php _e('SKU','Shopp'); ?>";
var SKU_LABEL_HELP = "<?php _e('Stock Keeping Unit','Shopp'); ?>";
var DONATIONS_VAR_LABEL = "<?php _e('Accept variable amounts','Shopp'); ?>";
var DONATIONS_MIN_LABEL = "<?php _e('Amount required as minimum','Shopp'); ?>";
var PRODUCT_DOWNLOAD_LABEL = "<?php _e('Product Download','Shopp'); ?>";
var NO_PRODUCT_DOWNLOAD_TEXT = "<?php _e('No product download.','Shopp'); ?>";
var NO_DOWNLOAD = "<?php _e('No download file.','Shopp'); ?>";
var DEFAULT_PRICELINE_LABEL = "<?php _e('Price & Delivery','Shopp'); ?>";
var FILE_NOT_FOUND_TEXT = "<?php _e('The file you specified could not be found.','Shopp'); ?>";
var FILE_NOT_READ_TEXT = "<?php _e('The file you specified is not readable and cannot be used.','Shopp'); ?>";
var FILE_ISDIR_TEXT = "<?php _e('The file you specified is a directory and cannot be used.','Shopp'); ?>";
var productOptions = new Array();
var optionMenus = new Array();
var pricingOptions = new Object();
var linkedPricing = false;
var detailsidx = 1;
var variationsidx = 1;
var optionsidx = 1;
var pricingidx = 1;
var pricelevelsidx = 1;
var fileUploader = false;
var changes = false;
var saving = false;
var flashUploader = false;
var pricesPayload = false;
jQuery(document).ready(function () {
var $=jQuery.noConflict();
var editslug = new SlugEditor(category,'category');
var imageUploads = new ImageUploads({"category" : $('#image-category-id').val()});
updateWorkflow();
$('#category').submit(function () {
this.action = this.action+"?"+$.param(request);
return true;
});
$('#templates, #details-template, #details-facetedmenu, #variations-template, #variations-pricing, #price-ranges, #facetedmenus-setting').hide();
$('#spectemplates-setting').change(function () {
if (this.checked) $('#templates, #details-template, #facetedmenus-setting').show();
else $('#details-template, #facetedmenus-setting').hide();
if (!$('#spectemplates-setting').attr('checked') && !$('#variations-setting').attr('checked'))
$('#templates').hide();
}).change();
$('#faceted-setting').change(function () {
if (this.checked) {
$('#details-menu').removeClass('options').addClass('menu');
$('#details-facetedmenu, #price-ranges').show();
} else {
$('#details-menu').removeClass('menu').addClass('options');
$('#details-facetedmenu, #price-ranges').hide();
}
}).change();
$('#variations-setting').change(function () {
if (this.checked) $('#templates, #variations-template, #variations-pricing').show();
else $('#variations-template, #variations-pricing').hide();
if (!$('#spectemplates-setting').attr('checked') && !$('#variations-setting').attr('checked'))
$('#templates').hide();
}).change();
if (details) for (s in details) addDetail(details[s]);
$('#addPriceLevel').click(function() { addPriceLevel(); });
$('#addDetail').click(function() { addDetail(); });
$('#addVariationMenu').click(function() { addVariationOptionsMenu(); });
$('#pricerange-facetedmenu').change(function () {
if ($(this).val() == "custom") $('#pricerange-menu, #addPriceLevel').show();
else $('#pricerange-menu, #addPriceLevel').hide();
}).change();
if (priceranges) for (key in priceranges) addPriceLevel(priceranges[key]);
if (options) loadVariations(options,prices);
if (!category) $('#title').focus();
function addPriceLevel (data) {
var menus = $('#pricerange-menu');
var id = pricelevelsidx++;
var menu = new NestedMenu(id,menus,'priceranges','',data,false,
{'axis':'y','scroll':false});
$(menu.label).change(function (){ this.value = asMoney(this.value); }).change();
}
if (!wp26) {
postboxes.add_postbox_toggles('admin_page_shopp-categories-edit');
// close postboxes that should be closed
jQuery('.if-js-closed').removeClass('if-js-closed').addClass('closed');
}
function addDetail (data) {
var menus = $('#details-menu');
var entries = $('#details-list');
var addOptionButton = $('#addDetailOption');
var id = detailsidx;
var menu = new NestedMenu(
id,menus,
'specs',
NEW_DETAIL_DEFAULT,
data,
{target:entries,type:'list'}
);
menu.items = new Array();
menu.addOption = function (data) {
var option = new NestedMenuOption(menu.index,menu.itemsElement,menu.dataname,NEW_OPTION_DEFAULT,data,true);
menu.items.push(option);
}
var facetedSetting = $('<li class="setting"></li>').appendTo(menu.itemsElement);
var facetedMenu = $('<select name="specs['+menu.index+'][facetedmenu]"></select>').appendTo(facetedSetting);
$('<option value="disabled">'+FACETED_DISABLED+'</option>').appendTo(facetedMenu);
$('<option value="auto">'+FACETED_AUTO+'</option>').appendTo(facetedMenu);
$('<option value="ranges">'+FACETED_RANGES+'</option>').appendTo(facetedMenu);
$('<option value="custom">'+FACETED_CUSTOM+'</option>').appendTo(facetedMenu);
if (data && data.facetedmenu) facetedMenu.val(data.facetedmenu);
facetedMenu.change(function () {
if ($(this).val() == "disabled" || $(this).val() == "auto") {
$(addOptionButton).hide();
$(menu.itemsElement).find('li.option').hide();
} else {
$(addOptionButton).show();
$(menu.itemsElement).find('li.option').show();
}
}).change();
// Load up existing options
if (data && data.options) {
for (var i in data.options) menu.addOption(data.options[i]);
}
$(menu.itemsElement).sortable({'axis':'y','items':'li.option','scroll':false});
menu.element.unbind('click',menu.click);
menu.element.click(function () {
menu.selected();
$(addOptionButton).unbind('click').click(menu.addOption);
$(facetedMenu).change();
});
detailsidx++;
}
function updateWorkflow () {
$('#workflow').change(function () {
setting = $(this).val();
request.page = workflow[setting];
request.id = category;
if (!request.id) request.id = "new";
if (setting == "new") request.next = setting;
// Find previous category
if (setting == "previous") {
$.each(worklist,function (i,entry) {
if (entry.id == category) {
if (worklist[i-1]) request.next = worklist[i-1].id;
else request.page = workflow['close'];
return true;
}
});
}
// Find next category
if (setting == "next") {
$.each(worklist,function (i,entry) {
if (entry.id == category) {
if (worklist[i+1]) request.next = worklist[i+1].id;
else request.page = workflow['close'];
return true;
}
});
}
}).change();
}
});
</script>
@@ -0,0 +1,173 @@
<?php
function save_meta_box ($Category) {
global $Shopp;
$workflows = array(
"continue" => __('Continue Editing','Shopp'),
"close" => __('Category Manager','Shopp'),
"new" => __('New Category','Shopp'),
"next" => __('Edit Next','Shopp'),
"previous" => __('Edit Previous','Shopp')
);
?>
<div id="major-publishing-actions">
<select name="settings[workflow]" id="workflow">
<?php echo menuoptions($workflows,$Shopp->Settings->get('workflow'),true); ?>
</select>
<input type="submit" class="button-primary" name="save" value="<?php _e('Save Category','Shopp'); ?>" />
</div>
<?php
}
add_meta_box('save-category', __('Save','Shopp'), 'save_meta_box', 'admin_page_shopp-categories-edit', 'side', 'core');
function settings_meta_box ($Category) {
global $Shopp;
$categories_menu = $Shopp->Flow->category_menu($Category->parent,$Category->id);
$categories_menu = '<option value="0" rel="-1,-1">'.__('Parent Category','Shopp').'&hellip;</option>'.$categories_menu;
?>
<p><select name="parent" id="category_parent"><?php echo $categories_menu; ?></select><br />
<?php _e('Categories, unlike tags, can be or have nested sub-categories.','Shopp'); ?></p>
<p><input type="hidden" name="spectemplate" value="off" /><input type="checkbox" name="spectemplate" value="on" id="spectemplates-setting" tabindex="11" <?php if ($Category->spectemplate == "on") echo ' checked="checked"'?> /><label for="spectemplates-setting"> <?php _e('Product Details Template','Shopp'); ?></label><br /><?php _e('Predefined details for products created in this category','Shopp'); ?></p>
<p id="facetedmenus-setting"><input type="hidden" name="facetedmenus" value="off" /><input type="checkbox" name="facetedmenus" value="on" id="faceted-setting" tabindex="12" <?php if ($Category->facetedmenus == "on") echo ' checked="checked"'?> /><label for="faceted-setting"> <?php _e('Faceted Menus','Shopp'); ?></label><br /><?php _e('Build drill-down filter menus based on the details template of this category','Shopp'); ?></p>
<p><input type="hidden" name="variations" value="off" /><input type="checkbox" name="variations" value="on" id="variations-setting" tabindex="13"<?php if ($Category->variations == "on") echo ' checked="checked"'?> /><label for="variations-setting"> <?php _e('Variations','Shopp'); ?></label><br /><?php _e('Predefined selectable product options for products created in this category','Shopp'); ?></p>
<?php
}
add_meta_box('category-settings', __('Settings','Shopp'), 'settings_meta_box', 'admin_page_shopp-categories-edit', 'side', 'core');
function images_meta_box ($Category) {
$db =& DB::get();
$Images = array();
if (!empty($Category->id)) {
$asset_table = DatabaseObject::tablename(Asset::$table);
$Images = $db->query("SELECT id,src,properties FROM $asset_table WHERE context='category' AND parent=$Category->id AND datatype='thumbnail' ORDER BY sortorder",AS_ARRAY);
}
?>
<ul id="lightbox">
<?php foreach ($Images as $i => $thumbnail): $thumbnail->properties = unserialize($thumbnail->properties); ?>
<li id="image-<?php echo $thumbnail->src; ?>"><input type="hidden" name="images[]" value="<?php echo $thumbnail->src; ?>" />
<div id="image-<?php echo $thumbnail->src; ?>-details">
<img src="?shopp_image=<?php echo $thumbnail->id; ?>" width="96" height="96" />
<div class="details">
<input type="hidden" name="imagedetails[<?php echo $i; ?>][id]" value="<?php echo $thumbnail->id; ?>" />
<p><label>Title: </label><input type="text" name="imagedetails[<?php echo $i; ?>][title]" value="<?php echo $thumbnail->properties['title']; ?>" /></p>
<p><label>Alt: </label><input type="text" name="imagedetails[<?php echo $i; ?>][alt]" value="<?php echo $thumbnail->properties['alt']; ?>" /></p>
<p class="submit"><input type="button" name="close" value="Close" class="button close" /></p>
</div>
</div>
<button type="button" name="deleteImage" value="<?php echo $thumbnail->src; ?>" title="Delete category image&hellip;" class="deleteButton"><img src="<?php echo SHOPP_PLUGINURI; ?>/core/ui/icons/delete.png" alt="-" width="16" height="16" /></button></li>
<?php endforeach; ?>
</ul>
<div class="clear"></div>
<input type="hidden" name="category" value="<?php echo $_GET['id']; ?>" id="image-category-id" />
<input type="hidden" name="deleteImages" id="deleteImages" value="" />
<div id="swf-uploader-button"></div>
<div id="swf-uploader">
<button type="button" class="button-secondary" name="add-image" id="add-image" tabindex="10"><small><?php _e('Add New Image','Shopp'); ?></small></button></div>
<div id="browser-uploader">
<button type="button" name="image_upload" id="image-upload" class="button-secondary"><small><?php _e('Add New Image','Shopp'); ?></small></button><br class="clear"/>
</div>
<p><?php _e('The first image will be the default image. These thumbnails are out of proportion, but will be correctly sized for shoppers.','Shopp'); ?></p>
<?php
}
add_meta_box('product-images', __('Category Images','Shopp'), 'images_meta_box', 'admin_page_shopp-categories-edit', 'normal', 'core');
function templates_meta_box ($Category) {
$pricerange_menu = array(
"disabled" => __('Price ranges disabled','Shopp'),
"auto" => __('Build price ranges automatically','Shopp'),
"custom" => __('Use custom price ranges','Shopp'),
);
?>
<p><?php _e('Setup template values that will be copied into new products that are created and assigned this category.','Shopp'); ?></p>
<div id="templates"></div>
<div id="details-template" class="panel">
<div class="pricing-label">
<label><?php _e('Product Details','Shopp'); ?></label>
</div>
<div class="pricing-ui">
<ul class="details multipane">
<li><input type="hidden" name="deletedSpecs" id="deletedSpecs" value="" />
<div id="details-menu" class="multiple-select options">
<ul></ul>
</div>
<div class="controls">
<button type="button" id="addDetail" class="button-secondary"><img src="<?php echo SHOPP_PLUGINURI; ?>/core/ui/icons/add.png" alt="+" width="16" height="16" /><small> <?php _e('Add Detail','Shopp'); ?></small></button>
</div>
</li>
<li id="details-facetedmenu">
<div id="details-list" class="multiple-select options">
<ul></ul>
</div>
<div class="controls">
<button type="button" id="addDetailOption" class="button-secondary"><img src="<?php echo SHOPP_PLUGINURI; ?>/core/ui/icons/add.png" alt="+" width="16" height="16" /><small> <?php _e('Add Option','Shopp'); ?></small></button>
</div>
</li>
</ul>
<div class="clear"></div>
</div>
<div id="price-ranges" class="panel">
<div class="pricing-label">
<label><?php _e('Price Range Search','Shopp'); ?></label>
</div>
<div class="pricing-ui">
<select name="pricerange" id="pricerange-facetedmenu">
<?php echo menuoptions($pricerange_menu,$Category->pricerange,true); ?>
</select>
<ul class="details multipane">
<li><div id="pricerange-menu" class="multiple-select options"><ul class=""></ul></div>
<div class="controls">
<button type="button" id="addPriceLevel" class="button-secondary"><img src="<?php echo SHOPP_PLUGINURI; ?>/core/ui/icons/add.png" alt="-" width="16" height="16" /><small> <?php _e('Add Price Range','Shopp'); ?></small></button>
</div>
</li>
</ul>
</div>
<div class="clear"></div>
<div id="pricerange"></div>
<p><?php _e('Configure how you want price range options in this category to appear.','Shopp'); ?></p>
</div>
</div>
<div id="variations-template">
<div id="variations-menus" class="panel">
<div class="pricing-label">
<label><?php _e('Variation Option Menus','Shopp'); ?></label>
</div>
<div class="pricing-ui">
<p><?php _e('Create a predefined set of variation options for products in this category.','Shopp'); ?></p>
<ul class="multipane">
<li><div id="variations-menu" class="multiple-select options menu"><ul></ul></div>
<div class="controls">
<button type="button" id="addVariationMenu" class="button-secondary"><img src="<?php echo SHOPP_PLUGINURI; ?>/core/ui/icons/add.png" alt="+" width="16" height="16" /><small> <?php _e('Add Option Menu','Shopp'); ?></small></button>
</div>
</li>
<li>
<div id="variations-list" class="multiple-select options"></div>
<div class="controls">
<button type="button" id="addVariationOption" class="button-secondary"><img src="<?php echo SHOPP_PLUGINURI; ?>/core/ui/icons/add.png" alt="+" width="16" height="16" /><small> <?php _e('Add Option','Shopp'); ?></small></button>
</div>
</li>
</ul>
<div class="clear"></div>
</div>
</div>
<br />
<div id="variations-pricing"></div>
</div>
<?php
}
add_meta_box('templates_menus', __('Product Templates &amp; Menus','Shopp'), 'templates_meta_box', 'admin_page_shopp-categories-edit', 'advanced', 'core');
do_action('do_meta_boxes', 'admin_page_shopp-categories-edit', 'normal', $Shopp->Category);
do_action('do_meta_boxes', 'admin_page_shopp-categories-edit', 'advanced', $Shopp->Category);
do_action('do_meta_boxes', 'admin_page_shopp-categories-edit', 'side', $Shopp->Category);
?>
@@ -0,0 +1,297 @@
<div class="wrap shopp">
<h2><?php _e('Customers','Shopp'); ?></h2>
<form action="<?php echo esc_url($_SERVER['REQUEST_URI']); ?>" id="orders" method="get">
<div>
<input type="hidden" name="page" value="<?php echo $page; ?>" />
<input type="hidden" name="status" value="<?php echo $status; ?>" />
</div>
<br class="clear" />
<p id="post-search" class="search-box">
<input type="text" id="customers-search-input" class="search-input" name="s" value="<?php echo attribute_escape($s); ?>" />
<input type="submit" value="<?php _e('Search','Shopp'); ?>" class="button" />
</p>
<div class="tablenav">
<div class="alignleft actions">
<button type="submit" id="delete-button" name="deleting" value="customer" class="button-secondary"><?php _e('Delete','Shopp'); ?></button>
<span class="filtering">
<select name="range" id="range">
<?php echo menuoptions($ranges,$range,true); ?>
</select>
<span id="dates">
<div id="start-position" class="calendar-wrap"><input type="text" id="start" name="start" value="<?php echo $startdate; ?>" size="10" class="search-input selectall" /></div>
<small><?php _e('to','Shopp'); ?></small>
<div id="end-position" class="calendar-wrap"><input type="text" id="end" name="end" value="<?php echo $enddate; ?>" size="10" class="search-input selectall" /></div>
</span>
<button type="submit" id="filter-button" name="filter" value="customers" class="button-secondary"><?php _e('Filter','Shopp'); ?></button>
</span>
</div>
<?php if ($page_links) echo "<div class='tablenav-pages'>$page_links</div>"; ?>
<div class="clear"></div>
</div>
<?php if (SHOPP_WP27): ?><div class="clear"></div>
<?php else: ?><br class="clear" /><?php endif; ?>
<table class="widefat" cellspacing="0">
<thead>
<tr><?php shopp_print_column_headers('shopp_page_shopp-customers'); ?></tr>
</thead>
<?php if (SHOPP_WP27): ?>
<tfoot>
<tr><?php shopp_print_column_headers('shopp_page_shopp-customers',false); ?></tr>
</tfoot>
<?php endif; ?>
<?php if (sizeof($Customers) > 0): ?>
<tbody id="customers-table" class="list orders">
<?php
if (SHOPP_WP27) $hidden = get_hidden_columns('shopp_page_shopp-customers');
else $hidden = array();
$even = false;
foreach ($Customers as $Customer):
$CustomerName = (empty($Customer->firstname) && empty($Customer->lastname))?'('.__('no contact name','Shopp').')':"{$Customer->firstname} {$Customer->lastname}";
?>
<tr<?php if (!$even) echo " class='alternate'"; $even = !$even; ?>>
<th scope='row' class='check-column'><input type='checkbox' name='selected[]' value='<?php echo $Customer->id; ?>' /></th>
<td class="name column-name"><a class='row-title' href='<?php echo add_query_arg(array('page'=>$this->Admin->editcustomer,'id'=>$Customer->id),$Shopp->wpadminurl."admin.php"); ?>' title='<?php _e('Edit','Shopp'); ?> &quot;<?php echo $CustomerName; ?>&quot;'><?php echo $CustomerName; ?></a><?php echo !empty($Customer->company)?"<br />$Customer->company":""; ?></td>
<td class="login column-login<?php echo in_array('login',$hidden)?' hidden':''; ?>"><?php echo $Customer->user_login; ?></td>
<td class="email column-email<?php echo in_array('email',$hidden)?' hidden':''; ?>"><a href="mailto:<?php echo $Customer->email; ?>"><?php echo $Customer->email; ?></a></td>
<td class="location column-location<?php echo in_array('location',$hidden)?' hidden':''; ?>"><?php
$location = '';
$location = $Customer->city;
if (!empty($location) && !empty($Customer->state)) $location .= ', ';
$location .= $Customer->state;
if (!empty($location) && !empty($Customer->country))
$location .= ' &mdash; ';
$location .= $Customer->country;
echo $location;
?></td>
<td class="total column-total<?php echo in_array('total',$hidden)?' hidden':''; ?>"><?php echo $Customer->orders; ?> &mdash; <?php echo money($Customer->total); ?></td>
<td class="date column-date<?php echo in_array('date',$hidden)?' hidden':''; ?>"><?php echo date("Y/m/d",mktimestamp($Customer->created)); ?></td>
</tr>
<?php endforeach; ?>
</tbody>
<?php else: ?>
<tbody><tr><td colspan="6"><?php _e('No','Shopp'); ?> <?php _e('customers, yet.','Shopp'); ?></td></tr></tbody>
<?php endif; ?>
</table>
</form>
<div class="tablenav">
<div class="alignleft actions">
<form action="<?php echo esc_url(add_query_arg(array_merge($_GET,array('lookup'=>'customerexport')),$Shopp->wpadminurl."admin.php")); ?>" id="log" method="post">
<button type="button" id="export-settings-button" name="export-settings" class="button-secondary"><?php _e('Export Options','Shopp'); ?></button>
<span id="export-settings" class="hidden">
<div id="export-columns" class="multiple-select">
<ul>
<li<?php $even = true; if ($even) echo ' class="odd"'; $even = !$even; ?>><input type="checkbox" name="selectall_columns" id="selectall_columns" /><label for="selectall_columns"><strong><?php _e('Select All','Shopp'); ?></strong></label></li>
<li<?php if ($even) echo ' class="odd"'; $even = !$even; ?>><input type="hidden" name="settings[customerexport_headers]" value="off" /><input type="checkbox" name="settings[customerexport_headers]" id="purchaselog_headers" value="on" /><label for="purchaselog_headers"><strong><?php _e('Include column headings','Shopp'); ?></strong></label></li>
<?php $even = true; foreach ($columns as $name => $label): ?>
<li<?php if ($even) echo ' class="odd"'; $even = !$even; ?>><input type="checkbox" name="settings[customerexport_columns][]" value="<?php echo $name; ?>" id="column-<?php echo $name; ?>" <?php echo in_array($name,$selected)?' checked="checked"':''; ?> /><label for="column-<?php echo $name; ?>" ><?php echo $label; ?></label></li>
<?php endforeach; ?>
</ul>
</div><br />
<select name="settings[customerexport_format]">
<?php echo menuoptions($exports,$formatPref,true); ?>
</select></span>
<button type="submit" id="download-button" name="download" value="export" class="button-secondary"><?php _e('Download','Shopp'); ?></button>
</div>
<?php if ($page_links) echo "<div class='tablenav-pages'>$page_links</div>"; ?>
<div class="clear"></div>
</div>
</div>
<div id="start-calendar" class="calendar"></div>
<div id="end-calendar" class="calendar"></div>
<script type="text/javascript">
helpurl = "<?php echo SHOPP_DOCS; ?>Managing Orders";
var lastexport = new Date(<?php echo date("Y,(n-1),j",$Shopp->Settings->get('customerexport_lastexport')); ?>);
jQuery(document).ready( function() {
var $=jQuery.noConflict();
$('#selectall').change( function() {
$('#customers-table th input').each( function () {
if (this.checked) this.checked = false;
else this.checked = true;
});
});
$('#delete-button').click(function() {
if (confirm("<?php echo addslashes(__('Are you sure you want to delete the selected customers?','Shopp')); ?>")) return true;
else return false;
});
function getDateInput(input) {
var match = false;
match = $(input).get(0).value.match(/^(\d{1,2}).{1}(\d{1,2}).{1}(\d{4})/);
if (match) return new Date(match[3],(match[1]-1),match[2]);
return false;
}
function formatDate (e) {
if (this.value == "") match = false;
if (this.value.match(/^(\d{6,8})/))
match = this.value.match(/(\d{1,2}?)(\d{1,2})(\d{4,4})$/);
else if (this.value.match(/^(\d{1,2}.{1}\d{1,2}.{1}\d{4})/))
match = this.value.match(/^(\d{1,2}).{1}(\d{1,2}).{1}(\d{4})/);
if (match) this.setDate(new Date(match[3],(match[1]-1),match[2]));
$('#start-calendar, #end-calendar').hide();
}
function setDate(date,calendar) {
$(this).val((date.getMonth()+1)+"/"+date.getDate()+"/"+date.getFullYear());
if (calendar) {
calendar.render(date.getMonth()+1,date.getDate(),date.getFullYear());
calendar.selection = date;
calendar.autoselect();
}
}
var start = $('#start');
var startdate = getDateInput(start);
var StartCalendar = new PopupCalendar($('#start-calendar'));
StartCalendar.scheduling = false;
if (startdate) {
StartCalendar.render(startdate.getMonth()+1,startdate.getDate(),startdate.getFullYear());
StartCalendar.selection = startdate;
StartCalendar.autoselect();
} else StartCalendar.render();
start.setDate = setDate;
start.get(0).setDate = setDate;
start.calendar = StartCalendar;
start.change(formatDate);
var end = $('#end');
var enddate = getDateInput(end);
var EndCalendar = new PopupCalendar($('#end-calendar'));
EndCalendar.scheduling = false;
if (enddate) {
EndCalendar.render(enddate.getMonth()+1,enddate.getDate(),enddate.getFullYear());
EndCalendar.selection = enddate;
EndCalendar.autoselect();
} else EndCalendar.render();
end.setDate = setDate;
end.get(0).setDate = setDate;
end.calendar = EndCalendar;
end.change(formatDate);
var scpos = $('#start-position').offset();
$('#start-calendar').hide()
.css({left:scpos.left,
top:scpos.top+$('#start-position').height()+10});
$('#start').click(function (e) {
$('#end-calendar').hide();
$('#start-calendar').toggle();
$(StartCalendar).change(function () {
$('#start').val((StartCalendar.selection.getMonth()+1)+"/"+
StartCalendar.selection.getDate()+"/"+
StartCalendar.selection.getFullYear());
});
});
var ecpos = $('#end-position').offset();
$('#end-calendar').hide()
.css({left:ecpos.left,
top:ecpos.top+$('#end-position input').height()+10});
$('#end').click(function (e) {
$('#start-calendar').hide();
$('#end-calendar').toggle();
$(EndCalendar).change(function () {
$('#end').val((EndCalendar.selection.getMonth()+1)+"/"+
EndCalendar.selection.getDate()+"/"+
EndCalendar.selection.getFullYear());
});
});
$('#range').change(function () {
if (this.selectedIndex == 0) {
start.val(''); end.val('');
$('#dates').addClass('hidden');
return;
} else $('#dates').removeClass('hidden');
var today = new Date();
var startdate = getDateInput($('#start'));
var enddate = getDateInput($('#end'));
if (!startdate) startdate = new Date(today.getFullYear(),today.getMonth(),today.getDate());
if (!enddate) enddate = new Date(today.getFullYear(),today.getMonth(),today.getDate());
today = new Date(today.getFullYear(),today.getMonth(),today.getDate());
switch($(this).val()) {
case 'week':
startdate.setDate(today.getDate()-today.getDay());
enddate = new Date(startdate.getFullYear(),startdate.getMonth(),startdate.getDate()+6);
break;
case 'month':
startdate.setDate(1);
enddate = new Date(startdate.getFullYear(),startdate.getMonth()+1,0);
break;
case 'quarter':
quarter = Math.floor(today.getMonth()/3);
startdate = new Date(today.getFullYear(),today.getMonth()-(today.getMonth()%3),1);
enddate = new Date(today.getFullYear(),startdate.getMonth()+3,0);
break;
case 'year':
startdate = new Date(today.getFullYear(),0,1);
enddate = new Date(today.getFullYear()+1,0,0);
break;
case 'yesterday':
startdate.setDate(today.getDate()-1);
enddate.setDate(today.getDate()-1);
break;
case 'lastweek':
startdate.setDate(today.getDate()-today.getDay()-7);
enddate.setDate((today.getDate()-today.getDay()+6)-7);
break;
case 'last30':
startdate.setDate(today.getDate()-30);
enddate.setDate(today.getDate());
break;
case 'last90':
startdate.setDate(today.getDate()-90);
enddate.setDate(today.getDate());
break;
case 'lastmonth':
startdate = new Date(today.getFullYear(),today.getMonth()-1,1);
enddate = new Date(today.getFullYear(),today.getMonth(),0);
break;
case 'lastquarter':
startdate = new Date(today.getFullYear(),(today.getMonth()-(today.getMonth()%3))-3,1);
enddate = new Date(today.getFullYear(),startdate.getMonth()+3,0);
break;
case 'lastyear':
startdate = new Date(today.getFullYear()-1,0,1);
enddate = new Date(today.getFullYear(),0,0);
break;
case 'lastexport':
startdate = lastexport;
enddate = today;
break;
case 'custom': break;
}
start.setDate(startdate,StartCalendar); end.setDate(enddate,EndCalendar);
}).change();
$('#export-settings-button').click(function () { $('#export-settings-button').hide(); $('#export-settings').removeClass('hidden'); });
$('#selectall_columns').change(function () {
if ($(this).attr('checked')) $('#export-columns input').not(this).attr('checked',true);
else $('#export-columns input').not(this).attr('checked',false);
});
<?php if (SHOPP_WP27): ?>
pagenow = 'shopp_page_shopp-customers';
columns.init(pagenow);
<?php endif; ?>
});
</script>
@@ -0,0 +1,283 @@
<?php if (SHOPP_WP27): ?>
<div class="wrap shopp">
<?php if (!empty($Shopp->Flow->Notice)): ?><div id="message" class="updated fade"><p><?php echo $Shopp->Flow->Notice; ?></p></div><?php endif; ?>
<h2><?php _e('Customer Editor','Shopp'); ?></h2>
<div id="ajax-response"></div>
<form name="customer" id="customer" action="<?php echo add_query_arg('page',$this->Admin->customers,$Shopp->wpadminurl."admin.php"); ?>" method="post">
<?php wp_nonce_field('shopp-save-customer'); ?>
<div class="hidden"><input type="hidden" name="id" value="<?php echo $Customer->id; ?>" /></div>
<div id="poststuff" class="metabox-holder has-right-sidebar">
<div id="side-info-column" class="inner-sidebar">
<?php
do_action('submitpage_box');
$side_meta_boxes = do_meta_boxes('admin_page_shopp-customers-edit', 'side', $Customer);
?>
</div>
<div id="post-body" class="<?php echo $side_meta_boxes ? 'has-sidebar' : 'has-sidebar'; ?>">
<div id="post-body-content" class="has-sidebar-content">
<?php
do_meta_boxes('admin_page_shopp-customers-edit', 'normal', $Customer);
do_meta_boxes('admin_page_shopp-customers-edit', 'advanced', $Customer);
wp_nonce_field( 'closedpostboxes', 'closedpostboxesnonce', false );
?>
</div>
</div>
</div> <!-- #poststuff -->
</form>
</div>
<?php else: ?>
<div class="wrap shopp">
<h2><?php _e('Customer Editor','Shopp'); ?></h2>
<form name="customer" id="customer" method="post" action="<?php echo add_query_arg('page',$Shopp->Flow->Admin->customers,$Shopp->wpadminurl."admin.php"); ?>">
<?php wp_nonce_field('shopp-save-customer'); ?>
<div class="hidden"><input type="hidden" name="id" value="<?php echo $Customer->id; ?>" /></div>
<table class="form-table">
<tr class="form-required">
<th scope="row" valign="top"><label for="name"><?php _e('Name','Shopp'); ?></label></th>
<td>
<div>
<span><input type="text" name="firstname" value="<?php echo attribute_escape($Customer->firstname); ?>" id="firstname" size="14" /><br />
<label for="firstname"><?php _e('First Name','Shopp'); ?></label></span>
<span><input type="text" name="lastname" value="<?php echo attribute_escape($Customer->lastname); ?>" id="lastname" size="30" /><br />
<label for="lastname"><?php _e('Last Name','Shopp'); ?></label></span><br class="clear" />
</div>
<p><input type="text" name="company" value="<?php echo attribute_escape($Customer->company); ?>" id="company" size="46" /><br />
<label for="lastname"><?php _e('Company','Shopp'); ?></label></p>
</td>
</tr>
<tr class="form-required">
<th scope="row" valign="top"><label for="email"><?php _e('Contact','Shopp'); ?></label></th>
<td>
<div>
<span><input type="text" name="email" value="<?php echo attribute_escape($Customer->email); ?>" id="email" size="24" /><br />
<label for="email"><?php _e('Email','Shopp'); ?> <em><?php _e('(required)')?></em></label></span>
<span><input type="text" name="phone" value="<?php echo attribute_escape($Customer->phone); ?>" id="phone" size="20" /><br />
<label for="phone"><?php _e('Phone','Shopp'); ?></label></span>
</div>
</td>
</tr>
<tr class="form-required">
<th scope="row" valign="top"><label for="email"><?php _e('Password','Shopp'); ?></label></th>
<td>
<div>
<span><input type="password" name="new-password" id="new-password" value="" size="20" class="selectall" /><br />
<label for="new-password"><?php _e('Enter a new password to change it.','Shopp'); ?></label></span>
<span><input type="password" name="confirm-password" id="confirm-password" value="" size="20" class="selectall" /><br />
<label for="confirm-password"><?php _e('Confirm the new password.','Shopp'); ?></label></span>
</div>
<br class="clear" />
<div id="pass-strength-result"><?php _e('Strength indicator'); ?></div>
<br class="clear" />
</td>
</tr>
<tr class="form-required">
<th scope="row" valign="top"><label for="billing-address"><?php _e('Billing Address','Shopp'); ?></label></th>
<td>
<div>
<input type="text" name="billing[address]" id="billing-address" value="<?php echo $Customer->Billing->address; ?>" size="46" /><br />
<input type="text" name="billing[xaddress]" id="billing-xaddress" value="<?php echo $Customer->Billing->xaddress; ?>" size="46" /><br />
<label for="billing-address"><?php _e('Street Address','Shopp'); ?></label>
</div>
<p>
<span>
<input type="text" name="billing[city]" id="billing-city" value="<?php echo $Customer->Billing->city; ?>" size="14" /><br />
<label for="billing-city"><?php _e('City','Shopp'); ?></label>
</span>
<span id="billing-state-inputs">
<select name="billing[state]" id="billing-state">
<?php echo menuoptions($Customer->billing_states,$Customer->Billing->state,true); ?>
</select>
<input name="billing[state]" id="billing-state-text" value="<?php echo $Customer->Billing->state; ?>" size="12" disabled="disabled" class="hidden" /><br />
<label for="billing-state"><?php _e('State / Province','Shopp'); ?></label>
</span>
<span>
<input type="text" name="billing[postcode]" id="billing-postcode" value="<?php echo $Customer->Billing->postcode; ?>" size="10" /><br />
<label for="billing-postcode"><?php _e('Postal Code','Shopp'); ?></label>
</span>
<br class="clear" />
</p>
<p>
<select name="billing[country]" id="billing-country">
<?php echo menuoptions($Customer->countries,$Customer->Billing->country,true); ?>
</select><br />
<label for="billing-country"><?php _e('Country','Shopp'); ?></label>
</p>
</td>
</tr>
<tr class="form-required">
<th scope="row" valign="top"><label for="shipping-address"><?php _e('Shipping Address','Shopp'); ?></label></th>
<td>
<p>
<input type="text" name="shipping[address]" id="shipping-address" value="<?php echo $Customer->Shipping->address; ?>" size="46" /><br />
<input type="text" name="shipping[xaddress]" id="shipping-xaddress" value="<?php echo $Customer->Shipping->xaddress; ?>" size="46" /><br />
<label for="shipping-address"><?php _e('Street Address','Shopp'); ?></label>
</p>
<p>
<span>
<input type="text" name="shipping[city]" id="shipping-city" value="<?php echo $Customer->Shipping->city; ?>" size="14" /><br />
<label for="shipping-city"><?php _e('City','Shopp'); ?></label>
</span>
<span id="shipping-state-inputs">
<select name="shipping[state]" id="shipping-state">
<?php echo menuoptions($Customer->billing_states,$Customer->Shipping->state,true); ?>
</select>
<input name="shipping[state]" id="shipping-state-text" value="<?php echo $Customer->Shipping->state; ?>" size="12" disabled="disabled" class="hidden" /><br />
<label for="shipping-state"><?php _e('State / Province','Shopp'); ?></label>
</span>
<span>
<input type="text" name="shipping[postcode]" id="shipping-postcode" value="<?php echo $Customer->Shipping->postcode; ?>" size="10" /><br />
<label for="shipping-postcode"><?php _e('Postal Code','Shopp'); ?></label>
</span>
<br class="clear" />
</p>
<p>
<select name="shipping[country]" id="shipping-country">
<?php echo menuoptions($Customer->countries,$Customer->Shipping->country,true); ?>
</select><br />
<label for="shipping-country"><?php _e('Country','Shopp'); ?></label>
</p>
</td>
</tr>
</table>
<p class="submit"><input type="submit" class="button-primary" name="save" value="Save Changes" /></p>
</form>
</div>
<?php endif; ?>
<div id="starts-calendar" class="calendar"></div>
<div id="ends-calendar" class="calendar"></div>
<script type="text/javascript">
helpurl = "<?php echo SHOPP_DOCS; ?>Editing_a_Customer";
var PWD_INDICATOR = "<?php _e('Strength indicator'); ?>";
var PWD_GOOD = "<?php _e('Good'); ?>";
var PWD_BAD = "<?php _e('Bad'); ?>";
var PWD_SHORT = "<?php _e('Short'); ?>";
var PWD_STRONG = "<?php _e('Strong'); ?>";
jQuery(document).ready( function() {
var $=jQuery.noConflict();
var wp26 = <?php echo (SHOPP_WP27)?'false':'true'; ?>;
var regions = <?php echo json_encode($regions); ?>;
if (!wp26) {
postboxes.add_postbox_toggles('admin_page_shopp-customers-edit');
// close postboxes that should be closed
jQuery('.if-js-closed').removeClass('if-js-closed').addClass('closed');
}
$('#username').click(function () {
document.location.href = '/wp-admin/user-edit.php?user_id='+$('#userid').val();
});
updateStates('#billing-country','#billing-state-inputs');
updateStates('#shipping-country','#shipping-state-inputs');
function updateStates (country,state) {
var selector = $(state).find('select');
var text = $(state).find('input');
var label = $(state).find('label');
function toggleStateInputs () {
if ($(selector).children().length > 1) {
$(selector).show().attr('disabled',false);
$(text).hide().attr('disabled',true);
$(label).attr('for',$(selector).attr('id'))
} else {
$(selector).hide().attr('disabled',true);
$(text).show().attr('disabled',false).val('');
$(label).attr('for',$(text).attr('id'))
}
}
$(country).change(function() {
if ($(selector).attr('type') == "text") return true;
$(selector).empty().attr('disabled',true);
$('<option></option>').val('').html('').appendTo(selector);
if (regions[this.value]) {
$.each(regions[this.value], function (value,label) {
option = $('<option></option>').val(value).html(label).appendTo(selector);
});
$(selector).attr('disabled',false);
}
toggleStateInputs();
});
toggleStateInputs();
}
// Included from the WP 2.8 password strength meter
// Copyright by Automattic
$('#new-password').val('').keyup( check_pass_strength );
function check_pass_strength () {
var pass = $('#new-password').val(), user = $('#email').val(), strength;
$('#pass-strength-result').removeClass('short bad good strong');
if ( ! pass ) {
$('#pass-strength-result').html( PWD_INDICATOR );
return;
}
strength = passwordStrength(pass, user);
switch ( strength ) {
case 2:
$('#pass-strength-result').addClass('bad').html( PWD_BAD );
break;
case 3:
$('#pass-strength-result').addClass('good').html( PWD_GOOD );
break;
case 4:
$('#pass-strength-result').addClass('strong').html( PWD_STRONG );
break;
default:
$('#pass-strength-result').addClass('short').html( PWD_SHORT );
}
}
function passwordStrength(password,username) {
var shortPass = 1, badPass = 2, goodPass = 3, strongPass = 4, symbolSize = 0, natLog, score;
//password < 4
if (password.length < 4 ) { return shortPass };
//password == username
if (password.toLowerCase()==username.toLowerCase()) return badPass;
if (password.match(/[0-9]/)) symbolSize +=10;
if (password.match(/[a-z]/)) symbolSize +=26;
if (password.match(/[A-Z]/)) symbolSize +=26;
if (password.match(/[^a-zA-Z0-9]/)) symbolSize +=31;
natLog = Math.log( Math.pow(symbolSize,password.length) );
score = natLog / Math.LN2;
if (score < 40 ) return badPass
if (score < 56 ) return goodPass
return strongPass;
}
});
</script>
@@ -0,0 +1,154 @@
<?php
function save_meta_box () {
?>
<div id="major-publishing-actions">
<input type="submit" class="button-primary" name="save" value="<?php _e('Save Changes','Shopp'); ?>" />
</div>
<?php
}
add_meta_box('save-customer', __('Save','Shopp'), 'save_meta_box', 'admin_page_shopp-customers-edit', 'side', 'core');
function password_meta_box () {
?>
<p>
<input type="password" name="new-password" id="new-password" value="" size="20" class="selectall" /><br />
<label for="new-password"><?php _e('Enter a new password to change it.','Shopp'); ?></label>
</p>
<p>
<input type="password" name="confirm-password" id="confirm-password" value="" size="20" class="selectall" /><br />
<label for="confirm-password"><?php _e('Confirm the new password.','Shopp'); ?></label>
</p>
<br class="clear" />
<div id="pass-strength-result"><?php _e('Strength indicator'); ?></div>
<br class="clear" />
<?php
}
add_meta_box('change-password', __('Change Password','Shopp'), 'password_meta_box', 'admin_page_shopp-customers-edit', 'side', 'core');
function profile_meta_box ($Customer) {
$wp_user = get_userdata($Customer->wpuser);
if (!empty($wp_user)):
?>
<p>
<span>
<input type="hidden" name="userid" id="userid" value="<?php echo $Customer->wpuser; ?>" />
<input type="text" name="username" id="username" value="<?php echo $wp_user->user_login; ?>" size="24" readonly="readonly" class="clickable" /><br />
<label for="username"><?php _e('Login (Click to edit user)','Shopp'); ?></label>
</span>
<?php endif; ?>
<p>
<span>
<input type="text" name="firstname" id="firstname" value="<?php echo $Customer->firstname; ?>" size="14" /><br />
<label for="firstname"><?php _e('First Name','Shopp'); ?></label>
</span>
<span>
<input type="text" name="lastname" id="lastname" value="<?php echo $Customer->lastname; ?>" size="30" /><br />
<label for="lastname"><?php _e('Last Name','Shopp'); ?></label>
</span>
</p>
<p>
<input type="text" name="company" id="company" value="<?php echo $Customer->company; ?>" /><br />
<label for="company"><?php _e('Company','Shopp'); ?></label>
</p>
<p>
<span>
<input type="text" name="email" id="email" value="<?php echo $Customer->email; ?>" size="24" /><br />
<label for="email"><?php _e('Email','Shopp'); ?> <em><?php _e('(required)')?></em></label>
</span>
<span>
<input type="text" name="phone" id="phone" value="<?php echo $Customer->phone; ?>" size="20" /><br />
<label for="phone"><?php _e('Phone','Shopp'); ?></label>
</span>
</p>
<?php if (is_array($Customer->info)):
foreach($Customer->info as $name => $info): ?>
<p>
<input type="text" name="info[<?php echo $name; ?>]" id="info-<?php echo sanitize_title_with_dashes($name); ?>" value="<?php echo $info; ?>" /><br />
<label for="info-<?php echo sanitize_title_with_dashes($name); ?>"><?php echo $name; ?></label>
</p>
<?php endforeach; endif;?>
<br class="clear" />
<?php
}
add_meta_box('customer-profile', __('Profile','Shopp'), 'profile_meta_box', 'admin_page_shopp-customers-edit', 'normal', 'core');
function billing_meta_box ($Customer) {
?>
<p>
<input type="text" name="billing[address]" id="billing-address" value="<?php echo $Customer->Billing->address; ?>" /><br />
<input type="text" name="billing[xaddress]" id="billing-xaddress" value="<?php echo $Customer->Billing->xaddress; ?>" /><br />
<label for="billing-address"><?php _e('Street Address','Shopp'); ?></label>
</p>
<p>
<span>
<input type="text" name="billing[city]" id="billing-city" value="<?php echo $Customer->Billing->city; ?>" size="14" /><br />
<label for="billing-city"><?php _e('City','Shopp'); ?></label>
</span>
<span id="billing-state-inputs">
<select name="billing[state]" id="billing-state">
<?php echo menuoptions($Customer->billing_states,$Customer->Billing->state,true); ?>
</select>
<input name="billing[state]" id="billing-state-text" value="<?php echo $Customer->Billing->state; ?>" size="12" disabled="disabled" class="hidden" />
<label for="billing-state"><?php _e('State / Province','Shopp'); ?></label>
</span>
<span>
<input type="text" name="billing[postcode]" id="billing-postcode" value="<?php echo $Customer->Billing->postcode; ?>" size="10" /><br />
<label for="billing-postcode"><?php _e('Postal Code','Shopp'); ?></label>
</span>
</p>
<p>
<span>
<select name="billing[country]" id="billing-country">
<?php echo menuoptions($Customer->countries,$Customer->Billing->country,true); ?>
</select>
<label for="billing-country"><?php _e('Country','Shopp'); ?></label>
</span>
</p>
<br class="clear" />
<?php
}
add_meta_box('customer-billing', __('Billing Address','Shopp'), 'billing_meta_box', 'admin_page_shopp-customers-edit', 'normal', 'core');
function shipping_meta_box ($Customer) {
?>
<p>
<input type="text" name="shipping[[address]" id="shipping-address" value="<?php echo $Customer->Shipping->address; ?>" /><br />
<input type="text" name="shipping[xaddress]" id="shipping-xaddress" value="<?php echo $Customer->Shipping->xaddress; ?>" /><br />
<label for="shipping-address"><?php _e('Street Address','Shopp'); ?></label>
</p>
<p>
<span>
<input type="text" name="shipping[city]" id="shipping-city" value="<?php echo $Customer->Shipping->city; ?>" size="14" /><br />
<label for="shipping-city"><?php _e('City','Shopp'); ?></label>
</span>
<span id="shipping-state-inputs">
<select name="shipping[state]" id="shipping-state">
<?php echo menuoptions($Customer->billing_states,$Customer->Shipping->state,true); ?>
</select>
<input name="shipping[state]" id="shipping-state-text" value="<?php echo $Customer->Shipping->state; ?>" size="12" disabled="disabled" class="hidden" />
<label for="shipping-state"><?php _e('State / Province','Shopp'); ?></label>
</span>
<span>
<input type="text" name="shipping[postcode]" id="shipping-postcode" value="<?php echo $Customer->Shipping->postcode; ?>" size="10" /><br />
<label for="shipping-postcode"><?php _e('Postal Code','Shopp'); ?></label>
</span>
</p>
<p>
<span>
<select name="shipping[country]" id="shipping-country">
<?php echo menuoptions($Customer->countries,$Customer->Shipping->country,true); ?>
</select>
<label for="shipping-country"><?php _e('Country','Shopp'); ?></label>
</span>
</p>
<br class="clear" />
<?php
}
add_meta_box('customer-shipping', __('Shipping Address','Shopp'), 'shipping_meta_box', 'admin_page_shopp-customers-edit', 'normal', 'core');
?>
@@ -0,0 +1,11 @@
<h5><?php _e('Using Advanced Customer Search','Shopp'); ?></h5>
<table border="0" class="advsearch">
<tr><td><strong><?php _e('Email','Shopp'); ?>:</strong></td><td>help.desk@shopplugin.net</td></tr>
<tr><td><strong><?php _e('Company','Shopp'); ?>:</strong></td><td>company:"Ingenesis Limited"<br />company:automattic</td></tr>
<tr><td><strong><?php _e('Login','Shopp'); ?>:</strong></td><td>login:admin</td></tr>
<tr><td><strong><?php _e('Address (lines 1 or 2)','Shopp'); ?>:</strong></td><td>address:"1 main st"</td></tr>
<tr><td><strong><?php _e('City','Shopp'); ?>:</strong></td><td>city:"san jose"<br />city:columbus</td></tr>
<tr><td><strong><?php _e('State/Province','Shopp'); ?>:</strong></td><td>state:"new york"<br />province:ontario</td></tr>
<tr><td><strong><?php _e('Zip/Postal Codes','Shopp'); ?>:</strong></td><td>zip:95131<br />postcode:M1P1C0</td></tr>
<tr><td><strong><?php _e('Country','Shopp'); ?>:</strong></td><td>country:US</td></tr>
</table>
@@ -0,0 +1,20 @@
<div class="wrap">
<h2><?php _e('Help','Shopp'); ?></h2>
<ul id="help">
<li>
<h3><a href="http://docs.shopplugin.net"><?php _e('Official Documentation','Shopp'); ?></a></h3>
<p><?php _e('The wiki is the best place to get started learning about the Shopp e-commerce platform. As Shopp is in beta, the documentation is sketchy at the moment, but it will become more complete as it nears release.','Shopp'); ?></p>
</li>
<li>
<h3><a href="http://forums.shopplugin.net"><?php _e('Support Forums','Shopp'); ?></a></h3>
<p><?php _e('You can also get help from fellow Shopp owners and developers by posting your questions and problems on the public support forums. To ensure you get quick responses, be sure to completely explain your problem by providing as much information about the problem you can (which may include quoting the code you are using or the exact text of error messages you are receiving).','Shopp'); ?></p>
</li>
<li>
<h3><a href="http://shopplugin.net/support"><?php _e('Premium Support','Shopp'); ?></a></h3>
<p><?php _e('Should you need in-depth assistance setting up or customizing your Shopp install, you may want to purchase premium support credit that will allow you to chat live with the Shopp developer for personal support.','Shopp'); ?></p>
</li>
</ul>
</div>
@@ -0,0 +1,13 @@
<h5><?php _e('Using Advanced Order Search','Shopp'); ?></h5>
<table border="0" class="advsearch">
<tr><td><strong><?php _e('Email','Shopp'); ?>:</strong></td><td>help.desk@shopplugin.net</td></tr>
<tr><td><strong><?php _e('Transaction ID','Shopp'); ?>:</strong></td><td>txn:95M27911DT480180V</td></tr>
<tr><td><strong><?php _e('Gateway','Shopp'); ?>:</strong></td><td>gateway:"paypal express"<br />gateway:firstdata</td></tr>
<tr><td><strong><?php _e('Credit Card Type','Shopp'); ?>:</strong></td><td>cardtype:visa</td></tr>
<tr><td><strong><?php _e('Company','Shopp'); ?>:</strong></td><td>company:"Ingenesis Limited"<br />company:automattic</td></tr>
<tr><td><strong><?php _e('Address (lines 1 or 2)','Shopp'); ?>:</strong></td><td>address:"1 main st"</td></tr>
<tr><td><strong><?php _e('City','Shopp'); ?>:</strong></td><td>city:"san jose"<br />city:columbus</td></tr>
<tr><td><strong><?php _e('State/Province','Shopp'); ?>:</strong></td><td>state:"new york"<br />province:ontario</td></tr>
<tr><td><strong><?php _e('Zip/Postal Codes','Shopp'); ?>:</strong></td><td>zip:95131<br />postcode:M1P1C0</td></tr>
<tr><td><strong><?php _e('Country','Shopp'); ?>:</strong></td><td>country:US</td></tr>
</table>
@@ -0,0 +1,28 @@
<div id="welcome" class="wrap">
<h2><img src="/wp-content/plugins/shopp/core/ui/icons/shopp.png" width="24" height="24"/> <?php _e('Welcome to Shopp','Shopp'); ?></h2>
<h3><?php _e('Congratulations on choosing Shopp and WordPress for your e-commerce solution!','Shopp'); ?></h3>
<p><?php _e('Before you dive in to setup, here are a few things to keep in mind:','Shopp'); ?></p>
<ul>
<li><strong><?php _e('Shopp has lots of easy to find help built-in.','Shopp'); ?></strong><br />
<?php printf(__('Click the %sHelp menu%s to access help articles about the screen you are using, directly from the %sofficial documentation%s.','Shopp'),'<strong>','</strong>','<a href="http://docs.shopplugin.net" target="_blank">','</a>'); ?>
<ul>
<li><?php printf(__('You can also get community help from the %sShopp Forums</a>','Shopp'),'<a href="http://forums.shopplugin.net">','</a>'); ?></li>
<li><?php _e('Or, get live online support by purchasing a support plan','Shopp'); ?></li>
<li><?php _e('Find qualified Shopp professionals you can contract for customization consulting work','Shopp'); ?></li>
</ul>
</li>
<li><strong><?php _e('Easy setup in just a few steps.','Shopp'); ?></strong><br /><?php _e('Setup is simple and takes about 10-15 minutes. Just jump through each of the settings screens to configure your store.','Shopp'); ?></li>
<li><strong><?php _e('Don\'t forget to activate your key!','Shopp'); ?></strong><br /><?php printf(__('Be sure to visit the %sShopp%s &rarr; %sSettings%s &rarr; %sUpdate%s screen and activate your update key so you can get trouble-free, automated updates.','Shopp'),'<strong>','</strong>','<strong>','</strong>','<strong><a href="admin.php?page='.$this->Flow->Admin->settings['update'][0].'">','</a></strong>'); ?></li>
<li><strong><?php _e('Show It Off','Shopp')?></strong><br /><?php printf(__('Once you\'re up and running, drop by the Shopp website and %ssubmit your site%s to be included in the Shopp-powered website showcase.','Shopp'),'<a href="http://shopplugin.net/showcase">','</a>'); ?></li>
</ul>
<br />
<form action="admin.php?page=<?php echo $this->Flow->Admin->settings['settings'][0]; ?>" method="post">
<div class="alignright"><input type="submit" name="setup" value="<?php _e('Continue to Shopp Setup','Shopp'); ?>&hellip;" class="button-primary" /></div>
<p><input type="hidden" name="settings[show_welcome]" value="off" /><input type="checkbox" name="settings[show_welcome]" id="welcome-toggle" value="on" <?php echo ($this->Settings->get('show_welcome') == "on")?' checked="checked"':''; ?> /><label for="welcome-toggle"> <small><?php _e('Show this screen every time after activating Shopp','Shopp'); ?></small></label></p>
</form>
</div>
Binary file not shown.

After

Width:  |  Height:  |  Size: 781 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 733 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 139 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 715 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 454 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 880 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 653 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 230 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 949 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 516 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 257 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 168 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 207 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 480 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 275 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 206 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 385 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 294 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 591 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 579 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 663 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 582 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 779 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 342 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 651 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 386 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 663 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

@@ -0,0 +1,10 @@
<form action="<?php echo esc_url($_SERVER['REQUEST_URI']); ?>" method="post">
<ul>
<li>
<span><input type="text" name="purchaseid" size="12" /><label><?php _e('Order Number','Shopp'); ?></label></span>
<span><input type="text" name="email" size="32" /><label><?php _e('E-mail Address','Shopp'); ?></label></span>
<span><input type="submit" name="vieworder" value="<?php _e('View Order','Shopp'); ?>" /></span>
</li>
</ul>
<br class="clear" />
</form>
@@ -0,0 +1,11 @@
<!-- <ul class="subsubsub right">
<li><a href="?page=shopp/customers"><?php _e('Customers','Shopp'); ?></a></li>
</ul> -->
<ul class="subsubsub">
<li><a href="<?php echo esc_url(add_query_arg(array_merge($_GET,array('status'=>null,'id'=>null)),$Shopp->wpadminurl."admin.php")); ?>"><?php _e('All Orders','Shopp'); ?></a></li>
<?php
$StatusCounts = $this->order_status_counts();
if (!empty($statusLabels)) foreach($statusLabels as $id => $label): ?>
<li>| <a href="<?php echo esc_url(add_query_arg(array_merge($_GET,array('status'=>$id,'id'=>null)),$Shopp->wpadminurl."admin.php")); ?>"><?php echo $label; ?></a> (<?php echo $StatusCounts[$id]; ?>)</li>
<?php endforeach; ?>
</ul>
@@ -0,0 +1,197 @@
<div class="wrap shopp">
<h2><?php _e('Order','Shopp'); ?></h2>
<?php if (!empty($updated)): ?><div id="message" class="updated fade"><p><?php echo $updated; ?></p></div><?php endif; ?>
<?php include("navigation.php"); ?>
<input type="submit" id="print-button" value="<?php _e('Print Order','Shopp'); ?>" class="button" />
<br class="clear" />
<div id="order">
<br class="clear" />
<div id="receipt" class="shopp">
<table class="transaction" cellspacing="0">
<tr><th><?php _e('Order Num','Shopp'); ?>:</th><td><?php echo $Purchase->id; ?></td></tr>
<tr><th><?php _e('Order Date','Shopp'); ?>:</th><td><?php echo _d(get_option('date_format'), $Purchase->created); ?></td></tr>
<?php if (!empty($Purchase->card) && !empty($Purchase->cardtype)): ?><tr><th><?php _e('Billed To','Shopp'); ?>:</th><td><?php (!empty($Purchase->card))?printf("%'X16d",$Purchase->card):''; ?> <?php echo (!empty($Purchase->cardtype))?'('.$Purchase->cardtype.')':''; ?></td></tr><?php endif; ?>
<tr><th><?php _e('Transaction','Shopp'); ?>:</th><td><?php echo $Purchase->transactionid; ?></td></tr>
<?php if ($Purchase->gateway == "Google Checkout"):?>
<tr><th><?php _e('Status','Shopp'); ?>:</th><td><?php echo $Purchase->transtatus; ?></td></tr>
<?php endif; ?>
<tr><td colspan="2"><br class="clear" /></td></tr>
<?php if (!empty($Purchase->phone)):?>
<tr><th><?php _e('Phone','Shopp'); ?>:</th><td><?php echo $Purchase->phone; ?></td></tr>
<?php endif; ?>
<?php if (!empty($Purchase->email)):?>
<tr><th><?php _e('Email','Shopp'); ?>:</th><td><?php echo '<a href="mailto:'.$Purchase->email.'">'.$Purchase->email.'</a>'; ?></td></tr>
<?php endif; ?>
<tr><td colspan="2"><br class="clear" /></td></tr>
<?php if (!empty($Purchase->data) && is_array($Purchase->data)):
foreach ($Purchase->data as $name => $value): ?>
<tr><th><?php echo $name; ?>:</th><td><?php if (strpos($value,"\n")): ?><textarea name="orderdata[<?php echo $name; ?>]" readonly="readonly" cols="30" rows="4"><?php echo $value; ?></textarea><?php else: echo $value; endif; ?></td></tr>
<?php endforeach; endif; ?>
</table>
<fieldset id="customer">
<legend><?php _e('Customer','Shopp'); ?></legend>
<address><big><?php echo "{$Purchase->firstname} {$Purchase->lastname}"; ?></big><br />
<?php echo $Purchase->address; ?><br />
<?php if (!empty($Purchase->xaddress)) echo $Purchase->xaddress."<br />"; ?>
<?php echo "{$Purchase->city}".(!empty($Purchase->shipstate)?', ':'')." {$Purchase->state} {$Purchase->postcode}" ?><br />
<?php echo $targets[$Purchase->country]; ?></address>
<?php if (!empty($Customer->info) && is_array($Customer->info)): ?>
<ul>
<?php foreach ($Customer->info as $name => $value): ?>
<li><strong><?php echo $name; ?>:</strong> <?php echo $value; ?></li>
<?php endforeach; ?>
</ul>
<?php endif; ?>
</fieldset>
<?php if (!empty($Purchase->shipaddress)): ?>
<fieldset id="shipto">
<legend><?php _e('Ship To','Shopp'); ?></legend>
<address><big><?php echo "{$Purchase->firstname} {$Purchase->lastname}"; ?></big><br />
<?php echo !empty($Purchase->company)?"$Purchase->company<br />":""; ?>
<?php echo $Purchase->shipaddress; ?><br />
<?php if (!empty($Purchase->shipxaddress)) echo $Purchase->shipxaddress."<br />"; ?>
<?php echo "{$Purchase->shipcity}".(!empty($Purchase->shipstate)?', ':'')." {$Purchase->shipstate} {$Purchase->shippostcode}" ?><br />
<?php echo $targets[$Purchase->shipcountry]; ?></address>
<?php if (!empty($Purchase->shipmethod)): ?>
<p><strong><?php _e('Shipping','Shopp'); ?>:</strong> <?php echo $Purchase->shipmethod; ?></p>
<?php endif;?>
</fieldset>
<?php endif; ?>
<?php if (sizeof($Purchase->purchased) > 0): ?>
<table class="widefat" cellspacing="0">
<thead>
<tr>
<th scope="col" class="item"><?php _e('Items Ordered','Shopp'); ?></th>
<th scope="col"><?php _e('Quantity','Shopp'); ?></th>
<th scope="col" class="money"><?php _e('Item Price','Shopp'); ?></th>
<th scope="col" class="money"><?php _e('Item Total','Shopp'); ?></th>
</tr>
</thead>
<tbody>
<?php $even = false; foreach ($Purchase->purchased as $id => $Item): ?>
<tr<?php if ($even) echo ' class="alternate"'; $even = !$even; ?>>
<td>
<?php echo $Item->name; ?>
<?php if (!empty($Item->optionlabel)) echo "({$Item->optionlabel})"; ?>
<?php if (is_array($Item->data) || !empty($Item->sku)): ?>
<ul>
<?php if (!empty($Item->sku)): ?><li><small><?php _e('SKU','Shopp'); ?>: <strong><?php echo $Item->sku; ?></strong></small></li><?php endif; ?>
<?php foreach ($Item->data as $key => $value): ?>
<li><small><?php echo $key; ?>: <strong><?php echo $value; ?></strong></small></li>
<?php endforeach; endif; ?>
</ul>
</td>
<td><?php echo $Item->quantity; ?></td>
<td class="money"><?php echo money($Item->unitprice+($Item->unitprice*$taxrate)); ?></td>
<td class="money total"><?php echo money($Item->total+($Item->total*$taxrate)); ?></td>
</tr>
<?php endforeach; ?>
<tr class="totals">
<th scope="row" colspan="3" class="total"><?php _e('Subtotal','Shopp'); ?></th>
<td class="money"><?php echo money($Purchase->subtotal); ?></td>
</tr>
<?php if ($Purchase->discount > 0): ?>
<tr class="totals">
<th scope="row" colspan="3" class="total"><?php _e('Discount','Shopp'); ?></th>
<td class="money">-<?php echo money($Purchase->discount); ?>
<?php if (!empty($Purchase->promos)): ?>
<ul class="promos">
<?php foreach ($Purchase->promos as $pid => $promo): ?>
<li><small><a href="?page=shopp-promotions-edit&amp;id=<?php echo $pid; ?>"><?php echo $promo; ?></a></small></li>
<?php endforeach; ?>
</ul>
<?php endif; ?>
</td>
</tr>
<?php endif; ?>
<?php if ($Purchase->freight > 0): ?>
<tr class="totals">
<th scope="row" colspan="3" class="total"><?php _e('Shipping','Shopp'); ?></th>
<td class="money"><?php echo money($Purchase->freight); ?></td>
</tr>
<?php endif; ?>
<?php if ($Purchase->tax > 0): ?>
<tr class="totals">
<th scope="row" colspan="3" class="total"><?php _e('Tax','Shopp'); ?></th>
<td class="money"><?php echo money($Purchase->tax); ?></td>
</tr>
<?php endif; ?>
<tr class="totals total">
<th scope="row" colspan="3" class="total"><?php _e('Total','Shopp'); ?></th>
<td class="money"><?php echo money($Purchase->total); ?></td>
</tr>
</tbody>
</table>
<?php else: ?>
<p class="warning"><?php _e('There were no items found for this purchase.','Shopp'); ?></p>
<?php endif; ?>
</div>
<form action="<?php echo esc_url($_SERVER['REQUEST_URI']); ?>" method="post" id="order-status">
<?php wp_nonce_field('shopp-save-order'); ?>
<div id="notification">
<div class="tablenav"><p class="alignright"><input type="hidden" name="receipt" value="no" /><input type="checkbox" name="receipt" value="yes" id="include-order" checked="checked" /><label for="include-order">&nbsp;<?php _e('Include a copy of the order in the message','Shopp'); ?></label></p>
</div>
<br class="clear" />
<p><textarea name="message" id="message" cols="50" rows="10" ></textarea></p>
</div>
<div class="tablenav">
<p class="alignright">
<label for="txn_status_menu"><?php _e('Payment','Shopp'); ?>:</label>
<select name="transtatus" id="txn_status_menu">
<?php echo menuoptions($txnStatusLabels,$Purchase->transtatus,true,true); ?>
</select>
&nbsp;
<label for="order_status_menu"><?php _e('Order Status','Shopp'); ?>:</label>
<select name="status" id="order_status_menu">
<?php echo menuoptions($statusLabels,$Purchase->status,true); ?>
</select>
<span class="middle"><input type="hidden" name="notify" value="no" /><input type="checkbox" name="notify" value="yes" id="notify-customer" /><label for="notify-customer">&nbsp;<?php _e('Send customer notification','Shopp'); ?></label></span>
<button type="submit" name="update" value="status" class="button-secondary"><?php _e('Update Status','Shopp'); ?></button></p>
</div>
</form>
</div>
</div>
<iframe id="print-receipt" name="receipt" src="?page=shopp-lookup&amp;lookup=receipt&amp;id=<?php echo $Purchase->id; ?>" width="400" height="100" class="invisible"></iframe>
<script type="text/javascript">
(function($){
$('#notification').hide();
$('#notify-customer').click(function () {
$('#notification').animate({
height: "toggle",
opacity:"toggle"
}, 500);
});
$('#print-button').click(function () {
var frame = $('#print-receipt').get(0);
if ($.browser.opera || $.browser.msie) {
var preview = window.open(frame.contentWindow.location.href+"&print=auto");
$(preview).load(function () {
preview.close();
});
} else {
frame.contentWindow.focus();
frame.contentWindow.print();
}
});
$('#customer').click(function () {
window.location = "<?php echo add_query_arg(array('page'=>$this->Admin->editcustomer,'id'=>$Purchase->customer),$Shopp->wpadminurl.'admin.php'); ?>";
});
})(jQuery)
</script>
@@ -0,0 +1,325 @@
<div class="wrap shopp">
<h2><?php _e('Orders','Shopp'); ?></h2>
<form action="<?php echo esc_url($_SERVER['REQUEST_URI']); ?>" id="orders" method="get">
<?php include("navigation.php"); ?>
<div>
<input type="hidden" name="page" value="<?php echo $page; ?>" />
<input type="hidden" name="status" value="<?php echo $status; ?>" />
</div>
<div class="clear"></div>
<p id="post-search" class="search-box">
<input type="text" id="orders-search-input" class="search-input" name="s" value="<?php echo attribute_escape($s); ?>" />
<input type="submit" value="<?php _e('Search Orders','Shopp'); ?>" class="button" />
</p>
<ul id="report">
<li><strong><?php echo $ordercount->total; ?></strong> <span><?php _e('Orders','Shopp'); ?></span></li>
<li><strong><?php echo money($ordercount->sales); ?></strong> <span><?php _e('Total Sales','Shopp'); ?></span></li>
<li><strong><?php echo money($ordercount->avgsale); ?></strong> <span><?php _e('Average Sale','Shopp'); ?></span></li>
</ul>
<div class="tablenav">
<div class="alignleft actions">
<button type="submit" id="delete-button" name="deleting" value="order" class="button-secondary"><?php _e('Delete','Shopp'); ?></button>
<select name="newstatus">
<?php echo menuoptions($statusLabels,false,true); ?>
</select>
<button type="submit" id="update-button" name="update" value="order" class="button-secondary"><?php _e('Update','Shopp'); ?></button>
<span class="filtering">
<select name="range" id="range">
<?php echo menuoptions($ranges,$range,true); ?>
</select>
<span id="dates">
<div id="start-position" class="calendar-wrap"><input type="text" id="start" name="start" value="<?php echo $startdate; ?>" size="10" class="search-input selectall" /></div>
<small>to</small>
<div id="end-position" class="calendar-wrap"><input type="text" id="end" name="end" value="<?php echo $enddate; ?>" size="10" class="search-input selectall" /></div>
</span>
<button type="submit" id="filter-button" name="filter" value="order" class="button-secondary"><?php _e('Filter','Shopp'); ?></button>
</span>
</div>
<?php if ($page_links) echo "<div class='tablenav-pages'>$page_links</div>"; ?>
<div class="clear"></div>
</div>
<?php if (SHOPP_WP27): ?><div class="clear"></div>
<?php else: ?><br class="clear" /><?php endif; ?>
<table class="widefat" cellspacing="0">
<thead>
<tr><?php shopp_print_column_headers('toplevel_page_shopp-orders'); ?></tr>
</thead>
<?php if (SHOPP_WP27): ?>
<tfoot>
<tr><?php shopp_print_column_headers('toplevel_page_shopp-orders',false); ?></tr>
</tfoot>
<?php endif; ?>
<?php if (sizeof($Orders) > 0): ?>
<tbody id="orders-table" class="list orders">
<?php
if (SHOPP_WP27) $hidden = get_hidden_columns('toplevel_page_shopp-orders');
else $hidden = array();
$even = false; foreach ($Orders as $Order):
$classes = array();
$txnstatus = $Order->transtatus;
if (array_key_exists($Order->transtatus,$txnStatusLabels)) $txnstatus = $txnStatusLabels[$Order->transtatus];
if (empty($txnstatus)) $txnstatus = "UNKNOWN";
$classes[] = strtolower(preg_replace('/[^\w]/','_',$txnstatus));
if (!$even) $classes[] = "alternate";
do_action_ref_array('shopp_order_row_css',array(&$classes,&$Order));
$even = !$even;
?>
<tr class="<?php echo join(' ',$classes); ?>">
<th scope='row' class='check-column'><input type='checkbox' name='selected[]' value='<?php echo $Order->id; ?>' /></th>
<td class="order column-order<?php echo in_array('order',$hidden)?' hidden':''; ?>"><?php echo $Order->id; ?></td>
<td class="name column-name"><a class='row-title' href='<?php echo add_query_arg(array('page'=>$this->Admin->orders,'id'=>$Order->id),$Shopp->wpadminurl."admin.php"); ?>' title='<?php _e('View','Shopp'); ?> &quot;<?php echo $Order->id; ?>&quot;'><?php echo (empty($Order->firstname) && empty($Order->lastname))?"(".__('no contact name','Shopp').")":"{$Order->firstname} {$Order->lastname}"; ?></a><?php echo !empty($Order->company)?"<br />$Order->company":""; ?></td>
<td class="destination column-destination<?php echo in_array('destination',$hidden)?' hidden':''; ?>"><?php
$location = '';
$location = $Order->shipcity;
if (!empty($location) && !empty($Order->shipstate)) $location .= ', ';
$location .= $Order->shipstate;
if (!empty($location) && !empty($Order->shipcountry))
$location .= ' &mdash; ';
$location .= $Order->shipcountry;
echo $location;
?></td>
<td class="total column-total<?php echo in_array('total',$hidden)?' hidden':''; ?>"><?php echo money($Order->total); ?></td>
<td class="txn column-txn<?php echo in_array('txn',$hidden)?' hidden':''; ?>"><?php echo $Order->transactionid; ?><br /><strong><?php echo $Order->gateway; ?></strong> &mdash; <?php echo $txnstatus; ?></td>
<td class="date column-date<?php echo in_array('date',$hidden)?' hidden':''; ?>"><?php echo date("Y/m/d",mktimestamp($Order->created)); ?><br />
<strong><?php echo $statusLabels[$Order->status]; ?></strong></td>
</tr>
<?php endforeach; ?>
</tbody>
<?php else: ?>
<tbody><tr><td colspan="6"><?php _e('No','Shopp'); ?><?php if (!empty($_GET['status'])) echo ' '.strtolower($statusLabels[$_GET['status']]); ?> <?php _e('orders, yet.','Shopp'); ?></td></tr></tbody>
<?php endif; ?>
</table>
</form>
<div class="tablenav">
<div class="alignleft actions">
<form action="<?php echo esc_url(add_query_arg(array_merge($_GET,array('lookup'=>'purchaselog')),$Shopp->wpadminurl."admin.php")); ?>" id="log" method="post">
<button type="button" id="export-settings-button" name="export-settings" class="button-secondary"><?php _e('Export Options','Shopp'); ?></button>
<span id="export-settings" class="hidden">
<div id="export-columns" class="multiple-select">
<ul>
<li<?php $even = true; if ($even) echo ' class="odd"'; $even = !$even; ?>><input type="checkbox" name="selectall_columns" id="selectall_columns" /><label for="selectall_columns"><strong><?php _e('Select All','Shopp'); ?></strong></label></li>
<li<?php if ($even) echo ' class="odd"'; $even = !$even; ?>><input type="hidden" name="settings[purchaselog_headers]" value="off" /><input type="checkbox" name="settings[purchaselog_headers]" id="purchaselog_headers" value="on" /><label for="purchaselog_headers"><strong><?php _e('Include column headings','Shopp'); ?></strong></label></li>
<?php $even = true; foreach ($columns as $name => $label): ?>
<li<?php if ($even) echo ' class="odd"'; $even = !$even; ?>><input type="checkbox" name="settings[purchaselog_columns][]" value="<?php echo $name; ?>" id="column-<?php echo $name; ?>" <?php echo in_array($name,$selected)?' checked="checked"':''; ?> /><label for="column-<?php echo $name; ?>" ><?php echo $label; ?></label></li>
<?php endforeach; ?>
</ul>
</div>
<?php PurchasesIIFExport::settings(); ?>
<br />
<select name="settings[purchaselog_format]" id="purchaselog-format">
<?php echo menuoptions($exports,$formatPref,true); ?>
</select></span>
<button type="submit" id="download-button" name="download" value="export" class="button-secondary"><?php _e('Download','Shopp'); ?></button>
</div>
<?php if ($page_links) echo "<div class='tablenav-pages'>$page_links</div>"; ?>
<div class="clear"></div>
</div>
</div>
<div id="start-calendar" class="calendar"></div>
<div id="end-calendar" class="calendar"></div>
<script type="text/javascript">
helpurl = "<?php echo SHOPP_DOCS; ?>Managing Orders";
var lastexport = new Date(<?php echo date("Y,(n-1),j",$Shopp->Settings->get('purchaselog_lastexport')); ?>);
jQuery(document).ready( function() {
var $=jQuery.noConflict();
$('#selectall').change( function() {
$('#orders-table th input').each( function () {
if (this.checked) this.checked = false;
else this.checked = true;
});
});
$('#delete-button').click(function() {
if (confirm("<?php echo addslashes(__('Are you sure you want to delete the selected orders?','Shopp')); ?>")) return true;
else return false;
});
$('#update-button').click(function() {
if (confirm("<?php echo addslashes(__('Are you sure you want to update the status of the selected orders?','Shopp')); ?>")) return true;
else return false;
});
function getDateInput(input) {
var match = false;
match = $(input).get(0).value.match(/^(\d{1,2}).{1}(\d{1,2}).{1}(\d{4})/);
if (match) return new Date(match[3],(match[1]-1),match[2]);
return false;
}
function formatDate (e) {
if (this.value == "") match = false;
if (this.value.match(/^(\d{6,8})/))
match = this.value.match(/(\d{1,2}?)(\d{1,2})(\d{4,4})$/);
else if (this.value.match(/^(\d{1,2}.{1}\d{1,2}.{1}\d{4})/))
match = this.value.match(/^(\d{1,2}).{1}(\d{1,2}).{1}(\d{4})/);
if (match) this.setDate(new Date(match[3],(match[1]-1),match[2]));
$('#start-calendar, #end-calendar').hide();
}
function setDate(date,calendar) {
$(this).val((date.getMonth()+1)+"/"+date.getDate()+"/"+date.getFullYear());
if (calendar) {
calendar.render(date.getMonth()+1,date.getDate(),date.getFullYear());
calendar.selection = date;
calendar.autoselect();
}
}
var start = $('#start');
var startdate = getDateInput(start);
var StartCalendar = new PopupCalendar($('#start-calendar'));
StartCalendar.scheduling = false;
if (startdate) {
StartCalendar.render(startdate.getMonth()+1,startdate.getDate(),startdate.getFullYear());
StartCalendar.selection = startdate;
StartCalendar.autoselect();
} else StartCalendar.render();
start.setDate = setDate;
start.get(0).setDate = setDate;
start.calendar = StartCalendar;
start.change(formatDate);
var end = $('#end');
var enddate = getDateInput(end);
var EndCalendar = new PopupCalendar($('#end-calendar'));
EndCalendar.scheduling = false;
if (enddate) {
EndCalendar.render(enddate.getMonth()+1,enddate.getDate(),enddate.getFullYear());
EndCalendar.selection = enddate;
EndCalendar.autoselect();
} else EndCalendar.render();
end.setDate = setDate;
end.get(0).setDate = setDate;
end.calendar = EndCalendar;
end.change(formatDate);
var scpos = $('#start-position').offset();
$('#start-calendar').hide()
.css({left:scpos.left,
top:scpos.top+$('#start-position').height()+10});
$('#start').click(function (e) {
$('#end-calendar').hide();
$('#start-calendar').toggle();
$(StartCalendar).change(function () {
$('#start').val((StartCalendar.selection.getMonth()+1)+"/"+
StartCalendar.selection.getDate()+"/"+
StartCalendar.selection.getFullYear());
});
});
var ecpos = $('#end-position').offset();
$('#end-calendar').hide()
.css({left:ecpos.left,
top:ecpos.top+$('#end-position input').height()+10});
$('#end').click(function (e) {
$('#start-calendar').hide();
$('#end-calendar').toggle();
$(EndCalendar).change(function () {
$('#end').val((EndCalendar.selection.getMonth()+1)+"/"+
EndCalendar.selection.getDate()+"/"+
EndCalendar.selection.getFullYear());
});
});
$('#range').change(function () {
if (this.selectedIndex == 0) {
start.val(''); end.val('');
$('#dates').addClass('hidden');
return;
} else $('#dates').removeClass('hidden');
var today = new Date();
var startdate = getDateInput($('#start'));
var enddate = getDateInput($('#end'));
if (!startdate) startdate = new Date(today.getFullYear(),today.getMonth(),today.getDate());
if (!enddate) enddate = new Date(today.getFullYear(),today.getMonth(),today.getDate());
today = new Date(today.getFullYear(),today.getMonth(),today.getDate());
switch($(this).val()) {
case 'week':
startdate.setDate(today.getDate()-today.getDay());
enddate = new Date(startdate.getFullYear(),startdate.getMonth(),startdate.getDate()+6);
break;
case 'month':
startdate.setDate(1);
enddate = new Date(startdate.getFullYear(),startdate.getMonth()+1,0);
break;
case 'quarter':
quarter = Math.floor(today.getMonth()/3);
startdate = new Date(today.getFullYear(),today.getMonth()-(today.getMonth()%3),1);
enddate = new Date(today.getFullYear(),startdate.getMonth()+3,0);
break;
case 'year':
startdate = new Date(today.getFullYear(),0,1);
enddate = new Date(today.getFullYear()+1,0,0);
break;
case 'yesterday':
startdate.setDate(today.getDate()-1);
enddate.setDate(today.getDate()-1);
break;
case 'lastweek':
startdate.setDate(today.getDate()-today.getDay()-7);
enddate.setDate((today.getDate()-today.getDay()+6)-7);
break;
case 'last30':
startdate.setDate(today.getDate()-30);
enddate.setDate(today.getDate());
break;
case 'last90':
startdate.setDate(today.getDate()-90);
enddate.setDate(today.getDate());
break;
case 'lastmonth':
startdate = new Date(today.getFullYear(),today.getMonth()-1,1);
enddate = new Date(today.getFullYear(),today.getMonth(),0);
break;
case 'lastquarter':
startdate = new Date(today.getFullYear(),(today.getMonth()-(today.getMonth()%3))-3,1);
enddate = new Date(today.getFullYear(),startdate.getMonth()+3,0);
break;
case 'lastyear':
startdate = new Date(today.getFullYear()-1,0,1);
enddate = new Date(today.getFullYear(),0,0);
break;
case 'lastexport':
startdate = lastexport;
enddate = today;
break;
case 'custom': break;
}
start.setDate(startdate,StartCalendar); end.setDate(enddate,EndCalendar);
}).change();
$('#export-settings-button').click(function () { $('#export-settings-button').hide(); $('#export-settings').removeClass('hidden'); });
$('#selectall_columns').change(function () {
if ($(this).attr('checked')) $('#export-columns input').not(this).attr('checked',true);
else $('#export-columns input').not(this).attr('checked',false);
});
<?php if (SHOPP_WP27): ?>
pagenow = 'toplevel_page_shopp-orders';
columns.init(pagenow);
<?php endif; ?>
});
</script>
File diff suppressed because one or more lines are too long
@@ -0,0 +1,332 @@
<?php if (SHOPP_WP27): ?>
<div class="wrap shopp">
<?php if (!empty($Shopp->Flow->Notice)): ?><div id="message" class="updated fade"><p><?php echo $Shopp->Flow->Notice; ?></p></div><?php endif; ?>
<h2><?php _e('Product Editor','Shopp'); ?></h2>
<div id="ajax-response"></div>
<form name="product" id="product" action="<?php echo $Shopp->wpadminurl; ?>admin.php" method="post">
<?php wp_nonce_field('shopp-save-product'); ?>
<div id="poststuff" class="metabox-holder has-right-sidebar">
<div id="side-info-column" class="inner-sidebar">
<?php
do_action('submitpage_box');
$side_meta_boxes = do_meta_boxes('admin_page_shopp-products-edit', 'side', $Product);
?>
</div>
<div id="post-body" class="<?php echo $side_meta_boxes ? 'has-sidebar' : 'has-sidebar'; ?>">
<div id="post-body-content" class="has-sidebar-content">
<div id="titlediv">
<div id="titlewrap">
<input name="name" id="title" type="text" value="<?php echo attribute_escape($Product->name); ?>" size="30" tabindex="1" autocomplete="off" />
</div>
<div class="inside">
<?php if (SHOPP_PERMALINKS && !empty($Product->id)): ?>
<div id="edit-slug-box"><strong><?php _e('Permalink','Shopp'); ?>:</strong>
<span id="sample-permalink"><?php echo $permalink; ?><span id="editable-slug" title="<?php _e('Click to edit this part of the permalink','Shopp'); ?>"><?php echo attribute_escape($Product->slug); ?></span><span id="editable-slug-full"><?php echo attribute_escape($Product->slug); ?></span>/</span>
<span id="edit-slug-buttons"><button type="button" class="edit-slug button"><?php _e('Edit','Shopp'); ?></button></span>
</div>
<?php else: ?>
<?php if (!empty($Product->id)): ?>
<div id="edit-slug-box"><strong><?php _e('Product ID','Shopp'); ?>:</strong>
<span id="editable-slug"><?php echo $Product->id; ?></span>
</div>
<?php endif; ?>
<?php endif; ?>
</div>
</div>
<div id="<?php echo user_can_richedit() ? 'postdivrich' : 'postdiv'; ?>" class="postarea">
<?php the_editor($Product->description,'content','Description', false); ?>
<?php wp_nonce_field( 'closedpostboxes', 'closedpostboxesnonce', false ); ?>
<?php wp_nonce_field( 'meta-box-order', 'meta-box-order-nonce', false ); ?>
</div>
<?php
do_meta_boxes('admin_page_shopp-products-edit', 'normal', $Product);
do_meta_boxes('admin_page_shopp-products-edit', 'advanced', $Product);
?>
</div>
</div>
</div> <!-- #poststuff -->
</form>
</div>
<?php else: ?>
<?php
$db =& DB::get();
$category_table = DatabaseObject::tablename(Category::$table);
$categories = $db->query("SELECT id,name,parent FROM $category_table ORDER BY parent,name",AS_ARRAY);
$categories = sort_tree($categories);
if (empty($categories)) $categories = array();
$categories_menu = '<option value="0" rel="-1,-1">'.__('Parent Category','Shopp').'&hellip;</option>';
foreach ($categories as $category) {
$padding = str_repeat("&nbsp;",$category->depth*3);
$categories_menu .= '<option value="'.$category->id.'" rel="'.$category->parent.','.$category->depth.'">'.$padding.$category->name.'</option>';
}
$selectedCategories = array();
foreach ($Product->categories as $category) $selectedCategories[] = $category->id;
?>
<div class="wrap shopp">
<?php if (!empty($Shopp->Flow->Notice)): ?><div id="message" class="updated fade"><p><?php echo $Shopp->Flow->Notice; ?></p></div><?php endif; ?>
<h2><?php _e('Product Editor','Shopp'); ?></h2>
<div id="ajax-response"></div>
<form name="product" id="product" action="<?php echo $Shopp->wpadminurl; ?>admin.php" method="post">
<?php wp_nonce_field('shopp-save-product'); ?>
<table class="form-table">
<tbody>
<tr class="form-required">
<th scope="row" valign="top"><label for="name"><?php _e('Product Name','Shopp'); ?></label></th>
<td><input name="name" id="name" type="text" value="<?php echo attribute_escape($Product->name); ?>" size="40" tabindex="1" /><br />
<?php if (SHOPP_PERMALINKS && !empty($Product->id)): ?>
<div id="edit-slug-box"><strong><?php _e('Permalink','Shopp'); ?>:</strong>
<span id="sample-permalink"><?php echo $permalink; ?><span id="editable-slug" title="<?php _e('Click to edit this part of the permalink','Shopp'); ?>"><?php echo attribute_escape($Product->slug); ?></span><span id="editable-slug-full"><?php echo attribute_escape($Product->slug); ?></span>/</span>
<span id="edit-slug-buttons"><button type="button" class="edit-slug button">Edit</button></span>
</div>
<?php else: ?>
<?php if (!empty($Product->id)): ?>
<div id="edit-slug-box"><strong><?php _e('Product ID','Shopp'); ?>:</strong>
<span id="editable-slug"><?php echo $Product->id; ?></span>
</div>
<?php endif; ?>
<?php endif; ?>
</tr>
<tr class="">
<th scope="row" valign="top"><label for="category-menu"><?php _e('Categories','Shopp'); ?></label>
<div id="new-category">
<input type="text" name="new-category" value="" size="15" id="new-category" /><br />
<select name="new-category-parent"><?php echo $categories_menu; ?></select>
<button id="add-new-category" type="button" class="button-secondary" tabindex="2"><small><?php _e('Add New Category','Shopp'); ?></small></button>
</div>
</th>
<td>
<div id="category-menu" class="multiple-select short">
<ul>
<?php $depth = 0; foreach ($categories as $category):
if ($category->depth > $depth) echo "<li><ul>"; ?>
<?php if ($category->depth < $depth): ?>
<?php for ($i = $category->depth; $i < $depth; $i++): ?>
</ul></li>
<?php endfor; ?>
<?php endif; ?>
<li id="category-element-<?php echo $category->id; ?>"><input type="checkbox" name="categories[]" value="<?php echo $category->id; ?>" id="category-<?php echo $category->id; ?>" tabindex="3"<?php if (in_array($category->id,$selectedCategories)) echo ' checked="checked"'; ?> class="category-toggle" /><label for="category-<?php echo $category->id; ?>"><?php echo $category->name; ?></label></li>
<?php $depth = $category->depth; endforeach; ?>
<?php for ($i = 0; $i < $depth; $i++): ?>
</ul></li>
<?php endfor; ?>
</ul>
</div><br />
<?php _e('Use categories to organize the products in your catalog.','Shopp'); ?></td>
</tr>
<tr class="form-required">
<th scope="row" valign="top"><label for="name"><?php _e('Tags','Shopp'); ?></label></th>
<td><input name="newtags" id="newtags" type="text" size="16" tabindex="4" autocomplete="off" value="<?php _e('enter, new, tags','Shopp'); ?>…" title="<?php _e('enter, new, tags','Shopp'); ?>…" class="form-input-tip" />
<button type="button" name="addtags" id="add-tags" class="button-secondary" tabindex="5"><small><?php _e('Add','Shopp'); ?></small></button><input type="hidden" name="taglist" id="tags" value="<?php echo join(",",$taglist); ?>"><br />
<?php _e('Separate tags with commas','Shopp'); ?><br />
<div id="taglist">
<label><big><strong><?php _e('Tags for this product:','Shopp'); ?></strong></big></label><br />
<div id="tagchecklist"></div>
</div>
</td>
<tr class="">
<th scope="row" valign="top"><label for="summary"><?php _e('Summary','Shopp'); ?></label></th>
<td><textarea name="summary" id="summary" rows="2" cols="50" tabindex="6" style="width: 97%;"><?php echo $Product->summary ?></textarea><br />
<?php _e('A brief description of the product to draw the customer\'s attention.','Shopp'); ?></td>
</tr>
<tr class="">
<th scope="row" valign="top"><label for="description"><?php _e('Description','Shopp'); ?></label></th>
<td><textarea name="description" id="content" rows="8" cols="50" tabindex="7" style="width: 97%;"><?php echo $Product->description ?></textarea><br />
<?php _e('Provide in-depth information about the product to be displayed on the product page.','Shopp'); ?></td>
</tr>
<tr class="">
<th><label><?php _e('Details &amp; Specs','Shopp'); ?></label>
<div id="new-detail">
<button type="button" id="addDetail" class="button-secondary" tabindex="8"><small><?php _e('Add Product Detail','Shopp'); ?></small></button>
</div>
</th>
<td>
<ul class="details multipane">
<li>
<div id="details-menu" class="multiple-select menu">
<input type="hidden" name="deletedSpecs" id="test" class="deletes" value="" />
<ul></ul>
</div>
</li>
<li><div id="details-list" class="list"><ul></ul></div></li>
</ul>
<div class="clear"></div>
<?php _e('Build a list of detailed information such as dimensions or features of the product.','Shopp'); ?>
</td>
</tr>
<tr id="product-images" class="form-required">
<th scope="row" valign="top"><label><?php _e('Product Images','Shopp'); ?></label>
<input type="hidden" name="product" value="<?php echo $_GET['id']; ?>" id="image-product-id" />
<input type="hidden" name="deleteImages" id="deleteImages" value="" />
<div id="swf-uploader-button"></div>
<div id="browser-uploader">
<button type="button" name="image_upload" id="image-upload" class="button-secondary"><small><?php _e('Add New Image','Shopp'); ?></small></button><br class="clear"/>
</div>
</th>
<td>
<ul id="lightbox">
<?php foreach ($Images as $i => $thumbnail): $thumbnail->properties = unserialize($thumbnail->properties); ?>
<li id="image-<?php echo $thumbnail->src; ?>"><input type="hidden" name="images[]" value="<?php echo $thumbnail->src; ?>" />
<div id="image-<?php echo $thumbnail->src; ?>-details">
<img src="?shopp_image=<?php echo $thumbnail->id; ?>" width="96" height="96" />
<div class="details">
<input type="hidden" name="imagedetails[<?php echo $i; ?>][id]" value="<?php echo $thumbnail->id; ?>" />
<p><label>Title: </label><input type="text" name="imagedetails[<?php echo $i; ?>][title]" value="<?php echo $thumbnail->properties['title']; ?>" /></p>
<p><label>Alt: </label><input type="text" name="imagedetails[<?php echo $i; ?>][alt]" value="<?php echo $thumbnail->properties['alt']; ?>" /></p>
<p class="submit"><input type="button" name="close" value="Close" class="button close" /></p>
</div>
</div>
<button type="button" name="deleteImage" value="<?php echo $thumbnail->src; ?>" title="Delete product image&hellip;" class="deleteButton"><img src="<?php echo SHOPP_PLUGINURI; ?>/core/ui/icons/delete.png" alt="-" width="16" height="16" /></button></li>
<?php endforeach; ?>
</ul>
<div class="clear"></div>
<p><?php _e('Images shown here will be out of proportion, but will be correctly sized for shoppers.','Shopp'); ?><br />
<?php _e('Double-click images to edit their details. Save the product to confirm deleted images.','Shopp'); ?></p>
</td>
</tr>
<tr>
<th scope="row" valign="top"><label for="published"><?php _e('Settings','Shopp'); ?></label></th>
<td><p><input type="hidden" name="published" value="off" /><input type="checkbox" name="published" value="on" id="published" tabindex="11" <?php if ($Product->published == "on") echo ' checked="checked"'?> /><label for="published"> <?php _e('Published','Shopp'); ?></label></p>
<p><input type="hidden" name="featured" value="off" /><input type="checkbox" name="featured" value="on" id="featured" tabindex="12" <?php if ($Product->featured == "on") echo ' checked="checked"'?> /><label for="featured"> <?php _e('Featured Product','Shopp'); ?></label></p>
<ul>
<li><input type="hidden" name="variations" value="off" /><input type="checkbox" name="variations" value="on" id="variations-setting" tabindex="13"<?php if ($Product->variations == "on") echo ' checked="checked"'?> /><label for="variations-setting"> <?php _e('Variations &mdash; Selectable product options','Shopp'); ?></label></li>
</ul>
</td>
</tr>
</tbody>
<tbody id="product-pricing">
</tbody>
</table>
<div id="variations">
<h3><?php _e('Variations','Shopp'); ?></h3>
<table class="form-table pricing">
<tbody>
<tr>
<th><?php _e('Option Menus','Shopp'); ?></th>
<td>
<?php _e('Create the menus and menu options for the product\'s variations.','Shopp'); ?><br />
<ul class="multipane options">
<li><div id="variations-menu" class="multiple-select menu"><ul></ul></div>
<div class="controls">
<button type="button" id="addVariationMenu" class="button-secondary" tabindex="14"><img src="<?php echo SHOPP_PLUGINURI; ?>/core/ui/icons/add.png" alt="-" width="16" height="16" /><small> <?php _e('Add Option Menu','Shopp'); ?></small></button>
</div>
</li>
<li>
<div id="variations-list" class="multiple-select options"></div>
<div class="controls right">
<button type="button" id="linkOptionVariations" class="button-secondary" tabindex="17"><img src="<?php echo SHOPP_PLUGINURI; ?>/core/ui/icons/linked.png" alt="link" width="16" height="16" /><small> <?php _e('Link All Variations','Shopp'); ?></small></button>
<button type="button" id="addVariationOption" class="button-secondary" tabindex="15"><img src="<?php echo SHOPP_PLUGINURI; ?>/core/ui/icons/add.png" alt="-" width="16" height="16" /><small> <?php _e('Add Option','Shopp'); ?></small></button>
</div>
</li>
</ul>
</td>
</tr>
</tbody>
<tbody id="variations-pricing"></tbody>
</table>
</div>
<div><input type="hidden" name="deletePrices" id="deletePrices" value="" />
<input type="hidden" name="prices" value="" id="prices" /></div>
<p class="submit"><input type="submit" class="button" name="save" value="<?php _e('Save Product','Shopp'); ?>" /> <select name="settings[workflow]" id="workflow">
<?php echo menuoptions($workflows,$Shopp->Settings->get('workflow'),true); ?>
</select>
</p>
</form>
</div>
<?php endif; ?>
<script type="text/javascript">
helpurl = "<?php echo SHOPP_DOCS; ?>Editing_a_Product";
var flashuploader = <?php echo ($uploader == 'flash' && !(false !== strpos(strtolower($_SERVER['HTTP_USER_AGENT']), 'mac') && apache_mod_loaded('mod_security')))?'true':'false'; ?>;
var wp26 = <?php echo (SHOPP_WP27)?'false':'true'; ?>;
var product = <?php echo (!empty($Product->id))?$Product->id:'false'; ?>;
var prices = <?php echo json_encode($Product->prices) ?>;
var specs = <?php echo json_encode($Product->specs) ?>;
var options = <?php echo json_encode($Product->options) ?>;
var priceTypes = <?php echo json_encode($priceTypes) ?>;
var shiprates = <?php echo json_encode($shiprates); ?>;
var buttonrsrc = '<?php echo includes_url('images/upload.png'); ?>';
var rsrcdir = '<?php echo SHOPP_PLUGINURI; ?>';
var siteurl = '<?php echo $Shopp->siteurl; ?>';
var adminurl = '<?php echo $Shopp->wpadminurl; ?>';
var ajaxurl = adminurl+'admin-ajax.php';
var addcategory_url = '<?php echo wp_nonce_url($Shopp->wpadminurl."admin-ajax.php", "shopp-ajax_add_category"); ?>';
var editslug_url = '<?php echo wp_nonce_url($Shopp->wpadminurl."admin-ajax.php", "shopp-ajax_edit_slug"); ?>';
var fileverify_url = '<?php echo wp_nonce_url($Shopp->wpadminurl."admin-ajax.php", "shopp-ajax_verify_file"); ?>';
var manager_page = '<?php echo $this->Admin->products; ?>';
var editor_page = '<?php echo $this->Admin->editproduct; ?>';
var request = <?php echo json_encode(stripslashes_deep($_GET)); ?>;
var workflow = {'continue':editor_page, 'close':manager_page, 'new':editor_page, 'next':editor_page, 'previous':editor_page};
var worklist = <?php echo json_encode($this->products_list(true)); ?>;
var filesizeLimit = <?php echo wp_max_upload_size(); ?>;
var weightUnit = '<?php echo $this->Settings->get('weight_unit'); ?>';
var storage = '<?php echo $this->Settings->get('product_storage'); ?>';
var productspath = '<?php echo addslashes(trailingslashit($this->Settings->get('products_path'))); ?>';
// Warning/Error Dialogs
var DELETE_IMAGE_WARNING = "<?php _e('Are you sure you want to delete this product image?','Shopp'); ?>";
var SERVER_COMM_ERROR = "<?php _e('There was an error communicating with the server.','Shopp'); ?>";
// Dynamic interface label translations
var LINK_ALL_VARIATIONS = "<?php _e('Link All Variations','Shopp'); ?>";
var UNLINK_ALL_VARIATIONS = "<?php _e('Unlink All Variations','Shopp'); ?>";
var LINK_VARIATIONS = "<?php _e('Link Variations','Shopp'); ?>";
var UNLINK_VARIATIONS = "<?php _e('Unlink Variations','Shopp'); ?>";
var ADD_IMAGE_BUTTON_TEXT = "<?php _e('Add New Image','Shopp'); ?>";
var UPLOAD_FILE_BUTTON_TEXT = "<?php _e('Upload&nbsp;File','Shopp'); ?>";
var SAVE_BUTTON_TEXT = "<?php _e('Save','Shopp'); ?>";
var CANCEL_BUTTON_TEXT = "<?php _e('Cancel','Shopp'); ?>";
var TYPE_LABEL = "<?php _e('Type','Shopp'); ?>";
var PRICE_LABEL = "<?php _e('Price','Shopp'); ?>";
var AMOUNT_LABEL = "<?php _e('Amount','Shopp'); ?>";
var SALE_PRICE_LABEL = "<?php _e('Sale Price','Shopp'); ?>";
var NOT_ON_SALE_TEXT = "<?php _e('Not on Sale','Shopp'); ?>";
var NOTAX_LABEL = "<?php _e('Not Taxed','Shopp'); ?>";
var SHIPPING_LABEL = "<?php _e('Shipping','Shopp'); ?>";
var FREE_SHIPPING_TEXT = "<?php _e('Free Shipping','Shopp'); ?>";
var WEIGHT_LABEL = "<?php _e('Weight','Shopp'); ?>";
var SHIPFEE_LABEL = "<?php _e('Handling Fee','Shopp'); ?>";
var INVENTORY_LABEL = "<?php _e('Inventory','Shopp'); ?>";
var NOT_TRACKED_TEXT = "<?php _e('Not Tracked','Shopp'); ?>";
var IN_STOCK_LABEL = "<?php _e('In Stock','Shopp'); ?>";
var OPTION_MENU_DEFAULT = "<?php _e('Option Menu','Shopp'); ?>";
var NEW_OPTION_DEFAULT = "<?php _e('New Option','Shopp'); ?>";
var SKU_LABEL = "<?php _e('SKU','Shopp'); ?>";
var SKU_LABEL_HELP = "<?php _e('Stock Keeping Unit','Shopp'); ?>";
var DONATIONS_VAR_LABEL = "<?php _e('Accept variable amounts','Shopp'); ?>";
var DONATIONS_MIN_LABEL = "<?php _e('Amount required as minimum','Shopp'); ?>";
var PRODUCT_DOWNLOAD_LABEL = "<?php _e('Product Download','Shopp'); ?>";
var NO_PRODUCT_DOWNLOAD_TEXT = "<?php _e('No product download.','Shopp'); ?>";
var NO_DOWNLOAD = "<?php _e('No download file.','Shopp'); ?>";
var DEFAULT_PRICELINE_LABEL = "<?php _e('Price & Delivery','Shopp'); ?>";
var FILE_NOT_FOUND_TEXT = "<?php _e('The file you specified could not be found.','Shopp'); ?>";
var FILE_NOT_READ_TEXT = "<?php _e('The file you specified is not readable and cannot be used.','Shopp'); ?>";
var FILE_ISDIR_TEXT = "<?php _e('The file you specified is a directory and cannot be used.','Shopp'); ?>";
</script>
@@ -0,0 +1,124 @@
<div class="wrap shopp">
<h2><?php _e('Products','Shopp'); ?></h2>
<?php if (!empty($Shopp->Flow->Notice)): ?><div id="message" class="updated fade"><p><?php echo $Shopp->Flow->Notice; ?></p></div><?php endif; ?>
<form action="" method="get" id="products-manager">
<div>
<input type="hidden" name="page" value="<?php echo $this->Admin->products; ?>" />
</div>
<p id="post-search" class="search-box">
<input type="text" id="products-search-input" class="search-input" name="s" value="<?php echo stripslashes(attribute_escape($s)); ?>" />
<input type="submit" value="<?php _e('Search Products','Shopp'); ?>" class="button" />
</p>
<p><a href="<?php echo add_query_arg(array('page'=>$this->Admin->editproduct,'id'=>'new'),$Shopp->wpadminurl."admin.php"); ?>" class="button"><?php _e('New Product','Shopp'); ?></a></p>
<div class="tablenav">
<?php if ($page_links) echo "<div class='tablenav-pages'>$page_links</div>"; ?>
<div class="alignleft actions">
<button type="submit" id="delete-button" name="deleting" value="product" class="button-secondary"><?php _e('Delete','Shopp'); ?></button>
<select name='cat'>
<?php echo $categories_menu; ?>
</select>
<select name='sl'>
<?php echo $inventory_menu; ?>
</select>
<input type="submit" id="filter-button" value="<?php _e('Filter','Shopp'); ?>" class="button-secondary">
</div>
<div class="clear"></div>
</div>
<?php if (SHOPP_WP27): ?><div class="clear"></div>
<?php else: ?><br class="clear" /><?php endif; ?>
<table class="widefat" cellspacing="0">
<thead>
<tr><?php shopp_print_column_headers('shopp_page_shopp-products'); ?></tr>
</thead>
<?php if (SHOPP_WP27): ?>
<tfoot>
<tr><?php shopp_print_column_headers('shopp_page_shopp-products',false); ?></tr>
</tfoot>
<?php endif; ?>
<?php if (sizeof($Products) > 0): ?>
<tbody id="products" class="list products">
<?php
$hidden = array();
if (SHOPP_WP27) $hidden = get_hidden_columns('shopp_page_shopp-products');
$even = false;
foreach ($Products as $key => $Product):
$editurl = esc_url(attribute_escape(add_query_arg(array_merge(stripslashes_deep($_GET),
array('page'=>$this->Admin->editproduct,
'id'=>$Product->id)),
$Shopp->wpadminurl."admin.php")));
$ProductName = empty($Product->name)?'('.__('no product name','Shopp').')':$Product->name;
?>
<tr<?php if (!$even) echo " class='alternate'"; $even = !$even; ?>>
<th scope='row' class='check-column'><input type='checkbox' name='delete[]' value='<?php echo $Product->id; ?>' /></th>
<td class="name column-name"><a class='row-title' href='<?php echo $editurl; ?>' title='<?php _e('Edit','Shopp'); ?> &quot;<?php echo $ProductName; ?>&quot;'><?php echo $ProductName; ?></a>
<div class="row-actions">
<span class='edit'><a href="<?php echo $editurl; ?>" title="<?php _e('Edit','Shopp'); ?> &quot;<?php echo $ProductName; ?>&quot;"><?php _e('Edit','Shopp'); ?></a> | </span>
<span class='edit'><a href="<?php echo esc_url(add_query_arg(array_merge($_GET,array('duplicate'=>$Product->id)),$Shopp->wpadminurl)); ?>" title="<?php _e('Duplicate','Shopp'); ?> &quot;<?php echo $ProductName; ?>&quot;"><?php _e('Duplicate','Shopp'); ?></a> | </span>
<span class='delete'><a class='submitdelete' title='<?php _e('Delete','Shopp'); ?> &quot;<?php echo $ProductName; ?>&quot;' href='' rel="<?php echo $Product->id; ?>"><?php _e('Delete','Shopp'); ?></a> | </span>
<span class='view'><a href="<?php echo (SHOPP_PERMALINKS)?$Shopp->shopuri.$Product->slug:add_query_arg('shopp_pid',$Product->id,$Shopp->shopuri); ?>" title="<?php _e('View','Shopp'); ?> &quot;<?php echo $ProductName; ?>&quot;" rel="permalink" target="_blank"><?php _e('View','Shopp'); ?></a></span>
</div>
</td>
<td class="category column-category<?php echo in_array('category',$hidden)?' hidden':''; ?>"><?php echo $Product->categories; ?></td>
<td class="price column-price<?php echo in_array('price',$hidden)?' hidden':''; ?>"><?php
if ($Product->variations == "off") echo money($Product->mainprice);
elseif ($Product->maxprice == $Product->minprice) echo money($Product->maxprice);
else echo money($Product->minprice)."&mdash;".money($Product->maxprice);
?></td>
<td class="inventory column-inventory<?php echo in_array('inventory',$hidden)?' hidden':''; ?>"><?php if ($Product->inventory == "on") echo $Product->stock; ?></td>
<td class="featured column-featured<?php echo ($Product->featured == "on")?' is-featured':''; echo in_array('featured',$hidden)?' hidden':''; ?>">&nbsp;</td>
</tr>
<?php endforeach; ?>
</tbody>
<?php else: ?>
<tbody><tr><td colspan="6"><?php _e('No products found.','Shopp'); ?></td></tr></tbody>
<?php endif; ?>
</table>
</form>
<div class="tablenav">
<?php if ($page_links) echo "<div class='tablenav-pages'>$page_links</div>"; ?>
<div class="clear"></div>
</div>
</div>
<script type="text/javascript">
helpurl = "<?php echo SHOPP_DOCS; ?>Products";
jQuery(document).ready( function() {
var $=jQuery.noConflict();
$('#selectall').change( function() {
$('#products th input').each( function () {
if (this.checked) this.checked = false;
else this.checked = true;
});
});
$('a.submitdelete').click(function () {
var name = $(this).attr('title');
if ( confirm("<?php _e('You are about to delete this product!\n \'Cancel\' to stop, \'OK\' to delete.','Shopp'); ?>")) {
$('<input type="hidden" name="delete[]" />').val($(this).attr('rel')).appendTo('#products-manager');
$('<input type="hidden" name="deleting" />').val('product').appendTo('#products-manager');
$('#products-manager').submit();
return false;
} else return false;
});
$('#delete-button').click(function() {
if (confirm("<?php echo addslashes(__('Are you sure you want to delete the selected products?','Shopp')); ?>")) return true;
else return false;
});
<?php if (SHOPP_WP27): ?>
pagenow = 'shopp_page_shopp-products';
columns.init(pagenow);
<?php endif; ?>
});
</script>
@@ -0,0 +1,207 @@
<?php
function save_meta_box ($Product) {
global $Shopp;
$workflows = array(
"continue" => __('Continue Editing','Shopp'),
"close" => __('Products Manager','Shopp'),
"new" => __('New Product','Shopp'),
"next" => __('Edit Next','Shopp'),
"previous" => __('Edit Previous','Shopp')
);
?>
<div><input type="hidden" name="id" value="<?php echo $Product->id; ?>" /></div>
<div id="major-publishing-actions">
<select name="settings[workflow]" id="workflow">
<?php echo menuoptions($workflows,$Shopp->Settings->get('workflow'),true); ?>
</select>
<input type="submit" class="button-primary" name="save" value="<?php _e('Save Product','Shopp'); ?>" />
</div>
<?php
}
add_meta_box('save-product', __('Save','Shopp'), 'save_meta_box', 'admin_page_shopp-products-edit', 'side', 'core');
function categories_meta_box ($Product) {
$db =& DB::get();
$category_table = DatabaseObject::tablename(Category::$table);
$categories = $db->query("SELECT id,name,parent FROM $category_table ORDER BY parent,name",AS_ARRAY);
$categories = sort_tree($categories);
if (empty($categories)) $categories = array();
$categories_menu = '<option value="0" rel="-1,-1">'.__('Parent Category','Shopp').'&hellip;</option>';
foreach ($categories as $category) {
$padding = str_repeat("&nbsp;",$category->depth*3);
$categories_menu .= '<option value="'.$category->id.'" rel="'.$category->parent.','.$category->depth.'">'.$padding.$category->name.'</option>';
}
$selectedCategories = array();
foreach ($Product->categories as $category) $selectedCategories[] = $category->id;
?>
<div id="category-menu" class="multiple-select short">
<ul>
<?php $depth = 0; foreach ($categories as $category):
if ($category->depth > $depth) echo "<li><ul>"; ?>
<?php if ($category->depth < $depth): ?>
<?php for ($i = $category->depth; $i < $depth; $i++): ?>
</ul></li>
<?php endfor; ?>
<?php endif; ?>
<li id="category-element-<?php echo $category->id; ?>"><input type="checkbox" name="categories[]" value="<?php echo $category->id; ?>" id="category-<?php echo $category->id; ?>" tabindex="3"<?php if (in_array($category->id,$selectedCategories)) echo ' checked="checked"'; ?> class="category-toggle" /><label for="category-<?php echo $category->id; ?>"><?php echo $category->name; ?></label></li>
<?php $depth = $category->depth; endforeach; ?>
<?php for ($i = 0; $i < $depth; $i++): ?>
</ul></li>
<?php endfor; ?>
</ul>
</div>
<div id="new-category">
<input type="text" name="new-category" value="" size="15" id="new-category" /><br />
<select name="new-category-parent"><?php echo $categories_menu; ?></select>
<button id="add-new-category" type="button" class="button-secondary" tabindex="2"><small><?php _e('Add','Shopp'); ?></small></button>
</div>
<?php
}
add_meta_box('categories-box', __('Categories','Shopp'), 'categories_meta_box', 'admin_page_shopp-products-edit', 'side', 'core');
function tags_meta_box ($Product) {
$taglist = array();
foreach ($Product->tags as $tag) $taglist[] = $tag->name;
?>
<input name="newtags" id="newtags" type="text" size="16" tabindex="4" autocomplete="off" value="<?php _e('enter, new, tags','Shopp'); ?>…" title="<?php _e('enter, new, tags','Shopp'); ?>…" class="form-input-tip" />
<button type="button" name="addtags" id="add-tags" class="button-secondary" tabindex="5"><small><?php _e('Add','Shopp'); ?></small></button><input type="hidden" name="taglist" id="tags" value="<?php echo join(",",attribute_escape_deep($taglist)); ?>"><br />
<label><?php _e('Separate tags with commas','Shopp'); ?></label>
<div id="taglist">
<label><big><strong><?php _e('Tags for this product:','Shopp'); ?></strong></big></label><br />
<div id="tagchecklist" class="tagchecklist"></div>
</div>
<?php
}
add_meta_box('product-tags', __('Tags','Shopp'), 'tags_meta_box', 'admin_page_shopp-products-edit', 'side', 'core');
function settings_meta_box ($Product) {
$taglist = array();
foreach ($Product->tags as $tag) $taglist[] = $tag->name;
?>
<p><input type="hidden" name="published" value="off" /><input type="checkbox" name="published" value="on" id="published" tabindex="11" <?php if ($Product->published == "on") echo ' checked="checked"'?> /><label for="published"> <?php _e('Published','Shopp'); ?></label></p>
<p><input type="hidden" name="featured" value="off" /><input type="checkbox" name="featured" value="on" id="featured" tabindex="12" <?php if ($Product->featured == "on") echo ' checked="checked"'?> /><label for="featured"> <?php _e('Featured Product','Shopp'); ?></label></p>
<p><input type="hidden" name="variations" value="off" /><input type="checkbox" name="variations" value="on" id="variations-setting" tabindex="13"<?php if ($Product->variations == "on") echo ' checked="checked"'?> /><label for="variations-setting"> <?php _e('Variations &mdash; Selectable product options','Shopp'); ?></label></p>
<?php
}
add_meta_box('product-settings', __('Settings','Shopp'), 'settings_meta_box', 'admin_page_shopp-products-edit', 'side', 'core');
function summary_meta_box ($Product) {
?>
<textarea name="summary" id="summary" rows="2" cols="50" tabindex="6"><?php echo $Product->summary ?></textarea><br />
<label for="summary"><?php _e('A brief description of the product to draw the customer\'s attention.','Shopp'); ?></label>
<?php
}
add_meta_box('product-summary', __('Summary','Shopp'), 'summary_meta_box', 'admin_page_shopp-products-edit', 'normal', 'core');
function details_meta_box ($Product) {
?>
<ul class="details multipane">
<li>
<div id="details-menu" class="multiple-select menu">
<input type="hidden" name="deletedSpecs" id="test" class="deletes" value="" />
<ul></ul>
</div>
</li>
<li><div id="details-list" class="list"><ul></ul></div></li>
</ul><br class="clear" />
<div id="new-detail">
<button type="button" id="addDetail" class="button-secondary" tabindex="8"><small><?php _e('Add Product Detail','Shopp'); ?></small></button>
<p><?php _e('Build a list of detailed information such as dimensions or features of the product.','Shopp'); ?></p>
</div>
<p></p>
<?php
}
add_meta_box('product-details-box', __('Details &amp; Specs','Shopp'), 'details_meta_box', 'admin_page_shopp-products-edit', 'normal', 'core');
function images_meta_box ($Product) {
$db =& DB::get();
if ($Product->id) {
$Assets = new Asset();
$Images = $db->query("SELECT id,src,properties FROM $Assets->_table WHERE context='product' AND parent=$Product->id AND datatype='thumbnail' ORDER BY sortorder",AS_ARRAY);
unset($Assets);
}
if (!isset($Images)) $Images = array();
?>
<ul id="lightbox">
<?php foreach ($Images as $i => $thumbnail): $thumbnail->properties = unserialize($thumbnail->properties); ?>
<li id="image-<?php echo $thumbnail->src; ?>"><input type="hidden" name="images[]" value="<?php echo $thumbnail->src; ?>" />
<div id="image-<?php echo $thumbnail->src; ?>-details">
<img src="?shopp_image=<?php echo $thumbnail->id; ?>" width="96" height="96" />
<div class="details">
<input type="hidden" name="imagedetails[<?php echo $i; ?>][id]" value="<?php echo $thumbnail->id; ?>" />
<p><label>Title: </label><input type="text" name="imagedetails[<?php echo $i; ?>][title]" value="<?php echo $thumbnail->properties['title']; ?>" /></p>
<p><label>Alt: </label><input type="text" name="imagedetails[<?php echo $i; ?>][alt]" value="<?php echo $thumbnail->properties['alt']; ?>" /></p>
<p class="submit"><input type="button" name="close" value="Close" class="button close" /></p>
</div>
</div>
<button type="button" name="deleteImage" value="<?php echo $thumbnail->src; ?>" title="Delete product image&hellip;" class="deleteButton"><img src="<?php echo SHOPP_PLUGINURI; ?>/core/ui/icons/delete.png" alt="-" width="16" height="16" /></button></li>
<?php endforeach; ?>
</ul>
<div class="clear"></div>
<input type="hidden" name="product" value="<?php echo $_GET['id']; ?>" id="image-product-id" />
<input type="hidden" name="deleteImages" id="deleteImages" value="" />
<div id="swf-uploader-button"></div>
<div id="browser-uploader">
<button type="button" name="image_upload" id="image-upload" class="button-secondary"><small><?php _e('Add New Image','Shopp'); ?></small></button><br class="clear"/>
</div>
<p><?php _e('Images shown here will be out of proportion, but will be correctly sized for shoppers.','Shopp'); ?><br />
<?php _e('Double-click images to edit their details. Save the product to confirm deleted images.','Shopp'); ?></p>
<?php
}
add_meta_box('product-images', __('Product Images','Shopp'), 'images_meta_box', 'admin_page_shopp-products-edit', 'normal', 'core');
function pricing_meta_box ($Product) {
?>
<div id="product-pricing"></div>
<div id="variations">
<div id="variations-menus" class="panel">
<div class="pricing-label">
<label><?php _e('Variation Option Menus','Shopp'); ?></label>
</div>
<div class="pricing-ui">
<p><?php _e('Create the menus and menu options for the product\'s variations.','Shopp'); ?></p>
<ul class="multipane options">
<li><div id="variations-menu" class="multiple-select menu"><ul></ul></div>
<div class="controls">
<button type="button" id="addVariationMenu" class="button-secondary" tabindex="14"><img src="<?php echo SHOPP_PLUGINURI; ?>/core/ui/icons/add.png" alt="+" width="16" height="16" /><small> <?php _e('Add Option Menu','Shopp'); ?></small></button>
</div>
</li>
<li>
<div id="variations-list" class="multiple-select options"></div>
<div class="controls right">
<button type="button" id="linkOptionVariations" class="button-secondary" tabindex="17"><img src="<?php echo SHOPP_PLUGINURI; ?>/core/ui/icons/linked.png" alt="link" width="16" height="16" /><small> <?php _e('Link All Variations','Shopp'); ?></small></button>
<button type="button" id="addVariationOption" class="button-secondary" tabindex="15"><img src="<?php echo SHOPP_PLUGINURI; ?>/core/ui/icons/add.png" alt="+" width="16" height="16" /><small> <?php _e('Add Option','Shopp'); ?></small></button>
</div>
</li>
</ul>
<div class="clear"></div>
</div>
</div>
<br />
<div id="variations-pricing"></div>
</div>
<div><input type="hidden" name="deletePrices" id="deletePrices" value="" />
<input type="hidden" name="prices" value="" id="prices" /></div>
<?php
}
add_meta_box('product-pricing-box', __('Pricing','Shopp'), 'pricing_meta_box', 'admin_page_shopp-products-edit', 'advanced', 'core');
do_action('do_meta_boxes', 'admin_page_shopp-products-edit', 'normal', $Shopp->Product);
do_action('do_meta_boxes', 'admin_page_shopp-products-edit', 'advanced', $Shopp->Product);
do_action('do_meta_boxes', 'admin_page_shopp-products-edit', 'side', $Shopp->Product);
?>
@@ -0,0 +1,348 @@
<?php if (SHOPP_WP27): ?>
<div class="wrap shopp">
<?php if (!empty($Shopp->Flow->Notice)): ?><div id="message" class="updated fade"><p><?php echo $Shopp->Flow->Notice; ?></p></div><?php endif; ?>
<h2><?php _e('Promotion Editor','Shopp'); ?></h2>
<div id="ajax-response"></div>
<form name="promotion" id="promotion" action="<?php echo add_query_arg('page',$this->Admin->promotions,$Shopp->wpadminurl."admin.php"); ?>" method="post">
<?php wp_nonce_field('shopp-save-promotion'); ?>
<div class="hidden"><input type="hidden" name="id" value="<?php echo $Promotion->id; ?>" /></div>
<div id="poststuff" class="metabox-holder has-right-sidebar">
<div id="side-info-column" class="inner-sidebar">
<?php
do_action('submitpage_box');
$side_meta_boxes = do_meta_boxes('admin_page_shopp-promotions-edit', 'side', $Promotion);
?>
</div>
<div id="post-body" class="<?php echo $side_meta_boxes ? 'has-sidebar' : 'has-sidebar'; ?>">
<div id="post-body-content" class="has-sidebar-content">
<div id="titlediv">
<div id="titlewrap">
<input name="name" id="title" type="text" value="<?php echo attribute_escape($Promotion->name); ?>" size="30" tabindex="1" autocomplete="off" />
</div>
</div>
<?php
do_meta_boxes('admin_page_shopp-promotions-edit', 'normal', $Promotion);
do_meta_boxes('admin_page_shopp-promotions-edit', 'advanced', $Promotion);
wp_nonce_field( 'closedpostboxes', 'closedpostboxesnonce', false );
?>
</div>
</div>
</div> <!-- #poststuff -->
</form>
</div>
<?php else: ?>
<div class="wrap shopp">
<h2><?php _e('Promotion Editor','Shopp'); ?></h2>
<form name="promotion" id="promotion" method="post" action="<?php echo add_query_arg('page',$Shopp->Flow->Admin->promotions,$Shopp->wpadminurl."admin.php"); ?>">
<?php wp_nonce_field('shopp-save-promotion'); ?>
<div class="hidden"><input type="hidden" name="id" value="<?php echo $Promotion->id; ?>" /></div>
<table class="form-table">
<tr class=" form-required">
<th scope="row" valign="top"><label for="promotion-name"><?php _e('Description','Shopp'); ?></label></th>
<td><input type="text" name="name" value="<?php echo attribute_escape($Promotion->name); ?>" id="promotion-name" size="40" /><br />
<?php _e('The name is used to describe the promotion on order receipts.','Shopp'); ?></td>
</tr>
<tr class=" form-required">
<th scope="row" valign="top"><label for="discount-status"><?php _e('Status','Shopp'); ?></label></th>
<td>
<label for="discount-status"><input type="hidden" name="status" value="disabled" /><input type="checkbox" name="status" id="discount-status" value="enabled"<?php echo ($Promotion->status == "enabled")?' checked="checked"':''; ?> /> &nbsp;<?php _e('Enabled','Shopp'); ?></label>
<p></p>
<div id="start-position" class="calendar-wrap"><input type="text" name="starts[month]" id="starts-month" title="<?php _e('Month','Shopp'); ?>" size="3" value="<?php echo ($Promotion->starts>1)?date("n",$Promotion->starts):''; ?>" class="selectall" />/<input type="text" name="starts[date]" id="starts-date" title="<?php _e('Day','Shopp'); ?>" size="3" value="<?php echo ($Promotion->starts>1)?date("j",$Promotion->starts):''; ?>" class="selectall" />/<input type="text" name="starts[year]" id="starts-year" title="<?php _e('Year','Shopp'); ?>" size="5" value="<?php echo ($Promotion->starts>1)?date("Y",$Promotion->starts):''; ?>" class="selectall" /></div> &mdash; <div id="end-position" class="calendar-wrap"><input type="text" name="ends[month]" id="ends-month" title="<?php _e('Month','Shopp'); ?>" size="3" value="<?php echo ($Promotion->ends>1)?date("n",$Promotion->ends):''; ?>" class="selectall" />/<input type="text" name="ends[date]" id="ends-date" title="<?php _e('Day','Shopp'); ?>" size="3" value="<?php echo ($Promotion->ends>1)?date("j",$Promotion->ends):''; ?>" class="selectall" />/<input type="text" name="ends[year]" id="ends-year" title="<?php _e('Year','Shopp'); ?>" size="5" value="<?php echo ($Promotion->ends>1)?date("Y",$Promotion->ends):''; ?>" class="selectall" /></div>
<br />
<?php _e('Enter the date range this promotion will be in effect for.','Shopp'); ?>
</td>
</tr>
<tr class=" form-required">
<th scope="row" valign="top"><label for="discount-type"><?php _e('Discount Type','Shopp'); ?></label></th>
<td><select name="type" id="discount-type">
<?php echo menuoptions($types,$Promotion->type,true); ?>
</select><br />
<?php _e('Select how the discount will be applied.','Shopp'); ?></td>
</tr>
<tr id="discount-row" class=" form-required">
<th scope="row" valign="top"><label for="discount-amount"><?php _e('Discount Amount','Shopp'); ?></label></th>
<td><input type="text" name="discount" id="discount-amount" value="<?php echo $Promotion->discount; ?>" size="10" /><br />
<?php _e('Enter the amount of this discount.','Shopp'); ?></td>
</tr>
<tr id="beyget-row" class=" form-required">
<th scope="row" valign="top"><label for="discount-amount"><?php _e('Item Quantities','Shopp'); ?></label></th>
<td><?php _e('Buy','Shopp'); ?> <input type="text" name="buyqty" id="buy-x" value="<?php echo $Promotion->buyqty; ?>" size="5" /> <?php _e('Get','Shopp'); ?> <input type="text" name="getqty" id="get-y" value="<?php echo $Promotion->getqty; ?>" size="5" /><br />
<?php _e('Enter the number of items that must be purchased and how many will be gifted.','Shopp'); ?></td>
</tr>
</table>
<br class="clear" />
<?php
$scope = '<select name="scope" id="promotion-scope">';
$scope .= menuoptions($scopes,$Promotion->scope,true);
$scope .= '</select>';
if (empty($Promotion->search)) $Promotion->search = "all";
$logic = '<select name="search" class="small">';
$logic .= menuoptions(array('any'=>__('any','Shopp'),'all' => __('all','Shopp')),$Promotion->search,true);
$logic .= '</select>';
?>
<h3><strong><?php printf(__('Apply discount to %s products where %s of these conditions are met','Shopp'),$scope,$logic); ?>:</strong></h3>
<table class="form-table" id="rules">
</table>
<p class="submit"><input type="submit" class="button-primary" name="save" value="Save Changes" /></p>
</form>
</div>
<?php endif; ?>
<div id="starts-calendar" class="calendar"></div>
<div id="ends-calendar" class="calendar"></div>
<script type="text/javascript">
helpurl = "<?php echo SHOPP_DOCS; ?>Running_Sales_%26_Promotions";
jQuery(document).ready( function() {
var $=jQuery.noConflict();
var wp26 = <?php echo (SHOPP_WP27)?'false':'true'; ?>;
var currencyFormat = <?php $base = $this->Settings->get('base_operations'); echo json_encode($base['currency']['format']); ?>;
var rules = <?php echo json_encode($Promotion->rules); ?>;
var ruleidx = 1;
var promotion = <?php echo (!empty($Promotion->id))?$Promotion->id:'false'; ?>;
var StartsCalendar = new PopupCalendar($('#starts-calendar'));
StartsCalendar.render();
var EndsCalendar = new PopupCalendar($('#ends-calendar'));
EndsCalendar.render();
var RULES_LANG = {
"Name":"<?php _e('Name','Shopp'); ?>",
"Category":"<?php _e('Category','Shopp'); ?>",
"Variation":"<?php _e('Variation','Shopp'); ?>",
"Price":"<?php _e('Price','Shopp'); ?>",
"Sale price":"<?php _e('Sale price','Shopp'); ?>",
"Type":"<?php _e('Type','Shopp'); ?>",
"In stock":"<?php _e('In stock','Shopp'); ?>",
"Item name":"<?php _e('Item name','Shopp'); ?>",
"Item amount":"<?php _e('Item amount','Shopp'); ?>",
"Item quantity":"<?php _e('Item quantity','Shopp'); ?>",
"Total quantity":"<?php _e('Total quantity','Shopp'); ?>",
"Shipping amount":"<?php _e('Shipping amount','Shopp'); ?>",
"Subtotal amount":"<?php _e('Subtotal amount','Shopp'); ?>",
"Promo code":"<?php _e('Promo code','Shopp'); ?>",
"Is equal to":"<?php _e('Is equal to','Shopp'); ?>",
"Is not equal to":"<?php _e('Is not equal to','Shopp'); ?>",
"Contains":"<?php _e('Contains','Shopp'); ?>",
"Does not contain":"<?php _e('Does not contain','Shopp'); ?>",
"Begins with":"<?php _e('Begins with','Shopp'); ?>",
"Ends with":"<?php _e('Ends with','Shopp'); ?>",
"Is greater than":"<?php _e('Is greater than','Shopp'); ?>",
"Is greater than or equal to":"<?php _e('Is greater than or equal to','Shopp'); ?>",
"Is less than":"<?php _e('Is less than','Shopp'); ?>",
"Is less than or equal to":"<?php _e('Is less than or equal to','Shopp'); ?>"
}
var product_conditions = {
"Name":{"logic":["boolean","fuzzy"],"value":"text"},
"Category":{"logic":["boolean","fuzzy"],"value":"text"},
"Variation":{"logic":["boolean","fuzzy"],"value":"text"},
"Price":{"logic":["boolean","amount"],"value":"price"},
"Sale price":{"logic":["boolean","amount"],"value":"price"},
"Type":{"logic":["boolean"],"value":"text"},
"In stock":{"logic":["boolean","amount"],"value":"text"}
}
var order_conditions = {
"Item name":{"logic":["boolean","fuzzy"],"value":"text"},
"Item quantity":{"logic":["boolean","amount"],"value":"text"},
"Item amount":{"logic":["boolean","amount"],"value":"price"},
"Total quantity":{"logic":["boolean","amount"],"value":"text"},
"Shipping amount":{"logic":["boolean","amount"],"value":"price"},
"Subtotal amount":{"logic":["boolean","amount"],"value":"price"},
"Promo code":{"logic":["boolean"],"value":"text"}
}
var logic = {
"boolean":["Is equal to","Is not equal to"],
"fuzzy":["Contains","Does not contain","Begins with","Ends with"],
"amount":["Is greater than","Is greater than or equal to","Is less than","Is less than or equal to"]
}
function add_condition (rule,location) {
var i = ruleidx;
if (!location) var row = $('<tr></tr>').appendTo('#rules');
else var row = $('<tr></tr>').insertAfter(location);
var cell = $('<td></td>').appendTo(row);
var deleteButton = $('<button type="button" class="delete"></button>').html('<img src="<?php echo SHOPP_PLUGINURI; ?>/core/ui/icons/delete.png" alt="Delete" width="16" height="16" />').appendTo(cell);
var properties = $('<select name="rules['+i+'][property]" class="ruleprops"></select>').appendTo(cell);
if ($('#promotion-scope').val() == "Order") {
for (var label in order_conditions)
$('<option></option>').html(RULES_LANG[label]).val(label).attr('rel','order').appendTo(properties);
} else {
for (var label in product_conditions)
$('<option></option>').html(RULES_LANG[label]).val(label).attr('rel','product').appendTo(properties);
}
var operation = $('<select name="rules['+i+'][logic]" ></select>').appendTo(cell);
var value = $('<span></span>').appendTo(cell);
var addspan = $('<span></span>').appendTo(cell);
var addButton = $('<button type="button" class="add"></button>').html('<img src="<?php echo SHOPP_PLUGINURI; ?>/core/ui/icons/add.png" alt="Add" width="16" height="16" />').appendTo(addspan);
addButton.click(function () { add_condition(false,row); });
deleteButton.click(function () { $(row).remove(); });
cell.hover(function () {
deleteButton.css('visibility','visible');
},function () {
deleteButton.css('visibility','hidden');
});
var valuefield = function (type) {
value.empty();
field = $('<input type="text" name="rules['+i+'][value]" class="selectall" />').appendTo(value);
if (type == "price") field.change(function () { this.value = asMoney(this.value); });
}
// Generate logic operation menu
properties.change(function () {
operation.empty();
if ($(this.options[this.selectedIndex]).attr('rel') == "product") var conditions = product_conditions[$(this).val()];
if ($(this.options[this.selectedIndex]).attr('rel') == "order") var conditions = order_conditions[$(this).val()];
if (conditions['logic'].length > 0) {
operation.show();
for (var l = 0; l < conditions['logic'].length; l++) {
var lop = conditions['logic'][l];
if (!lop) break;
for (var op = 0; op < logic[lop].length; op++)
$('<option></option>').html(RULES_LANG[logic[lop][op]]).val(logic[lop][op]).appendTo(operation);
}
} else operation.hide();
valuefield(conditions['value']);
}).change();
// Load up existing conditional rule
if (rule) {
properties.val(rule.property).change();
operation.val(rule.logic);
if (field) field.val(rule.value);
}
ruleidx++;
}
$('#discount-type').change(function () {
$('#discount-row').hide();
$('#beyget-row').hide();
var type = $(this).val();
if (type == "Percentage Off" || type == "Amount Off") $('#discount-row').show();
if (type == "Buy X Get Y Free") {
$('#beyget-row').show();
$('#promotion-scope').val('Order').change();
$('#promotion-scope option').eq(0).attr('disabled',true);
} else {
$('#promotion-scope option').eq(0).attr('disabled',false);
}
$('#discount-amount').unbind('change').change(function () {
if (type == "Percentage Off") this.value = asPercent(this.value);
if (type == "Amount Off") this.value = asMoney(this.value);
}).change();
}).change();
if (rules) for (var r in rules) add_condition(rules[r]);
else add_condition();
$('#promotion-scope').change(function () {
var scope = $(this).val();
var menus = $('#rules select.ruleprops');
$(menus).empty();
$(menus).each(function (id,menu) {
if (scope == "Order") {
for (var label in order_conditions)
$('<option></option>').html(RULES_LANG[label]).val(label).attr('rel','order').appendTo($(menu));
} else {
for (var label in product_conditions)
$('<option></option>').html(RULES_LANG[label]).val(label).attr('rel','product').appendTo($(menu));
}
});
});
var scpos = $('#start-position').offset();
$('#starts-calendar').hide()
.css({left:scpos.left,
top:scpos.top+$('#start-position input:first').height()});
$('#starts-month').click(function (e) {
$('#ends-calendar').hide();
$('#starts-calendar').toggle();
$(StartsCalendar).change(function () {
$('#starts-month').val(StartsCalendar.selection.getMonth()+1);
$('#starts-date').val(StartsCalendar.selection.getDate());
$('#starts-year').val(StartsCalendar.selection.getFullYear());
});
});
var ecpos = $('#end-position').offset();
$('#ends-calendar').hide()
.css({left:ecpos.left,
top:ecpos.top+$('#end-position input:first').height()});
$('#ends-month').click(function (e) {
$('#starts-calendar').hide();
$('#ends-calendar').toggle();
$(EndsCalendar).change(function () {
$('#ends-month').val(EndsCalendar.selection.getMonth()+1);
$('#ends-date').val(EndsCalendar.selection.getDate());
$('#ends-year').val(EndsCalendar.selection.getFullYear());
});
});
if (!wp26) {
jQuery(document).ready( function($) {
postboxes.add_postbox_toggles('admin_page_shopp-promotions-edit');
// close postboxes that should be closed
jQuery('.if-js-closed').removeClass('if-js-closed').addClass('closed');
});
}
if (!promotion) $('#title').focus();
});
</script>
@@ -0,0 +1,114 @@
<div class="wrap shopp">
<h2><?php _e('Promotions','Shopp'); ?></h2>
<form action="<?php echo esc_url($_SERVER['REQUEST_URI']); ?>" id="promotions" method="get">
<div>
<input type="hidden" name="page" value="<?php echo $this->Admin->promotions; ?>" />
</div>
<p id="post-search" class="search-box">
<input type="text" id="promotions-search-input" name="s" class="search-input" value="<?php echo attribute_escape($s); ?>" />
<input type="submit" value="<?php _e('Search Promotions','Shopp'); ?>" class="button" />
</p>
<p><a href="<?php echo esc_url(add_query_arg(array_merge($_GET,array('page'=>$this->Admin->editpromo,'id'=>'new')),$Shopp->wpadminurl."admin.php")); ?>" class="button"><?php _e('New Promotion','Shopp'); ?></a></p>
<div class="tablenav">
<?php if ($page_links) echo "<div class='tablenav-pages'>$page_links</div>"; ?>
<div class="alignleft actions"><button type="submit" id="delete-button" name="deleting" value="promotion" class="button-secondary"><?php _e('Delete','Shopp'); ?></button></div>
<div class="clear"></div>
</div>
<?php if (SHOPP_WP27): ?><div class="clear"></div>
<?php else: ?><br class="clear" /><?php endif; ?>
<table class="widefat" cellspacing="0">
<thead>
<tr><?php shopp_print_column_headers('shopp_page_shopp-promotions'); ?></tr>
</thead>
<?php if (SHOPP_WP27): ?>
<tfoot>
<tr><?php shopp_print_column_headers('shopp_page_shopp-promotions',false); ?></tr>
</tfoot>
<?php endif; ?>
<?php if (sizeof($Promotions) > 0): ?>
<tbody class="list promotions">
<?php
$hidden = array();
if (SHOPP_WP27) $hidden = get_hidden_columns('shopp_page_shopp-promotions');
$even = false;
foreach ($Promotions as $Promotion):
$editurl = add_query_arg(array_merge($_GET,array('page'=>$this->Admin->editpromo,'id'=>$Promotion->id)),$Shopp->wpadminurl."admin.php");
$PromotionName = empty($Promotion->name)?'('.__('no promotion name').')':$Promotion->name;
?>
<tr<?php if (!$even) echo " class='alternate'"; $even = !$even; ?>>
<th scope='row' class='check-column'><input type='checkbox' name='delete[]' value='<?php echo $Promotion->id; ?>' /></th>
<td width="33%" class="name column-name"><a class='row-title' href='<?php echo $editurl; ?>' title='<?php _e('Edit','Shopp'); ?> &quot;<?php echo $PromotionName; ?>&quot;'><?php echo $PromotionName; ?></a>
<div class="row-actions">
<span class='edit'><a href="<?php echo $editurl; ?>" title="<?php _e('Edit','Shopp'); ?> &quot;<?php echo $PromotionName; ?>&quot;"><?php _e('Edit','Shopp'); ?></a> | </span>
<span class='delete'><a class='submitdelete' title='<?php _e('Delete','Shopp'); ?> &quot;<?php echo $PromotionName; ?>&quot;' href='' rel="<?php echo $Promotion->id; ?>"><?php _e('Delete','Shopp'); ?></a></span>
</div>
</td>
<td class="discount column-discount<?php echo in_array('discount',$hidden)?' hidden':''; ?>"><?php
if ($Promotion->type == "Percentage Off") echo percentage($Promotion->discount);
if ($Promotion->type == "Amount Off") echo money($Promotion->discount);
if ($Promotion->type == "Free Shipping") echo $this->Settings->get("free_shipping_text");
if ($Promotion->type == "Buy X Get Y Free") echo __('Buy','Shopp').' '.$Promotion->buyqty.' '.__('Get','Shopp').' '.$Promotion->getqty.' '.__('Free','Shopp');
?></td>
<td class="applied column-applied<?php echo in_array('applied',$hidden)?' hidden':''; ?>"><?php echo $Promotion->scope; ?></td>
<td class="eff column-eff<?php echo in_array('eff',$hidden)?' hidden':''; ?>"><strong><?php echo $status[$Promotion->status]; ?></strong><?php
if (mktimestamp($Promotion->starts > 1) && mktimestamp($Promotion->ends) > 1)
echo "<br />"._d(get_option('date_format'),mktimestamp($Promotion->starts))." &mdash; "._d(get_option('date_format'),mktimestamp($Promotion->ends));
else echo "<br />"._d(get_option('date_format'),mktimestamp($Promotion->created)).", ".__('does not expire','Shopp');
?></td>
</tr>
<?php endforeach; ?>
</tbody>
<?php else: ?>
<tbody><tr><td colspan="5"><?php _e('No promotions found.','Shopp'); ?></td></tr></tbody>
<?php endif; ?>
</table>
</form>
<div class="tablenav">
<?php if ($page_links) echo "<div class='tablenav-pages'>$page_links</div>"; ?>
<div class="clear"></div>
</div>
</div>
<script type="text/javascript">
helpurl = "<?php echo SHOPP_DOCS; ?>Running_Sales_%26_Promotions";
jQuery(document).ready( function() {
var $=jQuery.noConflict();
$('#selectall').change( function() {
$('#promotions th input').each( function () {
if (this.checked) this.checked = false;
else this.checked = true;
});
});
$('a.submitdelete').click(function () {
if (confirm("<?php _e('You are about to delete this promotion!\n \'Cancel\' to stop, \'OK\' to delete.','Shopp'); ?>")) {
$('<input type="hidden" name="delete[]" />').val($(this).attr('rel')).appendTo('#promotions');
$('<input type="hidden" name="deleting" />').val('promotion').appendTo('#promotions');
$('#promotions').submit();
return false;
} else return false;
});
$('#delete-button').click(function() {
if (confirm("<?php echo addslashes(__('Are you sure you want to delete the selected promotions?','Shopp')); ?>")) {
$('<input type="hidden" name="promotions" value="list" />').appendTo($('#promotions'));
return true;
} else return false;
});
<?php if (SHOPP_WP27): ?>
pagenow = 'shopp_page_shopp-promotions';
columns.init(pagenow);
<?php endif; ?>
});
</script>
@@ -0,0 +1,73 @@
<?php
function save_meta_box ($Promotion) {
?>
<div id="misc-publishing-actions">
<label for="discount-status"><input type="hidden" name="status" value="disabled" /><input type="checkbox" name="status" id="discount-status" value="enabled"<?php echo ($Promotion->status == "enabled")?' checked="checked"':''; ?> /> &nbsp;<?php _e('Enabled','Shopp'); ?></label>
<p></p>
<div id="start-position" class="calendar-wrap"><input type="text" name="starts[month]" id="starts-month" title="<?php _e('Month','Shopp'); ?>" size="3" value="<?php echo ($Promotion->starts>1)?date("n",$Promotion->starts):''; ?>" class="selectall" />/<input type="text" name="starts[date]" id="starts-date" title="<?php _e('Day','Shopp'); ?>" size="3" value="<?php echo ($Promotion->starts>1)?date("j",$Promotion->starts):''; ?>" class="selectall" />/<input type="text" name="starts[year]" id="starts-year" title="<?php _e('Year','Shopp'); ?>" size="5" value="<?php echo ($Promotion->starts>1)?date("Y",$Promotion->starts):''; ?>" class="selectall" /></div>
<p><?php _e('Start promotion on this date.','Shopp'); ?></p>
<div id="end-position" class="calendar-wrap"><input type="text" name="ends[month]" id="ends-month" title="<?php _e('Month','Shopp'); ?>" size="3" value="<?php echo ($Promotion->ends>1)?date("n",$Promotion->ends):''; ?>" class="selectall" />/<input type="text" name="ends[date]" id="ends-date" title="<?php _e('Day','Shopp'); ?>" size="3" value="<?php echo ($Promotion->ends>1)?date("j",$Promotion->ends):''; ?>" class="selectall" />/<input type="text" name="ends[year]" id="ends-year" title="<?php _e('Year','Shopp'); ?>" size="5" value="<?php echo ($Promotion->ends>1)?date("Y",$Promotion->ends):''; ?>" class="selectall" /></div>
<p><?php _e('End the promotion on this date.','Shopp'); ?></p>
</div>
<div id="major-publishing-actions">
<input type="submit" class="button-primary" name="save" value="<?php _e('Save Promotion','Shopp'); ?>" />
</div>
<?php
}
add_meta_box('save-promotion', __('Save','Shopp'), 'save_meta_box', 'admin_page_shopp-promotions-edit', 'side', 'core');
function discount_meta_box ($Promotion) {
$types = array(
'Percentage Off' => __('Percentage Off','Shopp'),
'Amount Off' => __('Amount Off','Shopp'),
'Free Shipping' => __('Free Shipping','Shopp'),
'Buy X Get Y Free' => __('Buy X Get Y Free','Shopp')
);
?>
<p><span>
<select name="type" id="discount-type">
<?php echo menuoptions($types,$Promotion->type,true); ?>
</select></span>
<span id="discount-row">
&mdash;
<input type="text" name="discount" id="discount-amount" value="<?php echo $Promotion->discount; ?>" size="10" class="selectall" />
</span>
<span id="beyget-row">
&mdash;
&nbsp;<?php _e('Buy','Shopp'); ?> <input type="text" name="buyqty" id="buy-x" value="<?php echo $Promotion->buyqty; ?>" size="5" class="selectall" /> <?php _e('Get','Shopp'); ?> <input type="text" name="getqty" id="get-y" value="<?php echo $Promotion->getqty; ?>" size="5" class="selectall" />
</span></p>
<p><?php _e('Select the discount type and amount.','Shopp'); ?></p>
<?php
}
add_meta_box('promotion-discount', __('Discount','Shopp'), 'discount_meta_box', 'admin_page_shopp-promotions-edit', 'normal', 'core');
function rules_meta_box ($Promotion) {
$scopes = array(
'Catalog' => __('Catalog','Shopp'),
'Order' => __('Order','Shopp')
);
$scope = '<select name="scope" id="promotion-scope" class="small">';
$scope .= menuoptions($scopes,$Promotion->scope,true);
$scope .= '</select>';
if (empty($Promotion->search)) $Promotion->search = "all";
$logic = '<select name="search" class="small">';
$logic .= menuoptions(array('any'=>__('any','Shopp'),'all' => __('all','Shopp')),$Promotion->search,true);
$logic .= '</select>';
?>
<p><strong><?php printf(__('Apply discount to %s products where %s of these conditions are met','Shopp'),$scope,$logic); ?>:</strong></p>
<table class="form-table" id="rules"></table>
<?php
}
add_meta_box('promotion-rules', __('Conditions','Shopp'), 'rules_meta_box', 'admin_page_shopp-promotions-edit', 'normal', 'core');
?>
@@ -0,0 +1,73 @@
<div class="wrap shopp">
<?php if (!empty($updated)): ?><div id="message" class="updated fade"><p><?php echo $updated; ?></p></div><?php endif; ?>
<h2><?php _e('Checkout Settings','Shopp'); ?></h2>
<form name="settings" id="checkout" action="<?php echo esc_url($_SERVER['REQUEST_URI']); ?>" method="post">
<?php wp_nonce_field('shopp-settings-checkout'); ?>
<?php include("navigation.php"); ?>
<table class="form-table">
<tr class="form-required">
<th scope="row" valign="top"><label for="confirm_url"><?php _e('Order Confirmation','Shopp'); ?></label></th>
<td><input type="radio" name="settings[order_confirmation]" value="ontax" id="order_confirmation_ontax"<?php if($this->Settings->get('order_confirmation') == "ontax") echo ' checked="checked"' ?> /> <label for="order_confirmation_ontax"><?php _e('Show for taxed orders only','Shopp'); ?></label><br />
<input type="radio" name="settings[order_confirmation]" value="always" id="order_confirmation_always"<?php if($this->Settings->get('order_confirmation') == "always") echo ' checked="checked"' ?> /> <label for="order_confirmation_always"><?php _e('Show for all orders','Shopp') ?></label></td>
</tr>
<tr class="form-required">
<th scope="row" valign="top"><label for="receipt_copy_both"><?php _e('Receipt Emails','Shopp'); ?></label></th>
<td><input type="radio" name="settings[receipt_copy]" value="0" id="receipt_copy_customer_only"<?php if ($this->Settings->get('receipt_copy') == "0") echo ' checked="checked"'; ?> /> <label for="receipt_copy_customer_only"><?php _e('Send to Customer Only','Shopp'); ?></label><br />
<input type="radio" name="settings[receipt_copy]" value="1" id="receipt_copy_both"<?php if ($this->Settings->get('receipt_copy') == "1") echo ' checked="checked"'; ?> /> <label for="receipt_copy_both"><?php _e('Send to Customer &amp; Shop Owner Email','Shopp'); ?></label> (<?php _e('see','Shopp'); ?> <a href="?page=shopp-settings"><?php _e('General Settings','Shopp'); ?></a>)</td>
</tr>
<tr class="form-required">
<th scope="row" valign="top"><label for="account-system-none"><?php _e('Customer Accounts','Shopp'); ?></label></th>
<td><input type="radio" name="settings[account_system]" value="none" id="account-system-none"<?php if($this->Settings->get('account_system') == "none") echo ' checked="checked"' ?> /> <label for="account-system-none"><?php _e('No Accounts','Shopp'); ?></label><br />
<input type="radio" name="settings[account_system]" value="shopp" id="account-system-shopp"<?php if($this->Settings->get('account_system') == "shopp") echo ' checked="checked"' ?> /> <label for="account-system-shopp"><?php _e('Enable Account Logins','Shopp'); ?></label><br />
<input type="radio" name="settings[account_system]" value="wordpress" id="account-system-wp"<?php if($this->Settings->get('account_system') == "wordpress") echo ' checked="checked"' ?> /> <label for="account-system-wp"><?php _e('Enable Account Logins integrated with WordPress Accounts','Shopp'); ?></label></td>
</tr>
<tr class="form-required">
<th scope="row" valign="top"><label for="accounting-serial"><?php _e('Next Order Number','Shopp'); ?></label></th>
<td><input type="text" name="settings[next_order_id]" id="accounting-serial" value="<?php echo attribute_escape($next_setting); ?>" size="7" class="selectall" /><br />
<?php _e('Set the next order number to sync with your accounting systems.','Shopp'); ?></td>
</tr>
<tr class="form-required">
<th scope="row" valign="top"><label for="promo-limit"><?php _e('Promotions Limit','Shopp'); ?></label></th>
<td><select name="settings[promo_limit]" id="promo-limit">
<option value="">&infin;</option>
<?php echo menuoptions($promolimit,$this->Settings->get('promo_limit')); ?>
</select>
<label> <?php _e('per order','Shopp'); ?></label>
</td>
</tr>
</table>
<h3><?php _e('Digtal Product Downloads','Shopp')?></h3>
<table class="form-table">
<tr class="form-required">
<th scope="row" valign="top"><label for="download-limit"><?php _e('Download Limit','Shopp'); ?></label></th>
<td><select name="settings[download_limit]" id="download-limit">
<option value="">&infin;</option>
<?php echo menuoptions($downloads,$this->Settings->get('download_limit')); ?>
</select>
</td>
</tr>
<tr class="form-required">
<th scope="row" valign="top"><label for="download-timelimit"><?php _e('Time Limit','Shopp'); ?></label></th>
<td><select name="settings[download_timelimit]" id="download-timelimit">
<option value=""><?php _e('No Limit','Shopp'); ?></option>
<?php echo menuoptions($time,$this->Settings->get('download_timelimit'),true); ?>
</select>
</td>
</tr>
<tr class="form-required">
<th scope="row" valign="top"><label for="download-restriction"><?php _e('IP Restriction','Shopp'); ?></label></th>
<td><input type="hidden" name="settings[download_restriction]" value="off" />
<label for="download-restriction"><input type="checkbox" name="settings[download_restriction]" id="download-restriction" value="ip" <?php echo ($this->Settings->get('download_restriction') == "ip")?'checked="checked" ':'';?> /> <?php _e('Restrict to the computer the product is purchased from','Shopp'); ?></label></td>
</tr>
</table>
<p class="submit"><input type="submit" class="button-primary" name="save" value="<?php _e('Save Changes','Shopp'); ?>" /></p>
</form>
</div>
<script type="text/javascript">
helpurl = "<?php echo SHOPP_DOCS; ?>Checkout_Settings";
</script>
@@ -0,0 +1,6 @@
<ul class="subsubsub">
<?php $i = 0; foreach ($this->Admin->settings as $key => $screen): ?>
<li><a href="?page=<?php echo $screen[0] ?>"<?php if ($_GET['page'] == $screen[0]) echo ' class="current"'; ?>><?php echo $screen[1]; ?></a><?php if (count($this->Admin->settings)-1!=$i++): ?> | <?php endif; ?></li>
<?php endforeach; ?>
</ul>
<br class="clear" />
@@ -0,0 +1,59 @@
<div class="wrap shopp">
<?php if (!empty($updated)): ?><div id="message" class="updated fade"><p><?php echo $updated; ?></p></div><?php endif; ?>
<h2><?php _e('Payments Settings','Shopp'); ?></h2>
<form name="settings" id="payments" action="<?php echo esc_url($_SERVER['REQUEST_URI']); ?>" method="post">
<?php wp_nonce_field('shopp-settings-payments'); ?>
<?php include("navigation.php"); ?>
<table class="form-table">
<tr class="form-required">
<th scope="row" valign="top"><label for="payment-gateway"><?php _e('Payment Gateway','Shopp'); ?></label></th>
<td><select name="settings[payment_gateway]" id="payment-gateway">
<option value=""><?php _e('No On-site Checkout','Shopp'); ?></option>
<?php echo menuoptions($gateways,$payment_gateway,true); ?>
</select><br />
<?php _e('Select the payment gateway processor you will be using to process credit card transactions.','Shopp'); ?></td>
</tr>
<tbody id="payment-settings">
<?php if (is_array($LocalProcessors)) foreach ($LocalProcessors as &$Processor) $Processor->settings(); ?>
</tbody>
<?php if (is_array($XcoProcessors)): foreach ($XcoProcessors as &$Processor): ?>
<tr><?php $Processor->settings(); ?></tr>
<?php endforeach; endif; ?>
</table>
<p class="submit"><input type="submit" class="button-primary" name="save" value="<?php _e('Save Changes','Shopp'); ?>" /></p>
</form>
</div>
<script type="text/javascript">
helpurl = "<?php echo SHOPP_DOCS; ?>Payments_Settings";
function xcosettings (toggle,settings) {
(function($) {
toggle = $(toggle);
settings = $(settings);
if (!toggle.attr('checked')) settings.hide();
toggle.change(function () { settings.slideToggle(250); });
})(jQuery);
}
jQuery(document).ready( function() {
var $=jQuery.noConflict();
var gatewayHandlers = new CallbackRegistry();
<?php foreach ($LocalProcessors as &$Processor) $Processor->registerSettings(); ?>
<?php foreach ($XcoProcessors as &$Processor) $Processor->registerSettings(); ?>
$('#payment-gateway').change(function () {
$('#payment-settings tr').hide();
var target = '#'+gatewayHandlers.get(this.value);
if (this.value.length > 0) $(target).show();
}).change();
});
</script>

Some files were not shown because too many files have changed in this diff Show More