1<?php
2/**
3 * Zend Framework (http://framework.zend.com/)
4 *
5 * @link      http://github.com/zendframework/zf2 for the canonical source repository
6 * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
7 * @license   http://framework.zend.com/license/new-bsd New BSD License
8 */
9
10namespace Zend\Cache\Storage\Adapter;
11
12use Zend\Cache\Exception;
13
14/**
15 * These are options specific to the APC adapter
16 */
17class MemoryOptions extends AdapterOptions
18{
19    /**
20     * memory limit
21     *
22     * @var null|int
23     */
24    protected $memoryLimit = null;
25
26    /**
27     * Set memory limit
28     *
29     * - A number less or equal 0 will disable the memory limit
30     * - When a number is used, the value is measured in bytes. Shorthand notation may also be used.
31     * - If the used memory of PHP exceeds this limit an OutOfSpaceException
32     *   will be thrown.
33     *
34     * @link http://php.net/manual/faq.using.php#faq.using.shorthandbytes
35     * @param  string|int $memoryLimit
36     * @return MemoryOptions
37     */
38    public function setMemoryLimit($memoryLimit)
39    {
40        $memoryLimit = $this->normalizeMemoryLimit($memoryLimit);
41
42        if ($this->memoryLimit != $memoryLimit) {
43            $this->triggerOptionEvent('memory_limit', $memoryLimit);
44            $this->memoryLimit = $memoryLimit;
45        }
46
47        return $this;
48    }
49
50    /**
51     * Get memory limit
52     *
53     * If the used memory of PHP exceeds this limit an OutOfSpaceException
54     * will be thrown.
55     *
56     * @return int
57     */
58    public function getMemoryLimit()
59    {
60        if ($this->memoryLimit === null) {
61            // By default use half of PHP's memory limit if possible
62            $memoryLimit = $this->normalizeMemoryLimit(ini_get('memory_limit'));
63            if ($memoryLimit >= 0) {
64                $this->memoryLimit = (int) ($memoryLimit / 2);
65            } else {
66                // disable memory limit
67                $this->memoryLimit = 0;
68            }
69        }
70
71        return $this->memoryLimit;
72    }
73
74    /**
75     * Normalized a given value of memory limit into the number of bytes
76     *
77     * @param string|int $value
78     * @throws Exception\InvalidArgumentException
79     * @return int
80     */
81    protected function normalizeMemoryLimit($value)
82    {
83        if (is_numeric($value)) {
84            return (int) $value;
85        }
86
87        if (!preg_match('/(\-?\d+)\s*(\w*)/', ini_get('memory_limit'), $matches)) {
88            throw new Exception\InvalidArgumentException("Invalid  memory limit '{$value}'");
89        }
90
91        $value = (int) $matches[1];
92        if ($value <= 0) {
93            return 0;
94        }
95
96        switch (strtoupper($matches[2])) {
97            case 'G':
98                $value*= 1024;
99                // no break
100
101            case 'M':
102                $value*= 1024;
103                // no break
104
105            case 'K':
106                $value*= 1024;
107                // no break
108        }
109
110        return $value;
111    }
112}
113