1<?php
2/*
3 * vim:set softtabstop=4 shiftwidth=4 expandtab:
4 *
5 * LICENSE: GNU Affero General Public License, version 3 (AGPL-3.0-or-later)
6 * Copyright 2001 - 2020 Ampache.org
7 *
8 * This program is free software: you can redistribute it and/or modify
9 * it under the terms of the GNU Affero General Public License as published by
10 * the Free Software Foundation, either version 3 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 * GNU Affero General Public License for more details.
17 *
18 * You should have received a copy of the GNU Affero General Public License
19 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
20 *
21 */
22
23declare(strict_types=0);
24
25namespace Ampache\Module\Api;
26
27use Ampache\Config\AmpConfig;
28use Ampache\Module\Util\AjaxUriRetrieverInterface;
29use Ampache\Module\Util\Ui;
30
31/**
32 * Ajax class
33 *
34 * This class is specifically for setting up/printing out ajax related
35 * elements onto a page. It takes care of the observing and all that
36 * raz-a-ma-taz.
37 *
38 */
39class Ajax
40{
41    private static $include_override;
42    private static $counter = 0;
43
44    /**
45     * constructor
46     * This is what is called when the class is loaded
47     */
48    public function __construct()
49    {
50        // Rien a faire
51    } // constructor
52
53    /**
54     * observe
55     * This returns a string with the correct and full ajax 'observe' stuff
56     * from jQuery
57     * @param string $source
58     * @param string $method
59     * @param string $action
60     * @param string $confirm
61     * @return string
62     */
63    public static function observe($source, $method, $action, $confirm = '')
64    {
65        $non_quoted = array('document', 'window');
66
67        if (in_array($source, $non_quoted)) {
68            $source_txt = $source;
69        } else {
70            $source_txt = "'#$source'";
71        }
72
73        $observe   = "<script>";
74        $methodact = ($method == 'click') ? "update_action();" : "";
75        if (AmpConfig::get('ajax_load') && $method == 'load') {
76            $source_txt = "$( document ).ready(";
77        } else {
78            $source_txt = "$(" . $source_txt . ").on('" . $method . "', ";
79        }
80        if (!empty($confirm)) {
81            $observe .= $source_txt . "function(){ " . $methodact . " if (confirm(\"" . $confirm . "\")) { " . $action . " }});";
82        } else {
83            $observe .= $source_txt . "function(){ " . $methodact . " " . $action . ";});";
84        }
85        $observe .= "</script>";
86
87        return $observe;
88    } // observe
89
90    /**
91     * url
92     * This takes a string and makes an URL
93     * @param string $action
94     * @return string
95     */
96    public static function url($action)
97    {
98        global $dic;
99
100        return $dic->get(AjaxUriRetrieverInterface::class)->getAjaxUri() . $action;
101    }
102
103    /**
104     * action
105     * This takes the action, the source and the post (if passed) and
106     * generates the full ajax link
107     * @param string $action
108     * @param string $source
109     * @param string $post
110     * @return string
111     */
112    public static function action($action, $source, $post = '')
113    {
114        $url = self::url($action);
115
116        $non_quoted = array('document', 'window');
117
118        if (in_array($source, $non_quoted)) {
119            $source_txt = $source;
120        } else {
121            $source_txt = "'$source'";
122        }
123
124        if ($post) {
125            $ajax_string = "ajaxPost('$url', '$post', $source_txt)";
126        } else {
127            $ajax_string = "ajaxPut('$url', $source_txt)";
128        }
129
130        return $ajax_string;
131    } // action
132
133    /**
134     * button
135     * This prints out an img of the specified icon with the specified alt
136     * text and then sets up the required ajax for it.
137     * @param string $action
138     * @param string $icon
139     * @param string $alt
140     * @param string $source
141     * @param string $post
142     * @param string $class
143     * @param string $confirm
144     * @return string
145     */
146    public static function button($action, $icon, $alt, $source = '', $post = '', $class = '', $confirm = '')
147    {
148        // Get the correct action
149        $ajax_string = self::action($action, $source, $post);
150
151        // If they passed a span class
152        if ($class) {
153            $class = ' class="' . $class . '"';
154        }
155
156        $string = Ui::get_icon($icon, $alt);
157
158        // Generate an <a> so that it's more compliant with older
159        // browsers (ie :hover actions) and also to unify linkbuttons
160        // (w/o ajax) display
161        $string = "<a href=\"javascript:void(0);\" id=\"$source\" $class>" . $string . "</a>\n";
162
163        $string .= self::observe($source, 'click', $ajax_string, $confirm);
164
165        return $string;
166    } // button
167
168    /**
169     * button_with_text
170     * This prints out an img of the specified icon coupled with
171     * the text string and then sets up the required ajax for it.
172     * @param string $action
173     * @param string $icon
174     * @param string $text
175     * @param string $source
176     * @param string $post
177     * @param string $class
178     * @param string $confirm
179     * @return string
180     */
181    public static function button_with_text($action, $icon, $text, $source = '', $post = '', $class = '', $confirm = '')
182    {
183        // Get the correct action
184        $ajax_string = self::action($action, $source, $post);
185
186        // If they passed a span class
187        if ($class) {
188            $class = ' class="' . $class . '"';
189        }
190
191        $button = Ui::get_icon($icon, $text);
192
193        $string = "<a href=\"javascript:void(0);\" id=\"$source\" $class>" . $button . " " . $text . "</a>\n";
194
195        $string .= self::observe($source, 'click', $ajax_string, $confirm);
196
197        return $string;
198    } // button
199
200    /**
201     * text
202     * This prints out the specified text as a link and sets up the required
203     * ajax for the link so it works correctly
204     * @param string $action
205     * @param string $text
206     * @param string $source
207     * @param string $post
208     * @param string $class
209     * @return string
210     */
211    public static function text($action, $text, $source, $post = '', $class = '')
212    {
213        // Temporary workaround to avoid sorting on custom base requests
214        if (!defined("NO_BROWSE_SORTING") || strpos($source, "sort_") === false) {
215            // Avoid duplicate id
216            $source .= '_' . time() . '_' . self::$counter++;
217
218            // Format the string we wanna use
219            $ajax_string = self::action($action, $source, $post);
220
221            // If they passed a span class
222            if ($class) {
223                $class = ' class="' . $class . '"';
224            }
225
226            $string = "<a href=\"javascript:void(0);\" id=\"$source\" $class>$text</a>\n";
227
228            $string .= self::observe($source, 'click', $ajax_string);
229        } else {
230            $string = $text;
231        }
232
233        return $string;
234    } // text
235
236    /**
237     * run
238     * This runs the specified action no questions asked
239     * @param string $action
240     */
241    public static function run($action)
242    {
243        echo "<script><!--\n";
244        echo "$action";
245        echo "\n--></script>";
246    } // run
247
248    /**
249     * set_include_override
250     * This sets the including div override, used only one place. Kind of a
251     * hack.
252     * @param boolean $value
253     */
254    public static function set_include_override($value)
255    {
256        self::$include_override = make_bool($value);
257    } // set_include_override
258
259    /**
260     * start_container
261     * This checks to see if we're AJAXin'. If we aren't then it echoes out
262     * the html needed to start a container that can be replaced by Ajax.
263     * @param string $name
264     * @param string $class
265     * @return boolean
266     */
267    public static function start_container($name, $class = '')
268    {
269        if (defined('AJAX_INCLUDE') && !self::$include_override) {
270            return true;
271        } else {
272            echo '<div id="' . scrub_out($name) . '"';
273            if (!empty($class)) {
274                echo ' class="' . scrub_out($class) . '"';
275            }
276            echo '>';
277        }
278
279        return false;
280    } // start_container
281
282    /**
283     * end_container
284     * This ends the container if we're not doing the AJAX thing
285     * @return boolean
286     */
287    public static function end_container()
288    {
289        if (defined('AJAX_INCLUDE') && !self::$include_override) {
290            return true;
291        } else {
292            echo "</div>";
293            self::$include_override = false;
294        }
295
296        return false;
297    } // end_container
298} // end ajax.class
299