1<?php
2/**
3 * Login system task for automated upgrade tasks.
4 *
5 * Copyright 2011-2017 Horde LLC (http://www.horde.org/)
6 *
7 * See the enclosed file COPYING for license information (LGPL). If you
8 * did not receive this file, see http://www.horde.org/licenses/lgpl21.
9 *
10 * @author   Michael Slusarz <slusarz@horde.org>
11 * @category Horde
12 * @license  http://www.horde.org/licenses/lgpl21 LGPL 2.1
13 * @package  Core
14 */
15abstract class Horde_Core_LoginTasks_SystemTask_Upgrade extends Horde_LoginTasks_SystemTask
16{
17    /**
18     * The interval at which to run the task.
19     *
20     * @var integer
21     */
22    public $interval = Horde_LoginTasks::EVERY;
23
24    /**
25     * The current application.
26     *
27     * @var string
28     */
29    protected $_app = 'horde';
30
31    /**
32     * Do these upgrade tasks require authentication?
33     *
34     * @var boolean
35     */
36    protected $_auth = false;
37
38    /**
39     * The list of versions to upgrade.
40     *
41     * @var array
42     */
43    protected $_toupgrade = array();
44
45    /**
46     * The list of versions which upgrades will occur.
47     *
48     * @var array
49     */
50    protected $_versions = array();
51
52    /**
53     * Constructor.
54     */
55    public function __construct()
56    {
57        usort($this->_versions, 'version_compare');
58
59        if ($vers = $this->_pref('get')) {
60            foreach ($this->_versions as $val) {
61                /* Our versioning system is not compatible with PHP's
62                 * version_compare, since x.0.foo is ALWAYS greater than
63                 * x.0foo. */
64                $compare = (substr_count($val, '.') != substr_count($vers, '.'))
65                    ? preg_replace("/(\.0)((?:alpha|beta|RC)\d+)/i", "$2", $vers)
66                    : $vers;
67                if (version_compare($compare, $val) === -1) {
68                    $this->_toupgrade[] = $val;
69                }
70            }
71        } else {
72            $this->_toupgrade = $this->_versions;
73        }
74
75        $this->active = !empty($this->_toupgrade);
76    }
77
78    /**
79     * Perform upgrade tasks.
80     */
81    public function execute()
82    {
83        foreach ($this->_toupgrade as $val) {
84            $this->_upgrade($val);
85        }
86
87        $this->_pref('set');
88    }
89
90    /**
91     * Force re-run of all upgrade tasks.
92     */
93    public function forceUpgrade()
94    {
95        $this->active = true;
96        $this->_toupgrade = $this->_versions;
97        $this->execute();
98    }
99
100    /**
101     * Perform upgrade tasks for a given version.
102     *
103     * For those running a git checkout, the system task for a given version
104     * will run continuously until that version is released. Code should
105     * be added to not convert already converted values.
106     *
107     * @param string $version  A version string.
108     */
109    abstract protected function _upgrade($version);
110
111    /**
112     */
113    public function skip()
114    {
115        /* Skip task until we are authenticated. */
116        return ($this->_auth &&
117                !$GLOBALS['registry']->isAuthenticated(array('app' => $this->_app)));
118    }
119
120    /**
121     * Manage the upgrade preferences.
122     *
123     * @param string $action  Either 'get' or 'set'.
124     *
125     * @return string  The current version.
126     */
127    protected function _pref($action)
128    {
129        global $prefs, $registry;
130
131        $key = $this->_app;
132        if ($this->_auth) {
133            $key .= '_auth';
134        }
135
136        $upgrade = @unserialize($prefs->getValue('upgrade_tasks'));
137
138        switch ($action) {
139        case 'get':
140            $val = isset($upgrade[$key])
141                ? $upgrade[$key]
142                : null;
143            break;
144
145        case 'set':
146            $val = $registry->getVersion($this->_app, true);
147            $upgrade[$key] = $val;
148            $prefs->setValue('upgrade_tasks', serialize($upgrade));
149            break;
150        }
151
152        return $val;
153    }
154
155}
156