<?php
// Exit if accessed directly
if (!defined('ABSPATH')) exit;

class wpForoPostMeta {
	private $default;

	public function __construct(){
		$this->init_defaults();
		$this->init_hooks();
	}

	private function init_hooks(){
		add_action('wpforo_after_add_topic',            array($this, 'after_add_topic'));
		add_action('wpforo_after_edit_topic',           array($this, 'after_edit_topic'), 10, 2);
		add_action('wpforo_after_add_post',             array($this, 'after_add_post'));
		add_action('wpforo_after_edit_post',            array($this, 'after_edit_post'), 10, 2);
		add_action('wpforo_after_move_topic',           array($this, 'after_move_topic'), 10, 2);
		add_action('wpforo_after_merge_topic',          array($this, 'after_merge_topic'), 10, 3);
		add_action('wpforo_after_delete_post',          array($this, 'after_delete_post'));
		add_action('wpforo_post_status_update',         array($this, 'after_post_status_update'), 10, 2);
		add_action('wpforo_topic_private_update',       array($this, 'after_topic_private_update'), 10, 2);
		add_action('wpforo_after_is_first_post_update', array($this, 'after_is_first_post_update'), 10, 2);
	}

	private function init_defaults() {
		$this->default = new stdClass();
		$this->default->postmeta = array(
			'metaid'        => 0,
			'postid'        => 0,
			'metakey'       => '',
			'metavalue'     => '',
			'forumid'       => 0,
			'topicid'       => 0,
			'status'        => 0,
			'private'       => 0,
			'is_first_post' => 0
		);
		$this->default->postmeta_format = array(
			'metaid'        => '%d',
			'postid'        => '%d',
			'metakey'       => '%s',
			'metavalue'     => '%s',
			'forumid'       => '%d',
			'topicid'       => '%d',
			'status'        => '%d',
			'private'       => '%d',
			'is_first_post' => '%d'
		);
		$this->default->sql_select_args = array(
			'include'            => array(),
			'exclude'            => array(),
			'postids_include'    => array(),
			'postids_exclude'    => array(),
			'metakeys_include'   => array(),
			'metakeys_exclude'   => array(),
			'metavalues_include' => array(),
			'metavalues_exclude' => array(),
			'metavalue_like'     => null,
			'metavalue_notlike'  => null,
			'forumids_include'   => array(),
			'forumids_exclude'   => array(),
			'topicids_include'   => array(),
			'topicids_exclude'   => array(),
			'is_first_post'      => null,
			'status'             => null,
			'private'            => null,
			'orderby'            => null,
			'offset'             => null,
			'row_count'          => null
		);
	}

	public function fix_postmeta($postmeta){
		$postmeta = wpforo_array_args_cast_and_merge($postmeta, $this->default->postmeta);
		$postmeta['metavalue'] = wpforo_is_json($postmeta['metavalue']) ? json_decode($postmeta['metavalue'], true) : $postmeta['metavalue'];
		return $postmeta;
	}

