Site select element¶
Add a site picker to your own forms, and limit an entity reference to the content of one site.
Entity forms of site content need no code: Sites adds their Sites section
through Form decorator
(SitesSelectionContentEntityFormDecorator,
SitesSelectionEntityFormDecorator). The elements on this page are for forms
you build yourself.
site_select¶
Drupal\sites\Element\SiteSelect is core's select with sites as options.
Without #options, it offers the sites the current user may work on, from
UserSiteAccessInterface::getSiteOptions() (service sites.user_access),
sorted by label.
| Property | Default | Meaning |
|---|---|---|
#operation |
manage |
What the user may do with content on the site: add, remove, or manage (either). |
#entity |
NULL |
The entity the operation is about. Sites that do not accept its bundle are left out. |
#context |
[] |
entity_type_id and bundle, when there is no entity yet. |
#excluded_sites |
[] |
Site IDs to leave out. |
The other properties are core's select ones, like #multiple,
#empty_option and #required. The value is a site ID, or an array of site
IDs with #multiple.
$form['site'] = [
'#type' => 'site_select',
'#title' => $this->t('Site'),
'#operation' => 'add',
'#context' => ['entity_type_id' => 'node', 'bundle' => 'article'],
'#required' => TRUE,
];
The options authorize nothing: a client can post any site ID. Check the
submitted site before you write, as Drupal\sites\Form\AddContentToSite
does:
$site = $this->siteManager->getSite((string) $form_state->getValue('site'));
if (!$site instanceof SiteWithContentInterface
|| !$this->contentAssignment->addAccess($entity, $site, $this->currentUser())->isAllowed()) {
throw new AccessDeniedHttpException();
}
$this->membership->add($site->id(), $entity);
$this->contentAssignment is the sites.content_assignment service,
$this->membership is sites.membership.
sites_selection¶
Drupal\sites\Element\SitesSelection is the composite behind the Sites
section: a canonical site and further sites. Its value lists every site,
the canonical one included:
$value = [
'sites' => ['acme', 'globex'],
'canonical_site' => 'acme',
];
| Property | Default | Meaning |
|---|---|---|
#mode |
inline |
inline renders the canonical site, then the further sites. section renders the collapsible section with the dialog button of entity forms; only the Sites form decorators read its value. |
#entity |
NULL |
The entity the options are computed for. Without one, #entity_type_id, #bundle and #entity_id name it. |
#options |
computed | Site ID => label. Computed with getSiteOptions() when left out. |
#canonical_locked |
NULL |
NULL locks a stored canonical site, a site ID fixes it, FALSE keeps it editable. |
#canonical_required |
FALSE |
Without it, an empty canonical site becomes the first selected site. |
#canonical_title, #canonical_description, #select_title, #select_description |
Labels of the two parts. |
A locked canonical site changes only through the Change site operation of the content, because the canonical site decides whose permissions gate the entity form. Sites the user cannot offer stay in the value unchanged. Content of a Single site type (Content on sites) gets one select and no separate canonical site.
Apply the value with SiteContentAssignmentInterface::reconcile(): it adds
and removes the memberships the account may change, and sets the canonical
site only for content that has none.
$form['sites_selection'] = [
'#type' => 'sites_selection',
'#entity' => $entity,
'#default_value' => SitesSelection::membershipSeed($entity),
];
// In the submit handler, after the entity is saved:
$this->contentAssignment->reconcile(
$entity,
SitesSelection::normalizeSelection((array) $form_state->getValue('sites_selection')),
$this->currentUser(),
$is_new,
);
Drupal\sites_webform\EntitySettings\WebformEntitySettingsSitesForm is a
complete example.
A part of an entity form that depends on the chosen sites, like a per-site
alias widget, calls SitesSelection::registerDependent($subtree, $key) and
builds from SitesSelection::currentSelection($form_state, $entity). The
Sites dialog then renders it again when the user applies a new selection.
Tagify widget¶
With Sites Tagify enabled, every
site_select renders as site_select_tagify, and the further sites of
sites_selection as a select_tagify. Your form keeps asking for
site_select, and the value keeps the shape of a select. Sites Tagify adds:
#add_alland#remove_allonsite_select:TRUEor a translated label for links that select or clear all sites. A plainselectignores them, so set them whether or not the module is on.#tagify_match_limitonsites_selection: how many matches the widget suggests while typing. Without it, the Fallback match limit on/admin/sites/configuration/tagifyapplies;0shows all.
Entity reference selection per site¶
Two selection handlers limit what an entity reference offers:
| Handler | Settings | Offers |
|---|---|---|
site (SiteContentSelection) |
site_id, operation |
The content of the site. With operation add, the content the site does not hold yet; with any, all content. |
site_reference (SiteReferenceSelection) |
site_id (default: the active site), sites_filter_mode |
The content of the site, when the mode (enabled, default, disabled) filters. |
Both handlers build their query in the target type's own core handler, so
its rules stay (unpublished content, blocked users, reusable blocks only). On
top, SitesReferenceHooks applies a read scope to every reference selection
in an HTTP request: items of the sites the account reads
(SiteEntityAccessInterface::participatedSites(), plus the current site on a
site host), memberless items only with a real global view unassigned
content, everything with a real global administer sites. Drush and other
CLI runs are not scoped. The site handler offers only the bundles the site
accepts and never the anonymous user; for users it also needs "Add existing
users to a site" on the target site. Use it in your own forms:
$form['page'] = [
'#type' => 'entity_autocomplete',
'#target_type' => 'node',
'#selection_handler' => 'site',
'#selection_settings' => ['site_id' => $site->id(), 'operation' => 'add'],
];
A field gets site_reference from the Filter by site option on its
settings form, described in
Blocks and views. The mode
default follows the site's filter_references setting, and so does a field
with a core default:* handler, unless it references users. On a site's
hostname, a field that filters also hides references to other sites' content
when it is displayed.