| 1 |
<?php |
| 2 |
|
| 3 |
namespace wpforo\classes; |
| 4 |
|
| 5 |
use stdClass; |
| 6 |
|
| 7 |
// Exit if accessed directly |
| 8 |
if( ! defined( 'ABSPATH' ) ) exit; |
| 9 |
|
| 10 |
class PostMeta { |
| 11 |
private $default; |
| 12 |
|
| 13 |
public function __construct() { |
| 14 |
$this->init_defaults(); |
| 15 |
$this->init_hooks(); |
| 16 |
} |
| 17 |
|
| 18 |
private function init_hooks() { |
| 19 |
add_action( 'wpforo_after_add_topic', [ $this, 'after_add_topic' ], 10, 2 ); |
| 20 |
add_action( 'wpforo_after_edit_topic', [ $this, 'after_edit_topic' ], 10, 3 ); |
| 21 |
add_action( 'wpforo_after_add_post', [ $this, 'after_add_post' ], 10, 3 ); |
| 22 |
add_action( 'wpforo_after_edit_post', [ $this, 'after_edit_post' ], 10, 4 ); |
| 23 |
add_action( 'wpforo_after_move_topic', [ $this, 'after_move_topic' ], 10, 2 ); |
| 24 |
add_action( 'wpforo_after_merge_topic', [ $this, 'after_merge_topic' ], 10, 3 ); |
| 25 |
add_action( 'wpforo_after_delete_post', [ $this, 'after_delete_post' ] ); |
| 26 |
add_action( 'wpforo_post_status_update', [ $this, 'after_post_status_update' ], 10, 2 ); |
| 27 |
add_action( 'wpforo_topic_private_update', [ $this, 'after_topic_private_update' ], 10, 2 ); |
| 28 |
add_action( 'wpforo_after_is_first_post_update', [ $this, 'after_is_first_post_update' ], 10, 2 ); |
| 29 |
} |
| 30 |
|
| 31 |
private function init_defaults() { |
| 32 |
$this->default = new stdClass(); |
| 33 |
$this->default->postmeta = [ |
| 34 |
'metaid' => 0, |
| 35 |
'postid' => 0, |
| 36 |
'metakey' => '', |
| 37 |
'metavalue' => '', |
| 38 |
'forumid' => 0, |
| 39 |
'topicid' => 0, |
| 40 |
'status' => 0, |
| 41 |
'private' => 0, |
| 42 |
'is_first_post' => 0, |
| 43 |
]; |
| 44 |
$this->default->postmeta_format = [ |
| 45 |
'metaid' => '%d', |
| 46 |
'postid' => '%d', |
| 47 |
'metakey' => '%s', |
| 48 |
'metavalue' => '%s', |
| 49 |
'forumid' => '%d', |
| 50 |
'topicid' => '%d', |
| 51 |
'status' => '%d', |
| 52 |
'private' => '%d', |
| 53 |
'is_first_post' => '%d', |
| 54 |
]; |
| 55 |
$this->default->sql_select_args = [ |
| 56 |
'include' => [], |
| 57 |
'exclude' => [], |
| 58 |
'postids_include' => [], |
| 59 |
'postids_exclude' => [], |
| 60 |
'metakeys_include' => [], |
| 61 |
'metakeys_exclude' => [], |
| 62 |
'metavalues_include' => [], |
| 63 |
'metavalues_exclude' => [], |
| 64 |
'metavalue_like' => null, |
| 65 |
'metavalue_notlike' => null, |
| 66 |
'forumids_include' => [], |
| 67 |
'forumids_exclude' => [], |
| 68 |
'topicids_include' => [], |
| 69 |
'topicids_exclude' => [], |
| 70 |
'is_first_post' => null, |
| 71 |
'status' => null, |
| 72 |
'private' => null, |
| 73 |
'orderby' => null, |
| 74 |
'offset' => null, |
| 75 |
'row_count' => null, |
| 76 |
]; |
| 77 |
} |
| 78 |
|
| 79 |
public function fix_postmeta( $postmeta ) { |
| 80 |
$postmeta = wpforo_array_args_cast_and_merge( $postmeta, $this->default->postmeta ); |
| 81 |
$postmeta['metavalue'] = wpforo_is_json( $postmeta['metavalue'] ) ? json_decode( $postmeta['metavalue'], true ) : $postmeta['metavalue']; |
| 82 |
|
| 83 |
return $postmeta; |
| 84 |
} |
| 85 |
|
| 86 |
/** |
| 87 |
* @param array $postmeta |
| 88 |
* |
| 89 |
* @return bool|int |
| 90 |
*/ |
| 91 |
public function add( $postmeta ) { |
| 92 |
if( ! wpfval( $postmeta, 'postid' ) || ! wpfval( $postmeta, 'metakey' ) ) return false; |
| 93 |
|
| 94 |
if( ! wpfkey( $postmeta, 'topicid' ) || ! wpfkey( $postmeta, 'forumid' ) || ! wpfkey( $postmeta, 'status' ) || ! wpfkey( $postmeta, 'private' ) || ! wpfkey( $postmeta, 'is_first_post' ) ) { |
| 95 |
if( ! $post = WPF()->post->get_post( $postmeta['postid'], false ) ) return false; |
| 96 |
$postmeta['topicid'] = wpforo_bigintval( wpfval( $post, 'topicid' ) ); |
| 97 |
$postmeta['forumid'] = intval( wpfval( $post, 'forumid' ) ); |
| 98 |
$postmeta['status'] = intval( wpfval( $post, 'status' ) ); |
| 99 |
$postmeta['private'] = intval( wpfval( $post, 'private' ) ); |
| 100 |
$postmeta['is_first_post'] = intval( wpfval( $post, 'is_first_post' ) ); |
| 101 |
} |
| 102 |
|
| 103 |
$postmeta = wpforo_array_args_cast_and_merge( (array) $postmeta, $this->default->postmeta ); |
| 104 |
unset( $postmeta['metaid'] ); |
| 105 |
|
| 106 |
if( is_null( $postmeta['metavalue'] ) ) $postmeta['metavalue'] = ''; |
| 107 |
$postmeta['metavalue'] = wp_unslash( $postmeta['metavalue'] ); |
| 108 |
if( ! is_scalar( $postmeta['metavalue'] ) ) $postmeta['metavalue'] = json_encode( (array) $postmeta['metavalue'] ); |
| 109 |
|
| 110 |
$postmeta = wpforo_array_ordered_intersect_key( $postmeta, $this->default->postmeta_format ); |
| 111 |
if( WPF()->db->insert( |
| 112 |
WPF()->tables->postmeta, |
| 113 |
$postmeta, |
| 114 |
wpforo_array_ordered_intersect_key( $this->default->postmeta_format, $postmeta ) |
| 115 |
) ) { |
| 116 |
$metaid = WPF()->db->insert_id; |
| 117 |
do_action( 'wpforo_after_add_postmeta', $postmeta, $metaid ); |
| 118 |
return $metaid; |
| 119 |
} |
| 120 |
|
| 121 |
return false; |
| 122 |
} |
| 123 |
|
| 124 |
/** |
| 125 |
* @param array $postmeta |
| 126 |
* @param array|int $where |
| 127 |
* |
| 128 |
* @return bool |
| 129 |
*/ |
| 130 |
public function edit( $postmeta, $where ) { |
| 131 |
if( empty( $postmeta ) || empty( $where ) ) return false; |
| 132 |
if( is_numeric( $where ) ) $where = [ 'metaid' => $where ]; |
| 133 |
$postmeta = (array) $postmeta; |
| 134 |
$where = (array) $where; |
| 135 |
|
| 136 |
if( wpfkey( $postmeta, 'metavalue' ) ) { |
| 137 |
if( is_null( $postmeta['metavalue'] ) ) $postmeta['metavalue'] = ''; |
| 138 |
$postmeta['metavalue'] = wp_unslash( $postmeta['metavalue'] ); |
| 139 |
if( ! is_scalar( $postmeta['metavalue'] ) ) $postmeta['metavalue'] = json_encode( (array) $postmeta['metavalue'] ); |
| 140 |
} |
| 141 |
|
| 142 |
$postmeta = wpforo_array_ordered_intersect_key( $postmeta, $this->default->postmeta_format ); |
| 143 |
$where = wpforo_array_ordered_intersect_key( $where, $this->default->postmeta_format ); |
| 144 |
if( false !== WPF()->db->update( |
| 145 |
WPF()->tables->postmeta, |
| 146 |
$postmeta, |
| 147 |
$where, |
| 148 |
wpforo_array_ordered_intersect_key( $this->default->postmeta_format, $postmeta ), |
| 149 |
wpforo_array_ordered_intersect_key( $this->default->postmeta_format, $where ) |
| 150 |
) ) { |
| 151 |
do_action( 'wpforo_after_edit_postmeta', $postmeta, $where ); |
| 152 |
return true; |
| 153 |
} |
| 154 |
|
| 155 |
return false; |
| 156 |
} |
| 157 |
|
| 158 |
/** |
| 159 |
* @param array|int $where |
| 160 |
* |
| 161 |
* @return bool |
| 162 |
*/ |
| 163 |
public function delete( $where ) { |
| 164 |
if( empty( $where ) ) return false; |
| 165 |
if( is_numeric( $where ) ) $where = [ 'metaid' => $where ]; |
| 166 |
$where = (array) $where; |
| 167 |
|
| 168 |
$where = wpforo_array_ordered_intersect_key( $where, $this->default->postmeta_format ); |
| 169 |
if( false !== WPF()->db->delete( |
| 170 |
WPF()->tables->postmeta, |
| 171 |
$where, |
| 172 |
wpforo_array_ordered_intersect_key( $this->default->postmeta_format, $where ) |
| 173 |
) ) { |
| 174 |
do_action( 'wpforo_after_delete_postmeta', $where ); |
| 175 |
return true; |
| 176 |
} |
| 177 |
|
| 178 |
return false; |
| 179 |
} |
| 180 |
|
| 181 |
private function parse_args( $args ) { |
| 182 |
$args = wpforo_parse_args( $args, $this->default->sql_select_args ); |
| 183 |
$args = wpforo_array_ordered_intersect_key( $args, $this->default->sql_select_args ); |
| 184 |
$args['include'] = wpforo_parse_args( $args['include'] ); |
| 185 |
$args['exclude'] = wpforo_parse_args( $args['exclude'] ); |
| 186 |
$args['postids_include'] = wpforo_parse_args( $args['postids_include'] ); |
| 187 |
$args['postids_exclude'] = wpforo_parse_args( $args['postids_exclude'] ); |
| 188 |
$args['metakeys_include'] = wpforo_parse_args( $args['metakeys_include'] ); |
| 189 |
$args['metakeys_exclude'] = wpforo_parse_args( $args['metakeys_exclude'] ); |
| 190 |
$args['metavalues_include'] = wpforo_parse_args( $args['metavalues_include'] ); |
| 191 |
$args['metavalues_exclude'] = wpforo_parse_args( $args['metavalues_exclude'] ); |
| 192 |
$args['forumids_include'] = wpforo_parse_args( $args['forumids_include'] ); |
| 193 |
$args['forumids_exclude'] = wpforo_parse_args( $args['forumids_exclude'] ); |
| 194 |
$args['topicids_include'] = wpforo_parse_args( $args['topicids_include'] ); |
| 195 |
$args['topicids_exclude'] = wpforo_parse_args( $args['topicids_exclude'] ); |
| 196 |
|
| 197 |
return $args; |
| 198 |
} |
| 199 |
|
| 200 |
private function build_sql_select( $args, $select = '' ) { |
| 201 |
$args = $this->parse_args( $args ); |
| 202 |
if( ! $select ) $select = '*'; |
| 203 |
|
| 204 |
$wheres = []; |
| 205 |
|
| 206 |
if( ! is_null( $args['is_first_post'] ) ) $wheres[] = "`is_first_post` = '" . intval( $args['is_first_post'] ) . "'"; |
| 207 |
if( ! is_null( $args['status'] ) ) $wheres[] = "`status` = '" . intval( $args['status'] ) . "'"; |
| 208 |
if( ! is_null( $args['private'] ) ) $wheres[] = "`private` = " . intval( $args['private'] ); |
| 209 |
|
| 210 |
if( ! empty( $args['include'] ) ) $wheres[] = "`metaid` IN(" . implode( ',', array_map( 'wpforo_bigintval', $args['include'] ) ) . ")"; |
| 211 |
if( ! empty( $args['exclude'] ) ) $wheres[] = "`metaid` NOT IN(" . implode( ',', array_map( 'wpforo_bigintval', $args['exclude'] ) ) . ")"; |
| 212 |
|
| 213 |
if( ! empty( $args['postids_include'] ) ) $wheres[] = "`postid` IN(" . implode( ',', array_map( 'wpforo_bigintval', $args['postids_include'] ) ) . ")"; |
| 214 |
if( ! empty( $args['postids_exclude'] ) ) $wheres[] = "`postid` NOT IN(" . implode( ',', array_map( 'wpforo_bigintval', $args['postids_exclude'] ) ) . ")"; |
| 215 |
|
| 216 |
if( ! empty( $args['metakeys_include'] ) ) $wheres[] = "`metakey` IN('" . implode( "','", array_map( 'trim', $args['metakeys_include'] ) ) . "')"; |
| 217 |
if( ! empty( $args['metakeys_exclude'] ) ) $wheres[] = "`metakey` NOT IN('" . implode( "','", array_map( 'trim', $args['metakeys_exclude'] ) ) . "')"; |
| 218 |
|
| 219 |
if( ! empty( $args['metavalues_include'] ) ) $wheres[] = "`metavalue` IN('" . implode( "','", array_map( 'trim', $args['metavalues_include'] ) ) . "')"; |
| 220 |
if( ! empty( $args['metavalues_exclude'] ) ) $wheres[] = "`metavalue` NOT IN('" . implode( "','", array_map( 'trim', $args['metavalues_exclude'] ) ) . "')"; |
| 221 |
|
| 222 |
if( ! is_null( $args['metavalue_like'] ) ) $wheres[] = "`metavalue` LIKE '" . esc_sql( $args['metavalue_like'] ) . "'"; |
| 223 |
if( ! is_null( $args['metavalue_notlike'] ) ) $wheres[] = "`metavalue` NOT LIKE '" . esc_sql( $args['metavalue_notlike'] ) . "'"; |
| 224 |
|
| 225 |
if( ! empty( $args['forumids_include'] ) ) $wheres[] = "`forumid` IN(" . implode( ',', array_map( 'intval', $args['forumids_include'] ) ) . ")"; |
| 226 |
if( ! empty( $args['forumids_exclude'] ) ) $wheres[] = "`forumid` NOT IN(" . implode( ',', array_map( 'intval', $args['forumids_exclude'] ) ) . ")"; |
| 227 |
|
| 228 |
if( ! empty( $args['topicids_include'] ) ) $wheres[] = "`topicid` IN(" . implode( ',', array_map( 'wpforo_bigintval', $args['topicids_include'] ) ) . ")"; |
| 229 |
if( ! empty( $args['topicids_exclude'] ) ) $wheres[] = "`topicid` NOT IN(" . implode( ',', array_map( 'wpforo_bigintval', $args['topicids_exclude'] ) ) . ")"; |
| 230 |
|
| 231 |
$sql = "SELECT $select FROM " . WPF()->tables->postmeta; |
| 232 |
if( $wheres ) $sql .= " WHERE " . implode( " AND ", $wheres ); |
| 233 |
if( $args['orderby'] ) $sql .= " ORDER BY " . $args['orderby']; |
| 234 |
if( $args['row_count'] ) $sql .= " LIMIT " . wpforo_bigintval( $args['offset'] ) . "," . wpforo_bigintval( $args['row_count'] ); |
| 235 |
|
| 236 |
return $sql; |
| 237 |
} |
| 238 |
|
| 239 |
/** |
| 240 |
* @param int $metaid |
| 241 |
* |
| 242 |
* @return array|mixed |
| 243 |
*/ |
| 244 |
public function get_postmeta_by_id( $metaid ) { |
| 245 |
if( ! $metaid = wpforo_bigintval( $metaid ) ) return null; |
| 246 |
|
| 247 |
$key = 'get_postmeta_by_id_' . $metaid; |
| 248 |
if( WPF()->ram_cache->exists( $key ) ) return WPF()->ram_cache->get( $key ); |
| 249 |
|
| 250 |
if( $postmeta = (array) WPF()->db->get_row( $this->build_sql_select( [ 'include' => $metaid ] ), ARRAY_A ) ) { |
| 251 |
$postmeta = $this->fix_postmeta( $postmeta ); |
| 252 |
} |
| 253 |
|
| 254 |
WPF()->ram_cache->set( $key, $postmeta ); |
| 255 |
|
| 256 |
return $postmeta; |
| 257 |
} |
| 258 |
|
| 259 |
/** |
| 260 |
* @param int $postid |
| 261 |
* @param string $metakey |
| 262 |
* |
| 263 |
* @return bool |
| 264 |
*/ |
| 265 |
public function exists( $postid, $metakey ) { |
| 266 |
if( ! $metakey || ! ( $postid = wpforo_bigintval( $postid ) ) ) return false; |
| 267 |
$sql = "SELECT EXISTS( |
| 268 |
SELECT * FROM `" . WPF()->tables->postmeta . "` |
| 269 |
WHERE `postid` = %d |
| 270 |
AND `metakey` = %s |
| 271 |
) AS is_exists"; |
| 272 |
|
| 273 |
return (bool) WPF()->db->get_var( WPF()->db->prepare( $sql, $postid, $metakey ) ); |
| 274 |
} |
| 275 |
|
| 276 |
/** |
| 277 |
* @param array $args |
| 278 |
* @param string $field |
| 279 |
* |
| 280 |
* @return array |
| 281 |
*/ |
| 282 |
public function get_postmetas_col( $args, $field ) { |
| 283 |
$args = wpforo_array_ordered_intersect_key( (array) $args, $this->default->sql_select_args ); |
| 284 |
if( empty( $args ) ) return []; |
| 285 |
|
| 286 |
$key = 'get_postmetas_' . json_encode( $args ) . '_' . $field; |
| 287 |
if( WPF()->ram_cache->exists( $key ) ) return WPF()->ram_cache->get( $key ); |
| 288 |
|
| 289 |
$postmetas = WPF()->db->get_col( $this->build_sql_select( $args, "`$field`" ) ); |
| 290 |
|
| 291 |
WPF()->ram_cache->set( $key, $postmetas ); |
| 292 |
|
| 293 |
return $postmetas; |
| 294 |
} |
| 295 |
|
| 296 |
/** |
| 297 |
* @param array $args |
| 298 |
* |
| 299 |
* @return array |
| 300 |
*/ |
| 301 |
public function get_postmetas( $args ) { |
| 302 |
$args = wpforo_array_ordered_intersect_key( (array) $args, $this->default->sql_select_args ); |
| 303 |
if( empty( $args ) ) return []; |
| 304 |
|
| 305 |
$key = 'get_postmetas_' . json_encode( $args ); |
| 306 |
if( WPF()->ram_cache->exists( $key ) ) return WPF()->ram_cache->get( $key ); |
| 307 |
|
| 308 |
if( $postmetas = (array) WPF()->db->get_results( $this->build_sql_select( $args ), ARRAY_A ) ) { |
| 309 |
$postmetas = array_map( [ $this, 'fix_postmeta' ], $postmetas ); |
| 310 |
} |
| 311 |
|
| 312 |
WPF()->ram_cache->set( $key, $postmetas ); |
| 313 |
|
| 314 |
return $postmetas; |
| 315 |
} |
| 316 |
|
| 317 |
/** |
| 318 |
* @param int $postid |
| 319 |
* @param string|array $metakeys |
| 320 |
* @param bool $single |
| 321 |
* |
| 322 |
* @return array|mixed|null |
| 323 |
*/ |
| 324 |
public function get_postmeta( $postid, $metakeys = '', $single = false ) { |
| 325 |
if( ! $postid = wpforo_bigintval( $postid ) ) return null; |
| 326 |
$metakeys = array_filter( (array) $metakeys ); |
| 327 |
|
| 328 |
$key = 'get_postmeta_' . $postid . '_' . json_encode( $metakeys ) . '_' . $single; |
| 329 |
if( WPF()->ram_cache->exists( $key ) ) return WPF()->ram_cache->get( $key ); |
| 330 |
|
| 331 |
$postmeta = null; |
| 332 |
|
| 333 |
$args = [ |
| 334 |
'postids_include' => $postid, |
| 335 |
'metakeys_include' => $metakeys, |
| 336 |
'orderby' => '`metaid` ASC', |
| 337 |
'row_count' => $single && $metakeys ? 1 : null, |
| 338 |
]; |
| 339 |
if( $postmetas = $this->get_postmetas( $args ) ) { |
| 340 |
if( count( $metakeys ) === 1 ) { |
| 341 |
if( $single ) { |
| 342 |
$first = current( $postmetas ); |
| 343 |
$postmeta = $first['metavalue']; |
| 344 |
} else { |
| 345 |
$postmeta = []; |
| 346 |
foreach( $postmetas as $p ) $postmeta[] = $p['metavalue']; |
| 347 |
} |
| 348 |
} else { |
| 349 |
$postmeta = []; |
| 350 |
foreach( $postmetas as $p ) { |
| 351 |
if( $single ) { |
| 352 |
if( ! array_key_exists( $p['metakey'], $postmeta ) ) $postmeta[ $p['metakey'] ] = $p['metavalue']; |
| 353 |
} else { |
| 354 |
$postmeta[ $p['metakey'] ][] = $p['metavalue']; |
| 355 |
} |
| 356 |
} |
| 357 |
} |
| 358 |
} |
| 359 |
|
| 360 |
WPF()->ram_cache->set( $key, $postmeta ); |
| 361 |
|
| 362 |
return $postmeta; |
| 363 |
} |
| 364 |
|
| 365 |
public function search( $args ) { |
| 366 |
$args = array_filter( (array) $args ); |
| 367 |
if( ! $args ) return []; |
| 368 |
|
| 369 |
$selects = []; |
| 370 |
foreach( $args as $key => $value ) { |
| 371 |
if( $field = WPF()->post->get_field( $key ) ) { |
| 372 |
$value = (array) $value; |
| 373 |
$wheres = []; |
| 374 |
if( in_array( $field['type'], [ 'text', 'textarea', 'email', 'search', 'tel' ] ) ) { |
| 375 |
foreach( $value as $v ) $wheres[] = "`metavalue` LIKE '%" . esc_sql( wp_unslash( $v ) ) . "%'"; |
| 376 |
} elseif( $field['type'] === 'checkbox' || ( $field['type'] === 'select' && wpfval( $field, 'isMultiChoice' ) ) || ( $field['type'] === 'autocomplete' && wpfval( $field, 'isMultiChoice' ) ) ) { |
| 377 |
foreach( $value as $v ) { |
| 378 |
$v = preg_quote( preg_quote( wp_unslash( $v ) ) ); |
| 379 |
$wheres[] = "`metavalue` REGEXP '[\\\[,]\"" . $v . "\"[,\\\]]'"; |
| 380 |
} |
| 381 |
} else { |
| 382 |
foreach( $value as $v ) $wheres[] = "`metavalue` LIKE '" . esc_sql( wp_unslash( $v ) ) . "'"; |
| 383 |
} |
| 384 |
if( $wheres ) { |
| 385 |
$selects[] = "SELECT `postid`, `metakey` FROM `" . WPF()->tables->postmeta . "` |
| 386 |
WHERE `metakey` = '" . esc_sql( $key ) . "' AND " . implode( ' AND ', $wheres ); |
| 387 |
} |
| 388 |
} |
| 389 |
} |
| 390 |
|
| 391 |
if( $selects ) { |
| 392 |
$sql = "SELECT `postid`, COUNT(`postid`) AS pcount FROM |
| 393 |
(" . implode( ' UNION ', $selects ) . ") AS pm |
| 394 |
GROUP BY `postid` HAVING pcount = " . count( $selects ); |
| 395 |
|
| 396 |
return WPF()->db->get_col( $sql ); |
| 397 |
} |
| 398 |
|
| 399 |
return []; |
| 400 |
} |
| 401 |
|
| 402 |
private function delete_file( $postid, $metakey ) { |
| 403 |
$postid = wpforo_bigintval( $postid ); |
| 404 |
if( $postid && $metakey ) { |
| 405 |
if( $postmeta = $this->get_postmeta( $postid, $metakey ) ) { |
| 406 |
foreach( $postmeta as $file ) { |
| 407 |
$mediaid = (int) wpfval( $file, 'mediaid' ); |
| 408 |
$fileurl = (string) wpfval( $file, 'fileurl' ); |
| 409 |
$filedir = wpforo_fix_upload_dir( $fileurl ); |
| 410 |
if( $mediaid ) wp_delete_attachment( $mediaid ); |
| 411 |
wp_delete_file( $filedir ); |
| 412 |
} |
| 413 |
$this->delete( [ 'postid' => $postid, 'metakey' => $metakey ] ); |
| 414 |
} |
| 415 |
} |
| 416 |
} |
| 417 |
|
| 418 |
private function add_file( $type, $post ) { |
| 419 |
$postid = (int) ( wpfval( $post, 'first_postid' ) ? $post['first_postid'] : wpfval( $post, 'postid' ) ); |
| 420 |
|
| 421 |
if( $wpftcf_delete = array_filter( (array) wpfval( $_POST, 'wpftcf_delete' ) ) ) { |
| 422 |
foreach( $wpftcf_delete as $metakey ) { |
| 423 |
$this->delete_file( $postid, $metakey ); |
| 424 |
} |
| 425 |
} |
| 426 |
|
| 427 |
if( ! empty( wpfval( $_FILES, 'data', 'type' ) ) ) { |
| 428 |
$forum = WPF()->forum->get_forum( $post['forumid'] ); |
| 429 |
$fields_list = WPF()->post->get_topic_fields_list( false, $forum, ! WPF()->current_userid ); |
| 430 |
$mime_types = wp_get_mime_types(); |
| 431 |
$allowed_mime_types = get_allowed_mime_types(); |
| 432 |
foreach( $_FILES['data']['type'] as $k => $mime_type ) { |
| 433 |
if( in_array( $k, $fields_list ) ) { |
| 434 |
$field = WPF()->post->get_field( $k, $type, $forum ); |
| 435 |
$label = ( $field['label'] ?: $field['fieldKey'] ); |
| 436 |
|
| 437 |
if( $error = intval( wpfval( $_FILES, 'data', 'error', $k ) ) ) { |
| 438 |
$phpFileUploadErrors = [ |
| 439 |
0 => 'There is no error, the file uploaded with success', |
| 440 |
1 => 'The uploaded file size is too big', |
| 441 |
2 => 'The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form', |
| 442 |
3 => 'The uploaded file was only partially uploaded', |
| 443 |
// 4 => 'No file was uploaded', |
| 444 |
6 => 'Missing a temporary folder', |
| 445 |
7 => 'Failed to write file to disk.', |
| 446 |
8 => 'A PHP extension stopped the file upload.', |
| 447 |
]; |
| 448 |
if( $n = wpfval( $phpFileUploadErrors, $error ) ) WPF()->notice->add( $n, 'error' ); |
| 449 |
} else { |
| 450 |
$name = wpfval( $_FILES, 'data', 'name', $k ); |
| 451 |
$tmp_name = wpfval( $_FILES, 'data', 'tmp_name', $k ); |
| 452 |
$ext = pathinfo( $name, PATHINFO_EXTENSION ); |
| 453 |
$size = intval( $field['fileSize'] ); |
| 454 |
$fileExtensions = array_filter( (array) is_scalar( $field['fileExtensions'] ) ? explode( ',', trim( (string) $field['fileExtensions'] ) ) : $field['fileExtensions'] ); |
| 455 |
if( $fileExtensions ) { |
| 456 |
if( in_array( $ext, $fileExtensions ) ) { |
| 457 |
$extensions = explode( '|', array_search( $mime_type, $mime_types ) ); |
| 458 |
$e = in_array( $ext, $extensions ); |
| 459 |
} else { |
| 460 |
$e = false; |
| 461 |
} |
| 462 |
} else { |
| 463 |
$extensions = explode( '|', array_search( $mime_type, $allowed_mime_types ) ); |
| 464 |
$e = in_array( $ext, $extensions ); |
| 465 |
} |
| 466 |
|
| 467 |
if( ! empty( $e ) ) { |
| 468 |
if( wpfval( $_FILES, 'data', 'size', $k ) <= ( $size * 1024 * 1024 ) ) { |
| 469 |
$attach_dir = WPF()->folders['default_attachments']['dir'] . DIRECTORY_SEPARATOR . WPF()->current_userid; |
| 470 |
$attach_url = WPF()->folders['default_attachments']['url//'] . "/" . WPF()->current_userid; |
| 471 |
if( ! is_dir( $attach_dir ) ) wp_mkdir_p( $attach_dir ); |
| 472 |
|
| 473 |
$fnm = pathinfo( $name, PATHINFO_FILENAME ); |
| 474 |
$fnm = str_replace( ' ', '-', $fnm ); |
| 475 |
while( strpos( (string) $fnm, '--' ) !== false ) $fnm = str_replace( '--', '-', $fnm ); |
| 476 |
$fnm = preg_replace( "/[^-a-zA-Z0-9_]/", "", (string) $fnm ); |
| 477 |
$fnm = trim( (string) $fnm, "-" ); |
| 478 |
$fnm_empty = ! $fnm; |
| 479 |
|
| 480 |
$file_name = $fnm . "." . $ext; |
| 481 |
|
| 482 |
$attach_fname = time() . ( ! $fnm_empty ? '-' : '' ) . $file_name; |
| 483 |
$attach_path = $attach_dir . DIRECTORY_SEPARATOR . $attach_fname; |
| 484 |
|
| 485 |
if( is_dir( $attach_dir ) && move_uploaded_file( $tmp_name, $attach_path ) ) { |
| 486 |
$this->delete_file( $postid, $field['fieldKey'] ); |
| 487 |
|
| 488 |
$attach_id = wpforo_insert_to_media_library( $attach_path, $fnm ); |
| 489 |
$file = [ |
| 490 |
'fileurl' => $attach_url . '/' . $attach_fname, |
| 491 |
'filename' => basename( (string) $name ), |
| 492 |
'mediaid' => $attach_id, |
| 493 |
]; |
| 494 |
|
| 495 |
$postmeta = [ |
| 496 |
'postid' => $postid, |
| 497 |
'metakey' => $field['fieldKey'], |
| 498 |
'metavalue' => $file, |
| 499 |
'forumid' => $post['forumid'], |
| 500 |
'topicid' => $post['topicid'], |
| 501 |
'is_first_post' => 1, |
| 502 |
'status' => $post['status'], |
| 503 |
'private' => $post['private'], |
| 504 |
]; |
| 505 |
$this->add( $postmeta ); |
| 506 |
|
| 507 |
} else { |
| 508 |
WPF()->notice->add( 'Can\'t upload file', 'error' ); |
| 509 |
} |
| 510 |
|
| 511 |
} else { |
| 512 |
WPF()->notice->add( '%1$s - File is too large. Maximum allowed file size is %2$s MB', 'error', [ $label, $size ] ); |
| 513 |
} |
| 514 |
} else { |
| 515 |
WPF()->notice->add( '%1$s - File type is not allowed.', 'error', $label ); |
| 516 |
} |
| 517 |
} |
| 518 |
} |
| 519 |
} |
| 520 |
} |
| 521 |
} |
| 522 |
|
| 523 |
public function after_add_topic( $topic, $forum ) { |
| 524 |
$this->add_file( 'topic', $topic ); |
| 525 |
|
| 526 |
if( ! empty( $topic['postmetas'] ) ) { |
| 527 |
$fields_list = WPF()->post->get_topic_fields_list( false, $forum, ! WPF()->current_userid ); |
| 528 |
foreach( $topic['postmetas'] as $metakey => $metavalue ) { |
| 529 |
if( in_array( $metakey, $fields_list ) ) { |
| 530 |
$postmeta = [ |
| 531 |
'postid' => $topic['first_postid'], |
| 532 |
'metakey' => $metakey, |
| 533 |
'metavalue' => $metavalue, |
| 534 |
'forumid' => $topic['forumid'], |
| 535 |
'topicid' => $topic['topicid'], |
| 536 |
'is_first_post' => 1, |
| 537 |
'status' => $topic['status'], |
| 538 |
'private' => $topic['private'], |
| 539 |
]; |
| 540 |
$this->add( $postmeta ); |
| 541 |
} |
| 542 |
} |
| 543 |
} |
| 544 |
} |
| 545 |
|
| 546 |
public function after_edit_topic( $topic, $args, $forum ) { |
| 547 |
$this->add_file( 'topic', $topic ); |
| 548 |
|
| 549 |
if( ! empty( $args['postmetas'] ) ) { |
| 550 |
$fields_list = WPF()->post->get_topic_fields_list( false, $forum, ! WPF()->current_userid ); |
| 551 |
foreach( $args['postmetas'] as $metakey => $metavalue ) { |
| 552 |
if( in_array( $metakey, $fields_list ) ) { |
| 553 |
$postmeta = [ |
| 554 |
'metavalue' => $metavalue, |
| 555 |
'forumid' => $topic['forumid'], |
| 556 |
'topicid' => $topic['topicid'], |
| 557 |
'is_first_post' => 1, |
| 558 |
'status' => $topic['status'], |
| 559 |
'private' => $topic['private'], |
| 560 |
]; |
| 561 |
if( $this->exists( $topic['first_postid'], $metakey ) ) { |
| 562 |
$this->edit( $postmeta, [ |
| 563 |
'postid' => $topic['first_postid'], |
| 564 |
'metakey' => $metakey, |
| 565 |
] ); |
| 566 |
} else { |
| 567 |
$postmeta['postid'] = $topic['first_postid']; |
| 568 |
$postmeta['metakey'] = $metakey; |
| 569 |
$this->add( $postmeta ); |
| 570 |
} |
| 571 |
} |
| 572 |
} |
| 573 |
} |
| 574 |
} |
| 575 |
|
| 576 |
public function after_add_post( $post, $topic, $forum ) { |
| 577 |
$this->add_file( 'post', $post ); |
| 578 |
|
| 579 |
if( ! empty( $post['postmetas'] ) ) { |
| 580 |
$fields_list = WPF()->post->get_post_fields_list( false, $forum, ! WPF()->current_userid ); |
| 581 |
foreach( $post['postmetas'] as $metakey => $metavalue ) { |
| 582 |
if( in_array( $metakey, $fields_list ) ) { |
| 583 |
$postmeta = [ |
| 584 |
'postid' => $post['postid'], |
| 585 |
'metakey' => $metakey, |
| 586 |
'metavalue' => $metavalue, |
| 587 |
'forumid' => $post['forumid'], |
| 588 |
'topicid' => $post['topicid'], |
| 589 |
'is_first_post' => 0, |
| 590 |
'status' => $post['status'], |
| 591 |
'private' => $post['private'], |
| 592 |
]; |
| 593 |
$this->add( $postmeta ); |
| 594 |
} |
| 595 |
} |
| 596 |
} |
| 597 |
} |
| 598 |
|
| 599 |
public function after_edit_post( $post, $topic, $forum, $args ) { |
| 600 |
$this->add_file( 'post', $post ); |
| 601 |
|
| 602 |
if( ! empty( $args['postmetas'] ) ) { |
| 603 |
$fields_list = WPF()->post->get_post_fields_list( false, $forum, ! WPF()->current_userid ); |
| 604 |
foreach( $args['postmetas'] as $metakey => $metavalue ) { |
| 605 |
if( in_array( $metakey, $fields_list ) ) { |
| 606 |
$postmeta = [ |
| 607 |
'metavalue' => $metavalue, |
| 608 |
'forumid' => $post['forumid'], |
| 609 |
'topicid' => $post['topicid'], |
| 610 |
'is_first_post' => 0, |
| 611 |
'status' => $post['status'], |
| 612 |
'private' => $post['private'], |
| 613 |
]; |
| 614 |
if( $this->exists( $post['postid'], $metakey ) ) { |
| 615 |
$this->edit( $postmeta, [ |
| 616 |
'postid' => $post['postid'], |
| 617 |
'metakey' => $metakey, |
| 618 |
] ); |
| 619 |
} else { |
| 620 |
$postmeta['postid'] = $post['postid']; |
| 621 |
$postmeta['metakey'] = $metakey; |
| 622 |
$this->add( $postmeta ); |
| 623 |
} |
| 624 |
} |
| 625 |
} |
| 626 |
} |
| 627 |
} |
| 628 |
|
| 629 |
public function after_move_topic( $topic, $forumid ) { |
| 630 |
$this->edit( [ 'forumid' => $forumid ], [ 'topicid' => $topic['topicid'] ] ); |
| 631 |
} |
| 632 |
|
| 633 |
public function after_merge_topic( $target, $current, $postids ) { |
| 634 |
$sql = "UPDATE `" . WPF()->tables->postmeta . "` SET `topicid` = %d, `forumid` = %d, `private` = %d, `is_first_post` = 0 WHERE `topicid` = %d"; |
| 635 |
$sql = WPF()->db->prepare( $sql, $target['topicid'], $target['forumid'], (int) wpfval( $target, 'private' ), $current['topicid'] ); |
| 636 |
if( $postids ) $sql .= " AND `postid` IN(" . implode( ',', array_map( 'wpforo_bigintval', (array) $postids ) ) . ")"; |
| 637 |
WPF()->db->query( $sql ); |
| 638 |
} |
| 639 |
|
| 640 |
public function after_delete_post( $post ) { |
| 641 |
$this->delete( [ 'postid' => $post['postid'] ] ); |
| 642 |
} |
| 643 |
|
| 644 |
public function after_post_status_update( $post, $status ) { |
| 645 |
$this->edit( [ 'status' => $status ], [ 'postid' => $post['postid'] ] ); |
| 646 |
} |
| 647 |
|
| 648 |
public function after_topic_private_update( $topicid, $private ) { |
| 649 |
$this->edit( [ 'private' => $private ], [ 'topicid' => $topicid ] ); |
| 650 |
} |
| 651 |
|
| 652 |
public function after_is_first_post_update( $postid, $is_first_post ) { |
| 653 |
$this->edit( [ 'is_first_post' => $is_first_post ], [ 'postid' => $postid ] ); |
| 654 |
} |
| 655 |
} |
| 656 |
|