	/**
	 * @param array $postmeta
	 *
	 * @return bool|int
	 */
	public function add( $postmeta ) {
		if ( ! wpfval($postmeta, 'postid') || ! wpfval($postmeta, 'metakey')) return false;

		if( !wpfkey($postmeta, 'topicid')
		    || !wpfkey($postmeta, 'forumid')
		    || !wpfkey($postmeta, 'status')
		    || !wpfkey($postmeta, 'private')
			|| !wpfkey($postmeta, 'is_first_post')
		){
			if ( ! $post = WPF()->post->get_post($postmeta['postid'], false) ) return false;
			$postmeta['topicid']       = wpforo_bigintval(wpfval($post, 'topicid'));
			$postmeta['forumid']       = intval(wpfval($post, 'forumid'));
			$postmeta['status']        = intval(wpfval($post, 'status'));
			$postmeta['private']       = intval(wpfval($post, 'private'));
			$postmeta['is_first_post'] = intval(wpfval($post, 'is_first_post'));
		}

		$postmeta = wpforo_array_args_cast_and_merge( (array) $postmeta, $this->default->postmeta );
		unset( $postmeta['metaid'] );

		if( is_null($postmeta['metavalue']) ) $postmeta['metavalue'] = '';
		$postmeta['metavalue'] = wp_unslash($postmeta['metavalue']);
		if( !is_scalar($postmeta['metavalue']) ) $postmeta['metavalue'] = json_encode( (array) $postmeta['metavalue'] );

		$postmeta = wpforo_array_ordered_intersect_key( $postmeta, $this->default->postmeta_format );
		if( WPF()->db->insert(
			WPF()->tables->postmeta,
			$postmeta,
			wpforo_array_ordered_intersect_key( $this->default->postmeta_format, $postmeta )
		)){
			return WPF()->db->insert_id;
		}

		return false;
	}

	/**
	 * @param array $postmeta
	 * @param array|int $where
	 *
	 * @return bool
	 */
	public function edit( $postmeta, $where ) {
		if ( empty( $postmeta ) || empty( $where ) ) return false;
		if ( is_numeric( $where ) ) $where = array( 'metaid' => $where );
		$postmeta = (array) $postmeta;
		$where    = (array) $where;

		if( wpfkey($postmeta, 'metavalue') ){
			if( is_null($postmeta['metavalue']) ) $postmeta['metavalue'] = '';
			$postmeta['metavalue'] = wp_unslash($postmeta['metavalue']);
			if( !is_scalar($postmeta['metavalue']) ) $postmeta['metavalue'] = json_encode( (array) $postmeta['metavalue'] );
		}

		$postmeta = wpforo_array_ordered_intersect_key( $postmeta, $this->default->postmeta_format );
		$where    = wpforo_array_ordered_intersect_key( $where,    $this->default->postmeta_format );
		if ( false !== WPF()->db->update(
			WPF()->tables->postmeta,
			$postmeta,
			$where,
			wpforo_array_ordered_intersect_key( $this->default->postmeta_format, $postmeta ),
			wpforo_array_ordered_intersect_key( $this->default->postmeta_format, $where )
		)){
			return true;
		}

		return false;
	}

	/**
	 * @param array|int $where
	 *
	 * @return bool
	 */
	public function delete($where) {
		if ( empty( $where ) ) return false;
		if (is_numeric($where)) $where = array('metaid' => $where);
		$where = (array) $where;

		$where = wpforo_array_ordered_intersect_key($where, $this->default->postmeta_format);
		if (false !== WPF()->db->delete(
			WPF()->tables->postmeta,
			$where,
			wpforo_array_ordered_intersect_key($this->default->postmeta_format, $where)
		)){
			return true;
		}

		return false;
	}

	private function parse_args( $args ) {
		$args                       = wpforo_parse_args( $args, $this->default->sql_select_args );
		$args                       = wpforo_array_ordered_intersect_key( $args, $this->default->sql_select_args );
		$args['include']            = wpforo_parse_args( $args['include'] );
		$args['exclude']            = wpforo_parse_args( $args['exclude'] );
		$args['postids_include']    = wpforo_parse_args( $args['postids_include'] );
		$args['postids_exclude']    = wpforo_parse_args( $args['postids_exclude'] );
		$args['metakeys_include']   = wpforo_parse_args( $args['metakeys_include'] );
		$args['metakeys_exclude']   = wpforo_parse_args( $args['metakeys_exclude'] );
		$args['metavalues_include'] = wpforo_parse_args( $args['metavalues_include'] );
		$args['metavalues_exclude'] = wpforo_parse_args( $args['metavalues_exclude'] );
		$args['forumids_include']   = wpforo_parse_args( $args['forumids_include'] );
		$args['forumids_exclude']   = wpforo_parse_args( $args['forumids_exclude'] );
		$args['topicids_include']   = wpforo_parse_args( $args['topicids_include'] );
		$args['topicids_exclude']   = wpforo_parse_args( $args['topicids_exclude'] );

		return $args;
	}

