Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
81.58% covered (warning)
81.58%
31 / 38
16.67% covered (danger)
16.67%
1 / 6
CRAP
0.00% covered (danger)
0.00%
0 / 1
DedupeCommand
81.58% covered (warning)
81.58%
31 / 38
16.67% covered (danger)
16.67%
1 / 6
12.90
0.00% covered (danger)
0.00%
0 / 1
 configure
100.00% covered (success)
100.00%
11 / 11
100.00% covered (success)
100.00%
1 / 1
1
 getInput
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
 openOutputFile
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 writeToOutputFile
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 closeOutputFile
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 execute
90.91% covered (success)
90.91%
20 / 22
0.00% covered (danger)
0.00%
0 / 1
7.04
1<?php
2
3/**
4 * Console command: deduplicate lines in a sorted file.
5 *
6 * Needed for the Windows version of the alphabetical browse database generator,
7 * since Windows sort does not support deduplication. Assumes presorted input.
8 *
9 * PHP version 8
10 *
11 * Copyright (C) Villanova University 2020.
12 *
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License version 2,
15 * as published by the Free Software Foundation.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
25 *
26 * @category VuFind
27 * @package  Console
28 * @author   Demian Katz <demian.katz@villanova.edu>
29 * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
30 * @link     https://vufind.org/wiki/development Wiki
31 */
32
33namespace VuFindConsole\Command\Util;
34
35use Symfony\Component\Console\Attribute\AsCommand;
36use Symfony\Component\Console\Command\Command;
37use Symfony\Component\Console\Input\InputArgument;
38use Symfony\Component\Console\Input\InputInterface;
39use Symfony\Component\Console\Output\OutputInterface;
40use Symfony\Component\Console\Question\Question;
41
42/**
43 * Console command: deduplicate lines in a sorted file.
44 *
45 * @category VuFind
46 * @package  Console
47 * @author   Demian Katz <demian.katz@villanova.edu>
48 * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
49 * @link     https://vufind.org/wiki/development Wiki
50 */
51#[AsCommand(
52    name: 'util/dedupe',
53    description: 'Tool for deduplicating lines in a sorted file'
54)]
55class DedupeCommand extends Command
56{
57    /**
58     * Configure the command.
59     *
60     * @return void
61     */
62    protected function configure()
63    {
64        $this
65            ->setHelp('Deduplicates lines in a sorted file.')
66            ->addArgument(
67                'input',
68                InputArgument::OPTIONAL,
69                'the file to deduplicate (omit for interactive prompt).'
70            )->addArgument(
71                'output',
72                InputArgument::OPTIONAL,
73                'the output file (omit for interactive prompt).'
74            );
75    }
76
77    /**
78     * Fetch a single line of input from the user.
79     *
80     * @param InputInterface  $input  Input object
81     * @param OutputInterface $output Output object
82     * @param string          $prompt Prompt to display to the user.
83     *
84     * @return string        User-entered response.
85     */
86    protected function getInput(
87        InputInterface $input,
88        OutputInterface $output,
89        string $prompt
90    ): string {
91        $question = new Question($prompt, '');
92        return $this->getHelper('question')->ask($input, $output, $question);
93    }
94
95    /**
96     * Open a file for writing.
97     *
98     * @param string $filename File to open
99     *
100     * @return resource
101     */
102    protected function openOutputFile($filename)
103    {
104        return @fopen($filename, 'w');
105    }
106
107    /**
108     * Write a line to an output file.
109     *
110     * @param resource $handle File handle
111     * @param string   $text   Text to write
112     *
113     * @return void
114     */
115    protected function writeToOutputFile($handle, $text)
116    {
117        fwrite($handle, $text);
118    }
119
120    /**
121     * Close a file handle.
122     *
123     * @param resource $handle Handle from openOutputFile()
124     *
125     * @return void
126     */
127    protected function closeOutputFile($handle)
128    {
129        fclose($handle);
130    }
131
132    /**
133     * Run the command.
134     *
135     * @param InputInterface  $input  Input object
136     * @param OutputInterface $output Output object
137     *
138     * @return int 0 for success
139     */
140    protected function execute(InputInterface $input, OutputInterface $output)
141    {
142        $infile = $input->getArgument('input');
143        if (empty($infile)) {
144            $inprompt = 'Please specify an input file: ';
145            $infile = $this->getInput($input, $output, $inprompt);
146        }
147        $inHandle = @fopen($infile, 'r');
148        if (!$inHandle) {
149            $output->writeln('Could not open input file: ' . $infile);
150            return 1;
151        }
152        $outfile = $input->getArgument('output');
153        if (empty($outfile)) {
154            $outprompt = 'Please specify an output file: ';
155            $outfile = $this->getInput($input, $output, $outprompt);
156        }
157        $outHandle = $this->openOutputFile($outfile);
158        if (!$outHandle) {
159            $output->writeln('Could not open output file: ' . $outfile);
160            return 1;
161        }
162
163        $last = '';
164        while ($tmp = fgets($inHandle)) {
165            if ($tmp != $last) {
166                $this->writeToOutputFile($outHandle, $tmp);
167            }
168            $last = $tmp;
169        }
170
171        fclose($inHandle);
172        $this->closeOutputFile($outHandle);
173
174        return 0;
175    }
176}