/** * Sets up the fixture, for example, opens a network connection. * This method is called before a test is executed. * * @access protected */ protected function module_setup() { $user = User::get_by_name('posts_test'); if (!$user) { $user = User::create(array('username' => 'posts_test', 'email' => '*****@*****.**', 'password' => md5('q' . rand(0, 65535)))); } $this->user = $user; $post = Post::create(array('title' => 'Test Post', 'content' => 'These tests expect there to be at least one post.', 'user_id' => $user->id, 'status' => Post::status('published'), 'content_type' => Post::type('entry'))); $this->post_id = $post->id; $this->paramarray = array('id' => 'foofoo', 'post_id' => $this->post_id, 'name' => 'test', 'email' => '*****@*****.**', 'url' => 'http://example.org', 'ip' => ip2long('127.0.0.1'), 'content' => 'test content', 'status' => Comment::status('unapproved'), 'date' => DateTime::date_create(), 'type' => Comment::type('comment')); $this->comment = Comment::create($this->paramarray); }
/** * function get * Returns requested comments * @param array An associated array of parameters, or a querystring * @return array An array of Comment objects, one for each query result * * <code> * $comments = comments::get( array ( "author" => "skippy" ) ); * $comments = comments::get( array ( "slug" => "first-post", "status" => "1", "orderby" => "date ASC" ) ); * </code> * **/ public static function get($paramarray = array()) { $params = array(); $fns = array('get_results', 'get_row', 'get_value'); $select = ''; // what to select -- by default, everything foreach (Comment::default_fields() as $field => $value) { $select .= '' == $select ? "{comments}.{$field}" : ", {comments}.{$field}"; } // defaults $orderby = 'date DESC'; $limit = Options::get('pagination'); // Put incoming parameters into the local scope $paramarray = Utils::get_params($paramarray); // Transact on possible multiple sets of where information that is to be OR'ed if (isset($paramarray['where']) && is_array($paramarray['where'])) { $wheresets = $paramarray['where']; } else { $wheresets = array(array()); } $wheres = array(); $joins = array(); if (isset($paramarray['where']) && is_string($paramarray['where'])) { $wheres[] = $paramarray['where']; } else { foreach ($wheresets as $paramset) { // safety mechanism to prevent empty queries $where = array('1=1'); $paramset = array_merge((array) $paramarray, (array) $paramset); if (isset($paramset['id']) && (is_numeric($paramset['id']) || is_array($paramset['id']))) { if (is_numeric($paramset['id'])) { $where[] = "{comments}.id= ?"; $params[] = $paramset['id']; } else { if (is_array($paramset['id']) && !empty($paramset['id'])) { $id_list = implode(',', $paramset['id']); // Clean up the id list - remove all non-numeric or comma information $id_list = preg_replace("/[^0-9,]/", "", $id_list); // You're paranoid, ringmaster! :P $limit = count($paramset['id']); $where[] = '{comments}.id IN (' . addslashes($id_list) . ')'; } } } if (isset($paramset['status']) && FALSE !== $paramset['status']) { if (is_array($paramset['status'])) { $paramset['status'] = array_diff($paramset['status'], array('any')); array_walk($paramset['status'], create_function('&$a,$b', '$a = Comment::status( $a );')); $where[] = "{comments}.status IN (" . Utils::placeholder_string(count($paramset['status'])) . ")"; $params = array_merge($params, $paramset['status']); } else { $where[] = "{comments}.status= ?"; $params[] = Comment::status($paramset['status']); } } if (isset($paramset['type']) && FALSE !== $paramset['type']) { if (is_array($paramset['type'])) { $paramset['type'] = array_diff($paramset['type'], array('any')); array_walk($paramset['type'], create_function('&$a,$b', '$a = Comment::type( $a );')); $where[] = "type IN (" . Utils::placeholder_string(count($paramset['type'])) . ")"; $params = array_merge($params, $paramset['type']); } else { $where[] = "type= ?"; $params[] = Comment::type($paramset['type']); } } if (isset($paramset['name'])) { $where[] = "name= ?"; $params[] = $paramset['name']; } if (isset($paramset['email'])) { $where[] = "email= ?"; $params[] = $paramset['email']; } if (isset($paramset['url'])) { $where[] = "url= ?"; $params[] = $paramset['url']; } if (isset($paramset['post_id'])) { $where[] = "{comments}.post_id= ?"; $params[] = $paramset['post_id']; } if (isset($paramset['ip'])) { $where[] = "ip= ?"; $params[] = $paramset['ip']; } /* do searching */ if (isset($paramset['post_author'])) { $joins['posts'] = ' INNER JOIN {posts} ON {comments}.post_id = {posts}.id'; if (is_array($paramset['post_author'])) { $where[] = "{posts}.user_id IN (" . implode(',', array_fill(0, count($paramset['post_author']), '?')) . ")"; $params = array_merge($params, $paramset['post_author']); } else { $where[] = '{posts}.user_id = ?'; $params[] = (string) $paramset['post_author']; } } if (isset($paramset['criteria'])) { if (isset($paramset['criteria_fields'])) { // Support 'criteria_fields' => 'author,ip' rather than 'criteria_fields' => array( 'author', 'ip' ) if (!is_array($paramset['criteria_fields']) && is_string($paramset['criteria_fields'])) { $paramset['criteria_fields'] = explode(',', $paramset['criteria_fields']); } } else { $paramset['criteria_fields'] = array('content'); } $paramset['criteria_fields'] = array_unique($paramset['criteria_fields']); preg_match_all('/(?<=")([\\p{L}\\p{N}]+[^"]*)(?=")|([\\p{L}\\p{N}]+)/u', $paramset['criteria'], $matches); $where_search = array(); foreach ($matches[0] as $word) { foreach ($paramset['criteria_fields'] as $criteria_field) { $where_search[] .= "({comments}.{$criteria_field} LIKE CONCAT('%',?,'%'))"; $params[] = $word; } } if (count($where_search) > 0) { $where[] = '(' . implode(" \nOR\n ", $where_search) . ')'; } } /* * Build the pubdate * If we've got the day, then get the date. * If we've got the month, but no date, get the month. * If we've only got the year, get the whole year. * @todo Ensure that we've actually got all the needed parts when we query on them * @todo Ensure that the value passed in is valid to insert into a SQL date (ie '04' and not '4') */ if (isset($paramset['day'])) { /* Got the full date */ $where[] = 'date BETWEEN ? AND ?'; $startDate = sprintf('%d-%02d-%02d', $paramset['year'], $paramset['month'], $paramset['day']); $startDate = HabariDateTime::date_create($startDate); $params[] = $startDate->sql; $params[] = $startDate->modify('+1 day')->sql; } elseif (isset($paramset['month'])) { $where[] = 'date BETWEEN ? AND ?'; $startDate = sprintf('%d-%02d-%02d', $paramset['year'], $paramset['month'], 1); $startDate = HabariDateTime::date_create($startDate); $params[] = $startDate->sql; $params[] = $startDate->modify('+1 month')->sql; } elseif (isset($paramset['year'])) { $where[] = 'date BETWEEN ? AND ?'; $startDate = sprintf('%d-%02d-%02d', $paramset['year'], 1, 1); $startDate = HabariDateTime::date_create($startDate); $params[] = $startDate->sql; $params[] = $startDate->modify('+1 year')->sql; } // Concatenate the WHERE clauses if (count($where) > 0) { $wheres[] = ' (' . implode(' AND ', $where) . ') '; } } } // Only show comments to which the current user has permission to read the associated post if (isset($paramset['ignore_permissions'])) { $master_perm_where = ''; } else { // This set of wheres will be used to generate a list of comment_ids that this user can read $perm_where = array(); $perm_where_denied = array(); $params_where = array(); $where = array(); // every condition here will require a join with the posts table $joins['posts'] = 'INNER JOIN {posts} ON {comments}.post_id={posts}.id'; // Get the tokens that this user is granted or denied access to read $read_tokens = isset($paramset['read_tokens']) ? $paramset['read_tokens'] : ACL::user_tokens(User::identify(), 'read', true); $deny_tokens = isset($paramset['deny_tokens']) ? $paramset['deny_tokens'] : ACL::user_tokens(User::identify(), 'deny', true); // If a user can read his own posts, let him if (User::identify()->can('own_posts', 'read')) { $perm_where['own_posts_id'] = '{posts}.user_id = ?'; $params_where[] = User::identify()->id; } // If a user can read any post type, let him if (User::identify()->can('post_any', 'read')) { $perm_where = array('post_any' => '(1=1)'); $params_where = array(); } else { // If a user can read specific post types, let him $permitted_post_types = array(); foreach (Post::list_active_post_types() as $name => $posttype) { if (User::identify()->can('post_' . Utils::slugify($name), 'read')) { $permitted_post_types[] = $posttype; } } if (count($permitted_post_types) > 0) { $perm_where[] = '{posts}.content_type IN (' . implode(',', $permitted_post_types) . ')'; } // If a user can read posts with specific tokens, let him see comments on those posts if (count($read_tokens) > 0) { $joins['post_tokens__allowed'] = ' LEFT JOIN {post_tokens} pt_allowed ON {posts}.id= pt_allowed.post_id AND pt_allowed.token_id IN (' . implode(',', $read_tokens) . ')'; $perm_where['perms_join_null'] = 'pt_allowed.post_id IS NOT NULL'; } } // If a user is denied access to all posts, do so if (User::identify()->cannot('post_any')) { $perm_where_denied = array('(0=1)'); } else { // If a user is denied read access to specific post types, deny him $denied_post_types = array(); foreach (Post::list_active_post_types() as $name => $posttype) { if (User::identify()->cannot('post_' . Utils::slugify($name))) { $denied_post_types[] = $posttype; } } if (count($denied_post_types) > 0) { $perm_where_denied[] = '{posts}.content_type NOT IN (' . implode(',', $denied_post_types) . ')'; } } // If there are granted permissions to check, add them to the where clause if (count($perm_where) == 0 && !isset($joins['post_tokens__allowed'])) { // You have no grants. You get no comments. $where['perms_granted'] = '(0=1)'; } elseif (count($perm_where) > 0) { $where['perms_granted'] = ' (' . implode(' OR ', $perm_where) . ') '; $params = array_merge($params, $params_where); } if (count($deny_tokens) > 0) { $joins['post_tokens__denied'] = ' LEFT JOIN {post_tokens} pt_denied ON {posts}.id= pt_denied.post_id AND pt_denied.token_id IN (' . implode(',', $deny_tokens) . ')'; $perm_where_denied['perms_join_null'] = 'pt_denied.post_id IS NULL'; } // If there are denied permissions to check, add them to the where clause if (count($perm_where_denied) > 0) { $where['perms_denied'] = ' (' . implode(' AND ', $perm_where_denied) . ') '; } $master_perm_where = implode(' AND ', $where); } // Get any full-query parameters $possible = array('page', 'fetch_fn', 'count', 'month_cts', 'nolimit', 'limit', 'offset', 'orderby'); foreach ($possible as $varname) { if (isset($paramarray[$varname])) { ${$varname} = $paramarray[$varname]; } } if (isset($page) && is_numeric($page)) { $offset = (intval($page) - 1) * intval($limit); } if (isset($fetch_fn)) { if (!in_array($fetch_fn, $fns)) { $fetch_fn = $fns[0]; } } else { $fetch_fn = $fns[0]; } // is a count being request? if (isset($count)) { $select = "COUNT( 1 )"; $fetch_fn = 'get_value'; $orderby = ''; } // is a count of comments by month being requested? $groupby = ''; if (isset($month_cts)) { $select = 'MONTH(FROM_UNIXTIME(date)) AS month, YEAR(FROM_UNIXTIME(date)) AS year, COUNT({comments}.id) AS ct'; $groupby = 'year, month'; $orderby = 'year, month'; } if (isset($limit)) { $limit = " LIMIT {$limit}"; if (isset($offset)) { $limit .= " OFFSET {$offset}"; } } if (isset($nolimit) || isset($month_cts)) { $limit = ''; } // Build the final SQL statement $query = ' SELECT DISTINCT ' . $select . ' FROM {comments} ' . implode(' ', $joins); if (count($wheres) > 0) { $query .= ' WHERE (' . implode(" \nOR\n ", $wheres) . ')'; $query .= $master_perm_where == '' ? '' : ' AND (' . $master_perm_where . ')'; } elseif ($master_perm_where != '') { $query .= ' WHERE (' . $master_perm_where . ')'; } $query .= $groupby == '' ? '' : ' GROUP BY ' . $groupby; $query .= ($orderby == '' ? '' : ' ORDER BY ' . $orderby) . $limit; //Utils::debug( $query, $params ); DB::set_fetch_mode(PDO::FETCH_CLASS); DB::set_fetch_class('Comment'); $results = DB::$fetch_fn($query, $params, 'Comment'); if ('get_results' != $fetch_fn) { // return the results return $results; } elseif (is_array($results)) { $c = __CLASS__; $return_value = new $c($results); $return_value->get_param_cache = $paramarray; return $return_value; } }
/** * Remove a comment type from the database * @param integer|string $type The type of the comment * @param bool $delete If true, delete the type and all comments of that type instead of deactivating it */ public static function remove_type($type, $delete = false) { if ($delete) { // Delete comments of this type, delete type $type_id = Comment::type($type); DB::delete(DB::table('comments'), array('type' => $type_id)); DB::exec('DELETE FROM {commentinfo} WHERE comment_id IN (SELECT {commentinfo}.comment_id FROM {commentinfo} LEFT JOIN {comments} ON {commentinfo}.comment_id = {comments}.id WHERE {comments}.id IS NULL)'); DB::delete(DB::table('commenttype'), array('name' => Comment::type_name($type))); } else { DB::update(DB::table('commenttype'), array('name' => Comment::type_name($type), 'active' => 0), array('name')); } }
public function action_auth_ajax_wp_import_comments() { // get the values post'd in $inputs = $_POST->filter_keys(array('db_name', 'db_host', 'db_user', 'db_pass', 'db_prefix', 'category_import', 'import_index')); $inputs = $inputs->getArrayCopy(); // make sure we have all our default values $inputs = array_merge($this->default_values, $inputs); // get the wpdb $wpdb = $this->wp_connect($inputs['db_host'], $inputs['db_name'], $inputs['db_user'], $inputs['db_pass']); // if we couldn't connect, error out if (!$wpdb) { EventLog::log(_t('Failed to import from "%s"', array($inputs['db_name']))); Session::error(_t('Failed to import from "%s"', array($inputs['db_name']))); echo '<p>' . _t('Failed to connect using the given database connection details.') . '</p>'; } // we connected just fine, let's get moving! // begin a transaction. if we error out at any point, we want to roll back to before import began DB::begin_transaction(); // fetch the number of comments from the wordpress database so we can batch things up $num_comments = $wpdb->get_value('select count(comment_id) from ' . $inputs['db_prefix'] . 'comments'); // figure out the LIMIT we're at $min = $inputs['import_index'] * IMPORT_BATCH; $max = min($min + IMPORT_BATCH, $num_comments); // for display only echo '<p>' . _t('Importing comments %1$d - %2$d of %3$d.', array($min, $max, $num_comments)) . '</p>'; // get all the imported users so we can link old comment authors to new comment authors $users = DB::get_results('select user_id, value from {userinfo} where name = :name', array(':name' => 'wp_id')); // create an easy user map of old ID -> new ID $user_map = array(); foreach ($users as $info) { $user_map[$info->value] = $info->user_id; } // get all the imported posts so we can link old post IDs to new post IDs $posts = DB::get_results('select post_id, value from {postinfo} where name = :name', array(':name' => 'wp_id')); // create an easy post map of old ID -> new ID $post_map = array(); foreach ($posts as $info) { $post_map[$info->value] = $info->post_id; } // get all the comment IDs we've imported so far to make sure we don't duplicate any $comment_map = DB::get_column('select value from {commentinfo} where name = :name', array(':name' => 'wp_id')); // now we're ready to start importing comments $comments = $wpdb->get_results('select comment_id, comment_post_id, comment_author, comment_author_email, comment_author_url, comment_author_ip, comment_date, comment_content, comment_karma, comment_approved, comment_agent, comment_type, comment_parent, user_id from ' . $inputs['db_prefix'] . 'comments order by comment_id asc limit ' . $min . ', ' . IMPORT_BATCH); foreach ($comments as $comment) { // if this post is already in the list we've imported, skip it if (in_array($comment->id, $comment_map)) { continue; } // if the post this comment belongs to is not in the list of imported posts, skip it if (!isset($post_map[$comment->comment_post_id])) { continue; } // create the new comment $c = new Comment(array('content' => MultiByte::convert_encoding($comment->comment_content), 'name' => MultiByte::convert_encoding($comment->comment_author), 'email' => MultiByte::convert_encoding($comment->comment_author_email), 'url' => MultiByte::convert_encoding($comment->comment_author_url), 'date' => HabariDateTime::date_create($comment->comment_date), 'post_id' => $post_map[$comment->comment_post_id])); // figure out the comment type switch ($comment->comment_type) { case 'pingback': $c->type = Comment::type('pingback'); break; case 'trackback': $c->type = Comment::type('trackback'); break; default: case 'comment': $c->type = Comment::type('comment'); break; } // figure out the comment status switch ($comment->comment_approved) { case '1': $c->status = Comment::status('approved'); break; case '': case '0': $c->status = Comment::status('unapproved'); break; case 'spam': $c->status = Comment::status('spam'); break; default: // Comment::status() returns false if it doesn't recognize the status type $status = Comment::status($comment->comment_status); // store in a temp value because if you try and set ->status to an invalid value the Comment class freaks if ($status == false) { // we're not importing statuses we don't recognize - continue 2 to break out of the switch and the loop and continue to the next comment continue 2; } else { $c->status = $status; } break; } // save the old comment ID in info $c->info->wp_id = $comment->comment_id; // save the old post ID in info $c->info->wp_post_id = $comment->comment_post_id; // save the old comment karma - but only if it is something if ($comment->comment_karma != '0') { $c->info->wp_karma = $comment->comment_karma; } // save the old comment user agent - but only if it is something if ($comment->comment_agent != '') { $c->info->wp_agent = $comment->comment_agent; } // now that we've got all the pieces in place, save the comment try { $c->insert(); } catch (Exception $e) { EventLog::log($e->getMessage(), 'err'); echo '<p class="error">' . _t('There was an error importing comment ID %d. See the EventLog for the error message.', array($comment->comment_id)); echo '<p>' . _t('Rolling back changes…') . '</p>'; // rollback all changes before we return so the import hasn't changed anything yet DB::rollback(); // and return so they don't get AJAX to send them on to the next step return false; } } // if we've finished without an error, commit the import DB::commit(); if ($max < $num_comments) { // if there are more posts to import // get the next ajax url $ajax_url = URL::get('auth_ajax', array('context' => 'wp_import_comments')); // bump the import index by one so we get a new batch next time $inputs['import_index']++; } else { // display the completed message! EventLog::log(_t('Import completed from "%s"', array($inputs['db_name']))); echo '<p>' . _t('Import is complete.') . '</p>'; return; } // and spit out ajax to send them to the next step - posts! echo $this->get_ajax($ajax_url, $inputs); }
public function upgrade_db_post_5112() { $this->create_base_comment_types(); // Throw the existing values out far to avoid collisions DB::query('UPDATE {comments} SET status = status + 30, type = type + 30'); // Update statuses $updates = array('unapproved' => 0, 'approved' => 1, 'spam' => 2, 'deleted' => 3); foreach ($updates as $name => $oldvalue) { DB::query('UPDATE {comments} SET status = :newstatus WHERE status = :oldstatus', array('newstatus' => Comment::status($name), 'oldstatus' => 30 + $oldvalue)); } // Update types $updates = array('comment' => 0, 'pingback' => 1, 'trackback' => 2); foreach ($updates as $name => $oldvalue) { DB::query('UPDATE {comments} SET type = :newtype WHERE type = :oldtype', array('newtype' => Comment::type($name), 'oldtype' => 30 + $oldvalue)); } }
private function make_comment($post, $time) { $comment = Comment::create(array('post_id' => $post->id, 'name' => $this->get_comment_name(), 'url' => 'http://example.com', 'content' => $this->get_comment_content(), 'status' => $this->get_comment_status(), 'type' => Comment::type('comment'), 'date' => DateTime::date_create($time))); $comment->info->lipsum = true; $comment->info->commit(); }
/** * Add a comment to the site * * @param mixed $post A Post object instance or Post object id * @param string $name The commenter's name * @param string $email The commenter's email address * @param string $url The commenter's website URL * @param string $content The comment content * @param array $extra An associative array of extra values that should be considered */ function add_comment($post, $name = null, $email = null, $url = null, $content = null, $extra = null) { if (is_numeric($post)) { $post = Post::get(array('id' => $post)); } if (!$post instanceof Post) { // Not sure what you're trying to pull here, but that's no good header('HTTP/1.1 403 Forbidden', true, 403); die; } /* Sanitize data */ foreach (array('name', 'url', 'email', 'content') as $k) { ${$k} = InputFilter::filter(${$k}); } // there should never be any HTML in the name, so do some extra filtering on it $name = strip_tags(html_entity_decode($name, ENT_QUOTES, 'UTF-8')); /* Sanitize the URL */ if (!empty($url)) { $parsed = InputFilter::parse_url($url); if ($parsed['is_relative']) { // guess if they meant to use an absolute link $parsed = InputFilter::parse_url('http://' . $url); if (!$parsed['is_error']) { $url = InputFilter::glue_url($parsed); } else { // disallow relative URLs $url = ''; } } if ($parsed['is_pseudo'] || $parsed['scheme'] !== 'http' && $parsed['scheme'] !== 'https') { // allow only http(s) URLs $url = ''; } else { // reconstruct the URL from the error-tolerant parsing // http:moeffju.net/blog/ -> http://moeffju.net/blog/ $url = InputFilter::glue_url($parsed); } } /* Create comment object*/ $comment = new Comment(array('post_id' => $post->id, 'name' => $name, 'email' => $email, 'url' => $url, 'ip' => Utils::get_ip(), 'content' => $content, 'status' => Comment::status('approved'), 'date' => DateTime::create(), 'type' => Comment::type('comment'))); // Should this really be here or in a default filter? // In any case, we should let plugins modify the status after we set it here. $user = User::identify(); if ($user->loggedin && $comment->email == $user->email) { $comment->status = 'approved'; } // Allow themes to work with comment hooks Themes::create(); // Allow plugins to change comment data and add commentinfo based on plugin-added form fields Plugins::act('comment_accepted', $comment, $this->handler_vars, $extra); $spam_rating = 0; $spam_rating = Plugins::filter('spam_filter', $spam_rating, $comment, $this->handler_vars, $extra); if ($spam_rating >= Options::get('spam_percentage', 100)) { $comment->status = 'spam'; } $comment->insert(); $anchor = ''; // If the comment was saved if ($comment->id && $comment->status != 'spam') { $anchor = '#comment-' . $comment->id; // store in the user's session that this comment is pending moderation if ($comment->status == 'unapproved') { Session::notice(_t('Your comment is pending moderation.'), 'comment_' . $comment->id); } // if no cookie exists, we should set one // but only if the user provided some details $cookie_name = 'comment_' . Options::get('public-GUID'); // build the string we store for the cookie $cookie_content = implode('#', array($comment->name, $comment->email, $comment->url)); // if the user is not logged in and there is no cookie OR the cookie differs from the current set if (User::identify()->loggedin == false && (!isset($_COOKIE[$cookie_name]) || $_COOKIE[$cookie_name] != $cookie_content)) { // update the cookie setcookie($cookie_name, $cookie_content, time() + DateTime::YEAR, Site::get_path('base', true)); } } // Return the commenter to the original page. Utils::redirect($post->permalink . $anchor); }