<?php
+
/////////////////////////////////////////////////////////////////
/// getID3() by James Heinrich <info@getid3.org> //
-// available at http://getid3.sourceforge.net //
-// or http://www.getid3.org //
-// also https://github.com/JamesHeinrich/getID3 //
-/////////////////////////////////////////////////////////////////
-// See readme.txt for more details //
+// available at https://github.com/JamesHeinrich/getID3 //
+// or https://www.getid3.org //
+// or http://getid3.sourceforge.net //
+// see readme.txt for more details //
/////////////////////////////////////////////////////////////////
/// //
// write.php //
throw new Exception('write.php depends on getid3.lib.php, which is missing.');
}
-
-// NOTES:
-//
-// You should pass data here with standard field names as follows:
-// * TITLE
-// * ARTIST
-// * ALBUM
-// * TRACKNUMBER
-// * COMMENT
-// * GENRE
-// * YEAR
-// * ATTACHED_PICTURE (ID3v2 only)
-//
-// http://www.personal.uni-jena.de/~pfk/mpp/sv8/apekey.html
-// The APEv2 Tag Items Keys definition says "TRACK" is correct but foobar2000 uses "TRACKNUMBER" instead
-// Pass data here as "TRACKNUMBER" for compatability with all formats
-
-
+/**
+ * NOTES:
+ *
+ * You should pass data here with standard field names as follows:
+ * * TITLE
+ * * ARTIST
+ * * ALBUM
+ * * TRACKNUMBER
+ * * COMMENT
+ * * GENRE
+ * * YEAR
+ * * ATTACHED_PICTURE (ID3v2 only)
+ * The APEv2 Tag Items Keys definition says "TRACK" is correct but foobar2000 uses "TRACKNUMBER" instead
+ * Pass data here as "TRACKNUMBER" for compatability with all formats
+ *
+ * @link http://www.personal.uni-jena.de/~pfk/mpp/sv8/apekey.html
+ */
class getid3_writetags
{
- // public
- public $filename; // absolute filename of file to write tags to
- public $tagformats = array(); // array of tag formats to write ('id3v1', 'id3v2.2', 'id2v2.3', 'id3v2.4', 'ape', 'vorbiscomment', 'metaflac', 'real')
- public $tag_data = array(array()); // 2-dimensional array of tag data (ex: $data['ARTIST'][0] = 'Elvis')
- public $tag_encoding = 'ISO-8859-1'; // text encoding used for tag data ('ISO-8859-1', 'UTF-8', 'UTF-16', 'UTF-16LE', 'UTF-16BE', )
- public $overwrite_tags = true; // if true will erase existing tag data and write only passed data; if false will merge passed data with existing tag data
- public $remove_other_tags = false; // if true will erase remove all existing tags and only write those passed in $tagformats; if false will ignore any tags not mentioned in $tagformats
-
- public $id3v2_tag_language = 'eng'; // ISO-639-2 3-character language code needed for some ID3v2 frames (http://www.id3.org/iso639-2.html)
- public $id3v2_paddedlength = 4096; // minimum length of ID3v2 tags (will be padded to this length if tag data is shorter)
-
- public $warnings = array(); // any non-critical errors will be stored here
- public $errors = array(); // any critical errors will be stored here
-
- // private
- private $ThisFileInfo; // analysis of file before writing
+ /**
+ * Absolute filename of file to write tags to.
+ *
+ * @var string
+ */
+ public $filename;
+
+ /**
+ * Array of tag formats to write ('id3v1', 'id3v2.2', 'id2v2.3', 'id3v2.4', 'ape', 'vorbiscomment',
+ * 'metaflac', 'real').
+ *
+ * @var array
+ */
+ public $tagformats = array();
+
+ /**
+ * 2-dimensional array of tag data (ex: $data['ARTIST'][0] = 'Elvis').
+ *
+ * @var array
+ */
+ public $tag_data = array(array());
+
+ /**
+ * Text encoding used for tag data ('ISO-8859-1', 'UTF-8', 'UTF-16', 'UTF-16LE', 'UTF-16BE', ).
+ *
+ * @var string
+ */
+ public $tag_encoding = 'ISO-8859-1';
+
+ /**
+ * If true will erase existing tag data and write only passed data; if false will merge passed data
+ * with existing tag data.
+ *
+ * @var bool
+ */
+ public $overwrite_tags = true;
+
+ /**
+ * If true will erase remove all existing tags and only write those passed in $tagformats;
+ * If false will ignore any tags not mentioned in $tagformats.
+ *
+ * @var bool
+ */
+ public $remove_other_tags = false;
+
+ /**
+ * ISO-639-2 3-character language code needed for some ID3v2 frames.
+ *
+ * @link http://www.id3.org/iso639-2.html
+ *
+ * @var string
+ */
+ public $id3v2_tag_language = 'eng';
+
+ /**
+ * Minimum length of ID3v2 tags (will be padded to this length if tag data is shorter).
+ *
+ * @var int
+ */
+ public $id3v2_paddedlength = 4096;
+
+ /**
+ * Any non-critical errors will be stored here.
+ *
+ * @var array
+ */
+ public $warnings = array();
+
+ /**
+ * Any critical errors will be stored here.
+ *
+ * @var array
+ */
+ public $errors = array();
+
+ /**
+ * Analysis of file before writing.
+ *
+ * @var array
+ */
+ private $ThisFileInfo;
public function __construct() {
- return true;
}
-
+ /**
+ * @return bool
+ */
public function WriteTags() {
if (empty($this->filename)) {
$this->errors[] = 'tagformats must be an array in getid3_writetags';
return false;
}
+ // prevent duplicate tag formats
+ $this->tagformats = array_unique($this->tagformats);
+
+ // prevent trying to specify more than one version of ID3v2 tag to write simultaneously
+ $id3typecounter = 0;
+ foreach ($this->tagformats as $tagformat) {
+ if (substr(strtolower($tagformat), 0, 6) == 'id3v2.') {
+ $id3typecounter++;
+ }
+ }
+ if ($id3typecounter > 1) {
+ $this->errors[] = 'tagformats must not contain more than one version of ID3v2';
+ return false;
+ }
$TagFormatsToRemove = array();
+ $AllowedTagFormats = array();
if (filesize($this->filename) == 0) {
// empty file special case - allow any tag format, don't check existing format
switch ($tagformat) {
case 'ape':
$ape_writer = new getid3_write_apetag;
- if (($ape_writer->tag_data = $this->FormatDataForAPE()) !== false) {
+ if ($ape_writer->tag_data = $this->FormatDataForAPE()) {
$ape_writer->filename = $this->filename;
if (($success = $ape_writer->WriteAPEtag()) === false) {
$this->errors[] = 'WriteAPEtag() failed with message(s):<pre><ul><li>'.str_replace("\n", '</li><li>', htmlentities(trim(implode("\n", $ape_writer->errors)))).'</li></ul></pre>';
case 'id3v1':
$id3v1_writer = new getid3_write_id3v1;
- if (($id3v1_writer->tag_data = $this->FormatDataForID3v1()) !== false) {
+ if ($id3v1_writer->tag_data = $this->FormatDataForID3v1()) {
$id3v1_writer->filename = $this->filename;
if (($success = $id3v1_writer->WriteID3v1()) === false) {
$this->errors[] = 'WriteID3v1() failed with message(s):<pre><ul><li>'.str_replace("\n", '</li><li>', htmlentities(trim(implode("\n", $id3v1_writer->errors)))).'</li></ul></pre>';
$id3v2_writer = new getid3_write_id3v2;
$id3v2_writer->majorversion = intval(substr($tagformat, -1));
$id3v2_writer->paddedlength = $this->id3v2_paddedlength;
- if (($id3v2_writer->tag_data = $this->FormatDataForID3v2($id3v2_writer->majorversion)) !== false) {
+ $id3v2_writer_tag_data = $this->FormatDataForID3v2($id3v2_writer->majorversion);
+ if ($id3v2_writer_tag_data !== false) {
+ $id3v2_writer->tag_data = $id3v2_writer_tag_data;
+ unset($id3v2_writer_tag_data);
$id3v2_writer->filename = $this->filename;
if (($success = $id3v2_writer->WriteID3v2()) === false) {
$this->errors[] = 'WriteID3v2() failed with message(s):<pre><ul><li>'.str_replace("\n", '</li><li>', htmlentities(trim(implode("\n", $id3v2_writer->errors)))).'</li></ul></pre>';
case 'vorbiscomment':
$vorbiscomment_writer = new getid3_write_vorbiscomment;
- if (($vorbiscomment_writer->tag_data = $this->FormatDataForVorbisComment()) !== false) {
+ if ($vorbiscomment_writer->tag_data = $this->FormatDataForVorbisComment()) {
$vorbiscomment_writer->filename = $this->filename;
if (($success = $vorbiscomment_writer->WriteVorbisComment()) === false) {
$this->errors[] = 'WriteVorbisComment() failed with message(s):<pre><ul><li>'.str_replace("\n", '</li><li>', htmlentities(trim(implode("\n", $vorbiscomment_writer->errors)))).'</li></ul></pre>';
case 'metaflac':
$metaflac_writer = new getid3_write_metaflac;
- if (($metaflac_writer->tag_data = $this->FormatDataForMetaFLAC()) !== false) {
+ if ($metaflac_writer->tag_data = $this->FormatDataForMetaFLAC()) {
$metaflac_writer->filename = $this->filename;
if (($success = $metaflac_writer->WriteMetaFLAC()) === false) {
$this->errors[] = 'WriteMetaFLAC() failed with message(s):<pre><ul><li>'.str_replace("\n", '</li><li>', htmlentities(trim(implode("\n", $metaflac_writer->errors)))).'</li></ul></pre>';
case 'real':
$real_writer = new getid3_write_real;
- if (($real_writer->tag_data = $this->FormatDataForReal()) !== false) {
+ if ($real_writer->tag_data = $this->FormatDataForReal()) {
$real_writer->filename = $this->filename;
if (($success = $real_writer->WriteReal()) === false) {
$this->errors[] = 'WriteReal() failed with message(s):<pre><ul><li>'.str_replace("\n", '</li><li>', htmlentities(trim(implode("\n", $real_writer->errors)))).'</li></ul></pre>';
}
-
+ /**
+ * @param string[] $TagFormatsToDelete
+ *
+ * @return bool
+ */
public function DeleteTags($TagFormatsToDelete) {
foreach ($TagFormatsToDelete as $DeleteTagFormat) {
$success = false; // overridden if tag deletion is successful
break;
default:
- $this->errors[] = 'Invalid tag format to delete: "'.$tagformat.'"';
+ $this->errors[] = 'Invalid tag format to delete: "'.$DeleteTagFormat.'"';
return false;
break;
}
return true;
}
-
+ /**
+ * @param string $TagFormat
+ * @param array $tag_data
+ *
+ * @return bool
+ * @throws Exception
+ */
public function MergeExistingTagData($TagFormat, &$tag_data) {
// Merge supplied data with existing data, if requested
if ($this->overwrite_tags) {
// do nothing - ignore previous data
} else {
-throw new Exception('$this->overwrite_tags=false is known to be buggy in this version of getID3. Will be fixed in the near future, check www.getid3.org for a newer version.');
+ throw new Exception('$this->overwrite_tags=false is known to be buggy in this version of getID3. Check http://github.com/JamesHeinrich/getID3 for a newer version.');
if (!isset($this->ThisFileInfo['tags'][$TagFormat])) {
return false;
}
return true;
}
+ /**
+ * @return array
+ */
public function FormatDataForAPE() {
$ape_tag_data = array();
foreach ($this->tag_data as $tag_key => $valuearray) {
return $ape_tag_data;
}
-
+ /**
+ * @return array
+ */
public function FormatDataForID3v1() {
+ $tag_data_id3v1 = array();
$tag_data_id3v1['genreid'] = 255;
if (!empty($this->tag_data['GENRE'])) {
foreach ($this->tag_data['GENRE'] as $key => $value) {
return $tag_data_id3v1;
}
+ /**
+ * @param int $id3v2_majorversion
+ *
+ * @return array|false
+ */
public function FormatDataForID3v2($id3v2_majorversion) {
$tag_data_id3v2 = array();
return $tag_data_id3v2;
}
+ /**
+ * @return array
+ */
public function FormatDataForVorbisComment() {
$tag_data_vorbiscomment = $this->tag_data;
// and convert data to UTF-8 strings
foreach ($tag_data_vorbiscomment as $tag_key => $valuearray) {
foreach ($valuearray as $key => $value) {
- str_replace("\r", "\n", $value);
- if (strstr($value, "\n")) {
- unset($tag_data_vorbiscomment[$tag_key][$key]);
- $multilineexploded = explode("\n", $value);
- foreach ($multilineexploded as $newcomment) {
- if (strlen(trim($newcomment)) > 0) {
- $tag_data_vorbiscomment[$tag_key][] = getid3_lib::iconv_fallback($this->tag_encoding, 'UTF-8', $newcomment);
+ if (($tag_key == 'ATTACHED_PICTURE') && is_array($value)) {
+ continue; // handled separately in write.metaflac.php
+ } else {
+ str_replace("\r", "\n", $value);
+ if (strstr($value, "\n")) {
+ unset($tag_data_vorbiscomment[$tag_key][$key]);
+ $multilineexploded = explode("\n", $value);
+ foreach ($multilineexploded as $newcomment) {
+ if (strlen(trim($newcomment)) > 0) {
+ $tag_data_vorbiscomment[$tag_key][] = getid3_lib::iconv_fallback($this->tag_encoding, 'UTF-8', $newcomment);
+ }
}
+ } elseif (is_string($value) || is_numeric($value)) {
+ $tag_data_vorbiscomment[$tag_key][$key] = getid3_lib::iconv_fallback($this->tag_encoding, 'UTF-8', $value);
+ } else {
+ $this->warnings[] = '$data['.$tag_key.']['.$key.'] is not a string value - all of $data['.$tag_key.'] NOT written to VorbisComment tag';
+ unset($tag_data_vorbiscomment[$tag_key]);
+ break;
}
- } elseif (is_string($value) || is_numeric($value)) {
- $tag_data_vorbiscomment[$tag_key][$key] = getid3_lib::iconv_fallback($this->tag_encoding, 'UTF-8', $value);
- } else {
- $this->warnings[] = '$data['.$tag_key.']['.$key.'] is not a string value - all of $data['.$tag_key.'] NOT written to VorbisComment tag';
- unset($tag_data_vorbiscomment[$tag_key]);
- break;
}
}
}
return $tag_data_vorbiscomment;
}
+ /**
+ * @return array
+ */
public function FormatDataForMetaFLAC() {
// FLAC & OggFLAC use VorbisComments same as OggVorbis
// but require metaflac to do the writing rather than vorbiscomment
return $this->FormatDataForVorbisComment();
}
+ /**
+ * @return array
+ */
public function FormatDataForReal() {
$tag_data_real['title'] = getid3_lib::iconv_fallback($this->tag_encoding, 'ISO-8859-1', implode(' ', (isset($this->tag_data['TITLE'] ) ? $this->tag_data['TITLE'] : array())));
$tag_data_real['artist'] = getid3_lib::iconv_fallback($this->tag_encoding, 'ISO-8859-1', implode(' ', (isset($this->tag_data['ARTIST'] ) ? $this->tag_data['ARTIST'] : array())));