1<?php
2/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
3
4/**
5 * Evaluates to true if a for the files for which a newer version
6 * can be found in a specified archive
7 * Comparison is by default made on dates of the files, or position
8 * in the archive (if two files have the same date or the date of a
9 * file is not specified).
10 *
11 * PHP versions 4 and 5
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: Duplicate.php,v 1.1 2005/05/30 17:18:11 vincentlascaux Exp $
33 * @link       http://pear.php.net/package/File_Archive
34 */
35
36require_once "File/Archive/Predicate.php";
37
38/**
39 * Evaluates to true if a for the files for which a newer version
40 * can be found in a specified archive
41 * Comparison is by default made on dates of the files, or position
42 * in the archive (if two files have the same date or the date of a
43 * file is not specified).
44 */
45class File_Archive_Predicate_Duplicate extends File_Archive_Predicate
46{
47    /**
48     * @var array Key is the filename, value is an array of date (index 0) and
49     *      position in the archive (index) 1 of the newest entry with this filename
50     */
51    var $newest = array();
52
53    /**
54     * @var int The current position of the file in the source
55     */
56    var $pos = 0;
57
58    /**
59     * @param File_Archive_Reader $source The source will be inspected to find
60     *        the date of old files
61     *        The predicate should then be used on the same source to remove the
62     *        old duplicate files
63     */
64    function File_Archive_Predicate_Duplicate(&$source)
65    {
66        //Ensure we are at the begining of the file
67        $source->close();
68        $pos = 0;
69        while ($source->next()) {
70            $filename = $source->getFilename();
71            $stat = $source->getStat();
72            $value = isset($this->newest[$filename]) ? $this->newest[$filename] : null;
73
74            if ($value === null ||
75                $this->compare($stat[9], $value[0]) >= 0
76               ) {
77                $this->newest[$filename] = array($stat[9], $pos);
78            }
79            $pos++;
80        }
81    }
82
83    /**
84     * Compare the dates of two files. null is considered infinitely old
85     *
86     * @return int < 0 if $a can be considered older than $b
87     *             = 0 if $a and $b can be considered same age
88     *             > 0 if $a can be considered newer than $b
89     */
90    function compare($a, $b) {
91        return ($a === null ? -1 : $a) - ($b === null ? -1 : $b);
92    }
93
94    /**
95     * @see File_Archive_Predicate::isTrue()
96     */
97    function isTrue(&$source)
98    {
99        $filename = $source->getFilename();
100        $stat = $source->getStat();
101        $value = isset($this->newest[$filename]) ? $this->newest[$filename] : null;
102        if ($value === null) {
103            $delete = false;
104        } else {
105            $comp = $this->compare($stat[9], $value[0]);
106
107            $delete = $comp < 0 ||
108                  ($comp == 0 && $this->pos != $value[1]);
109
110        }
111        $this->pos++;
112        return $delete;
113    }
114}
115
116?>