public function tearDown() { $this->logger->enable(); $this->session->invalidate(); $this->events->restore(); $this->hooks->restore(); }
/** * Invalidate the query cache * * @return void */ protected function invalidateQueryCache() { if ($this->queryCache) { $this->queryCache->clear(); $this->logger->log("Query cache invalidated", \Elgg\Logger::INFO); } }
/** * @group IconService */ public function testCanCleanUpOnFailure() { $service = $this->createService(); $file = new \ElggFile(); $file->owner_guid = 1; $file->setFilename('400x300.gif'); $file->mimetype = 'image/gif'; $service->saveIconFromElggFile($this->entity, $file); $this->assertTrue($service->hasIcon($this->entity, 'master')); $this->assertTrue($service->hasIcon($this->entity, 'large')); $this->assertTrue($service->hasIcon($this->entity, 'medium')); $this->assertTrue($service->hasIcon($this->entity, 'small')); $this->assertTrue($service->hasIcon($this->entity, 'tiny')); $this->assertTrue($service->hasIcon($this->entity, 'topbar')); $this->logger->disable(); // This will fail for square icons because cropping coordinates are not square $service->saveIconFromElggFile($this->entity, $file, 'icon', ['x1' => 0, 'y1' => 0, 'x2' => 10, 'y2' => 20]); $this->logger->enable(); $this->assertFalse($service->hasIcon($this->entity, 'master')); $this->assertFalse($service->hasIcon($this->entity, 'large')); $this->assertFalse($service->hasIcon($this->entity, 'medium')); $this->assertFalse($service->hasIcon($this->entity, 'small')); $this->assertFalse($service->hasIcon($this->entity, 'tiny')); $this->assertFalse($service->hasIcon($this->entity, 'topbar')); }
/** * Invalidate the query cache * * @return void */ protected function invalidateQueryCache() { if ($this->query_cache) { $this->query_cache->clear(); if ($this->logger) { $this->logger->info("Query cache invalidated"); } } }
/** * Run any php upgrade scripts which are required * * @param int $version Version upgrading from. * @param bool $quiet Suppress errors. Don't use this. * * @return bool */ protected function upgradeCode($version, $quiet = false) { $version = (int) $version; $upgrade_path = elgg_get_engine_path() . '/lib/upgrades/'; $processed_upgrades = $this->getProcessedUpgrades(); $upgrade_files = $this->getUpgradeFiles($upgrade_path); if ($upgrade_files === false) { return false; } $upgrades = $this->getUnprocessedUpgrades($upgrade_files, $processed_upgrades); // Sort and execute sort($upgrades); foreach ($upgrades as $upgrade) { $upgrade_version = $this->getUpgradeFileVersion($upgrade); $success = true; if ($upgrade_version <= $version) { // skip upgrade files from before the installation version of Elgg // because the upgrade files from before the installation version aren't // added to the database. continue; } // hide all errors. if ($quiet) { // hide include errors as well as any exceptions that might happen try { if (!@self::includeCode("{$upgrade_path}/{$upgrade}")) { $success = false; $this->logger->error("Could not include {$upgrade_path}/{$upgrade}"); } } catch (\Exception $e) { $success = false; $this->logger->error($e->getMessage()); } } else { if (!self::includeCode("{$upgrade_path}/{$upgrade}")) { $success = false; $this->logger->error("Could not include {$upgrade_path}/{$upgrade}"); } } if ($success) { // don't set the version to a lower number in instances where an upgrade // has been merged from a lower version of Elgg if ($upgrade_version > $version) { $this->datalist->set('version', $upgrade_version); } // incrementally set upgrade so we know where to start if something fails. $this->setProcessedUpgrade($upgrade); } else { return false; } } return true; }
/** * Verify a datalist name is valid * * @param string $name Datalist name to be checked * * @return bool */ protected function validateName($name) { // Can't use elgg_strlen() because not available until core loaded. if (is_callable('mb_strlen')) { $is_valid = mb_strlen($name) <= 255; } else { $is_valid = strlen($name) <= 255; } if (!$is_valid) { $this->logger->error("The name length for configuration variables cannot be greater than 255"); } return $is_valid; }
/** * Set the value for a datalist element. * * Plugin authors should use elgg_save_config() and pass null for the site GUID. * * @warning Names should be selected so as not to collide with the names for the * site config. * * @warning Values set here are not available in $CONFIG until next page load. * * @param string $name The name of the datalist * @param string $value The new value * * @return bool * @access private */ function set($name, $value) { $name = trim($name); // cannot store anything longer than 255 characters in db, so catch before we set if (elgg_strlen($name) > 255) { $this->logger->error("The name length for configuration variables cannot be greater than 255"); return false; } $escaped_name = $this->db->sanitizeString($name); $escaped_value = $this->db->sanitizeString($value); $success = $this->db->insertData("INSERT INTO {$this->table}" . " SET name = '{$escaped_name}', value = '{$escaped_value}'" . " ON DUPLICATE KEY UPDATE value = '{$escaped_value}'"); $this->cache->put($name, $value); return $success !== false; }
/** * Includes view PHP or static file * * @param string $view The view name * @param array $vars Variables passed to view * @param string $viewtype The viewtype * @param bool $issue_missing_notice Log a notice if the view is missing * * @return string|false output generated by view file inclusion or false */ private function renderViewFile($view, array $vars, $viewtype, $issue_missing_notice) { $file = $this->findViewFile($view, $viewtype); if (!$file) { if ($issue_missing_notice) { $this->logger->log("{$viewtype}/{$view} view does not exist.", 'NOTICE'); } return false; } if (pathinfo($file, PATHINFO_EXTENSION) === 'php') { ob_start(); include $file; return ob_get_clean(); } return file_get_contents($file); }
/** * Get a user by GUID even if the entity is hidden or disabled * * @param int $guid User GUID. Default is logged in user * * @return ElggUser|false * @throws UserFetchFailureException * @access private */ public function getUserForPermissionsCheck($guid = 0) { if (!$guid) { return $this->session->getLoggedInUser(); } // need to ignore access and show hidden entities for potential hidden/disabled users $ia = $this->session->setIgnoreAccess(true); $show_hidden = access_show_hidden_entities(true); $user = $this->get($guid, 'user'); $this->session->setIgnoreAccess($ia); access_show_hidden_entities($show_hidden); if (!$user) { // requested to check access for a specific user_guid, but there is no user entity, so the caller // should cancel the check and return false $message = $this->translator->translate('UserFetchFailureException', array($guid)); $this->logger->warn($message); throw new UserFetchFailureException(); } return $user; }
/** * Returns a configuration array of icon sizes * * @param string $entity_type Entity type * @param string $entity_subtype Entity subtype * @param string $type The name of the icon. e.g., 'icon', 'cover_photo' * @return array * @throws InvalidParameterException */ public function getSizes($entity_type = null, $entity_subtype = null, $type = 'icon') { $sizes = []; if (!$type) { $type = 'icon'; } if ($type == 'icon') { $sizes = $this->config->get('icon_sizes'); } $params = ['type' => $type, 'entity_type' => $entity_type, 'entity_subtype' => $entity_subtype]; if ($entity_type) { $sizes = $this->hooks->trigger("entity:{$type}:sizes", $entity_type, $params, $sizes); } if (!is_array($sizes)) { throw new InvalidParameterException("The icon size configuration for image type '{$type}' " . "must be an associative array of image size names and their properties"); } if (empty($sizes)) { $this->logger->error("Failed to find size configuration for image of type '{$type}' for entity type " . "'{$entity_type}'. Use the 'entity:{$type}:sizes, {$entity_type}' hook to define the icon sizes"); } return $sizes; }
/** * Add or update a config setting. * * Plugin authors should use elgg_set_config(). * * If the config name already exists, it will be updated to the new value. * * @note Internal: These settings are stored in the dbprefix_config table and read * during system boot into $CONFIG. * * @note Internal: The value is serialized so we maintain type information. * * @param string $name The name of the configuration value * @param mixed $value Its value * * @return bool */ function set($name, $value) { $name = trim($name); // cannot store anything longer than 255 characters in db, so catch before we set if (elgg_strlen($name) > 255) { $this->logger->error("The name length for configuration variables cannot be greater than 255"); return false; } $this->CONFIG->{$name} = $value; $dbprefix = $this->CONFIG->dbprefix; $sql = "\n\t\t\tINSERT INTO {$dbprefix}config\n\t\t\tSET name = :name,\n\t\t\t\tvalue = :value\n\t\t\tON DUPLICATE KEY UPDATE value = :value\n\t\t"; $params = [':name' => $name, ':value' => serialize($value)]; $version = (int) $this->CONFIG->version; if (!empty($version) && $version < 2016102500) { // need to do this the old way as long as site_guid columns have not been dropped $sql = "\n\t\t\t\tINSERT INTO {$dbprefix}config\n\t\t\t\tSET name = :name,\n\t\t\t\t\tvalue = :value,\n\t\t\t\t\tsite_guid = :site_guid\n\t\t\t\tON DUPLICATE KEY UPDATE value = :value\n\t\t\t"; $params[':site_guid'] = 1; } $result = $this->db->insertData($sql, $params); $this->boot->invalidateCache(); return $result !== false; }
/** * Validates class and returns an instance of batch * * @param string $class The fully qualified class name * @return boolean True if valid upgrade */ public function getBatch($class) { if (!class_exists($class)) { $this->logger->error("Upgrade class {$class} was not found"); return false; } $batch = new $class(); if (!$batch instanceof Batch) { $this->logger->error("Upgrade class {$class} should implement Elgg\\Upgrade\\Batch"); return false; } $version = $batch::VERSION; // Version must be in format yyyymmddnn if (preg_match("/^[0-9]{10}\$/", $version) == 0) { $this->logger->error("Upgrade {$class} defines an invalid upgrade version: {$version}"); return false; } if (!$batch->isRequired()) { return false; } return $batch; }
/** * Unlocks mutex * * @param string $namespace Namespace to use for the database table * @return void */ public function unlock($namespace) { $this->assertNamespace($namespace); $this->db->deleteData("DROP TABLE {$this->db->getTablePrefix()}{$namespace}_lock"); $this->logger->notice("Mutex unlocked for {$namespace}."); }
/** * Send a notification to a subscriber * * @param NotificationEvent $event The notification event * @param int $guid The guid of the subscriber * @param string $method The notification method * @param array $params Default notification params * @return bool * @access private */ protected function sendNotification(NotificationEvent $event, $guid, $method, array $params = []) { $actor = $event->getActor(); $object = $event->getObject(); if ($event instanceof InstantNotificationEvent) { $recipient = $this->entities->get($guid); /* @var \ElggEntity $recipient */ $subject = elgg_extract('subject', $params, ''); $body = elgg_extract('body', $params, ''); $summary = elgg_extract('summary', $params, ''); } else { $recipient = $this->entities->get($guid, 'user'); /* @var \ElggUser $recipient */ if (!$recipient || $recipient->isBanned()) { return false; } if ($recipient->getGUID() == $event->getActorGUID()) { // Content creators should not be receiving subscription // notifications about their own content return false; } if (!$actor || !$object) { return false; } if ($object instanceof ElggEntity && !has_access_to_entity($object, $recipient)) { // Recipient does not have access to the notification object // The access level may have changed since the event was enqueued return false; } $subject = $this->getNotificationSubject($event, $recipient); $body = $this->getNotificationBody($event, $recipient); $summary = ''; $params['origin'] = Notification::ORIGIN_SUBSCRIPTIONS; } $language = $recipient->language; $params['event'] = $event; $params['method'] = $method; $params['sender'] = $actor; $params['recipient'] = $recipient; $params['language'] = $language; $params['object'] = $object; $params['action'] = $event->getAction(); $notification = new Notification($actor, $recipient, $language, $subject, $body, $summary, $params); $notification = $this->hooks->trigger('prepare', 'notification', $params, $notification); if (!$notification instanceof Notification) { throw new RuntimeException("'prepare','notification' hook must return an instance of " . Notification::class); } $type = 'notification:' . $event->getDescription(); if ($this->hooks->hasHandler('prepare', $type)) { $notification = $this->hooks->trigger('prepare', $type, $params, $notification); if (!$notification instanceof Notification) { throw new RuntimeException("'prepare','{$type}' hook must return an instance of " . Notification::class); } } else { // pre Elgg 1.9 notification message generation $notification = $this->getDeprecatedNotificationBody($notification, $event, $method); } $notification = $this->hooks->trigger('format', "notification:{$method}", [], $notification); if (!$notification instanceof Notification) { throw new RuntimeException("'format','notification:{$method}' hook must return an instance of " . Notification::class); } if ($this->hooks->hasHandler('send', "notification:{$method}")) { // return true to indicate the notification has been sent $params = array('notification' => $notification, 'event' => $event); $result = $this->hooks->trigger('send', "notification:{$method}", $params, false); if ($this->logger->getLevel() == Logger::INFO) { $logger_data = print_r((array) $notification->toObject(), true); if ($result) { $this->logger->info("Notification sent: " . $logger_data); } else { $this->logger->info("Notification was not sent: " . $logger_data); } } return $result; } else { // pre Elgg 1.9 notification handler $userGuid = $notification->getRecipientGUID(); $senderGuid = $notification->getSenderGUID(); $subject = $notification->subject; $body = $notification->body; $params = $notification->params; return (bool) _elgg_notify_user($userGuid, $senderGuid, $subject, $body, $params, array($method)); } }