Passed
Push — master ( 90d3bd...f8fb01 )
by Maurício
11:38
created

OutputBuffering::stop()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 14
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 12

Importance

Changes 0
Metric Value
cc 3
eloc 8
nc 3
nop 0
dl 0
loc 14
ccs 0
cts 12
cp 0
crap 12
rs 10
c 0
b 0
f 0
1
<?php
2
/**
3
 * Output buffering wrapper
4
 */
5
6
declare(strict_types=1);
7
8
namespace PhpMyAdmin;
9
10
use function defined;
11
use function flush;
12
use function function_exists;
13
use function header;
0 ignored issues
show
Bug introduced by
This use statement conflicts with another class in this namespace, PhpMyAdmin\header. Consider defining an alias.

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...
14
use function ini_get;
15
use function ob_end_clean;
16
use function ob_flush;
17
use function ob_get_contents;
18
use function ob_get_length;
19
use function ob_get_level;
20
use function ob_get_status;
21
use function ob_start;
22
use function register_shutdown_function;
23
24
/**
25
 * Output buffering wrapper class
26
 */
27
class OutputBuffering
28
{
29
    private static $_instance;
30
    private $_mode;
31
    private $_content;
32
33
    /** @var bool */
34
    private $_on;
35
36
    /**
37
     * Initializes class
38
     */
39
    private function __construct()
40
    {
41
        $this->_mode = $this->getMode();
42
        $this->_on = false;
43
    }
44
45
    /**
46
     * This function could be used eventually to support more modes.
47
     *
48
     * @return int the output buffer mode
49
     */
50
    private function getMode()
51
    {
52
        $mode = 0;
53
        if ($GLOBALS['cfg']['OBGzip'] && function_exists('ob_start')) {
54
            if (ini_get('output_handler') == 'ob_gzhandler') {
55
                // If a user sets the output_handler in php.ini to ob_gzhandler, then
56
                // any right frame file in phpMyAdmin will not be handled properly by
57
                // the browser. My fix was to check the ini file within the
58
                // PMA_outBufferModeGet() function.
59
                $mode = 0;
60
            } elseif (function_exists('ob_get_level') && ob_get_level() > 0) {
61
                // happens when php.ini's output_buffering is not Off
62
                ob_end_clean();
63
                $mode = 1;
64
            } else {
65
                $mode = 1;
66
            }
67
        }
68
69
        // Zero (0) is no mode or in other words output buffering is OFF.
70
        // Follow 2^0, 2^1, 2^2, 2^3 type values for the modes.
71
        // Useful if we ever decide to combine modes.  Then a bitmask field of
72
        // the sum of all modes will be the natural choice.
73
        return $mode;
74
    }
75
76
    /**
77
     * Returns the singleton OutputBuffering object
78
     *
79
     * @return OutputBuffering object
80
     */
81
    public static function getInstance()
82
    {
83
        if (empty(self::$_instance)) {
84
            self::$_instance = new OutputBuffering();
85
        }
86
87
        return self::$_instance;
88
    }
89
90
    /**
91
     * This function will need to run at the top of all pages if output
92
     * output buffering is turned on.  It also needs to be passed $mode from
93
     * the PMA_outBufferModeGet() function or it will be useless.
94
     *
95
     * @return void
96
     */
97
    public function start()
98
    {
99
        if ($this->_on) {
100
            return;
101
        }
102
103
        if ($this->_mode && function_exists('ob_gzhandler')) {
104
            ob_start('ob_gzhandler');
105
        }
106
        ob_start();
107
        if (! defined('TESTSUITE')) {
108
            header('X-ob_mode: ' . $this->_mode);
109
        }
110
        register_shutdown_function(
111
            [
112
                self::class,
113
                'stop',
114
            ]
115
        );
116
        $this->_on = true;
117
    }
118
119
    /**
120
     * This function will need to run at the bottom of all pages if output
121
     * buffering is turned on.  It also needs to be passed $mode from the
122
     * PMA_outBufferModeGet() function or it will be useless.
123
     *
124
     * @return void
125
     */
126
    public static function stop()
127
    {
128
        $buffer = self::getInstance();
129
        if (! $buffer->_on) {
130
            return;
131
        }
132
133
        $buffer->_on = false;
134
        $buffer->_content = ob_get_contents();
135
        if (ob_get_length() <= 0) {
136
            return;
137
        }
138
139
        ob_end_clean();
140
    }
141
142
    /**
143
     * Gets buffer content
144
     *
145
     * @return string buffer content
146
     */
147
    public function getContents()
148
    {
149
        return $this->_content;
150
    }
151
152
    /**
153
     * Flushes output buffer
154
     *
155
     * @return void
156
     */
157
    public function flush()
158
    {
159
        if (ob_get_status() && $this->_mode) {
160
            ob_flush();
161
        } else {
162
            flush();
163
        }
164
    }
165
}
166