diff --git a/src/ID3/Encoding.php b/src/ID3/Encoding.php
index c0966d1..ad512b4 100644
--- a/src/ID3/Encoding.php
+++ b/src/ID3/Encoding.php
@@ -69,4 +69,11 @@ interface ID3_Encoding
* @return integer
*/
public function getEncoding();
+
+ /**
+ * Sets the text encoding.
+ *
+ * @param integer $encoding The text encoding.
+ */
+ public function setEncoding($encoding);
}
diff --git a/src/ID3/ExtendedHeader.php b/src/ID3/ExtendedHeader.php
index a7648a0..c299074 100644
--- a/src/ID3/ExtendedHeader.php
+++ b/src/ID3/ExtendedHeader.php
@@ -36,7 +36,7 @@
*/
/**#@+ @ignore */
-require_once("Object.php");
+require_once("ID3/Object.php");
/**#@-*/
/**
@@ -96,7 +96,7 @@ final class ID3_ExtendedHeader extends ID3_Object
{
parent::__construct($reader);
- $offset = $this->_reader->offset;
+ $offset = $this->_reader->getOffset();
$this->_size = $this->decodeSynchsafe32($this->_reader->readUInt32BE());
$this->_reader->skip(1);
$this->_flags = $this->_reader->readInt8();
@@ -105,7 +105,7 @@ final class ID3_ExtendedHeader extends ID3_Object
$this->_reader->skip(1);
if ($this->hasFlag(self::CRC32)) {
$this->_reader->skip(1);
- $this->_crc = Transform::getInt32BE
+ $this->_crc = Transform::fromInt32BE
(($this->_reader->read(1) << 4) &
$this->decodeSynchsafe32($this->_reader->read(4)));
}
@@ -114,7 +114,7 @@ final class ID3_ExtendedHeader extends ID3_Object
$this->_restrictions = $this->_reader->readInt8(1);
}
- $this->_reader->skip($this->_size - $this->_reader->offset - $offset);
+ $this->_reader->skip($this->_size - $this->_reader->getOffset() - $offset);
}
/**
@@ -133,12 +133,44 @@ final class ID3_ExtendedHeader extends ID3_Object
*/
public function hasFlag($flag) { return ($this->_flags & $flag) == $flag; }
+ /**
+ * Returns the flags byte.
+ *
+ * @return integer
+ */
+ public function getFlags($flags) { return $this->_flags; }
+
+ /**
+ * Sets the flags byte.
+ *
+ * @param integer $flags The flags byte.
+ */
+ public function setFlags($flags) { $this->_flags = $flags; }
+
/**
* Returns the CRC-32 data.
*
* @return integer
*/
- public function getCRC() { return $this->_crc; }
+ public function getCrc()
+ {
+ if ($this->hasFlag(self::CRC32))
+ return $this->_crc;
+ return false;
+ }
+
+ /**
+ * Sets whether the CRC-32 should be generated upon tag write.
+ *
+ * @param boolean $useCrc Whether CRC-32 should be generated
+ */
+ public function setCrc($useCrc)
+ {
+ if ($useCrc)
+ $this->setFlags($this->getFlags() | self::CDC32);
+ else
+ $this->setFlags($this->getFlags() & ~self::CDC32);
+ }
/**
* Returns the restrictions. For some applications it might be desired to
@@ -189,4 +221,30 @@ final class ID3_ExtendedHeader extends ID3_Object
* @return integer
*/
public function getRestrictions() { return $this->_restrictions; }
+
+ /**
+ * Sets the restrictions byte. See {@link #getRestrictions} for more.
+ *
+ * @param integer $restrictions The restrictions byte.
+ */
+ public function setRestrictions($restrictions)
+ {
+ $this->_restrictions = $restrictions;
+ }
+
+ /**
+ * Returns the header raw data.
+ *
+ * @todo CRC must use safesynch
+ * @return string
+ */
+ public function toString()
+ {
+ return Transform::toUInt32BE($this->encodeSynchsafe32($this->_size)) .
+ Transform::toInt8(1) . Transform::toInt8($this->_flags) .
+ ($this->hasFlag(self::UPDATE) ? "\0" : "") .
+ ($this->hasFlag(self::CRC32) ? Transform::toInt8(5) . $this->_crc : "") .
+ ($this->hasFlag(self::RESTRICTED) ?
+ Transform::toInt8(1) . Transform::toInt8($this->_restrictions) : "");
+ }
}
diff --git a/src/ID3/Frame.php b/src/ID3/Frame.php
index 9af49f0..01e32ed 100644
--- a/src/ID3/Frame.php
+++ b/src/ID3/Frame.php
@@ -36,7 +36,7 @@
*/
/**#@+ @ignore */
-require_once("Object.php");
+require_once("ID3/Object.php");
/**#@-*/
/**
@@ -117,17 +117,17 @@ class ID3_Frame extends ID3_Object
private $_identifier;
/** @var integer */
- private $_size;
+ private $_size = 0;
/** @var integer */
- private $_flags;
+ private $_flags = 0;
/**
- * Raw content read from the frame.
+ * Raw content of the frame.
*
* @var string
*/
- protected $_data;
+ protected $_data = "";
/**
* Constructs the class with given parameters and reads object related data
@@ -136,14 +136,18 @@ class ID3_Frame extends ID3_Object
* @todo Only limited subset of flags are processed.
* @param Reader $reader The reader object.
*/
- public function __construct($reader)
+ public function __construct($reader = null)
{
parent::__construct($reader);
-
- $this->_identifier = $this->_reader->readString8(4);
- $this->_size = $this->decodeSynchsafe32($this->_reader->readUInt32BE());
- $this->_flags = $this->_reader->readUInt16BE();
- $this->_data = $this->_reader->read($this->_size);
+
+ if ($reader === null) {
+ $this->_identifier = substr(get_class($this), -4);
+ } else {
+ $this->_identifier = $this->_reader->readString8(4);
+ $this->_size = $this->decodeSynchsafe32($this->_reader->readUInt32BE());
+ $this->_flags = $this->_reader->readUInt16BE();
+ $this->_data = $this->_reader->read($this->_size);
+ }
}
/**
@@ -185,18 +189,35 @@ class ID3_Frame extends ID3_Object
*
* @return integer
*/
- public function getFlags($flags)
- {
- return $this->_flags;
- }
+ public function getFlags($flags) { return $this->_flags; }
/**
* Sets the frame flags byte.
*
* @param string $flags The flags byte.
*/
- public function setFlags($flags)
+ public function setFlags($flags) { $this->_flags = $flags; }
+
+ /**
+ * Sets the frame raw data.
+ *
+ * @return string
+ */
+ protected function setData($data)
{
- $this->_flags = $flags;
+ $this->_data = $data;
+ $this->_size = strlen($data);
+ }
+
+ /**
+ * Returns the frame raw data.
+ *
+ * @return string
+ */
+ public function __toString()
+ {
+ return Transform::toString8(substr($this->_identifier, 0, 4), 4) .
+ Transform::toUInt32BE($this->encodeSynchsafe32($this->_size)) .
+ Transform::toUInt16BE($this->_flags) . $this->_data;
}
}
diff --git a/src/ID3/Frame/AbstractLink.php b/src/ID3/Frame/AbstractLink.php
index 5120923..51694c6 100644
--- a/src/ID3/Frame/AbstractLink.php
+++ b/src/ID3/Frame/AbstractLink.php
@@ -59,10 +59,12 @@ abstract class ID3_Frame_AbstractLink extends ID3_Frame
*
* @param Reader $reader The reader object.
*/
- public function __construct($reader)
+ public function __construct($reader = null)
{
parent::__construct($reader);
- $this->_link = preg_split("/\\x00/", $this->_data, 1);
+
+ if ($reader !== null)
+ $this->_link = preg_split("/\\x00/", $this->_data, 1);
}
/**
@@ -71,4 +73,22 @@ abstract class ID3_Frame_AbstractLink extends ID3_Frame
* @return string
*/
public function getLink() { return $this->_link; }
+
+ /**
+ * Sets the link.
+ *
+ * @param string $link The link.
+ */
+ public function setLink($link) { $this->_link = $link; }
+
+ /**
+ * Returns the frame raw data.
+ *
+ * @return string
+ */
+ public function __toString()
+ {
+ $this->setData($link);
+ return parent::__toString();
+ }
}
diff --git a/src/ID3/Frame/AbstractText.php b/src/ID3/Frame/AbstractText.php
index dae85dd..5aebf38 100644
--- a/src/ID3/Frame/AbstractText.php
+++ b/src/ID3/Frame/AbstractText.php
@@ -54,7 +54,7 @@ abstract class ID3_Frame_AbstractText extends ID3_Frame
implements ID3_Encoding
{
/** @var integer */
- private $_encoding;
+ private $_encoding = ID3_Encoding::UTF8;
/** @var string */
private $_text;
@@ -64,10 +64,13 @@ abstract class ID3_Frame_AbstractText extends ID3_Frame
*
* @param Reader $reader The reader object.
*/
- public function __construct($reader)
+ public function __construct($reader = null)
{
parent::__construct($reader);
-
+
+ if ($reader === null)
+ return;
+
$this->_encoding = ord($this->_data{0});
$this->_data = substr($this->_data, 1);
switch ($this->_encoding) {
@@ -91,11 +94,61 @@ abstract class ID3_Frame_AbstractText extends ID3_Frame
* @return integer
*/
public function getEncoding() { return $this->_encoding; }
-
+
+ /**
+ * Sets the text encoding.
+ *
+ * @param integer $encoding The text encoding.
+ */
+ public function setEncoding($encoding) { $this->_encoding = $encoding; };
+
+ /**
+ * Returns the first text chunk the frame contains.
+ *
+ * @return string
+ */
+ public function getText() { return $this->_text[0]; }
+
/**
* Returns an array of texts the frame contains.
*
* @return Array
*/
- public function getText() { return $this->_text; }
+ public function getTexts() { return $this->_text; }
+
+ /**
+ * Sets the text using given encoding.
+ *
+ * @param mixed $text The test string or an array of strings.
+ */
+ public function setText($text, $encoding = ID3_Encoding::UTF8)
+ {
+ $this->_encoding = $encoding;
+ $this->_text = is_array($text) ? $text : array($text);
+ }
+
+ /**
+ * Returns the frame raw data.
+ *
+ * @return string
+ */
+ public function __toString()
+ {
+ $data = Transform::toInt8($this->_encoding);
+ switch ($this->_encoding) {
+ case self::UTF16:
+ $data .= Transform::toString16(implode("\0\0", $this->_text));
+ break;
+ case self::UTF16BE:
+ $data .= Transform::toString16BE(implode("\0\0", $this->_text));
+ break;
+ case self::UTF16LE:
+ $data .= Transform::toString16LE(implode("\0\0", $this->_text));
+ break;
+ default:
+ $data .= implode("\0", $this->_text);
+ }
+ $this->setData($data);
+ return parent::__toString();
+ }
}
diff --git a/src/ID3/Header.php b/src/ID3/Header.php
index 8c3f75a..c7ce031 100644
--- a/src/ID3/Header.php
+++ b/src/ID3/Header.php
@@ -36,7 +36,7 @@
*/
/**#@+ @ignore */
-require_once("Object.php");
+require_once("ID3/Object.php");
/**#@-*/
/**
@@ -72,13 +72,13 @@ final class ID3_Header extends ID3_Object
const FOOTER = 32;
/** @var integer */
- private $_version;
+ private $_version = 4;
/** @var integer */
- private $_revision;
+ private $_revision = 0;
/** @var integer */
- private $_flags;
+ private $_flags = 0;
/** @var integer */
private $_size;
@@ -89,10 +89,13 @@ final class ID3_Header extends ID3_Object
*
* @param Reader $reader The reader object.
*/
- public function __construct($reader)
+ public function __construct($reader = null)
{
parent::__construct($reader);
-
+
+ if ($reader === null)
+ return;
+
$this->_version = $this->_reader->readInt8();
$this->_revision = $this->_reader->readInt8();
$this->_flags = $this->_reader->readInt8();
@@ -122,10 +125,45 @@ final class ID3_Header extends ID3_Object
*/
public function hasFlag($flag) { return ($this->_flags & $flag) == $flag; }
+ /**
+ * Returns the flags byte.
+ *
+ * @return integer
+ */
+ public function getFlags($flags) { return $this->_flags; }
+
+ /**
+ * Sets the flags byte.
+ *
+ * @param string $flags The flags byte.
+ */
+ public function setFlags($flags) { $this->_flags = $flags; }
+
/**
* Returns the tag size, excluding the header and the footer.
*
* @return integer
*/
public function getSize() { return $this->_size; }
+
+ /**
+ * Sets the tag size, excluding the header and the footer. Called
+ * automatically upon tag generation to adjust the tag size.
+ *
+ * @param integer $size The size of the tag, in bytes.
+ */
+ public function setSize($size) { $this->_size = $size; }
+
+ /**
+ * Returns the header/footer raw data without the identifier.
+ *
+ * @return string
+ */
+ protected function __toString()
+ {
+ return Transform::toInt8($this->_version) .
+ Transform::toInt8($this->_revision) .
+ Transform::toInt8($this->_flags) .
+ Transform::toUInt32BE($this->encodeSynchsafe32($this->_size));
+ }
}
diff --git a/src/ID3/Language.php b/src/ID3/Language.php
index 785496f..e4f6336 100644
--- a/src/ID3/Language.php
+++ b/src/ID3/Language.php
@@ -59,4 +59,11 @@ interface ID3_Language
* @return string
*/
public function getLanguage();
+
+ /**
+ * Sets the text language code.
+ *
+ * @param string $language The text language code.
+ */
+ public function setLanguage($language);
}
diff --git a/src/ID3/Timing.php b/src/ID3/Timing.php
index bbcccd0..7eafee2 100644
--- a/src/ID3/Timing.php
+++ b/src/ID3/Timing.php
@@ -63,4 +63,11 @@ interface ID3_Timing
* @return integer
*/
public function getFormat();
+
+ /**
+ * Sets the timing format.
+ *
+ * @param integer $format The timing format.
+ */
+ public function setFormat($format);
}
diff --git a/src/ID3v1.php b/src/ID3v1.php
index 29a7b45..9128d5c 100644
--- a/src/ID3v1.php
+++ b/src/ID3v1.php
@@ -123,9 +123,9 @@ final class ID3v1
return;
$this->_reader = new Reader($filename);
- if ($this->_reader->size < 128)
+ if ($this->_reader->getSize() < 128)
return;
- $this->_reader->offset = -128;
+ $this->_reader->setOffset(-128);
if ($this->_reader->read(3) != "TAG") {
$this->_reader = false; // reset reader, see write
return;
diff --git a/src/ID3v2.php b/src/ID3v2.php
index 7e89642..6990265 100644
--- a/src/ID3v2.php
+++ b/src/ID3v2.php
@@ -99,7 +99,7 @@ final class ID3v2
private $_extendedHeader;
/** @var ID3_Header */
- private $_footer = null;
+ private $_footer;
/** @var Array */
private $_frames = array();
@@ -111,7 +111,7 @@ final class ID3v2
* Constructs the ID3v2 class with given file and options.
*
* @todo Only limited subset of flags are processed.
- * @todo ID3_Footer
+ * @todo Utilize the SEEK frame and search for a footer to find the tag
* @param string $filename The path to the file.
* @param Array $options The options array.
*/
@@ -123,8 +123,10 @@ final class ID3v2
}
if (($this->_filename = $filename) === false ||
- file_exists($filename) === false)
+ file_exists($filename) === false) {
+ $this->_header = new ID3_Header();
return;
+ }
$this->_reader = new Reader($filename);
@@ -137,12 +139,8 @@ final class ID3v2
("File does not contain ID3v2 tag of supported version: " . $filename);
if ($this->_header->hasFlag(ID3_Header::EXTENDEDHEADER))
$this->_extendedHeader = new ID3_ExtendedHeader($this->_reader);
- if ($this->_header->hasFlag(ID3_Header::FOOTER)) {
- $offset = $this->_reader->offset;
- $this->_reader->offset = $this->_header->getSize() + 10;
- $this->_footer = new ID3_Header($this->_reader);
- $this->_reader->offset = $offset;
- }
+ if ($this->_header->hasFlag(ID3_Header::FOOTER))
+ $this->_footer = &$this->_header; // skip footer, and rather copy header
while ($frame = $this->nextFrame()) {
if (!isset($this->_frames[$frame->identifier]))
@@ -166,7 +164,8 @@ final class ID3v2
*/
public function hasExtendedHeader()
{
- return $this->_header->hasFlag(ID3_Header::EXTENDEDHEADER);
+ if ($this->_header)
+ return $this->_header->hasFlag(ID3_Header::EXTENDEDHEADER);
}
/**
@@ -182,6 +181,20 @@ final class ID3v2
return false;
}
+ /**
+ * Sets the extended header object.
+ *
+ * @param ID3_ExtendedHeader $extendedHeader The header object
+ */
+ public function setExtendedHeader($extendedHeader)
+ {
+ if (is_subclass_of($extendedHeader, "ID3_ExtendedHeader")) {
+ $this->_header->flags =
+ $this->_header->flags | ID3_Header::EXTENDEDHEADER;
+ $this->_extendedHeader = $extendedHeader;
+ } else throw new ID3_Exception("Invalid argument");
+ }
+
/**
* Checks whether there are frames left in the tag. Returns true if
* there are frames left in the tag, false otherwise.
@@ -190,16 +203,16 @@ final class ID3v2
*/
protected function hasFrames()
{
- $offset = $this->_reader->offset;
+ $offset = $this->_reader->getOffset();
// Return false if we reached the end of the tag
- if ($offset >= $this->_header->getSize() - 10 -
+ if ($offset - 10 >= $this->_header->getSize() -
($this->hasFooter() ? 10 : 0))
return false;
// Return false if we reached the last frame, true otherwise
$res = $this->_reader->readUInt32BE() != 0;
- $this->_reader->offset = $offset;
+ $this->_reader->setOffset($offset);
return $res;
}
@@ -214,10 +227,11 @@ final class ID3v2
{
$frame = false;
if ($this->hasFrames()) {
- $offset = $this->_reader->offset;
+ $offset = $this->_reader->getOffset();
$identifier = $this->_reader->readString8(4);
- $this->_reader->offset = $offset;
- if (file_exists($filename = "ID3/Frame/" . $identifier . ".php"))
+ $this->_reader->setOffset($offset);
+ if (@fopen($filename = "ID3/Frame/" .
+ strtoupper($identifier) . ".php", "r", true) !== false)
require_once($filename);
if (class_exists($classname = "ID3_Frame_" . $identifier))
$frame = new $classname($this->_reader);
@@ -276,6 +290,19 @@ final class ID3v2
return $matches;
}
+ /**
+ * Adds a new frame to the tag and returns it.
+ *
+ * @param ID3_Frame $frame The frame to add.
+ * @return ID3_Frame
+ */
+ public function addFrame($frame)
+ {
+ if (!$this->hasFrame($frame->getIdentifier()))
+ $this->_frames[$frame->getIdentifier()] = array();
+ return $this->_frames[$frame->getIdentifier()][] = $frame;
+ }
+
/**
* Checks whether there is a footer present in the tag. Returns
* true if the footer is present, false otherwise.
@@ -299,18 +326,131 @@ final class ID3v2
return false;
}
+ /**
+ * Sets whether the tag should have a footer defined.
+ *
+ * @param boolean $useFooter Whether the tag should have a footer
+ */
+ public function setFooter($useFooter)
+ {
+ if ($useFooter) {
+ $this->_header->setFlags
+ ($this->_header->getFlags() | ID3_Header::FOOTER);
+ $this->_footer = &$this->_header;
+ } else {
+ /* Count footer bytes towards the tag size, so it gets removed or
+ overridden upon re-write */
+ if ($this->hasFooter())
+ $this->_header->setSize($this->_header->getSize() + 10);
+
+ $this->_header->setFlags
+ ($this->_header->getFlags() & ~ID3_Header::FOOTER);
+ $this->_footer = null;
+ }
+ }
+
+ /**
+ * Writes the possibly altered ID3v2 tag back to the file where it was read.
+ * If the class was constructed without a file name, one can be provided here
+ * as an argument. Regardless, the write operation will override previous
+ * tag information, if found.
+ *
+ * If write is called without setting any frames to the tag, the tag is
+ * removed from the file.
+ *
+ * @param string $filename The optional path to the file.
+ */
+ public function write($filename = false)
+ {
+ if (empty($this->_frames))
+ throw new ID3_Exception("Tag must contain at least one frame");
+
+ if ($filename === false && ($filename = $this->_filename) === false)
+ throw new ID3_Exception("No file given to write the tag to");
+
+ if (($fd = fopen
+ ($filename, file_exists($filename) ? "r+b" : "wb")) === false)
+ throw new ID3_Exception("Unable to open file for writing: " . $filename);
+
+ $oldTagSize = $this->_header->getSize();
+ $tag = "" . $this;
+ $tagSize = strlen($tag);
+
+ if ($this->_reader === null || $tagSize - 10 > $oldTagSize) {
+ fseek($fd, 0, SEEK_END);
+ $oldFileSize = ftell($fd);
+ ftruncate($fd, $newFileSize = $tagSize - $oldTagSize + $oldFileSize);
+ for ($i = 1, $cur = $oldFileSize; $cur > 0; $cur -= 1024, $i++) {
+ fseek($fd, -(($i * 1024) + ($newFileSize - $oldFileSize)), SEEK_END);
+ $buffer = fread($fd, 1024);
+ fseek($fd, -($i * 1024), SEEK_END);
+ fwrite($fd, $buffer, 1024);
+ }
+ }
+ fseek($fd, 0);
+ fwrite($fd, $tag);
+
+ $this->_filename = $filename;
+ }
+
/**
* Magic function so that $obj->value will work. The method will attempt to
* return the first frame that matches the identifier.
*
+ * If there is no frame or field with given name, the method will attempt to
+ * create a frame with given identifier.
+ *
+ * If none of these work, an exception is thrown.
+ *
* @param string $name The frame or field name.
* @return mixed
*/
public function __get($name) {
- if (isset($this->_frames[$name]))
- return $this->_frames[$name][0];
+ if (isset($this->_frames[strtoupper($name)]))
+ return $this->_frames[strtoupper($name)][0];
if (method_exists($this, "get" . ucfirst($name)))
return call_user_func(array($this, "get" . ucfirst($name)));
- else throw new ID3_Exception("Unknown frame/field: " . $name);
+ if (@fopen($filename =
+ "ID3/Frame/" . strtoupper($name) . ".php", "r", true) !== false)
+ require_once($filename);
+ if (class_exists($classname = "ID3_Frame_" . strtoupper($name)))
+ return $this->addFrame(new $classname());
+ throw new ID3_Exception("Unknown frame/field: " . $name);
+ }
+
+ /**
+ * Returns the tag raw data.
+ *
+ * @return string
+ */
+ public function __toString()
+ {
+ $data = "";
+ if ($this->hasExtendedHeader())
+ $data .= $this->getExtendedHeader();
+ foreach ($this->_frames as $frames)
+ foreach ($frames as $frame)
+ $data .= $frame;
+
+ $datalen = strlen($data);
+ $padlen = 0;
+
+ /* The tag padding is calculated as follows. If the tag can be written in
+ the space of the previous tag, the remaining space is used for padding.
+ If there is no previous tag or the new tag is bigger than the space taken
+ by the previous tag, the padding is calculated using the following
+ logaritmic equation: log(0.2(x + 10)), ranging from some 300 bytes to
+ almost 5000 bytes given the tag length of 0..256M. */
+ if ($this->hasFooter() === false) {
+ if ($this->_reader !== null && $datalen < $this->_header->getSize())
+ $padlen = $this->_header->getSize() - $datalen;
+ else
+ $padlen = ceil(log(0.2 * ($datalen / 1024 + 10), 10) * 1024);
+ }
+
+ $this->_header->setSize($datalen + $padlen);
+
+ return "ID3" . $this->_header . str_pad($data, $datalen + $padlen, "\0") .
+ ($this->hasFooter() ? "3DI" . $this->getFooter() : "");
}
}
diff --git a/src/Transform.php b/src/Transform.php
index ed410cb..59cddcb 100644
--- a/src/Transform.php
+++ b/src/Transform.php
@@ -332,9 +332,9 @@ final class Transform
public static function fromString16($value)
{
if ($value{0} == 0xfe && $value{1} = 0xff)
- return self::fromString16LE(substr($value, 2));
- else
return self::fromString16BE(substr($value, 2));
+ else
+ return self::fromString16LE(substr($value, 2));
}
/**
diff --git a/tests/TestAll.php b/tests/TestAll.php
index 0275732..c635446 100644
--- a/tests/TestAll.php
+++ b/tests/TestAll.php
@@ -1,57 +1,58 @@
-addTestSuite(substr($file, 0, -4));
- }
-}
-closedir($dir);
-
-PHPUnit_TextUI_TestRunner::run($suite);
-/**#@-*/
+addTestSuite(substr($file, 0, -4));
+ }
+}
+closedir($dir);
+
+PHPUnit_TextUI_TestRunner::run($suite);
+/**#@-*/
diff --git a/tests/TestID3v1.php b/tests/TestID3v1.php
index 1f7c7de..5c58950 100644
--- a/tests/TestID3v1.php
+++ b/tests/TestID3v1.php
@@ -1,194 +1,194 @@
-
- * @copyright Copyright (c) 2008 The PHP Reader Project Workgroup
- * @license http://code.google.com/p/php-reader/wiki/License New BSD License
- * @version $Rev$
- */
-final class TestID3v1 extends PHPUnit_Framework_TestCase
-{
- function testTagCreate()
- {
- $id3 = new ID3v1();
-
- $id3->title = "Title 1";
- $this->assertEquals("Title 1", $id3->title);
-
- $id3->artist = "Artist 1";
- $this->assertEquals("Artist 1", $id3->artist);
-
- $id3->album = "Album 1";
- $this->assertEquals("Album 1", $id3->album);
-
- $id3->year = "2008";
- $this->assertEquals("2008", $id3->year);
-
- $id3->comment = "Comment 1";
- $this->assertEquals("Comment 1", $id3->comment);
-
- $id3->track = 30;
- $this->assertEquals(30, $id3->track);
-
- $id3->genre = array_search("Classical", ID3v1::$genres);
- $this->assertEquals("Classical", $id3->genre);
-
- $id3->write("id3v1.tag");
- }
-
- function testTagReadAfterCreate()
- {
- $id3 = new ID3v1("id3v1.tag");
- $this->assertEquals("Title 1", $id3->title);
- $this->assertEquals("Artist 1", $id3->artist);
- $this->assertEquals("Album 1", $id3->album);
- $this->assertEquals("2008", $id3->year);
- $this->assertEquals("Comment 1", $id3->comment);
- $this->assertEquals(30, $id3->track);
- $this->assertEquals("Classical", $id3->genre);
- }
-
- function testTagChange()
- {
- $id3 = new ID3v1("id3v1.tag");
-
- $id3->title = "Title 2";
- $this->assertEquals("Title 2", $id3->title);
-
- $id3->artist = "Artist 2";
- $this->assertEquals("Artist 2", $id3->artist);
-
- $id3->album = "Album 2";
- $this->assertEquals("Album 2", $id3->album);
-
- $id3->year = "2045";
- $this->assertEquals("2045", $id3->year);
-
- $id3->comment = "Comment 2";
- $this->assertEquals("Comment 2", $id3->comment);
-
- $id3->track = 10;
- $this->assertEquals(10, $id3->track);
-
- $id3->genre = array_search("Trance", ID3v1::$genres);
- $this->assertEquals("Trance", $id3->genre);
-
- $id3->write();
- }
-
- function testTagReadAfterChange()
- {
- $id3 = new ID3v1("id3v1.tag");
- $this->assertEquals("Title 2", $id3->title);
- $this->assertEquals("Artist 2", $id3->artist);
- $this->assertEquals("Album 2", $id3->album);
- $this->assertEquals("2045", $id3->year);
- $this->assertEquals("Comment 2", $id3->comment);
- $this->assertEquals(10, $id3->track);
- $this->assertEquals("Trance", $id3->genre);
- }
-
- function testTagReplace()
- {
- $id3 = new ID3v1();
-
- $id3->title = "Title 3";
- $this->assertEquals("Title 3", $id3->title);
- $this->assertEquals("Unknown", $id3->genre);
-
- $id3->write("id3v1.tag");
- }
-
- function testTagReadAfterReplace()
- {
- $id3 = new ID3v1("id3v1.tag");
- $this->assertEquals("Title 3", $id3->title);
- $this->assertEquals("", $id3->artist);
- $this->assertEquals("", $id3->album);
- $this->assertEquals("", $id3->year);
- $this->assertEquals("", $id3->comment);
- $this->assertEquals("", $id3->track);
- $this->assertEquals("Unknown", $id3->genre);
- }
-
- function testTagCreateVersion10()
- {
- $id3 = new ID3v1();
-
- $id3->title = "Title 4";
- $this->assertEquals("Title 4", $id3->title);
-
- $id3->artist = "Artist 4";
- $this->assertEquals("Artist 4", $id3->artist);
-
- $id3->album = "Album 4";
- $this->assertEquals("Album 4", $id3->album);
-
- $id3->year = "2020";
- $this->assertEquals("2020", $id3->year);
-
- $id3->comment = "A comment field with 30 chars.";
- $this->assertEquals("A comment field with 30 chars.", $id3->comment);
-
- $id3->genre = array_search("Classical", ID3v1::$genres);
- $this->assertEquals("Classical", $id3->genre);
-
- $id3->write("id3v1.tag");
- }
-
- function testTagReadAfterCreateVersion10()
- {
- $id3 = new ID3v1("id3v1.tag");
- $this->assertEquals("Title 4", $id3->title);
- $this->assertEquals("Artist 4", $id3->artist);
- $this->assertEquals("Album 4", $id3->album);
- $this->assertEquals("2020", $id3->year);
- $this->assertEquals("A comment field with 30 chars.", $id3->comment);
- $this->assertEquals("", $id3->track);
- $this->assertEquals("Classical", $id3->genre);
- }
-}
+
+ * @copyright Copyright (c) 2008 The PHP Reader Project Workgroup
+ * @license http://code.google.com/p/php-reader/wiki/License New BSD License
+ * @version $Rev$
+ */
+final class TestID3v1 extends PHPUnit_Framework_TestCase
+{
+ function testTagCreate()
+ {
+ $id3 = new ID3v1();
+
+ $id3->title = "Title 1";
+ $this->assertEquals("Title 1", $id3->title);
+
+ $id3->artist = "Artist 1";
+ $this->assertEquals("Artist 1", $id3->artist);
+
+ $id3->album = "Album 1";
+ $this->assertEquals("Album 1", $id3->album);
+
+ $id3->year = "2008";
+ $this->assertEquals("2008", $id3->year);
+
+ $id3->comment = "Comment 1";
+ $this->assertEquals("Comment 1", $id3->comment);
+
+ $id3->track = 30;
+ $this->assertEquals(30, $id3->track);
+
+ $id3->genre = array_search("Classical", ID3v1::$genres);
+ $this->assertEquals("Classical", $id3->genre);
+
+ $id3->write("id3v1.tag");
+ }
+
+ function testTagReadAfterCreate()
+ {
+ $id3 = new ID3v1("id3v1.tag");
+ $this->assertEquals("Title 1", $id3->title);
+ $this->assertEquals("Artist 1", $id3->artist);
+ $this->assertEquals("Album 1", $id3->album);
+ $this->assertEquals("2008", $id3->year);
+ $this->assertEquals("Comment 1", $id3->comment);
+ $this->assertEquals(30, $id3->track);
+ $this->assertEquals("Classical", $id3->genre);
+ }
+
+ function testTagChange()
+ {
+ $id3 = new ID3v1("id3v1.tag");
+
+ $id3->title = "Title 2";
+ $this->assertEquals("Title 2", $id3->title);
+
+ $id3->artist = "Artist 2";
+ $this->assertEquals("Artist 2", $id3->artist);
+
+ $id3->album = "Album 2";
+ $this->assertEquals("Album 2", $id3->album);
+
+ $id3->year = "2045";
+ $this->assertEquals("2045", $id3->year);
+
+ $id3->comment = "Comment 2";
+ $this->assertEquals("Comment 2", $id3->comment);
+
+ $id3->track = 10;
+ $this->assertEquals(10, $id3->track);
+
+ $id3->genre = array_search("Trance", ID3v1::$genres);
+ $this->assertEquals("Trance", $id3->genre);
+
+ $id3->write();
+ }
+
+ function testTagReadAfterChange()
+ {
+ $id3 = new ID3v1("id3v1.tag");
+ $this->assertEquals("Title 2", $id3->title);
+ $this->assertEquals("Artist 2", $id3->artist);
+ $this->assertEquals("Album 2", $id3->album);
+ $this->assertEquals("2045", $id3->year);
+ $this->assertEquals("Comment 2", $id3->comment);
+ $this->assertEquals(10, $id3->track);
+ $this->assertEquals("Trance", $id3->genre);
+ }
+
+ function testTagReplace()
+ {
+ $id3 = new ID3v1();
+
+ $id3->title = "Title 3";
+ $this->assertEquals("Title 3", $id3->title);
+ $this->assertEquals("Unknown", $id3->genre);
+
+ $id3->write("id3v1.tag");
+ }
+
+ function testTagReadAfterReplace()
+ {
+ $id3 = new ID3v1("id3v1.tag");
+ $this->assertEquals("Title 3", $id3->title);
+ $this->assertEquals("", $id3->artist);
+ $this->assertEquals("", $id3->album);
+ $this->assertEquals("", $id3->year);
+ $this->assertEquals("", $id3->comment);
+ $this->assertEquals("", $id3->track);
+ $this->assertEquals("Unknown", $id3->genre);
+ }
+
+ function testTagCreateVersion10()
+ {
+ $id3 = new ID3v1();
+
+ $id3->title = "Title 4";
+ $this->assertEquals("Title 4", $id3->title);
+
+ $id3->artist = "Artist 4";
+ $this->assertEquals("Artist 4", $id3->artist);
+
+ $id3->album = "Album 4";
+ $this->assertEquals("Album 4", $id3->album);
+
+ $id3->year = "2020";
+ $this->assertEquals("2020", $id3->year);
+
+ $id3->comment = "A comment field with 30 chars.";
+ $this->assertEquals("A comment field with 30 chars.", $id3->comment);
+
+ $id3->genre = array_search("Classical", ID3v1::$genres);
+ $this->assertEquals("Classical", $id3->genre);
+
+ $id3->write("id3v1.tag");
+ }
+
+ function testTagReadAfterCreateVersion10()
+ {
+ $id3 = new ID3v1("id3v1.tag");
+ $this->assertEquals("Title 4", $id3->title);
+ $this->assertEquals("Artist 4", $id3->artist);
+ $this->assertEquals("Album 4", $id3->album);
+ $this->assertEquals("2020", $id3->year);
+ $this->assertEquals("A comment field with 30 chars.", $id3->comment);
+ $this->assertEquals("", $id3->track);
+ $this->assertEquals("Classical", $id3->genre);
+ }
+}
diff --git a/tests/TestID3v2.php b/tests/TestID3v2.php
new file mode 100644
index 0000000..f5eedad
--- /dev/null
+++ b/tests/TestID3v2.php
@@ -0,0 +1,123 @@
+
+ * @copyright Copyright (c) 2008 The PHP Reader Project Workgroup
+ * @license http://code.google.com/p/php-reader/wiki/License New BSD License
+ * @version $Rev$
+ */
+final class TestID3v2 extends PHPUnit_Framework_TestCase
+{
+ function testTagCreate()
+ {
+ $id3 = new ID3v2();
+ $id3->tit2->text = "Title 1";
+ $this->assertEquals("Title 1", $id3->tit2->text);
+ $id3->tope->text = "Artist 1";
+ $this->assertEquals("Artist 1", $id3->tope->text);
+ $id3->talb->text = "Album 1";
+ $this->assertEquals("Album 1", $id3->talb->text);
+ $id3->tdrc->text = "2008";
+ $this->assertEquals("2008", $id3->tdrc->text);
+ $id3->comm->text = "Comment 1";
+ $this->assertEquals("Comment 1", $id3->comm->text);
+ $id3->trck->text = "11/13";
+ $this->assertEquals("11/13", $id3->trck->text);
+ $id3->tcon->text = "Classical";
+ $this->assertEquals("Classical", $id3->tcon->text);
+
+ $id3->write("id3v2.tag");
+ echo "create";
+ }
+
+ function testTagReadAfterCreate()
+ {
+ $id3 = new ID3v2("id3v2.tag");
+ echo "read after create";
+ $this->assertEquals("Title 1", $id3->tit2->text);
+ $this->assertEquals("Artist 1", $id3->tope->text);
+ $this->assertEquals("Album 1", $id3->talb->text);
+ $this->assertEquals("2008", $id3->tdrc->text);
+ $this->assertEquals("Comment 1", $id3->comm->text);
+ $this->assertEquals("11/13", $id3->trck->text);
+ $this->assertEquals("Classical", $id3->tcon->text);
+ }
+
+ function testTagChange()
+ {
+ $id3 = new ID3v2("id3v2.tag");
+
+ $id3->tit2->text = "Title 2";
+ $this->assertEquals("Title 2", $id3->tit2->text);
+ $id3->tope->text = "Artist 2";
+ $this->assertEquals("Artist 2", $id3->tope->text);
+ $id3->talb->text = "Album 2";
+ $this->assertEquals("Album 2", $id3->talb->text);
+ $id3->tdrc->text = "2020";
+ $this->assertEquals("2020", $id3->tdrc->text);
+ $id3->comm->text = "Comment 2";
+ $this->assertEquals("Comment 2", $id3->comm->text);
+ $id3->trck->text = "13/13";
+ $this->assertEquals("13/13", $id3->trck->text);
+ $id3->tcon->text = "Trance";
+ $this->assertEquals("Trance", $id3->tcon->text);
+
+ $id3->write();
+ }
+
+ function testTagReadAfterChange()
+ {
+ $id3 = new ID3v2("id3v2.tag");
+ $this->assertEquals("Title 2", $id3->tit2->text);
+ $this->assertEquals("Artist 2", $id3->tope->text);
+ $this->assertEquals("Album 2", $id3->talb->text);
+ $this->assertEquals("2020", $id3->tdrc->text);
+ $this->assertEquals("Comment 2", $id3->comm->text);
+ $this->assertEquals("13/13", $id3->trck->text);
+ $this->assertEquals("Trance", $id3->tcon->text);
+ }
+}
diff --git a/tests/TestTransform.php b/tests/TestTransform.php
index 0962f9f..94740d3 100644
--- a/tests/TestTransform.php
+++ b/tests/TestTransform.php
@@ -1,166 +1,166 @@
-
- * @copyright Copyright (c) 2008 The PHP Reader Project Workgroup
- * @license http://code.google.com/p/php-reader/wiki/License New BSD License
- * @version $Rev$
- */
-final class TestTransform extends PHPUnit_Framework_TestCase
-{
- function testInt64LE()
- {
- $this->assertEquals
- (0x7fffffffffffffff, Transform::fromInt64BE
- (Transform::toInt64BE(0x7fffffffffffffff)));
- }
-
- function testInt64BE()
- {
- $this->assertEquals
- (0x7fffffffffffffff, Transform::fromInt64BE
- (Transform::toInt64BE(0x7fffffffffffffff)));
- }
-
- function testInt32()
- {
- $this->assertEquals
- (0x7fffffff, Transform::fromInt32(Transform::toInt32(0x7fffffff)));
- }
-
- function testUInt32LE()
- {
- $this->assertEquals
- ("78563412", Transform::fromHHex(Transform::toUInt32LE(0x12345678)));
- $this->assertEquals
- (0xffffffff, Transform::fromUInt32LE(Transform::toUInt32LE(0xffffffff)));
- }
-
- function testUInt32BE()
- {
- $this->assertEquals
- ("12345678", Transform::fromHHex(Transform::toUInt32BE(0x12345678)));
- $this->assertEquals
- (0xffffffff, Transform::fromUInt32BE(Transform::toUInt32BE(0xffffffff)));
- }
-
- function testInt16()
- {
- $this->assertEquals
- (0x7fff, Transform::fromInt16(Transform::toInt16(0x7fff)));
- }
-
- function testUInt16LE()
- {
- $this->assertEquals
- ("fffe", Transform::fromHHex(Transform::toUInt16LE(0xfeff)));
- $this->assertEquals
- (0xffff, Transform::fromUInt16LE(Transform::toUInt16LE(0xffff)));
- }
-
- function testUInt16BE()
- {
- $this->assertEquals
- ("feff", Transform::fromHHex(Transform::toUInt16BE(0xfeff)));
- $this->assertEquals
- (0xffff, Transform::fromUInt16BE(Transform::toUInt16BE(0xffff)));
- }
-
- function testInt8()
- {
- $this->assertEquals(0x7f, Transform::fromInt8(Transform::toInt8(0x7f)));
- }
-
- function testString16()
- {
- $this->assertEquals("00e4", Transform::fromHHex
- (Transform::fromString16(Transform::toString16("\xff\xfe\xe4\x00"))));
- $this->assertEquals("e400", Transform::fromHHex
- (Transform::fromString16(Transform::toString16("\xfe\xff\x00\xe4"))));
- }
-
- function testString16LE()
- {
- $this->assertEquals
- ("fffe", Transform::fromHHex(Transform::toString16LE("\xff\xfe")));
- $this->assertEquals
- ("\0T\0h\0i\0s\0 \0i\0s\0 \0a\0 \0t\0e\0s\0t\0.",
- Transform::fromString16LE(Transform::toString16LE
- ("\0T\0h\0i\0s\0 \0i\0s\0 \0a\0 \0t\0e\0s\0t\0.")));
- }
-
- function testString16BE()
- {
- $this->assertEquals
- ("feff", Transform::fromHHex(Transform::toString16BE("\xff\xfe")));
- $this->assertEquals
- ("\0T\0h\0i\0s\0 \0i\0s\0 \0a\0 \0t\0e\0s\0t\0.",
- Transform::fromString16BE(Transform::toString16BE
- ("\0T\0h\0i\0s\0 \0i\0s\0 \0a\0 \0t\0e\0s\0t\0.")));
- }
-
- function testHHex()
- {
- $this->assertEquals("6c34", bin2hex(Transform::toHHex("6c34")));
- $this->assertEquals("6c34", Transform::fromHHex(Transform::toHHex("6c34")));
- }
-
- function testLHex()
- {
- $this->assertEquals("c643", bin2hex(Transform::toLHex("6c34")));
- $this->assertEquals("6c34", Transform::fromLHex(Transform::toLHex("6c34")));
- }
-
- function testGUID()
- {
- $this->assertEquals
- ("75b22630-668e-11cf-a6d9-00aa0062ce6c",
- Transform::fromGUID(Transform::toGUID
- ("75b22630-668e-11cf-a6d9-00aa0062ce6c")));
- }
-
-}
+
+ * @copyright Copyright (c) 2008 The PHP Reader Project Workgroup
+ * @license http://code.google.com/p/php-reader/wiki/License New BSD License
+ * @version $Rev$
+ */
+final class TestTransform extends PHPUnit_Framework_TestCase
+{
+ function testInt64LE()
+ {
+ $this->assertEquals
+ (0x7fffffffffffffff, Transform::fromInt64BE
+ (Transform::toInt64BE(0x7fffffffffffffff)));
+ }
+
+ function testInt64BE()
+ {
+ $this->assertEquals
+ (0x7fffffffffffffff, Transform::fromInt64BE
+ (Transform::toInt64BE(0x7fffffffffffffff)));
+ }
+
+ function testInt32()
+ {
+ $this->assertEquals
+ (0x7fffffff, Transform::fromInt32(Transform::toInt32(0x7fffffff)));
+ }
+
+ function testUInt32LE()
+ {
+ $this->assertEquals
+ ("78563412", Transform::fromHHex(Transform::toUInt32LE(0x12345678)));
+ $this->assertEquals
+ (0xffffffff, Transform::fromUInt32LE(Transform::toUInt32LE(0xffffffff)));
+ }
+
+ function testUInt32BE()
+ {
+ $this->assertEquals
+ ("12345678", Transform::fromHHex(Transform::toUInt32BE(0x12345678)));
+ $this->assertEquals
+ (0xffffffff, Transform::fromUInt32BE(Transform::toUInt32BE(0xffffffff)));
+ }
+
+ function testInt16()
+ {
+ $this->assertEquals
+ (0x7fff, Transform::fromInt16(Transform::toInt16(0x7fff)));
+ }
+
+ function testUInt16LE()
+ {
+ $this->assertEquals
+ ("fffe", Transform::fromHHex(Transform::toUInt16LE(0xfeff)));
+ $this->assertEquals
+ (0xffff, Transform::fromUInt16LE(Transform::toUInt16LE(0xffff)));
+ }
+
+ function testUInt16BE()
+ {
+ $this->assertEquals
+ ("feff", Transform::fromHHex(Transform::toUInt16BE(0xfeff)));
+ $this->assertEquals
+ (0xffff, Transform::fromUInt16BE(Transform::toUInt16BE(0xffff)));
+ }
+
+ function testInt8()
+ {
+ $this->assertEquals(0x7f, Transform::fromInt8(Transform::toInt8(0x7f)));
+ }
+
+ function testString16()
+ {
+ $this->assertEquals("00e4", Transform::fromHHex
+ (Transform::fromString16(Transform::toString16("\xff\xfe\x00\xe4"))));
+ $this->assertEquals("00e4", Transform::fromHHex
+ (Transform::fromString16(Transform::toString16("\xfe\xff\x00\xe4"))));
+ }
+
+ function testString16LE()
+ {
+ $this->assertEquals
+ ("fffe", Transform::fromHHex(Transform::toString16LE("\xff\xfe")));
+ $this->assertEquals
+ ("\0T\0h\0i\0s\0 \0i\0s\0 \0a\0 \0t\0e\0s\0t\0.",
+ Transform::fromString16LE(Transform::toString16LE
+ ("\0T\0h\0i\0s\0 \0i\0s\0 \0a\0 \0t\0e\0s\0t\0.")));
+ }
+
+ function testString16BE()
+ {
+ $this->assertEquals
+ ("feff", Transform::fromHHex(Transform::toString16BE("\xff\xfe")));
+ $this->assertEquals
+ ("\0T\0h\0i\0s\0 \0i\0s\0 \0a\0 \0t\0e\0s\0t\0.",
+ Transform::fromString16BE(Transform::toString16BE
+ ("\0T\0h\0i\0s\0 \0i\0s\0 \0a\0 \0t\0e\0s\0t\0.")));
+ }
+
+ function testHHex()
+ {
+ $this->assertEquals("6c34", bin2hex(Transform::toHHex("6c34")));
+ $this->assertEquals("6c34", Transform::fromHHex(Transform::toHHex("6c34")));
+ }
+
+ function testLHex()
+ {
+ $this->assertEquals("c643", bin2hex(Transform::toLHex("6c34")));
+ $this->assertEquals("6c34", Transform::fromLHex(Transform::toLHex("6c34")));
+ }
+
+ function testGUID()
+ {
+ $this->assertEquals
+ ("75b22630-668e-11cf-a6d9-00aa0062ce6c",
+ Transform::fromGUID(Transform::toGUID
+ ("75b22630-668e-11cf-a6d9-00aa0062ce6c")));
+ }
+
+}