1<?php
2// (c) Copyright by authors of the Tiki Wiki CMS Groupware Project
3//
4// All Rights Reserved. See copyright.txt for details and a complete list of authors.
5// Licensed under the GNU LESSER GENERAL PUBLIC LICENSE. See license.txt for details.
6// $Id$
7
8require_once('Exception.php');
9
10/**
11 * @package   Tiki
12 * @subpackage    Language
13 * Scan directories collecting files that should be parsed
14 * when searching for translatable strings. Provide methods
15 * to manually exclude directories from the search and
16 * manually include files inside excluded directories.
17 */
18class Language_CollectFiles
19{
20	/**
21	 * List of excluded directories.
22	 * @var array
23	 */
24	protected $excludeDirs = [];
25
26	/**
27	 * List of files manually included files.
28	 * @var array
29	 */
30	protected $includeFiles = [];
31
32	/**
33	 * List of valid file extensions
34	 * @var array
35	 */
36	protected $extensions = ['.tpl', '.php'];
37
38	/**
39	 * Set $this->excludeDirs
40	 * @param array $excludeDirs
41	 * @return null
42	 */
43	public function setExcludeDirs(array $excludeDirs)
44	{
45		$cwd = getcwd() . '/';
46
47		foreach ($excludeDirs as $key => $dir) {
48			$dir = $cwd . $dir;
49
50			if (! is_dir($dir)) {
51				throw new Language_Exception("Dir $dir does not exist");
52			}
53
54			$excludeDirs[$key] = $dir;
55		}
56
57		$this->excludeDirs = $excludeDirs;
58	}
59
60	/**
61	 * Set $this->includeFiles
62	 * @param array $includeFiles
63	 * @return null
64	 */
65	public function setIncludeFiles(array $includeFiles)
66	{
67		foreach ($includeFiles as $file) {
68			if (! file_exists($file)) {
69				throw new Language_Exception("File $file does not exist");
70			}
71		}
72
73		$this->includeFiles = $includeFiles;
74	}
75
76	/**
77	 * Set $this->extensions
78	 * @param array $extensions
79	 * @return null
80	 */
81	public function setExtensions(array $extensions)
82	{
83		$this->extensions = $extensions;
84	}
85
86	/**
87	 * Return $this->excludeDirs
88	 * @return array
89	 */
90	public function getExcludeDirs()
91	{
92		return $this->excludeDirs;
93	}
94
95	/**
96	 * Return $this->includeFiles
97	 * @return array
98	 */
99	public function getIncludeFiles()
100	{
101		return $this->includeFiles;
102	}
103
104	/**
105	 * Return all files that can contain
106	 * "localizable" strings.
107	 * @param $dir
108	 * @return array all files that can contain "localizable" strings
109	 */
110	public function run($dir)
111	{
112		$files = array_merge($this->scanDir($dir), $this->getIncludeFiles());
113		$files = array_values(array_unique($files));
114
115		return $files;
116	}
117
118	/**
119	 * Recursively scan directory and return all its
120	 * files (excluding $this->excludeDirs)
121	 *
122	 * @param $dir base dir
123	 * @return array collected files
124	 */
125	public function scanDir($dir)
126	{
127		if (! file_exists($dir)) {
128			throw new Language_Exception("Dir $dir does not exist.");
129		}
130
131		$files = [];
132		$pattern = $this->buildExtensionsPattern();
133		$contents = scandir($dir);
134
135		foreach ($contents as $file) {
136			// Skip current, parent and hidden directories
137			if ('.' === $file || '..' === $file
138				|| ((is_dir($file)) && strpos($file, '.') === 0)) {
139				continue;
140			}
141
142			$path = $dir . '/' . $file;
143
144			if (in_array($path, $this->getExcludeDirs())) {
145				continue;
146			}
147
148			if (preg_match($pattern, $file)) {
149				$files[] = $path;
150			} elseif (is_dir($path)) {
151				$files = array_merge($files, $this->scanDir($path));
152			}
153		}
154
155		foreach ($this->getIncludeFiles() as $file) {
156			if (preg_match($pattern, $file) && ! in_array($file, $files)) {
157				$files[] = $file;
158			}
159		}
160
161		return $files;
162	}
163
164	/**
165	 * Auxiliary method to build a pattern with
166	 * the valid extensions to match against file names
167	 *
168	 * @return string
169	 */
170	protected function buildExtensionsPattern()
171	{
172		$extensionsString = '';
173
174		foreach ($this->extensions as $extension) {
175			$extensionsString .= substr($extension, 1) . '|';
176		}
177
178		$extensionsString = substr($extensionsString, 0, strlen($extensionsString) - 1);
179
180		return "/.*\.($extensionsString)$/";
181	}
182}
183