diff -u b/core/modules/history/history.module b/core/modules/history/history.module --- b/core/modules/history/history.module +++ b/core/modules/history/history.module @@ -81,7 +81,7 @@ return $return; } - $result = \Drupal::database()->query('SELECT [nid], [timestamp] FROM {history} WHERE [uid] = :uid AND [nid] IN ( :nids[] )', [ + $result = \Drupal::database()->query('SELECT [nid], timestamp FROM {history} WHERE [uid] = :uid AND [nid] IN ( :nids[] )', [ ':uid' => \Drupal::currentUser()->id(), ':nids[]' => array_keys($nodes_to_read), ]); diff -u b/core/modules/migrate/migrate.api.php b/core/modules/migrate/migrate.api.php --- b/core/modules/migrate/migrate.api.php +++ b/core/modules/migrate/migrate.api.php @@ -136,7 +136,7 @@ * @ingroup migration */ function hook_migrate_MIGRATION_ID_prepare_row(Row $row, MigrateSourceInterface $source, MigrationInterface $migration) { - $value = $source->getDatabase()->query('SELECT value FROM {variable} WHERE name = :name', [':name' => 'mymodule_filter_foo_' . $row->getSourceProperty('format')])->fetchField(); + $value = $source->getDatabase()->query('SELECT [value] FROM {variable} WHERE [name] = :name', [':name' => 'mymodule_filter_foo_' . $row->getSourceProperty('format')])->fetchField(); if ($value) { $row->setSourceProperty('settings:mymodule:foo', unserialize($value)); } diff -u b/core/modules/search/src/SearchIndex.php b/core/modules/search/src/SearchIndex.php --- b/core/modules/search/src/SearchIndex.php +++ b/core/modules/search/src/SearchIndex.php @@ -286,7 +286,7 @@ $words = array_keys($words); foreach ($words as $word) { // Get total count. - $total = $this->replica->query("SELECT SUM(score) FROM {search_index} WHERE word = :word", [':word' => $word]) + $total = $this->replica->query("SELECT SUM([score]) FROM {search_index} WHERE [word] = :word", [':word' => $word]) ->fetchField(); // Apply Zipf's law to equalize the probability distribution. $total = log10(1 + 1 / (max(1, $total))); @@ -298,7 +298,7 @@ // Find words that were deleted from search_index, but are still in // search_total. We use a LEFT JOIN between the two tables and keep only // the rows which fail to join. - $result = $this->replica->query("SELECT [t.word] AS realword, [i.word] FROM {search_total} t LEFT JOIN {search_index} i ON t.word = i.word WHERE [i.word] IS NULL"); + $result = $this->replica->query("SELECT [t].[word] AS realword, [i].[word] FROM {search_total} t LEFT JOIN {search_index} i ON [t].[word] = [i].[word] WHERE [i].[word] IS NULL"); $or = new Condition('OR'); foreach ($result as $word) { $or->condition('word', $word->realword); reverted: --- b/core/modules/search/tests/src/Functional/SearchNodeUpdateAndDeletionTest.php +++ a/core/modules/search/tests/src/Functional/SearchNodeUpdateAndDeletionTest.php @@ -100,7 +100,7 @@ // Get the node info from the search index tables. $connection = Database::getConnection(); + $search_index_dataset = $connection->query("SELECT sid FROM {search_index} WHERE type = 'node_search' AND word = :word", [':word' => 'dragons']) - $search_index_dataset = $connection->query("SELECT [sid] FROM {search_index} WHERE [type] = 'node_search' AND [word] = :word", [':word' => 'dragons']) ->fetchField(); $this->assertNotEqual($search_index_dataset, FALSE, t('Node info found on the search_index')); @@ -108,7 +108,7 @@ $node->delete(); // Check if the node info is gone from the search table. + $search_index_dataset = $connection->query("SELECT sid FROM {search_index} WHERE type = 'node_search' AND word = :word", [':word' => 'dragons']) - $search_index_dataset = $connection->query("SELECT [sid] FROM {search_index} WHERE [type] = 'node_search' AND [word] = :word", [':word' => 'dragons']) ->fetchField(); $this->assertFalse($search_index_dataset, t('Node info successfully removed from search_index')); reverted: --- b/core/modules/system/tests/src/Functional/Database/TemporaryQueryTest.php +++ a/core/modules/system/tests/src/Functional/Database/TemporaryQueryTest.php @@ -44,8 +44,8 @@ } // Now try to run two temporary queries in the same request. + $table_name_test = $connection->queryTemporary('SELECT name FROM {test}', []); + $table_name_task = $connection->queryTemporary('SELECT pid FROM {test_task}', []); - $table_name_test = $connection->queryTemporary('SELECT [name] FROM {test}', []); - $table_name_task = $connection->queryTemporary('SELECT [pid] FROM {test_task}', []); $this->assertEqual($this->countTableRows($table_name_test), $this->countTableRows('test'), 'A temporary table was created successfully in this request.'); $this->assertEqual($this->countTableRows($table_name_task), $this->countTableRows('test_task'), 'A second temporary table was created successfully in this request.'); reverted: --- b/core/modules/taxonomy/tests/src/Functional/TermIndexTest.php +++ a/core/modules/taxonomy/tests/src/Functional/TermIndexTest.php @@ -117,7 +117,7 @@ // Check that the term is indexed, and only once. $node = $this->drupalGetNodeByTitle($edit['title[0][value]']); $connection = Database::getConnection(); + $index_count = $connection->query('SELECT COUNT(*) FROM {taxonomy_index} WHERE nid = :nid AND tid = :tid', [ - $index_count = $connection->query('SELECT COUNT(*) FROM {taxonomy_index} WHERE [nid] = :nid AND [tid] = :tid', [ ':nid' => $node->id(), ':tid' => $term_1->id(), ])->fetchField(); @@ -128,12 +128,12 @@ $this->drupalPostForm('node/' . $node->id() . '/edit', $edit, t('Save')); // Check that both terms are indexed. + $index_count = $connection->query('SELECT COUNT(*) FROM {taxonomy_index} WHERE nid = :nid AND tid = :tid', [ - $index_count = $connection->query('SELECT COUNT(*) FROM {taxonomy_index} WHERE [nid] = :nid AND [tid] = :tid', [ ':nid' => $node->id(), ':tid' => $term_1->id(), ])->fetchField(); $this->assertEqual(1, $index_count, 'Term 1 is indexed.'); + $index_count = $connection->query('SELECT COUNT(*) FROM {taxonomy_index} WHERE nid = :nid AND tid = :tid', [ - $index_count = $connection->query('SELECT COUNT(*) FROM {taxonomy_index} WHERE [nid] = :nid AND [tid] = :tid', [ ':nid' => $node->id(), ':tid' => $term_2->id(), ])->fetchField(); @@ -144,12 +144,12 @@ $this->drupalPostForm('node/' . $node->id() . '/edit', $edit, t('Save')); // Check that only one term is indexed. + $index_count = $connection->query('SELECT COUNT(*) FROM {taxonomy_index} WHERE nid = :nid AND tid = :tid', [ - $index_count = $connection->query('SELECT COUNT(*) FROM {taxonomy_index} WHERE [nid] = :nid AND [tid] = :tid', [ ':nid' => $node->id(), ':tid' => $term_1->id(), ])->fetchField(); $this->assertEqual(0, $index_count, 'Term 1 is not indexed.'); + $index_count = $connection->query('SELECT COUNT(*) FROM {taxonomy_index} WHERE nid = :nid AND tid = :tid', [ - $index_count = $connection->query('SELECT COUNT(*) FROM {taxonomy_index} WHERE [nid] = :nid AND [tid] = :tid', [ ':nid' => $node->id(), ':tid' => $term_2->id(), ])->fetchField(); @@ -164,12 +164,12 @@ $node->save(); // Check that the index was not changed. + $index_count = $connection->query('SELECT COUNT(*) FROM {taxonomy_index} WHERE nid = :nid AND tid = :tid', [ - $index_count = $connection->query('SELECT COUNT(*) FROM {taxonomy_index} WHERE [nid] = :nid AND [tid] = :tid', [ ':nid' => $node->id(), ':tid' => $term_1->id(), ])->fetchField(); $this->assertEqual(0, $index_count, 'Term 1 is not indexed.'); + $index_count = $connection->query('SELECT COUNT(*) FROM {taxonomy_index} WHERE nid = :nid AND tid = :tid', [ - $index_count = $connection->query('SELECT COUNT(*) FROM {taxonomy_index} WHERE [nid] = :nid AND [tid] = :tid', [ ':nid' => $node->id(), ':tid' => $term_2->id(), ])->fetchField(); @@ -180,12 +180,12 @@ $node->save(); // Check that both terms are indexed. + $index_count = $connection->query('SELECT COUNT(*) FROM {taxonomy_index} WHERE nid = :nid AND tid = :tid', [ - $index_count = $connection->query('SELECT COUNT(*) FROM {taxonomy_index} WHERE [nid] = :nid AND [tid] = :tid', [ ':nid' => $node->id(), ':tid' => $term_1->id(), ])->fetchField(); $this->assertEqual(1, $index_count, 'Term 1 is indexed.'); + $index_count = $connection->query('SELECT COUNT(*) FROM {taxonomy_index} WHERE nid = :nid AND tid = :tid', [ - $index_count = $connection->query('SELECT COUNT(*) FROM {taxonomy_index} WHERE [nid] = :nid AND [tid] = :tid', [ ':nid' => $node->id(), ':tid' => $term_2->id(), ])->fetchField(); @@ -196,12 +196,12 @@ $node->save(); // Check that only one term is indexed. + $index_count = $connection->query('SELECT COUNT(*) FROM {taxonomy_index} WHERE nid = :nid AND tid = :tid', [ - $index_count = $connection->query('SELECT COUNT(*) FROM {taxonomy_index} WHERE [nid] = :nid AND [tid] = :tid', [ ':nid' => $node->id(), ':tid' => $term_1->id(), ])->fetchField(); $this->assertEqual(1, $index_count, 'Term 1 is indexed once.'); + $index_count = $connection->query('SELECT COUNT(*) FROM {taxonomy_index} WHERE nid = :nid AND tid = :tid', [ - $index_count = $connection->query('SELECT COUNT(*) FROM {taxonomy_index} WHERE [nid] = :nid AND [tid] = :tid', [ ':nid' => $node->id(), ':tid' => $term_2->id(), ])->fetchField(); diff -u b/core/modules/tracker/tracker.module b/core/modules/tracker/tracker.module --- b/core/modules/tracker/tracker.module +++ b/core/modules/tracker/tracker.module @@ -212,7 +212,7 @@ $connection = \Drupal::database(); // @todo This should be actually filtering on the desired language and just // fall back to the default language. - $node = $connection->query('SELECT [nid], [status], [uid], [changed] FROM {node_field_data} WHERE [nid] = :nid AND [default_langcode] = 1 ORDER BY changed DESC, status DESC', [':nid' => $nid])->fetchObject(); + $node = $connection->query('SELECT [nid], [status], [uid], [changed] FROM {node_field_data} WHERE [nid] = :nid AND [default_langcode] = 1 ORDER BY [changed] DESC, [status] DESC', [':nid' => $nid])->fetchObject(); // Adding a comment can only increase the changed timestamp, so our // calculation here is simple. @@ -314,7 +314,7 @@ // and the node itself. // We only need to do this if the removed item has a timestamp that equals // or exceeds the listed changed timestamp for the node. - $tracker_node = $connection->query('SELECT nid, changed FROM {tracker_node} WHERE nid = :nid', [':nid' => $nid])->fetchObject(); + $tracker_node = $connection->query('SELECT [nid], [changed] FROM {tracker_node} WHERE [nid] = :nid', [':nid' => $nid])->fetchObject(); if ($tracker_node && $changed >= $tracker_node->changed) { // If we're here, the item being removed is *possibly* the item that // established the node's changed timestamp. only in patch2: unchanged: --- a/core/modules/aggregator/src/FeedStorage.php +++ b/core/modules/aggregator/src/FeedStorage.php @@ -16,7 +16,7 @@ class FeedStorage extends SqlContentEntityStorage implements FeedStorageInterfac * {@inheritdoc} */ public function getFeedIdsToRefresh() { - return $this->database->query('SELECT fid FROM {' . $this->getBaseTable() . '} WHERE queued = 0 AND checked + refresh < :time AND refresh <> :never', [ + return $this->database->query('SELECT [fid] FROM {' . $this->getBaseTable() . '} WHERE [queued] = 0 AND [checked] + [refresh] < :time AND [refresh] <> :never', [ ':time' => REQUEST_TIME, ':never' => static::CLEAR_NEVER, ])->fetchCol(); only in patch2: unchanged: --- a/core/modules/ban/src/BanIpManager.php +++ b/core/modules/ban/src/BanIpManager.php @@ -30,7 +30,7 @@ public function __construct(Connection $connection) { * {@inheritdoc} */ public function isBanned($ip) { - return (bool) $this->connection->query("SELECT * FROM {ban_ip} WHERE ip = :ip", [':ip' => $ip])->fetchField(); + return (bool) $this->connection->query("SELECT * FROM {ban_ip} WHERE [ip] = :ip", [':ip' => $ip])->fetchField(); } /** @@ -63,7 +63,7 @@ public function unbanIp($id) { * {@inheritdoc} */ public function findById($ban_id) { - return $this->connection->query("SELECT ip FROM {ban_ip} WHERE iid = :iid", [':iid' => $ban_id])->fetchField(); + return $this->connection->query("SELECT [ip] FROM {ban_ip} WHERE [iid] = :iid", [':iid' => $ban_id])->fetchField(); } } only in patch2: unchanged: --- a/core/modules/book/src/BookOutlineStorage.php +++ b/core/modules/book/src/BookOutlineStorage.php @@ -27,7 +27,7 @@ public function __construct(Connection $connection) { * {@inheritdoc} */ public function getBooks() { - return $this->connection->query("SELECT DISTINCT(bid) FROM {book}")->fetchCol(); + return $this->connection->query("SELECT DISTINCT([bid]) FROM {book}")->fetchCol(); } /** @@ -35,7 +35,7 @@ public function getBooks() { */ public function hasBooks() { return (bool) $this->connection - ->query('SELECT count(bid) FROM {book}') + ->query('SELECT count([bid]) FROM {book}') ->fetchField(); } @@ -89,7 +89,7 @@ public function delete($nid) { */ public function loadBookChildren($pid) { return $this->connection - ->query("SELECT * FROM {book} WHERE pid = :pid", [':pid' => $pid]) + ->query("SELECT * FROM {book} WHERE [pid] = :pid", [':pid' => $pid]) ->fetchAllAssoc('nid', \PDO::FETCH_ASSOC); } only in patch2: unchanged: --- a/core/modules/comment/src/CommentStatistics.php +++ b/core/modules/comment/src/CommentStatistics.php @@ -154,7 +154,7 @@ public function create(FieldableEntityInterface $entity, $fields) { * {@inheritdoc} */ public function getMaximumCount($entity_type) { - return $this->database->query('SELECT MAX(comment_count) FROM {comment_entity_statistics} WHERE entity_type = :entity_type', [':entity_type' => $entity_type])->fetchField(); + return $this->database->query('SELECT MAX([comment_count]) FROM {comment_entity_statistics} WHERE [entity_type] = :entity_type', [':entity_type' => $entity_type])->fetchField(); } /** only in patch2: unchanged: --- a/core/modules/comment/src/CommentStorage.php +++ b/core/modules/comment/src/CommentStorage.php @@ -185,12 +185,12 @@ public function getNewCommentPageNumber($total_comments, $new_comments, Fieldabl $first_thread = substr($first_thread, 0, -1); // Find the number of the first comment of the first unread thread. - $count = $this->database->query('SELECT COUNT(*) FROM {' . $data_table . '} WHERE entity_id = :entity_id - AND entity_type = :entity_type - AND field_name = :field_name - AND status = :status - AND SUBSTRING(thread, 1, (LENGTH(thread) - 1)) < :thread - AND default_langcode = 1', [ + $count = $this->database->query('SELECT COUNT(*) FROM {' . $data_table . '} WHERE [entity_id] = :entity_id + AND [entity_type] = :entity_type + AND [field_name] = :field_name + AND [status] = :status + AND SUBSTRING([thread], 1, (LENGTH([thread]) - 1)) < :thread + AND [default_langcode] = 1', [ ':status' => CommentInterface::PUBLISHED, ':entity_id' => $entity->id(), ':field_name' => $field_name, only in patch2: unchanged: --- a/core/modules/comment/src/Plugin/views/argument/UserUid.php +++ b/core/modules/comment/src/Plugin/views/argument/UserUid.php @@ -54,7 +54,7 @@ public function title() { $title = \Drupal::config('user.settings')->get('anonymous'); } else { - $title = $this->database->query('SELECT name FROM {users_field_data} WHERE uid = :uid AND default_langcode = 1', [':uid' => $this->argument])->fetchField(); + $title = $this->database->query('SELECT [name] FROM {users_field_data} WHERE [uid] = :uid AND [default_langcode] = 1', [':uid' => $this->argument])->fetchField(); } if (empty($title)) { return $this->t('No user'); only in patch2: unchanged: --- a/core/modules/comment/src/Plugin/views/field/NodeNewComments.php +++ b/core/modules/comment/src/Plugin/views/field/NodeNewComments.php @@ -155,9 +155,9 @@ public function preRender(&$values) { } if ($nids) { - $result = $this->database->query("SELECT n.nid, COUNT(c.cid) as num_comments FROM {node} n INNER JOIN {comment_field_data} c ON n.nid = c.entity_id AND c.entity_type = 'node' AND c.default_langcode = 1 - LEFT JOIN {history} h ON h.nid = n.nid AND h.uid = :h_uid WHERE n.nid IN ( :nids[] ) - AND c.changed > GREATEST(COALESCE(h.timestamp, :timestamp1), :timestamp2) AND c.status = :status GROUP BY n.nid", [ + $result = $this->database->query("SELECT [n].[nid], COUNT([c].[cid]) as num_comments FROM {node} n INNER JOIN {comment_field_data} c ON [n].[nid] = [c].[entity_id] AND [c].[entity_type] = 'node' AND [c].[default_langcode] = 1 + LEFT JOIN {history} h ON [h].[nid] = [n].[nid] AND [h].[uid] = :h_uid WHERE [n].[nid] IN ( :nids[] ) + AND [c].[changed] > GREATEST(COALESCE(h.timestamp, :timestamp1), :timestamp2) AND [c].[status] = :status GROUP BY [n].[nid]", [ ':status' => CommentInterface::PUBLISHED, ':h_uid' => $user->id(), ':nids[]' => $nids, only in patch2: unchanged: --- a/core/modules/dblog/dblog.module +++ b/core/modules/dblog/dblog.module @@ -90,7 +90,7 @@ function dblog_cron() { * List of uniquely defined database log message types. */ function _dblog_get_message_types() { - return \Drupal::database()->query('SELECT DISTINCT(type) FROM {watchdog} ORDER BY type') + return \Drupal::database()->query('SELECT DISTINCT([type]) FROM {watchdog} ORDER BY [type]') ->fetchAllKeyed(0, 0); } only in patch2: unchanged: --- a/core/modules/dblog/src/Controller/DbLogController.php +++ b/core/modules/dblog/src/Controller/DbLogController.php @@ -248,7 +248,7 @@ public function overview() { * If no event found for the given ID. */ public function eventDetails($event_id) { - $dblog = $this->database->query('SELECT w.*, u.uid FROM {watchdog} w LEFT JOIN {users} u ON u.uid = w.uid WHERE w.wid = :id', [':id' => $event_id])->fetchObject(); + $dblog = $this->database->query('SELECT w.*, [u].[uid] FROM {watchdog} w LEFT JOIN {users} u ON [u].[uid] = [w].[uid] WHERE [w].[wid] = :id', [':id' => $event_id])->fetchObject(); if (empty($dblog)) { throw new NotFoundHttpException(); only in patch2: unchanged: --- a/core/modules/dblog/src/Plugin/rest/resource/DBLogResource.php +++ b/core/modules/dblog/src/Plugin/rest/resource/DBLogResource.php @@ -39,7 +39,7 @@ class DBLogResource extends ResourceBase { */ public function get($id = NULL) { if ($id) { - $record = Database::getConnection()->query("SELECT * FROM {watchdog} WHERE wid = :wid", [':wid' => $id]) + $record = Database::getConnection()->query("SELECT * FROM {watchdog} WHERE [wid] = :wid", [':wid' => $id]) ->fetchAssoc(); if (!empty($record)) { return new ResourceResponse($record); only in patch2: unchanged: --- a/core/modules/forum/src/ForumIndexStorage.php +++ b/core/modules/forum/src/ForumIndexStorage.php @@ -32,7 +32,7 @@ public function __construct(Connection $database) { * {@inheritdoc} */ public function getOriginalTermId(NodeInterface $node) { - return $this->database->queryRange("SELECT f.tid FROM {forum} f INNER JOIN {node} n ON f.vid = n.vid WHERE n.nid = :nid ORDER BY f.vid DESC", 0, 1, [':nid' => $node->id()])->fetchField(); + return $this->database->queryRange("SELECT [f].[tid] FROM {forum} f INNER JOIN {node} n ON [f].[vid] = [n].[vid] WHERE [n].[nid] = :nid ORDER BY [f].[vid] DESC", 0, 1, [':nid' => $node->id()])->fetchField(); } /** @@ -92,14 +92,14 @@ public function update(NodeInterface $node) { */ public function updateIndex(NodeInterface $node) { $nid = $node->id(); - $count = $this->database->query("SELECT COUNT(cid) FROM {comment_field_data} c INNER JOIN {forum_index} i ON c.entity_id = i.nid WHERE c.entity_id = :nid AND c.field_name = 'comment_forum' AND c.entity_type = 'node' AND c.status = :status AND c.default_langcode = 1", [ + $count = $this->database->query("SELECT COUNT([cid]) FROM {comment_field_data} c INNER JOIN {forum_index} i ON [c].[entity_id] = [i].[nid] WHERE [c].[entity_id] = :nid AND [c].[field_name] = 'comment_forum' AND [c].[entity_type] = 'node' AND [c].[status] = :status AND [c].[default_langcode] = 1", [ ':nid' => $nid, ':status' => CommentInterface::PUBLISHED, ])->fetchField(); if ($count > 0) { // Comments exist. - $last_reply = $this->database->queryRange("SELECT cid, name, created, uid FROM {comment_field_data} WHERE entity_id = :nid AND field_name = 'comment_forum' AND entity_type = 'node' AND status = :status AND default_langcode = 1 ORDER BY cid DESC", 0, 1, [ + $last_reply = $this->database->queryRange("SELECT [cid], [name], [created], [uid] FROM {comment_field_data} WHERE [entity_id] = :nid AND [field_name] = 'comment_forum' AND [entity_type] = 'node' AND [status] = :status AND [default_langcode] = 1 ORDER BY [cid] DESC", 0, 1, [ ':nid' => $nid, ':status' => CommentInterface::PUBLISHED, ])->fetchObject(); only in patch2: unchanged: --- a/core/modules/locale/locale.module +++ b/core/modules/locale/locale.module @@ -799,7 +799,7 @@ function locale_translation_get_file_history() { if (empty($history)) { // Get file history from the database. - $result = \Drupal::database()->query('SELECT project, langcode, filename, version, uri, timestamp, last_checked FROM {locale_file}'); + $result = \Drupal::database()->query('SELECT [project], [langcode], [filename], [version], [uri], timestamp, [last_checked] FROM {locale_file}'); foreach ($result as $file) { $file->type = $file->timestamp ? LOCALE_TRANSLATION_CURRENT : ''; $history[$file->project][$file->langcode] = $file; only in patch2: unchanged: --- a/core/modules/node/node.api.php +++ b/core/modules/node/node.api.php @@ -380,7 +380,7 @@ function hook_node_access(\Drupal\node\NodeInterface $node, $op, \Drupal\Core\Se * @ingroup entity_crud */ function hook_node_search_result(\Drupal\node\NodeInterface $node) { - $rating = \Drupal::database()->query('SELECT SUM(points) FROM {my_rating} WHERE nid = :nid', ['nid' => $node->id()])->fetchField(); + $rating = \Drupal::database()->query('SELECT SUM([points]) FROM {my_rating} WHERE [nid] = :nid', ['nid' => $node->id()])->fetchField(); return ['rating' => \Drupal::translation()->formatPlural($rating, '1 point', '@count points')]; } @@ -400,7 +400,7 @@ function hook_node_search_result(\Drupal\node\NodeInterface $node) { */ function hook_node_update_index(\Drupal\node\NodeInterface $node) { $text = ''; - $ratings = \Drupal::database()->query('SELECT title, description FROM {my_ratings} WHERE nid = :nid', [':nid' => $node->id()]); + $ratings = \Drupal::database()->query('SELECT [title], [description] FROM {my_ratings} WHERE [nid] = :nid', [':nid' => $node->id()]); foreach ($ratings as $rating) { $text .= '