	private function build_sql_select($args, $select = ''){
		$args = $this->parse_args($args);
		if( !$select ) $select = '*';

		$wheres = array();

		if (!is_null($args['is_first_post']))      $wheres[] = "`is_first_post` = '"    . intval($args['is_first_post']) ."'";
		if (!is_null($args['status']))             $wheres[] = "`status` = '"           . intval($args['status']) ."'";
		if (!is_null($args['private']))            $wheres[] = "`private` = "           . intval($args['private']);

		if (!empty($args['include']))              $wheres[] = "`metaid` IN("           . implode(',', array_map('wpforo_bigintval', $args['include'])) . ")";
		if (!empty($args['exclude']))              $wheres[] = "`metaid` NOT IN("       . implode(',', array_map('wpforo_bigintval', $args['exclude'])) . ")";

		if (!empty($args['postids_include']))      $wheres[] = "`postid` IN("           . implode(',', array_map('wpforo_bigintval', $args['postids_include'])) . ")";
		if (!empty($args['postids_exclude']))      $wheres[] = "`postid` NOT IN("       . implode(',', array_map('wpforo_bigintval', $args['postids_exclude'])) . ")";

		if (!empty($args['metakeys_include']))     $wheres[] = "`metakey` IN('"         . implode("','", array_map('trim', $args['metakeys_include'])) . "')";
		if (!empty($args['metakeys_exclude']))     $wheres[] = "`metakey` NOT IN('"     . implode("','", array_map('trim', $args['metakeys_exclude'])) . "')";

		if (!empty($args['metavalues_include']))   $wheres[] = "`metavalue` IN('"       . implode("','", array_map('trim', $args['metavalues_include'])) . "')";
		if (!empty($args['metavalues_exclude']))   $wheres[] = "`metavalue` NOT IN('"   . implode("','", array_map('trim', $args['metavalues_exclude'])) . "')";

		if (!is_null($args['metavalue_like']))     $wheres[] = "`metavalue` LIKE '"     . esc_sql($args['metavalue_like']) . "'";
		if (!is_null($args['metavalue_notlike']))  $wheres[] = "`metavalue` NOT LIKE '" . esc_sql($args['metavalue_notlike']) . "'";

		if (!empty($args['forumids_include']))     $wheres[] = "`forumid` IN("          . implode(',', array_map('intval', $args['forumids_include'])) . ")";
		if (!empty($args['forumids_exclude']))     $wheres[] = "`forumid` NOT IN("      . implode(',', array_map('intval', $args['forumids_exclude'])) . ")";

		if (!empty($args['topicids_include']))     $wheres[] = "`topicid` IN("          . implode(',', array_map('wpforo_bigintval', $args['topicids_include'])) . ")";
		if (!empty($args['topicids_exclude']))     $wheres[] = "`topicid` NOT IN("      . implode(',', array_map('wpforo_bigintval', $args['topicids_exclude'])) . ")";

		$sql = "SELECT {$select} FROM " . WPF()->tables->postmeta;
		if ($wheres) $sql .= " WHERE " . implode(" AND ", $wheres);
		if ( $args['orderby'] ) $sql .= " ORDER BY " . $args['orderby'];
		if ($args['row_count']) $sql .= " LIMIT " . wpforo_bigintval($args['offset']) . "," . wpforo_bigintval($args['row_count']);

		return $sql;
	}

