Completed
Branch master (939199)
by
unknown
39:35
created

includes/cache/localisation/LCStoreCDB.php (1 issue)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
/**
3
 * This program is free software; you can redistribute it and/or modify
4
 * it under the terms of the GNU General Public License as published by
5
 * the Free Software Foundation; either version 2 of the License, or
6
 * (at your option) any later version.
7
 *
8
 * This program is distributed in the hope that it will be useful,
9
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
 * GNU General Public License for more details.
12
 *
13
 * You should have received a copy of the GNU General Public License along
14
 * with this program; if not, write to the Free Software Foundation, Inc.,
15
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
16
 * http://www.gnu.org/copyleft/gpl.html
17
 *
18
 * @file
19
 */
20
use Cdb\Exception;
0 ignored issues
show
This use statement conflicts with another class in this namespace, Exception.

Let’s assume that you have a directory layout like this:

.
|-- OtherDir
|   |-- Bar.php
|   `-- Foo.php
`-- SomeDir
    `-- Foo.php

and let’s assume the following content of Bar.php:

// Bar.php
namespace OtherDir;

use SomeDir\Foo; // This now conflicts the class OtherDir\Foo

If both files OtherDir/Foo.php and SomeDir/Foo.php are loaded in the same runtime, you will see a PHP error such as the following:

PHP Fatal error:  Cannot use SomeDir\Foo as Foo because the name is already in use in OtherDir/Foo.php

However, as OtherDir/Foo.php does not necessarily have to be loaded and the error is only triggered if it is loaded before OtherDir/Bar.php, this problem might go unnoticed for a while. In order to prevent this error from surfacing, you must import the namespace with a different alias:

// Bar.php
namespace OtherDir;

use SomeDir\Foo as SomeDirFoo; // There is no conflict anymore.
Loading history...
21
use Cdb\Reader;
22
use Cdb\Writer;
23
24
/**
25
 * LCStore implementation which stores data as a collection of CDB files in the
26
 * directory given by $wgCacheDirectory. If $wgCacheDirectory is not set, this
27
 * will throw an exception.
28
 *
29
 * Profiling indicates that on Linux, this implementation outperforms MySQL if
30
 * the directory is on a local filesystem and there is ample kernel cache
31
 * space. The performance advantage is greater when the DBA extension is
32
 * available than it is with the PHP port.
33
 *
34
 * See Cdb.php and http://cr.yp.to/cdb.html
35
 */
36
class LCStoreCDB implements LCStore {
37
38
	/** @var Reader[] */
39
	private $readers;
40
41
	/** @var Writer */
42
	private $writer;
43
44
	/** @var string Current language code */
45
	private $currentLang;
46
47
	/** @var bool|string Cache directory. False if not set */
48
	private $directory;
49
50 View Code Duplication
	function __construct( $conf = [] ) {
51
		global $wgCacheDirectory;
52
53
		if ( isset( $conf['directory'] ) ) {
54
			$this->directory = $conf['directory'];
55
		} else {
56
			$this->directory = $wgCacheDirectory;
57
		}
58
	}
59
60
	public function get( $code, $key ) {
61
		if ( !isset( $this->readers[$code] ) ) {
62
			$fileName = $this->getFileName( $code );
63
64
			$this->readers[$code] = false;
65
			if ( file_exists( $fileName ) ) {
66
				try {
67
					$this->readers[$code] = Reader::open( $fileName );
68
				} catch ( Exception $e ) {
69
					wfDebug( __METHOD__ . ": unable to open cdb file for reading\n" );
70
				}
71
			}
72
		}
73
74
		if ( !$this->readers[$code] ) {
75
			return null;
76
		} else {
77
			$value = false;
78
			try {
79
				$value = $this->readers[$code]->get( $key );
80
			} catch ( Exception $e ) {
81
				wfDebug( __METHOD__ . ": \Cdb\Exception caught, error message was "
82
					. $e->getMessage() . "\n" );
83
			}
84
			if ( $value === false ) {
85
				return null;
86
			}
87
88
			return unserialize( $value );
89
		}
90
	}
91
92
	public function startWrite( $code ) {
93
		if ( !file_exists( $this->directory ) ) {
94
			if ( !wfMkdirParents( $this->directory, null, __METHOD__ ) ) {
95
				throw new MWException( "Unable to create the localisation store " .
96
					"directory \"{$this->directory}\"" );
97
			}
98
		}
99
100
		// Close reader to stop permission errors on write
101
		if ( !empty( $this->readers[$code] ) ) {
102
			$this->readers[$code]->close();
103
		}
104
105
		try {
106
			$this->writer = Writer::open( $this->getFileName( $code ) );
107
		} catch ( Exception $e ) {
108
			throw new MWException( $e->getMessage() );
109
		}
110
		$this->currentLang = $code;
111
	}
112
113
	public function finishWrite() {
114
		// Close the writer
115
		try {
116
			$this->writer->close();
117
		} catch ( Exception $e ) {
118
			throw new MWException( $e->getMessage() );
119
		}
120
		$this->writer = null;
121
		unset( $this->readers[$this->currentLang] );
122
		$this->currentLang = null;
123
	}
124
125
	public function set( $key, $value ) {
126
		if ( is_null( $this->writer ) ) {
127
			throw new MWException( __CLASS__ . ': must call startWrite() before calling set()' );
128
		}
129
		try {
130
			$this->writer->set( $key, serialize( $value ) );
131
		} catch ( Exception $e ) {
132
			throw new MWException( $e->getMessage() );
133
		}
134
	}
135
136
	protected function getFileName( $code ) {
137
		if ( strval( $code ) === '' || strpos( $code, '/' ) !== false ) {
138
			throw new MWException( __METHOD__ . ": Invalid language \"$code\"" );
139
		}
140
141
		return "{$this->directory}/l10n_cache-$code.cdb";
142
	}
143
144
}
145