Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
51.72% covered (warning)
51.72%
15 / 29
40.00% covered (danger)
40.00%
4 / 10
CRAP
0.00% covered (danger)
0.00%
0 / 1
state_helper
51.72% covered (warning)
51.72%
15 / 29
40.00% covered (danger)
40.00%
4 / 10
32.01
0.00% covered (danger)
0.00%
0 / 1
 __construct
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 is_action_in_progress
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 type
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
 action
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
 counter
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
 init
81.82% covered (warning)
81.82%
9 / 11
0.00% covered (danger)
0.00%
0 / 1
3.05
 update_counter
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
2
 clear_state
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 load_state
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
6
 save_state
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
1<?php
2/**
3 *
4 * This file is part of the phpBB Forum Software package.
5 *
6 * @copyright (c) phpBB Limited <https://www.phpbb.com>
7 * @license GNU General Public License, version 2 (GPL-2.0)
8 *
9 * For full copyright and license information, please see
10 * the docs/CREDITS.txt file.
11 *
12 */
13
14namespace phpbb\search;
15
16use phpbb\config\config;
17use phpbb\search\exception\action_in_progress_exception;
18use phpbb\search\exception\no_action_in_progress_exception;
19use phpbb\search\exception\no_search_backend_found_exception;
20use phpbb\search\exception\search_exception;
21
22class state_helper
23{
24    protected const STATE_SEARCH_TYPE = 0;
25    protected const STATE_ACTION = 1;
26    protected const STATE_POST_COUNTER = 2;
27
28    /** @var config */
29    protected $config;
30
31    /** @var search_backend_factory */
32    protected $search_backend_factory;
33
34    /**
35     * Constructor.
36     *
37     * @param config                    $config
38     * @param search_backend_factory    $search_backend_factory
39     */
40    public function __construct(config $config, search_backend_factory $search_backend_factory)
41    {
42        $this->config = $config;
43        $this->search_backend_factory = $search_backend_factory;
44    }
45
46    /**
47     * Returns whether there is an action in progress
48     *
49     * @return bool
50     */
51    public function is_action_in_progress(): bool
52    {
53        return !empty($this->config['search_indexing_state']);
54    }
55
56    /**
57     * @return string The class name of the search backend
58     *
59     * @throws no_action_in_progress_exception If there is no action in progress
60     */
61    public function type(): string
62    {
63        $state = $this->load_state();
64
65        return $state[self::STATE_SEARCH_TYPE];
66    }
67
68    /**
69     * @return string The action that is being executed, can be 'create' or 'delete'
70     *
71     * @throws no_action_in_progress_exception If there is no action in progress
72     */
73    public function action(): string
74    {
75        $state = $this->load_state();
76
77        return $state[self::STATE_ACTION];
78    }
79
80    /**
81     * @return int The post counter
82     *
83     * @throws no_action_in_progress_exception If there is no action in progress
84     */
85    public function counter(): int
86    {
87        $state = $this->load_state();
88
89        return $state[self::STATE_POST_COUNTER];
90    }
91
92    /**
93     * Start a indexing or delete process.
94     *
95     * @param string $search_type
96     * @param string $action
97     *
98     * @throws action_in_progress_exception  If there is an action in progress
99     * @throws no_search_backend_found_exception If search backend don't exist
100     * @throws search_exception If action isn't valid
101     */
102    public function init(string $search_type, string $action): void
103    {
104        // It's not possible to start a new process when there is one already running
105        if ($this->is_action_in_progress())
106        {
107            throw new action_in_progress_exception();
108        }
109
110        // Make sure the search type exists (if not, throw an exception)
111        $this->search_backend_factory->get($search_type);
112
113        // Make sure the action is correct (just in case)
114        if (!in_array($action, ['create', 'delete']))
115        {
116            throw new search_exception('INVALID_ACTION');
117        }
118
119        $state = [
120            self::STATE_SEARCH_TYPE => $search_type,
121            self::STATE_ACTION => $action,
122            self::STATE_POST_COUNTER => 0
123        ];
124
125        $this->save_state($state);
126    }
127
128    /**
129     * Set the post counter
130     *
131     * @param int $counter
132     *
133     * @throws no_action_in_progress_exception If there is no action in progress
134     */
135    public function update_counter(int $counter): void
136    {
137        $state = $this->load_state();
138
139        $state[self::STATE_POST_COUNTER] = $counter;
140
141        $this->save_state($state);
142    }
143
144    /**
145     * Clear the state
146     */
147    public function clear_state(): void
148    {
149        $this->save_state();
150    }
151
152    /**
153     * Load the state from the database
154     *
155     * @return array
156     *
157     * @throws no_action_in_progress_exception If there is no action in progress
158     */
159    private function load_state(): array
160    {
161        // Is not possible to execute an action over state if it's empty
162        if (!$this->is_action_in_progress())
163        {
164            throw new no_action_in_progress_exception();
165        }
166
167        return explode(',', $this->config['search_indexing_state']);
168    }
169
170    /**
171     * Save the specified state in the database
172     *
173     * @param array $state
174     */
175    private function save_state(array $state = []): void
176    {
177        ksort($state);
178
179        $this->config->set('search_indexing_state', implode(',', $state));
180    }
181}