diff --git a/editor/Makefile b/editor/Makefile index 598d3ab6..9b919523 100755 --- a/editor/Makefile +++ b/editor/Makefile @@ -2,8 +2,6 @@ # Source directories srcdir = lib/js -shareddir = ../shared -sharedjsdir = $(shareddir)/js # Output directory builddir = build @@ -17,14 +15,14 @@ deps = $(patsubst %,$(srcdir)/%,$(_deps)) # 'export' step is run) # Removing webL10n for now since we've made local modifications to it that are # yet to be merged upstream -# extdeps = $(shareddir)/webL10n/l10n.js +# extdeps = $(srcdir)/webL10n/l10n.js extdeps = # Modules (these are combined into the library) modules = $(srcdir)/parapara.js \ $(srcdir)/eraser.js \ $(srcdir)/svgClassList.js \ - $(sharedjsdir)/xhr.js + $(srcdir)/xhr.js # File list files = $(modules) $(deps) diff --git a/wall/database/.gitignore b/editor/database/.gitignore similarity index 100% rename from wall/database/.gitignore rename to editor/database/.gitignore diff --git a/editor/database/create.sql b/editor/database/create.sql new file mode 100755 index 00000000..d9262ed8 --- /dev/null +++ b/editor/database/create.sql @@ -0,0 +1,41 @@ +/* Drop tables in appropriate order to maintain constraints */ +DROP TRIGGER IF EXISTS `characters_after_insert`; +DROP TRIGGER IF EXISTS `characters_after_delete`; +DROP TABLE IF EXISTS `changes`; +DROP TABLE IF EXISTS `characters`; + +CREATE TABLE `characters` ( + `charId` int(11) unsigned NOT NULL AUTO_INCREMENT, + `title` varchar(128) DEFAULT NULL, + `author` varchar(128) DEFAULT NULL, + `groundOffset` decimal(4,3) DEFAULT '0.000' COMMENT '0.000 - 1.000', + `width` float DEFAULT NULL COMMENT 'Bounding box width', + `height` float DEFAULT NULL COMMENT 'Bounding box height', + `galleryUrlShort` varchar(40) DEFAULT NULL COMMENT 'Shortened URL for the gallery display of this character', + `createDate` datetime NOT NULL COMMENT 'Creation datetime in UTC', + PRIMARY KEY (`charId`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +/* Audit table */ + +CREATE TABLE `changes` ( + `changeId` int(15) unsigned NOT NULL AUTO_INCREMENT, + `changeType` enum('add-character', 'remove-character') NOT NULL COMMENT 'The type of change', + `contextId` int(11) unsigned DEFAULT NULL COMMENT 'The character ID (or, in future, some other ID) corresponding to the change, if appropriate', + `changeTime` datetime NOT NULL COMMENT 'The time when the change occurred in UTC', + PRIMARY KEY (`changeId`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Audit of changes to walls for live streams of events'; + +/* Audit triggers */ + +/* add-character */ +CREATE TRIGGER `characters_after_insert` AFTER INSERT ON `characters` + FOR EACH ROW + INSERT INTO changes (changeType, contextId, changeTime) + VALUES ('add-character', NEW.charId, UTC_TIMESTAMP()); + +/* remove-character */ +CREATE TRIGGER `characters_after_delete` AFTER DELETE ON `characters` + FOR EACH ROW + INSERT INTO changes (changeType, contextId, changeTime) + VALUES ('remove-character', OLD.charId, UTC_TIMESTAMP()); diff --git a/editor/database/migrate-001.php b/editor/database/migrate-001.php new file mode 100644 index 00000000..c957634c --- /dev/null +++ b/editor/database/migrate-001.php @@ -0,0 +1,96 @@ + 'mysql', + 'username' => 'parapara_migrate', + 'database' => 'parapara', + 'hostspec' => '127.0.0.1' + ); + +/* + * Get database connection + */ +if (is_array($dsn) && !array_key_exists('password', $dsn)) { + $prompt = "Password for `" . $dsn['username'] . "`: "; + $dsn['password'] = _readline($prompt); +} + +$conn =& MDB2::connect($dsn); +if (PEAR::isError($conn)) { + die('Error connecting to DB: ' . $conn->getMessage() + . ', ' . $conn->getDebugInfo()); +} +echo "Connected to database\n"; + +/* + * Get ready for some managing + */ +$conn->loadModule('Manager'); + +/* + * Fix buggy handling of index naming in MySQL + */ +$conn->options['idxname_format'] = '%s'; + +/* + * Do backup + */ +if (is_array($dsn) && $dsn['phptype'] == 'mysql') { + $backup_file = + 'parapara_migrate_' . str_pad(MIGRATE_ID, 3, '0', STR_PAD_LEFT) + . gmdate('_Ymd_His') . '.sql'; + echo "Backing up to $backup_file\n"; + exec("mysqldump -h " . $dsn['hostspec'] . " -u " . $dsn['username'] + . " --password=" . $dsn['password'] . " " . $dsn['database'] + . " > $backup_file"); +} + +/* Drop reference from characters to session ID */ +$constraints = $conn->listTableConstraints('characters'); +if (in_array('characters_ibfk_1', $constraints)) { + ensureOk($conn->dropConstraint('characters', 'characters_ibfk_1')); +} + +function ensureOk($res) { + global $conn; + if (PEAR::isError($res)) { + die($res->getMessage() . ", " . $res->getDebugInfo()); + } +} + +function _readline($prompt) { + if (PHP_OS == 'WINNT') { + echo $prompt; + return stream_get_line(STDIN, 1024, PHP_EOL); + } else { + return readline($prompt); + } +} + +?> diff --git a/shared/js/xhr.js b/editor/lib/js/xhr.js similarity index 100% rename from shared/js/xhr.js rename to editor/lib/js/xhr.js diff --git a/wall/lib/.gitignore b/editor/lib/php/.gitignore similarity index 100% rename from wall/lib/.gitignore rename to editor/lib/php/.gitignore diff --git a/wall/lib/CACerts/cacert.pem b/editor/lib/php/CACerts/cacert.pem similarity index 100% rename from wall/lib/CACerts/cacert.pem rename to editor/lib/php/CACerts/cacert.pem diff --git a/wall/lib/PEAR/.gitignore b/editor/lib/php/PEAR/.gitignore similarity index 100% rename from wall/lib/PEAR/.gitignore rename to editor/lib/php/PEAR/.gitignore diff --git a/wall/lib/PEAR/MDB2.php b/editor/lib/php/PEAR/MDB2.php similarity index 100% rename from wall/lib/PEAR/MDB2.php rename to editor/lib/php/PEAR/MDB2.php diff --git a/wall/lib/PEAR/MDB2/Date.php b/editor/lib/php/PEAR/MDB2/Date.php similarity index 100% rename from wall/lib/PEAR/MDB2/Date.php rename to editor/lib/php/PEAR/MDB2/Date.php diff --git a/wall/lib/PEAR/MDB2/Driver/Datatype/Common.php b/editor/lib/php/PEAR/MDB2/Driver/Datatype/Common.php similarity index 100% rename from wall/lib/PEAR/MDB2/Driver/Datatype/Common.php rename to editor/lib/php/PEAR/MDB2/Driver/Datatype/Common.php diff --git a/wall/lib/PEAR/MDB2/Driver/Datatype/mysql.php b/editor/lib/php/PEAR/MDB2/Driver/Datatype/mysql.php similarity index 100% rename from wall/lib/PEAR/MDB2/Driver/Datatype/mysql.php rename to editor/lib/php/PEAR/MDB2/Driver/Datatype/mysql.php diff --git a/wall/lib/PEAR/MDB2/Driver/Function/Common.php b/editor/lib/php/PEAR/MDB2/Driver/Function/Common.php similarity index 100% rename from wall/lib/PEAR/MDB2/Driver/Function/Common.php rename to editor/lib/php/PEAR/MDB2/Driver/Function/Common.php diff --git a/wall/lib/PEAR/MDB2/Driver/Function/mysql.php b/editor/lib/php/PEAR/MDB2/Driver/Function/mysql.php similarity index 100% rename from wall/lib/PEAR/MDB2/Driver/Function/mysql.php rename to editor/lib/php/PEAR/MDB2/Driver/Function/mysql.php diff --git a/wall/lib/PEAR/MDB2/Driver/Manager/Common.php b/editor/lib/php/PEAR/MDB2/Driver/Manager/Common.php similarity index 100% rename from wall/lib/PEAR/MDB2/Driver/Manager/Common.php rename to editor/lib/php/PEAR/MDB2/Driver/Manager/Common.php diff --git a/wall/lib/PEAR/MDB2/Driver/Manager/mysql.php b/editor/lib/php/PEAR/MDB2/Driver/Manager/mysql.php similarity index 100% rename from wall/lib/PEAR/MDB2/Driver/Manager/mysql.php rename to editor/lib/php/PEAR/MDB2/Driver/Manager/mysql.php diff --git a/wall/lib/PEAR/MDB2/Driver/Native/Common.php b/editor/lib/php/PEAR/MDB2/Driver/Native/Common.php similarity index 100% rename from wall/lib/PEAR/MDB2/Driver/Native/Common.php rename to editor/lib/php/PEAR/MDB2/Driver/Native/Common.php diff --git a/wall/lib/PEAR/MDB2/Driver/Native/mysql.php b/editor/lib/php/PEAR/MDB2/Driver/Native/mysql.php similarity index 100% rename from wall/lib/PEAR/MDB2/Driver/Native/mysql.php rename to editor/lib/php/PEAR/MDB2/Driver/Native/mysql.php diff --git a/wall/lib/PEAR/MDB2/Driver/Reverse/Common.php b/editor/lib/php/PEAR/MDB2/Driver/Reverse/Common.php similarity index 100% rename from wall/lib/PEAR/MDB2/Driver/Reverse/Common.php rename to editor/lib/php/PEAR/MDB2/Driver/Reverse/Common.php diff --git a/wall/lib/PEAR/MDB2/Driver/Reverse/mysql.php b/editor/lib/php/PEAR/MDB2/Driver/Reverse/mysql.php similarity index 100% rename from wall/lib/PEAR/MDB2/Driver/Reverse/mysql.php rename to editor/lib/php/PEAR/MDB2/Driver/Reverse/mysql.php diff --git a/wall/lib/PEAR/MDB2/Driver/mysql.php b/editor/lib/php/PEAR/MDB2/Driver/mysql.php similarity index 100% rename from wall/lib/PEAR/MDB2/Driver/mysql.php rename to editor/lib/php/PEAR/MDB2/Driver/mysql.php diff --git a/wall/lib/PEAR/MDB2/Extended.php b/editor/lib/php/PEAR/MDB2/Extended.php similarity index 100% rename from wall/lib/PEAR/MDB2/Extended.php rename to editor/lib/php/PEAR/MDB2/Extended.php diff --git a/wall/lib/PEAR/MDB2/Iterator.php b/editor/lib/php/PEAR/MDB2/Iterator.php similarity index 100% rename from wall/lib/PEAR/MDB2/Iterator.php rename to editor/lib/php/PEAR/MDB2/Iterator.php diff --git a/wall/lib/PEAR/MDB2/LOB.php b/editor/lib/php/PEAR/MDB2/LOB.php similarity index 100% rename from wall/lib/PEAR/MDB2/LOB.php rename to editor/lib/php/PEAR/MDB2/LOB.php diff --git a/wall/lib/PEAR/Mail.php b/editor/lib/php/PEAR/Mail.php similarity index 100% rename from wall/lib/PEAR/Mail.php rename to editor/lib/php/PEAR/Mail.php diff --git a/wall/lib/PEAR/Mail/RFC822.php b/editor/lib/php/PEAR/Mail/RFC822.php similarity index 100% rename from wall/lib/PEAR/Mail/RFC822.php rename to editor/lib/php/PEAR/Mail/RFC822.php diff --git a/wall/lib/PEAR/Mail/mail.php b/editor/lib/php/PEAR/Mail/mail.php similarity index 100% rename from wall/lib/PEAR/Mail/mail.php rename to editor/lib/php/PEAR/Mail/mail.php diff --git a/wall/lib/PEAR/Mail/mock.php b/editor/lib/php/PEAR/Mail/mock.php similarity index 100% rename from wall/lib/PEAR/Mail/mock.php rename to editor/lib/php/PEAR/Mail/mock.php diff --git a/wall/lib/PEAR/Mail/null.php b/editor/lib/php/PEAR/Mail/null.php similarity index 100% rename from wall/lib/PEAR/Mail/null.php rename to editor/lib/php/PEAR/Mail/null.php diff --git a/wall/lib/PEAR/Mail/sendmail.php b/editor/lib/php/PEAR/Mail/sendmail.php similarity index 100% rename from wall/lib/PEAR/Mail/sendmail.php rename to editor/lib/php/PEAR/Mail/sendmail.php diff --git a/wall/lib/PEAR/Mail/smtp.php b/editor/lib/php/PEAR/Mail/smtp.php similarity index 100% rename from wall/lib/PEAR/Mail/smtp.php rename to editor/lib/php/PEAR/Mail/smtp.php diff --git a/wall/lib/PEAR/Mail/smtpmx.php b/editor/lib/php/PEAR/Mail/smtpmx.php similarity index 100% rename from wall/lib/PEAR/Mail/smtpmx.php rename to editor/lib/php/PEAR/Mail/smtpmx.php diff --git a/wall/lib/PEAR/PEAR.php b/editor/lib/php/PEAR/PEAR.php similarity index 100% rename from wall/lib/PEAR/PEAR.php rename to editor/lib/php/PEAR/PEAR.php diff --git a/wall/lib/PEAR/PEAR5.php b/editor/lib/php/PEAR/PEAR5.php similarity index 100% rename from wall/lib/PEAR/PEAR5.php rename to editor/lib/php/PEAR/PEAR5.php diff --git a/wall/lib/UriUtils.inc b/editor/lib/php/UriUtils.inc similarity index 100% rename from wall/lib/UriUtils.inc rename to editor/lib/php/UriUtils.inc diff --git a/wall/lib/api.inc b/editor/lib/php/api.inc similarity index 55% rename from wall/lib/api.inc rename to editor/lib/php/api.inc index b674e471..d55c170f 100755 --- a/wall/lib/api.inc +++ b/editor/lib/php/api.inc @@ -36,31 +36,4 @@ function getRequestData() { return $json; } -// Looks for either wallId or wallName and returns: -// -// * the corresponding Wall object if found -// * null if either a wallId or wallName was specified but it wasn't found -// * "Not specified" if neither wallId or wallName were specified -function getRequestedWall() { - // Sanitize input - $wallId = toIntOrNull(@$_REQUEST['wallId']); - $wallName = !isset($_REQUEST['wallName']) || - is_null($_REQUEST['wallName']) || - strlen(trim($_REQUEST['wallName'])) == 0 - ? null - : trim($_REQUEST['wallName']); - - // Check if anything was specified - if ($wallId === null && $wallName === null) - return "Not specified"; - - // Try the ID first since it's faster and easier - $wall = Walls::getById($wallId); - if ($wall) - return $wall; - - // Try the path - return Walls::getByPath($wallName); -} - ?> diff --git a/wall/lib/characters.email.inc b/editor/lib/php/characters.email.inc similarity index 100% rename from wall/lib/characters.email.inc rename to editor/lib/php/characters.email.inc diff --git a/wall/lib/characters.file.inc b/editor/lib/php/characters.file.inc similarity index 100% rename from wall/lib/characters.file.inc rename to editor/lib/php/characters.file.inc diff --git a/wall/lib/characters.inc b/editor/lib/php/characters.inc similarity index 66% rename from wall/lib/characters.inc rename to editor/lib/php/characters.inc index 46552cc0..e2ba1c8a 100755 --- a/wall/lib/characters.inc +++ b/editor/lib/php/characters.inc @@ -6,18 +6,18 @@ require_once("parapara.inc"); require_once("exceptions.inc"); +require_once("utils.inc"); require_once("UriUtils.inc"); -require_once("walls.inc"); +require_once("db.inc"); require_once("characters.email.inc"); class Character { private $_charId = null; - private $_wall = null; private $fields = null; private $dirtyFields = array(); static private $virtualFields = - array('rawUrl','galleryUrl', 'emailUrl', 'previewUrl', 'wall'); + array('rawUrl', 'galleryUrl', 'emailUrl', 'previewUrl'); static private $readOnlyFields = array('charId'); @@ -53,10 +53,6 @@ class Character { case 'emailUrl': return Character::getEmailUrl($this->_charId); - - case 'wall': - // We call isset above which will fill this in - return $this->_wall; } return null; @@ -77,12 +73,6 @@ class Character { case 'emailUrl': return CharacterEmailer::isEmailEnabled(); - - case 'wall': - if ($this->_wall === null) { - $this->_wall = Walls::getById($this->wallId); - } - return $this->_wall !== null; } // Semi-virtual fields @@ -135,13 +125,6 @@ class Character { // Sanitize values switch($name) { - case 'active': - $value = (bool)$value; - break; - - case 'x': - $value = self::sanitizeX($value); - break; // If we ever support setting the title and author, we'll need to rewrite // the metadata in the SVG file too @@ -181,14 +164,6 @@ class Character { foreach ($this->dirtyFields as $name) { // Determine the type of the field switch ($name) { - case 'active': - $type = 'boolean'; - break; - - case 'x': - $type = 'integer'; - break; - default: $type = 'text'; break; @@ -196,10 +171,6 @@ class Character { // Determine value to write to database switch ($name) { - case 'x': - $value = floor($this->x * 1000); - break; - default: $value = $this->$name; break; @@ -232,22 +203,13 @@ class Character { self::$virtualFields, self::$readOnlyFields); - // Fields we don't want to export - $keysToDrop = array('wall'); - $result = array(); foreach ($keys as $key) { - if (!in_array($key, $keysToDrop)) { $result[$key] = $this->$key; } - } return $result; } - public function canAdminister() { - return $this->wall->canAdminister(); - } - public static function getCharactersPath() { global $config; return trimTrailingSlash($config['characters']['path']); @@ -255,7 +217,7 @@ class Character { public static function getCharactersFilePath() { // The character path is a relative to the public folder - return realpath(dirname(__FILE__) . '/../public/' . + return realpath(dirname(__FILE__) . '/../../public/' . self::getCharactersPath()); } @@ -326,22 +288,9 @@ abstract class CharacterDeleteMode { } class Characters { - public static function create($svg, $fields, $wallId) { + public static function create($svg, $fields) { global $config; - // Get wall - $wall = Walls::getById($wallId); - if ($wall === null) { - error_log("Wall $wallId not found when adding character"); - throw new KeyedException('wall-not-found', 'Wall not found'); - } - - // Get latest session - $session = $wall->latestSession; - if ($session === null || $session['end'] !== null) { - throw new KeyedException('no-active-session'); - } - // Check SVG if (isset($config['characters']['max_size']) && strlen($svg) > $config['characters']['max_size']) { @@ -360,7 +309,6 @@ class Characters { $fields['width'] = Character::sanitizeWidthOrHeight(@$fields['width']); $fields['height'] = Character::sanitizeWidthOrHeight(@$fields['height']); $date = gmdate('Y-m-d H:i:s'); - $x = floor($wall->getCurrentProgress() * 1000); // Start transaction $conn =& getDbConnection(); @@ -370,19 +318,14 @@ class Characters { // Insert record $query = 'INSERT INTO characters' - . ' (sessionId, wallId, title, author, x, groundOffset, width, height,' - . ' createDate, active)' + . ' (title, author, groundOffset, width, height, createDate)' . ' VALUES ' - . '(' . $conn->quote($session['sessionId'], 'integer') - . ',' . $conn->quote($wallId, 'integer') - . ',' . $conn->quote($fields['title'], 'text') + . '(' . $conn->quote($fields['title'], 'text') . ',' . $conn->quote($fields['author'], 'text') - . ',' . $conn->quote($x, 'integer') . ',' . $conn->quote($fields['groundOffset'], 'decimal') . ',' . $conn->quote($fields['width'], 'float') . ',' . $conn->quote($fields['height'], 'float') . ',' . $conn->quote($date, 'timestamp') - . ',TRUE' // active . ')'; $res =& $conn->exec($query); checkDbResult($res, $conn); @@ -409,7 +352,7 @@ class Characters { // Commit transaction $conn->commit(); - +error_log(Character::getGalleryUrl($charId)); // Store shortened URL for future reference $char = self::getById($charId); if ($char->galleryUrlShort) { @@ -448,17 +391,13 @@ class Characters { private static function dbRowToChar($row) { // Map database fields $data = array(); - $mapping = array('sessionid' => 'sessionId', - 'wallid' => 'wallId', - 'title', + $mapping = array('title', 'author', - 'x', 'groundoffset' => 'groundOffset', 'width', 'height', 'galleryurlshort' => 'galleryUrlShort', - 'createdate' => 'createDate', - 'active' => 'active'); + 'createdate' => 'createDate'); foreach ($mapping as $dbKey => $mdKey) { $dbKey = is_int($dbKey) ? $mdKey : $dbKey; if (!array_key_exists($dbKey, $row)) { @@ -469,10 +408,6 @@ class Characters { } // Process values that need special handling - $data['active'] = (bool)$data['active']; - $data['wallId'] = intval($data['wallId']); - $data['sessionId'] = intval($data['sessionId']); - $data['x'] = intval($data['x']) / 1000; $data['groundOffset'] = floatval($data['groundOffset']); $data['width'] = floatval($data['width']); $data['height'] = floatval($data['height']); @@ -487,82 +422,6 @@ class Characters { return new Character(intval($row['charid']), $data); } - public static function getBySession($wallId, $sessionId) { - // Prepare parameters - $wallId = @intval($wallId); - if ($wallId < 1) - throw new KeyedException('bad-request'); - $sessionId = @intval($sessionId); - if ($sessionId < 1) - throw new KeyedException('bad-request'); - - // Verify IDs are valid - // (We return an empty array if we have valid IDs but no characters but - // return NULL if the IDs are not valid. This is consistent with - // Characters::getById etc. where 'not found' is represented by null) - if (!self::isValidSession($wallId, $sessionId)) - return null; - - // Run query - $conn =& getDbConnection(); - $res =& $conn->query( - 'SELECT * FROM characters' - . ' WHERE wallId = ' . $conn->quote($wallId, 'integer') - . ' AND sessionId = ' . $conn->quote($sessionId, 'integer') - . ' ORDER BY charId'); - $conn->disconnect(); - checkDbResult($res); - - // Prepare result - $result = array(); - $conn->setFetchMode(MDB2_FETCHMODE_ASSOC); - while ($row = $res->fetchRow()) { - array_push($result, self::dbRowToChar($row)); - } - - return $result; - } - - public static function getByWall($wallId) { - // Prepare parameters - $wallId = intval($wallId); - if ($wallId < 1) - throw new KeyedException('bad-request'); - - // Verify wall ID is valid - $wall = Walls::getById($wallId); - if (!$wall) - return null; - - // Run query - $conn =& getDbConnection(); - $res =& $conn->query( - 'SELECT * FROM characters' - . ' WHERE wallId = ' . $conn->quote($wallId, 'integer') - . ' ORDER BY sessionId, charId'); - $conn->disconnect(); - checkDbResult($res); - - // Prepare result - $result = array(); - $session = array(); - $sessionId = null; - $conn->setFetchMode(MDB2_FETCHMODE_ASSOC); - while ($row = $res->fetchRow()) { - if ($sessionId && $sessionId != $row['sessionid']) { - $result[$sessionId] = $session; - $session = array(); - } - array_push($session, self::dbRowToChar($row)); - $sessionId = $row['sessionid']; - } - if ($sessionId) { - $result[$sessionId] = $session; - } - - return $result; - } - public static function deleteById($charId, $deleteMode = CharacterDeleteMode::DeleteAll) { @@ -623,113 +482,6 @@ class Characters { return true; } - - public static function deleteBySession($wallId, $sessionId, - $deleteMode = CharacterDeleteMode::DeleteAll) - { - // _bulkDelete permits a null sessionId (it means, "all sessions for this - // wall"), but this method should be getting called with a null value so we - // handle it here instead - if ($sessionId === null) - throw new KeyedException('bad-request'); - - return self::_bulkDelete($wallId, $sessionId, $deleteMode); - } - - public static function deleteByWall($wallId, - $deleteMode = CharacterDeleteMode::DeleteAll) - { - return self::_bulkDelete($wallId, null, $deleteMode); - } - - protected static function _bulkDelete($wallId, $sessionId, $deleteMode) { - // Prepare parameters - $wallId = intval($wallId); - if ($wallId < 1) - throw new KeyedException('bad-request'); - $sessionId = toIntOrNull($sessionId); - if ($sessionId !== null && $sessionId < 1) - throw new KeyedException('bad-request'); - - // Verify IDs are valid - // (We return zero if we have valid IDs but no characters but - // return NULL if the IDs are not valid.) - if ($sessionId) { - if (!self::isValidSession($wallId, $sessionId)) - return null; - } else { - $wall = Walls::getById($wallId); - if (!$wall) - return null; - } - - // Set up condition for selecting characters - $conn =& getDbConnection(); - $cond = 'wallId = ' . $conn->quote($wallId, 'integer'); - if ($sessionId) { - $cond .= ' AND sessionId = ' . $conn->quote($sessionId, 'integer'); - } - - // Get list of characters to remove - // (We need this so we can delete the corresponding files) - $charIds =& $conn->queryCol('SELECT charId FROM characters WHERE ' . $cond, - 'integer'); - checkDbResult($charIds); - - // Check if this session/wall is already empty - if (count($charIds) === 0) - return 0; - - // Start transaction - $trans = $conn->beginTransaction(); - checkDbResult($trans); - - // Delete records - $res =& $conn->exec('DELETE FROM characters WHERE ' . $cond); - checkDbResult($res, $conn); - $rowsAffected = $res; - - // Delete corresponding SVG files - if ($deleteMode === CharacterDeleteMode::DeleteAll) { - $deleter = new BatchFileDeleter(); - foreach ($charIds as $charId) { - $filename = Character::getFileForId($charId); - if (!$deleter->deleteFile($filename)) { - $deleter->rollback(); - $conn->rollback(); - error_log("Failed to delete file: $filename"); - throw new KeyedException('server-error', "Failed to delete file"); - } - - // Delete the preview file too. - // - // If this fails we don't care. And if we have a failure later on, - // there's no need to restore these files since they will be - // auto-generated anyway. - $preview = Character::getPreviewFile($charId); - @unlink($preview); - } - $deleter->commit(); - } - - // Commit transaction - $conn->commit(); - - return $rowsAffected; - } - - private static function isValidSession($wallId, $sessionId) { - $conn =& getDbConnection(); - $res =& $conn->query( - 'SELECT sessionId FROM sessions ' - . ' WHERE wallId = ' . $conn->quote($wallId, 'integer') - . ' AND sessionId = ' . $conn->quote($sessionId, 'integer') - . ' LIMIT 1'); - checkDbResult($res); - $validSession = $res->numRows() !== 0; - $res->free(); - return $validSession; - } } // A helper class that deletes a series of files in such a way that the whole diff --git a/wall/lib/config.inc.sample b/editor/lib/php/config.inc.sample similarity index 100% rename from wall/lib/config.inc.sample rename to editor/lib/php/config.inc.sample diff --git a/wall/lib/config.test.inc.sample b/editor/lib/php/config.test.inc.sample similarity index 100% rename from wall/lib/config.test.inc.sample rename to editor/lib/php/config.test.inc.sample diff --git a/wall/lib/db.inc b/editor/lib/php/db.inc similarity index 100% rename from wall/lib/db.inc rename to editor/lib/php/db.inc diff --git a/editor/lib/php/editor-util.inc b/editor/lib/php/editor-util.inc deleted file mode 100644 index 93fc017b..00000000 --- a/editor/lib/php/editor-util.inc +++ /dev/null @@ -1,40 +0,0 @@ -editorStylesheet === null) - return null; - - // Construct URL to stylesheet - // XXX Rename upload_server to wall_server - $server_path = $config['editor']['upload_server']; - // Make sure server doesn't ends with a / - if (substr($server_path, -1) == "/") - $server_path = substr($server_path, 0, -1); - return $server_path . $design->editorStylesheet; -} -?> diff --git a/wall/lib/exceptions.inc b/editor/lib/php/exceptions.inc similarity index 100% rename from wall/lib/exceptions.inc rename to editor/lib/php/exceptions.inc diff --git a/wall/lib/parapara.inc b/editor/lib/php/parapara.inc similarity index 100% rename from wall/lib/parapara.inc rename to editor/lib/php/parapara.inc diff --git a/wall/lib/template.inc b/editor/lib/php/template.inc similarity index 100% rename from wall/lib/template.inc rename to editor/lib/php/template.inc diff --git a/wall/lib/utils.inc b/editor/lib/php/utils.inc similarity index 100% rename from wall/lib/utils.inc rename to editor/lib/php/utils.inc diff --git a/editor/public/api/.htaccess b/editor/public/api/.htaccess new file mode 100755 index 00000000..d85df6e5 --- /dev/null +++ b/editor/public/api/.htaccess @@ -0,0 +1,17 @@ +Options -Indexes + + order allow,deny + deny from all + + + + RewriteEngine On + RewriteCond %{REQUEST_FILENAME} !-f + RewriteCond %{REQUEST_FILENAME} !-d + RewriteBase /api/ + # Character upload/management + RewriteRule ^characters$ _characters.php [L] + RewriteRule ^characters/([0-9]+)$ _characters.php?charId=$1 [L] + # Character email + RewriteRule ^characters/([0-9]+)/email$ _character_email.php?charId=$1 [L] + diff --git a/wall/public/api/_character_email.php b/editor/public/api/_character_email.php similarity index 93% rename from wall/public/api/_character_email.php rename to editor/public/api/_character_email.php index d1643270..881f7b5c 100644 --- a/wall/public/api/_character_email.php +++ b/editor/public/api/_character_email.php @@ -3,7 +3,7 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. */ -require_once('../../lib/parapara.inc'); +require_once('../../lib/php/parapara.inc'); require_once('api.inc'); require_once('characters.inc'); diff --git a/wall/public/api/_characters.php b/editor/public/api/_characters.php similarity index 68% rename from wall/public/api/_characters.php rename to editor/public/api/_characters.php index 3fc5ad16..361f7e30 100644 --- a/wall/public/api/_characters.php +++ b/editor/public/api/_characters.php @@ -3,11 +3,10 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. */ -require_once('../../lib/parapara.inc'); +require_once('../../lib/php/parapara.inc'); require_once('api.inc'); require_once('utils.inc'); require_once('characters.inc'); -require_once('login.inc'); // We allow uploading characters from anywhere, so setup CORS headers as needed if ($_SERVER['REQUEST_METHOD'] == 'POST' || @@ -23,20 +22,14 @@ // Normal request (not OPTIONS) header('Content-Type: application/json; charset=UTF-8'); -// Get wall -$wall = getRequestedWall(getUserEmail()); - // Parse input $data = getRequestData(); switch ($_SERVER['REQUEST_METHOD']) { case 'POST': - if (!$wall || $wall == "Not specified") { - bailWithError('no-wall'); - } $fields = $data["metadata"]; $svg = $data["svg"]; - $char = Characters::create($svg, $fields, $wall->wallId); + $char = Characters::create($svg, $fields); $result = $char->asArray(); // Hide email URL field if emailing is not available @@ -45,27 +38,6 @@ } break; - case 'GET': - if (!$wall || $wall == "Not specified") { - bailWithError('no-wall'); - } - $sessionId = array_key_exists('sessionId', $_REQUEST) - ? intval($_REQUEST['sessionId']) : null; - $flatten = create_function('$char', 'return $char->asArray();'); - if ($sessionId) { - $characters = Characters::getBySession($wall->wallId, $sessionId); - if ($characters === null) { - bailWithError('session-not-found'); - } - $result = array_map($flatten, $characters); - } else { - $result = $wall->getSessions("Include characters"); - foreach($result as &$session) { - $session['characters'] = array_map($flatten, $session['characters']); - } - } - break; - case 'PUT': case 'PATCH': // Check we are logged in diff --git a/wall/public/characters/.gitignore b/editor/public/characters/.gitignore similarity index 100% rename from wall/public/characters/.gitignore rename to editor/public/characters/.gitignore diff --git a/wall/public/characters/.htaccess b/editor/public/characters/.htaccess similarity index 89% rename from wall/public/characters/.htaccess rename to editor/public/characters/.htaccess index 3cd74c0d..ceb65970 100644 --- a/wall/public/characters/.htaccess +++ b/editor/public/characters/.htaccess @@ -1,4 +1,4 @@ -Options ExecCGI +FollowSymLinks Includes -MultiViews +Options +ExecCGI +FollowSymLinks +Includes -MultiViews DirectorySlash Off RewriteEngine on RewriteRule ^(\d+)$ gallery.php?id=$1 [L] diff --git a/wall/public/characters/gallery.php b/editor/public/characters/gallery.php similarity index 93% rename from wall/public/characters/gallery.php rename to editor/public/characters/gallery.php index 2c9ecd6d..f3dba306 100755 --- a/wall/public/characters/gallery.php +++ b/editor/public/characters/gallery.php @@ -4,15 +4,17 @@ * You can obtain one at http://mozilla.org/MPL/2.0/. */ -require_once("../../lib/parapara.inc"); +require_once("../../lib/php/parapara.inc"); require_once("db.inc"); require_once("characters.inc"); -require_once("walls.inc"); // Check for a valid ID $id = intval($_REQUEST['id']); if ($id < 1 || !@file_exists($id . '.svg')) { $filename = "sad-face.svg"; + $previewUrl = null; + $title = null; + $desc = null; } else { // Load the SVG $filename = $id . '.svg'; @@ -36,13 +38,9 @@ if ($char->createDate) { $createDate = strtotime($char->createDate); } - $wall = $char->wall; $previewUrl = $char->previewUrl; $rawUrl = $char->rawUrl; } - if ($wall) { - $eventName = $wall->name; - } } catch (KeyedException $e) { } } ?> @@ -55,7 +53,7 @@ - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/wall/public/designs/picture-frame/editor/editor.css b/wall/public/designs/picture-frame/editor/editor.css deleted file mode 100644 index 4bf8c3b0..00000000 --- a/wall/public/designs/picture-frame/editor/editor.css +++ /dev/null @@ -1,4 +0,0 @@ -div.canvas-background { - background-color: lightgrey; - background-image: none; -} diff --git a/wall/public/designs/picture-frame/images/kaminarimon.jpg b/wall/public/designs/picture-frame/images/kaminarimon.jpg deleted file mode 100644 index af947a07..00000000 Binary files a/wall/public/designs/picture-frame/images/kaminarimon.jpg and /dev/null differ diff --git a/wall/public/designs/picture-frame/images/shibuya.jpg b/wall/public/designs/picture-frame/images/shibuya.jpg deleted file mode 100644 index ce29f1e1..00000000 Binary files a/wall/public/designs/picture-frame/images/shibuya.jpg and /dev/null differ diff --git a/wall/public/designs/picture-frame/images/skytree.jpg b/wall/public/designs/picture-frame/images/skytree.jpg deleted file mode 100644 index cf8d0c7b..00000000 Binary files a/wall/public/designs/picture-frame/images/skytree.jpg and /dev/null differ diff --git a/wall/public/designs/picture-frame/preview/picture-frame.png b/wall/public/designs/picture-frame/preview/picture-frame.png deleted file mode 100644 index 94f27401..00000000 Binary files a/wall/public/designs/picture-frame/preview/picture-frame.png and /dev/null differ diff --git a/wall/public/designs/picture-frame/wall.svg b/wall/public/designs/picture-frame/wall.svg deleted file mode 100644 index 7b84e98e..00000000 --- a/wall/public/designs/picture-frame/wall.svg +++ /dev/null @@ -1,204 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/wall/public/designs/space/editor/editor.css b/wall/public/designs/space/editor/editor.css deleted file mode 100644 index bd706f2f..00000000 --- a/wall/public/designs/space/editor/editor.css +++ /dev/null @@ -1,9 +0,0 @@ -div.canvas-background { - background-color: black; - background: url('jimen.png') left bottom repeat-x, - url('space-bg.jpg') black; - background-size: auto 9%, cover; -} -#anim-controls .overlay-shading { - fill: white; -} diff --git a/wall/public/designs/space/editor/jimen.png b/wall/public/designs/space/editor/jimen.png deleted file mode 100644 index 4e63ad1b..00000000 Binary files a/wall/public/designs/space/editor/jimen.png and /dev/null differ diff --git a/wall/public/designs/space/editor/space-bg.jpg b/wall/public/designs/space/editor/space-bg.jpg deleted file mode 100644 index 82cc76a2..00000000 Binary files a/wall/public/designs/space/editor/space-bg.jpg and /dev/null differ diff --git a/wall/public/designs/space/images/back01.jpg b/wall/public/designs/space/images/back01.jpg deleted file mode 100755 index bfc2b5b3..00000000 Binary files a/wall/public/designs/space/images/back01.jpg and /dev/null differ diff --git a/wall/public/designs/space/images/back02.jpg b/wall/public/designs/space/images/back02.jpg deleted file mode 100755 index a5bb6ddb..00000000 Binary files a/wall/public/designs/space/images/back02.jpg and /dev/null differ diff --git a/wall/public/designs/space/images/ground.png b/wall/public/designs/space/images/ground.png deleted file mode 100755 index 0da7e209..00000000 Binary files a/wall/public/designs/space/images/ground.png and /dev/null differ diff --git a/wall/public/designs/space/images/naka.png b/wall/public/designs/space/images/naka.png deleted file mode 100755 index bee54847..00000000 Binary files a/wall/public/designs/space/images/naka.png and /dev/null differ diff --git a/wall/public/designs/space/images/oku.png b/wall/public/designs/space/images/oku.png deleted file mode 100755 index 097ef78e..00000000 Binary files a/wall/public/designs/space/images/oku.png and /dev/null differ diff --git a/wall/public/designs/space/images/temae.png b/wall/public/designs/space/images/temae.png deleted file mode 100755 index 8dac3652..00000000 Binary files a/wall/public/designs/space/images/temae.png and /dev/null differ diff --git a/wall/public/designs/space/js/wall.js b/wall/public/designs/space/js/wall.js deleted file mode 100644 index d085b67f..00000000 --- a/wall/public/designs/space/js/wall.js +++ /dev/null @@ -1,137 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this file, - * You can obtain one at http://mozilla.org/MPL/2.0/. */ - -function initialize(Wall, wallData, design, $) { - - var SpaceWall = Wall.extend({ - // Debug wall - // - // Shows wall progress for debugging positioning - debug: false, - - init: function(doc, wallData) { - // Add debugging output if necessary - if (this.debug) { - updateProgress(this, doc); - } - - // Work out timing from template - this.planetDurationMs = - document.getElementById("time-base").getSimpleDuration() * 1000; - this.charDurationMs = - document.getElementById("char-time-base").getSimpleDuration() * 1000; - - this._super(doc, wallData); - }, - - getTemplateFields: function(character) { - var fields = this._super(character); - - // Calculate the timing for when the character should make its debut. This - // is a bit tricky because we have two animations going in different - // directions: the spinning planet and the walking characters. - // - // Normally we set the begin time as follows: - // - // begin = character.x * this.wallData.defaultDuration - // - // Or, replacing 'character.x' with just 'x', and - // 'this.wallData.defaultDuration' with just 'planetDuration' we have: - // - // begin = x * planetDuration - // - // HOWEVER, that fails to take into account that the path we're putting - // the characters on to is moving in the opposite direction. In effect we - // have to push the characters out "sooner" to compensate for the opposing - // rotation of the path. - // - // How much sooner? Basically, we subtract the amount of time the planet - // would have moved in the opposite direction while the character was - // waiting to start which is basically: - // - // x * (characterDuration / planetDuration) * planetDuration - // - // Let's call the rate of the character movement to the rate of the - // planet, simply the "rate" as follows: - // - var rate = this.charDurationMs / this.planetDurationMs; - // - // Then, the amount we need to subtract is just: - // - // x * rate * planetDuration - // - // So our begin time is: - // - // begin = x * planetDuration - x * rate * planetDuration - // = x * planetDuration * (1 - rate) - // - // Then, finally, we have to make some slight tweaks so that the character - // is ready for its debut. When the server receives a new character it - // records the current position of the wall as the character's x position. - // - // However, it may take a second or two from that point until we receive - // the character and finish downloading the SVG character. So, we add - // a little to the character's x value to allow time for the character to - // get ready. - // - // Call this the start delay: - // - var startDelay = 0.008; - // - // All that gives us: - // - fields.begin = (character.x + startDelay) * - this.planetDurationMs * - (1 - rate); - fields.beginStr = fields.begin / 1000 + "s"; - - // Now to calculate the range where an individual animation should be - // turned on. - // - // I did all sorts of complex maths for this an some how it all cancelled - // out to something really simply. - // - // Basically, we have the follow two constants which are empirically - // derived based on the shape of the path. If you change the ratio of the - // character animation to the planet these will likely need fixing. - // - // Firstly, in some sections of the path the characters need to be turned - // on a bit sooner since the path is irregular. This is the shift forwards - // factor: - var shiftForwards = 0.04; - - // That lets us calculate when the character is ready to hit the stage as - // follows: - var debut = Math.max((character.x - shiftForwards) * rate, 0); - - // Then we have to decide how long to keep them there and the following - // seems to be about right: - var displayLength = 0.08; - - // Then just set up the key times: - fields.displayKeyTimes = - "0; " + - debut.toFixed(3) + "; " + - Number(debut + displayLength).toFixed(3); - - return fields; - }, - }); - - /* - * Debugging functionality to show the current wall progress - */ - function updateProgress(wall, doc) { - var progress = doc.getElementById("progress-debug"); - if (progress) { - progress.setAttribute("display", "block"); - progress.textContent = Number(wall.getWallProgress() * 1000).toFixed(0); - } - window.setTimeout(function() { updateProgress(wall, doc); }, 500); - } - - return SpaceWall; -} - -document.initialize = initialize; diff --git a/wall/public/designs/space/main.js b/wall/public/designs/space/main.js deleted file mode 100755 index dee370d4..00000000 --- a/wall/public/designs/space/main.js +++ /dev/null @@ -1,148 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this file, - * You can obtain one at http://mozilla.org/MPL/2.0/. */ - -var CHARACTER_WIDTH = 300; -var CHARACTER_HEIGHT = 300; -var CHARACTER_DURATION = 20; // sec - -// Maximum number of "old" characters to show. That is, we always show newly -// added characters, even if 100 come it at one time. -// We apply this threshold and drop characters when: -// * Characters have been shown the minimum number of times, or -// * When getting the initial list of characters from the server (for characters -// that have already been displayed in the past). -var NUM_CHARACTERS_THRESHOLD = 35; - -// Number of times to show a character before shrinking it -var NUM_ITERATIONS_AT_FULL_SIZE = 2; - -// Minimum number of times to show a character shrunk or faded before it can be -// dropped -var MIN_NUM_ITERATIONS_AT_REDUCED_SIZE = 1; - -var Main = { - - SVG_NS: "http://www.w3.org/2000/svg", - XLINK_NS: "http://www.w3.org/1999/xlink", - - start: function() { - Main.timebase = document.getElementById("time-base"); - Main.main_layer = document.getElementById("main-layer"); - Main.main_layer_path = document.getElementById("main-layer-path"); - Database.start(Main.timebase, Main.showCharacter); - }, - - showCharacter: function(character, currentActiveTime, - currentSimpleTime, currentRate, durationRate) { - var ANIMATE_RANGE = 0.5; - - // Start is the offset into the motion path at which to start animations for - // the current time. We set it to -1 and then calculate it for the first - // animation that is ready to be appended. After that, we just re-use the - // same value. - var start = -1; - - // Start diff is the amount of tweaking we have to do to get a start value - // that's off the screen. - var startdiff = 0; - - // Create a group to wrap the character and its animation - var g = document.createElementNS(Main.SVG_NS, "g"); - g.setAttribute("id", character.id); - - // Create the character image - var image = document.createElementNS(Main.SVG_NS, "image"); - var imageid = character.id + "-image"; - image.setAttribute("id", imageid); - image.setAttributeNS(Main.XLINK_NS, "href", character.uri); - image.setAttribute("width", CHARACTER_WIDTH); - image.setAttribute("height", CHARACTER_HEIGHT); - - if (!character.repeatCount) { - character.repeatCount = 0; - } - var imageTransform = ""; - if (character.repeatCount >= NUM_ITERATIONS_AT_FULL_SIZE) { - // Shrink character in half - var actualWidth = CHARACTER_WIDTH / 2; - var actualHeight = CHARACTER_HEIGHT / 2; - imageTransform = - "translate(-" + actualWidth/2 + " -"+(actualHeight-20)+") " + - "scale(0.5)"; - } else { - imageTransform = - "translate(-"+CHARACTER_WIDTH/2+" -"+(CHARACTER_HEIGHT-20)+")"; - } - image.setAttribute("transform", imageTransform); - g.appendChild(image); - - // Add a shadow to the character - var use = document.createElementNS(Main.SVG_NS, "use"); - use.setAttribute("transform", "matrix(1 0 0 -0.5 0 0)"); - use.setAttribute("filter", "url(#shadow)"); - use.setAttributeNS(Main.XLINK_NS, "href", "#"+imageid); - g.appendChild(use); - - // Create the animation - var animateMotion = document.createElementNS(Main.SVG_NS, "animateMotion"); - animateMotion.setAttribute("dur", - Math.round(CHARACTER_DURATION*durationRate)+"s"); - animateMotion.setAttribute("rotate", "auto"); - animateMotion.setAttribute("begin", currentActiveTime+"s"); - animateMotion.setAttribute("repeatCount", "1"); - animateMotion.setAttribute("calcMode", "linear"); - var mpath = document.createElementNS(Main.SVG_NS, "mpath"); - mpath.setAttributeNS(Main.XLINK_NS, "href", "#main-layer-path"); - animateMotion.appendChild(mpath); - - // When the animation finishes, remove the character - animateMotion.addEventListener("endEvent", function(e) { - var gElement = e.originalTarget.parentNode; - gElement.parentNode.removeChild(gElement); - }, true); - - // Find the point on the path to start the animation so that it will - // appear just off-screen - if (start == -1) { - start = (1-currentRate); - var matrix = Main.main_layer_path.getScreenCTM(); - for (;;) { - var point = - Main.main_layer_path.getPointAtLength(start). - matrixTransform(matrix); -// console.log("-- "+start+" : "+point.x+","+point.y+" --"); - if (point.x > window.innerWidth) { - break; - } - start += 0.01; - startdiff += 0.01; - if (start > 1) { - start -= 1; - } - } - } - // Since we animate in the opposite direction to the path, we subtract the - // range of the animation from the start value. - var end = start - ANIMATE_RANGE + startdiff; - if (end >= 0) { -// console.error(start+";"+end); - animateMotion.setAttribute("keyPoints", start+";"+end); - animateMotion.setAttribute("keyTimes", "0;1"); - } else { - var startRate = start*(1/ANIMATE_RANGE); -// console.error(start+";0;1;"+(end+1)); -// console.error("0;"+startRate+";"+startRate+";1"); - animateMotion.setAttribute("keyPoints", start+";0;1;"+(end+1)); - animateMotion.setAttribute("keyTimes", - "0;"+startRate+";"+startRate+";1"); - } - - // Add the animation to the group, then add the group to the scene - g.appendChild(animateMotion); - Main.main_layer.appendChild(g); - - // Update the character's status so we don't add it again - character.repeatCount++; - } -} diff --git a/wall/public/designs/space/preview/space.mp4 b/wall/public/designs/space/preview/space.mp4 deleted file mode 100644 index 5fb5fa74..00000000 Binary files a/wall/public/designs/space/preview/space.mp4 and /dev/null differ diff --git a/wall/public/designs/space/preview/space.png b/wall/public/designs/space/preview/space.png deleted file mode 100644 index 76d3a754..00000000 Binary files a/wall/public/designs/space/preview/space.png and /dev/null differ diff --git a/wall/public/designs/space/preview/space.webm b/wall/public/designs/space/preview/space.webm deleted file mode 100644 index e3a97e46..00000000 Binary files a/wall/public/designs/space/preview/space.webm and /dev/null differ diff --git a/wall/public/designs/space/wall.svg b/wall/public/designs/space/wall.svg deleted file mode 100644 index dffd04db..00000000 --- a/wall/public/designs/space/wall.svg +++ /dev/null @@ -1,106 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 50% - diff --git a/wall/public/designs/wa/editor/editor.css b/wall/public/designs/wa/editor/editor.css deleted file mode 100644 index 91d85257..00000000 --- a/wall/public/designs/wa/editor/editor.css +++ /dev/null @@ -1,13 +0,0 @@ -div.canvas-background { - background-image: none; - /* Fallback for older browsers */ - background-color: white; - /* Fallback syntax for WebKit which doesn't do four-value syntax yet (WebKit - * bug 37514) */ - background: url('mountains.jpg') left top repeat-x, - white; - /* Full effect */ - background: url('mountains.jpg') left 10% top repeat-x, - white; - background-size: auto 100%, auto 60%; -} diff --git a/wall/public/designs/wa/editor/mountains.jpg b/wall/public/designs/wa/editor/mountains.jpg deleted file mode 100644 index e22577ba..00000000 Binary files a/wall/public/designs/wa/editor/mountains.jpg and /dev/null differ diff --git a/wall/public/designs/wa/editor/tree.png b/wall/public/designs/wa/editor/tree.png deleted file mode 100644 index 6dd80678..00000000 Binary files a/wall/public/designs/wa/editor/tree.png and /dev/null differ diff --git a/wall/public/designs/wa/images/layer1.jpg b/wall/public/designs/wa/images/layer1.jpg deleted file mode 100755 index 5cd58b12..00000000 Binary files a/wall/public/designs/wa/images/layer1.jpg and /dev/null differ diff --git a/wall/public/designs/wa/images/layer2.jpg b/wall/public/designs/wa/images/layer2.jpg deleted file mode 100755 index d03539c2..00000000 Binary files a/wall/public/designs/wa/images/layer2.jpg and /dev/null differ diff --git a/wall/public/designs/wa/images/layer3.png b/wall/public/designs/wa/images/layer3.png deleted file mode 100755 index 0be8bd33..00000000 Binary files a/wall/public/designs/wa/images/layer3.png and /dev/null differ diff --git a/wall/public/designs/wa/js/wall.js b/wall/public/designs/wa/js/wall.js deleted file mode 100644 index d91dcc3d..00000000 --- a/wall/public/designs/wa/js/wall.js +++ /dev/null @@ -1,30 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this file, - * You can obtain one at http://mozilla.org/MPL/2.0/. */ - -function initialize(Wall, wallData, design, $) { - - var WaWall = Wall.extend({ - getTemplateFields: function(character) { - var fields = this._super(character); - - // Position character - var yOfCharacter = 700 - 700 * character.groundOffset - character.height; - fields.charTransform = "translate(0, " + yOfCharacter + ")"; - - // Position shadow - var ymat = character.height * 1.5 - 2; - fields.useTransform = "matrix(1 0 0 -0.5 0 " + ymat + ")"; - - // Extra positioning value so we make sure the animation continues until - // at least the end of the screen - fields.rightEdge = 1280 + character.width; - - return fields; - }, - }); - - return WaWall; -} - -document.initialize = initialize; diff --git a/wall/public/designs/wa/main.js b/wall/public/designs/wa/main.js deleted file mode 100755 index 48bedd6a..00000000 --- a/wall/public/designs/wa/main.js +++ /dev/null @@ -1,112 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this file, - * You can obtain one at http://mozilla.org/MPL/2.0/. */ - -var CHARACTER_WIDTH = 300; -var CHARACTER_HEIGHT = 300; -var CHARACTER_DURATION = 30; // sec - -// Maximum number of "old" characters to show. That is, we always show newly -// added characters, even if 100 come it at one time. -// We apply this threshold and drop characters when: -// * Characters have been shown the minimum number of times, or -// * When getting the initial list of characters from the server (for characters -// that have already been displayed in the past). -var NUM_CHARACTERS_THRESHOLD = 35; - -// Number of times to show a character before shrinking/fading it -var NUM_ITERATIONS_AT_FULL_SIZE = 2; - -// Minimum number of times to show a character shrunk or faded before it can be -// dropped -var MIN_NUM_ITERATIONS_AT_REDUCED_SIZE = 1; - -var Main = { - - start: function() { - Main.timebase = document.getElementById("time-base"); - Main.main_layer = document.getElementById("main-layer"); - Database.start(Main.timebase, Main.showCharacter); }, - - showCharacter: function(character, currentActiveTime, currentSimpleTime, - currentRate, durationRate) { - // Create a group to wrap the character and its animation - var g = document.createElementNS("http://www.w3.org/2000/svg", "g"); - g.setAttribute("id", character.id); - //bounds of image - var wOfBounding = character.width; - var hOfBounding = character.height; - - if (character.isNew == true) { - // displays author name if the character is new. - var authorText = - document.createElementNS("http://www.w3.org/2000/svg", "text"); - var text = character.author ? character.author : "NEW!"; - text += " : "; - text += character.title ? character.title : "untitled"; - authorText.textContent = text; - - authorText.setAttribute("font-family", "helvetica"); - authorText.setAttribute("font-size", "40"); - authorText.setAttribute("text-anchor", "middle"); - authorText.setAttribute("x", wOfBounding/2); - g.appendChild(authorText); - } - - // Create the character image - var image = - document.createElementNS("http://www.w3.org/2000/svg", "image"); - var imageid = character.id+"i"; - image.setAttribute("id", imageid); - image.setAttributeNS("http://www.w3.org/1999/xlink", "href", character.uri); - image.setAttribute("width", wOfBounding); - image.setAttribute("height", hOfBounding); - image.setAttribute("overflow", "visible"); - var yOfCharacter = 700 - 700*character.groundOffset-hOfBounding; - g.setAttribute("transform", "translate(0, "+yOfCharacter+")"); - g.appendChild(image); - - // Add a shadow to the character - var use = document.createElementNS("http://www.w3.org/2000/svg", "use"); - // Position the shadow below the image - // We use a measure of 1.5 times the height: - // - 1 for the height of the character, - // - 0.5 for the height of the shadow. - // The extra 2 is just so the shape overlaps the shadow *just* a little - var ymat = hOfBounding * 1.5 - 2; - use.setAttribute("transform", "matrix(1 0 0 -0.5 0 "+ymat+")"); - use.setAttribute("filter", "url(#shadow)"); - use.setAttributeNS("http://www.w3.org/1999/xlink", "href", "#"+imageid); - // Add shadow *behind* character - g.insertBefore(use, image); - - // Create the animation - var animateMotion = - document.createElementNS("http://www.w3.org/2000/svg", "animateMotion"); - animateMotion.setAttribute("dur", - Math.round(CHARACTER_DURATION * durationRate)+"s"); - animateMotion.setAttribute("begin", currentActiveTime+"s"); - animateMotion.setAttribute("calcMode", "linear"); - animateMotion.setAttribute("repeatCount", "1"); - animateMotion.setAttribute("fill", "freeze"); - animateMotion.setAttribute("attributeName", "transform"); - animateMotion.setAttribute("type", "transform"); - animateMotion.setAttribute("rotate", "auto"); - animateMotion.setAttribute("from", (-CHARACTER_WIDTH)+" 0"); - animateMotion.setAttribute("to", "1280 0"); - - // When the animation finishes, remove the character - animateMotion.addEventListener("endEvent", function(e) { - var gElement = e.originalTarget.parentNode; - gElement.parentNode.removeChild(gElement); - }, true); - - // Add the animation to the group, then add the group to the scene - g.appendChild(animateMotion); - Main.main_layer.appendChild(g); - - // Update the character's status so we don't add it again - character.repeatCount++; - } - -} diff --git a/wall/public/designs/wa/preview/wa.mp4 b/wall/public/designs/wa/preview/wa.mp4 deleted file mode 100644 index 69a837b9..00000000 Binary files a/wall/public/designs/wa/preview/wa.mp4 and /dev/null differ diff --git a/wall/public/designs/wa/preview/wa.png b/wall/public/designs/wa/preview/wa.png deleted file mode 100644 index a99307db..00000000 Binary files a/wall/public/designs/wa/preview/wa.png and /dev/null differ diff --git a/wall/public/designs/wa/preview/wa.webm b/wall/public/designs/wa/preview/wa.webm deleted file mode 100644 index ee26b146..00000000 Binary files a/wall/public/designs/wa/preview/wa.webm and /dev/null differ diff --git a/wall/public/designs/wa/wall.svg b/wall/public/designs/wa/wall.svg deleted file mode 100644 index ecbc347a..00000000 --- a/wall/public/designs/wa/wall.svg +++ /dev/null @@ -1,70 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/wall/public/designs/world-pictures/editor/editor.css b/wall/public/designs/world-pictures/editor/editor.css deleted file mode 100644 index 4bf8c3b0..00000000 --- a/wall/public/designs/world-pictures/editor/editor.css +++ /dev/null @@ -1,4 +0,0 @@ -div.canvas-background { - background-color: lightgrey; - background-image: none; -} diff --git a/wall/public/designs/world-pictures/images/arc-fg.png b/wall/public/designs/world-pictures/images/arc-fg.png deleted file mode 100644 index b631a7bb..00000000 Binary files a/wall/public/designs/world-pictures/images/arc-fg.png and /dev/null differ diff --git a/wall/public/designs/world-pictures/images/arc-thumb.jpg b/wall/public/designs/world-pictures/images/arc-thumb.jpg deleted file mode 100644 index 346244d0..00000000 Binary files a/wall/public/designs/world-pictures/images/arc-thumb.jpg and /dev/null differ diff --git a/wall/public/designs/world-pictures/images/arc.jpg b/wall/public/designs/world-pictures/images/arc.jpg deleted file mode 100644 index 8ca5ece6..00000000 Binary files a/wall/public/designs/world-pictures/images/arc.jpg and /dev/null differ diff --git a/wall/public/designs/world-pictures/images/big-ben.jpg b/wall/public/designs/world-pictures/images/big-ben.jpg deleted file mode 100644 index f9712d2d..00000000 Binary files a/wall/public/designs/world-pictures/images/big-ben.jpg and /dev/null differ diff --git a/wall/public/designs/world-pictures/images/eye-bg.jpg b/wall/public/designs/world-pictures/images/eye-bg.jpg deleted file mode 100644 index a536a27d..00000000 Binary files a/wall/public/designs/world-pictures/images/eye-bg.jpg and /dev/null differ diff --git a/wall/public/designs/world-pictures/images/eye-wheel.png b/wall/public/designs/world-pictures/images/eye-wheel.png deleted file mode 100644 index 213543c6..00000000 Binary files a/wall/public/designs/world-pictures/images/eye-wheel.png and /dev/null differ diff --git a/wall/public/designs/world-pictures/images/eye.jpg b/wall/public/designs/world-pictures/images/eye.jpg deleted file mode 100644 index 0c944d4c..00000000 Binary files a/wall/public/designs/world-pictures/images/eye.jpg and /dev/null differ diff --git a/wall/public/designs/world-pictures/images/fuji-thumb.jpg b/wall/public/designs/world-pictures/images/fuji-thumb.jpg deleted file mode 100644 index 2a55663f..00000000 Binary files a/wall/public/designs/world-pictures/images/fuji-thumb.jpg and /dev/null differ diff --git a/wall/public/designs/world-pictures/images/fuji.jpg b/wall/public/designs/world-pictures/images/fuji.jpg deleted file mode 100644 index bc8d6299..00000000 Binary files a/wall/public/designs/world-pictures/images/fuji.jpg and /dev/null differ diff --git a/wall/public/designs/world-pictures/images/london-thumb.jpg b/wall/public/designs/world-pictures/images/london-thumb.jpg deleted file mode 100644 index 4198776e..00000000 Binary files a/wall/public/designs/world-pictures/images/london-thumb.jpg and /dev/null differ diff --git a/wall/public/designs/world-pictures/images/pyramids-thumb.jpg b/wall/public/designs/world-pictures/images/pyramids-thumb.jpg deleted file mode 100644 index d8f047ca..00000000 Binary files a/wall/public/designs/world-pictures/images/pyramids-thumb.jpg and /dev/null differ diff --git a/wall/public/designs/world-pictures/images/pyramids.jpg b/wall/public/designs/world-pictures/images/pyramids.jpg deleted file mode 100644 index da7350b7..00000000 Binary files a/wall/public/designs/world-pictures/images/pyramids.jpg and /dev/null differ diff --git a/wall/public/designs/world-pictures/images/rushmore-thumb.jpg b/wall/public/designs/world-pictures/images/rushmore-thumb.jpg deleted file mode 100644 index da1fb18f..00000000 Binary files a/wall/public/designs/world-pictures/images/rushmore-thumb.jpg and /dev/null differ diff --git a/wall/public/designs/world-pictures/images/rushmore.jpg b/wall/public/designs/world-pictures/images/rushmore.jpg deleted file mode 100644 index 8962b370..00000000 Binary files a/wall/public/designs/world-pictures/images/rushmore.jpg and /dev/null differ diff --git a/wall/public/designs/world-pictures/images/tower-bridge-fg.png b/wall/public/designs/world-pictures/images/tower-bridge-fg.png deleted file mode 100644 index f2010727..00000000 Binary files a/wall/public/designs/world-pictures/images/tower-bridge-fg.png and /dev/null differ diff --git a/wall/public/designs/world-pictures/images/tower-bridge.jpg b/wall/public/designs/world-pictures/images/tower-bridge.jpg deleted file mode 100644 index 52e5c4df..00000000 Binary files a/wall/public/designs/world-pictures/images/tower-bridge.jpg and /dev/null differ diff --git a/wall/public/designs/world-pictures/images/uluru-thumb.jpg b/wall/public/designs/world-pictures/images/uluru-thumb.jpg deleted file mode 100644 index 1765fcca..00000000 Binary files a/wall/public/designs/world-pictures/images/uluru-thumb.jpg and /dev/null differ diff --git a/wall/public/designs/world-pictures/images/uluru.jpg b/wall/public/designs/world-pictures/images/uluru.jpg deleted file mode 100644 index c29857d0..00000000 Binary files a/wall/public/designs/world-pictures/images/uluru.jpg and /dev/null differ diff --git a/wall/public/designs/world-pictures/images/wall-layer-1.png b/wall/public/designs/world-pictures/images/wall-layer-1.png deleted file mode 100644 index 776580fb..00000000 Binary files a/wall/public/designs/world-pictures/images/wall-layer-1.png and /dev/null differ diff --git a/wall/public/designs/world-pictures/images/wall-layer-2.png b/wall/public/designs/world-pictures/images/wall-layer-2.png deleted file mode 100644 index 7dbf2831..00000000 Binary files a/wall/public/designs/world-pictures/images/wall-layer-2.png and /dev/null differ diff --git a/wall/public/designs/world-pictures/images/wall-layer-3.png b/wall/public/designs/world-pictures/images/wall-layer-3.png deleted file mode 100644 index 51e3c55e..00000000 Binary files a/wall/public/designs/world-pictures/images/wall-layer-3.png and /dev/null differ diff --git a/wall/public/designs/world-pictures/images/wall-thumb.jpg b/wall/public/designs/world-pictures/images/wall-thumb.jpg deleted file mode 100644 index 730afd68..00000000 Binary files a/wall/public/designs/world-pictures/images/wall-thumb.jpg and /dev/null differ diff --git a/wall/public/designs/world-pictures/images/wall.jpg b/wall/public/designs/world-pictures/images/wall.jpg deleted file mode 100644 index c136bb33..00000000 Binary files a/wall/public/designs/world-pictures/images/wall.jpg and /dev/null differ diff --git a/wall/public/designs/world-pictures/images/westminster-cars.png b/wall/public/designs/world-pictures/images/westminster-cars.png deleted file mode 100644 index c9c9265e..00000000 Binary files a/wall/public/designs/world-pictures/images/westminster-cars.png and /dev/null differ diff --git a/wall/public/designs/world-pictures/js/wall.js b/wall/public/designs/world-pictures/js/wall.js deleted file mode 100644 index b11973cf..00000000 --- a/wall/public/designs/world-pictures/js/wall.js +++ /dev/null @@ -1,66 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this file, - * You can obtain one at http://mozilla.org/MPL/2.0/. */ - -(function () { - function init() { - // Look for a current view - var viewParam = getParam('view'); - if (viewParam) - var currentView = document.querySelector('#' + viewParam); - - // If a current view is found, remove all other views - if (currentView) { - var views = document.querySelectorAll(".view"); - Array.prototype.forEach.call(views, - function (view) { - if (view !== currentView) { - view.parentNode.removeChild(view); - } - }); - - // Promote current view's viewBox / pAR to root - var rootSVG = currentView.ownerSVGElement; - rootSVG.appendChild(currentView); - [ "viewBox", "preserveAspectRatio" ].forEach( - function(attrName) { - if (currentView.hasAttribute(attrName)) { - rootSVG.setAttribute(attrName, - currentView.getAttribute(attrName)); - } - }); - } else { - // Selection view -- remove all templates - removeAllMatchingSelector("template"); - } - - // Update links so that they append to the parent - if (parent) { - var links = document.querySelectorAll("a"); - Array.prototype.forEach.call(links, - function (link) { - link.href.baseVal = - parent.document.location.pathname + link.href.baseVal; - }); - } - } - - function getParam(name) { - name = name.replace(/[\[]/, "\\\[").replace(/[\]]/, "\\\]"); - var regex = new RegExp("[\\?&]" + name + "=([^&#]*)"), - results = regex.exec(location.search); - return results == null - ? null - : decodeURIComponent(results[1].replace(/\+/g, " ")); - } - - function removeAllMatchingSelector(selector) { - var matches = document.querySelectorAll(selector); - Array.prototype.forEach.call(matches, - function (match) { - match.parentNode.removeChild(match); - }); - } - - window.addEventListener("DOMContentLoaded", init); -})(); diff --git a/wall/public/designs/world-pictures/preview/world-pictures.png b/wall/public/designs/world-pictures/preview/world-pictures.png deleted file mode 100644 index 4f35e5d1..00000000 Binary files a/wall/public/designs/world-pictures/preview/world-pictures.png and /dev/null differ diff --git a/wall/public/designs/world-pictures/wall.svg b/wall/public/designs/world-pictures/wall.svg deleted file mode 100644 index 1192a9c6..00000000 --- a/wall/public/designs/world-pictures/wall.svg +++ /dev/null @@ -1,503 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - London - - - - - - Arc de Triomphe - - - - - - Pyramids - - - - - - Great Wall - - - - - - Mount Fuji - - - - - - Mount Rushmore - - - - - - Uluru - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/wall/public/img/top_editor.png b/wall/public/img/top_editor.png deleted file mode 100644 index b35e0b46..00000000 Binary files a/wall/public/img/top_editor.png and /dev/null differ diff --git a/wall/public/img/top_gallery.png b/wall/public/img/top_gallery.png deleted file mode 100644 index db4e919a..00000000 Binary files a/wall/public/img/top_gallery.png and /dev/null differ diff --git a/wall/public/img/top_wall.png b/wall/public/img/top_wall.png deleted file mode 100644 index c1c09202..00000000 Binary files a/wall/public/img/top_wall.png and /dev/null differ diff --git a/wall/public/index.html.php b/wall/public/index.html.php deleted file mode 100755 index 2fb4497d..00000000 --- a/wall/public/index.html.php +++ /dev/null @@ -1,46 +0,0 @@ - - - - - - - Parapara Animation - - - - - -
-
-
- - - -
-