	/**
	 * @param int $metaid
	 *
	 * @return array|mixed
	 */
	public function get_postmeta_by_id($metaid) {
		if( !$metaid = wpforo_bigintval($metaid) ) return null;

		$key = 'get_postmeta_by_id_' . $metaid;
		if( WPF()->sql_cache->is_exist($key) ) return WPF()->sql_cache->get($key);

		if( $postmeta = (array) WPF()->db->get_row( $this->build_sql_select( array('include' => $metaid) ), ARRAY_A ) ){
			$postmeta = $this->fix_postmeta($postmeta);
		}

		WPF()->sql_cache->set($key, $postmeta);
		return $postmeta;
	}

	/**
	 * @param int $postid
	 * @param string $metakey
	 *
	 * @return bool
	 */
	public function exists($postid, $metakey){
		if( !$metakey || !($postid = wpforo_bigintval($postid)) ) return false;
		$sql = "SELECT EXISTS( 
            SELECT * FROM `" . WPF()->tables->postmeta . "` 
                WHERE `postid` = %d 
                AND `metakey` = %s 
        ) AS is_exists";
		return (bool) WPF()->db->get_var( WPF()->db->prepare($sql, $postid, $metakey) );
	}

	/**
	 * @param array $args
	 * @param string $field
	 *
	 * @return array
	 */
	public function get_postmetas_col($args, $field){
		$args = wpforo_array_ordered_intersect_key( (array) $args, $this->default->sql_select_args );
		if( empty($args) ) return array();

		$key = 'get_postmetas_' . json_encode($args) . '_' . $field;
		if( WPF()->sql_cache->is_exist($key) ) return WPF()->sql_cache->get($key);

		$postmetas = (array) WPF()->db->get_col( $this->build_sql_select($args, "`{$field}`") );

		WPF()->sql_cache->set($key, $postmetas);
		return $postmetas;
	}

	/**
	 * @param array $args
	 *
	 * @return array
	 */
	public function get_postmetas($args){
		$args = wpforo_array_ordered_intersect_key( (array) $args, $this->default->sql_select_args );
		if( empty($args) ) return array();

		$key = 'get_postmetas_' . json_encode($args);
		if( WPF()->sql_cache->is_exist($key) ) return WPF()->sql_cache->get($key);

		if( $postmetas = (array) WPF()->db->get_results( $this->build_sql_select($args), ARRAY_A ) ){
			$postmetas = array_map( array($this, 'fix_postmeta'), $postmetas );
		}

		WPF()->sql_cache->set($key, $postmetas);
		return $postmetas;
	}

	/**
	 * @param int $postid
	 * @param string|array $metakeys
	 * @param bool $single
	 *
	 * @return array|mixed|null
	 */
	public function get_postmeta($postid, $metakeys = '', $single = false){
		if( !$postid = wpforo_bigintval($postid) ) return null;
		$metakeys = array_filter((array) $metakeys);

		$key = 'get_postmeta_' . $postid . '_'. json_encode($metakeys) . '_' . (string) $single;
		if( WPF()->sql_cache->is_exist($key) ) return WPF()->sql_cache->get($key);

		$postmeta = null;

		$args = array(
			'postids_include'  => $postid,
			'metakeys_include' => $metakeys,
			'orderby'          => '`metaid` ASC',
			'row_count'        => $single && $metakeys ? 1 : null
		);
		if( $postmetas = $this->get_postmetas($args) ){
			if( count($metakeys) === 1 ){
				if( $single ){
					$first = current($postmetas);
					$postmeta = $first['metavalue'];
				}else{
					$postmeta = array();
					foreach ($postmetas as $p) $postmeta[] = $p['metavalue'];
				}
			}else{
				$postmeta = array();
				foreach ($postmetas as $p) {
					if( $single ){
						if( !array_key_exists( $p['metakey'], $postmeta ) ) $postmeta[ $p['metakey'] ] = $p['metavalue'];
					}else{
						$postmeta[ $p['metakey'] ][] = $p['metavalue'];
					}
				}
			}
		}

		WPF()->sql_cache->set($key, $postmeta);
		return $postmeta;
	}

	public function search($args){
		$args = array_filter( (array) $args );
		if( !$args ) return array();

		$selects = array();
		foreach ( $args as $key => $value ){
			if( $field = WPF()->post->get_field($key) ){
				$value = (array) $value;
				$wheres = array();
				if( in_array( $field['type'], array('text','textarea','email','search','tel') ) ){
					foreach ( $value as $v ) $wheres[] = "`metavalue` LIKE '%". esc_sql( wp_unslash($v) ) ."%'";
				}elseif( $field['type'] === 'checkbox' || ( $field['type'] === 'select' && wpfval($field, 'isMultiChoice') ) ){
					foreach ( $value as $v ) {
						$v = preg_quote(preg_quote(wp_unslash($v)));
						$wheres[] = "`metavalue` REGEXP '[\\\[,]\"". esc_sql($v) ."\"[,\\\]]'";
					}
				}else{
					foreach ( $value as $v ) $wheres[] = "`metavalue` LIKE '". esc_sql( wp_unslash($v) ) ."'";
				}
				if( $wheres ){
					$selects[] = "SELECT `postid`, `metakey` FROM `". WPF()->tables->postmeta ."` 
					WHERE `metakey` = '". esc_sql($key) ."' AND " . implode(' AND ', $wheres);
				}
			}
		}

		if( $selects ){
			$sql = "SELECT `postid`, COUNT(`postid`) AS pcount FROM
			(". implode(' UNION ', $selects) .") AS pm
			GROUP BY `postid` HAVING pcount = " . count($selects);
			return (array) WPF()->db->get_col($sql);
		}
		return array();
	}

	private function delete_file($postid, $metakey){
		$postid = wpforo_bigintval($postid);
		if( $postid && $metakey ){
			if( $postmeta = $this->get_postmeta( $postid, $metakey ) ){
				foreach ( $postmeta as $file ){
					$mediaid = (int) wpfval( $file, 'mediaid' );
					$fileurl = (string) wpfval($file, 'fileurl');
					$filedir = wpforo_fix_upload_dir($fileurl);
					if( $mediaid ) wp_delete_attachment($mediaid);
					wp_delete_file($filedir);
				}
				$this->delete( array('postid' => $postid, 'metakey' => $metakey) );
			}
		}
	}

	private function add_file( $post ){
		$postid = (int) (wpfval($post, 'first_postid') ? $post['first_postid'] : wpfval($post, 'postid'));

		if( $wpftcf_delete = array_filter( (array) wpfval($_POST, 'wpftcf_delete') ) ){
			foreach ( $wpftcf_delete as $metakey ){
				$this->delete_file($postid, $metakey);
			}
		}

		if( !empty( wpfval($_FILES, 'data', 'type') ) ){
			$fields_list = WPF()->post->get_topic_fields_list();
			$mime_types = wp_get_mime_types();
			$allowed_mime_types = get_allowed_mime_types();
			foreach( $_FILES['data']['type'] as $k => $mime_type ){
				if( in_array($k, $fields_list) ){
					$field = WPF()->post->get_field($k);
					$label = ($field['label'] ? $field['label'] : $field['fieldKey']);

					if( $error = intval( wpfval($_FILES, 'data', 'error', $k) ) ){
						$phpFileUploadErrors = array(
							0 => 'There is no error, the file uploaded with success',
							1 => 'The uploaded file size is too big',
							2 => 'The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form',
							3 => 'The uploaded file was only partially uploaded',
//							4 => 'No file was uploaded',
							6 => 'Missing a temporary folder',
							7 => 'Failed to write file to disk.',
							8 => 'A PHP extension stopped the file upload.',
						);
						if( $n = wpfval( $phpFileUploadErrors, $error ) ) WPF()->notice->add( $n, 'error' );
					}else{
						$name = wpfval($_FILES, 'data', 'name', $k);
						$tmp_name = wpfval($_FILES, 'data', 'tmp_name', $k);
						$ext = pathinfo($name, PATHINFO_EXTENSION);
						$size = intval($field['fileSize']);
						$fileExtensions = array_filter( (array) is_scalar($field['fileExtensions']) ? explode(',', trim($field['fileExtensions'])) : $field['fileExtensions'] );
						if( $fileExtensions ){
							if( in_array( $ext, $fileExtensions ) ){
								$extensions = explode( '|', array_search($mime_type, $mime_types) );
								$e = in_array($ext, $extensions);
							}else{
								$e = false;
							}
						}else{
							$extensions = explode( '|', array_search($mime_type, $allowed_mime_types) );
							$e = in_array($ext, $extensions);
						}

						if( !empty($e) ){
							if ( wpfval($_FILES, 'data', 'size', $k) <= ($size * 1024 * 1024) ) {
								$wp_upload_dir = wp_upload_dir();
								$uplds_dir = $wp_upload_dir['basedir']."/wpforo";
								$attach_dir = $wp_upload_dir['basedir']."/wpforo/default_attachments/" . WPF()->current_userid;
								$attach_url = preg_replace('#^https?\:#is', '', $wp_upload_dir['baseurl'])."/wpforo/default_attachments/" . WPF()->current_userid;
								if(!is_dir($uplds_dir)) wp_mkdir_p($uplds_dir);
								if(!is_dir($attach_dir)) wp_mkdir_p($attach_dir);

								$fnm = pathinfo($name, PATHINFO_FILENAME);
								$fnm = str_replace(' ', '-', $fnm);
								while(strpos($fnm, '--') !== FALSE) $fnm = str_replace('--', '-', $fnm);
								$fnm = preg_replace("/[^-a-zA-Z0-9_]/", "", $fnm);
								$fnm = trim($fnm, "-");
								$fnm_empty = ( $fnm ? FALSE : TRUE );

								$file_name = $fnm . "." . $ext;

								$attach_fname = current_time( 'timestamp', 1 ).( !$fnm_empty ? '-' : '' ) . $file_name;
								$attach_path = $attach_dir . "/" . $attach_fname;

								if( is_dir($attach_dir) && move_uploaded_file($tmp_name, $attach_path) ){
									$this->delete_file($postid, $field['fieldKey']);

									$attach_id = wpforo_insert_to_media_library( $attach_path, $fnm );
									$file = array(
										'fileurl'  => $attach_url . '/' . $attach_fname,
						                'filename' => basename( $name ),
						                'mediaid'  => $attach_id
									);

									$postmeta = array(
										'postid'        => $postid,
										'metakey'       => $field['fieldKey'],
										'metavalue'     => $file,
										'forumid'       => $post['forumid'],
										'topicid'       => $post['topicid'],
										'is_first_post' => 1,
										'status'        => $post['status'],
										'private'       => $post['private']
									);
									$this->add($postmeta);

								}else{
									WPF()->notice->add('Can\'t upload file', 'error');
								}

							}else{
								WPF()->notice->add('%1$s - File is too large. Maximum allowed file size is %2$s MB', 'error', array($label, $size));
							}
						}else{
							WPF()->notice->add('%1$s - File type is not allowed.', 'error', $label);
						}
					}
				}
			}
		}
	}

	public function after_add_topic($topic){
		$this->add_file($topic);

		if( !empty($topic['postmetas']) ){
			$fields_list = WPF()->post->get_topic_fields_list();
			foreach ( $topic['postmetas'] as $metakey => $metavalue ){
				if( in_array( $metakey, $fields_list ) ){
					$postmeta = array(
						'postid'        => $topic['first_postid'],
						'metakey'       => $metakey,
						'metavalue'     => $metavalue,
						'forumid'       => $topic['forumid'],
						'topicid'       => $topic['topicid'],
						'is_first_post' => 1,
						'status'        => $topic['status'],
						'private'       => $topic['private']
					);
					$this->add($postmeta);
				}
			}
		}
	}

	public function after_edit_topic($topic, $args){
		$this->add_file($topic);

		if( !empty($args['postmetas']) ){
			$fields_list = WPF()->post->get_topic_fields_list();
			foreach ( $args['postmetas'] as $metakey => $metavalue ){
				if( in_array( $metakey, $fields_list ) ){
					$postmeta = array(
						'metavalue'     => $metavalue,
						'forumid'       => $topic['forumid'],
						'topicid'       => $topic['topicid'],
						'is_first_post' => 1,
						'status'        => $topic['status'],
						'private'       => $topic['private']
					);
					if( $this->exists($topic['first_postid'], $metakey) ){
						$this->edit( $postmeta, array(
							'postid'  => $topic['first_postid'],
							'metakey' => $metakey
						));
					}else{
						$postmeta['postid']  = $topic['first_postid'];
						$postmeta['metakey'] = $metakey;
						$this->add($postmeta);
					}
				}
			}
		}
	}

	public function after_add_post($post){
		$this->add_file($post);

		if( !empty($post['postmetas']) ){
			$fields_list = WPF()->post->get_post_fields_list();
			foreach ( $post['postmetas'] as $metakey => $metavalue ){
				if( in_array( $metakey, $fields_list ) ){
					$postmeta = array(
						'postid'        => $post['postid'],
						'metakey'       => $metakey,
						'metavalue'     => $metavalue,
						'forumid'       => $post['forumid'],
						'topicid'       => $post['topicid'],
						'is_first_post' => 0,
						'status'        => $post['status'],
						'private'       => $post['private']
					);
					$this->add($postmeta);
				}
			}
		}
	}

	public function after_edit_post($post, $args){
		$this->add_file($post);

		if( !empty($args['postmetas']) ){
			$fields_list = WPF()->post->get_post_fields_list();
			foreach ( $args['postmetas'] as $metakey => $metavalue ){
				if( in_array( $metakey, $fields_list ) ){
					$postmeta = array(
						'metavalue'     => $metavalue,
						'forumid'       => $post['forumid'],
						'topicid'       => $post['topicid'],
						'is_first_post' => 0,
						'status'        => $post['status'],
						'private'       => $post['private']
					);
					if( $this->exists($post['postid'], $metakey) ){
						$this->edit( $postmeta, array(
							'postid'  => $post['postid'],
							'metakey' => $metakey
						));
					}else{
						$postmeta['postid']  = $post['postid'];
						$postmeta['metakey'] = $metakey;
						$this->add($postmeta);
					}
				}
			}
		}
	}

	public function after_move_topic($topic, $forumid){
		$this->edit( array('forumid' => $forumid), array('topicid' => $topic['topicid']) );
	}

	public function after_merge_topic($target, $current, $postids){
		$sql = "UPDATE `" . WPF()->tables->postmeta . "` SET `topicid` = %d, `forumid` = %d, `private` = %d, `is_first_post` = 0 WHERE `topicid` = %d";
		$sql = WPF()->db->prepare($sql, $target['topicid'], $target['forumid'], $target['private'], $current['topicid']);
		if( $postids ) $sql .= " AND `postid` IN(" . implode(',', array_map('wpforo_bigintval', (array) $postids)) . ")";
		WPF()->db->query($sql);
	}

	public function after_delete_post($post){
		$this->delete(array('postid' => $post['postid']));
	}

	public function after_post_status_update($postid, $status){
		$this->edit( array('status' => $status), array('postid' => $postid) );
	}

	public function after_topic_private_update($topicid, $private){
		$this->edit( array('private' => $private), array('topicid' => $topicid) );
	}

	public function after_is_first_post_update($postid, $is_first_post){
		$this->edit( array('is_first_post' => $is_first_post), array('postid' => $postid) );
	}
}