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\Repository\Model;
26
27use Ampache\Module\System\Dba;
28
29/**
30 * UserPlaylist Class
31 *
32 * This class handles the user playlists in Ampache. It handles the
33 * user_playlist table creating a global play queue for each user
34 */
35class User_Playlist extends database_object
36{
37    protected const DB_TABLENAME = 'user_playlist';
38
39    public int $user;
40
41    /**
42     * Constructor
43     * This takes a user_id as an optional argument and gathers the
44     * information.  If no user_id is passed or the requested one isn't
45     * found, return false.
46     * @param string $user_id
47     */
48    public function __construct($user_id = '')
49    {
50        if (!$user_id) {
51            return false;
52        }
53
54        $this->user = (int)$user_id;
55
56        return true;
57    } // __construct
58
59    /**
60     * get_items
61     * Returns an array of all object_ids currently in this User_Playlist.
62     * @return array
63     */
64    public function get_items()
65    {
66        $items = array();
67        // Select all objects from this user
68        $sql        = "SELECT `id`, `object_type`, `object_id`, `track`, `current_track`, `current_time` FROM `user_playlist` WHERE `user` = ? ORDER BY `track`, `id`";
69        $db_results = Dba::read($sql, array($this->user));
70
71        while ($results = Dba::fetch_assoc($db_results)) {
72            $items[] = array(
73                'id' => $results['id'],
74                'object_type' => $results['object_type'],
75                'object_id' => $results['object_id'],
76                'track' => $results['track'],
77                'current_track' => $results['current_track'],
78                'current_time' => $results['current_time']
79            );
80        }
81
82        return $items;
83    } // get_items
84
85    /**
86     * get_current_object
87     * This returns the next object in the user_playlist.
88     * @return array
89     */
90    public function get_current_object()
91    {
92        $items = array();
93        // Select the current object for this user
94        $sql        = "SELECT `id`, `object_type`, `object_id`, `track`, `current_track`, `current_time` FROM `user_playlist` WHERE `user`= ? AND `current_track` = 1 LIMIT 1";
95        $db_results = Dba::read($sql, array($this->user));
96
97        while ($results = Dba::fetch_assoc($db_results)) {
98            $items = array(
99                'id' => $results['id'],
100                'object_type' => $results['object_type'],
101                'object_id' => $results['object_id'],
102                'track' => $results['track'],
103                'current_track' => $results['current_track'],
104                'current_time' => $results['current_time']
105            );
106        }
107
108        return $items;
109    } // get_current_object
110
111    /**
112     * set_current_object
113     * set the active object in the user_playlist.
114     * @param string $object_type
115     * @param int $object_id
116     * @param int $position
117     */
118    public function set_current_object($object_type, $object_id, $position)
119    {
120        // remove the old current
121        $sql = "UPDATE `user_playlist` SET `current_track` = 0, `current_time` = 0 WHERE `user` = ?";
122        Dba::write($sql, array($this->user));
123        // set the new one
124        $sql = "UPDATE `user_playlist` SET `current_track` = 1, `current_time` = ? WHERE `object_type` = ? AND `object_id` = ? AND `user` = ? LIMIT 1";
125        Dba::write($sql, array($position, $object_type, $object_id, $this->user));
126    } // set_current_object
127
128    /**
129     * set_current_id
130     * set the active object using the row id in user_playlist.
131     * @param string $object_type
132     * @param int $playlist_id
133     * @param int $position
134     */
135    public function set_current_id($object_type, $playlist_id, $position)
136    {
137        // remove the old current
138        $sql = "UPDATE `user_playlist` SET `current_track` = 0, `current_time` = 0 WHERE `user` = ?";
139        Dba::write($sql, array($this->user));
140        // set the new one
141        $sql = "UPDATE `user_playlist` SET `current_track` = 1, `current_time` = ? WHERE `object_type` = ? AND `id` = ? AND `user` = ? LIMIT 1";
142        Dba::write($sql, array($position, $object_type, $playlist_id, $this->user));
143    } // set_current_object
144
145    /**
146     * get_count
147     * This returns a count of the total number of tracks that are in this playlist
148     * @return int
149     */
150    public function get_count()
151    {
152        $sql        = "SELECT COUNT(`user`) AS `count` FROM `user_playlist` WHERE `user` = ?";
153        $db_results = Dba::read($sql, array($this->user));
154        $results    = Dba::fetch_assoc($db_results);
155
156        return (int)$results['count'];
157    } // get_count
158
159    /**
160     * clear
161     * This clears all the objects out of a user's playlist
162     */
163    public function clear()
164    {
165        $sql = "DELETE FROM `user_playlist` WHERE `user` = ?";
166        Dba::write($sql, array($this->user));
167    } // clear
168
169    /**
170     * add_item
171     * This adds a new song to the playlist
172     */
173    public function add_item($data)
174    {
175        $sql = "INSERT INTO `user_playlist` (`user`, `object_type`, `object_id`, `track`) VALUES (?, ?, ?, ?)";
176        Dba::write($sql, array($this->user, $data['object_type'], $data['object_id'], $data['track']));
177    } // add_item
178
179    /**
180     * set_items
181     * This function resets the User_Playlist while optionally setting the update client and time for that user
182     * @param array $playlist
183     * @param string $current_type
184     * @param int $current_id
185     * @param int $current_time
186     * @param int $time
187     * @param string $client
188     */
189    public function set_items($playlist, $current_type, $current_id, $current_time, $time = null, $client = null)
190    {
191        if (!empty($playlist)) {
192            // clear the old list
193            $this->clear();
194            // set the new items
195            $index = 1;
196            foreach ($playlist as $row) {
197                $row['track'] = $index;
198                $this->add_item($row);
199                $index++;
200            }
201            $this->set_current_object($current_type, $current_id, $current_time);
202
203            // subsonic cares about queue dates so set them (and set them together)
204            if ($time && $client) {
205                User::set_user_data($this->user, 'playqueue_time', $time);
206                User::set_user_data($this->user, 'playqueue_client', $client);
207            }
208        }
209    } // set_items
210}
211