diff options
| author | 2019-10-31 18:15:47 +0100 | |
|---|---|---|
| committer | 2019-10-31 18:15:47 +0100 | |
| commit | 3aa66f317b496ccd9a2df914bbc747c52081a7ad (patch) | |
| tree | 6a3f3f74899801abdca00546e213dfdc141c53cf /app/Models/FeedDAO.php | |
| parent | 82611c9622ed23b0e9fcf5f9f651ddffa1fd7706 (diff) | |
| parent | fcae48f313d399050cb15f37a8a73ae52fc67796 (diff) | |
Merge pull request #2599 from FreshRSS/dev1.15.0
FreshRSS 1.15
Diffstat (limited to 'app/Models/FeedDAO.php')
| -rw-r--r-- | app/Models/FeedDAO.php | 208 |
1 files changed, 103 insertions, 105 deletions
diff --git a/app/Models/FeedDAO.php b/app/Models/FeedDAO.php index c9c9f6301..fa0001df7 100644 --- a/app/Models/FeedDAO.php +++ b/app/Models/FeedDAO.php @@ -3,14 +3,13 @@ class FreshRSS_FeedDAO extends Minz_ModelPdo implements FreshRSS_Searchable { protected function addColumn($name) { - Minz_Log::warning('FreshRSS_FeedDAO::addColumn: ' . $name); + Minz_Log::warning(__method__ . ': ' . $name); try { if ($name === 'attributes') { //v1.11.0 - $stm = $this->bd->prepare('ALTER TABLE `' . $this->prefix . 'feed` ADD COLUMN attributes TEXT'); - return $stm && $stm->execute(); + return $this->pdo->exec('ALTER TABLE `_feed` ADD COLUMN attributes TEXT') !== false; } } catch (Exception $e) { - Minz_Log::error('FreshRSS_FeedDAO::addColumn error: ' . $e->getMessage()); + Minz_Log::error(__method__ . ' error: ' . $e->getMessage()); } return false; } @@ -18,7 +17,7 @@ class FreshRSS_FeedDAO extends Minz_ModelPdo implements FreshRSS_Searchable { protected function autoUpdateDb($errorInfo) { if (isset($errorInfo[0])) { if ($errorInfo[0] === FreshRSS_DatabaseDAO::ER_BAD_FIELD_ERROR || $errorInfo[0] === FreshRSS_DatabaseDAOPGSQL::UNDEFINED_COLUMN) { - foreach (array('attributes') as $column) { + foreach (['attributes'] as $column) { if (stripos($errorInfo[2], $column) !== false) { return $this->addColumn($column); } @@ -30,7 +29,7 @@ class FreshRSS_FeedDAO extends Minz_ModelPdo implements FreshRSS_Searchable { public function addFeed($valuesTmp) { $sql = ' - INSERT INTO `' . $this->prefix . 'feed` + INSERT INTO `_feed` ( url, category, @@ -39,18 +38,24 @@ class FreshRSS_FeedDAO extends Minz_ModelPdo implements FreshRSS_Searchable { description, `lastUpdate`, priority, + `pathEntries`, `httpAuth`, error, - keep_history, ttl, attributes ) VALUES - (?, ?, ?, ?, ?, ?, 10, ?, 0, ?, ?, ?)'; - $stm = $this->bd->prepare($sql); + (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)'; + $stm = $this->pdo->prepare($sql); $valuesTmp['url'] = safe_ascii($valuesTmp['url']); $valuesTmp['website'] = safe_ascii($valuesTmp['website']); + if (!isset($valuesTmp['pathEntries'])) { + $valuesTmp['pathEntries'] = ''; + } + if (!isset($valuesTmp['attributes'])) { + $valuesTmp['attributes'] = []; + } $values = array( substr($valuesTmp['url'], 0, 511), @@ -59,16 +64,18 @@ class FreshRSS_FeedDAO extends Minz_ModelPdo implements FreshRSS_Searchable { substr($valuesTmp['website'], 0, 255), mb_strcut($valuesTmp['description'], 0, 1023, 'UTF-8'), $valuesTmp['lastUpdate'], + isset($valuesTmp['priority']) ? intval($valuesTmp['priority']) : FreshRSS_Feed::PRIORITY_MAIN_STREAM, + mb_strcut($valuesTmp['pathEntries'], 0, 511, 'UTF-8'), base64_encode($valuesTmp['httpAuth']), - FreshRSS_Feed::KEEP_HISTORY_DEFAULT, + isset($valuesTmp['error']) ? intval($valuesTmp['error']) : 0, isset($valuesTmp['ttl']) ? intval($valuesTmp['ttl']) : FreshRSS_Feed::TTL_DEFAULT, - isset($valuesTmp['attributes']) ? json_encode($valuesTmp['attributes']) : '', + is_string($valuesTmp['attributes']) ? $valuesTmp['attributes'] : json_encode($valuesTmp['attributes'], JSON_UNESCAPED_SLASHES), ); if ($stm && $stm->execute($values)) { - return $this->bd->lastInsertId('"' . $this->prefix . 'feed_id_seq"'); + return $this->pdo->lastInsertId('`_feed_id_seq`'); } else { - $info = $stm == null ? array(2 => 'syntax error') : $stm->errorInfo(); + $info = $stm == null ? $this->pdo->errorInfo() : $stm->errorInfo(); if ($this->autoUpdateDb($info)) { return $this->addFeed($valuesTmp); } @@ -129,13 +136,13 @@ class FreshRSS_FeedDAO extends Minz_ModelPdo implements FreshRSS_Searchable { if ($key === 'httpAuth') { $valuesTmp[$key] = base64_encode($v); } elseif ($key === 'attributes') { - $valuesTmp[$key] = json_encode($v); + $valuesTmp[$key] = is_string($valuesTmp[$key]) ? $valuesTmp[$key] : json_encode($valuesTmp[$key], JSON_UNESCAPED_SLASHES); } } $set = substr($set, 0, -2); - $sql = 'UPDATE `' . $this->prefix . 'feed` SET ' . $set . ' WHERE id=?'; - $stm = $this->bd->prepare($sql); + $sql = 'UPDATE `_feed` SET ' . $set . ' WHERE id=?'; + $stm = $this->pdo->prepare($sql); foreach ($valuesTmp as $v) { $values[] = $v; @@ -145,7 +152,7 @@ class FreshRSS_FeedDAO extends Minz_ModelPdo implements FreshRSS_Searchable { if ($stm && $stm->execute($values)) { return $stm->rowCount(); } else { - $info = $stm == null ? array(2 => 'syntax error') : $stm->errorInfo(); + $info = $stm == null ? $this->pdo->errorInfo() : $stm->errorInfo(); if ($this->autoUpdateDb($info)) { return $this->updateFeed($id, $valuesTmp); } @@ -166,7 +173,7 @@ class FreshRSS_FeedDAO extends Minz_ModelPdo implements FreshRSS_Searchable { } public function updateLastUpdate($id, $inError = false, $mtime = 0) { //See also updateCachedValue() - $sql = 'UPDATE `' . $this->prefix . 'feed` ' + $sql = 'UPDATE `_feed` ' . 'SET `lastUpdate`=?, error=? ' . 'WHERE id=?'; $values = array( @@ -174,12 +181,12 @@ class FreshRSS_FeedDAO extends Minz_ModelPdo implements FreshRSS_Searchable { $inError ? 1 : 0, $id, ); - $stm = $this->bd->prepare($sql); + $stm = $this->pdo->prepare($sql); if ($stm && $stm->execute($values)) { return $stm->rowCount(); } else { - $info = $stm == null ? array(2 => 'syntax error') : $stm->errorInfo(); + $info = $stm == null ? $this->pdo->errorInfo() : $stm->errorInfo(); Minz_Log::error('SQL error updateLastUpdate: ' . $info[2]); return false; } @@ -192,8 +199,8 @@ class FreshRSS_FeedDAO extends Minz_ModelPdo implements FreshRSS_Searchable { $newCat = $catDAO->getDefault(); } - $sql = 'UPDATE `' . $this->prefix . 'feed` SET category=? WHERE category=?'; - $stm = $this->bd->prepare($sql); + $sql = 'UPDATE `_feed` SET category=? WHERE category=?'; + $stm = $this->pdo->prepare($sql); $values = array( $newCat->id(), @@ -203,44 +210,54 @@ class FreshRSS_FeedDAO extends Minz_ModelPdo implements FreshRSS_Searchable { if ($stm && $stm->execute($values)) { return $stm->rowCount(); } else { - $info = $stm == null ? array(2 => 'syntax error') : $stm->errorInfo(); + $info = $stm == null ? $this->pdo->errorInfo() : $stm->errorInfo(); Minz_Log::error('SQL error changeCategory: ' . $info[2]); return false; } } public function deleteFeed($id) { - $sql = 'DELETE FROM `' . $this->prefix . 'feed` WHERE id=?'; - $stm = $this->bd->prepare($sql); + $sql = 'DELETE FROM `_feed` WHERE id=?'; + $stm = $this->pdo->prepare($sql); $values = array($id); if ($stm && $stm->execute($values)) { return $stm->rowCount(); } else { - $info = $stm == null ? array(2 => 'syntax error') : $stm->errorInfo(); + $info = $stm == null ? $this->pdo->errorInfo() : $stm->errorInfo(); Minz_Log::error('SQL error deleteFeed: ' . $info[2]); return false; } } public function deleteFeedByCategory($id) { - $sql = 'DELETE FROM `' . $this->prefix . 'feed` WHERE category=?'; - $stm = $this->bd->prepare($sql); + $sql = 'DELETE FROM `_feed` WHERE category=?'; + $stm = $this->pdo->prepare($sql); $values = array($id); if ($stm && $stm->execute($values)) { return $stm->rowCount(); } else { - $info = $stm == null ? array(2 => 'syntax error') : $stm->errorInfo(); + $info = $stm == null ? $this->pdo->errorInfo() : $stm->errorInfo(); Minz_Log::error('SQL error deleteFeedByCategory: ' . $info[2]); return false; } } + public function selectAll() { + $sql = 'SELECT id, url, category, name, website, description, `lastUpdate`, priority, ' + . '`pathEntries`, `httpAuth`, error, ttl, attributes ' + . 'FROM `_feed`'; + $stm = $this->pdo->query($sql); + while ($row = $stm->fetch(PDO::FETCH_ASSOC)) { + yield $row; + } + } + public function searchById($id) { - $sql = 'SELECT * FROM `' . $this->prefix . 'feed` WHERE id=?'; - $stm = $this->bd->prepare($sql); + $sql = 'SELECT * FROM `_feed` WHERE id=?'; + $stm = $this->pdo->prepare($sql); $values = array($id); @@ -255,8 +272,8 @@ class FreshRSS_FeedDAO extends Minz_ModelPdo implements FreshRSS_Searchable { } } public function searchByUrl($url) { - $sql = 'SELECT * FROM `' . $this->prefix . 'feed` WHERE url=?'; - $stm = $this->bd->prepare($sql); + $sql = 'SELECT * FROM `_feed` WHERE url=?'; + $stm = $this->pdo->prepare($sql); $values = array($url); @@ -272,25 +289,21 @@ class FreshRSS_FeedDAO extends Minz_ModelPdo implements FreshRSS_Searchable { } public function listFeedsIds() { - $sql = 'SELECT id FROM `' . $this->prefix . 'feed`'; - $stm = $this->bd->prepare($sql); - $stm->execute(); + $sql = 'SELECT id FROM `_feed`'; + $stm = $this->pdo->query($sql); return $stm->fetchAll(PDO::FETCH_COLUMN, 0); } public function listFeeds() { - $sql = 'SELECT * FROM `' . $this->prefix . 'feed` ORDER BY name'; - $stm = $this->bd->prepare($sql); - $stm->execute(); - + $sql = 'SELECT * FROM `_feed` ORDER BY name'; + $stm = $this->pdo->query($sql); return self::daoToFeed($stm->fetchAll(PDO::FETCH_ASSOC)); } public function arrayFeedCategoryNames() { //For API - $sql = 'SELECT f.id, f.name, c.name as c_name FROM `' . $this->prefix . 'feed` f ' - . 'INNER JOIN `' . $this->prefix . 'category` c ON c.id = f.category'; - $stm = $this->bd->prepare($sql); - $stm->execute(); + $sql = 'SELECT f.id, f.name, c.name as c_name FROM `_feed` f ' + . 'INNER JOIN `_category` c ON c.id = f.category'; + $stm = $this->pdo->query($sql); $res = $stm->fetchAll(PDO::FETCH_ASSOC); $feedCategoryNames = array(); foreach ($res as $line) { @@ -307,17 +320,18 @@ class FreshRSS_FeedDAO extends Minz_ModelPdo implements FreshRSS_Searchable { */ public function listFeedsOrderUpdate($defaultCacheDuration = 3600, $limit = 0) { $this->updateTTL(); - $sql = 'SELECT id, url, name, website, `lastUpdate`, `pathEntries`, `httpAuth`, keep_history, ttl, attributes ' - . 'FROM `' . $this->prefix . 'feed` ' + $sql = 'SELECT id, url, name, website, `lastUpdate`, `pathEntries`, `httpAuth`, ttl, attributes ' + . 'FROM `_feed` ' . ($defaultCacheDuration < 0 ? '' : 'WHERE ttl >= ' . FreshRSS_Feed::TTL_DEFAULT - . ' AND `lastUpdate` < (' . (time() + 60) . '-(CASE WHEN ttl=' . FreshRSS_Feed::TTL_DEFAULT . ' THEN ' . intval($defaultCacheDuration) . ' ELSE ttl END)) ') + . ' AND `lastUpdate` < (' . (time() + 60) + . '-(CASE WHEN ttl=' . FreshRSS_Feed::TTL_DEFAULT . ' THEN ' . intval($defaultCacheDuration) . ' ELSE ttl END)) ') . 'ORDER BY `lastUpdate` ' . ($limit < 1 ? '' : 'LIMIT ' . intval($limit)); - $stm = $this->bd->prepare($sql); - if ($stm && $stm->execute()) { + $stm = $this->pdo->query($sql); + if ($stm !== false) { return self::daoToFeed($stm->fetchAll(PDO::FETCH_ASSOC)); } else { - $info = $stm == null ? array(0 => '', 1 => '', 2 => 'syntax error') : $stm->errorInfo(); + $info = $stm == null ? $this->pdo->errorInfo() : $stm->errorInfo(); if ($this->autoUpdateDb($info)) { return $this->listFeedsOrderUpdate($defaultCacheDuration); } @@ -327,8 +341,8 @@ class FreshRSS_FeedDAO extends Minz_ModelPdo implements FreshRSS_Searchable { } public function listByCategory($cat) { - $sql = 'SELECT * FROM `' . $this->prefix . 'feed` WHERE category=? ORDER BY name'; - $stm = $this->bd->prepare($sql); + $sql = 'SELECT * FROM `_feed` WHERE category=? ORDER BY name'; + $stm = $this->pdo->prepare($sql); $values = array($cat); @@ -338,8 +352,8 @@ class FreshRSS_FeedDAO extends Minz_ModelPdo implements FreshRSS_Searchable { } public function countEntries($id) { - $sql = 'SELECT COUNT(*) AS count FROM `' . $this->prefix . 'entry` WHERE id_feed=?'; - $stm = $this->bd->prepare($sql); + $sql = 'SELECT COUNT(*) AS count FROM `_entry` WHERE id_feed=?'; + $stm = $this->pdo->prepare($sql); $values = array($id); $stm->execute($values); $res = $stm->fetchAll(PDO::FETCH_ASSOC); @@ -348,8 +362,8 @@ class FreshRSS_FeedDAO extends Minz_ModelPdo implements FreshRSS_Searchable { } public function countNotRead($id) { - $sql = 'SELECT COUNT(*) AS count FROM `' . $this->prefix . 'entry` WHERE id_feed=? AND is_read=0'; - $stm = $this->bd->prepare($sql); + $sql = 'SELECT COUNT(*) AS count FROM `_entry` WHERE id_feed=? AND is_read=0'; + $stm = $this->pdo->prepare($sql); $values = array($id); $stm->execute($values); $res = $stm->fetchAll(PDO::FETCH_ASSOC); @@ -357,62 +371,51 @@ class FreshRSS_FeedDAO extends Minz_ModelPdo implements FreshRSS_Searchable { return $res[0]['count']; } - public function updateCachedValue($id) { //For multiple feeds, call updateCachedValues() - $sql = 'UPDATE `' . $this->prefix . 'feed` ' //2 sub-requests with FOREIGN KEY(e.id_feed), INDEX(e.is_read) faster than 1 request with GROUP BY or CASE - . 'SET `cache_nbEntries`=(SELECT COUNT(e1.id) FROM `' . $this->prefix . 'entry` e1 WHERE e1.id_feed=`' . $this->prefix . 'feed`.id),' - . '`cache_nbUnreads`=(SELECT COUNT(e2.id) FROM `' . $this->prefix . 'entry` e2 WHERE e2.id_feed=`' . $this->prefix . 'feed`.id AND e2.is_read=0) ' - . 'WHERE id=?'; - $values = array($id); - $stm = $this->bd->prepare($sql); - - if ($stm && $stm->execute($values)) { - return $stm->rowCount(); - } else { - $info = $stm == null ? array(2 => 'syntax error') : $stm->errorInfo(); - Minz_Log::error('SQL error updateCachedValue: ' . $info[2]); - return false; + public function updateCachedValues($id = null) { + //2 sub-requests with FOREIGN KEY(e.id_feed), INDEX(e.is_read) faster than 1 request with GROUP BY or CASE + $sql = 'UPDATE `_feed` ' + . 'SET `cache_nbEntries`=(SELECT COUNT(e1.id) FROM `_entry` e1 WHERE e1.id_feed=`_feed`.id),' + . '`cache_nbUnreads`=(SELECT COUNT(e2.id) FROM `_entry` e2 WHERE e2.id_feed=`_feed`.id AND e2.is_read=0)' + . ($id != null ? ' WHERE id=:id' : ''); + $stm = $this->pdo->prepare($sql); + if ($id != null) { + $stm->bindParam(':id', $id, PDO::PARAM_INT); } - } - public function updateCachedValues() { //For one single feed, call updateCachedValue($id) - $sql = 'UPDATE `' . $this->prefix . 'feed` ' - . 'SET `cache_nbEntries`=(SELECT COUNT(e1.id) FROM `' . $this->prefix . 'entry` e1 WHERE e1.id_feed=`' . $this->prefix . 'feed`.id),' - . '`cache_nbUnreads`=(SELECT COUNT(e2.id) FROM `' . $this->prefix . 'entry` e2 WHERE e2.id_feed=`' . $this->prefix . 'feed`.id AND e2.is_read=0)'; - $stm = $this->bd->prepare($sql); if ($stm && $stm->execute()) { return $stm->rowCount(); } else { - $info = $stm == null ? array(2 => 'syntax error') : $stm->errorInfo(); - Minz_Log::error('SQL error updateCachedValues: ' . $info[2]); + $info = $stm == null ? $this->pdo->errorInfo() : $stm->errorInfo(); + Minz_Log::error('SQL error updateCachedValue: ' . $info[2]); return false; } } public function truncate($id) { - $sql = 'DELETE FROM `' . $this->prefix . 'entry` WHERE id_feed=?'; - $stm = $this->bd->prepare($sql); - $values = array($id); - $this->bd->beginTransaction(); - if (!($stm && $stm->execute($values))) { - $info = $stm == null ? array(2 => 'syntax error') : $stm->errorInfo(); + $sql = 'DELETE FROM `_entry` WHERE id_feed=:id'; + $stm = $this->pdo->prepare($sql); + $stm->bindParam(':id', $id, PDO::PARAM_INT); + $this->pdo->beginTransaction(); + if (!($stm && $stm->execute())) { + $info = $stm == null ? $this->pdo->errorInfo() : $stm->errorInfo(); Minz_Log::error('SQL error truncate: ' . $info[2]); - $this->bd->rollBack(); + $this->pdo->rollBack(); return false; } $affected = $stm->rowCount(); - $sql = 'UPDATE `' . $this->prefix . 'feed` ' - . 'SET `cache_nbEntries`=0, `cache_nbUnreads`=0 WHERE id=?'; - $values = array($id); - $stm = $this->bd->prepare($sql); - if (!($stm && $stm->execute($values))) { - $info = $stm == null ? array(2 => 'syntax error') : $stm->errorInfo(); + $sql = 'UPDATE `_feed` ' + . 'SET `cache_nbEntries`=0, `cache_nbUnreads`=0 WHERE id=:id'; + $stm = $this->pdo->prepare($sql); + $stm->bindParam(':id', $id, PDO::PARAM_INT); + if (!($stm && $stm->execute())) { + $info = $stm == null ? $this->pdo->errorInfo() : $stm->errorInfo(); Minz_Log::error('SQL error truncate: ' . $info[2]); - $this->bd->rollBack(); + $this->pdo->rollBack(); return false; } - $this->bd->commit(); + $this->pdo->commit(); return $affected; } @@ -446,7 +449,6 @@ class FreshRSS_FeedDAO extends Minz_ModelPdo implements FreshRSS_Searchable { $myFeed->_pathEntries(isset($dao['pathEntries']) ? $dao['pathEntries'] : ''); $myFeed->_httpAuth(isset($dao['httpAuth']) ? base64_decode($dao['httpAuth']) : ''); $myFeed->_error(isset($dao['error']) ? $dao['error'] : 0); - $myFeed->_keepHistory(isset($dao['keep_history']) ? $dao['keep_history'] : FreshRSS_Feed::KEEP_HISTORY_DEFAULT); $myFeed->_ttl(isset($dao['ttl']) ? $dao['ttl'] : FreshRSS_Feed::TTL_DEFAULT); $myFeed->_attributes('', isset($dao['attributes']) ? $dao['attributes'] : ''); $myFeed->_nbNotRead(isset($dao['cache_nbUnreads']) ? $dao['cache_nbUnreads'] : 0); @@ -461,20 +463,16 @@ class FreshRSS_FeedDAO extends Minz_ModelPdo implements FreshRSS_Searchable { } public function updateTTL() { - $sql = <<<SQL -UPDATE `{$this->prefix}feed` - SET ttl = :new_value - WHERE ttl = :old_value -SQL; - $stm = $this->bd->prepare($sql); + $sql = 'UPDATE `_feed` SET ttl=:new_value WHERE ttl=:old_value'; + $stm = $this->pdo->prepare($sql); if (!($stm && $stm->execute(array(':new_value' => FreshRSS_Feed::TTL_DEFAULT, ':old_value' => -2)))) { - $info = $stm == null ? array(2 => 'syntax error') : $stm->errorInfo(); + $info = $stm == null ? $this->pdo->errorInfo() : $stm->errorInfo(); Minz_Log::error('SQL warning updateTTL 1: ' . $info[2] . ' ' . $sql); - $sql2 = 'ALTER TABLE `' . $this->prefix . 'feed` ADD COLUMN ttl INT NOT NULL DEFAULT ' . FreshRSS_Feed::TTL_DEFAULT; //v0.7.3 - $stm = $this->bd->prepare($sql2); - if (!($stm && $stm->execute())) { - $info = $stm == null ? array(2 => 'syntax error') : $stm->errorInfo(); + $sql2 = 'ALTER TABLE `_feed` ADD COLUMN ttl INT NOT NULL DEFAULT ' . FreshRSS_Feed::TTL_DEFAULT; //v0.7.3 + $stm = $this->pdo->query($sql2); + if ($stm === false) { + $info = $stm == null ? $this->pdo->errorInfo() : $stm->errorInfo(); Minz_Log::error('SQL error updateTTL 2: ' . $info[2] . ' ' . $sql2); } } else { |
