Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
14 / 14
100.00% covered (success)
100.00%
5 / 5
CRAP
100.00% covered (success)
100.00%
1 / 1
GitIgnore
100.00% covered (success)
100.00%
14 / 14
100.00% covered (success)
100.00%
5 / 5
9
100.00% covered (success)
100.00%
1 / 1
 __construct
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 path
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 entries
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getIterator
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 fromFile
100.00% covered (success)
100.00%
10 / 10
100.00% covered (success)
100.00%
1 / 1
5
1<?php
2
3declare(strict_types=1);
4
5/**
6 * This file is part of fast-forward/dev-tools.
7 *
8 * This source file is subject to the license bundled
9 * with this source code in the file LICENSE.
10 *
11 * @copyright Copyright (c) 2026 Felipe SayĆ£o Lobato Abreu <github@mentordosnerds.com>
12 * @license   https://opensource.org/licenses/MIT MIT License
13 *
14 * @see       https://github.com/php-fast-forward/dev-tools
15 * @see       https://github.com/php-fast-forward
16 * @see       https://datatracker.ietf.org/doc/html/rfc2119
17 */
18
19namespace FastForward\DevTools\GitIgnore;
20
21use ArrayIterator;
22use SplFileObject;
23
24/**
25 * Represents a .gitignore file with its path and entries.
26 *
27 * This class implements IteratorAggregate to allow iteration over entries
28 * and provides a factory method to load .gitignore content from the file system.
29 *
30 * @implements GitIgnoreInterface
31 */
32  class GitIgnore implements GitIgnoreInterface
33{
34    /**
35     * Initializes a GitIgnore instance with the given path and entries.
36     *
37     * @param string $path the file system path to the .gitignore file
38     * @param list<string> $entries the .gitignore entries
39     */
40    public function __construct(
41        public string $path,
42        public array $entries
43    ) {}
44
45    /**
46     * Returns the file system path to the .gitignore file.
47     *
48     * @return string the absolute path to the .gitignore file
49     */
50    public function path(): string
51    {
52        return $this->path;
53    }
54
55    /**
56     * Returns the list of entries from the .gitignore file.
57     *
58     * @return list<string> the non-empty .gitignore entries
59     */
60    public function entries(): array
61    {
62        return $this->entries;
63    }
64
65    /**
66     * Returns an iterator over the .gitignore entries.
67     *
68     * This method implements the IteratorAggregate interface.
69     *
70     * @return ArrayIterator<int, string> an iterator over the entries
71     */
72    public function getIterator(): ArrayIterator
73    {
74        return new ArrayIterator($this->entries);
75    }
76
77    /**
78     * Creates a GitIgnore instance from a file path.
79     *
80     * If the file does not exist, returns an empty GitIgnore with the given path.
81     * Empty lines and whitespace-only lines are filtered from the entries.
82     *
83     * @param string $gitignorePath the file system path to the .gitignore file
84     *
85     * @return static a new GitIgnore instance
86     */
87    public static function fromFile(string $gitignorePath): self
88    {
89        if (! file_exists($gitignorePath)) {
90            return new self($gitignorePath, []);
91        }
92
93        $file = new SplFileObject($gitignorePath, 'r');
94        $file->setFlags(SplFileObject::SKIP_EMPTY | SplFileObject::DROP_NEW_LINE);
95
96        $entries = [];
97        foreach ($file as $line) {
98            $trimmed = trim($line ?: '');
99
100            if ('' !== $trimmed) {
101                $entries[] = $trimmed;
102            }
103        }
104
105        return new self($gitignorePath, array_values($entries));
106    }
107}