123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570 |
- <?php
- namespace Drupal\domain\Entity;
- use Drupal\Core\Config\ConfigValueException;
- use Drupal\Core\Config\Entity\ConfigEntityBase;
- use Drupal\Core\Entity\EntityStorageInterface;
- use Drupal\Core\Link;
- use Drupal\Core\Url;
- use Drupal\Core\StringTranslation\StringTranslationTrait;
- use Drupal\domain\DomainInterface;
- use Drupal\domain\DomainNegotiator;
- /**
- * Defines the domain entity.
- *
- * @ConfigEntityType(
- * id = "domain",
- * label = @Translation("Domain record"),
- * module = "domain",
- * handlers = {
- * "storage" = "Drupal\domain\DomainStorage",
- * "access" = "Drupal\domain\DomainAccessControlHandler",
- * "list_builder" = "Drupal\domain\DomainListBuilder",
- * "form" = {
- * "default" = "Drupal\domain\DomainForm",
- * "edit" = "Drupal\domain\DomainForm",
- * "delete" = "Drupal\domain\Form\DomainDeleteForm"
- * }
- * },
- * config_prefix = "record",
- * admin_permission = "administer domains",
- * entity_keys = {
- * "id" = "id",
- * "domain_id" = "domain_id",
- * "label" = "name",
- * "uuid" = "uuid",
- * "status" = "status",
- * "weight" = "weight"
- * },
- * links = {
- * "delete-form" = "/admin/config/domain/delete/{domain}",
- * "edit-form" = "/admin/config/domain/edit/{domain}",
- * "collection" = "/admin/config/domain",
- * },
- * uri_callback = "domain_uri",
- * config_export = {
- * "id",
- * "domain_id",
- * "hostname",
- * "name",
- * "scheme",
- * "status",
- * "weight",
- * "is_default",
- * }
- * )
- */
- class Domain extends ConfigEntityBase implements DomainInterface {
- use StringTranslationTrait;
- /**
- * The ID of the domain entity.
- *
- * @var string
- */
- protected $id;
- /**
- * The domain record ID.
- *
- * @var int
- */
- protected $domain_id;
- /**
- * The domain list name (e.g. Drupal).
- *
- * @var string
- */
- protected $name;
- /**
- * The domain hostname (e.g. example.com).
- *
- * @var string
- */
- protected $hostname;
- /**
- * The domain record sort order.
- *
- * @var int
- */
- protected $weight;
- /**
- * Indicates the default domain.
- *
- * @var bool
- */
- protected $is_default = FALSE;
- /**
- * The domain record protocol (e.g. http://).
- *
- * @var string
- */
- protected $scheme;
- /**
- * The domain record base path, a calculated value.
- *
- * @var string
- */
- protected $path;
- /**
- * The domain record current url, a calculated value.
- *
- * @var string
- */
- protected $url;
- /**
- * The domain record http response test (e.g. 200), a calculated value.
- *
- * @var int
- */
- protected $response = NULL;
- /**
- * The redirect method to use, if needed.
- *
- * @var int|null
- */
- protected $redirect = NULL;
- /**
- * The type of match returned by the negotiator.
- *
- * @var int
- */
- protected $matchType;
- /**
- * The canonical hostname for the domain.
- *
- * @var string
- */
- protected $canonical;
- /**
- * {@inheritdoc}
- */
- public static function preCreate(EntityStorageInterface $storage_controller, array &$values) {
- parent::preCreate($storage_controller, $values);
- $domain_storage = \Drupal::entityTypeManager()->getStorage('domain');
- $default = $domain_storage->loadDefaultId();
- $count = $storage_controller->getQuery()->count()->execute();
- $values += [
- 'scheme' => empty($GLOBALS['is_https']) ? 'http' : 'https',
- 'status' => 1,
- 'weight' => $count + 1,
- 'is_default' => (int) empty($default),
- ];
- // Note that we have not created a domain_id, which is only used for
- // node access control and will be added on save.
- }
- /**
- * {@inheritdoc}
- */
- public function isActive() {
- $negotiator = \Drupal::service('domain.negotiator');
- /** @var self $domain */
- $domain = $negotiator->getActiveDomain();
- if (empty($domain)) {
- return FALSE;
- }
- return ($this->id() == $domain->id());
- }
- /**
- * {@inheritdoc}
- */
- public function addProperty($name, $value) {
- if (!isset($this->{$name})) {
- $this->{$name} = $value;
- }
- }
- /**
- * {@inheritdoc}
- */
- public function isDefault() {
- return (bool) $this->is_default;
- }
- /**
- * {@inheritdoc}
- */
- public function isHttps() {
- return (bool) ($this->getScheme(FALSE) == 'https');
- }
- /**
- * {@inheritdoc}
- */
- public function saveDefault() {
- if (!$this->isDefault()) {
- // Swap the current default.
- /** @var self $default */
- if ($default = \Drupal::entityTypeManager()->getStorage('domain')->loadDefaultDomain()) {
- $default->is_default = FALSE;
- $default->setHostname($default->getCanonical());
- $default->save();
- }
- // Save the new default.
- $this->is_default = TRUE;
- $this->setHostname($this->getCanonical());
- $this->save();
- }
- else {
- \Drupal::messenger()->addMessage($this->t('The selected domain is already the default.'), 'warning');
- }
- }
- /**
- * {@inheritdoc}
- */
- public function enable() {
- $this->setStatus(TRUE);
- $this->setHostname($this->getCanonical());
- $this->save();
- }
- /**
- * {@inheritdoc}
- */
- public function disable() {
- if (!$this->isDefault()) {
- $this->setStatus(FALSE);
- $this->setHostname($this->getCanonical());
- $this->save();
- }
- else {
- \Drupal::messenger()->addMessage($this->t('The default domain cannot be disabled.'), 'warning');
- }
- }
- /**
- * {@inheritdoc}
- */
- public function saveProperty($name, $value) {
- if (isset($this->{$name})) {
- $this->{$name} = $value;
- $this->setHostname($this->getCanonical());
- $this->save();
- \Drupal::messenger()->addMessage($this->t('The @key attribute was set to @value for domain @hostname.', [
- '@key' => $name,
- '@value' => $value,
- '@hostname' => $this->hostname,
- ]));
- }
- else {
- \Drupal::messenger()->addMessage($this->t('The @key attribute does not exist.', ['@key' => $name]));
- }
- }
- /**
- * {@inheritdoc}
- */
- public function setPath() {
- global $base_path;
- $this->path = $this->getScheme() . $this->getHostname() . ($base_path ?: '/');
- }
- /**
- * {@inheritdoc}
- */
- public function setUrl() {
- $request = \Drupal::request();
- $uri = $request ? $request->getRequestUri() : '/';
- $this->url = $this->getScheme() . $this->getHostname() . $uri;
- }
- /**
- * {@inheritdoc}
- */
- public function getPath() {
- if (!isset($this->path)) {
- $this->setPath();
- }
- return $this->path;
- }
- /**
- * Returns the raw path of the domain object, without the base url.
- */
- public function getRawPath() {
- return $this->getScheme() . $this->getHostname();
- }
- /**
- * Builds a link from a known internal path.
- *
- * @param string $path
- * A Drupal-formatted internal path, starting with /. Note that it is the
- * caller's responsibility to handle the base_path().
- *
- * @return string
- * The built link.
- */
- public function buildUrl($path) {
- return $this->getRawPath() . $path;
- }
- /**
- * {@inheritdoc}
- */
- public function getUrl() {
- if (!isset($this->url)) {
- $this->setUrl();
- }
- return $this->url;
- }
- /**
- * {@inheritdoc}
- */
- public function preSave(EntityStorageInterface $storage) {
- parent::preSave($storage);
- // Sets the default domain properly.
- /** @var self $default */
- $default = $storage->loadDefaultDomain();
- if (!$default) {
- $this->is_default = TRUE;
- }
- elseif ($this->is_default && $default->getDomainId() != $this->getDomainId()) {
- // Swap the current default.
- $default->is_default = FALSE;
- $default->save();
- }
- // Ensures we have a proper domain_id.
- if ($this->isNew()) {
- $this->createDomainId();
- }
- // Prevent duplicate hostname.
- $hostname = $this->getHostname();
- // Do not use domain loader because it may change hostname.
- $existing = $storage->loadByProperties(['hostname' => $hostname]);
- $existing = reset($existing);
- if ($existing && $this->getDomainId() != $existing->getDomainId()) {
- throw new ConfigValueException("The hostname ($hostname) is already registered.");
- }
- }
- /**
- * {@inheritdoc}
- */
- public function postSave(EntityStorageInterface $storage, $update = TRUE) {
- parent::postSave($storage, $update);
- // Invalidate cache tags relevant to domains.
- \Drupal::service('cache_tags.invalidator')->invalidateTags(['rendered', 'url.site']);
- }
- /**
- * {@inheritdoc}
- */
- public static function postDelete(EntityStorageInterface $storage, array $entities) {
- parent::postDelete($storage, $entities);
- foreach ($entities as $entity) {
- $actions = $storage->loadMultiple([
- 'domain_default_action.' . $entity->id(),
- 'domain_delete_action.' . $entity->id(),
- 'domain_disable_action.' . $entity->id(),
- 'domain_enable_action.' . $entity->id(),
- ]);
- foreach ($actions as $action) {
- $action->delete();
- }
- }
- // Invalidate cache tags relevant to domains.
- \Drupal::service('cache_tags.invalidator')->invalidateTags(['rendered', 'url.site']);
- }
- /**
- * {@inheritdoc}
- */
- public function createDomainId() {
- // We cannot reliably use sequences (1, 2, 3) because those can be different
- // across environments. Instead, we use the crc32 hash function to create a
- // unique numeric id for each domain. In some systems (Windows?) we have
- // reports of crc32 returning a negative number. Issue #2794047.
- // If we don't use hash(), then crc32() returns different results for 32-
- // and 64-bit systems. On 32-bit systems, the number returned may also be
- // too large for PHP.
- // See #2908236.
- $id = hash('crc32', $this->id());
- $id = abs(hexdec(substr($id, 0, -2)));
- $this->createNumericId($id);
- }
- /**
- * Creates a unique numeric id for use in the {node_access} table.
- *
- * @param int $id
- * An integer to use as the numeric id.
- */
- public function createNumericId($id) {
- // Ensure that this value is unique.
- $storage = \Drupal::entityTypeManager()->getStorage('domain');
- $result = $storage->loadByProperties(['domain_id' => $id]);
- if (empty($result)) {
- $this->domain_id = $id;
- }
- else {
- $id++;
- $this->createNumericId($id);
- }
- }
- /**
- * {@inheritdoc}
- */
- public function getScheme($add_suffix = TRUE) {
- $scheme = $this->scheme;
- if ($scheme == 'variable') {
- $scheme = \Drupal::entityTypeManager()->getStorage('domain')->getDefaultScheme();
- }
- elseif ($scheme != 'https') {
- $scheme = 'http';
- }
- $scheme .= ($add_suffix) ? '://' : '';
- return $scheme;
- }
- /**
- * {@inheritdoc}
- */
- public function getRawScheme() {
- return $this->scheme;
- }
- /**
- * {@inheritdoc}
- */
- public function getResponse() {
- if (empty($this->response)) {
- $validator = \Drupal::service('domain.validator');
- $validator->checkResponse($this);
- }
- return $this->response;
- }
- /**
- * {@inheritdoc}
- */
- public function setResponse($response) {
- $this->response = $response;
- }
- /**
- * {@inheritdoc}
- */
- public function getLink($current_path = TRUE) {
- $options = ['absolute' => TRUE, 'https' => $this->isHttps()];
- if ($current_path) {
- $url = Url::fromUri($this->getUrl(), $options);
- }
- else {
- $url = Url::fromUri($this->getPath(), $options);
- }
- return Link::fromTextAndUrl($this->getCanonical(), $url)->toString();
- }
- /**
- * {@inheritdoc}
- */
- public function getRedirect() {
- return $this->redirect;
- }
- /**
- * {@inheritdoc}
- */
- public function setRedirect($code = 302) {
- $this->redirect = $code;
- }
- /**
- * {@inheritdoc}
- */
- public function getHostname() {
- return $this->hostname;
- }
- /**
- * {@inheritdoc}
- */
- public function setHostname($hostname) {
- $this->hostname = $hostname;
- }
- /**
- * {@inheritdoc}
- */
- public function getDomainId() {
- return $this->domain_id;
- }
- /**
- * {@inheritdoc}
- */
- public function getWeight() {
- return $this->weight;
- }
- /**
- * {@inheritdoc}
- */
- public function setMatchType($match_type = DomainNegotiator::DOMAIN_MATCH_EXACT) {
- $this->matchType = $match_type;
- }
- /**
- * {@inheritdoc}
- */
- public function getMatchType() {
- return $this->matchType;
- }
- /**
- * {@inheritdoc}
- */
- public function getPort() {
- $ports = explode(':', $this->getHostname());
- if (isset($ports[1])) {
- return ':' . $ports[1];
- }
- return '';
- }
- /**
- * {@inheritdoc}
- */
- public function setCanonical($hostname = NULL) {
- if (is_null($hostname)) {
- $this->canonical = $this->getHostname();
- }
- else {
- $this->canonical = $hostname;
- }
- }
- /**
- * {@inheritdoc}
- */
- public function getCanonical() {
- if (empty($this->canonical)) {
- $this->setCanonical();
- }
- return $this->canonical;
- }
- }
|