Skip to content

Instantly share code, notes, and snippets.

@pglatz
Last active May 13, 2026 23:13
Show Gist options
  • Select an option

  • Save pglatz/b4758419d2b740c72b9df163604f13ed to your computer and use it in GitHub Desktop.

Select an option

Save pglatz/b4758419d2b740c72b9df163604f13ed to your computer and use it in GitHub Desktop.
code sample:- site utilities

Site

Support for site services and utilities.

CONTENTS OF THIS FILE

  • Introduction
  • Requirements
  • Installation
  • Configuration
  • Maintainers

INTRODUCTION

Site is custom module for various site issues.

REQUIREMENTS

This module requires no modules outside of Drupal core.

INSTALLATION

CONFIGURATION

No configuration is required.

MAINTAINERS

Current maintainers:

ls -R css README.md site.info.yml site.module templates js scss site.libraries.yml src

./css: site.css site.css.map

./js: site.js

./scss: site.scss

./src: Plugin

./src/Plugin: Block

./src/Plugin/Block: CopyrightBlock.php

./templates: copyright-block.html.twig

<?php
namespace Drupal\site\Plugin\Block;
use Drupal\Core\Block\BlockBase;
/**
* Provides a 'Copyright' Block.
*
* @Block(
* id = "copyright_block",
* admin_label = @Translation("Copyright Block")
* )
*/
class CopyrightBlock extends BlockBase {
public function build() {
$parts = explode('.', \Drupal::VERSION);
$major_version = $parts[0];
return [
'#theme' => 'copyright_block',
'#year' => date('Y'),
'#vers' => $major_version,
];
}
}
// Bootstrap functions, variables and mixins
@import "../../../../themes/contrib/bootstrap5/dist/bootstrap/5.3.8/scss/functions";
@import "../../../../themes/contrib/bootstrap5/dist/bootstrap/5.3.8/scss/variables";
@import "../../../../themes/contrib/bootstrap5/dist/bootstrap/5.3.8/scss/mixins";
// styles for site module
.home-img {
margin-right: 10px;
border-radius: 10px;
}
.region-header {
.navbar-brand {
padding-top: 10px;
img {
margin-left: 10px;
}
}
}
#block-johnbutton-site-branding {
background-color: #ddd;
}
.node--type-blog-post {
margin-bottom: 1.5rem;
padding-bottom: .5rem;
border-bottom: 2-x solid #eee;
img {
border-radius: 10px;
margin: 10px;
}
.node__links li {
padding: 0 1em 0 0;
}
}
// header
header {
#block-aidev-site-branding {
background-color: #dddddd;
padding: 0.5em;
}
.navbar {
background-color: #dddddd;
}
}
main {
margin-top: 1em;
}
// footer
footer {
padding: 0 !important;
}
footer .region-footer {
background-color: #dddddd;
padding: 1rem;
}
// copyright block
.region-copyright {
margin-top: 1em;
padding: 1rem;
background-color: #ddd;
#block-johnbutton-copyrightblock {
#footer-copyright {
display: flex;
flex-direction: row;
.c-vers {
margin-left: auto;
}
}
}
}
// media gallery grid
.photoswipe-gallery {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 1rem;
@include media-breakpoint-up(md) {
grid-template-columns: repeat(3, 1fr);
}
@include media-breakpoint-up(lg) {
grid-template-columns: repeat(4, 1fr);
}
// Force 2 columns in sidebar regions
.region-sidebar-first &,
.region-sidebar-second & {
grid-template-columns: repeat(2, 1fr);
}
.gallery-item {
display: flex;
flex-direction: column;
.gallery-item__name {
@include font-size($h6-font-size);
margin-bottom: 0.25rem;
}
.gallery-item__description {
@include font-size($small-font-size);
margin-bottom: 0.5rem;
p:last-child {
margin-bottom: 0;
}
}
img {
width: 100%;
height: auto;
display: block;
}
}
}
.media-gallery-layout--vertical {
h2
{
font-size: calc(.5rem + 0.9vw);
text-align: center;
}
}
// latest gallery photos block - vertical layout
.media-gallery-layout--vertical .block__content {
.view-gallery-link {
display: block;
width: fit-content;
margin: 0.5em auto 0;
padding-left: 8px;
padding-right: 8px;
}
.photoswipe-gallery {
display: flex;
flex-direction: column;
align-items: center;
gap: 0.5rem;
img {
border-radius: 10px;
}
.media-oembed-content {
border-radius: 10px;
overflow: hidden;
}
}
.media-gallery-latest-items-view-all {
display: block;
width: fit-content;
margin: 0.5rem auto 0;
}
}
// Override vertical layout to 2 columns in sidebars
.region-sidebar-first,
.region-sidebar-second {
.media-gallery-layout--vertical .block__content .photoswipe-gallery {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 0.5rem;
margin-top: 1em;
}
.media-gallery-latest-items-view-all {
display: none !important;
}
}
.region-sidebar-second {
margin-left: 10px;
border-left: 2px solid #ccc;
min-height: 100%;
}
// blog posts
.node--type-blog-post {
.node__submitted {
margin-bottom: 1rem;
font-style: italic;
}
.field--name-field-blog-tags .field__label {
font-weight: normal;
padding-top: 0.5rem;
border-top: 1px solid #ccc;
width: 20%;
}
}
// main nav
#block-aidev-main-menu-menu {
@include font-size($h3-font-size);
margin-bottom: 0;
}
// user menu (below copyright)
.region-user {
background-color: #dddddd;
padding: 0 1rem 1rem;
h2#block-aidev-useraccountmenu-menu {
display: none;
}
ul.nav {
display: inline;
list-style: none;
margin: 0;
padding: 0;
}
li.nav-item {
display: inline;
}
a.nav-link {
display: inline;
padding: 0;
}
li.nav-item:not(:last-child)::after {
content: " | ";
}
}
// contact form
#block-johnbutton-contactblock {
margin-top: 1em;
padding-top: 0.5em;
border-top: 1px solid #ddd;
h2 {
text-align: center;
cursor: pointer;
}
.block__content {
display: none;
}
&.contact-form-open .block__content {
display: block;
}
.form-actions a.cancel {
display: block;
margin-top: 0.5em;
margin-left: 0;
font-weight: 400;
line-height: 1.5;
text-align: center;
text-decoration: none;
cursor: pointer;
padding: $btn-padding-y $btn-padding-x;
font-size: $btn-font-size;
border-radius: $btn-border-radius;
color: #fff;
background-color: $secondary;
border: $btn-border-width solid $secondary;
width: fit-content;
&:hover {
background-color: shade-color($secondary, 20%);
border-color: shade-color($secondary, 25%);
color: #fff;
}
}
}
#edit-preview {
background-color: #42a877;
}
#edit-captcha .accordion-item {
// hide captcha instructions on remote
display: none;;
}
.captcha-type-challenge--recaptcha {
margin-left: 1em;
border: 1px solid #ddd;
padding: 0.5em;
#edit-captcha-response--description,
.captcha__description {
font-style: italic;
}
}
name: Site
type: module
description: 'Site utilities and content for In my day.'
package: Electronovelty
core_version_requirement: '^9.4 || ^10 || ^11'
version: '1.0'
(function (Drupal) {
'use strict';
var processed = false;
Drupal.behaviors.contactFormToggle = {
attach: function () {
if (processed) {
return;
}
var block = document.getElementById('block-johnbutton-contactblock');
if (!block) {
return;
}
var title = block.querySelector('h2');
if (!title) {
return;
}
processed = true;
title.addEventListener('click', function () {
block.classList.toggle('contact-form-open');
});
}
};
})(Drupal);
styling:
version: '1.0'
css:
component:
css/site.css: {}
js:
js/site.js: {}
dependencies:
- core/drupal
<?php
/**
* @file
* Node Site functions for EN9 module file
*/
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Routing\RouteMatchInterface;
/**
* Implements hook_form_alter().
*/
function site_form_alter(array &$form, FormStateInterface $form_state, string $form_id): void {
// Set the message textarea to 6 rows for contact forms.
if (str_starts_with($form_id, 'contact_message_') && isset($form['message']['widget'][0]['value'])) {
$form['message']['widget'][0]['value']['#rows'] = 6;
}
}
/**
* Implements hook_theme().
*/
function site_theme($existing, $type, $theme, $path) {
return [
'copyright_block' => [
'variables' => ['year' => NULL, 'vers' => NULL],
'template' => 'copyright-block',
],
];
}
/**
* Implements hook_preprocess_field().
*
* Attaches individual media name and description to each item in the
* media_gallery images field so the field template can render them.
*/
function site_preprocess_field(array &$variables): void {
if ($variables['field_name'] !== 'images' || $variables['element']['#entity_type'] !== 'media_gallery') {
return;
}
$field_items = $variables['element']['#items'];
foreach ($variables['items'] as $delta => &$item) {
$media = $field_items[$delta]->entity ?? NULL;
if (!$media) {
continue;
}
$item['media_name'] = $media->label();
$item['media_description'] = $media->hasField('field_description')
? $media->get('field_description')->processed
: '';
// Invalidate the gallery's render cache when the media entity changes.
$variables['#cache']['tags'][] = 'media:' . $media->id();
}
}
/**
* Implements hook_preprocess_block().
*
* Adds a "view gallery" link to media gallery blocks.
*/
function site_preprocess_block(array &$variables): void {
if ($variables['base_plugin_id'] !== 'media_gallery_latest_items_all_galleries') {
return;
}
$variables['content']['view_gallery_link'] = [
'#type' => 'link',
'#title' => t('view gallery'),
'#url' => \Drupal\Core\Url::fromUri('internal:/media_gallery/1'),
'#attributes' => [
'class' => ['view-gallery-link', 'btn', 'btn-primary', 'btn-sm'],
],
'#weight' => -10,
];
}
/**
* Implements hook_help().
*/
function site_help($route_name, RouteMatchInterface $route_match) {
if ($route_name == 'help.page.site') {
$output = file_get_contents(Drupal::service('extension.list.module')->getPath('site') . '/README.md');
$output = '<pre>' . $output . '</pre>';
return [
'#type' => 'markup',
'#markup' => $output,
];
}
}
// Bootstrap functions, variables and mixins
@import "../../../../themes/contrib/bootstrap5/dist/bootstrap/5.3.8/scss/functions";
@import "../../../../themes/contrib/bootstrap5/dist/bootstrap/5.3.8/scss/variables";
@import "../../../../themes/contrib/bootstrap5/dist/bootstrap/5.3.8/scss/mixins";
// styles for site module
.home-img {
margin-right: 10px;
border-radius: 10px;
}
.region-header {
.navbar-brand {
padding-top: 10px;
img {
margin-left: 10px;
}
}
}
#block-johnbutton-site-branding {
background-color: #ddd;
}
.node--type-blog-post {
margin-bottom: 1.5rem;
padding-bottom: .5rem;
border-bottom: 2-x solid #eee;
img {
border-radius: 10px;
margin: 10px;
}
.node__links li {
padding: 0 1em 0 0;
}
}
// header
header {
#block-aidev-site-branding {
background-color: #dddddd;
padding: 0.5em;
}
.navbar {
background-color: #dddddd;
}
}
main {
margin-top: 1em;
}
// footer
footer {
padding: 0 !important;
}
footer .region-footer {
background-color: #dddddd;
padding: 1rem;
}
// copyright block
.region-copyright {
margin-top: 1em;
padding: 1rem;
background-color: #ddd;
#block-johnbutton-copyrightblock {
#footer-copyright {
display: flex;
flex-direction: row;
.c-vers {
margin-left: auto;
}
}
}
}
// media gallery grid
.photoswipe-gallery {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 1rem;
@include media-breakpoint-up(md) {
grid-template-columns: repeat(3, 1fr);
}
@include media-breakpoint-up(lg) {
grid-template-columns: repeat(4, 1fr);
}
// Force 2 columns in sidebar regions
.region-sidebar-first &,
.region-sidebar-second & {
grid-template-columns: repeat(2, 1fr);
}
.gallery-item {
display: flex;
flex-direction: column;
.gallery-item__name {
@include font-size($h6-font-size);
margin-bottom: 0.25rem;
}
.gallery-item__description {
@include font-size($small-font-size);
margin-bottom: 0.5rem;
p:last-child {
margin-bottom: 0;
}
}
img {
width: 100%;
height: auto;
display: block;
}
}
}
.media-gallery-layout--vertical {
h2
{
font-size: calc(.5rem + 0.9vw);
text-align: center;
}
}
// latest gallery photos block - vertical layout
.media-gallery-layout--vertical .block__content {
.view-gallery-link {
display: block;
width: fit-content;
margin: 0.5em auto 0;
padding-left: 8px;
padding-right: 8px;
}
.photoswipe-gallery {
display: flex;
flex-direction: column;
align-items: center;
gap: 0.5rem;
img {
border-radius: 10px;
}
.media-oembed-content {
border-radius: 10px;
overflow: hidden;
}
}
.media-gallery-latest-items-view-all {
display: block;
width: fit-content;
margin: 0.5rem auto 0;
}
}
// Override vertical layout to 2 columns in sidebars
.region-sidebar-first,
.region-sidebar-second {
.media-gallery-layout--vertical .block__content .photoswipe-gallery {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 0.5rem;
margin-top: 1em;
}
.media-gallery-latest-items-view-all {
display: none !important;
}
}
.region-sidebar-second {
margin-left: 10px;
border-left: 2px solid #ccc;
min-height: 100%;
}
// blog posts
.node--type-blog-post {
.node__submitted {
margin-bottom: 1rem;
font-style: italic;
}
.field--name-field-blog-tags .field__label {
font-weight: normal;
padding-top: 0.5rem;
border-top: 1px solid #ccc;
width: 20%;
}
}
// main nav
#block-aidev-main-menu-menu {
@include font-size($h3-font-size);
margin-bottom: 0;
}
// user menu (below copyright)
.region-user {
background-color: #dddddd;
padding: 0 1rem 1rem;
h2#block-aidev-useraccountmenu-menu {
display: none;
}
ul.nav {
display: inline;
list-style: none;
margin: 0;
padding: 0;
}
li.nav-item {
display: inline;
}
a.nav-link {
display: inline;
padding: 0;
}
li.nav-item:not(:last-child)::after {
content: " | ";
}
}
// contact form
#block-johnbutton-contactblock {
margin-top: 1em;
padding-top: 0.5em;
border-top: 1px solid #ddd;
h2 {
text-align: center;
cursor: pointer;
}
.block__content {
display: none;
}
&.contact-form-open .block__content {
display: block;
}
.form-actions a.cancel {
display: block;
margin-top: 0.5em;
margin-left: 0;
font-weight: 400;
line-height: 1.5;
text-align: center;
text-decoration: none;
cursor: pointer;
padding: $btn-padding-y $btn-padding-x;
font-size: $btn-font-size;
border-radius: $btn-border-radius;
color: #fff;
background-color: $secondary;
border: $btn-border-width solid $secondary;
width: fit-content;
&:hover {
background-color: shade-color($secondary, 20%);
border-color: shade-color($secondary, 25%);
color: #fff;
}
}
}
#edit-preview {
background-color: #42a877;
}
#edit-captcha .accordion-item {
// hide captcha instructions on remote
display: none;;
}
.captcha-type-challenge--recaptcha {
margin-left: 1em;
border: 1px solid #ddd;
padding: 0.5em;
#edit-captcha-response--description,
.captcha__description {
font-style: italic;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment