public function __construct(Context $context) { parent::__construct($context); $this->config = $context->getService('config'); $config = $this->config->get('foolz/foolframe', 'swiftmailer'); switch ($config['transport']) { case 'smtp': $transport = Swift_SmtpTransport::newInstance()->setHost($config['host'])->setPort($config['port'])->setUsername($config['username'])->setPassword($config['password'])->setEncryption($config['encryption'])->setAuthMode('login'); break; default: $transport = Swift_SendmailTransport::newInstance(); } $this->mailer = Swift_Mailer::newInstance($transport); }
/** * Non-dynamic sidebar array. * Permissions are set inside * * @return array sidebar array */ private function getSidebarValues() { $sidebar = []; // load sidebars from modules and leave FoolFrame sidebar on bottom foreach ($this->config->get('foolz/foolframe', 'config', 'modules.installed') as $module) { $module_sidebar = $this->config->get($module['namespace'], 'sidebar'); if (is_array($module_sidebar)) { $sidebar = array_merge($module_sidebar['sidebar'], $sidebar); } } return $sidebar; }
public function instantiate() { $this->loader = new Loader(); // store all the relevant data from the modules foreach ($this->config->get('foolz/foolframe', 'config', 'modules.installed') as $module) { $dir = $this->config->get($module['namespace'], 'package', 'directories.plugins'); $this->loader->addDir($dir); $dir = VAPPPATH . $module['namespace'] . '/plugins'; $this->loader->addDir($dir); } // public dir for plugins $this->loader->addDir(VAPPPATH . 'foolz/foolframe/plugins/'); foreach ($this->getEnabled() as $enabled) { try { $plugin = $this->loader->get($enabled['slug']); $plugin->bootstrap(); // we could use execute() but we want to inject more in the call \Foolz\Plugin\Hook::forge('Foolz\\Plugin\\Plugin::execute#' . $plugin->getConfig('name'))->setObject($plugin)->setParam('context', $this->getContext())->execute(); $this->loader->get($enabled['slug'])->enabled = true; } catch (\OutOfBoundsException $e) { } } }
public function before() { $this->config = $this->getContext()->getService('config'); $this->preferences = $this->getContext()->getService('preferences'); $this->uri = $this->getContext()->getService('uri'); $this->profiler = $this->getContext()->getService('profiler'); $this->radix_coll = $this->getContext()->getService('foolfuuka.radix_collection'); $this->media_factory = $this->getContext()->getService('foolfuuka.media_factory'); $this->comment_factory = $this->getContext()->getService('foolfuuka.comment_factory'); // this has already been forged in the foolfuuka bootstrap $theme_instance = \Foolz\Theme\Loader::forge('foolfuuka'); try { $theme_name = $this->getQuery('theme', $this->getCookie('theme')) ?: $this->preferences->get('foolfuuka.theme.default'); $theme_name_exploded = explode('/', $theme_name); if (count($theme_name_exploded) >= 2) { $theme_name = $theme_name_exploded[0] . '/' . $theme_name_exploded[1]; } $theme = $theme_instance->get($theme_name); if (!isset($theme->enabled) || !$theme->enabled) { throw new \OutOfBoundsException(); } $this->theme = $theme; } catch (\OutOfBoundsException $e) { $theme_name = 'foolz/foolfuuka-theme-foolfuuka'; $this->theme = $theme_instance->get('foolz/foolfuuka-theme-foolfuuka'); } // TODO this is currently bootstrapped in the foolfuuka bootstrap because we need it running before the router. //$this->theme->bootstrap(); $this->builder = $this->theme->createBuilder(); $this->param_manager = $this->builder->getParamManager(); $this->builder->createLayout('chan'); if (count($theme_name_exploded) == 3) { try { $this->builder->setStyle($theme_name_exploded[2]); } catch (\OutOfBoundsException $e) { // just let it go with default on getStyle() } } $pass = $this->getCookie('reply_password', ''); $name = $this->getCookie('reply_name'); $email = $this->getCookie('reply_email'); // KEEP THIS IN SYNC WITH THE ONE IN THE POSTS ADMIN PANEL $to_bind = ['context' => $this->getContext(), 'request' => $this->getRequest(), 'user_name' => $name, 'user_email' => $email, 'user_pass' => $pass, 'disable_headers' => false, 'is_page' => false, 'is_thread' => false, 'is_last50' => false, 'order' => false, 'modifiers' => [], 'backend_vars' => ['user_name' => $name, 'user_email' => $email, 'user_pass' => $pass, 'site_url' => $this->uri->base(), 'default_url' => $this->uri->base(), 'archive_url' => $this->uri->base(), 'system_url' => $this->uri->base(), 'api_url' => $this->uri->base(), 'cookie_domain' => $this->config->get('foolz/foolframe', 'config', 'config.cookie_domain'), 'cookie_prefix' => $this->config->get('foolz/foolframe', 'config', 'config.cookie_prefix'), 'selected_theme' => $theme_name, 'csrf_token_key' => 'csrf_token', 'images' => ['banned_image' => $this->theme->getAssetManager()->getAssetLink('images/banned-image.png'), 'banned_image_width' => 150, 'banned_image_height' => 150, 'missing_image' => $this->theme->getAssetManager()->getAssetLink('images/missing-image.jpg'), 'missing_image_width' => 150, 'missing_image_height' => 150], 'gettext' => ['submit_state' => _i('Submitting'), 'thread_is_real_time' => _i('This thread is being displayed in real time.'), 'update_now' => _i('Update now'), 'ghost_mode' => _i('This thread has entered ghost mode. Your reply will be marked as a ghost post and will only affect the ghost index.')]]]; $this->param_manager->setParams($to_bind); $this->builder->createPartial('tools_modal', 'tools_modal'); $this->builder->createPartial('tools_search', 'tools_search'); $this->builder->createPartial('tools_advanced_search', 'advanced_search'); }
public function get($setting, $fallback = null, $show_empty_string = false) { if (!$this->loaded) { $this->load(); } if (isset($this->preferences[$setting]) && ($show_empty_string || $this->preferences[$setting] !== '')) { return $this->preferences[$setting]; } if ($fallback !== null) { return $fallback; } $segments = explode('.', $setting); $identifier = array_shift($segments); $query = implode('.', $segments); return $this->config->get($this->modules[$identifier]['namespace'], 'package', 'preferences.' . $query); }
/** * @param string $username * @param string $password * @param bool $ip_decimal * * @throws WrongUsernameOrPasswordException * @throws LimitExceededException */ public function authenticateWithUsernameAndPassword($username, $password, $ip_decimal = false) { if ($this->countAttempts($username) >= $this->config->get('foolz/foolframe', 'foolauth', 'attempts_to_lock')) { throw new LimitExceededException(); } $user = $this->dc->qb()->select('*')->from($this->dc->p('users'), 'l')->where('l.username = :username')->setParameters([':username' => $username])->execute()->fetch(); if (!$user) { throw new WrongUsernameOrPasswordException(); } if (!password_verify($password, $user['password'])) { $this->dc->getConnection()->insert($this->dc->p('user_login_attempts'), ['username' => $username, 'ip' => $ip_decimal ?: 0, 'time' => time()]); throw new WrongUsernameOrPasswordException(); } $this->resetAttempts($username); $this->user = new User($this->getContext(), $user); }
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'); }
/** * Process the secure tripcode * * @param string $plain the word to generate the secure tripcode from * @return string the processed secure tripcode */ protected function p_processSecureTripcode($plain) { return substr(base64_encode(sha1($plain . base64_decode($this->config->get('foolz/foolfuuka', 'config', 'comment.secure_tripcode_salt')), true)), 0, 11); }
/** * Get the full URL to the media, and in case switch between multiple CDNs * * @param boolean $thumbnail True if looking for a thumbnail, false for full media * * @return null|string Null if not available, string of the url if available */ public function getLink(Request $request, $thumbnail = false, $download = false) { $before = \Foolz\Plugin\Hook::forge('Foolz\\Foolfuuka\\Model\\Media::getLink.call.before.method.body')->setObject($this)->setParams(['thumbnail' => $thumbnail])->execute()->get(); if (!$before instanceof \Foolz\Plugin\Void) { return $before; } $image = null; if ($this->config->get('foolz/foolfuuka', 'config', 'media.filecheck') === true) { // locate the image if ($thumbnail && file_exists($this->getDir($thumbnail)) !== false) { if ($this->op == 1) { $image = $this->media->preview_op ?: $this->media->preview_reply; } else { $image = $this->media->preview_reply ?: $this->media->preview_op; } } // full image if (!$thumbnail && file_exists($this->getDir(false)) !== false) { $image = $this->media->media; } // fallback if we have the full image but not the thumbnail if ($thumbnail && $image === null && file_exists($this->getDir(false))) { $thumbnail = false; $image = $this->media->media; } } else { // locate the image if ($thumbnail) { if ($this->op == 1) { $image = $this->media->preview_op ?: $this->media->preview_reply; } else { $image = $this->media->preview_reply ?: $this->media->preview_op; } } else { if ($this->radix->archive && !$this->radix->getValue('archive_full_images')) { return null; } else { $image = $this->media->media; } } } if ($image !== null) { if ($download === true && $this->preferences->get('foolfuuka.boards.media_download_url')) { return $this->preferences->get('foolfuuka.boards.media_download_url') . '/' . $this->radix->shortname . '/' . ($thumbnail ? 'thumb' : 'image') . '/' . substr($image, 0, 4) . '/' . substr($image, 4, 2) . '/' . $image; } if ($request->isSecure() && $this->preferences->get('foolfuuka.boards.media_balancers_https')) { $balancers = $this->preferences->get('foolfuuka.boards.media_balancers_https'); } if (!isset($balancers) && $this->preferences->get('foolfuuka.boards.media_balancers')) { $balancers = $this->preferences->get('foolfuuka.boards.media_balancers'); } $media_cdn = []; if (isset($balancers)) { $media_cdn = array_filter(preg_split('/\\r\\n|\\r|\\n/', $balancers)); } if (!empty($media_cdn) && $this->media->media_id > 0) { return $media_cdn[$this->media->media_id % count($media_cdn)] . '/' . $this->radix->shortname . '/' . ($thumbnail ? 'thumb' : 'image') . '/' . substr($image, 0, 4) . '/' . substr($image, 4, 2) . '/' . $image; } return $this->preferences->get('foolfuuka.boards.url') . '/' . $this->radix->shortname . '/' . ($thumbnail ? 'thumb' : 'image') . '/' . substr($image, 0, 4) . '/' . substr($image, 4, 2) . '/' . $image; } if ($thumbnail && $this->media->media_status === 'normal') { $this->media->media_status = 'not-available'; } return null; }
/** * 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); }
/** * Checks that the CSRF token cookie and POST match * * @param Request $request * @return bool */ public function checkCsrfTokenGet(Request $request) { $cookie_name = $this->config->get('foolz/foolframe', 'config', 'config.cookie_prefix') . 'csrf_token'; return $request->cookies->get($cookie_name) !== null && $request->query->get('csrf_token') !== null && $request->cookies->get($cookie_name) === $request->query->get('csrf_token'); }
public function handleWeb(Request $request = null) { if ($request === null) { // create the request from the globals if we don't have custom input $request = Request::createFromGlobals(); } $this->container->register('uri', '\\Foolz\\FoolFrame\\Model\\Uri')->addArgument($this)->addArgument($request); $remember_me = $request->cookies->get($this->config->get('foolz/foolframe', 'config', 'config.cookie_prefix') . 'rememberme'); if (!count($this->child_contextes)) { // no app installed, we need to go to the install $this->loadInstallRoutes($this->route_collection); } else { $this->profiler->log('Start Auth rememberme'); /** @var Auth $auth */ $auth = $this->getService('auth'); if ($remember_me) { try { $auth->authenticateWithRememberMe($remember_me); } catch (WrongKeyException $e) { } } $this->profiler->log('Stop Auth rememberme'); Hook::forge('Foolz\\FoolFrame\\Model\\Context::handleWeb#obj.afterAuth')->setObject($this)->setParam('route_collection', $this->route_collection)->execute(); $this->profiler->log('Start Plugins handleWeb'); $this->getService('plugins')->handleWeb(); $this->profiler->log('Stop Plugins handleWeb'); $this->profiler->log('Start language setup'); $available_langs = $this->config->get('foolz/foolframe', 'package', 'preferences.lang.available'); $lang = $request->cookies->get('language'); if (!$lang || !array_key_exists($lang, $available_langs)) { $lang = $this->preferences->get('foolframe.lang.default'); } // HHVM does not support gettext if (function_exists('bindtextdomain')) { $locale = $lang . '.utf8'; putenv('LANG=' . $locale); putenv('LANGUAGE=' . $locale); setlocale(LC_ALL, $locale); bindtextdomain($lang, DOCROOT . 'assets/locale'); bind_textdomain_codeset($lang, 'UTF-8'); textdomain($lang); } $this->profiler->log('Stop language setup'); $this->profiler->log('Start routes setup'); // load the routes from the child contextes first Hook::forge('Foolz\\FoolFrame\\Model\\Context::handleWeb#obj.routing')->setObject($this)->setParam('route_collection', $this->route_collection)->execute(); foreach ($this->child_contextes as $context) { $context->handleWeb($request); $context->loadRoutes($this->route_collection); } $this->profiler->log('Stop routes setup'); $this->profiler->log('Start routes load'); $this->loadRoutes($this->route_collection); $this->profiler->log('Stop routes setup'); } // load the framework routes Hook::forge('Foolz\\FoolFrame\\Model\\Context::handleWeb#obj.context')->setObject($this)->execute(); // this is the first time we know we have a request for sure // hooks that need the request to function must run here Hook::forge('Foolz\\FoolFrame\\Model\\Context::handleWeb#obj.request')->setObject($this)->setParam('request', $request)->execute(); $this->container->register('notices', 'Foolz\\FoolFrame\\Model\\Notices')->addArgument($this)->addArgument($request); $this->profiler->log('Start HttpKernel loading'); $request_context = new RequestContext(); $request_context->fromRequest($request); $matcher = new UrlMatcher($this->route_collection, $request_context); $resolver = new ControllerResolver($this); $dispatcher = new EventDispatcher(); $dispatcher->addSubscriber(new RouterListener($matcher, null, $this->logger)); $dispatcher->addSubscriber(new ResponseListener('UTF-8')); $this->http_kernel = new HttpKernel($dispatcher, $resolver); $this->profiler->log('End HttpKernel loading'); // if this hook is used, it can override the entirety of the request handling $response = Hook::forge('Foolz\\FoolFrame\\Model\\Context::handleWeb#obj.response')->setObject($this)->setParam('request', $request)->execute()->get(false); if (!$response) { try { $this->profiler->log('Request handling start'); $response = $this->http_kernel->handle($request); $this->profiler->log('Request handling end'); } catch (NotFoundHttpException $e) { $controller_404 = $this->route_collection->get('404')->getDefault('_controller'); $request = new Request(); $request->attributes->add(['_controller' => $controller_404]); $response = $this->http_kernel->handle($request); } // stick the html of the profiler at the end if ($request->getRequestFormat() == 'html' && isset($auth) && $auth->hasAccess('maccess.admin')) { $content = explode('</body>', $response->getContent()); if (count($content) == 2) { $this->profiler->log('Execution end'); $response->setContent($content[0] . $this->profiler->getHtml() . '</body>' . $content[1]); } } } $this->getService('security')->updateCsrfToken($response); $response->send(); }
/** * Creates the tables for the board */ public function createTables() { $config = $this->config->get('foolz/foolframe', 'db', 'default'); $config['dbname'] = $this->preferences->get('foolfuuka.boards.db') ?: $config['dbname']; $config['prefix'] = $this->preferences->get("foolfuuka.boards.prefix"); $conn = new DoctrineConnection($this->getContext(), $config); $charset = 'utf8mb4'; $collate = 'utf8mb4_general_ci'; $sm = $conn->getConnection()->getSchemaManager(); $schema = $sm->createSchema(); // create the main table also in _deleted flavour foreach (['', '_deleted'] as $key) { if (!$schema->hasTable($this->getPrefix() . $this->shortname . $key)) { $table = $schema->createTable($this->getPrefix() . $this->shortname . $key); if ($conn->getConnection()->getDriver()->getName() == 'pdo_mysql') { $table->addOption('charset', $charset); $table->addOption('collate', $collate); } $table->addColumn('doc_id', 'integer', ['unsigned' => true, 'autoincrement' => true]); $table->addColumn('media_id', 'integer', ['unsigned' => true, 'default' => 0]); $table->addColumn('poster_ip', 'decimal', ['unsigned' => true, 'precision' => 39, 'scale' => 0, 'default' => 0]); $table->addColumn('num', 'integer', ['unsigned' => true]); $table->addColumn('subnum', 'integer', ['unsigned' => true]); $table->addColumn('thread_num', 'integer', ['unsigned' => true, 'default' => 0]); $table->addColumn('op', 'boolean', ['default' => 0]); $table->addColumn('timestamp', 'integer', ['unsigned' => true]); $table->addColumn('timestamp_expired', 'integer', ['unsigned' => true]); $table->addColumn('preview_orig', 'string', ['length' => 20, 'notnull' => false]); $table->addColumn('preview_w', 'smallint', ['unsigned' => true, 'default' => 0]); $table->addColumn('preview_h', 'smallint', ['unsigned' => true, 'default' => 0]); $table->addColumn('media_filename', 'text', ['length' => 65532, 'notnull' => false]); $table->addColumn('media_w', 'smallint', ['unsigned' => true, 'default' => 0]); $table->addColumn('media_h', 'smallint', ['unsigned' => true, 'default' => 0]); $table->addColumn('media_size', 'integer', ['unsigned' => true, 'default' => 0]); $table->addColumn('media_hash', 'string', ['length' => 25, 'notnull' => false]); $table->addColumn('media_orig', 'string', ['length' => 20, 'notnull' => false]); $table->addColumn('spoiler', 'boolean', ['default' => 0]); $table->addColumn('deleted', 'boolean', ['default' => 0]); $table->addColumn('capcode', 'string', ['length' => 1, 'default' => 'N']); $table->addColumn('email', 'string', ['length' => 100, 'notnull' => false]); $table->addColumn('name', 'string', ['length' => 100, 'notnull' => false]); $table->addColumn('trip', 'string', ['length' => 25, 'notnull' => false]); $table->addColumn('title', 'string', ['length' => 100, 'notnull' => false]); $table->addColumn('comment', 'text', ['length' => 65532, 'notnull' => false]); $table->addColumn('delpass', 'text', ['length' => 255, 'notnull' => false]); $table->addColumn('sticky', 'boolean', ['default' => 0]); $table->addColumn('locked', 'boolean', ['default' => 0]); $table->addColumn('poster_hash', 'string', ['length' => 8, 'notnull' => false]); $table->addColumn('poster_country', 'string', ['length' => 2, 'notnull' => false]); $table->addColumn('exif', 'text', ['length' => 65532, 'notnull' => false]); $table->setPrimaryKey(['doc_id']); $table->addUniqueIndex(['num', 'subnum'], $this->getIndex($key, 'num_subnum_index')); $table->addIndex(['thread_num', 'num', 'subnum'], $this->getIndex($key, 'thread_num_subnum_index')); $table->addIndex(['subnum'], $this->getIndex($key, 'subnum_index')); $table->addIndex(['op'], $this->getIndex($key, 'op_index')); $table->addIndex(['media_id'], $this->getIndex($key, 'media_id_index')); $table->addIndex(['media_hash'], $this->getIndex($key, 'media_hash_index')); $table->addIndex(['media_orig'], $this->getIndex($key, 'media_orig_index')); $table->addIndex(['name', 'trip'], $this->getIndex($key, 'name_trip_index')); $table->addIndex(['trip'], $this->getIndex($key, 'trip_index')); $table->addIndex(['email'], $this->getIndex($key, 'email_index')); $table->addIndex(['poster_ip'], $this->getIndex($key, 'poster_ip_index')); $table->addIndex(['timestamp'], $this->getIndex($key, 'timestamp_index')); } } if (!$schema->hasTable($this->getPrefix() . $this->shortname . '_threads')) { $table_threads = $schema->createTable($this->getPrefix() . $this->shortname . '_threads'); if ($conn->getConnection()->getDriver()->getName() == 'pdo_mysql') { $table_threads->addOption('charset', $charset); $table_threads->addOption('collate', $collate); } $table_threads->addColumn('thread_num', 'integer', ['unsigned' => true]); $table_threads->addColumn('time_op', 'integer', ['unsigned' => true]); $table_threads->addColumn('time_last', 'integer', ['unsigned' => true]); $table_threads->addColumn('time_bump', 'integer', ['unsigned' => true]); $table_threads->addColumn('time_ghost', 'integer', ['unsigned' => true, 'notnull' => false, 'default' => 'null']); $table_threads->addColumn('time_ghost_bump', 'integer', ['unsigned' => true, 'notnull' => false, 'default' => 'null']); $table_threads->addColumn('time_last_modified', 'integer', ['unsigned' => true]); $table_threads->addColumn('nreplies', 'integer', ['unsigned' => true, 'default' => 0]); $table_threads->addColumn('nimages', 'integer', ['unsigned' => true, 'default' => 0]); $table_threads->addColumn('sticky', 'boolean', ['default' => 0]); $table_threads->addColumn('locked', 'boolean', ['default' => 0]); $table_threads->setPrimaryKey(['thread_num']); $table_threads->addIndex(['locked'], $this->getIndex('_threads', 'locked_index')); $table_threads->addIndex(['time_op'], $this->getIndex('_threads', 'time_op_index')); $table_threads->addIndex(['time_bump'], $this->getIndex('_threads', 'time_bump_index')); $table_threads->addIndex(['time_ghost_bump'], $this->getIndex('_threads', 'time_ghost_bump_index')); $table_threads->addIndex(['sticky'], $this->getIndex('_threads', 'sticky_index')); $table_threads->addIndex(['sticky', 'time_bump'], $this->getIndex('_threads', 'sticky_time_bump_index')); $table_threads->addIndex(['sticky', 'time_ghost_bump'], $this->getIndex('_threads', 'sticky_time_ghost_bump_index')); $table_threads->addIndex(['sticky', 'thread_num'], $this->getIndex('_threads', 'sticky_thread_num_index')); } if (!$schema->hasTable($this->getPrefix() . $this->shortname . '_users')) { $table_users = $schema->createTable($this->getPrefix() . $this->shortname . '_users'); if ($conn->getConnection()->getDriver()->getName() == 'pdo_mysql') { $table_users->addOption('charset', $charset); $table_users->addOption('collate', $collate); } $table_users->addColumn('user_id', 'integer', ['unsigned' => true, 'autoincrement' => true]); $table_users->addColumn('name', 'string', ['length' => 100, 'default' => '']); $table_users->addColumn('trip', 'string', ['length' => 25, 'default' => '']); $table_users->addColumn('firstseen', 'integer', ['unsigned' => true]); $table_users->addColumn('postcount', 'integer', ['unsigned' => true]); $table_users->setPrimaryKey(['user_id']); $table_users->addUniqueIndex(['name', 'trip'], $this->getIndex('_users', 'name_trip_index')); $table_users->addIndex(['firstseen'], $this->getIndex('_users', 'firstseen_index')); $table_users->addIndex(['postcount'], $this->getIndex('_users', 'postcount_index')); } if (!$schema->hasTable($this->getPrefix() . $this->shortname . '_images')) { $table_images = $schema->createTable($this->getPrefix() . $this->shortname . '_images'); if ($conn->getConnection()->getDriver()->getName() == 'pdo_mysql') { $table_images->addOption('charset', 'utf8'); $table_images->addOption('collate', 'utf8_general_ci'); } $table_images->addColumn('media_id', 'integer', ['unsigned' => true, 'autoincrement' => true]); $table_images->addColumn('media_hash', 'string', ['length' => 25]); $table_images->addColumn('media', 'string', ['length' => 20, 'notnull' => false]); $table_images->addColumn('preview_op', 'string', ['length' => 20, 'notnull' => false]); $table_images->addColumn('preview_reply', 'string', ['length' => 20, 'notnull' => false]); $table_images->addColumn('total', 'integer', ['unsigned' => true, 'default' => 0]); $table_images->addColumn('banned', 'smallint', ['unsigned' => true, 'default' => 0]); $table_images->setPrimaryKey(['media_id']); $table_images->addUniqueIndex(['media_hash'], $this->getIndex('_images', 'media_hash_index')); $table_images->addIndex(['total'], $this->getIndex('_images', 'total_index')); $table_images->addIndex(['banned'], $this->getIndex('_images', 'banned_index')); } if (!$schema->hasTable($this->getPrefix() . $this->shortname . '_daily')) { $table_daily = $schema->createTable($this->getPrefix() . $this->shortname . '_daily'); if ($conn->getConnection()->getDriver()->getName() == 'pdo_mysql') { $table_daily->addOption('charset', 'utf8'); $table_daily->addOption('collate', 'utf8_general_ci'); } $table_daily->addColumn('day', 'integer', ['unsigned' => true]); $table_daily->addColumn('posts', 'integer', ['unsigned' => true]); $table_daily->addColumn('images', 'integer', ['unsigned' => true]); $table_daily->addColumn('sage', 'integer', ['unsigned' => true]); $table_daily->addColumn('anons', 'integer', ['unsigned' => true]); $table_daily->addColumn('trips', 'integer', ['unsigned' => true]); $table_daily->addColumn('names', 'integer', ['unsigned' => true]); $table_daily->setPrimaryKey(['day']); } $conn->getConnection()->beginTransaction(); foreach ($schema->getMigrateFromSql($sm->createSchema(), $sm->getDatabasePlatform()) as $query) { $conn->getConnection()->query($query); } $md5_array = $this->dc->qb()->select('md5')->from($this->dc->p('banned_md5'), 'm')->execute()->fetchAll(); // in a transaction multiple inserts are almost like a single one foreach ($md5_array as $item) { $conn->getConnection()->insert($this->getTable('_images'), ['md5' => $item['md5'], 'banned' => 1]); } $conn->getConnection()->commit(); }