public function board_statistics($output, $shortname = null) { $boards = $this->radix_coll->getAll(); $available = $this->board_stats->getAvailableStats(); while (true) { // Obtain all of the statistics already stored on the database to check for update frequency. $stats = $this->dc->qb()->select('board_id, name, timestamp')->from($this->dc->p('plugin_fu_board_statistics'), 'bs')->orderBy('timestamp', 'desc')->execute()->fetchAll(); // Obtain the list of all statistics enabled. $avail = []; foreach ($available as $k => $a) { // get only the non-realtime ones if (isset($available['frequency'])) { $avail[] = $k; } } foreach ($boards as $board) { if (!is_null($shortname) && $shortname != $board->shortname) { continue; } // Update all statistics for the specified board or current board. $output->writeln($board->shortname . ' (' . $board->id . ')'); foreach ($available as $k => $a) { $output->writeln(' ' . $k . ' '); $found = false; $skip = false; foreach ($stats as $r) { // Determine if the statistics already exists or that the information is outdated. if ($r['board_id'] == $board->id && $r['name'] == $k) { // This statistics report has run once already. $found = true; if (!isset($a['frequency'])) { $skip = true; continue; } // This statistics report has not reached its frequency EOL. if (time() - $r['timestamp'] <= $a['frequency']) { $skip = true; continue; } break; } } // racing conditions with our cron. if ($found === false) { $this->board_stats->saveStat($board->id, $k, time() + 600, ''); } // We were able to obtain a LOCK on the statistics report and has already reached the // targeted frequency time. if ($skip === false) { $output->writeln('* Processing...'); $process = 'process' . $a['function']; $result = $this->board_stats->{$process}($board); // Save the statistics report in a JSON array. $this->board_stats->saveStat($board->id, $k, time(), $result); } } } sleep(10); } }
public function install_modules() { $this->config->addPackage('unknown', ASSETSPATH); $class_name = $this->config->get('unknown', 'package', 'main.class_name'); $name_lowercase = strtolower($class_name); $modules = ['foolframe' => ['context' => '\\Foolz\\FoolFrame\\Model\\Context', 'namespace' => 'foolz/foolframe'], $name_lowercase => ['context' => $this->config->get('unknown', 'package', 'main.class_context'), 'namespace' => 'foolz/' . $name_lowercase]]; $dc = new DoctrineConnection($this->getContext(), $this->config); $sm = SchemaManager::forge($dc->getConnection(), $dc->getPrefix()); Schema::load($this->getContext(), $sm); $schema_class = '\\Foolz\\' . $class_name . '\\Model\\Schema'; $schema_class::load($this->getContext(), $sm); $sm->commit(); $this->config->set('foolz/foolframe', 'config', 'modules.installed', $modules); $this->config->set('foolz/foolframe', 'config', 'install.installed', true); $this->config->save('foolz/foolframe', 'config'); }
/** * Adds a new ban * * @param string $ip_decimal The IP of the banned user in decimal format * @param string $reason The reason for the ban * @param int $length The length of the ban in seconds * @param array $board_ids The array of board IDs, global ban if left empty * * @return \Foolz\Foolfuuka\Model\Ban * @throws \Foolz\Foolfuuka\Model\BanException */ public function add($ip_decimal, $reason, $length, $board_ids = []) { // 0 is a global ban if (empty($board_ids)) { $board_ids = [0]; } else { // check that all ids are existing boards $valid_board_ids = []; foreach ($this->radix_coll->getAll() as $board) { $valid_board_ids[] = $board->id; } foreach ($board_ids as $id) { if (!in_array($id, $valid_board_ids)) { throw new BanException(_i('You entered a non-existent board ID.')); } } } if (!ctype_digit((string) $ip_decimal)) { throw new BanException(_i('You entered an invalid IP.')); } if (mb_strlen($reason, 'utf-8') > 10000) { throw new BanException(_i('You entered a too long reason for the ban.')); } if (!ctype_digit($length)) { throw new BanException(_i('You entered an invalid length for the ban.')); } $time = time(); $objects = []; try { $old = $this->getByIp($ip_decimal); } catch (BanNotFoundException $e) { $old = false; } foreach ($board_ids as $board_id) { $new = new Ban($this->getContext()); $new->ip = $ip_decimal; $new->reason = $reason; $new->start = $time; $new->length = $length; $new->board_id = $board_id; $new->creator_id = $this->getAuth()->getUser()->getId(); $new->appeal = ''; if (isset($old[$new->board_id])) { if ($new->length < $old[$new->board_id]->length) { $new->length = $old[$new->board_id]->length; } $this->dc->qb()->update($this->dc->p('banned_posters'))->where('id = :id')->set('start', $new->start)->set('length', $new->length)->set('creator_id', $new->creator_id)->setParameter(':id', $old[$new->board_id]->id)->execute(); } else { $this->dc->getConnection()->insert($this->dc->p('banned_posters'), ['ip' => $new->ip, 'reason' => $new->reason, 'start' => $new->start, 'length' => $new->length, 'board_id' => $new->board_id, 'creator_id' => $new->creator_id, 'appeal' => $new->appeal]); } $objects[] = $new; } return $objects; }
public function processUsersOnline($board) { $datetime = new \DateTime('@' . time(), new \DateTimeZone('UTC')); if ($board->archive) { $datetime->setTimezone(new \DateTimeZone('America/New_York')); } $timestamp = strtotime($datetime->format('Y-m-d H:i:s')); $result = []; $result['board'] = $this->dc->qb()->select('name, trip, MAX(timestamp) AS timestamp, num, subnum')->from($board->getTable(), 'b')->where('timestamp > ' . ($timestamp - 1800))->groupBy('name')->addGroupBy('trip')->orderBy('MAX(timestamp)', 'desc')->execute()->fetchAll(); $result['ghost'] = $this->dc->qb()->select('name, trip, MAX(timestamp) AS timestamp, num, subnum')->from($board->getTable(), 'b')->where('subnum <> 0')->andWhere('timestamp > ' . ($timestamp - 3600))->groupBy('name')->addGroupBy('trip')->orderBy('MAX(timestamp)', 'desc')->execute()->fetchAll(); return $result; }
public function deleteAccount($id, $key) { $row = $this->dc->qb()->select('*')->from($this->dc->p('users'), 'l')->where('id = :id')->andWhere('deletion_time > :deletion_time')->setParameter(':id', $id)->setParameter(':deletion_time', time() - 900)->execute()->fetch(); if (!$row || !password_verify($key, $row['deletion_key'])) { throw new WrongKeyException(); } $affected_rows = $this->dc->qb()->delete($this->dc->p('users'))->where('id = :id')->setParameter(':id', $id)->execute(); if (!$affected_rows) { throw new WrongKeyException(); } return true; }
/** * Remove the tables associated to the Radix */ public function removeTables() { $tables = ['', '_deleted', '_images', '_threads', '_users', '_daily']; $sm = $this->dc->getConnection()->getSchemaManager(); $schema = $sm->createSchema(); foreach ($tables as $table) { $schema->dropTable($this->getTable($table)); } foreach ($schema->getMigrateFromSql($sm->createSchema(), $sm->getDatabasePlatform()) as $query) { $this->dc->getConnection()->query($query); } }
public function set($setting, $value, $reload = true) { // if array, serialize value if (is_array($value)) { $value = serialize($value); } $count = $this->dc->qb()->select('COUNT(*) as count')->from($this->dc->p('preferences'), 'p')->where('p.name = :name')->setParameter(':name', $setting)->execute()->fetch()['count']; if ($count > 0) { $this->dc->qb()->update($this->dc->p('preferences'))->set('value', ':value')->where('name = :name')->setParameters([':value' => $value, ':name' => $setting])->execute(); } else { $this->dc->getConnection()->insert($this->dc->p('preferences'), ['name' => $setting, 'value' => $value]); } if ($reload) { return $this->load(true); } return $this->preferences; }
public function install($slug) { $plugin = $this->loader->get($slug); $plugin->install(); $this->dc->getConnection()->insert($this->dc->p('plugins'), ['slug' => $slug, 'enabled' => 1]); $this->clearCache(); // run the schema update $sm = \Foolz\FoolFrame\Model\SchemaManager::forge($this->dc->getConnection(), $this->dc->getPrefix() . 'plugin_'); foreach ($this->getInstalled() as $enabled) { try { $plug = $this->loader->get($enabled['slug']); if (!$plug->isBootstrapped()) { $plug->bootstrap(); } \Foolz\Plugin\Hook::forge('Foolz\\FoolFrame\\Model\\Plugin::install#' . $plug->getConfig('name'))->setParam('context', $this->getContext())->setParam('schema', $sm->getCodedSchema())->execute(); } catch (\OutOfBoundsException $e) { } } $sm->commit(); $this->clearCache(); }
/** * Gets a post by num or doc_d * * @return \Foolz\Foolslide\Model\Board The current object * @throws BoardMalformedInputException If the $num is not a valid post number * @throws BoardMissingOptionsException If doc_id or num has not been specified * @throws BoardPostNotFoundException If the post has not been found */ protected function p_getPostComments() { extract($this->options); $query = $this->dc->qb()->select('*')->from($this->radix->getTable(), 'r'); if (isset($num)) { if (!static::isValidPostNumber($num)) { throw new BoardMalformedInputException(); } $num_arr = static::splitPostNumber($num); $query->where('num = :num')->andWhere('subnum = :subnum')->setParameter(':num', $num_arr['num'])->setParameter(':subnum', $num_arr['subnum']); } elseif (isset($doc_id)) { $query->where('doc_id = :doc_id')->setParameter(':doc_id', $doc_id); } else { throw new BoardMissingOptionsException(_i('No posts found with the submitted options.')); } $result = $query->leftJoin('r', $this->radix->getTable('_images'), 'mg', 'mg.media_id = r.media_id')->execute()->fetchAll(); if (!count($result)) { throw new BoardPostNotFoundException(_i('Post not found.')); } foreach ($result as $bulk) { $data = new CommentBulk(); $data->import($bulk, $this->radix); $this->comments_unsorted[] = $data; } foreach ($this->comments_unsorted as $comment) { $this->comments[$comment->comment->num . ($comment->comment->subnum ? '_' . $comment->comment->subnum : '')] = $comment; } return $this; }
/** * Delete the post and eventually the entire thread if it's OP * Also deletes the images when it's the only post with that image * * @param null $password * @param bool $force * @param bool $thread * @throws CommentSendingDatabaseException * @throws CommentDeleteWrongPassException * @return array|bool */ protected function p_delete($password = null, $force = false, $thread = false) { if (!$this->getAuth()->hasAccess('comment.passwordless_deletion') && $force !== true) { if (!password_verify($password, $this->comment->getDelpass())) { throw new CommentDeleteWrongPassException(_i('You did not provide the correct deletion password.')); } } try { $this->dc->getConnection()->beginTransaction(); // check that the post isn't already in deleted $has_deleted = $this->dc->qb()->select('COUNT(*) as found')->from($this->radix->getTable('_deleted'), 'd')->where('doc_id = :doc_id')->setParameter(':doc_id', $this->comment->doc_id)->execute()->fetch(); if (!$has_deleted['found']) { // throw into _deleted table $this->dc->getConnection()->executeUpdate('INSERT INTO ' . $this->radix->getTable('_deleted') . ' ' . $this->dc->qb()->select('*')->from($this->radix->getTable(), 't')->where('doc_id = ' . $this->dc->getConnection()->quote($this->comment->doc_id))->getSQL()); } // delete post $this->dc->qb()->delete($this->radix->getTable())->where('doc_id = :doc_id')->setParameter(':doc_id', $this->comment->doc_id)->execute(); // purge reports $this->dc->qb()->delete($this->dc->p('reports'))->where('board_id = :board_id')->andWhere('doc_id = :doc_id')->setParameter(':board_id', $this->radix->id)->setParameter(':doc_id', $this->comment->doc_id)->execute(); // clear cache $this->radix_coll->clearCache(); // remove image file if (isset($this->media)) { $media_sql = $this->dc->qb()->select('COUNT(*)')->from($this->radix->getTable(), 't')->where('media_id = :media_id')->setParameter(':media_id', $this->media->media_id)->getSQL(); $this->dc->qb()->update($this->radix->getTable('_images'))->set('total', '(' . $media_sql . ')')->where('media_id = :media_id')->setParameter(':media_id', $this->media->media_id)->execute(); $has_image = $this->dc->qb()->select('total')->from($this->radix->getTable('_images'), 'ti')->where('media_id = :media_id')->setParameter(':media_id', $this->media->media_id)->execute()->fetch(); if (!$has_image || !$has_image['total']) { $media = new Media($this->getContext(), $this->bulk); $media->delete(); } } // if this is OP, delete replies too if ($this->comment->op) { // delete thread data $this->dc->qb()->delete($this->radix->getTable('_threads'))->where('thread_num = :thread_num')->setParameter(':thread_num', $this->comment->thread_num)->execute(); // process each comment $comments = $this->dc->qb()->select('doc_id')->from($this->radix->getTable(), 'b')->where('thread_num = :thread_num')->setParameter(':thread_num', $this->comment->thread_num)->execute()->fetchAll(); foreach ($comments as $comment) { $post = Board::forge($this->getContext())->getPost()->setOptions('doc_id', $comment['doc_id'])->setRadix($this->radix)->getComments(); $post = current($post); $post = new Comment($this->getContext(), $post); $post->delete(null, true, true); } } else { // if this is not triggered by a thread deletion, update the thread table if ($thread === false && !$this->radix->archive) { $time_last = ' ( COALESCE(GREATEST( time_op, ( SELECT MAX(timestamp) FROM ' . $this->radix->getTable() . ' xr WHERE thread_num = ' . $this->dc->getConnection()->quote($this->comment->thread_num) . ' AND subnum = 0 ) ), time_op) )'; $time_bump = ' ( COALESCE(GREATEST( time_op, ( SELECT MAX(timestamp) FROM ' . $this->radix->getTable() . ' xr WHERE thread_num = ' . $this->dc->getConnection()->quote($this->comment->thread_num) . ' AND subnum = 0 AND (email <> \'sage\' OR email IS NULL) ) ), time_op) )'; $time_ghost = ' ( SELECT MAX(timestamp) FROM ' . $this->radix->getTable() . ' xr WHERE thread_num = ' . $this->dc->getConnection()->quote($this->comment->thread_num) . ' AND subnum <> 0 )'; $time_ghost_bump = ' ( SELECT MAX(timestamp) FROM ' . $this->radix->getTable() . ' xr WHERE thread_num = ' . $this->dc->getConnection()->quote($this->comment->thread_num) . ' AND subnum <> 0 AND (email <> \'sage\' OR email IS NULL) )'; // update thread information $this->dc->qb()->update($this->radix->getTable('_threads'))->set('time_last', $time_last)->set('time_bump', $time_bump)->set('time_ghost', $time_ghost)->set('time_ghost_bump', $time_ghost_bump)->set('time_last_modified', ':time')->set('nreplies', 'nreplies - 1')->set('nimages', $this->media === null ? 'nimages' : 'nimages - 1')->where('thread_num = :thread_num')->setParameter(':time', $this->getRadixTime())->setParameter(':thread_num', $this->comment->thread_num)->execute(); } } $this->dc->getConnection()->commit(); $this->clearCache(); if ($thread === false) { $this->audit->log(Audit::AUDIT_DEL_POST, ['radix' => $this->radix->id, 'doc_id' => $this->comment->doc_id, 'thread_num' => $this->comment->thread_num, 'num' => $this->comment->num, 'subnum' => $this->comment->subnum]); } } catch (\Doctrine\DBAL\DBALException $e) { $this->logger->error('\\Foolz\\FoolFuuka\\Model\\CommentInsert: ' . $e->getMessage()); $this->dc->getConnection()->rollBack(); throw new CommentSendingDatabaseException(_i('Something went wrong when deleting the post in the database. Try again.')); } return $this; }
/** * Inserts the media uploaded (static::forgeFromUpload()) * * @param string $microtime The time in microseconds to use for the local filename * @param boolean $is_op True if the thumbnail sizes should be for OP, false if they should be for a reply * * @return \Foolz\Foolfuuka\Model\Media The current object updated with the insert data * @throws MediaInsertInvalidFormatException In case the media is not a valid format * @throws MediaInsertDomainException In case the media uploaded is in example too small or validations don't pass * @throws MediaInsertRepostException In case the media has been reposted too recently according to control panel settings * @throws MediaThumbnailCreationException If the thumbnail fails to generate */ public function p_insert($microtime, $is_op) { $file = $this->temp_file; $this->op = $is_op; $data = \Foolz\Plugin\Hook::forge('Foolz\\Foolfuuka\\Model\\Media::insert.result.media_data')->setParams(['dimensions' => getimagesize($file->getPathname()), 'file' => $file, 'name' => $file->getClientOriginalName(), 'path' => $file->getPathname(), 'hash' => base64_encode(pack("H*", md5(file_get_contents($file->getPathname())))), 'size' => $file->getClientSize(), 'time' => $microtime, 'media_orig' => $microtime . '.' . strtolower($file->getClientOriginalExtension()), 'preview_orig' => $microtime . 's.' . strtolower($file->getClientOriginalExtension())])->execute()->getParams(); if (!($getimagesize = $data['dimensions'])) { throw new MediaInsertInvalidFormatException(_i('The file you uploaded is not allowed.')); } // if width and height are lower than 25 reject the image if ($getimagesize[0] < 25 || $getimagesize[1] < 25) { throw new MediaInsertDomainException(_i('The file you uploaded is too small.')); } if ($getimagesize[0] > $this->radix->getValue('max_image_size_width') || $getimagesize[1] > $this->radix->getValue('max_image_size_height')) { throw new MediaInsertDomainException(_i('The dimensions of the file you uploaded is too large.')); } $this->media->media_w = $getimagesize[0]; $this->media->media_h = $getimagesize[1]; $this->media->media_filename = $data['name']; $this->media->media_hash = $data['hash']; $this->media->media_size = $data['size']; $this->media->media_orig = $data['media_orig']; $this->media->preview_orig = $data['preview_orig']; $do_thumb = true; $do_full = true; try { $duplicate = CommentBulk::forge($this->radix, null, $this->media_factory->getByMediaHash($this->radix, $this->media->media_hash)); $duplicate = new Media($this->getContext(), $duplicate); // we want the current media to work with the same filenames as previously stored $this->media->media_id = $duplicate->media->media_id; $this->media->media = $duplicate->media->media; $this->media->media_orig = $duplicate->media->media; $this->media->preview_op = $duplicate->media->preview_op; $this->media->preview_reply = $duplicate->media->preview_reply; if (!$this->getAuth()->hasAccess('comment.limitless_comment') && $this->radix->getValue('min_image_repost_time')) { // if it's -1 it means that image reposting is disabled, so this image shouldn't pass if ($this->radix->getValue('min_image_repost_time') == -1) { throw new MediaInsertRepostException(_i('This image has already been posted once. This board doesn\'t allow image reposting.')); } // we don't have to worry about archives with weird timestamps, we can't post images there $duplicate_entry = $this->dc->qb()->select('COUNT(*) as count, MAX(timestamp) as max_timestamp')->from($this->radix->getTable(), 'r')->where('media_id = :media_id')->andWhere('timestamp > :timestamp')->setParameter('media_id', $duplicate->media->media_id)->setParameter('timestamp', time() - $this->radix->getValue('min_image_repost_time'))->setMaxResults(1)->execute()->fetch(); if ($duplicate_entry['count']) { $datetime = new \DateTime(date('Y-m-d H:i:s', $duplicate_entry['max_timestamp'] + $this->radix->getValue('min_image_repost_time'))); $remain = $datetime->diff(new \DateTime()); throw new MediaInsertRepostException(_i('This image has been posted recently. You will be able to post it again in %s.', ($remain->d > 0 ? $remain->d . ' ' . _i('day(s)') : '') . ' ' . ($remain->h > 0 ? $remain->h . ' ' . _i('hour(s)') : '') . ' ' . ($remain->i > 0 ? $remain->i . ' ' . _i('minute(s)') : '') . ' ' . ($remain->s > 0 ? $remain->s . ' ' . _i('second(s)') : ''))); } } // if we're here, we got the media $duplicate_dir = $duplicate->getDir(); if ($duplicate_dir !== null && file_exists($duplicate_dir)) { $do_full = false; } $duplicate->op = $is_op; $duplicate_dir_thumb = $duplicate->getDir(true, true); if ($duplicate_dir_thumb !== null && file_exists($duplicate_dir_thumb)) { $duplicate_dir_thumb_size = getimagesize($duplicate_dir_thumb); $this->media->preview_w = $duplicate_dir_thumb_size[0]; $this->media->preview_h = $duplicate_dir_thumb_size[1]; $do_thumb = false; } } catch (MediaNotFoundException $e) { } if ($do_thumb) { $thumb_width = $this->radix->getValue('thumbnail_reply_width'); $thumb_height = $this->radix->getValue('thumbnail_reply_height'); if ($is_op) { $thumb_width = $this->radix->getValue('thumbnail_op_width'); $thumb_height = $this->radix->getValue('thumbnail_op_height'); } if (!file_exists($this->pathFromFilename(true, $is_op))) { mkdir($this->pathFromFilename(true, $is_op), 0777, true); } $return = \Foolz\Plugin\Hook::forge('Foolz\\Foolfuuka\\Model\\Media::insert.result.create_thumbnail')->setObject($this)->setParams(['thumb_width' => $thumb_width, 'thumb_height' => $thumb_height, 'exec' => str_replace(' ', '\\ ', $this->preferences->get('foolframe.imagick.convert_path')), 'is_op' => $is_op, 'media' => $file, 'thumb' => $this->pathFromFilename(true, $is_op, true)])->execute()->get(); if ($return instanceof \Foolz\Plugin\Void) { if ($this->radix->getValue('enable_animated_gif_thumbs') && strtolower($file->getClientOriginalExtension()) === 'gif') { exec(str_replace(' ', '\\ ', $this->preferences->get('foolframe.imagick.convert_path')) . " " . $data['path'] . " -coalesce -treedepth 4 -colors 256 -quality 80 -background none " . "-resize \"" . $thumb_width . "x" . $thumb_height . ">\" " . $this->pathFromFilename(true, $is_op, true)); } else { exec(str_replace(' ', '\\ ', $this->preferences->get('foolframe.imagick.convert_path')) . " " . $data['path'] . "[0] -quality 80 -background none " . "-resize \"" . $thumb_width . "x" . $thumb_height . ">\" " . $this->pathFromFilename(true, $is_op, true)); } } if (!file_exists($this->pathFromFilename(true, $is_op, true))) { throw new MediaThumbnailCreationException(_i('The thumbnail failed to generate.')); } $thumb_getimagesize = getimagesize($this->pathFromFilename(true, $is_op, true)); $this->media->preview_w = $thumb_getimagesize[0]; $this->media->preview_h = $thumb_getimagesize[1]; if ($do_full) { if (!file_exists($this->pathFromFilename())) { mkdir($this->pathFromFilename(), 0777, true); } copy($data['path'], $this->pathFromFilename(false, false, true)); } } if (function_exists('exif_read_data') && in_array(strtolower($file->getClientOriginalExtension()), ['jpg', 'jpeg', 'tiff'])) { $exif_data = null; getimagesize($data['path'], $exif_data); if (!isset($exif_data['APP1']) || strpos($exif_data['APP1'], 'Exif') === 0) { $exif = exif_read_data($data['path']); if ($exif !== false) { $this->media->exif = $exif; } } } if (!$this->media->media_id) { $this->dc->getConnection()->insert($this->radix->getTable('_images'), ['media_hash' => $this->media->media_hash, 'media' => $this->media->media_orig, 'preview_op' => $this->op ? $this->media->preview_orig : null, 'preview_reply' => !$this->op ? $this->media->preview_orig : null, 'total' => 1, 'banned' => 0]); $this->media->media_id = $this->dc->getConnection()->lastInsertId($this->radix->getTable('_images_media_id_seq')); } else { $media_sql = $this->dc->qb()->select('COUNT(*)')->from($this->radix->getTable(), 't')->where('media_id = :media_id')->setParameter(':media_id', $this->media->media_id)->getSQL(); $query = $this->dc->qb()->update($this->radix->getTable('_images')); if ($this->media === null) { $query->set('media', ':media_orig')->setParameter(':media_orig', $this->media->preview_orig); } if ($this->op && $this->media->preview_op === null) { $query->set('preview_op', ':preview_orig')->setParameter(':preview_orig', $this->media->preview_orig); } if (!$this->op && $this->media->preview_reply === null) { $query->set('preview_reply', ':preview_orig')->setParameter(':preview_orig', $this->media->preview_orig); } $query->set('total', '(' . $media_sql . ')'); $query->where('media_id = :media_id')->setParameter(':media_id', $this->media->media_id)->execute(); } return $this; }
/** * Puts the table in readily available variables */ public function preload() { $this->profiler->log('Radix::preload Start'); try { $result = Cache::item('foolfuuka.model.radix.preload')->get(); } catch (\OutOfBoundsException $e) { $result = $this->dc->qb()->select('*')->from($this->dc->p('boards'), 'b')->orderBy('shortname', 'ASC')->execute()->fetchAll(); Cache::item('foolfuuka.model.radix.preload')->set($result, 900); } if (!is_array($result) || empty($result)) { $this->preloaded_radixes = []; return false; } $result_object = []; foreach ($result as $item) { // don't process hidden boards if (!$this->getAuth()->hasAccess('boards.see_hidden') && $item['hidden'] == 1) { continue; } $structure = $this->structure($item); $result_object[$item['id']] = new Radix($this->getContext(), $this); // set the plain database data as keys foreach ($item as $k => $i) { $result_object[$item['id']]->{$k} = $i; // we set it also in the values so we can just use it from there as commodity $result_object[$item['id']]->setValue($k, $i); } // url values for commodity $result_object[$item['id']]->setValue('formatted_title', $item['name'] ? '/' . $item['shortname'] . '/ - ' . $item['name'] : '/' . $item['shortname'] . '/'); // load the basic value of the preferences foreach ($structure as $key => $arr) { if (!isset($result_object[$item['id']]->{$key}) && isset($arr['boards_preferences'])) { $result_object[$item['id']]->setValue($key, $this->config->get('foolz/foolfuuka', 'package', 'preferences.radix.' . $key, false)); } foreach (['sub', 'sub_inverse'] as $sub) { if (isset($arr[$sub])) { foreach ($arr[$sub] as $k => $a) { if (!isset($result_object[$item['id']]->{$k}) && isset($a['boards_preferences'])) { $result_object[$item['id']]->setValue($k, $this->config->get('foolz/foolfuuka', 'package', 'preferences.radix.' . $k, false)); } } } } } } // load the preferences from the board_preferences table $this->profiler->log('Radix::load_preferences Start'); try { $preferences = Cache::item('foolfuuka.model.radix.load_preferences')->get(); } catch (\OutOfBoundsException $e) { $preferences = $this->dc->qb()->select('*')->from($this->dc->p('boards_preferences'), 'p')->execute()->fetchAll(); Cache::item('foolfuuka.model.radix.load_preferences')->set($preferences, 900); } foreach ($preferences as $value) { // in case of leftover values, it would try instantiating a new stdClass and that would trigger error if (isset($result_object[$value['board_id']])) { $result_object[$value['board_id']]->setValue($value['name'], $value['value']); } } $this->preloaded_radixes = $result_object; $this->profiler->logMem('Radix $this->preloaded_radixes', $this->preloaded_radixes); $this->profiler->log('Radix::load_preferences End'); // take them all and then filter/do whatever (we use this to split the boards through various subdomains) // only public is affected! admins and mods will see all boards at all the time $this->preloaded_radixes = \Foolz\Plugin\Hook::forge('Foolz\\Foolfuuka\\Model\\Radix::preload.result.public')->setObject($this)->setParam('preloaded_radixes', $this->preloaded_radixes)->execute()->get($this->preloaded_radixes); $this->profiler->log('Radix::preload End'); $this->profiler->logMem('Radix $this->preloaded_radixes w/ preferences', $this->preloaded_radixes); }
/** * Returns the Comment by doc_id or the first Comment found with a matching media_id * * @return null|\Foolz\FoolFuuka\Model\CommentBulk * @throws \Foolz\FoolFuuka\Model\ReportMediaNotFoundException * @throws \Foolz\FoolFuuka\Model\ReportCommentNotFoundException */ public function p_getComment() { if ($this->media_id !== null) { // custom "get the first doc_id with the media" $doc_id_res = $this->dc->qb()->select('doc_id')->from($this->radix_coll->getById($this->board_id)->getTable(), 'a')->where('media_id = :media_id')->orderBy('timestamp', 'desc')->setParameter('media_id', $this->media_id)->execute()->fetch(); if ($doc_id_res !== null) { $this->doc_id = $doc_id_res->doc_id; } else { $this->report_coll->delete($this->id); return null; } } try { $comments = Board::forge($this->getContext())->getPost()->setRadix($this->radix)->setOptions('doc_id', $this->doc_id)->getComments(); $this->comment = current($comments); } catch (BoardException $e) { $this->report_coll->delete($this->id); return null; } return $this->comment; }
public function log($type, $data) { $this->dc->getConnection()->insert($this->dc->p('audit_log'), ['timestamp' => time(), 'user' => $this->getAuth()->getUser()->getId(), 'type' => $type, 'data' => json_encode($data)]); }
/** * Deletes a Report * * @param int $id The ID of the Report * * @throws \Foolz\FoolFuuka\Model\ReportNotFoundException */ public function p_delete($id) { $this->dc->qb()->delete($this->dc->p('reports'))->where('id = :id')->setParameter(':id', $id)->execute(); $this->clearCache(); }
public function action_database_setup() { if ($this->getPost()) { $validator = new Validator(); $validator->add('hostname', _i('Database Hostname'), [new Trim(), new Assert\NotBlank()])->add('prefix', _i('Table Prefix'), [new Trim()])->add('username', _i('Username'), [new Trim(), new Assert\NotBlank()])->add('database', _i('Database name'), [new Trim(), new Assert\NotBlank()]); $validator->validate($this->getPost()); if (!$validator->getViolations()->count()) { $input = $validator->getFinalValues(); $input['password'] = $this->getPost('password'); $input['type'] = $this->getPost('type'); if ($this->install->check_database($input)) { $this->install->setup_database($input); $dc = new DoctrineConnection($this->getContext(), $this->config); $sm = SchemaManager::forge($dc->getConnection(), $dc->getPrefix()); Schema::load($this->getContext(), $sm); $sm->commit(); $this->install->create_salts(); return new RedirectResponse($this->uri->create('install/create_admin')); } else { $this->notices->set('warning', _i('Connection to specified database failed. Please check your connection details again.')); } } else { $this->notices->set('warning', $validator->getViolations()->getText()); } } $this->process('database_setup'); $this->param_manager->setParam('method_title', _i('Database Setup')); $this->builder->createPartial('body', 'install/database_setup'); return new Response($this->builder->build()); }