1<?php
2/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
3
4/**
5 * A writer wrapper that will remove the files the eventual duplicate
6 * files from the reader to keep only the new ones
7 * When calling newFile, the file with the highest index in the reader
8 * and the same filename will be removed
9 * Note that it ensure that the archive won't have duplicates only if
10 * it didn't have duplicates before, and if no two calls to newFile with
11 * the same filename is done
12 *
13 * This library is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU Lesser General Public
15 * License as published by the Free Software Foundation; either
16 * version 2.1 of the License, or (at your option) any later version.
17 *
18 * This library is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
21 * Lesser General Public License for more details.
22 *
23 * You should have received a copy of the GNU Lesser General Public
24 * License along with this library; if not, write to the Free Software
25 * Foundation, Inc., 59 Temple Place, Suite 330,Boston,MA 02111-1307 USA
26 *
27 * @category   File Formats
28 * @package    File_Archive
29 * @author     Vincent Lascaux <vincentlascaux@php.net>
30 * @copyright  1997-2005 The PHP Group
31 * @license    http://www.gnu.org/copyleft/lesser.html  LGPL
32 * @version    CVS: $Id: UniqueAppender.php,v 1.1 2005/05/30 19:44:53 vincentlascaux Exp $
33 * @link       http://pear.php.net/package/File_Archive
34 */
35
36require_once "File/Archive/Writer.php";
37require_once "File/Archive/Reader.php";
38require_once "File/Archive/Predicate/Index.php";
39
40/**
41 * A writer wrapper that will remove the files the eventual duplicate
42 * files from the reader to keep only the new ones
43 * If there were already some duplications in the provided reader, not
44 * all duplication will be removed
45 * If you use newFile with the same filename several file, only the latest
46 * write will be kept (no time comparision is done)
47 */
48class File_Archive_Writer_UniqueAppender extends File_Archive_Writer
49{
50    var $reader;
51    var $writer;
52    var $fileList = array();
53    var $toDelete = array();
54
55    /**
56     * Construct a unique writer that will write to the specified writer
57     * and remove duplicate files from the reader on close
58     */
59    function File_Archive_Writer_UniqueAppender(&$reader)
60    {
61        $reader->close();
62        $pos = 0;
63        while ($reader->next()) {
64            $this->fileList[$reader->getFilename()] = $pos++;
65        }
66
67        $this->reader =& $reader;
68        $this->writer = $reader->makeAppendWriter();
69    }
70
71    /**
72     * @see File_Archive_Writer::newFile()
73     */
74    function newFile($filename, $stat = array(), $mime = "application/octet-stream")
75    {
76        if (isset($this->fileList[$filename])) {
77            $this->toDelete[$this->fileList[$filename]] = true;
78        }
79
80        return $this->writer->newFile($filename, $stat, $mime);
81    }
82
83    /**
84     * @see File_Archive_Writer::newFromTempFile()
85     */
86    function newFromTempFile($tmpfile, $filename, $stat = array(), $mime = "application/octet-stream")
87    {
88        if (isset($this->fileList[$filename])) {
89            $this->toDelete[$this->fileList[$filename]] = true;
90        }
91
92        return $this->writer->newFromTempFile($tmpfile, $filename, $stat, $mime);
93    }
94
95    /**
96     * @see File_Archive_Writer::newFileNeedsMIME()
97     */
98    function newFileNeedsMIME()
99    {
100        return $this->writer->newFileNeedsMIME();
101    }
102
103    /**
104     * @see File_Archive_Writer::writeData()
105     */
106    function writeData($data)
107    {
108        return $this->writer->writeData($data);
109    }
110
111    /**
112     * @see File_Archive_Writer::writeFile()
113     */
114    function writeFile($filename)
115    {
116        return $this->writer->writeFile($filename);
117    }
118
119    /**
120     * Close the writer, eventually flush the data, write the footer...
121     * This function must be called before the end of the script
122     */
123    function close()
124    {
125        $error = $this->writer->close();
126        if (PEAR::isError($error)) {
127            return $error;
128        }
129
130        if (!empty($this->toDelete)) {
131            $tmp = $this->reader->makeWriterRemoveFiles(
132                new File_Archive_Predicate_Index($this->toDelete)
133            );
134            if (PEAR::isError($tmp)) {
135                return $tmp;
136            }
137
138            return $tmp->close();
139        }
140    }
141}
142
143?>