Parapara Animation

-
-
-
- - - - diff --git a/wall/public/js/lib/backbone-min.js b/wall/public/js/lib/backbone-min.js deleted file mode 100644 index 266fc362..00000000 --- a/wall/public/js/lib/backbone-min.js +++ /dev/null @@ -1,4 +0,0 @@ -(function(){var t=this;var e=t.Backbone;var i=[];var r=i.push;var s=i.slice;var n=i.splice;var a;if(typeof exports!=="undefined"){a=exports}else{a=t.Backbone={}}a.VERSION="1.0.0";var h=t._;if(!h&&typeof require!=="undefined")h=require("underscore");a.$=t.jQuery||t.Zepto||t.ender||t.$;a.noConflict=function(){t.Backbone=e;return this};a.emulateHTTP=false;a.emulateJSON=false;var o=a.Events={on:function(t,e,i){if(!l(this,"on",t,[e,i])||!e)return this;this._events||(this._events={});var r=this._events[t]||(this._events[t]=[]);r.push({callback:e,context:i,ctx:i||this});return this},once:function(t,e,i){if(!l(this,"once",t,[e,i])||!e)return this;var r=this;var s=h.once(function(){r.off(t,s);e.apply(this,arguments)});s._callback=e;return this.on(t,s,i)},off:function(t,e,i){var r,s,n,a,o,u,c,f;if(!this._events||!l(this,"off",t,[e,i]))return this;if(!t&&!e&&!i){this._events={};return this}a=t?[t]:h.keys(this._events);for(o=0,u=a.length;o").attr(t);this.setElement(e,false)}else{this.setElement(h.result(this,"el"),false)}}});a.sync=function(t,e,i){var r=k[t];h.defaults(i||(i={}),{emulateHTTP:a.emulateHTTP,emulateJSON:a.emulateJSON});var s={type:r,dataType:"json"};if(!i.url){s.url=h.result(e,"url")||U()}if(i.data==null&&e&&(t==="create"||t==="update"||t==="patch")){s.contentType="application/json";s.data=JSON.stringify(i.attrs||e.toJSON(i))}if(i.emulateJSON){s.contentType="application/x-www-form-urlencoded";s.data=s.data?{model:s.data}:{}}if(i.emulateHTTP&&(r==="PUT"||r==="DELETE"||r==="PATCH")){s.type="POST";if(i.emulateJSON)s.data._method=r;var n=i.beforeSend;i.beforeSend=function(t){t.setRequestHeader("X-HTTP-Method-Override",r);if(n)return n.apply(this,arguments)}}if(s.type!=="GET"&&!i.emulateJSON){s.processData=false}if(s.type==="PATCH"&&window.ActiveXObject&&!(window.external&&window.external.msActiveXFilteringEnabled)){s.xhr=function(){return new ActiveXObject("Microsoft.XMLHTTP")}}var o=i.xhr=a.ajax(h.extend(s,i));e.trigger("request",e,o,i);return o};var k={create:"POST",update:"PUT",patch:"PATCH","delete":"DELETE",read:"GET"};a.ajax=function(){return a.$.ajax.apply(a.$,arguments)};var S=a.Router=function(t){t||(t={});if(t.routes)this.routes=t.routes;this._bindRoutes();this.initialize.apply(this,arguments)};var $=/\((.*?)\)/g;var T=/(\(\?)?:\w+/g;var H=/\*\w+/g;var A=/[\-{}\[\]+?.,\\\^$|#\s]/g;h.extend(S.prototype,o,{initialize:function(){},route:function(t,e,i){if(!h.isRegExp(t))t=this._routeToRegExp(t);if(h.isFunction(e)){i=e;e=""}if(!i)i=this[e];var r=this;a.history.route(t,function(s){var n=r._extractParameters(t,s);i&&i.apply(r,n);r.trigger.apply(r,["route:"+e].concat(n));r.trigger("route",e,n);a.history.trigger("route",r,e,n)});return this},navigate:function(t,e){a.history.navigate(t,e);return this},_bindRoutes:function(){if(!this.routes)return;this.routes=h.result(this,"routes");var t,e=h.keys(this.routes);while((t=e.pop())!=null){this.route(t,this.routes[t])}},_routeToRegExp:function(t){t=t.replace(A,"\\$&").replace($,"(?:$1)?").replace(T,function(t,e){return e?t:"([^/]+)"}).replace(H,"(.*?)");return new RegExp("^"+t+"$")},_extractParameters:function(t,e){var i=t.exec(e).slice(1);return h.map(i,function(t){return t?decodeURIComponent(t):null})}});var I=a.History=function(){this.handlers=[];h.bindAll(this,"checkUrl");if(typeof window!=="undefined"){this.location=window.location;this.history=window.history}};var N=/^[#\/]|\s+$/g;var P=/^\/+|\/+$/g;var O=/msie [\w.]+/;var C=/\/$/;I.started=false;h.extend(I.prototype,o,{interval:50,getHash:function(t){var e=(t||this).location.href.match(/#(.*)$/);return e?e[1]:""},getFragment:function(t,e){if(t==null){if(this._hasPushState||!this._wantsHashChange||e){t=this.location.pathname;var i=this.root.replace(C,"");if(!t.indexOf(i))t=t.substr(i.length)}else{t=this.getHash()}}return t.replace(N,"")},start:function(t){if(I.started)throw new Error("Backbone.history has already been started");I.started=true;this.options=h.extend({},{root:"/"},this.options,t);this.root=this.options.root;this._wantsHashChange=this.options.hashChange!==false;this._wantsPushState=!!this.options.pushState;this._hasPushState=!!(this.options.pushState&&this.history&&this.history.pushState);var e=this.getFragment();var i=document.documentMode;var r=O.exec(navigator.userAgent.toLowerCase())&&(!i||i<=7);this.root=("/"+this.root+"/").replace(P,"/");if(r&&this._wantsHashChange){this.iframe=a.$(' -
- Full-screen - -
- -
-
- -
- - -
- - -
- - - diff --git a/wall/public/walls/_sessions.php b/wall/public/walls/_sessions.php deleted file mode 100644 index 92c47d43..00000000 --- a/wall/public/walls/_sessions.php +++ /dev/null @@ -1,89 +0,0 @@ -name); - $thumbnail = $wall->thumbnail; - $sessions = $wall->getSessions(); - $thisWallPath = $wallsRoot . '/' . rawurlencode($wall->urlPath); - if (!$sessions || empty($sessions)) { - // No sessions - $error = "no-sessions"; - } else if (count($sessions) == 1) { - // Only one session so just redirect to the live page which will show the - // latest session - $latestSessionUrl = - $wallsRoot . '/' . rawurlencode($wall->urlPath) . '/gallery'; - header("Location: $latestSessionUrl\n\n"); - exit; - } else { - // Sort list of sessions latest-first - $sessions = array_reverse($sessions); - } - } else { - $error = "wall-not-found"; - } -} catch (Exception $e) { $error = "server-error"; } - -?> - - - - - <?php echo $wallName - ?> - - - - -
-
-
- -

-
-
-
- - - - Error: - -
- - diff --git a/wall/public/walls/_wall.php b/wall/public/walls/_wall.php deleted file mode 100644 index e80d545a..00000000 --- a/wall/public/walls/_wall.php +++ /dev/null @@ -1,44 +0,0 @@ - - - - - - - Parapara Animation loading... - - - - - - - - -
- - diff --git a/wall/public/walls/css/walls.css b/wall/public/walls/css/walls.css deleted file mode 100644 index c062eb3f..00000000 --- a/wall/public/walls/css/walls.css +++ /dev/null @@ -1,32 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this file, - * You can obtain one at http://mozilla.org/MPL/2.0/. */ - -div.error { - display: none; - position: fixed; - - left: 50%; - width: 400px; - max-width: 80%; - margin-left: -200px; - text-align: center; - - top: 50%; - margin-top: -75px; - vertical-align: middle; - - background: rgb(242, 222, 222); - border: 1px solid rgb(185, 74, 72); - color: rgb(185, 74, 72); - border-radius: 15px; - padding: 35px 14px; -} -@media (max-width: 400px) { - div.error { - left: inherit; - width: 96%; - margin-left: 2%; - margin-right: 2%; - } -} diff --git a/wall/public/walls/index.php b/wall/public/walls/index.php deleted file mode 100644 index 09edf2e3..00000000 --- a/wall/public/walls/index.php +++ /dev/null @@ -1,69 +0,0 @@ - - -latestSession) && isset($b->latestSession)) { - $startA = $a->latestSession['start']; - $startB = $b->latestSession['start']; - if ($startA == $startB) { - return $a->wallId > $b->wallId ? -1 : 1; - } - return strtotime($startA) > strtotime($startB) ? -1 : 1; - } else if (isset($a->latestSession) && !isset($b->latestSession)) { - return -1; - } else if (!isset($a->latestSession) && isset($b->latestSession)) { - return 1; - } else { - return $a->wallId > $b->wallId ? -1 : 1; - } -} - -$walls = Walls::getAllPublic(); -usort($walls, "activeFirst"); -?> - - - - Parapara Animation - galleries - - - - -
-
-
- -

Gallery

-
-
-
-
    -name); - $href = "/walls/" . rawurlencode($wall->urlPath) . "/sessions"; - $thumbnail = $wall->thumbnail; - $date = @$wall->latestSession['start']; -?> -
  • - -
-
- - diff --git a/wall/public/walls/js/main.js b/wall/public/walls/js/main.js deleted file mode 100644 index bcca271e..00000000 --- a/wall/public/walls/js/main.js +++ /dev/null @@ -1,25 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this file, - * You can obtain one at http://mozilla.org/MPL/2.0/. */ - -require.config({ - baseUrl: '/js/lib', - paths: { - // Aliases - walls: '../../walls/js', - - // Shims - jquery: 'jquery-2.0.2.min', - underscore: 'underscore-min', - webL10n: 'l10n' - }, - shim: { - 'underscore': { exports: '_' }, - 'webL10n': { exports: 'document.webL10n' } - } -}); - -require(['walls/wall-runner'], function (WallRunner) { - var runner = new WallRunner(Parapara.wallName, Parapara.sessionId); - runner.initialize(); -}); diff --git a/wall/public/walls/js/subclass.js b/wall/public/walls/js/subclass.js deleted file mode 100644 index 829b436b..00000000 --- a/wall/public/walls/js/subclass.js +++ /dev/null @@ -1,65 +0,0 @@ -/* Simple JavaScript Inheritance - * By John Resig http://ejohn.org/ - * MIT Licensed. - */ -// Inspired by base2 and Prototype -(function(){ - var initializing = false, - fnTest = /xyz/.test(function(){xyz;}) ? /\b_super\b/ : /.*/; - - // The base Class implementation (does nothing) - this.Class = function(){}; - - // Create a new Class that inherits from this class - Class.extend = function(prop) { - var _super = this.prototype; - - // Instantiate a base class (but only create the instance, - // don't run the init constructor) - initializing = true; - var prototype = new this(); - initializing = false; - - // Copy the properties over onto the new prototype - for (var name in prop) { - // Check if we're overwriting an existing function - prototype[name] = typeof prop[name] == "function" && - typeof _super[name] == "function" && fnTest.test(prop[name]) ? - (function(name, fn){ - return function() { - var tmp = this._super; - - // Add a new ._super() method that is the same method - // but on the super-class - this._super = _super[name]; - - // The method only need to be bound temporarily, so we - // remove it when we're done executing - var ret = fn.apply(this, arguments); - this._super = tmp; - - return ret; - }; - })(name, prop[name]) : - prop[name]; - } - - // The dummy class constructor - function Class() { - // All construction is actually done in the init method - if ( !initializing && this.init ) - this.init.apply(this, arguments); - } - - // Populate our constructed prototype object - Class.prototype = prototype; - - // Enforce the constructor to be what we expect - Class.prototype.constructor = Class; - - // And make this class extendable - Class.extend = arguments.callee; - - return Class; - }; -})(); diff --git a/wall/public/walls/js/wall-runner.js b/wall/public/walls/js/wall-runner.js deleted file mode 100644 index 4c8aaf38..00000000 --- a/wall/public/walls/js/wall-runner.js +++ /dev/null @@ -1,172 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this file, - * You can obtain one at http://mozilla.org/MPL/2.0/. */ - -define([ 'jquery', 'walls/wall' ], -function ($, Wall) { - return function (wallName, sessionId) - { - var runner = this; - - runner.initialize = function() { - // Check for support - if (!window.SVGAnimateElement) { - showError("This browser does not support SVG animation."); - return; - } - if (!window.EventSource) { - showError("This browser does not support event streaming."); - return; - } - - // Look up wall - if (!wallName) { - showError("No wall specified"); - return; - } - var url = '/api/walls/byname/' + wallName; - var wall, design; - var deferred = $.get(url) - .then(function(data) { - if (data.error_key || !data.designId) { - showError("Couldn't load wall"); - console.log("Wall not found"); - console.log(data); - return deferred.fail(); - } - wall = data; - - // Fetch designs - return $.get('/api/designs'); - }) - .then(function(designs) { - if (designs.error_key) { - showError("Couldn't load wall"); - console.log("Error in designs"); - console.log(designs); - return deferred.fail(); - } - // Find the design for this wall - var result = - $.grep(designs, function(d) { return d.designId == wall.designId;}); - if (result.length !== 1) { - showError("Couldn't load wall"); - console.log("Couldn't find matching design"); - console.log(designs); - return deferred.fail(); - } - design = result[0]; - if (!design.wall) { - showError("Couldn't load wall"); - console.log("Couldn't find wall source for design"); - console.log(design); - return deferred.fail(); - } - - // Update window title - document.title = wall.name; - - // Work out iframe src - // - If we have a query string on the parent, set the same - // query string on the child. - var iframeSrc = design.wall + document.location.search; - - // Start loading wall design - var iframe = $("iframe.wall"); - iframe.attr('src', iframeSrc); - iframe[0].addEventListener("load", function() { - runner.initWall(wall, design, iframe[0]); - }); - }) - .fail(function() { - showError("Couldn't load wall"); - console.log("Couldn't load designs"); - }); - } - - // XXX i10n - function showError(msg) { - $("div.error").text(msg).show(); - $("body").addClass("error"); - } - - runner.initWall = function(wallData, designData, iframe) { - // We have a default implementation of a Wall controller but specific - // walls can override this by defining an initialize method on the - // document to which we pass the default implementation so that they can - // selectively override the methods they care about - wallProto = Wall; - if (iframe.contentDocument.initialize) { - wallProto = - iframe.contentDocument.initialize(Wall, wallData, designData, $) || - Wall; - } - var wall = new wallProto(iframe.contentDocument, wallData); - - // Set up data - if (!sessionId) { - runner.initLiveStream(wall); - } else { - runner.initSessionDisplay(wall, sessionId); - } - }; - - runner.initLiveStream = function(wall) { - // Close old stream - if (runner.wallStream) { - runner.wallStream.close(); - runner.wallStream = null; - } - var wallStream = runner.wallStream = - new EventSource('/api/walls/byname/' + wallName + '/live'); - wallStream.onerror = function(e) { - console.log("Dropped connection?"); - }; - - // Map to wall callbacks - wallStream.addEventListener("sync-progress", function(e) { - wall.syncProgress(parseFloat(e.data)); - }); - wallStream.addEventListener("start-session", - wall.startSession.bind(wall)); - wallStream.addEventListener("add-character", function(e) { - wall.addCharacter(JSON.parse(e.data)); - }); - wallStream.addEventListener("remove-character", function(e) { - wall.removeCharacter(parseInt(e.data)); - }); - wallStream.addEventListener("change-duration", function(e) { - wall.changeDuration(parseFloat(e.data)); - }); - wallStream.addEventListener("change-design", function(e) { - window.location.reload(true); - }); - wallStream.addEventListener("remove-wall", function(e) { - showError("Wall removed"); - wallStream.close(); - }); - }; - - runner.initSessionDisplay = function(wall, sessionId) { - var url = - '/api/walls/byname/' + wallName + - '/sessions/' + sessionId + '/characters'; - var deferred = $.get(url) - .then(function(characters) { - if (characters.error_key) { - showError("Couldn't load wall"); - console.log("Error in characters"); - console.log(characters); - return deferred.fail(); - } - characters.forEach(function(character) { - wall.addCharacter(character); - }); - }) - .fail(function() { - showError("Couldn't load wall"); - console.log("Couldn't find session"); - }); - }; - }; -}); diff --git a/wall/public/walls/js/wall.js b/wall/public/walls/js/wall.js deleted file mode 100644 index 9f1a8934..00000000 --- a/wall/public/walls/js/wall.js +++ /dev/null @@ -1,438 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this file, - * You can obtain one at http://mozilla.org/MPL/2.0/. */ - -define([ 'jquery', 'walls/subclass' ], -function ($) { - return Class.extend({ - // Convenience definitions - SVG_NS: "http://www.w3.org/2000/svg", - XLINK_NS: "http://www.w3.org/1999/xlink", - - init: function(doc, wallData) { - // Store the passed in data so subclasses can access it - this.doc = doc; - this.wallData = wallData; - - // Calculate the effective duration in milliseconds - this.durationMs = wallData.duration || wallData.defaultDuration; - - // A number in the range [0,1) representing the difference between the - // unit progress of the wall if left untouched and the unit progress of - // the wall as defined by the server. - // - // This value is used to adjust the begin times of animations so that they - // are in sync with the server. - this.timeShift = 0; - - // Do an initial scale to make sure the background is running at the right - // duration - this.scaleAnimations(); - }, - - syncProgress: function(progress) { - // Calculate the difference between where the wall *currently* is and - // where it *should* be. - var progressDiff = this.getClockProgress() - progress; - - // Adjust the timeshift - this.timeShift = progressDiff; - - // Apply adjustments - this.scaleAnimations(this.getAnimations()); - }, - - startSession: function() { - // Get all characters in the document - var characters = this.doc.querySelectorAll(".character"); - - // Don't include characters that are actually templates - characters = Array.prototype.filter.call(characters, isNotTemplateChild); - - // Remove each character - var wall = this; - characters.forEach(function(character) { - wall.removeCharacter(character); - }); - }, - - addCharacter: function(character) { - // Find character templates - var templates = this.getCharacterTemplates(); - - // Instantiate each template - var wall = this; - var elems = []; - Array.prototype.forEach.call(templates, - function(template) { - // Create the elements - var characterElem = wall.instantiateTemplate(template, character); - - // Scale timing - wall.scaleAnimations(wall.getAnimations(characterElem)); - - // Append to document - if (characterElem.hasAttribute("data-target")) { - container = - wall.doc.getElementById( - characterElem.getAttribute("data-target")); - if (container) { - container.appendChild(characterElem); - wall.kickStartCharacter(characterElem); - } - } - - elems.push(characterElem); - } - ); - - // Return the list so subclasses can make last-minute changes - return elems; - }, - - removeCharacter: function(character) { - // See if character is: - // - an element - // - an array of elements - // - an ID - var characters; - if (character.tagName) { - characters = new Array(character); - } else if (Object.prototype.toString.call(character) === - '[object Array]') { - characters = character; - } else if (typeof character === 'string' || - typeof character === 'number') { - var nodelist = - this.doc.querySelectorAll('[data-char-id="' + character + '"]'); - characters = Array.prototype.slice.call(nodelist); - } - console.log(characters); - if (!characters || !characters.length) - return; - - // Fade out and remove each character - var wall = this; - characters.forEach(function(charElem) { - // Add a fade out animation - var fadeOut = document.createElementNS(wall.SVG_NS, "animate"); - fadeOut.setAttribute("attributeName", "opacity"); - fadeOut.setAttribute("to", "0"); - fadeOut.setAttribute("dur", "0.5s"); - fadeOut.setAttribute("begin", "indefinite"); - fadeOut.setAttribute("fill", "freeze"); - - // Attach event handler to actually remove the character - // (TODO: Use a timeout as a fallback since some UAs don't support these - // animation events very well.) - fadeOut.addEventListener("endEvent", function(e) { - charElem.parentNode.removeChild(charElem); - }, true); - - // Add and trigger the animation - charElem.appendChild(fadeOut); - fadeOut.beginElement(); - }); - }, - - changeDuration: function(duration) { - this.durationMs = duration; - this.scaleAnimations(this.getAnimations()); - }, - - changeDesign: function() { - // XXX Refresh - }, - - removeWall: function(duration) { - // XXX Handle this further up the chain? - }, - - // Helper methods - // - // These are split out and public so that subclasses can selectively - // override parts as needed - - getClockProgress: function() { - var svg = $('svg', this.doc)[0]; - if (!svg) - return 0; - - var progress = svg.getCurrentTime() * 1000 / this.durationMs; - return progress ? progress % 1 : 0; - }, - - getWallProgress: function() { - var progress = this.getClockProgress() - this.timeShift; - return progress >= 1 ? progress - 1 : progress; - }, - - scaleAnimations: function(animations) { - // animations is a NodeList or similar - if (typeof animations === "undefined") - animations = this.getAnimations(); - - // How much do we scale by? - var scaleAmount = this.durationMs / this.wallData.defaultDuration; - - // How much do we need to shift begin times by? - var seekAmountMs = this.timeShift * this.durationMs; - - // Scale each animation - var wall = this; - Array.prototype.forEach.call(animations, - function(anim) { - wall.scaleAnimation(anim, scaleAmount, seekAmountMs); - }); - }, - - scaleAnimation: function(anim, scaleAmount, seekAmountMs) { - // Get unscaled begin time - var origBegin = anim.getAttribute("data-begin"); - if (!origBegin) { - origBegin = anim.getAttribute("begin") || "0s"; - anim.setAttribute("data-begin", origBegin); - } - var origBeginMs = parseTime(origBegin); - - // Calculate scaled begin time that incorporates: - // - seek offsets to sync up with the wall time defined on the server - // - scaling due to changes in the duration - if (origBeginMs !== null) { - var newBeginMs = origBeginMs * scaleAmount + seekAmountMs; - anim = this.updateBeginTime(anim, newBeginMs); - } - - // Get original duration - var origDur = anim.getAttribute("data-dur"); - if (!origDur) { - origDur = anim.getAttribute("dur"); - anim.setAttribute("data-dur", origDur); - } - var origDurMs = parseTime(origDur); - - // Update duration - if (origDurMs !== null) { - var newDurMs = origDurMs * scaleAmount; - var newDurValue = newDurMs / 1000 + "s"; - if (anim.getAttribute("dur") != newDurValue) { - anim.setAttribute("dur", newDurValue); - } - } - }, - - // Get all animations that are candidates for automatic scaling. - getAnimations: function(contextNode) { - if (typeof contextNode === "undefined") - contextNode = this.doc; - - // Get all animations that loop indefinitely. Animations that don't look - // indefinitely are likely "effects"--things like fading characters out or - // temporarily showing things that shouldn't be scaled. - // - // In future we'll probably need to distinguish between animations where - // we want to scale the duration only or the start time only etc. - var candidates = contextNode.querySelectorAll( - 'animate[repeatCount=indefinite],' - + 'animate[repeatDur=indefinite],' - + 'animateTransform[repeatCount=indefinite],' - + 'animateTransform[repeatDur=indefinite],' - + 'animateMotion[repeatCount=indefinite],' - + 'animateMotion[repeatDur=indefinite]'); - - return Array.prototype.filter.call(candidates, isNotTemplateChild); - }, - - updateBeginTime: function(anim, newBeginTimeMs) { - // This operation is quite expensive so make sure its necessary - if ((anim.hasAttribute("begin") && - parseTime(anim.getAttribute("begin")) == newBeginTimeMs) || - !anim.hasAttribute("begin") && newBeginTimeMs == 0) { - return anim; - } - - var beginValue = (newBeginTimeMs / 1000) + "s"; - var isAttached = false; - try { - isAttached = !!anim.ownerSVGElement; - } catch (e) { /* do nothing */ } - if (isAttached) { - // Clone the animation and update - // (See comment in animationClone as to why this is necessary) - var clone = this.animationClone(anim); - clone.setAttribute("begin", beginValue); - - // Put this animation in the same place - anim.parentNode.insertBefore(clone, anim); - anim.parentNode.removeChild(anim); - kickStartAnimation(clone); - - return clone; - } - - // We haven't put the animation in the document yet so we can just - // update the begin attribute directly. - // (We're assuming here that we haven't just been temporarily removed - // from the document.) - anim.setAttribute("begin", beginValue); - - return anim; - }, - - animationClone: function(elem) { - // SMIL says that once a begin time is resolved its fixed. That's - // a problem if you want to seek an item that is already playing backwards - // because you won't be able to create a begin time earlier than the - // current one. - // - // In Firefox this is easy to work around--just temporarily detach the - // animation element from the document, updates its begin time, re-attach - // and everything works as expected. - // - // In Chrome, however, that won't clear the previously resolved begin - // times. In fact, even calling *cloneNode* causes the previously resolved - // begin times to be cloned! So, for Chrome we have to manually build up - // an exact replica of the animation so we can change its begin time! - // - // If anyone is using syncbase timing then all this extra cloning is sure - // to cause havoc. - var clone = - elem.ownerDocument.createElementNS(elem.namespaceURI, elem.tagName); - for (var i = 0; i < elem.attributes.length; i++) { - var attrib = elem.attributes[i]; - if (attrib.namespaceURI) { - clone.setAttributeNS(attrib.namespaceURI, attrib.name, - attrib.value); - } else { - clone.setAttribute(attrib.name, attrib.value); - } - } - - // Clone children--generally animation elements don't have interesting - // children so we can just clone them blindly - for (var i = 0; i < elem.childNodes.length; i++) { - clone.appendChild(elem.childNodes[i].cloneNode()); - } - return clone; - }, - - getCharacterTemplates: function() { - return this.doc.querySelectorAll('template .character,' - + 'template.character'); - }, - - instantiateTemplate: function(template, character) { - // Clone node - var instance = template.cloneNode(true /*deep*/); - - // Get fields to fill in - var templateFields = this.getTemplateFields(character); - - // Walk through subtree and update fields - var nodeIterator = - document.createNodeIterator(instance, NodeFilter.SHOW_ELEMENT, null); - var elem; - while (elem = nodeIterator.nextNode()) { - this.applyTemplateFields(elem, templateFields); - } - - return instance; - }, - - getTemplateFields: function(character) { - var beginTime = (character.x ? (character.x - 1) : 0) * - this.wallData.defaultDuration; - return { - id: character.charId, - width: character.width, - height: character.height, - title: character.title, - author: character.author, - x: character.x, - uri: character.rawUrl, - dur: this.wallData.defaultDuration, - durStr: (this.wallData.defaultDuration / 1000) + "s", - begin: beginTime, - beginStr: (beginTime / 1000) + "s" - }; - }, - - templateKeyRegex: new RegExp("{{(.+?)}}", "g"), - - applyTemplateFields: function(elem, fields) { - var substitute = function(match, key) { - return fields[key] || ""; - }; - - for (var i = elem.attributes.length - 1; i >= 0; i--) { - var attrib = elem.attributes[i]; - if (attrib.name.substring(0, 10) == 'data-tmpl-') { - var name = attrib.name.substring(10); - var value = attrib.value.replace(this.templateKeyRegex, substitute); - if (elem.namespaceURI == this.SVG_NS && name == "href") { - elem.setAttributeNS(this.XLINK_NS, name, value); - } else { - elem.setAttribute(name, value); - } - } - } - // Remove template attributes - for (var i = elem.attributes.length - 1; i >= 0; i--) { - var attrib = elem.attributes[i]; - if (attrib.name.substring(0, 10) == 'data-tmpl-') { - } - } - return elem; - }, - - // Safari has a bug where animations added dynamically don't get started so - // we have to kick-start them - kickStartCharacter: function(instance) { - console.assert(instance.ownerDocument, - "Instance should be attached before this is called"); - var animations = - instance.querySelectorAll("animate, animateMotion, animateTransform" - + ", set"); - Array.prototype.forEach.call(animations, kickStartAnimation); - } - }); - - // Helpers - - // Don't apply to animations that are templates - function isNotTemplateChild(candidate) { - while (candidate = candidate.parentNode) { - if (candidate.tagName == "template") { - return false; - } - } - return true; - } - - function kickStartAnimation(animation) { - // This is only really needed for Safari - if (navigator.userAgent.indexOf("WebKit") === -1) - return; - - try { - if (animation.getStartTime() === Infinity) { - var startTime = parseTime(animation.getAttribute("begin")) / 1000; - if (startTime === null) - startTime = 0; - animation.beginElementAt( - startTime - animation.ownerSVGElement.getCurrentTime()); - } - } catch (e) { } - } - - // Very simple time parsing: Only supports 's' and 'ms' times. - // Returns a value in milliseconds - function parseTime(str) { - if (!str) - return null; - var matches = str.match(/^\s*(-?[0-9.]+)(m?s)\s*$/); - return matches - ? parseFloat(matches[1]) * (matches[2] == "s" ? 1000 : 1) - : null; - } -}); diff --git a/wall/templates/email_anim.en-US.inc b/wall/templates/email_anim.en-US.inc deleted file mode 100644 index ce6c979e..00000000 --- a/wall/templates/email_anim.en-US.inc +++ /dev/null @@ -1,22 +0,0 @@ -Subject: Parapara Animation - -Thanks for making a Parapara Animation! - -You can visit see your creation at the link below. - - - -Title: - -Author: - - -You can view your artwork at home. Why not show it to your family and friends! - --- -Parapara Animation Team -parapara@mozilla-japan.org diff --git a/wall/templates/email_anim.ja.inc b/wall/templates/email_anim.ja.inc deleted file mode 100755 index ab92a982..00000000 --- a/wall/templates/email_anim.ja.inc +++ /dev/null @@ -1,21 +0,0 @@ -Subject: Parapara Animation - -Parapara Animation を作ってくれて、どうもありがとうございます! - -以下のウェブページにあなたの作品を展示させていただきました。 - - -タイトル: - -作者: - - -おうちに帰ってからも作品は展示されていますので、家族の方々や、学校に行って友達や先生に自慢してください! - --- -Parapara Animation 制作チーム -parapara@mozilla-japan.org diff --git a/wall/tests/ParaparaTestCase.php b/wall/tests/ParaparaTestCase.php deleted file mode 100644 index 96cfa16e..00000000 --- a/wall/tests/ParaparaTestCase.php +++ /dev/null @@ -1,163 +0,0 @@ -getMessage() - . ', ' . $conn->getDebugInfo()); - die("Couldn't connect to database: " . $conn->getMessage()); - } - - // Get statements to execute - $statements = - self::getSqlStatements(dirname(__FILE__) . '/../database/create.sql'); - if (!$statements) { - die("Couldn't get SQL statements to init database"); - } - - // Run statements - foreach ($statements as $statement) { - $res = $conn->exec($statement); - if (PEAR::isError($res)) { - die($res->getMessage() . " [executing: $statement]"); - } - } - - // Store connection so we don't do this again - self::$conn = $conn; - } - - protected static function getSqlStatements($file) { - // Get file contents - $contents = file_get_contents($file); - if (!$contents) { - error_log("Couldn't read SQL file: " . $file); - return null; - } - - // Do some massaging of the data - - // Remove comments - // - // There are various kinds: - // # Comment - // -- Comment - // /* Comment */ - $comment_patterns = array('/\s*#.*\n/', - '/\s*--.*\n/', - '/\/\*.*?\*\//s'); - $contents = preg_replace($comment_patterns, "\n", $contents); - - // Split SQL statements - $delim = ';'; - $statements = array(); - do { - // Split up to DELIMITER using the current delimeter - $matches = preg_split("/\bDELIMITER (\S+)\n/", $contents, 2, - PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE); - $statements = - array_merge($statements, - preg_split("/" . preg_quote($delim) . "\s?\n/", - $matches[0], NULL, PREG_SPLIT_NO_EMPTY)); - - // If we have a DELIMETER then update accordingly - if (count($matches) == 3) { - $delim = $matches[1]; - $contents = $matches[2]; - } else { - $contents = null; - } - } while ($contents); - - // Normalise whitestpace - $statements = preg_replace("/\s/", ' ', $statements); - - // Remove empty statements - $statements = - array_filter($statements, array('ParaparaTestCase', 'isNotEmpty')); - - return $statements; - } - - public static function isNotEmpty($str) { - return trim($str) != ''; - } - - public function getConnection() { - return self::$conn; - } - - /* ---------------------------------------------------------------------- - * - * API member - * - * ---------------------------------------------------------------------*/ - - protected $_api = null; - - public function __get($name) { - if ($name === 'api') { - if ($this->_api === null) { - $this->_api = new ParaparaAPI($this->getConnection()); - } - return $this->_api; - } - } - - /* ---------------------------------------------------------------------- - * - * Extra assertions - * - * ---------------------------------------------------------------------*/ - - function idLike ($thing) { - return isset($thing) && is_int($thing) && $thing > 0; - } - - function assertIdLike($candidate, $message = '%s') { - $dumper = new SimpleDumper(); - $message = sprintf( - $message, - "[" . $dumper->describeValue($candidate) . - "] doesn't look like an ID"); - return $this->assertTrue($this->idLike($candidate), $message); - } -} - -?> diff --git a/wall/tests/all_tests.php b/wall/tests/all_tests.php deleted file mode 100644 index b34cff09..00000000 --- a/wall/tests/all_tests.php +++ /dev/null @@ -1,16 +0,0 @@ -addFile('unit/all_tests.php'); - $this->addFile('api/all_tests.php'); - } -} -?> diff --git a/wall/tests/api/APITestCase.php b/wall/tests/api/APITestCase.php deleted file mode 100644 index 7210dd60..00000000 --- a/wall/tests/api/APITestCase.php +++ /dev/null @@ -1,32 +0,0 @@ -testDesign = "test"; - list($this->testDesignId, $this->testDesignFolder) = - $this->api->addDesign($this->testDesign, array("test.jpg")); - } - - function tearDown() { - $this->api->cleanUp(); - parent::tearDown(); - } -} - -?> diff --git a/wall/tests/api/ParaparaAPI.php b/wall/tests/api/ParaparaAPI.php deleted file mode 100644 index 12ad7558..00000000 --- a/wall/tests/api/ParaparaAPI.php +++ /dev/null @@ -1,550 +0,0 @@ -db = $db; - $this->designsPath = dirname(__FILE__) . '/../../public/designs/'; - - if (!self::$updatedSessionSettings) { - // Don't let session_start use cookies since otherwise we'll get errors - // about headers already being sent - ini_set("session.use_cookies",0); - } - } - - /* - * Utility method that removes everything created through this class. - * - * This is provided so that test code can easily clean up after each test run. - */ - function cleanUp() { - // We need to be logged in in order to delete stuff but make sure we're - // logged in as the default user. We assume anything created under another - // user account will be cleaned up manually. - if ($this->sessionId) { - $this->logout(); - } - $this->login(); - // Characters - while (count($this->createdCharacters)) { - $this->removeCharacter($this->createdCharacters[0]); - } - // Walls - while (count($this->createdWalls)) { - $this->removeWall($this->createdWalls[0]); - } - // Designs - while (count($this->createdDesigns)) { - $this->removeDesignByName($this->createdDesigns[0]); - } - // Logout - if ($this->sessionId) { - $this->logout(); - } - } - - /* ---------------------------------------------------------------------- - * - * Login / sessions - * - * ---------------------------------------------------------------------*/ - - public $userEmail = null; - protected $sessionId = null; - - function login($email = null) { - session_name(WALLMAKER_SESSION_NAME); - session_cache_limiter(''); // Prevent warnings about not being able to send - // cache limiting headers - session_start(); - - // Set email - $email = $email ? $email : self::DEFAULT_USER_EMAIL; - $_SESSION['email'] = $email; - $this->userEmail = $email; - - // We're about to call into the wall server which will want to access the - // same session but session files are opened exclusively so we store the - // session ID in a variable and then close it. - $this->sessionId = session_id(); - session_write_close(); - } - - function logout() { - // Clear up the session on the server side - session_name(WALLMAKER_SESSION_NAME); - session_start(); - unset($_SESSION['email']); - session_destroy(); - session_write_close(); - - // Clear local state - $this->sessionId = null; - $this->userEmail = null; - } - - /* ---------------------------------------------------------------------- - * - * Wall handling - * - * ---------------------------------------------------------------------*/ - - protected $createdWalls = array(); - - function createWall($name, $designId) { - // Prepare payload - $payload['name'] = $name; - $payload['design'] = $designId; - - // Make request - global $config; - $url = $config['test']['wall_server'] . 'api/walls'; - $wall = $this->postJson($url, $payload); - - // Track wall so we can clean it up - if (is_array($wall) && !array_key_exists('error_key', $wall) && - array_key_exists('wallId', $wall)) { - array_push($this->createdWalls, $wall['wallId']); - } - - return $wall; - } - - function removeWall($wallIdOrPath, $keepCharacters = null) { - // Remember wallId so we can remove from the list of created walls - if (is_int($wallIdOrPath)) { - $wallId = $wallIdOrPath; - } else { - $wall = $this->getWall($wallIdOrPath); - if ($wall) { - $wallId = $wall['wallId']; - } - } - - // Prepare payload - $payload = null; - if ($keepCharacters == "Keep character files") { - $payload = array('keepCharacters' => true); - } - - // Make request - global $config; - $url = $config['test']['wall_server'] . "api/walls/" - . (is_int($wallIdOrPath) ? $wallIdOrPath : "byname/$wallIdOrPath"); - $result = $this->deleteJson($url, $payload); - - // Remove from list of createdWalls - if (is_array($result) && $wallId && - (!array_key_exists('error_key', $result) || - $result['error_key'] == 'wall-not-found')) { - while (($pos = array_search($wallId, $this->createdWalls)) !== FALSE) { - array_splice($this->createdWalls, $pos, 1); - } - } - - return $result; - } - - function getWalls() { - global $config; - $url = $config['test']['wall_server'] . 'api/walls'; - return $this->getJson($url); - } - - function getWall($wallIdOrPath) { - global $config; - $url = $config['test']['wall_server'] . 'api/walls/' - . (is_int($wallIdOrPath) ? $wallIdOrPath : "byname/$wallIdOrPath"); - return $this->getJson($url); - } - - function updateWall($wallIdOrPath, $payload) { - global $config; - $url = $config['test']['wall_server'] . 'api/walls/' - . (is_int($wallIdOrPath) ? $wallIdOrPath : "byname/$wallIdOrPath"); - return $this->putJson($url, $payload); - } - - /* ---------------------------------------------------------------------- - * - * Wall session handling - * - * ---------------------------------------------------------------------*/ - - function startSession($wallId, $latestSessionId = "Not set") { - // Prepare payload - $payload = array(); - if ($latestSessionId != "Not set") { - $payload['latestSessionId'] = $latestSessionId; - } - - // Make request - global $config; - $url = $config['test']['wall_server'] . "api/walls/$wallId/sessions"; - return $this->postJson($url, $payload); - } - - function endSession($wallId, $sessionId) { - global $config; - $url = $config['test']['wall_server'] . - "api/walls/$wallId/sessions/$sessionId"; - return $this->putJson($url, array('end' => true)); - } - - function restartSession($wallId, $sessionId) { - global $config; - $url = $config['test']['wall_server'] . - "api/walls/$wallId/sessions/$sessionId"; - return $this->putJson($url, array('end' => null)); - } - - function getSessions($wallId) { - global $config; - $url = $config['test']['wall_server'] . "api/walls/$wallId/sessions"; - return $this->getJson($url); - } - - function deleteSession($wallId, $sessionId, $keepCharacters = null) { - // Prepare payload - $payload = null; - if ($keepCharacters == "Keep character files") { - $payload = array('keepCharacters' => true); - } - - global $config; - $url = $config['test']['wall_server'] . - "api/walls/$wallId/sessions/$sessionId"; - return $this->deleteJson($url, $payload); - } - - /* ---------------------------------------------------------------------- - * - * Character handling - * - * ---------------------------------------------------------------------*/ - - // Characters created here that have not yet been removed - protected $createdCharacters = array(); - - static protected $testCharacterFields = - array( - 'title' => 'Test title', - 'author' => 'Test author', - 'groundOffset' => 0.1, - 'width' => 123.0, - 'height' => 456.0); - static protected $testSvg = ''; - - function createCharacter($wallIdOrPath, $fields = null, $svg = null) { - // Sanity check - if (!$wallIdOrPath) { - error_log("Empty wall ID or path passed to createCharacter"); - return null; - } - - // Prepare payload - $payload['metadata'] = self::$testCharacterFields; - $payload['metadata'] = $fields - ? array_merge(self::$testCharacterFields, $fields) - : self::$testCharacterFields; - $payload['svg'] = $svg ? $svg : self::$testSvg; - - // Make request - global $config; - $url = $config['test']['wall_server'] . 'api/walls/' - . (is_int($wallIdOrPath) ? $wallIdOrPath : "byname/$wallIdOrPath") - . '/characters'; - $char = $this->postJson($url, $payload); - - // Track character so we can clean it up - if (is_array($char) && !array_key_exists('error_key', $char) && - array_key_exists('charId', $char)) { - array_push($this->createdCharacters, $char['charId']); - } - - return $char; - } - - function removeCharacter($charId) { - // Delete - global $config; - $url = $config['test']['wall_server'] . "api/characters/$charId"; - $result = $this->deleteJson($url, null); - - // Remove from list of createdCharacters - if (is_array($result) && - (!array_key_exists('error_key', $result) || - $result['error_key'] == 'character-not-found')) { - while ( - ($pos = array_search($charId, $this->createdCharacters)) !== FALSE) { - array_splice($this->createdCharacters, $pos, 1); - } - } - - return $result; - } - - function removeCharacterFile($charId) { - $svgfilename = Character::getFileForId($charId); - if (file_exists($svgfilename)) { - if (@unlink($svgfilename) === FALSE) { - throw new Exception("Failed to delete file"); - } - } - } - - // Unlike other methods in this class in this case we take the URL as - // a parameter. This is because the create character action returns an email - // URL (so the editor is a little less coupled to the backend) and we want to - // test that the returned URL is actually correct. - function emailCharacterByUrl($url, $fields) { - return $this->postJson($url, $fields); - } - - function getCharactersBySession($wallId, $sessionId) { - global $config; - $url = $config['test']['wall_server'] . 'api/walls/' . $wallId - . '/sessions/' . $sessionId . '/characters'; - return $this->getJson($url); - } - - function getCharactersByWall($wallId) { - global $config; - $url = $config['test']['wall_server'] . 'api/walls/' . $wallId - . '/characters'; - return $this->getJson($url); - } - - function updateCharacter($charId, $payload) { - global $config; - $url = $config['test']['wall_server'] . 'api/characters/' . $charId; - return $this->putJson($url, $payload); - } - - /* ---------------------------------------------------------------------- - * - * Design handling - * - * ---------------------------------------------------------------------*/ - - // Path to designs folder - protected $designsPath; - - // Designs created here that have not yet been removed - protected $createdDesigns = array(); - - function addDesign($name, $previewFilesToAdd = array()) { - // Add to DB - $query = - 'INSERT INTO designs' - . ' (name, duration)' - . ' VALUES ('. $this->db->quote($name, 'text') . ', 3000)'; - $res =& $this->db->query($query); - if (PEAR::isError($res)) { - die($res->getMessage() . ', ' . $res->getDebugInfo()); - } - - // Store ID - $designId = $this->db->lastInsertID('designs', 'designId'); - if (PEAR::isError($designId)) { - die($res->getMessage() . ', ' . $res->getDebugInfo()); - } - - // Add path for preview files - if (!file_exists($this->designsPath . $name)) { - if (!mkdir($this->designsPath . $name)) { - die("Couldn't create design folder"); - } - } - if (!file_exists($this->designsPath . $name . "/preview")) { - if (!mkdir($this->designsPath . $name . "/preview")) { - die("Couldn't create preview folder"); - } - } - $designFolder = $this->designsPath . $name . "/"; - - // Add preview files - if (is_array($previewFilesToAdd) && count($previewFilesToAdd)) { - foreach($previewFilesToAdd as $filename) { - $file = $designFolder . 'preview/' . $filename; - $handle = fopen($file, 'w'); - fclose($handle); - } - } - - // Record the design so we can automatically remove it if necessary - array_push($this->createdDesigns, $name); - - return array($designId, $designFolder); - } - - function removeDesignByName($name) { - // Remove from db - $res =& - $this->db->query('DELETE FROM designs WHERE name = ' - . $this->db->quote($name, 'text')); - if (PEAR::isError($res)) { - die($res->getMessage() . ', ' . $res->getDebugInfo()); - } - - // Remove preview files - $designFolder = $this->designsPath . $name . "/"; - $previewFolder = $designFolder . 'preview'; - if (file_exists($previewFolder)) { - foreach (glob($previewFolder . '/*.*') as $filename) { - unlink($filename); - } - if (!rmdir($previewFolder)) { - die("Couldn't remove preview folder: $previewFolder"); - } - } - // Remove design folder - if (file_exists($designFolder)) { - foreach (glob($designFolder . '/*.*') as $filename) { - unlink($filename); - } - if (!rmdir($designFolder)) { - die("Couldn't remove design folder: $designFolder"); - } - } - - // Remove from list of createdDesigns - while (($pos = array_search($name, $this->createdDesigns)) !== FALSE) { - array_splice($this->createdDesigns, $pos, 1); - } - } - - function getDesigns() { - // Make request - global $config; - $url = $config['test']['wall_server'] . 'api/designs'; - return $this->getJson($url); - } - - /* ---------------------------------------------------------------------- - * - * Request handling - * - * ---------------------------------------------------------------------*/ - - protected function getJson($url) { - return $this->makeJsonRequest($url, "GET"); - } - - protected function postJson($url, $parameters) { - return $this->makeJsonRequest($url, "POST", $parameters); - } - - protected function putJson($url, $parameters) { - return $this->makeJsonRequest($url, "PUT", $parameters); - } - - protected function deleteJson($url, $parameters) { - return $this->makeJsonRequest($url, "DELETE", $parameters); - } - - protected function makeJsonRequest($url, $method, $parameters = null) { - $payload = null; - $contentType = null; - - // Prepare payload - if ($parameters !== null) { - $payload = json_encode($parameters); - $contentType = "application/json"; - } - - // Make request - list($data, $httpCode, $contentType) = - $this->makeRequest($url, $method, $payload, $contentType); - - // Check response - if ($httpCode !== 200) { - return array( - 'error_key' => 'server-error', - 'error_detail' => 'Unexpected HTTP code: ' . @$info['http_code']); - } - if ($contentType !== 'application/json; charset=UTF-8') { - return array( - 'error_key' => 'server-error', - 'error_detail' => 'Unexpected content-type: ' . @$info['content_type']); - } - - // Decode - $response = json_decode($data, true); - if ($response === null) { - return array( - 'error_key' => 'server-error', - 'error_detail' => "Failed to parse response: $response"); - } - return $response; - } - - // Requests a URL using the specified method and payload - // - // Returns a triple: (data, http response code, response content type) - protected function makeRequest($url, $method, - $payload = null, - $payloadContentType = null) { - // Initialize request - $ch = curl_init($url); - curl_setopt($ch, CURLOPT_HEADER, false); - curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); - curl_setopt($ch, CURLOPT_BINARYTRANSFER, true); - curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $method); - - // Set up parameters if any - if ($payload) { - if ($payloadContentType) { - curl_setopt($ch, CURLOPT_HTTPHEADER, - array('Content-type: ' . $payloadContentType)); - } - $fh = fopen('php://temp', 'rw'); - fwrite($fh, $payload); - rewind($fh); - curl_setopt($ch, CURLOPT_INFILE, $fh); - curl_setopt($ch, CURLOPT_INFILESIZE, strlen($payload)); - curl_setopt($ch, CURLOPT_PUT, true); - } - - // Set session cookie if logged in - if ($this->sessionId) { - curl_setopt($ch, CURLOPT_COOKIE, - WALLMAKER_SESSION_NAME . "=" . $this->sessionId); - } - - // Make request - $data = curl_exec($ch); - $info = curl_getinfo($ch); - - // Tidy up - curl_close($ch); - if (isset($fh)) - fclose($fh); - - // Return result - return array($data, @$info['http_code'], @$info['content_type']); - } -} - -?> diff --git a/wall/tests/api/TestCharactersAPI.php b/wall/tests/api/TestCharactersAPI.php deleted file mode 100644 index 605475c2..00000000 --- a/wall/tests/api/TestCharactersAPI.php +++ /dev/null @@ -1,228 +0,0 @@ -api->login(); - $wall = $this->api->createWall('Test wall', $this->testDesignId); - - // Don't need to be logged-in in order to create a character - $this->api->logout(); - $char = $this->api->createCharacter($wall['wallId']); - $this->assertTrue(@$char['charId'] > 0, "Failed to create character"); - - // Try fetching the character - $contents = file_get_contents($char['rawUrl']); - $this->assertTrue($contents !== FALSE, "Failed to load character from URL: " - . $char['rawUrl']); - if ($contents) { - $this->assertTrue(strpos($contents, "api->login(); - $wall = $this->api->createWall('Test wall', $this->testDesignId); - - // Create one character in the first session - $this->api->createCharacter($wall['wallId']); - - // Create a couple of characters in a new session - $newSession = - $this->api->startSession($wall['wallId'], - $wall['latestSession']['sessionId']); - $charA = $this->api->createCharacter($wall['wallId'], - array('title' => 'Character A')); - $charB = $this->api->createCharacter($wall['wallId'], - array('title' => 'Character B')); - $this->api->logout(); - - // Fetch - $result = - $this->api->getCharactersBySession($wall['wallId'], - $newSession['sessionId']); - - // Check result - $this->assertNotNull($result); - $this->assertEqual(count($result), 2); - $this->assertIdentical($charA, $result[0]); - $this->assertIdentical($charB, $result[1]); - } - - function testGetCharactersByBadSession() { - // Make wall - $this->api->login(); - $wall = $this->api->createWall('Test wall', $this->testDesignId); - $this->api->logout(); - - // Fetch - $result = $this->api->getCharactersBySession($wall['wallId'], 2); - - // Check result - $this->assertEqual(@$result['error_key'], 'session-not-found'); - } - - function testGetCharactersByWall() { - // Make wall - $this->api->login(); - $wall = $this->api->createWall('Test wall', $this->testDesignId); - - // Create the following structure: - // - // - Session 1 - // - Character A - // - Character B - // - Session 2 - // - Session 3 - // - Character C - $session1 = $wall['latestSession']; - $charA = $this->api->createCharacter($wall['wallId'], - array('title' => 'Character A')); - $charB = $this->api->createCharacter($wall['wallId'], - array('title' => 'Character B')); - $session2 = - $this->api->startSession($wall['wallId'], $session1['sessionId']); - $session3 = - $this->api->startSession($wall['wallId'], $session2['sessionId']); - $charC = $this->api->createCharacter($wall['wallId'], - array('title' => 'Character C')); - - // Fetch - $result = $this->api->getCharactersByWall($wall['wallId']); - - // Check result - $this->assertNotNull($result); - $this->assertEqual(count($result), 3); - $this->assertEqual(count($result[0]['characters']), 2); - $this->assertIdentical($charA, $result[0]['characters'][0]); - $this->assertIdentical($charB, $result[0]['characters'][1]); - $this->assertEqual(count($result[1]['characters']), 0); - $this->assertEqual(count($result[2]['characters']), 1); - $this->assertIdentical($charC, $result[2]['characters'][0]); - } - - function testUpdateCharacter() { - // Create wall - $this->api->login(); - $wall = $this->api->createWall('Test wall', $this->testDesignId); - - // Create character - $char = $this->api->createCharacter($wall['wallId']); - - // Set read-only - $result = - $this->api->updateCharacter($char['charId'], array('charId' => 25)); - $this->assertEqual(@$result['error_key'], 'readonly-field'); - - // Set bad ID - $result = - $this->api->updateCharacter($char['charId']+1, array('active' => FALSE)); - $this->assertEqual(@$result['error_key'], 'character-not-found'); - - // Set nothing - $result = $this->api->updateCharacter($char['charId'], array()); - $this->assertSame(count($result), 0); - - // Test authorisation - $this->api->logout(); - $result = - $this->api->updateCharacter($char['charId'], array('active' => FALSE)); - $this->assertEqual(@$result['error_key'], 'logged-out'); - - // No authorisation - $this->api->login('abc@abc.org'); - $result = - $this->api->updateCharacter($char['charId'], array('active' => FALSE)); - $this->assertEqual(@$result['error_key'], 'no-auth'); - $this->api->logout(); - } - - function testHideCharacter() { - // Create wall - $this->api->login(); - $wall = $this->api->createWall('Test wall', $this->testDesignId); - - // Create character - $char = $this->api->createCharacter($wall['wallId']); - - // Check active state - $this->assertTrue(@$char['active'], "Character not active initially"); - - // Update active state - $result = - $this->api->updateCharacter($char['charId'], array('active' => FALSE)); - $this->assertFalse(@$result['active']); - - // Set same - $result = - $this->api->updateCharacter($char['charId'], array('active' => FALSE)); - $this->assertSame(count($result), 0); - } - - function testDeleteCharacter() { - // Create wall - $this->api->login(); - $wall = $this->api->createWall('Test wall', $this->testDesignId); - - // Create character - $char = $this->api->createCharacter($wall['wallId']); - $sessions = $this->api->getCharactersByWall($wall['wallId']); - $this->assertSame(count($sessions[0]['characters']), 1); - - // Delete character - $result = $this->api->removeCharacter($char['charId']); - $this->assertTrue(is_array($result) && count($result) === 0, - "Unexpected result deleting character: " . @$result['error_key']); - - // Try fetching - $sessions = $this->api->getCharactersByWall($wall['wallId']); - $this->assertSame(count($sessions[0]['characters']), 0); - - // Try fetching raw URLs - $this->assertFalse(@file_get_contents($char['galleryUrl'])); - $this->assertFalse(@file_get_contents($char['rawUrl'])); - - // Try deleting again - $result = $this->api->removeCharacter($char['charId']); - $this->assertEqual(@$result['error_key'], 'character-not-found'); - } - - function testDeleteCharacterPermissions() { - // Create wall - $this->api->login(); - $wall = $this->api->createWall('Test wall', $this->testDesignId); - - // Create character - $char = $this->api->createCharacter($wall['wallId']); - - // Logout and delete - $this->api->logout(); - $result = $this->api->removeCharacter($char['charId']); - $this->assertEqual(@$result['error_key'], 'logged-out'); - - // Try as another user - $this->api->login('abc@abc.org'); - $result = $this->api->removeCharacter($char['charId']); - $this->assertEqual(@$result['error_key'], 'no-auth'); - - // Finish up - $this->api->logout(); - } -} -?> diff --git a/wall/tests/api/TestCreateWall.php b/wall/tests/api/TestCreateWall.php deleted file mode 100644 index 8fbca950..00000000 --- a/wall/tests/api/TestCreateWall.php +++ /dev/null @@ -1,126 +0,0 @@ -api->login(); - } - - function testLoggedOut() { - $this->api->logout(); - - // Check it fails if we're logged out - $wall = $this->api->createWall('Test wall', $this->testDesignId); - $this->assertTrue(@$wall['error_key'] == 'logged-out', - "Got wall whilst logged out"); - } - - function testCreate() { - // Create wall - $wall = $this->api->createWall('Test wall', $this->testDesignId); - $this->assertTrue(!array_key_exists('error_key', $wall), - 'Got error creating wall: ' . @$wall['error_key'] - . ' (' . @$wall['error_detail'] . ')'); - $this->assertTrue(is_int(@$wall['wallId']) && $wall['wallId'] > 0, - "Unexpected wall ID: " . @$wall['wallId']); - } - - function testName() { - // Test same name is returned - $wall = $this->api->createWall('Test wall', $this->testDesignId); - $this->assertEqual(@$wall['name'], 'Test wall'); - - // Test non-ASCII name - $wall = $this->api->createWall('素晴らしい壁', $this->testDesignId); - $this->assertEqual(@$wall['name'], '素晴らしい壁'); - - // Test name is trimmed - $wall = $this->api->createWall(" \t space\r\n ", $this->testDesignId); - $this->assertEqual(@$wall['name'], 'space'); - - // Test empty name is rejected - $wall = $this->api->createWall("", $this->testDesignId); - $this->assertTrue(@$wall['error_key'] == 'empty-name', - "Made wall with no name"); - - // Test whitespace-only name is rejected - $wall = $this->api->createWall(" \t\r\n ", $this->testDesignId); - $this->assertTrue(@$wall['error_key'] == 'empty-name', - "Made wall with whitespace name"); - - // Test duplicate name is rejected - $wallA = $this->api->createWall('Test wall', $this->testDesignId); - $wallB = $this->api->createWall(' Test wall ', $this->testDesignId); - $this->assertTrue(@$wallB['error_key'] == 'duplicate-name', - "Made two walls with the same name"); - } - - function testUrl() { - // Test simplification - $wall = $this->api->createWall(' Test wall ', $this->testDesignId); - $this->assertEqual($this->getWallPath(@$wall['wallUrl']), 'test-wall'); - - // Test non-ASCII - $wall = $this->api->createWall('Café', $this->testDesignId); - $this->assertEqual($this->getWallPath(@$wall['wallUrl']), 'caf%C3%A9'); - - // Test converting full-with numbers to half-width - $wall = $this->api->createWall('123ABC ', $this->testDesignId); - $this->assertEqual($this->getWallPath(@$wall['wallUrl']), '123abc'); - - // Test when simplification produces duplicates - // -- we should generate a random wall path instead - $wallA = $this->api->createWall('ABC', $this->testDesignId); - $wallB = $this->api->createWall('abc', $this->testDesignId); - $this->assertNotEqual($this->getWallPath(@$wallB['wallUrl']), 'abc'); - - // Test editor URL - $wall = $this->api->createWall('Test wall 2', $this->testDesignId); - $this->assertTrue(!empty($wall['editorUrl']), 'No editor URL found'); - - // Test special characters - $wall = $this->api->createWall('Test? a=b c&d e..f g/h 2+3', - $this->testDesignId); - $this->assertEqual($this->getWallPath(@$wall['wallUrl']), - 'test--a-b-c-d-e--f-g-h-2-3'); - } - - function testEmail() { - // Try a bad email - $this->api->logout(); - $this->api->login('abc'); - $wall = $this->api->createWall('Test wall 2', $this->testDesignId); - $this->assertEqual(@$wall['error_key'], 'bad-email'); - } - - function testDesignId() { - // Test design ID matches what we put in - $wall = $this->api->createWall('Test wall 1', $this->testDesignId); - $this->assertEqual(@$wall['designId'], $this->testDesignId); - - // Test a bad ID fails - $wall = $this->api->createWall('Test wall 2', 5000); - $this->assertEqual(@$wall['error_key'], 'design-not-found'); - } - - function getWallPath($wallUrl) { - // Convert http://...../wall-path/ => wall-path - if (!preg_match('/\/([^\/]*)$/', $wallUrl, $matches)) - return null; - return $matches[1]; - } -} - -?> diff --git a/wall/tests/api/TestDeleteWall.php b/wall/tests/api/TestDeleteWall.php deleted file mode 100644 index bef87f2a..00000000 --- a/wall/tests/api/TestDeleteWall.php +++ /dev/null @@ -1,93 +0,0 @@ -api->login(); - } - - function testDelete() { - // Create wall - $wall = $this->api->createWall('Test wall', $this->testDesignId); - - // Delete wall - $result = $this->api->removeWall($wall['wallId']); - $this->assertTrue(!array_key_exists('error_key', $result), - 'Got error deleting wall: ' . @$result['error_key'] - . ' (' . @$result['error_detail'] . ')'); - } - - function testLoggedOut() { - // Create wall - $wall = $this->api->createWall('Test wall', $this->testDesignId); - $this->api->logout(); - - // Check it fails if we're logged out - $result = $this->api->removeWall($wall['wallId']); - $this->assertEqual(@$result['error_key'], 'logged-out', - "Deleted wall whilst logged out: %s"); - } - - function testDeleteByPath() { - // Create wall - $wall = $this->api->createWall('Test wall', $this->testDesignId); - - // Delete wall - $result = $this->api->removeWall('test-wall'); - $this->assertTrue(!array_key_exists('error_key', $result), - 'Got error deleting wall: ' . @$result['error_key'] - . ' (' . @$result['error_detail'] . ')'); - } - - function testWrongUser() { - // Create wall - $wall = $this->api->createWall('Test wall', $this->testDesignId); - $this->api->logout(); - - // Login as someone else - $this->api->login('abc@abc.org'); - $result = $this->api->removeWall($wall['wallId']); - $this->assertEqual(@$result['error_key'], 'no-auth'); - $this->api->logout(); - } - - function testBadWallId() { - $result = $this->api->removeWall(999999); - $this->assertEqual(@$result['error_key'], 'wall-not-found'); - } - - function testKeepCharacters() { - $wall = $this->api->createWall('Wall 1', $this->testDesignId); - $char = $this->api->createCharacter($wall['wallId']); - $result = $this->api->removeWall($wall['wallId'], "Keep character files"); - - // Check character can still be read - $this->assertNotEqual(@file_get_contents($char['rawUrl']), FALSE); - - // Clean up - $this->api->removeCharacterFile($char['charId']); - } - - function testRemoveCharacters() { - $wall = $this->api->createWall('Wall 1', $this->testDesignId); - $char = $this->api->createCharacter($wall['wallId']); - $result = $this->api->removeWall($wall['wallId']); - - // Check character can't be read - $this->assertIdentical(@file_get_contents($char['rawUrl']), FALSE); - } -} - -?> diff --git a/wall/tests/api/TestEmailAPI.php b/wall/tests/api/TestEmailAPI.php deleted file mode 100644 index 1968f1d1..00000000 --- a/wall/tests/api/TestEmailAPI.php +++ /dev/null @@ -1,85 +0,0 @@ -api->login(); - $wall = $this->api->createWall('Test wall', $this->testDesignId); - $this->api->logout(); - - // Create test character - $this->testCharacter = $this->api->createCharacter($wall['wallId']); - } - - function testSendEmail() { - // Try emailing the character - $fields = array( - 'address' => 'test@test.org', - 'locale' => 'en-US' - ); - $result = - $this->api->emailCharacterByUrl($this->testCharacter['emailUrl'], - $fields); - $this->assertTrue(!array_key_exists('error_key', $result), - "Failed to email character: " . print_r($result, true)); - } - - function testNoAddress() { - $fields = array('locale' => 'en-US'); - $result = - $this->api->emailCharacterByUrl($this->testCharacter['emailUrl'], - $fields); - $this->assertEqual(@$result['error_key'], 'bad-email'); - } - - function testBadAddress() { - $fields = array( - 'address' => '123', - 'locale' => 'en-US' - ); - $result = - $this->api->emailCharacterByUrl($this->testCharacter['emailUrl'], - $fields); - $this->assertEqual(@$result['error_key'], 'sending-failed'); - } - - function testBadCharacter() { - $url = str_replace($this->testCharacter['charId'], - '9999999', - $this->testCharacter['emailUrl']); - $fields = array( - 'address' => 'test@test.org', - 'locale' => 'en-US' - ); - $result = - $this->api->emailCharacterByUrl($url, $fields); - $this->assertEqual(@$result['error_key'], 'char-not-found'); - } - - function testNoLocale() { - // Should still work - $fields = array('address' => 'test@test.org'); - $result = - $this->api->emailCharacterByUrl($this->testCharacter['emailUrl'], - $fields); - $this->assertTrue(!array_key_exists('error_key', $result), - "Failed to email character without locale: " . print_r($result, true)); - } -} -?> diff --git a/wall/tests/api/TestGetDesigns.php b/wall/tests/api/TestGetDesigns.php deleted file mode 100644 index f2a6d234..00000000 --- a/wall/tests/api/TestGetDesigns.php +++ /dev/null @@ -1,166 +0,0 @@ -testDesignFolder . 'preview/test.jpg'); - } - - function testGetDesigns() { - $designs = $this->api->getDesigns(); - - // Check result - $this->assertTrue(!array_key_exists('error_key', $designs), - 'Got error getting designs: ' . @$designs['error_key'] - . ' (' . @$designs['error_detail'] . ')'); - - // Check the number of results---should have at least one test design - // (see APITestCase.php) - $this->assertTrue(count($designs) >= 1, - "Too few designs: " . count($designs)); - - // Check the format too - foreach ($designs as $design) { - $this->assertTrue(array_key_exists('name', $design), - "No name key found in design: " . print_r($design, true)); - $this->assertTrue(array_key_exists('duration', $design), - "No duration key found in design: " . print_r($design, true)); - } - } - - function testDesign() { - $testDesign = $this->getTestDesign(); - - // Check duration - $this->assertTrue($testDesign['duration'] == 3000, - "Unexpected duration: " . $testDesign['duration']); - } - - function testThumbnail() { - $design = $this->getTestDesign(); - - // No thumbnail entry should exist yet - $this->assertTrue(!array_key_exists('thumbnail', $design), - "Unexpected thumbnail entry in design"); - - // Add a JPG file - $this->addPreviewFile('test.jpg'); - $this->checkForThumbnail('jpg'); - - // Add a PNG file (should win) - $this->addPreviewFile('test.png'); - $this->checkForThumbnail('png'); - - // Remove PNG and JPG should be back - unlink($this->testDesignFolder . 'preview/test.png'); - $this->checkForThumbnail('jpg'); - - // Add GIF (JPG should win) - $this->addPreviewFile('test.gif'); - $this->checkForThumbnail('jpg'); - - // Remove JPG - unlink($this->testDesignFolder . 'preview/test.jpg'); - $this->checkForThumbnail('gif'); - } - - function checkForThumbnail($extension) { - $expected = "/designs/test/preview/test.$extension"; - $design = $this->getTestDesign(); - $this->assertTrue(array_key_exists('thumbnail', $design), - "Thumbnail entry should exist, expected: $expected"); - if (!array_key_exists('thumbnail', $design)) - return; - $this->assertTrue($design['thumbnail'] == $expected, - "Unexpected thumbnail file: " . $design['thumbnail'] - . ", expected: $expected"); - } - - function testVideo() { - $design = $this->getTestDesign(); - - // No video entry should exist yet - $this->assertTrue(!array_key_exists('video', $design), - "Unexpected video entry in design"); - - // Add MP4 - $this->addPreviewFile('test.mp4'); - $design = $this->getTestDesign(); - $this->assertTrue(array_key_exists('video', $design), - "Video entry should exist"); - $this->assertTrue(is_array($design['video']), - "Video entry should be an array"); - $this->assertTrue(count($design['video']) === 1, - "Should be only one video entry"); - $this->assertTrue($design['video'][0] == '/designs/test/preview/test.mp4', - "Unexpected video file: " . $design['video'][0]); - - // Add WebM - $this->addPreviewFile('test.webm'); - $design = $this->getTestDesign(); - $this->assertTrue(count($design['video']) === 2, - "Should be two video entries"); - $this->assertTrue($design['video'][0] == '/designs/test/preview/test.mp4', - "Unexpected video file: " . $design['video'][0]); - $this->assertTrue($design['video'][1] == '/designs/test/preview/test.webm', - "Unexpected video file: " . $design['video'][1]); - } - - function testWall() { - // Add SVG file - $file = $this->testDesignFolder . 'wall.svg'; - $handle = fopen($file, 'w'); - fclose($handle); - - // Test - $design = $this->getTestDesign(); - $this->assertTrue(array_key_exists('wall', $design)); - $this->assertIdentical(@$design['wall'], '/designs/test/wall.svg'); - - // Add HTML file - $file = $this->testDesignFolder . 'wall.html'; - $handle = fopen($file, 'w'); - fclose($handle); - - // Test - $design = $this->getTestDesign(); - $this->assertTrue(array_key_exists('wall', $design)); - $this->assertIdentical(@$design['wall'], '/designs/test/wall.html'); - } - - function getTestDesign() { - $designs = $this->api->getDesigns(); - - $testDesign = null; - foreach ($designs as $design) { - $this->assertTrue(array_key_exists('name', $design), - "No name key found in design: " . print_r($design, true)); - if ($design['name'] == 'test') { - $testDesign = $design; - } - } - $this->assertTrue($testDesign !== null, "Couldn't find test design"); - return $testDesign; - } - - function addPreviewFile($filename) { - $file = $this->testDesignFolder . 'preview/' . $filename; - $handle = fopen($file, 'w'); - fclose($handle); - } -} - -?> diff --git a/wall/tests/api/TestGetWall.php b/wall/tests/api/TestGetWall.php deleted file mode 100644 index f14ce280..00000000 --- a/wall/tests/api/TestGetWall.php +++ /dev/null @@ -1,112 +0,0 @@ -api->login(); - } - - function testLoggedOut() { - // Create wall - $wall = $this->api->createWall('Test wall', $this->testDesignId); - $wallId = $wall['wallId']; - $this->api->logout(); - - // Check when logged out we get a limited view - $wall = $this->api->getWall($wallId); - $this->assertTrue(!array_key_exists('error_key', $wall), - "Failed to get wall"); - $this->assertTrue(!array_key_exists('latestSession', $wall), - "Got full details of wall even while logged out"); - } - - function testGetWall() { - // Create wall - $wall = $this->api->createWall('Test wall', $this->testDesignId); - $wallId = $wall['wallId']; - - // Check it succeeds - $wall = $this->api->getWall($wallId); - $this->assertTrue(!array_key_exists('error_key', $wall), - "Failed to get wall"); - - // Check name - $this->assertTrue(@$wall['name'] === 'Test wall', - "Unexpected wall name: " . @$wall['name']); - - // Check URL - $wallUrl = @$wall['wallUrl']; - $this->assertTrue($wallUrl, "No wall URL"); - $this->assertTrue(!$wallUrl || $this->looksLikeAUrl($wallUrl), - "Unexpected wall URL format: " . $wallUrl); - - // Check editor URL - $editorUrl = @$wall['editorUrl']; - $this->assertTrue($editorUrl, "No editor URL"); - $this->assertTrue(!$editorUrl || $this->looksLikeAUrl($editorUrl), - "Unexpected editor URL format: " . $editorUrl); - - // Check editor short URL - $editorUrlShort = @$wall['editorUrlShort']; - $this->assertTrue(!$editorUrlShort || $this->looksLikeAUrl($editorUrlShort), - "Unexpected shortened editor URL format: " - . $editorUrlShort); - - // Check thumbnail - $this->assertEqual(@substr($wall['thumbnail'], -strlen("test.jpg")), - "test.jpg"); - } - - function testGetWallByPath() { - // Create wall - $createdWall = $this->api->createWall('Test wall', $this->testDesignId); - - // Get wall - $fetchedWall = $this->api->getWall('test-wall'); - $this->assertTrue(!array_key_exists('error_key', $fetchedWall), - "Failed to get wall using path"); - $this->assertIdentical(@$fetchedWall['wallId'], @$createdWall['wallId']); - - // Check session information is also loaded correctly - $this->assertIdentical(@$fetchedWall['status'], @$createdWall['status']); - } - - function testNotFound() { - $wall = $this->api->getWall(5000); - $this->assertEqual(@$wall['error_key'], 'wall-not-found'); - } - - function testSomeoneElsesWall() { - // Create wall - $wall = $this->api->createWall('Test wall', $this->testDesignId); - $wallId = $wall['wallId']; - $this->api->logout(); - - // Login as someone else - $this->api->login('abc@abc.org'); - $wall = $this->api->getWall($wallId); - $this->assertTrue(!array_key_exists('latestSession', $wall), - "Got full details of someone else's wall"); - $this->api->logout(); - } - - function looksLikeAUrl($url) { - $parts = parse_url($url); - return @$parts['scheme'] == 'http' || - @$parts['scheme'] == 'https'; - } -} - -?> diff --git a/wall/tests/api/TestGetWalls.php b/wall/tests/api/TestGetWalls.php deleted file mode 100644 index e1b275a6..00000000 --- a/wall/tests/api/TestGetWalls.php +++ /dev/null @@ -1,53 +0,0 @@ -api->login(); - } - - function testLoggedOut() { - // When logged out we should get an error - $this->api->logout(); - $walls = $this->api->getWalls(); - $this->assertTrue(array_key_exists('error_key', $walls) && - $walls['error_key'] == 'logged-out', - "Got walls whilst logged out."); - } - - function testGetWalls() { - // No walls initially - $walls = $this->api->getWalls(); - $this->assertNotNull($walls); - $this->assertTrue(is_array($walls)); - $this->assertTrue(!array_key_exists('error_key', $walls)); - $this->assertEqual(count($walls), 0); - - // Create some walls - $wallA = $this->api->createWall('Wall A', $this->testDesignId); - $wallB = $this->api->createWall('Wall B', $this->testDesignId); - - // Fetch them - $walls = $this->api->getWalls(); - $this->assertNotNull($walls); - $this->assertTrue(is_array($walls)); - $this->assertTrue(!array_key_exists('error_key', $walls)); - $this->assertEqual(count($walls), 2); - $this->assertIdentical($wallA, $walls[1]); - $this->assertIdentical($wallB, $walls[0]); - } -} - -?> diff --git a/wall/tests/api/TestSessions.php b/wall/tests/api/TestSessions.php deleted file mode 100644 index a44ef4ee..00000000 --- a/wall/tests/api/TestSessions.php +++ /dev/null @@ -1,451 +0,0 @@ -api->login(); - } - - function testCreateWall() { - // Create wall - $wall = $this->api->createWall('Test wall', $this->testDesignId); - $this->assertEqual(@$wall['status'], 'running'); - - // Check there is a session ID, start time and null end time - $this->assertTrue(!empty($wall['latestSession']), - "No session information found"); - if (@$wall['latestSession']) { - $this->assertTrue($this->isOpenSession($wall['latestSession']), - "After creating a wall we should have an open session"); - } - } - - function testEndSession() { - // Create wall - $wall = $this->api->createWall('Test wall', $this->testDesignId); - - // Get current session ID - $sessionId = $wall['latestSession']['sessionId']; - - // End session - $response = $this->api->endSession($wall['wallId'], $sessionId); - - // Check we got the times and status - $this->assertTrue(!array_key_exists('error_key', $response), - "Failed to end session: " . @$response['error_key']); - $this->assertTrue($this->isClosedSession($response), - "Session does not appear to be ended."); - - // Check the ID is the same - $this->assertEqual(@$response['sessionId'], $sessionId, - "Got different session IDs: %s"); - - // Re-fetch wall - $wall = $this->api->getWall($wall['wallId']); - $this->assertTrue($wall['status'] == 'finished'); - $this->assertTrue($this->isClosedSession($wall['latestSession']), - "Refetched wall session does not appear to be ended."); - - // Logout and check it fails - $this->api->logout(); - $response = $this->api->endSession($wall['wallId'], $sessionId); - $this->assertTrue(@$response['error_key'] == 'logged-out', - "Closed session whilst logged out."); - } - - function testEndClosedSession() { - // Create wall - $wall = $this->api->createWall('Test wall', $this->testDesignId); - $sessionId = $wall['latestSession']['sessionId']; - - // End session - $response = $this->api->endSession($wall['wallId'], $sessionId); - $this->assertTrue($this->isClosedSession($response), - "Session does not appear to be ended"); - - // End again - $response = $this->api->endSession($wall['wallId'], $sessionId); - $this->assertTrue(array_key_exists('error_key', $response) && - $response['error_key'] == 'parallel-change', - "No error about parallel change when closing twice"); - $this->assertTrue($this->isClosedSession(@$response['error_detail']), - "Doubly-ended session does not appear to be ended"); - - // Check ID hasn't changed - $this->assertEqual(@$response['error_detail']['sessionId'], $sessionId, - "Got different session IDs: %s"); - - // Re-fetch wall (to check we're in a consistent state) - $wall = $this->api->getWall($wall['wallId']); - $this->assertTrue($wall['status'] == 'finished'); - $this->assertTrue($this->isClosedSession($wall['latestSession']), - "Refetched wall session does not appear to be ended."); - } - - function testEndSomeoneElsesWall() { - // Create using test user - $wall = $this->api->createWall('Test wall', $this->testDesignId); - $sessionId = $wall['latestSession']['sessionId']; - - // Switch user - $this->api->login('abc@abc.org'); - $response = $this->api->endSession($wall['wallId'], $sessionId); - $this->assertEqual(@$response['error_key'], 'no-auth'); - } - - function testStartNew() { - // Create wall - $wall = $this->api->createWall('Test wall', $this->testDesignId); - $latestSessionId = $wall['latestSession']['sessionId']; - - // Start new session - $response = $this->api->startSession($wall['wallId'], $latestSessionId); - - // Check we got the times and status - $this->assertTrue(!array_key_exists('error_key', $response), - "Failed to start new session: " . - @$response['error_key']); - $this->assertTrue($this->isOpenSession($response), - "Session does not appear to be open"); - - // Check the IDs differ - $this->assertEqual(@$response['sessionId'], $latestSessionId+1, - "Got unexpected session ID: %s"); - - // Check previous session is closed - $sessions = $this->api->getSessions($wall['wallId']); - $this->assertTrue($this->isClosedSession($sessions[0]), - "Previous session was not closed"); - - // Re-fetch wall - $wall = $this->api->getWall($wall['wallId']); - $this->assertTrue($wall['status'] == 'running'); - $this->assertTrue($this->isOpenSession($wall['latestSession']), - "Refetched wall session does not appear to be open"); - - // Logout and check it fails - $this->api->logout(); - $response = $this->api->startSession($wall['wallId'], $latestSessionId); - $this->assertTrue(array_key_exists('error_key', $response) && - $response['error_key'] == 'logged-out', - "Started new session whilst logged out."); - } - - function testStartNewNoLatestSession() { - // Create wall - $wall = $this->api->createWall('Test wall', $this->testDesignId); - - // Start new session - $response = $this->api->startSession($wall['wallId']); - - // Check we got the times and status - $this->assertTrue(!array_key_exists('error_key', $response), - "Failed to start new session: " . - @$response['error_key']); - } - - function testParallelStartNew() { - // Create wall - $wall = $this->api->createWall('Test wall', $this->testDesignId); - $latestSessionId = $wall['latestSession']['sessionId']; - - // Start new session - $responseA = $this->api->startSession($wall['wallId'], $latestSessionId); - - // And do it again but with the OLD sessionId - $responseB = $this->api->startSession($wall['wallId'], $latestSessionId); - $this->assertTrue(array_key_exists('error_key', $responseB) && - $responseB['error_key'] == 'parallel-change', - "No error about parallel change when starting with old " - . "session ID"); - $this->assertTrue($this->isOpenSession(@$responseB['error_detail']), - "Session returned after starting twice does not appear " - . " to be open"); - - // Check the session returned by the parallel change matches that returned - // when we first started a new session - $this->assertEqual(@$responseA['sessionId'], - @$responseB['error_detail']['sessionId'], - "Got unexpected session ID: %s"); - } - - function testRestartSession() { - $wall = $this->api->createWall('Test wall', $this->testDesignId); - $sessionId = $wall['latestSession']['sessionId']; - - // End and restart session - $this->api->endSession($wall['wallId'], $sessionId); - $response = $this->api->restartSession($wall['wallId'], $sessionId); - - // Check we got the times and status - $this->assertTrue(!@array_key_exists('error_key', $response), - "Failed to end session: " . @$response['error_key']); - $this->assertTrue($this->isOpenSession($response), - "Session does not appear to be open"); - - // Double-check ID - $this->assertEqual(@$response['sessionId'], $sessionId, - "Got different session IDs: %s"); - } - - function testRestartSessionWhileLoggedOut() { - // Create wall and session - $wall = $this->api->createWall('Test wall', $this->testDesignId); - $sessionId = $wall['latestSession']['sessionId']; - - // Logout and check it fails - $this->api->logout(); - $response = $this->api->restartSession(@$wall['wallId'], $sessionId); - $this->assertTrue(@$response['error_key'] == 'logged-out', - "Closed session whilst logged out."); - } - - function testRestartNotLatestSession() { - $wall = $this->api->createWall('Test wall', $this->testDesignId); - $sessionId = $wall['latestSession']['sessionId']; - - // Create a new session and restart old session - $this->api->startSession($wall['wallId']); - $response = $this->api->restartSession($wall['wallId'], $sessionId); - - // Check we got an error - $this->assertTrue(array_key_exists('error_key', $response) && - $response['error_key'] == 'parallel-change', - "No error about parallel change when restarting old" - . " session"); - } - - function testRestartAlreadyOpenSession() { - $wall = $this->api->createWall('Test wall', $this->testDesignId); - $sessionId = $wall['latestSession']['sessionId']; - - // Restart current session - $response = $this->api->restartSession($wall['wallId'], $sessionId); - - // Check we got an error - $this->assertTrue(array_key_exists('error_key', $response) && - $response['error_key'] == 'parallel-change', - "No error about parallel change when restarting open" - . " session"); - } - - function testRestartBadSession() { - $wall = $this->api->createWall('Test wall', $this->testDesignId); - $sessionId = $wall['latestSession']['sessionId']; - - // Restart invalid session - $response = $this->api->restartSession($wall['wallId'], $sessionId + 1); - - // Check we got an error - $this->assertTrue(array_key_exists('error_key', $response) && - $response['error_key'] == 'parallel-change', - "No error about parallel change when restarting invalid" - . " session"); - } - - function testStartSomeoneElsesWall() { - // Create wall as test user - $wall = $this->api->createWall('Test wall', $this->testDesignId); - $latestSessionId = $wall['latestSession']['sessionId']; - - // Switch user - $this->api->login('abc@abc.org'); - $response = $this->api->startSession($wall['wallId'], $latestSessionId); - $this->assertEqual(@$response['error_key'], 'no-auth'); - } - - // Session IDs should be wall-specific - function testSessionIds() { - // Create first wall - $wallA = $this->api->createWall('Wall 1', $this->testDesignId); - $idA = $wallA['latestSession']['sessionId']; - - // Create second wall - $wallB = $this->api->createWall('Wall 2', $this->testDesignId); - $idB = $wallB['latestSession']['sessionId']; - - // Check IDs - $this->assertEqual($idA, 1); - $this->assertEqual($idB, 1); - - // Test next ID is 2 - $response = $this->api->startSession($wallA['wallId'], $idA); - $this->assertEqual(@$response['sessionId'], 2); - } - - function testInitialSessionList() { - // Get initial list - $wall = $this->api->createWall('Wall 1', $this->testDesignId); - $sessions = $this->api->getSessions($wall['wallId']); - $this->assertTrue(!array_key_exists('error_key', $sessions), - 'Got error getting designs: ' . @$sessions['error_key'] - . ' (' . @$sessions['error_detail'] . ')'); - - // Should have one element - $this->assertTrue(is_array($sessions) && count($sessions) === 1, - 'Unexpected initial list of sessions: ' . print_r($sessions, true)); - $this->assertEqual($sessions[0]['sessionId'], 1); - $this->assertTrue($this->isOpenSession($sessions[0]), - "Session does not appear to be open"); - } - - function testDeleteSession() { - $wall = $this->api->createWall('Wall 1', $this->testDesignId); - $result = $this->api->deleteSession($wall['wallId'], - $wall['latestSession']['sessionId']); - - // Should have no sessions - $sessions = $this->api->getSessions($wall['wallId']); - $this->assertTrue(is_array($sessions) && count($sessions) === 0, - 'Failed to delete session: ' . print_r($sessions, true)); - - // Check updated latest session and status - $this->assertIdentical(@$result['status'], "finished"); - $this->assertTrue(array_key_exists("latestSession", $result) && - $result['latestSession'] === null, - "Updated latest session should be null"); - } - - function testDeleteSessionWithPreviousSession() { - $wall = $this->api->createWall('Wall 1', $this->testDesignId); - $response = $this->api->startSession($wall['wallId']); - $this->assertTrue($response); - $result = $this->api->deleteSession($wall['wallId'], 2); - - // Should have one session - $sessions = $this->api->getSessions($wall['wallId']); - $this->assertEqual(count($sessions), 1); - - // Check updated latest session and status - $this->assertIdentical(@$result['status'], "finished"); - $this->assertTrue(array_key_exists("latestSession", $result) && - $result['latestSession'] !== null, - "Updated latest session should not be null"); - } - - function testDeleteSessionBadId() { - $wall = $this->api->createWall('Wall 1', $this->testDesignId); - $result = $this->api->deleteSession($wall['wallId'], - $wall['latestSession']['sessionId']+1); - $this->assertEqual(@$result['error_key'], 'session-not-found'); - } - - function testDeleteNotLatestSession() { - $wall = $this->api->createWall('Wall 1', $this->testDesignId); - $response = $this->api->startSession($wall['wallId']); - $this->assertTrue($response); - $result = $this->api->deleteSession($wall['wallId'], 1); - - // Should have one session - $sessions = $this->api->getSessions($wall['wallId']); - $this->assertEqual(count($sessions), 1); - - // Check updated latest session and status - $this->assertIdentical(@$result['status'], "running"); - $this->assertIdentical(@$result['latestSession']['sessionId'], 2); - } - - function testDeleteSessionAndCharacters() { - $wall = $this->api->createWall('Wall 1', $this->testDesignId); - $char = $this->api->createCharacter($wall['wallId']); - $result = $this->api->deleteSession($wall['wallId'], - $wall['latestSession']['sessionId']); - - // Check character can't be read - $this->assertIdentical(@file_get_contents($char['rawUrl']), FALSE); - } - - function testDeleteSessionButNotCharacters() { - $wall = $this->api->createWall('Wall 1', $this->testDesignId); - $char = $this->api->createCharacter($wall['wallId']); - $result = $this->api->deleteSession($wall['wallId'], - $wall['latestSession']['sessionId'], - "Keep character files"); - - // Check character can be read - $this->assertNotEqual(@file_get_contents($char['rawUrl']), FALSE); - - // Clean up - $this->api->removeCharacterFile($char['charId']); - } - - function testDeleteSessionNotLoggedIn() { - $wall = $this->api->createWall('Wall 1', $this->testDesignId); - $this->api->logout(); - $result = $this->api->deleteSession($wall['wallId'], - $wall['latestSession']['sessionId']); - $this->assertSame(@$result['error_key'], 'logged-out'); - } - - function testDeleteSessionNoAuth() { - $wall = $this->api->createWall('Wall 1', $this->testDesignId); - $this->api->login('abc@abc.org'); - $result = $this->api->deleteSession($wall['wallId'], - $wall['latestSession']['sessionId']); - $this->assertSame(@$result['error_key'], 'no-auth'); - } - - function isOpenSession($session) { - return $this->checkSession($session, true); - } - - function isClosedSession($session) { - return $this->checkSession($session, false); - } - - function checkSession($session, $shouldBeOpen) { - $this->assertTrue($session !== null, "Bad session"); - if (!$session) - return false; - - // Check session end - $this->assertTrue(intval(@$session['sessionId']) > 0, "Bad session id"); - - // Check session start - $this->assertPattern($this->dateRegEx, @$session['start']); - - // Check session end - $this->assertTrue(array_key_exists('end', $session) && - ($session['end'] === null || - preg_match($this->dateRegEx, @$session['end'])), - "Unexpected session end: " . @$session['end']); - - return $shouldBeOpen xor @$session['end'] !== null; - } - - function getWall($wallId) { - // Make request - global $config; - $url = $config['test']['wall_server'] . 'api/walls/' . $wallId; - $response = $this->get($url); - - // Check response - $this->assertResponse(200); - $this->assertMime('application/json; charset=UTF-8'); - - // Parse response - $wall = json_decode($response,true); - $this->assertTrue($wall !== null, - "Failed to decode response: $response"); - - // Check there's no error - $this->assertTrue(!array_key_exists('error_key', $wall), - "Failed to get wall:" . @$wall['error_key']); - - return $wall; - } -} - -?> diff --git a/wall/tests/api/TestSetWall.php b/wall/tests/api/TestSetWall.php deleted file mode 100644 index 5e0b971a..00000000 --- a/wall/tests/api/TestSetWall.php +++ /dev/null @@ -1,339 +0,0 @@ -api->login(); - $wall = $this->api->createWall('ABC', $this->testDesignId); - $this->testWallId = $wall['wallId']; - } - - function tearDown() { - // Clear test wall ID - $this->testWallId = null; - parent::tearDown(); - } - - function testSetName() { - // Update title - $result = - $this->api->updateWall($this->testWallId, array('name' => 'ABCD')); - $this->assertTrue(!array_key_exists('error_key', $result), - "Failed to set wall name " . @$result['error_key']); - $this->assertEqual(@$result['name'], 'ABCD'); - - // Check it actually updated the wall - $wall = $this->api->getWall($this->testWallId); - $this->assertEqual(@$wall['name'], 'ABCD'); - - // Try setting the same title--nothing should be returned since nothing - // changed - $result = - $this->api->updateWall($this->testWallId, array('name' => 'ABCD')); - $this->assertEqual(count($result), 0); - - // Test changes to capitalization are accepted - $result = $this->api->updateWall($this->testWallId, - array('name' => "abcd")); - $this->assertEqual(@$result['name'], 'abcd'); - - // Trimming - $result = $this->api->updateWall($this->testWallId, - array('name' => " \twall name\n ")); - $this->assertEqual(@$result['name'], 'wall name'); - - // Non-ASCII - $result = - $this->api->updateWall($this->testWallId, array('name' => 'テスト')); - $this->assertEqual(@$result['name'], 'テスト'); - - // Empty title - $result = $this->api->updateWall($this->testWallId, array('name' => "")); - $this->assertTrue(@$result['error_key'] == 'empty-name', - "Made wall name empty"); - - // Whitespace only - $result = - $this->api->updateWall($this->testWallId, array('name' => " \t\n ")); - $this->assertTrue(@$result['error_key'] == 'empty-name', - "Made wall name whitespace only"); - - // Duplicate title - $duplicateWall = $this->api->createWall('Wall #2', $this->testDesignId); - $duplicateWallId = $duplicateWall['wallId']; - $result = - $this->api->updateWall($this->testWallId, array('name' => "Wall #2")); - $this->assertTrue(@$result['error_key'] == 'duplicate-name', - "Made duplicate wall name"); - } - - function testSetUrlPath() { - // Update url path - $result = - $this->api->updateWall($this->testWallId, array('urlPath' => 'abc-d')); - $this->assertTrue(!array_key_exists('error_key', $result), - "Failed to set wall url " . @$result['error_key']); - $this->assertPattern("/\/abc-d$/", @$result['wallUrl']); - $this->assertPattern("/\/abc-d$/", @$result['editorUrl']); - - // Not really sure how best to test the short URL short of making a mock - // shortener service - - // Check it was actually set - $wall = $this->api->getWall($this->testWallId); - $this->assertPattern("/\/abc-d$/", @$wall['wallUrl']); - $this->assertPattern("/\/abc-d$/", @$wall['editorUrl']); - - // Attempt to set wallUrl directly - $result = - $this->api->updateWall($this->testWallId, array('wallUrl' => 'abc-d')); - $this->assertEqual(@$result['error_key'], 'readonly-field'); - - // Set editorUrl - $result = $this->api->updateWall($this->testWallId, - array('editorUrl' => 'abc-d')); - $this->assertEqual(@$result['error_key'], 'readonly-field'); - - // Set editorUrlShort - $result = $this->api->updateWall($this->testWallId, - array('editorUrlShort' => 'abc-d')); - $this->assertEqual(@$result['error_key'], 'readonly-field'); - - // Set same - $result = - $this->api->updateWall($this->testWallId, array('urlPath' => 'abc-d')); - $this->assertEqual(count($result), 0); - - // Non-ASCII - $result = $this->api->updateWall($this->testWallId, - array('urlPath' => 'テスト')); - $this->assertPattern("/\/" . rawurlencode("テスト") . "$/", - @$result['wallUrl']); - - // Bad URL -- slashes - $result = - $this->api->updateWall($this->testWallId, array('urlPath' => 'ab/cd')); - $this->assertPattern("/\/ab-cd$/", @$result['wallUrl']); - - // Bad URL -- dots - $result = $this->api->updateWall($this->testWallId, - array('urlPath' => '../abcd')); - $this->assertPattern("/\/---abcd$/", @$result['wallUrl']); - - // Bad URL -- other bad stuff - $result = $this->api->updateWall($this->testWallId, - array('urlPath' => 'Test? a=b c&d 2+3')); - $this->assertPattern("/\/test--a-b-c-d-2-3$/", @$result['wallUrl']); - - // Empty URL - $result = $this->api->updateWall($this->testWallId, array('urlPath' => '')); - $this->assertEqual(@$result['error_key'], 'bad-path'); - - // Whitespace only - $result = - $this->api->updateWall($this->testWallId, array('urlPath' => " \t")); - $this->assertEqual(@$result['error_key'], 'bad-path'); - - // Wide whitespace too - $result = - $this->api->updateWall($this->testWallId, array('urlPath' => ' ')); - $this->assertEqual(@$result['error_key'], 'bad-path'); - - // Duplicate URL - $duplicateWall = $this->api->createWall('Wall 2', $this->testDesignId); - $duplicateWallId = $duplicateWall['wallId']; - $result = $this->api->updateWall($this->testWallId, - array('urlPath' => "wall-2")); - $this->assertEqual(@$result['error_key'], 'duplicate-path'); - } - - function testNotFound() { - $result = $this->api->updateWall(500, array('name' => 'ABCD')); - $this->assertTrue(@$result['error_key'] == 'wall-not-found', - "Found non-existent wall"); - } - - function testSetSomeoneElsesWall() { - // Login as someone else - $this->api->login('abc@abc.org'); - $result = - $this->api->updateWall($this->testWallId, array('name' => 'ABCD')); - $this->assertEqual(@$result['error_key'], 'no-auth'); - $this->api->logout(); - } - - function testUnrecognizedParam() { - // Update mispelled param - $result = $this->api->updateWall($this->testWallId, array('nam' => 'ABCD')); - $this->assertEqual(@$result['error_key'], 'unknown-field'); - } - - function testId() { - // It shouldn't be possible to change the wall ID - $result = $this->api->updateWall($this->testWallId, array('wallId' => 5)); - $this->assertEqual(@$result['error_key'], 'readonly-field'); - - // Variation on the theme - $result = $this->api->updateWall($this->testWallId, array('id' => 5)); - $this->assertEqual(@$result['error_key'], 'unknown-field'); - } - - function testNoChange() { - // Change nothing - $result = $this->api->updateWall($this->testWallId, array()); - $this->assertTrue(!array_key_exists('error_key', $result), - "Failed to do nothing " . @$result['error_key']); - $this->assertEqual(count(@$result), 0); - } - - function testSetMultiple() { - // Update title and event description - $result = $this->api->updateWall($this->testWallId, - array('name' => 'ABCD', - 'duration' => 1234)); - $this->assertTrue(!array_key_exists('error_key', $result), - "Failed to set wall name and duration" - . @$result['error_key']); - $this->assertTrue(@count($result) >= 2); - $this->assertEqual(@$result['name'], 'ABCD'); - $this->assertEqual(@$result['duration'], 1234); - - // Check it actually updated the wall - $wall = $this->api->getWall($this->testWallId); - $this->assertEqual(@$wall['name'], 'ABCD'); - $this->assertEqual(@$wall['duration'], 1234); - } - - function testSetDesign() { - // Update design - // (We are just going to guess here that there is a design with ID 1 and - // it's not the test design) - $result = $this->api->updateWall($this->testWallId, array('designId' => 1)); - $this->assertTrue(!array_key_exists('error_key', $result), - "Failed to update design" . @$result['error_key']); - $this->assertEqual(@$result['designId'], 1); - $this->assertTrue(strlen(@$result['thumbnail']) > 0, - "Thumbnail not returned when updating design"); - $this->assertTrue(intval(@$result['defaultDuration']) > 0, - "Default duration not returned when updating design"); - - // Unrecognized design - $result = - $this->api->updateWall($this->testWallId, array('designId' => 999)); - $this->assertEqual(@$result['error_key'], 'bad-design'); - - // Test non-number - $result = - $this->api->updateWall($this->testWallId, array('designId' => 'abc')); - $this->assertEqual(@$result['error_key'], 'bad-request'); - - // Test setting defaultDuration or thumbnail fails - $result = - $this->api->updateWall($this->testWallId, array('thumbnail' => 'abc')); - $this->assertEqual(@$result['error_key'], 'readonly-field'); - $result = $this->api->updateWall($this->testWallId, - array('defaultDuration' => 5)); - $this->assertEqual(@$result['error_key'], 'readonly-field'); - } - - function testSetDuration() { - // Update duration - $result = - $this->api->updateWall($this->testWallId, array('duration' => 3000)); - $this->assertTrue(!array_key_exists('error_key', $result), - "Failed to update duration " . @$result['error_key']); - $this->assertEqual(@$result['duration'], 3000); - $this->assertTrue(@$result['defaultDuration'] > 0, - "Default duration not returned when updating design"); - - // Check it was actually set - $wall = $this->api->getWall($this->testWallId); - $this->assertEqual(3000, @$wall['duration']); - - // Same value - $result = - $this->api->updateWall($this->testWallId, array('duration' => 3000)); - $this->assertEqual(count($result), 0); - - // String value - // (It's ok if this doesn't work but since it seems to, we should test it) - $result = - $this->api->updateWall($this->testWallId, array('duration' => "5000")); - $this->assertEqual(@$result['duration'], 5000); - - // Out of range (negative) - $result = - $this->api->updateWall($this->testWallId, array('duration' => -100)); - $this->assertEqual(@$result['error_key'], 'bad-request'); - - // Out of range (zero) - $result = - $this->api->updateWall($this->testWallId, array('duration' => 0)); - $this->assertEqual(@$result['error_key'], 'bad-request'); - - // Out of range (overflow) - $result = $this->api->updateWall($this->testWallId, - array('duration' => 2147483648)); - $this->assertEqual(@$result['error_key'], 'bad-request'); - - // Not numeric - $result = - $this->api->updateWall($this->testWallId, array('duration' => "abc")); - $this->assertEqual(@$result['error_key'], 'bad-request'); - - // Not numeric (2) - // (This checks we're not just blindly applying intval) - $result = $this->api->updateWall($this->testWallId, - array('duration' => "12 grapes")); - $this->assertEqual(@$result['error_key'], 'bad-request'); - - // Null ok - $result = - $this->api->updateWall($this->testWallId, array('duration' => null)); - $this->assertTrue(!array_key_exists('error_key', $result), - "Failed to update duration to null: " - . @$result['error_key']); - $this->assertEqual(@$result['duration'], null); - $this->assertTrue(@$result['defaultDuration'] > 0, - "Default duration should be non-null even " . - "if duration is null"); - - // Check it was actually set - $wall = $this->api->getWall($this->testWallId); - $this->assertEqual(null, @$wall['duration']); - - // Same value - $result = - $this->api->updateWall($this->testWallId, array('duration' => null)); - $this->assertEqual(count($result), 0); - - // String "null" - $result = - $this->api->updateWall($this->testWallId, array('duration' => "null")); - $this->assertTrue(!array_key_exists('error_key', $result), - "Failed to update duration to null: " - . @$result['error_key']); - $this->assertEqual(@$result['duration'], null); - - // Test you can't set defaultDuration - $result = $this->api->updateWall($this->testWallId, - array('defaultDuration' => 5000)); - $this->assertEqual(@$result['error_key'], 'readonly-field'); - } -} diff --git a/wall/tests/api/TestWallStream.php b/wall/tests/api/TestWallStream.php deleted file mode 100644 index 39dd62ad..00000000 --- a/wall/tests/api/TestWallStream.php +++ /dev/null @@ -1,720 +0,0 @@ -stream = null; - - // Create a test wall - $this->api->login(); - $this->testWall = $this->api->createWall('Test wall', $this->testDesignId); - $this->api->logout(); - - // This is a long-running test but flushing any output should hopefully stop - // the browser from giving up - ob_flush(); - flush(); - } - - function tearDown() { - $this->closeStream(); - parent::tearDown(); - } - - function testNoWall() { - list($stream, $headers) = $this->openStream($this->testWall['wallId'] + 1); - - // Check for remove-wall event - $events = $this->readEvents($stream, $lastEventId); - $this->assertIdentical(count($events), 1, - "Unexpected number of events: %s"); - $this->assertIdentical(@$events[0]['event'], "remove-wall"); - } - - function testNoCharacters() { - list($stream, $headers) = $this->openStream($this->testWall['wallId']); - - // Check headers - $this->assertIdentical(@intval($headers['http_code']), 200, - "Unexpected HTTP response: %s"); - $this->assertIdentical(@$headers['Content-Type'], - "text/event-stream; charset=UTF-8"); - - // Should get one sync-progress and one start-session event - $events = $this->readEvents($stream, $lastEventId); - $this->assertIdentical(count($events), 2, - "Unexpected number of events: %s"); - $this->assertIdentical(@$events[0]['event'], "sync-progress"); - $syncProgress = @$events[0]['data']; - $this->assertTrue(floatval($syncProgress) >= 0 && - floatval($syncProgress) < 1, - "Unexpected sync progress value: " . $syncProgress); - $this->assertIdentical(@$events[1]['event'], "start-session"); - $this->assertTrue(intval($lastEventId) > 1); - } - - function testNoSessions() { - // Remove session - $this->api->login(); - $this->api->deleteSession($this->testWall['wallId'], - $this->testWall['latestSession']['sessionId']); - $this->api->logout(); - - // Get stream - list($stream, $headers) = $this->openStream($this->testWall['wallId']); - - // Should get one sync-progress and one start-session event - $events = $this->readEvents($stream, $lastEventId); - $this->assertIdentical(count($events), 2, - "Unexpected number of events: %s"); - $this->assertIdentical(@$events[0]['event'], "sync-progress"); - $this->assertIdentical(@$events[1]['event'], "start-session"); - } - - function testInitialCharacters() { - // Add some characters - $charA = $this->api->createCharacter($this->testWall['wallId'], - array('title' => 'Character A')); - $charB = $this->api->createCharacter($this->testWall['wallId'], - array('title' => 'Character B')); - - // Read stream - list($stream, $headers) = $this->openStream($this->testWall['wallId']); - - // Should get sync-progress, start-session event, 2 x add-character events - $events = $this->readEvents($stream, $lastEventId); - $this->assertIdentical(count($events), 4, - "Unexpected number of events: %s"); - $this->assertIdentical(@$events[0]['event'], "sync-progress"); - $this->assertIdentical(@$events[1]['event'], "start-session"); - $this->assertIdentical(@$events[2]['event'], "add-character"); - $this->assertIdentical(@$events[3]['event'], "add-character"); - - // Check the character data - $this->assertIdentical(json_decode(@$events[2]['data'], true), $charA); - $this->assertIdentical(json_decode(@$events[3]['data'], true), $charB); - } - - function testAddCharacters() { - // Read stream - list($stream, $headers) = $this->openStream($this->testWall['wallId']); - - // Should get start-session event - $events = $this->readEvents($stream, $lastEventId); - $this->assertIdentical(count($events), 2, - "Unexpected number of events: %s"); - $this->assertIdentical(@$events[0]['event'], "sync-progress"); - $this->assertIdentical(@$events[1]['event'], "start-session"); - $initialEventId = $lastEventId; - - // Add some characters - $charA = $this->api->createCharacter($this->testWall['wallId'], - array('title' => 'Character A')); - $charB = $this->api->createCharacter($this->testWall['wallId'], - array('title' => 'Character B')); - - // Read subsequent events - $events = $this->readEvents($stream, $lastEventId); - $this->assertIdentical(count($events), 2, - "Unexpected number of events: %s"); - $this->assertIdentical(@$events[0]['event'], "add-character"); - $this->assertIdentical(@$events[1]['event'], "add-character"); - - // Check the character data - $this->assertIdentical(json_decode(@$events[0]['data'], true), $charA); - $this->assertIdentical(json_decode(@$events[1]['data'], true), $charB); - - // Check the event ID has increased - $this->assertTrue($lastEventId >= $initialEventId + 2, - "Last event ID has not increased by the expected amount"); - } - - function testAddCharactersAfterResume() { - // Read stream - list($stream, $headers) = $this->openStream($this->testWall['wallId']); - - // Should get start-session event - $events = $this->readEvents($stream, $lastEventId); - $this->assertIdentical(count($events), 2, - "Unexpected number of events: %s"); - $this->assertIdentical(@$events[0]['event'], "sync-progress"); - $this->assertIdentical(@$events[1]['event'], "start-session"); - $initialEventId = $lastEventId; - - // Close stream - $this->closeStream(); - - // Add some characters - $charA = $this->api->createCharacter($this->testWall['wallId'], - array('title' => 'Character A')); - $charB = $this->api->createCharacter($this->testWall['wallId'], - array('title' => 'Character B')); - - // Re-open stream - list($stream, $headers) = - $this->openStream($this->testWall['wallId'], $lastEventId); - - // Read subsequent events - $events = $this->readEvents($stream, $lastEventId); - $this->assertIdentical(count($events), 3, - "Unexpected number of events: %s"); - $this->assertIdentical(@$events[0]['event'], "sync-progress"); - $this->assertIdentical(@$events[1]['event'], "add-character"); - $this->assertIdentical(@$events[2]['event'], "add-character"); - - // Check the character data - $this->assertIdentical(json_decode(@$events[1]['data'], true), $charA); - $this->assertIdentical(json_decode(@$events[2]['data'], true), $charB); - - // Check the event ID has increased - $this->assertTrue($lastEventId >= $initialEventId + 2, - "Last event ID has not increased by the expected amount"); - } - - function testAddCharactersBeforeAndAfterResume() { - // Read stream - list($stream, $headers) = $this->openStream($this->testWall['wallId']); - - // Should get start-session event - $events = $this->readEvents($stream, $lastEventId); - $this->assertIdentical(count($events), 2, - "Unexpected number of events: %s"); - $this->assertIdentical(@$events[0]['event'], "sync-progress"); - $this->assertIdentical(@$events[1]['event'], "start-session"); - $initialEventId = $lastEventId; - - // Add a character - $charA = $this->api->createCharacter($this->testWall['wallId'], - array('title' => 'Character A')); - - // Check the stream - $events = $this->readEvents($stream, $lastEventId); - $this->assertIdentical(count($events), 1, - "Unexpected number of events: %s"); - $this->assertIdentical(@$events[0]['event'], "add-character"); - $this->assertIdentical(json_decode(@$events[0]['data'], true), $charA); - - // Close stream - $this->closeStream(); - - // Add another character - $charB = $this->api->createCharacter($this->testWall['wallId'], - array('title' => 'Character B')); - - // Re-open stream - list($stream, $headers) = - $this->openStream($this->testWall['wallId'], $lastEventId); - - // Check the character data - $events = $this->readEvents($stream, $lastEventId); - $this->assertIdentical(count($events), 2, - "Unexpected number of events: %s"); - $this->assertIdentical(@$events[0]['event'], "sync-progress"); - $this->assertIdentical(@$events[1]['event'], "add-character"); - $this->assertIdentical(json_decode(@$events[1]['data'], true), $charB); - } - - function testHiddenCharacters() { - // Add some characters - $charA = $this->api->createCharacter($this->testWall['wallId'], - array('title' => 'Character A')); - $charB = $this->api->createCharacter($this->testWall['wallId'], - array('title' => 'Character B')); - - // Hide character A - $this->api->login(); - $this->api->updateCharacter($charA['charId'], array('active' => false)); - - // Read stream - list($stream, $headers) = $this->openStream($this->testWall['wallId']); - - // Should get sync-progress, start-session event, 1 x add-character events - $events = $this->readEvents($stream, $lastEventId); - $this->assertIdentical(count($events), 3, - "Unexpected number of events: %s"); - $this->assertIdentical(@$events[0]['event'], "sync-progress"); - $this->assertIdentical(@$events[1]['event'], "start-session"); - $this->assertIdentical(@$events[2]['event'], "add-character"); - - // Check the character data - $this->assertIdentical(json_decode(@$events[2]['data'], true), $charB); - } - - function testShowHideCharacters() { - // Add a character - $char = $this->api->createCharacter($this->testWall['wallId'], - array('title' => 'Character')); - - // Read stream - list($stream, $headers) = $this->openStream($this->testWall['wallId']); - $events = $this->readEvents($stream, $lastEventId); - $initialEventId = $lastEventId; - - // Hide character - $this->api->login(); - $this->api->updateCharacter($char['charId'], array('active' => false)); - - // Read event - $events = $this->readEvents($stream, $lastEventId); - $this->assertIdentical(count($events), 1, - "Unexpected number of events: %s"); - $this->assertIdentical(@$events[0]['event'], "remove-character"); - $this->assertIdentical(@intval($events[0]['data']), $char['charId']); - $this->assertIdentical(@intval($events[0]['id']), $initialEventId + 1); - - // Show character - $this->api->updateCharacter($char['charId'], array('active' => true)); - - // Read event - $events = $this->readEvents($stream, $lastEventId); - $this->assertIdentical(count($events), 1, - "Unexpected number of events: %s"); - $this->assertIdentical(@$events[0]['event'], "add-character"); - $this->assertIdentical(json_decode(@$events[0]['data'], true), $char); - $this->assertIdentical(@intval($events[0]['id']), $initialEventId + 2); - } - - function testShowHideCharactersFromOldSession() { - // Add a character - $char = $this->api->createCharacter($this->testWall['wallId'], - array('title' => 'Character')); - - // Start new session - $this->api->login(); - $session = $this->api->startSession($this->testWall['wallId']); - - // Read stream - list($stream, $headers) = $this->openStream($this->testWall['wallId']); - $events = $this->readEvents($stream, $lastEventId); - - // Hide character - $this->api->updateCharacter($char['charId'], array('active' => false)); - - // Check for no events - $events = $this->readEvents($stream, $lastEventId); - $this->assertIdentical(count($events), 0, - "Unexpected number of events: %s"); - - // Show character - $this->api->updateCharacter($char['charId'], array('active' => true)); - - // Check for no events - $events = $this->readEvents($stream, $lastEventId); - $this->assertIdentical(count($events), 0, - "Unexpected number of events: %s"); - } - - function testRemoveCharacter() { - // Add a character - $char = $this->api->createCharacter($this->testWall['wallId'], - array('title' => 'Character')); - - // Read stream - list($stream, $headers) = $this->openStream($this->testWall['wallId']); - - // Get initial events - $events = $this->readEvents($stream, $lastEventId); - $initialEventId = $lastEventId; - - // Remove character - $this->api->login(); - $this->api->removeCharacter($char['charId']); - - // Read event - $events = $this->readEvents($stream, $lastEventId); - $this->assertIdentical(count($events), 1, - "Unexpected number of events: %s"); - $this->assertIdentical(@$events[0]['event'], "remove-character"); - $this->assertIdentical(@intval($events[0]['data']), $char['charId']); - $this->assertIdentical(@intval($events[0]['id']), $initialEventId + 1); - } - - function testRemoveCharacterFromOldSession() { - // Add a character - $char = $this->api->createCharacter($this->testWall['wallId'], - array('title' => 'Character')); - - // Start new session - $this->api->login(); - $session = $this->api->startSession($this->testWall['wallId']); - - // Read stream - list($stream, $headers) = $this->openStream($this->testWall['wallId']); - $events = $this->readEvents($stream, $lastEventId); - - // Remove character - $this->api->removeCharacter($char['charId']); - - // Check for no events - $events = $this->readEvents($stream, $lastEventId); - $this->assertIdentical(count($events), 0, - "Unexpected number of events: %s"); - } - - function testAddRemoveSession() { - // Add character - $char = $this->api->createCharacter($this->testWall['wallId'], - array('title' => 'Character')); - - // Read stream - list($stream, $headers) = $this->openStream($this->testWall['wallId']); - - // Get initial events - $events = $this->readEvents($stream, $lastEventId); - $initialEventId = $lastEventId; - - // Start session - $this->api->login(); - $session = $this->api->startSession($this->testWall['wallId']); - - // Read event - $events = $this->readEvents($stream, $lastEventId); - $this->assertIdentical(count($events), 1, - "Unexpected number of events: %s"); - $this->assertIdentical(@$events[0]['event'], "start-session"); - $this->assertIdentical(@intval($events[0]['id']), $initialEventId + 1); - - // Remove session - $this->api->deleteSession($this->testWall['wallId'], $session['sessionId']); - - // Read events: Should get a start-session event plus an add-character event - // for every character in the previous session. - $events = $this->readEvents($stream, $lastEventId); - $this->assertIdentical(count($events), 2, - "Unexpected number of events: %s"); - $this->assertIdentical(@$events[0]['event'], "start-session"); - $this->assertIdentical(@intval($events[0]['id']), $initialEventId + 2); - $this->assertIdentical(@$events[1]['event'], "add-character"); - $this->assertIdentical(json_decode(@$events[1]['data'], true), $char); - } - - function testRemoveOldSession() { - // Remember first session - $firstSessionId = $this->testWall['latestSession']['sessionId']; - - // Add character - $char = $this->api->createCharacter($this->testWall['wallId'], - array('title' => 'Character')); - - // Read stream - list($stream, $headers) = $this->openStream($this->testWall['wallId']); - $events = $this->readEvents($stream, $lastEventId); - - // Start a new session - $this->api->login(); - $session = $this->api->startSession($this->testWall['wallId']); - - // Read event - $events = $this->readEvents($stream, $lastEventId); - $this->assertIdentical(count($events), 1, - "Unexpected number of events: %s"); - $this->assertIdentical(@$events[0]['event'], "start-session"); - - // Remove first session - $this->api->deleteSession($this->testWall['wallId'], $firstSessionId); - - // Should be no events - $this->assertIdentical(count($this->readEvents($stream, $lastEventId)), 0, - "Generated events when deleting insignificant event"); - } - - function testChangeDuration() { - // Read stream - list($stream, $headers) = $this->openStream($this->testWall['wallId']); - $events = $this->readEvents($stream, $lastEventId); - $initialEventId = $lastEventId; - - // Update duration - $this->api->login(); - $this->api->updateWall($this->testWall['wallId'], - array('duration' => 1234)); - - // Read events: change-duration, sync-progress - $events = $this->readEvents($stream, $lastEventId); - $this->assertIdentical(count($events), 2, - "Unexpected number of events: %s"); - $this->assertIdentical(@$events[0]['event'], "change-duration"); - $this->assertIdentical(intval(@$events[0]['data']), 1234); - $this->assertIdentical(intval($lastEventId), $initialEventId + 1); - $this->assertIdentical(@$events[1]['event'], "sync-progress"); - $syncProgress = @$events[1]['data']; - $this->assertTrue(floatval($syncProgress) >= 0 && - floatval($syncProgress) < 1, - "Unexpected sync progress value: " . $syncProgress); - - // Set duration to default - $this->api->updateWall($this->testWall['wallId'], - array('duration' => null)); - - // Read events--we should get the actual default duration not null, or zero, - // or the previous value - $events = $this->readEvents($stream, $lastEventId); - $this->assertIdentical(count($events), 2, - "Unexpected number of events: %s"); - $this->assertIdentical(@$events[0]['event'], "change-duration"); - $reportedDuration = intval(@$events[0]['data']); - $this->assertTrue($reportedDuration > 0 && $reportedDuration != 1234, - "Unexpected duration: $reportedDuration"); - $this->assertIdentical(intval($lastEventId), $initialEventId + 2); - $this->assertIdentical(@$events[1]['event'], "sync-progress"); - } - - function testChangeDesign() { - // Read stream - list($stream, $headers) = $this->openStream($this->testWall['wallId']); - $events = $this->readEvents($stream, $lastEventId); - $initialEventId = $lastEventId; - - // Update duration - $this->api->login(); - $this->api->updateWall($this->testWall['wallId'], array('designId' => 1)); - - // Read event - $events = $this->readEvents($stream, $lastEventId); - $this->assertIdentical(count($events), 1, - "Unexpected number of events: %s"); - $this->assertIdentical(@$events[0]['event'], "change-design"); - $this->assertIdentical(intval($lastEventId), $initialEventId + 1); - } - - // We'd like to test for a deleted wall too but currently the implementation - // only checks if the wall exists every 10 seconds and that's too long for - // a unit test to wait. - - function openStream($wallIdOrPath, $lastEventId = null) { - // Check there is no request in progress - if ($this->stream !== null) { - $this->fail("Stream already open"); - return null; - } - - // Get URL - global $config; - $url = $config['test']['wall_server'] . 'api/walls/' - . (is_int($wallIdOrPath) ? $wallIdOrPath : "byname/$wallIdOrPath") - . '/live'; - $url_parts = parse_url($url); - - // Start connection - $port = isset($url_parts['port']) ? $url_parts['port'] : 80; - $this->stream = fsockopen($url_parts['host'], $port, $err_num, $err_msg); - if ($this->stream === FALSE) { - $this->fail("Couldn't open socket $err_msg [$err_num]"); - $this->stream = null; - return null; - } - - // Make request - stream_set_blocking($this->stream, 0); - fputs($this->stream, "GET " . $url_parts['path'] . " HTTP/1.1\r\n"); - fputs($this->stream, 'Host: ' . $url_parts['host'] . "\r\n"); - if ($lastEventId !== null) { - fputs($this->stream, 'Last-Event-ID: ' . $lastEventId . "\r\n"); - } - fputs($this->stream, "\r\n"); - - // Wait for initial response - if (!$this->waitForStream($this->stream)) { - $this->fail("No response"); - return null; - } - - // Parse header - $headers = $this->readHeaders($this->stream, $lastEventId); - if (!$headers) - return null; - - // Check status code - if (intval($headers['http_code']) !== 200) { - return array($this->stream, $headers); - } - - // Check for chunked transfer - if (!isset($headers['Transfer-Encoding']) || - $headers['Transfer-Encoding'] !== 'chunked') { - $this->fail("Didn't get chunked encoding"); - return null; - } - - return array($this->stream, $headers); - } - - function readHeaders($stream) { - $headers = array(); - - // HTTP response code - $response = fgets($stream); - if (!$response) { - $this->fail("No HTTP response"); - return null; - } - $headers['http_code'] = substr($response, 9, 3); - - // Other headers - while ($line = fgets($stream)) { - if (trim($line) == "") - break; - $parts = explode(':', $line, 2); - if (count($parts) !== 2 || trim($parts[0]) == "") { - $this->fail("Bad header: $line"); - return null; - } - $headers[trim($parts[0])] = trim($parts[1]); - } - - return $headers; - } - - function readEvents($stream, &$lastId) { - // See if there is data already in the buffer - $data = $this->readData($stream); - if (!$data) { - // If not, wait up to 1 second for it - if (!$this->waitForStream($stream)) - return array(); - - // Read again - $data = $this->readData($stream); - } - - // Split on double line break - $events = preg_split("/(\r\n|\r|\n){2}/", $data); - - // HTML says every event must finish with a blank line--so drop anything - // after the last double line break - $events = array_slice($events, 0, count($events) - 1); - - // Parse each event - $events = array_map("parseEvent", $events); - - // Remove any null values - $events = array_filter($events); - - // Walk backwards through events to look for any changes to the event ID - for ($i = count($events) - 1; $i >= 0; $i--) { - if (isset($events[$i]['id'])) { - $lastId = $events[$i]['id']; - break; - } - } - - return $events; - } - - function readData($stream) { - $data = ""; - while ($chunk = $this->readChunk($stream)) - $data .= $chunk; - - return strlen($data) ? $data : null; - } - - function readChunk($stream) { - $firstLine = fgets($stream); - if (!$firstLine) - return null; - - // Read chunk size - if (!preg_match("/^([0-9A-Fa-f]+)(;.*)?\r\n$/", $firstLine, $matches)) { - $this->fail("Invalid chunk"); - return null; - } - $contentLength = hexdec($matches[1]); - - // Read chunk - $chunk = stream_get_contents($stream, $contentLength); - - // Discard trailing carriage-return linefeed pair - stream_get_contents($stream, 2); - - return $chunk; - } - - function waitForStream($stream, $timeout = 1) { - $read = array($stream); - $write = null; - $except = null; - return stream_select($read, $write, $except, $timeout); - } - - function closeStream() { - if ($this->stream) { - fclose($this->stream); - $this->stream = null; - } - } -} - -/* Callback methods */ - -function parseEvent($event) { - $result = array('event' => '', 'data' => ''); - $lines = preg_split("/(\r\n|\r|\n)/", $event); - - foreach($lines as $line) { - // Comment - if ($line[0] == ':') { - if (isset($result["_comments"])) - array_push($result["_comments"], $line); - else - $result["_comments"] = array($line); - - // field: value - } elseif ($pos = strpos($line, ':')) { - $field = substr($line, 0, $pos); - $value = substr($line, $pos+1); - // Strip initial space if any - if (strlen($value) && $value[0] === ' ') - $value = substr($value, 1); - processField($field, $value, $result); - - // field - } else { - processField($line, "", $result); - } - } - - // HTML says that if the data buffer is an empty string then discard - if ($result['data'] === '') - return null; - - return $result; -} - -function processField($field, $value, &$event) { - switch ($field) { - case 'event': - $event['event'] .= $value; - break; - - case 'data': - $event['data'] .= "$value\n"; - break; - - case 'id': - $event['id'] = $value; - break; - - case 'retry': - $event['retry'] = intval($value); - break; - - default: - /* Ignore */ - break; - } -} -?> diff --git a/wall/tests/api/all_tests.php b/wall/tests/api/all_tests.php deleted file mode 100644 index 27ffc207..00000000 --- a/wall/tests/api/all_tests.php +++ /dev/null @@ -1,31 +0,0 @@ -TestSuite('API tests'); - $this->addFile(dirname(__FILE__) . '/TestGetDesigns.php'); - $this->addFile(dirname(__FILE__) . '/TestCreateWall.php'); - $this->addFile(dirname(__FILE__) . '/TestGetWalls.php'); - $this->addFile(dirname(__FILE__) . '/TestGetWall.php'); - $this->addFile(dirname(__FILE__) . '/TestSetWall.php'); - $this->addFile(dirname(__FILE__) . '/TestDeleteWall.php'); - $this->addFile(dirname(__FILE__) . '/TestSessions.php'); - $this->addFile(dirname(__FILE__) . '/TestCharactersAPI.php'); - $this->addFile(dirname(__FILE__) . '/TestEmailAPI.php'); - $this->addFile(dirname(__FILE__) . '/TestWallStream.php'); - } -} -?> diff --git a/wall/tests/unit/ParaparaUnitTestCase.php b/wall/tests/unit/ParaparaUnitTestCase.php deleted file mode 100644 index 5d992877..00000000 --- a/wall/tests/unit/ParaparaUnitTestCase.php +++ /dev/null @@ -1,100 +0,0 @@ -'; - protected $testCharacterFields = array( - 'title' => 'Test title', - 'author' => 'Test author', - 'groundOffset' => 0.1, - 'width' => 123.0, - 'height' => 456.0); - - // Array to track all created characters so we can clean them up - protected $createdCharacters = array(); - - function __construct($name = false) { - parent::__construct($name); - } - - function setUp($testCharacter = "create") { - parent::setUp(); - - // Login - $_SESSION['email'] = "test@test.org"; - - // Test design - list($designId) = $this->api->addDesign("test", array("test.jpg")); - - // Test wall - $this->testWall = Walls::create("Test wall", $designId); - $this->testWall->startSession(); - - // Test character - if ($testCharacter != "Don't create test character") { - $this->testCharacter = $this->createCharacter(); - } - } - - function tearDown() { - // Remove test characters - while (count($this->createdCharacters)) { - $this->removeCharacter($this->createdCharacters[0]); - } - $this->testCharacter = null; - - // Remove test wall - $this->testWall->destroy(); - $this->testWall = null; - - // Clean up other resources - $this->api->cleanUp(); - - // Logout - unset($_SESSION['email']); - - parent::tearDown(); - } - - // Utility wrapper that calls Characters::create and tracks the character so - // it will be deleted automatically on tear-down - function createCharacter($fields = NOT_SET, $wallId = NOT_SET, $svg = NOT_SET) - { - // Fill in default parameters - if ($fields === NOT_SET) - $fields = $this->testCharacterFields; - if ($wallId === NOT_SET) - $wallId = $this->testWall->wallId; - if ($svg === NOT_SET) - $svg = $this->testCharacterSvg; - - $char = Characters::create($svg, $fields, $wallId); - if ($char !== null && isset($char->charId)) { - array_push($this->createdCharacters, $char->charId); - } - return $char; - } - - function removeCharacter($charId) { - Characters::deleteById($charId); - - // Remove from list of createdCharacters - while (($pos = array_search($charId, $this->createdCharacters)) !== FALSE) { - array_splice($this->createdCharacters, $pos, 1); - } - } -} - -?> diff --git a/wall/tests/unit/TestCharacterEmail.php b/wall/tests/unit/TestCharacterEmail.php deleted file mode 100644 index a8fdee40..00000000 --- a/wall/tests/unit/TestCharacterEmail.php +++ /dev/null @@ -1,117 +0,0 @@ -testMailer =& Mail::factory('mock'); - - // Make sure a transport is set initially - global $config; - $config['mail']['transport'] = 'mock'; - } - - function testEnabled() { - // Remove mail configuration in settings - global $config; - unset($config['mail']['transport']); - $this->assertFalse(CharacterEmailer::isEmailEnabled()); - try { - CharacterEmailer::sendEmail($this->testCharacter, $this->testAddress); - $this->fail("Failed to throw exception with no mail transport"); - } catch (KeyedException $e) { - $this->assertEqual($e->getKey(), "email-disabled"); - } - - // Supply mailer manually - try { - CharacterEmailer::sendEmail($this->testCharacter, $this->testAddress, - null, $this->testMailer); - } catch (KeyedException $e) { - $this->fail("Failed to send mail with manual mailer, exception: " - . $e->getKey() . ", " . $e->getMessage()); - } - } - - function testAddress() { - try { - CharacterEmailer::sendEmail($this->testCharacter, ""); - $this->fail("Failed to throw exception with no email address"); - } catch (KeyedException $e) { - $this->assertEqual($e->getKey(), "bad-email"); - } - } - - function testSend() { - global $config; - - // Send - CharacterEmailer::sendEmail($this->testCharacter, $this->testAddress, - null, $this->testMailer); - - // Check message was sent - $this->assertEqual(count($this->testMailer->sentMessages), 1); - $message = @$this->testMailer->sentMessages[0]; - - // Check address - $this->assertEqual(@$message['recipients'], $this->testAddress); - - // Check headers - $this->assertEqual(@$message['headers']['From'], $config['mail']['from']); - - // Check body - $this->assertTrue(strlen(@$message['body']) > 0); - $this->assertTrue( - strpos(@$message['body'], $this->testCharacter->galleryUrl) !== false); - $this->assertTrue( - strpos(@$message['body'], $this->testCharacter->title) !== false); - $this->assertTrue( - strpos(@$message['body'], $this->testCharacter->author) !== false); - } - - function testBadLocale() { - // Send - CharacterEmailer::sendEmail($this->testCharacter, $this->testAddress, - 'abc', $this->testMailer); - - // Check message was sent - $this->assertEqual(count($this->testMailer->sentMessages), 1); - $message = @$this->testMailer->sentMessages[0]; - $this->assertTrue(strlen(@$message['body']) > 0); - } - - function testGoodLocale() { - // Get default body - CharacterEmailer::sendEmail($this->testCharacter, $this->testAddress, - null, $this->testMailer); - - // Send with Japanese template - CharacterEmailer::sendEmail($this->testCharacter, $this->testAddress, - 'ja', $this->testMailer); - - // Check messages were sent - $this->assertEqual(count($this->testMailer->sentMessages), 2); - - // Compare bodies - $defaultMessage = @$this->testMailer->sentMessages[0]; - $japaneseMessage = @$this->testMailer->sentMessages[1]; - $this->assertTrue(strlen(@$defaultMessage['body']) > 0); - $this->assertTrue(strlen(@$japaneseMessage['body']) > 0); - $this->assertNotEqual($defaultMessage, $japaneseMessage); - } -} diff --git a/wall/tests/unit/TestCharacterFile.php b/wall/tests/unit/TestCharacterFile.php deleted file mode 100644 index e0e3f757..00000000 --- a/wall/tests/unit/TestCharacterFile.php +++ /dev/null @@ -1,31 +0,0 @@ -testFolder . '/*.in.svg') as $filename) { - // Check for a static reference file - $refFile = str_replace('.in.svg', '.static.svg', $filename); - if (!file_exists($refFile)) - continue; - - // Run staticalizer - $in = file_get_contents($filename); - $ref = file_get_contents($refFile); - $out = CharacterFile::getStaticCharacter($in); - - // Compare - $this->assertEqual($out, trim($ref), "%s (File: $filename)"); - } - } -} - -?> diff --git a/wall/tests/unit/TestCharacters.php b/wall/tests/unit/TestCharacters.php deleted file mode 100644 index 2db671ee..00000000 --- a/wall/tests/unit/TestCharacters.php +++ /dev/null @@ -1,811 +0,0 @@ -testFields =& $this->testCharacterFields; - $this->testSvg =& $this->testCharacterSvg; - } - - function setUp() { - parent::setUp("Don't create test character"); - } - - function testCreateCharacter() { - $char = $this->createCharacter(); - - $this->assertIdLike(@$char->charId, "Bad character ID: %s"); - $this->assertIdLike(@$char->wallId, "Bad wall ID: %s"); - $this->assertIdLike(@$char->sessionId, "Bad session ID: %s"); - - $this->assertIdentical(@$char->title, $this->testFields['title']); - $this->assertIdentical(@$char->author, $this->testFields['author']); - $this->assertIdentical(@$char->groundOffset, - $this->testFields['groundOffset']); - $this->assertIdentical(@$char->width, $this->testFields['width']); - $this->assertIdentical(@$char->height, $this->testFields['height']); - $this->assertPattern($this->dateRegEx, @$char->createDate); - $this->assertIdentical(@$char->active, TRUE); - $this->assertWithinMargin(@$char->x, - $this->testWall->getCurrentProgress(), 0.1); - } - - function testWallNotFound() { - try { - $char = $this->createCharacter($this->testFields, 0); - $this->fail("Failed to throw exception with bad Wall ID"); - } catch (KeyedException $e) { - $this->assertEqual($e->getKey(), "wall-not-found"); - } - } - - function testNoSession() { - $this->testWall->endSession(); - try { - $char = $this->createCharacter(); - $this->fail("Failed to throw exception with no active session"); - } catch (KeyedException $e) { - $this->assertEqual($e->getKey(), "no-active-session"); - } - } - - function testTitleTrimming() { - $this->testFields['title'] = "  abc "; - $char = $this->createCharacter(); - $this->assertIdentical(@$char->title, "abc"); - } - - function testTitleIsOptional() { - $this->testFields['title'] = null; - $char = $this->createCharacter(); - $this->assertIdentical(@$char->title, null); - } - - function testAuthorTrimming() { - $this->testFields['author'] = "  author "; - $char = $this->createCharacter(); - $this->assertIdentical(@$char->author, "author"); - } - - function testAuthorOptional() { - $this->testFields['author'] = null; - $char = $this->createCharacter(); - $this->assertIdentical(@$char->author, null); - } - - function testGroundOffset() { - // If not set -> 0 - $fields = $this->testFields; - unset($fields['groundOffset']); - $char = $this->createCharacter($fields); - $this->assertIdentical(@$char->groundOffset, 0.0); - - // Negative - $fields['groundOffset'] = -0.5; - $char = $this->createCharacter($fields); - $this->assertIdentical(@$char->groundOffset, 0.0); - - // > 1 - $fields['groundOffset'] = 2.5; - $char = $this->createCharacter($fields); - $this->assertIdentical(@$char->groundOffset, 1.0); - - // Non float - $fields['groundOffset'] = 'abc'; - $char = $this->createCharacter($fields); - $this->assertIdentical(@$char->groundOffset, 0.0); - } - - function testWidthHeightRequired() { - foreach (array('width', 'height') as $field) { - $fields = $this->testFields; - unset($fields[$field]); - try { - $char = $this->createCharacter($fields); - $this->fail("Failed to throw exception when missing required field: " - . $field); - } catch (KeyedException $e) { - $this->assertEqual($e->getKey(), "bad-request"); - } - } - } - - function testWidthHeightRange() { - foreach (array('width', 'height') as $field) { - $this->checkExceptionCreatingCharWithValue($field, -1, 'bad-request'); - $this->checkExceptionCreatingCharWithValue($field, 0, 'bad-request'); - $this->checkExceptionCreatingCharWithValue($field, 'abc', 'bad-request'); - $this->checkExceptionCreatingCharWithValue($field, 999999999999, - 'bad-request'); - } - } - - function checkExceptionCreatingCharWithValue($field, $value, $key) { - $fields = $this->testFields; - $fields[$field] = $value; - try { - $char = $this->createCharacter($fields); - $this->fail("Failed to throw exception when setting $field to $value"); - } catch (KeyedException $e) { - $this->assertEqual($e->getKey(), $key, - "Unexpected exception key when setting $field to $value: %s"); - } - } - - function testFile() { - $char = $this->createCharacter(); - - $expectedFile = Character::getFileForId($char->charId); - $this->assertTrue(is_readable($expectedFile), - "SVG file not found at $expectedFile"); - $this->assertIdentical(@file_get_contents($expectedFile), $this->testSvg); - } - - function testFileConfig() { - // Test a trailing slash and whitespace is ignored - global $config; - $config['characters']['path'] .= '/ '; - - $char = $this->createCharacter(); - $expectedFile = Character::getFileForId($char->charId); - $this->assertTrue(is_readable($expectedFile), - "SVG file not found at $expectedFile"); - $this->assertIdentical(@file_get_contents($expectedFile), $this->testSvg); - } - - // XXX It would be good to test when the file can't be written but I can't - // find an easy way to do this on Windows (short of abstracting out the file - // system and using a mock object). - - function testFileExists() { - $charA = $this->createCharacter(); - - // Create a file where the next character *would* be saved - $charAFile = Character::getFileForId($charA->charId); - $nextId = $charA->charId + 1; - $nextFile = preg_replace('/' . $charA->charId . '(\.\w+)$/', - "$nextId\\1", $charAFile); - $handle = fopen($nextFile, 'w'); - fclose($handle); - - // Now try to create a character - try { - $charB = $this->createCharacter(); - $this->fail("Failed to throw exception when target file already exists"); - } catch (KeyedException $e) { - $this->assertEqual($e->getKey(), 'save-failed', - "Unexpected exception key when target file already exists"); - } - - // Check DB change was backed out - $this->assertNull(Characters::getById($nextId)); - - // Tidy up - unlink($nextFile); - } - - function testLargeFile() { - // Work out what the current ID is - $prevChar = $this->createCharacter(); - $nextId = $prevChar->charId + 1; - - // Work out the maximum - global $config; - if (!isset($config['characters']['max_size'])) { - $config['characters']['max_size'] = 6000; - } - $maxLen = $config['characters']['max_size']; - - // Prepare SVG - $svgHeader = ""; - $pathData = - "M100 100C300,80 400,300 450,100 450,100 500,-100 -90,220110,150"; - $iterationsRequired = - ceil(($maxLen - strlen($svgHeader) - strlen($svgFooter)) - / strlen($pathData)); - $bigSvg = $svgHeader; - while ($iterationsRequired--) - $bigSvg .= $pathData; - $bigSvg .= $svgFooter; - - // Create a massive file - try { - $char = $this->createCharacter($this->testFields, - $this->testWall->wallId, $bigSvg); - $this->fail("Failed to throw exception with large SVG file"); - } catch (KeyedException $e) { - $this->assertEqual($e->getKey(), 'character-too-large', - "Unexpected exception key with large SVG file"); - } - - // Check DB change was backed out - $this->assertNull(Characters::getById($nextId)); - } - - function testRawUrl() { - $char = $this->createCharacter(); - $this->assertTrue(strlen(@$char->rawUrl) > 0, "Empty raw URL"); - } - - function testGalleryUrl() { - $char = $this->createCharacter(); - $this->assertTrue(strlen(@$char->galleryUrl) > 0, "Empty gallery URL"); - } - - function testPreviewUrl() { - $char = $this->createCharacter(); - $this->assertTrue(strlen(@$char->previewUrl) > 0, "Empty preview URL"); - } - - function testEmailUrl() { - $char = $this->createCharacter(); - - // The email URL should only be set if email is enabled so make sure it is - global $config; - $config['mail']['transport'] = 'smtp'; - $this->assertPattern('/' . $char->charId . '\/email$/', @$char->emailUrl); - - // Disable email - unset($config['mail']['transport']); - $this->assertFalse(isset($char->emailUrl)); - } - - function testGetById() { - $createdChar = $this->createCharacter(); - $fetchedChar = Characters::getById($createdChar->charId); - $this->assertIdentical($createdChar, $fetchedChar); - } - - function testGetBadId() { - $this->assertNull(Characters::getById(999999)); - } - - function testInvalidId() { - foreach($this->invalidIds as $id) { - try { - $char = Characters::getById($id); - $this->fail("Failed to throw exception with bad id: $id"); - } catch (KeyedException $e) { - $this->assertEqual($e->getKey(), 'bad-request', - "Unexpected exception key bad id '$id': %s"); - } - } - } - - function testGetBySession() { - $wallId = $this->testWall->wallId; - $sessionId = $this->testWall->latestSession['sessionId']; - - // Check initial state - $chars = Characters::getBySession($wallId, $sessionId); - $this->assertIdentical(count($chars), 0); - - // Add characters - $charA = $this->createCharacter(); - $charB = $this->createCharacter(); - $charC = $this->createCharacter(); - - // Check new state - $chars = Characters::getBySession($wallId, $sessionId); - $this->assertIdentical(count($chars), 3); - $this->assertIdentical($chars[0], $charA); - $this->assertIdentical($chars[1], $charB); - $this->assertIdentical($chars[2], $charC); - } - - function testBadSession() { - $wallId = $this->testWall->wallId; - $sessionId = $this->testWall->latestSession['sessionId']; - $this->assertNull(Characters::getBySession($wallId, $sessionId + 1)); - } - - function testInvalidSession() { - $goodWallId = $this->testWall->wallId; - $goodSessionId = $this->testWall->latestSession['sessionId']; - - foreach($this->invalidIds as $badId) { - try { - $char = Characters::getBySession($badId, $goodSessionId); - $this->fail("Failed to throw exception with bad wall id: $badId"); - } catch (KeyedException $e) { - $this->assertEqual($e->getKey(), 'bad-request', - "Unexpected exception key bad wall id '$badId': %s"); - } - try { - $char = Characters::getBySession($goodWallId, $badId); - $this->fail("Failed to throw exception with bad session id: $badId"); - } catch (KeyedException $e) { - $this->assertEqual($e->getKey(), 'bad-request', - "Unexpected exception key bad session id '$badId': %s"); - } - } - } - - function testGetByWall() { - $wallId = $this->testWall->wallId; - - // Check initial state - $chars = Characters::getByWall($wallId); - $this->assertIdentical(count($chars), 0); - - // Add characters to first session - $sessionA = $this->testWall->latestSession['sessionId']; - $charAA = $this->createCharacter(); - $charAB = $this->createCharacter(); - - // Add characters to a second session - $this->testWall->startSession(); - $sessionB = $this->testWall->latestSession['sessionId']; - $charBA = $this->createCharacter(); - - // Add a third empty session - // (These don't appear in the output) - $this->testWall->startSession(); - $sessionC = $this->testWall->latestSession['sessionId']; - - // Check new state - $chars = Characters::getByWall($wallId); - $this->assertIdentical(count($chars), 2); - $this->assertIdentical(count(@$chars[$sessionA]), 2); - $this->assertIdentical(@$chars[$sessionA][0], $charAA); - $this->assertIdentical(@$chars[$sessionA][1], $charAB); - $this->assertIdentical(count(@$chars[$sessionB]), 1); - $this->assertIdentical(@$chars[$sessionB][0], $charBA); - } - - function testBadWall() { - $this->assertNull(Characters::getByWall(99999)); - } - - function testInvalidWall() { - foreach($this->invalidIds as $id) { - try { - $char = Characters::getByWall($id); - $this->fail("Failed to throw exception with bad wall id: $id"); - } catch (KeyedException $e) { - $this->assertEqual($e->getKey(), 'bad-request', - "Unexpected exception key bad wall id '$id': %s"); - } - } - } - - function testDelete() { - $char = - Characters::create($this->testSvg, $this->testFields, - $this->testWall->wallId); - $this->assertTrue(Characters::deleteById($char->charId)); - $this->assertNull(Characters::getById($char->charId)); - $this->assertFalse(Characters::deleteById($char->charId)); - - $expectedFile = Character::getFileForId($char->charId); - $this->assertFalse(file_exists($expectedFile), - "SVG still remains at $expectedFile"); - } - - function testDeleteFileLocked() { - // Lock the character file - $char = - Characters::create($this->testSvg, $this->testFields, - $this->testWall->wallId); - $file = $char->getFileForId($char->charId); - $fp = fopen($file, "rw+"); - flock($fp, LOCK_EX); - - // Try to delete - try { - $result = Characters::deleteById($char->charId); - $this->fail("Failed to throw exception when deleting locked file"); - } catch (KeyedException $e) { - $this->assertEqual($e->getKey(), 'server-error', - "Unexpected exception key when deleting locked file"); - } - - // Check database was not changed - $this->assertNotNull(Characters::getById($char->charId)); - - // Tidy up - flock($fp, LOCK_UN); - fclose($fp); - $this->assertTrue(Characters::deleteById($char->charId)); - $this->assertFalse(file_exists($file)); - } - - function testDeleteFileMissing() { - // Delete character file - $char = - Characters::create($this->testSvg, $this->testFields, - $this->testWall->wallId); - $file = $char->getFileForId($char->charId); - unlink($file); - - // Try to delete - $result = Characters::deleteById($char->charId); - - // Check database WAS changed - $this->assertNull(Characters::getById($char->charId)); - $this->assertFalse(Characters::deleteById($char->charId)); - } - - function testDeleteKeepFile() { - $char = - Characters::create($this->testSvg, $this->testFields, - $this->testWall->wallId); - $this->assertTrue(Characters::deleteById($char->charId, - CharacterDeleteMode::DeleteRecordOnly)); - $this->assertNull(Characters::getById($char->charId)); - $this->assertFalse(Characters::deleteById($char->charId)); - - $expectedFile = Character::getFileForId($char->charId); - $this->assertTrue(file_exists($expectedFile), - "SVG still remains at $expectedFile"); - if (file_exists($expectedFile)) { - unlink($expectedFile); - } - } - - function testDeleteInvalidId() { - foreach($this->invalidIds as $id) { - try { - $char = Characters::deleteById($id); - $this->fail("Failed to throw exception with bad id: $id"); - } catch (KeyedException $e) { - $this->assertEqual($e->getKey(), 'bad-request', - "Unexpected exception key bad id '$id': %s"); - } - } - } - - function testDeletePreviewFiles() { - $char = - Characters::create($this->testSvg, $this->testFields, - $this->testWall->wallId); - - // Create a cached preview file - $this->createPreviewFile($char); - - // Delete - $this->assertTrue(Characters::deleteById($char->charId)); - - // Check cached preview file is gone - $previewFile = Character::getPreviewFile($char->charId); - $this->assertFalse(file_exists($previewFile), "Preview file not removed"); - } - - function testDeleteBySession() { - $wallId = $this->testWall->wallId; - $sessionA = $this->testWall->latestSession['sessionId']; - - // Check initial state - $result = Characters::deleteBySession($wallId, $sessionA); - $this->assertIdentical($result, 0); - - // Add characters to first session - $charAA = $this->createCharacter(); - $charAB = $this->createCharacter(); - - // Start a new session and add characters - $this->testWall->startSession(); - $sessionB = $this->testWall->latestSession['sessionId']; - $charBA = $this->createCharacter(); - - // Delete from first session - $result = Characters::deleteBySession($wallId, $sessionA); - $this->assertIdentical($result, 2); - $chars = Characters::getBySession($wallId, $sessionA); - $this->assertIdentical(count($chars), 0); - $chars = Characters::getBySession($wallId, $sessionB); - $this->assertIdentical(count($chars), 1); - - // Delete from second session - $result = Characters::deleteBySession($wallId, $sessionB); - $this->assertIdentical($result, 1); - $chars = Characters::getBySession($wallId, $sessionB); - $this->assertIdentical(count($chars), 0); - } - - function testDeleteBySessionWithPreviews() { - // Get wall and session - $wallId = $this->testWall->wallId; - $session = $this->testWall->latestSession['sessionId']; - - // Add character to session - $char = $this->createCharacter(); - - // Create a cached preview file - $this->createPreviewFile($char); - - // Delete session characters - $result = Characters::deleteBySession($wallId, $session); - $this->assertIdentical($result, 1); - - // Check cached preview file is gone - $previewFile = Character::getPreviewFile($char->charId); - $this->assertFalse(file_exists($previewFile), "Preview file not removed"); - } - - function testDeleteBadSession() { - $wallId = $this->testWall->wallId; - $sessionId = $this->testWall->latestSession['sessionId']; - $result = Characters::deleteBySession($wallId, $sessionId+1); - $this->assertIdentical($result, null); - } - - function testDeleteInvalidSession() { - $goodWallId = $this->testWall->wallId; - $goodSessionId = $this->testWall->latestSession['sessionId']; - - foreach($this->invalidIds as $badId) { - try { - $char = Characters::deleteBySession($badId, $goodSessionId); - $this->fail("Failed to throw exception with bad wall id: $badId"); - } catch (KeyedException $e) { - $this->assertEqual($e->getKey(), 'bad-request', - "Unexpected exception key bad wall id '$badId': %s"); - } - try { - $char = Characters::deleteBySession($goodWallId, $badId); - $this->fail("Failed to throw exception with bad session id: $badId"); - } catch (KeyedException $e) { - $this->assertEqual($e->getKey(), 'bad-request', - "Unexpected exception key bad session id '$badId': %s"); - } - } - } - - function testDeleteBySessionFileLocked() { - $wallId = $this->testWall->wallId; - $sessionId = $this->testWall->latestSession['sessionId']; - - // Add characters - $charA = $this->createCharacter(); - $charB = $this->createCharacter(); - $charC = $this->createCharacter(); - - // Lock the second character file - $file = Character::getFileForId($charB->charId); - $fp = fopen($file, "rw+"); - flock($fp, LOCK_EX); - - // Try to delete session - try { - $result = Characters::deleteBySession($wallId, $sessionId); - $this->fail("Failed to throw exception when deleting locked file"); - } catch (KeyedException $e) { - $this->assertEqual($e->getKey(), 'server-error', - "Unexpected exception key when deleting locked file"); - } - - // Check all files exist - $this->assertTrue(file_exists(Character::getFileForId($charA->charId))); - $this->assertTrue(file_exists(Character::getFileForId($charB->charId))); - $this->assertTrue(file_exists(Character::getFileForId($charC->charId))); - - // Check database was not changed - $chars = Characters::getBySession($wallId, $sessionId); - $this->assertIdentical(count($chars), 3); - - // Unlock and delete properly - flock($fp, LOCK_UN); - fclose($fp); - $result = Characters::deleteBySession($wallId, $sessionId); - $this->assertIdentical($result, 3); - } - - function testDeleteBySessionFileMissing() { - $wallId = $this->testWall->wallId; - $sessionId = $this->testWall->latestSession['sessionId']; - - // Add characters - $charA = $this->createCharacter(); - $charB = $this->createCharacter(); - $charC = $this->createCharacter(); - - // Delete second file - $file = Character::getFileForId($charB->charId); - unlink($file); - - // Delete session - $result = Characters::deleteBySession($wallId, $sessionId); - $this->assertIdentical($result, 3); - - // Check all files are gone - $this->assertFalse(file_exists(Character::getFileForId($charA->charId))); - $this->assertFalse(file_exists(Character::getFileForId($charB->charId))); - $this->assertFalse(file_exists(Character::getFileForId($charC->charId))); - - // Check database is up-to-date - $chars = Characters::getBySession($wallId, $sessionId); - $this->assertIdentical(count($chars), 0); - } - - function testDeleteBySessionKeepFiles() { - $wallId = $this->testWall->wallId; - $sessionId = $this->testWall->latestSession['sessionId']; - - // Add characters - $charA = $this->createCharacter(); - $charB = $this->createCharacter(); - - // Delete session - $result = - Characters::deleteBySession($wallId, $sessionId, - CharacterDeleteMode::DeleteRecordOnly); - $this->assertIdentical($result, 2); - - // Check files are still there - $this->assertTrue(file_exists(Character::getFileForId($charA->charId))); - $this->assertTrue(file_exists(Character::getFileForId($charB->charId))); - - // Check database is up-to-date - $chars = Characters::getBySession($wallId, $sessionId); - $this->assertIdentical(count($chars), 0); - - // Tidy up - unlink(Character::getFileForId($charA->charId)); - unlink(Character::getFileForId($charB->charId)); - } - - function testDeleteByWall() { - $wallId = $this->testWall->wallId; - - // Check initial state - $result = Characters::deleteByWall($wallId); - $this->assertIdentical($result, 0); - - // Add characters to first session - $this->createCharacter(); - $this->createCharacter(); - - // Start a new session and add characters - $this->testWall->startSession(); - $this->createCharacter(); - - // Delete characters - $result = Characters::deleteByWall($wallId); - $this->assertIdentical($result, 3); - $chars = Characters::getByWall($wallId); - $this->assertIdentical(count($chars), 0); - } - - function testDeleteBadWall() { - $wallId = $this->testWall->wallId; - $result = Characters::deleteByWall($wallId+1); - $this->assertIdentical($result, null); - } - - function testDeleteInvalidWall() { - foreach($this->invalidIds as $id) { - try { - $char = Characters::deleteByWall($id); - $this->fail("Failed to throw exception with bad id: $id"); - } catch (KeyedException $e) { - $this->assertEqual($e->getKey(), 'bad-request', - "Unexpected exception key bad id '$id': %s"); - } - } - } - - function testDeleteWallKeepFiles() { - $wallId = $this->testWall->wallId; - $char = $this->createCharacter(); - - // Delete characters - $result = - Characters::deleteByWall($wallId, CharacterDeleteMode::DeleteRecordOnly); - $file = Character::getFileForId($char->charId); - $this->assertTrue(file_exists($file)); - - // Tidy up - unlink($file); - } - - // We don't bother testing Character::deleteByWall with regards to missing - // files, locked files etc. since we rely on the fact that it's using the same - // underlying code as deleteBySession for that - - function testSetReadonly() { - $char = $this->createCharacter(); - try { - $char->charId = 5; - $this->fail("Failed to throw exception when setting character ID"); - } catch (KeyedException $e) { - $this->assertEqual($e->getKey(), "readonly-field"); - } - } - - function testEmptySave() { - $char = $this->createCharacter(); - $rv = $char->save(); - $this->assertTrue(is_array($rv), - "Even when there is nothing to save," - . " the return value should be an array"); - } - - function testSetActive() { - $char = $this->createCharacter(); - $this->assertIdentical(@$char->active, TRUE); - - // Update - $char->active = FALSE; - $rv = $char->save(); - $this->assertIdentical(@count($rv), 1, - "Unexpected number of changed fields when changing active state"); - $this->assertIdentical(@$rv['active'], FALSE); - - // Check if has been saved - $fetchedChar = Characters::getById($char->charId); - $this->assertIdentical($fetchedChar->active, FALSE); - - // Check no change - $char->active = FALSE; - $rv = $char->save(); - $this->assertIdentical(@count($rv), 0, "Redundant change not detected"); - - // Check value coercion - $char->active = "true"; - $rv = $char->save(); - $this->assertIdentical(@count($rv), 1, - "Unexpected number of changed fields when changing active state"); - $this->assertIdentical(@$rv['active'], TRUE); - } - - function testSetX() { - $char = $this->createCharacter(); - - // Update - $char->x = 0.432; - $rv = $char->save(); - $this->assertIdentical(@$rv['x'], 0.432); - - // Check if has been saved - $fetchedChar = Characters::getById($char->charId); - $this->assertIdentical($fetchedChar->x, 0.432); - - // Check value coercion - $char->x = "0.567"; - $rv = $char->save(); - $this->assertIdentical(@$rv['x'], 0.567); - - // Check out of range - try { - $char->x = 1.1; - $this->fail("Failed to throw exception with bad x value"); - } catch (KeyedException $e) { - $this->assertEqual($e->getKey(), "bad-request"); - } - } - - function testAsArray() { - $char = $this->createCharacter(); - - $array = $char->asArray(); - $this->assertTrue(is_array($array)); - // Check read-only fields - $this->assertIdentical(@$array['charId'], $char->charId); - // Check regular fields - $this->assertIdentical(@$array['wallId'], $char->wallId); - // Check virtual fields - $this->assertIdentical(@$array['galleryUrl'], $char->galleryUrl); - // Check some fields are dropped - $this->assertTrue(!array_key_exists('wall', $array)); - } - - function createPreviewFile($char) { - $previewFile = Character::getPreviewFile($char->charId); - file_put_contents($previewFile, "test"); - $this->assertTrue(file_exists($previewFile)); - } -} - -?> diff --git a/wall/tests/unit/TestWalls.php b/wall/tests/unit/TestWalls.php deleted file mode 100644 index 5a7ac590..00000000 --- a/wall/tests/unit/TestWalls.php +++ /dev/null @@ -1,337 +0,0 @@ -testCharacterFields; - - // Session 1 - $session1 = $this->testWall->latestSession; - $fields['title'] = 'Character A'; - $charA = $this->createCharacter($fields); - $fields['title'] = 'Character B'; - $charB = $this->createCharacter($fields); - - // Session 2 - $this->testWall->startSession(); - $session2 = $this->testWall->latestSession; - - // Session 3 - $this->testWall->startSession(); - $session3 = $this->testWall->latestSession; - $fields['title'] = 'Character C'; - $charC = $this->createCharacter($fields); - - // Get summary - $summary = $this->testWall->getSessions("Include characters"); - - // Test structure - $this->assertEqual(count($summary), 3); - - // Test session 1 - $this->assertIdentical($summary[0]['sessionId'], $session1['sessionId']); - $this->assertTrue(array_key_exists('characters', $summary[0]), - "No characters array along with session"); - $this->assertEqual(count(@$summary[0]['characters']), 2); - $this->assertIdentical(@$summary[0]['characters'][0], $charA); - $this->assertIdentical(@$summary[0]['characters'][1], $charB); - - // Test session 2 - $this->assertIdentical($summary[1]['sessionId'], $session2['sessionId']); - $this->assertTrue(array_key_exists('characters', $summary[1]), - "No characters array along with session"); - $this->assertEqual(count(@$summary[1]['characters']), 0); - - // Test session 3 - $this->assertIdentical($summary[2]['sessionId'], $session3['sessionId']); - $this->assertTrue(array_key_exists('characters', $summary[2]), - "No characters array along with session"); - $this->assertEqual(count(@$summary[2]['characters']), 1); - $this->assertIdentical(@$summary[2]['characters'][0], $charC); - } - - function testGetAll() { - // Get walls--should have only the test wall so far - $walls = Walls::getAllForUser("test@test.org"); - $this->assertEqual(count($walls), 1); - $this->assertIdentical(@$walls[0], $this->testWall); - - // Create a second wall - $wall2 = Walls::create("Second wall", $this->testWall->designId, - "test@test.org"); - $walls = Walls::getAllForUser("test@test.org"); - $this->assertEqual(count($walls), 2); - $this->assertIdentical(@$walls[0], $wall2); - - // Remove both walls - $wall2->destroy(); - $this->testWall->destroy(); - $walls = Walls::getAllForUser("test@test.org"); - $this->assertEqual(count($walls), 0); - } - - function testDeleteSession() { - // Check initial state - $summary = $this->testWall->getSessions(); - $this->assertIdentical(count($summary), 1); - $this->assertIdentical($this->testWall->status, "running"); - - // Delete session - $latestSessionId = $this->testWall->latestSession['sessionId']; - $rv = $this->testWall->deleteSession($latestSessionId); - $this->assertIdentical($rv, true); - - // Check state is updated - $summary = $this->testWall->getSessions(); - $this->assertIdentical(count($summary), 0); - $this->assertIdentical($this->testWall->status, "finished"); - $this->assertIdentical($this->testWall->latestSession, null); - } - - function testDeleteSessionWithPreviousSession() { - // Check initial state - $this->testWall->startSession(); - $summary = $this->testWall->getSessions(); - $this->assertIdentical(count($summary), 2); - $this->assertIdentical($this->testWall->status, "running"); - $this->assertIdentical($this->testWall->latestSession['sessionId'], 2); - $this->assertIdentical($this->testWall->latestSession['end'], null); - - // Delete session - $latestSessionId = $this->testWall->latestSession['sessionId']; - $rv = $this->testWall->deleteSession($latestSessionId); - $this->assertIdentical($rv, true); - - // Check state is updated - $summary = $this->testWall->getSessions(); - $this->assertIdentical(count($summary), 1); - $this->assertIdentical($this->testWall->status, "finished"); - $this->assertNotEqual($this->testWall->latestSession['sessionId'], null); - $this->assertIdentical($this->testWall->latestSession['sessionId'], 1); - $this->assertNotEqual($this->testWall->latestSession['end'], null); - } - - function testDeleteSessionBadId() { - // Check initial state - $summary = $this->testWall->getSessions(); - $this->assertIdentical(count($summary), 1); - - // Try deleting session - try { - $this->testWall->deleteSession( - $this->testWall->latestSession['sessionId'] + 1); - $this->fail("Failed to throw exception with bad session ID"); - } catch (KeyedException $e) { - $this->assertEqual($e->getKey(), "session-not-found"); - // Check nothing changed - // XXX Check no characters were deleted - $this->assertIdentical(count($summary), 1); - } - } - - function testDeleteNotLatestSession() { - // Create extra session - $firstSessionId = $this->testWall->latestSession['sessionId']; - $this->testWall->startSession(); - - // Delete session - $rv = $this->testWall->deleteSession($firstSessionId); - $this->assertIdentical($rv, true); - - // Check state is not updated - $summary = $this->testWall->getSessions(); - $this->assertIdentical(count($summary), 1); - $this->assertIdentical($this->testWall->status, "running"); - $this->assertNotEqual($this->testWall->latestSession, null); - } - - function testDeleteSessionAndCharacters() { - // Set up characters - $session = $this->testWall->latestSession; - $fields = $this->testCharacterFields; - $char = $this->createCharacter($fields); - - // Check initial state - $charFile = Character::getFileForId($char->charId); - $this->assertTrue(file_exists($charFile), "No SVG at $charFile"); - - // Delete - $rv = $this->testWall->deleteSession($session['sessionId']); - $this->assertIdentical($rv, true); - - // Check for characters - $this->assertFalse(file_exists($charFile), - "SVG still remains at $charFile"); - } - - function testDeleteSessionButNotCharacters() { - // Set up characters - $session = $this->testWall->latestSession; - $fields = $this->testCharacterFields; - $char = $this->createCharacter($fields); - - // Check initial state - $charFile = Character::getFileForId($char->charId); - $this->assertTrue(file_exists($charFile), "No SVG at $charFile"); - - // Delete record only - $rv = $this->testWall->deleteSession($session['sessionId'], - CharacterDeleteMode::DeleteRecordOnly); - $this->assertIdentical($rv, true); - - // Check for characters - $this->assertTrue(file_exists($charFile), - "SVG still remains at $charFile"); - - // Tidy up - @unlink($charFile); - } - - function testFailedDelete() { - // Set up characters - $session = $this->testWall->latestSession; - $fields = $this->testCharacterFields; - $char = $this->createCharacter($fields); - - // Check initial state - $charFile = Character::getFileForId($char->charId); - $this->assertTrue(file_exists($charFile), "No SVG at $charFile"); - - // Lock character file - $fp = fopen($charFile, "rw+"); - flock($fp, LOCK_EX); - - // Delete - try { - $this->testWall->deleteSession($session['sessionId']); - $this->fail("Failed to throw exception when deleting session with" - . " locked character file"); - } catch (KeyedException $e) { - $this->assertEqual($e->getKey(), 'server-error', - "Unexpected exception key when deleting locked file"); - } - - // Check status hasn't changed - $summary = $this->testWall->getSessions(); - $this->assertIdentical(count($summary), 1); - $this->assertIdentical($this->testWall->status, "running"); - - // Unlock file so it can be cleaned up - flock($fp, LOCK_UN); - fclose($fp); - } - - function testRestartSession() { - // Check initial state - $this->testWall->endSession(); - $this->assertIdentical($this->testWall->status, "finished"); - $this->assertNotEqual($this->testWall->latestSession['end'], null); - $originalStart = $this->testWall->latestSession['start']; - - // Re-open session - $rv = $this->testWall->restartSession(); - $this->assertIdentical($rv, true); - $this->assertIdentical($this->testWall->status, "running"); - $this->assertIdentical($this->testWall->latestSession['end'], null); - $this->assertIdentical($this->testWall->latestSession['start'], - $originalStart); - } - - function testRestartNotLatestSession() { - $this->testWall->startSession(); - $rv = $this->testWall->restartSession(1); - $this->assertIdentical($rv, false); - } - - function testRestartAlreadyOpenSession() { - $rv = $this->testWall->restartSession(1); - $this->assertIdentical($rv, false); - } - - function testRestartBadSession() { - $rv = $this->testWall->restartSession(2); - $this->assertIdentical($rv, false); - } - - function testDeleteWall() { - // Delete wall - $this->testWall->destroy(); - - // Check it has gone - $wall = Walls::getById($this->testWall->wallId); - $this->assertIdentical($wall, null, "Failed to delete wall: %s"); - } - - function testDeleteWallAndCharacters() { - // Create some characters - $session1 = $this->testWall->latestSession; - $fields = $this->testCharacterFields; - $fields['title'] = 'Character A'; - $charA = $this->createCharacter($fields); - - // Session 2 - $this->testWall->startSession(); - $session2 = $this->testWall->latestSession; - $fields['title'] = 'Character B'; - $charB = $this->createCharacter($fields); - - // Delete - $this->testWall->destroy(); - - // Check characters are gone - $charFile = Character::getFileForId($charA->charId); - $this->assertFalse(file_exists($charFile), "SVG still at $charFile"); - $charFile = Character::getFileForId($charB->charId); - $this->assertFalse(file_exists($charFile), "SVG still at $charFile"); - } - - function testDeleteWallNotCharacters() { - // Create some characters - $session1 = $this->testWall->latestSession; - $fields = $this->testCharacterFields; - $fields['title'] = 'Character A'; - $charA = $this->createCharacter($fields); - - // Session 2 - $this->testWall->startSession(); - $session2 = $this->testWall->latestSession; - $fields['title'] = 'Character B'; - $charB = $this->createCharacter($fields); - - // Delete - $this->testWall->destroy(CharacterDeleteMode::DeleteRecordOnly); - - // Check characters are still there - $charFile = Character::getFileForId($charA->charId); - $this->assertTrue(file_exists($charFile), "No SVG at $charFile"); - @unlink($charFile); - $charFile = Character::getFileForId($charB->charId); - $this->assertTrue(file_exists($charFile), "No SVG at $charFile"); - @unlink($charFile); - } -} - -?> diff --git a/wall/tests/unit/all_tests.php b/wall/tests/unit/all_tests.php deleted file mode 100644 index 1283f36c..00000000 --- a/wall/tests/unit/all_tests.php +++ /dev/null @@ -1,19 +0,0 @@ -TestSuite('Unit tests'); - $this->addFile(dirname(__FILE__) . '/TestCharacters.php'); - $this->addFile(dirname(__FILE__) . '/TestCharacterEmail.php'); - $this->addFile(dirname(__FILE__) . '/TestCharacterFile.php'); - $this->addFile(dirname(__FILE__) . '/TestWalls.php'); - } -} -?> diff --git a/wall/tests/unit/characters/animate-and-co.in.svg b/wall/tests/unit/characters/animate-and-co.in.svg deleted file mode 100644 index 96e44b1f..00000000 --- a/wall/tests/unit/characters/animate-and-co.in.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/wall/tests/unit/characters/animate-and-co.static.svg b/wall/tests/unit/characters/animate-and-co.static.svg deleted file mode 100644 index c2615be8..00000000 --- a/wall/tests/unit/characters/animate-and-co.static.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/wall/tests/unit/characters/metadata.in.svg b/wall/tests/unit/characters/metadata.in.svg deleted file mode 100644 index b0d5c35a..00000000 --- a/wall/tests/unit/characters/metadata.in.svg +++ /dev/null @@ -1 +0,0 @@ -TitleNameさんより diff --git a/wall/tests/unit/characters/metadata.static.svg b/wall/tests/unit/characters/metadata.static.svg deleted file mode 100644 index 331cde42..00000000 --- a/wall/tests/unit/characters/metadata.static.svg +++ /dev/null @@ -1 +0,0 @@ -TitleNameさんより diff --git a/wall/tests/unit/characters/multi-frame.in.svg b/wall/tests/unit/characters/multi-frame.in.svg deleted file mode 100644 index 4f480411..00000000 --- a/wall/tests/unit/characters/multi-frame.in.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/wall/tests/unit/characters/multi-frame.static.svg b/wall/tests/unit/characters/multi-frame.static.svg deleted file mode 100644 index 4c205105..00000000 --- a/wall/tests/unit/characters/multi-frame.static.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/wall/tests/unit/characters/nested-g.in.svg b/wall/tests/unit/characters/nested-g.in.svg deleted file mode 100644 index b7364b44..00000000 --- a/wall/tests/unit/characters/nested-g.in.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/wall/tests/unit/characters/nested-g.static.svg b/wall/tests/unit/characters/nested-g.static.svg deleted file mode 100644 index 33cc4756..00000000 --- a/wall/tests/unit/characters/nested-g.static.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/wall/tests/unit/characters/no-frames.in.svg b/wall/tests/unit/characters/no-frames.in.svg deleted file mode 100644 index 59eb7a01..00000000 --- a/wall/tests/unit/characters/no-frames.in.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/wall/tests/unit/characters/no-frames.static.svg b/wall/tests/unit/characters/no-frames.static.svg deleted file mode 100644 index 59eb7a01..00000000 --- a/wall/tests/unit/characters/no-frames.static.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/wall/tests/unit/characters/single-frame.in.svg b/wall/tests/unit/characters/single-frame.in.svg deleted file mode 100644 index c2615be8..00000000 --- a/wall/tests/unit/characters/single-frame.in.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/wall/tests/unit/characters/single-frame.static.svg b/wall/tests/unit/characters/single-frame.static.svg deleted file mode 100644 index c2615be8..00000000 --- a/wall/tests/unit/characters/single-frame.static.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/wall/tests/unit/characters/two-frame.in.svg b/wall/tests/unit/characters/two-frame.in.svg deleted file mode 100644 index 87e0cc0e..00000000 --- a/wall/tests/unit/characters/two-frame.in.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/wall/tests/unit/characters/two-frame.static.svg b/wall/tests/unit/characters/two-frame.static.svg deleted file mode 100644 index 8cfa7476..00000000 --- a/wall/tests/unit/characters/two-frame.static.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/wall/tools/fillInShortUrls.php b/wall/tools/fillInShortUrls.php deleted file mode 100644 index ef260d0c..00000000 --- a/wall/tools/fillInShortUrls.php +++ /dev/null @@ -1,67 +0,0 @@ -query('SELECT * FROM characters ORDER BY charId'); -checkDbResult($res); - -// Iterate -$conn->setFetchMode(MDB2_FETCHMODE_ASSOC); -while ($row = $res->fetchRow()) { - print "Character " . $row['charid'] . "... "; - - // See if it already has a short URL - // (Remove this to overwrite all short URLs) - if ($row[strtolower($field)] !== null) { - print "has URL, skipping.\n"; - continue; - } - - // Get short URL - $shortUrl = Character::getShortGalleryUrl($row['charid']); - if (!$shortUrl) { - print "couldn't get short URL, skipping.\n"; - continue; - } - - // Update record - print "saving short URL ($shortUrl)... "; - $query = 'UPDATE characters SET ' - . ' galleryUrlShort = ' . $conn->quote($shortUrl, 'text') - . ' WHERE charId = ' . $conn->quote($row['charid'], 'integer'); - $updateRes =& $conn->exec($query); - checkDbResult($updateRes); - print "saved.\n"; -} - -// Done -$conn->disconnect(); -print "Done.\n"; - -?> diff --git a/wall/tools/flipbook.html b/wall/tools/flipbook.html deleted file mode 100755 index 262b948f..00000000 --- a/wall/tools/flipbook.html +++ /dev/null @@ -1,103 +0,0 @@ - - - - - パラパラ漫画 - - - - - - - -