Good Afternoon,
I cannot figure out how to remove the key board divider key after my favicon in the browser tab. Please see the image below.
Note: I am developing with Drupal 8.
Drupal construct, by default, the page title such: [Entity-Title] | [Site Name].
It's seems you don't have a title on this page.
It depends which page(s) you try to change. For an Entity, just set the title field would fix your probleme.
Titles on routes now can be set on various ways, depending on your use case.
Previously (drupal-7) just drupal_set_title() was called in whatever place. The following use cases exist:
Override title tag
You may override the title tag in the head of your HTML document using the HOOK_preprocess_html.
function mymodule_preprocess_html(&$variables) {
// Change the Title
$variables['head_title']['title'] = 'Title';
// Change the Suffix (sitename)
$variables['head_title']['name'] = 'Suffix';
}
Static title
For static titles you set a '_title' on the routing definition:
block.admin_add:
path: '/admin/structure/block/add/{plugin_id}/{theme}'
defaults:
_controller: '\Drupal\block\Controller\BlockAddController::blockAddConfigureForm'
_title: 'Configure block'
requirements:
_permission: 'administer blocks'
Dynamic title
If you write a controller and you need a dynamic title, for example depending on the site configuration, use _title_callback in the route defaults.
mymodule.test:
path: '/mymodule/test'
defaults:
_controller: '\Drupal\mymodule\Controller\TestController::getContent'
_title_callback: '\Drupal\mymodule\Controller\TestController::getTitle'
<?php
class TestController {
/**
* Returns a page title.
*/
public function getTitle() {
// The \Drupal::config() should be injected instead of using static call.
return 'Foo: ' . \Drupal::config()->get('system.site')->get('name');
}
/**
* Returns a page render array.
*/
public function getContent() {
$build = array();
$build['#markup'] = 'Hello Drupal';
return $build;
}
}
Final title override
If you write a controller and you need to override the title from the route, you can return #title in the render array. This should generally to be avoided, since the title for the page when fully rendered could be different from the title in other contexts (like in the breadcrumb).
<?php
class TestController {
/**
* Renders a page with a title.
*
* #return array
* A render array as expected by drupal_render()
*/
public function getContentWithTitle() {
$build = array();
$build['#markup'] = 'Hello Drupal';
// The \Drupal::config() should be injected instead of using static call.
$build['#title'] = 'Foo: ' . Drupal::config()->get('system.site')->get('name');
return $build;
}
}
drupal_set_title() in Drupal 8
As you can see here that drupal_set_title() is deprecated in Drupal 8.
$request = \Drupal::request();
if ($route = $request->attributes->get(\Symfony\Cmf\Component\Routing\RouteObjectInterface::ROUTE_OBJECT)) {
$route->setDefault('_title', 'New Title');
}
Related
I would like to assign a template on my PageLayoutView preview in order to avoid writing HTML on my PHP files and better maintain it. How can i achieve that using TYPO3 10?
I would like to use it for example on the textmedia content element and add the subheader in.
In order to achieve that, you will have to use the Standalone view. I would write a function which i can call it whenever i want to use it. Normally i would include the function on a Helper Class but for the sake of this answer i will put it on the same class. So lets say we have the textmedia content element and we want to add fields on the backend Preview.
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Fluid\View\StandaloneView;
/**
* Contains a preview rendering for the page module of CType="textmedia"
*/
class TextMediaPreviewRenderer implements PageLayoutViewDrawItemHookInterface
{
/**
* Preprocesses the preview rendering of a content element of type "textmedia"
*
* #param \TYPO3\CMS\Backend\View\PageLayoutView $parentObject Calling parent object
* #param bool $drawItem Whether to draw the item using the default functionality
* #param string $headerContent Header content
* #param string $subheaderContent Subheader content
* #param string $itemContent Item content
* #param array $row Record row of tt_content
*/
public function preProcess(
PageLayoutView &$parentObject,
&$drawItem,
&$headerContent,
&$subheaderContent,
&$itemContent,
array &$row
) {
if ($row['CType'] === 'textmedia') {
$standaloneView = $this->getStandAloneConfig();
/*Disable TYPO3's default backend view configuration */
$drawItem = false;
/*Assign all the results to the backend */
$standaloneView->assignMultiple([
'title' => $parentObject->CType_labels[$row['CType']],
'type' => $row['CType'],
'content' => $row,
]);
$itemContent .= $standaloneView->render();
}
}
public function getStandAloneConfig()
{
$standaloneView = GeneralUtility::makeInstance(StandaloneView::class);
$standaloneView->setLayoutRootPaths([10,'EXT:your_extension/Resources/Private/Backend/Layouts/']);
$standaloneView->setTemplateRootPaths([10,'EXT:your_extension/Resources/Private/Backend/Templates/']);
$standaloneView->setPartialRootPaths([10,'EXT:your_extension/Resources/Private/Backend/Partials/']);
$standaloneView->setFormat('html');
$standaloneView->setTemplate('PageLayoutView.html');
return $standaloneView;
}
What is happening is the following
First, we get the StandAlone configuration. In this configuration (getStandAloneConfig()) we set the path to where our templates, partials and layouts are. Then we assign the type (html) and then the name of the template where our preview is going to be built on (PageLayoutView.html).
After that we reset everything that TYPO3 writes on the Preview ($drawItem = false;) so we can write our own.
Last and not least we assign the variables which we are going to use on the HTML file.
Under your_extension/Resources/Private/Backend/Templates/PageLayoutView.html
<html xmlns:f="http://typo3.org/ns/TYPO3/CMS/Fluid/ViewHelpers" data-namespace-typo3-fluid="true">
<f:switch expression="{type}">
<f:case value="textmedia">
<f:render partial="Textmedia" arguments="{_all}"/>
</f:case>
<f:case value="text">
<f:render partial="Text" arguments="{_all}"/>
</f:case>
<f:defaultCase>
<f:render partial="Header" arguments="{_all}"/>
</f:defaultCase>
</f:switch>
</html>
I personally use the PageLayoutView.html as a controller which decides, which partial should be rendered. So i assign the variable {type} and i render the partial based on its value.
Under your_extension/Resources/Private/Backend/Partials/Textmedia.html
<html xmlns:f="http://typo3.org/ns/TYPO3/CMS/Fluid/ViewHelpers" data-namespace-typo3-fluid="true">
<p><strong class="element_title">{title}</strong></p>
<table class="element_table">
<tbody>
<tr>
<th>Subheader</th>
<td>{content.subheader}</td>
</tr>
</tbody>
</table>
</html>
Now you can look what is inside the {content} variable and render it on your HTML.
If you want to style your Preview you can do the following: Under your ext_tables.php add the following line:
$GLOBALS['TBE_STYLES']['stylesheet'] = 'EXT:your_extension/Resources/Public/Css/Backend/page-layout-view.css';
There's a pretty easy way. Just set an alternative path for the preview templates.
\TYPO3\CMS\Backend\View\PageLayoutView::tt_content_drawItem():
// If the previous hook did not render something,
// then check if a Fluid-based preview template was defined for this CType
// and render it via Fluid. Possible option:
// mod.web_layout.tt_content.preview.media = EXT:site_mysite/Resources/Private/Templates/Preview/Media.html
if ($drawItem) {
$fluidPreview = $this->renderContentElementPreviewFromFluidTemplate($row);
if ($fluidPreview !== null) {
$out .= $fluidPreview;
$drawItem = false;
}
}
I have a Drupal 8.7 site and the Drupal Commerce 2.14 module
In the template of my store to display the field field_professionnel_cgv I use this code TWIG :
{{ store.field_professionnel_cgv }}
How to display this field from the template of my products.
You could add to your module mymodule_preprocess_commerce_product() hook function and inside that function get store entity and set twig variable with data from it so it will be available inside your template.
Check how original function looks like at:
/modules/contrib/commerce/modules/product/commerce_product.module
function template_preprocess_commerce_product(array &$variables) {
/** #var Drupal\commerce_product\Entity\ProductInterface $product */
$product = $variables['elements']['#commerce_product'];
$variables['product_entity'] = $product;
$variables['product_url'] = $product->isNew() ? '' : $product->toUrl();
$variables['product'] = [];
foreach (Element::children($variables['elements']) as $key) {
$variables['product'][$key] = $variables['elements'][$key];
}
}
So you'll have to fetch store object and assign twig variable like it's done here.
Still a newbie in Silverstripe. I am experimenting with the CMS and I would like to create a new CMS menu with text fields in it. I managed to add a CMS menu item with a gridfield in it to add data objects but what I require is to have text fields directly inside the CMS menu item without creating a Data Object (similar to the Settings menu as shown in the image below)
Can someone guide me in what I need to extend and how to set the thing up? Many thanks in advance.
You can extend the settings section. The following example adds a tab called Social Media under the settings section and 2 fields FacebookURL and TwitterURL. You can change this to any fields / tabs that you want.
**mysite/_config/extensions.yml
---
Name: mysiteextensions
After: 'framework/*','cms/*'
---
SiteConfig:
extensions:
- SiteConfigDecorator
mysite/code/extensions/SiteConfigDecorator
<?php
class SiteConfigDecorator extends DataExtension {
private static $db = array(
'FacebookURL' => 'Varchar(200)',
'TwitterURL' => 'Varchar(200)'
);
private static $has_one = array(
'FooterQuoteButtonPage' => 'SiteTree'
);
public function updateCMSFields(FieldList $fields) {
$fields->addFieldToTab('Root.SocialMedia', TextField::create('FacebookURL', 'Facebook URL'));
$fields->addFieldToTab('Root.SocialMedia', TextField::create('TwitterURL', 'Twitter URL'));
}
function __construct() {
parent::__construct();
}
}
To access these fields in the templates, you use $SiteConfig.FIELDNAME. In this case it would be $SiteConfig.FacebookURL and $SiteConfig.TwitterURL
I am working on Xcart-5 website customization. And I created my own module and doing work on that. I just created some Global Attributes (" As a Plain text ") field and assign these attributes to some product. Now I want to access these fields value in programming in the product details page for assigning some other value programatically at run time.
How can I achieve this task. Kindly provide me the solution .
In your module you should decorate the \XLite\Model\Attribute class and extend the getAttributeValue() method there.
For instance, if I use a module with developer ID Tony and module ID AttributesDemo, then I would need to create the XCartDirectory/classes/XLite/Module/Tony/AttributesDemo/Model/Attribute.php file with the following content:
<?php
// vim: set ts=4 sw=4 sts=4 et:
namespace XLite\Module\Tony\AttributesDemo\Model;
/**
* Attribute
* #MappedSuperClass
*/
abstract class Attribute extends \XLite\Model\AttributeAbstract implements \XLite\Base\IDecorator
{
public function getAttributeValue(\XLite\Model\Product $product, $asString = false)
{
$result = parent::getAttributeValue($product, $asString);
if (!$asString) {
foreach ($result as $obj) {
if ($obj->asString() == 'Mac') {
$obj->getAttributeOption()->setName('Windows');
}
}
}
return $result;
}
}
Such implementation will change Mac values to Windows ones in all attributes.
I have a Magento website with the following category structure (CAPITALS letters are CATEGORIES and small letters are products):
ROOT CATEGORY
APPARELS
SHOP BY SIZE
product1
product2
product3
SHOP BY COLLECTION
product4
product5
SHOP BY DESIGN
product6
product7
product8
product9
I want to show my navigation menu as SHOP BY SIZE, SHOP BY COLLECTION and SHOP BY DESIGN. I don't want the navigation to start with APPARELS level. Is there any way to do this?
Note: As per Magento design, ROOT CATEGORY cannot be shown in navigation menu. The navigation menu starts from categories in 2nd level i.e. APPARELS in this case.
Take a look at navigation.php, you could alter the core functionality but by using a module with rewrite (never directly alter a corefile!). I always start there when i need custom navigation functionality.
http://freegento.com/doc/db/d56/_catalog_2_block_2_navigation_8php-source.html
edit, alltough i often use this method, i would advise to avoid rewriting as much as possible, I don't think its possible in this case tough because we are talking about displaying lvl 2 categories as main nav
IF you truly want to use the design Root -> Apparels -> Shop By * you can do this with a single override and modification
config.xml - this is obviously a heavily simplified file, you'll need to provide a helper rewrite for the file.
<?xml version="1.0"?>
<config>
<helpers>
<catalog>
<rewrite>
<category>Namespace_Module_Helper_Catalog_Category</category>
</rewrite>
</catalog>
</helpers>
</config>
Category.php
This assumes you want to use the first child category under your site's root category. In your case it would be "Apparels". This modification takes into account the use of flat or non-flat category tables. There are other options for selecting the ID, one would be a system configuration with the category list as a source thus allowing you to choose your navigations root category directly.
The crux of this file is getting the Parent ID to be the "root category" you want to base the navigation on. Again, for your case the parent ID would be set to that of the "apparels" category.
class Namespace_Module_Helper_Catalog_Category extends Mage_Catalog_Helper_Category {
public function getStoreCategories($sorted=false, $asCollection=false, $toLoad=true)
{
$parent = Mage::app()->getStore()->getRootCategoryId();
$cacheKey = sprintf('%d-%d-%d-%d', $parent, $sorted, $asCollection, $toLoad);
if (isset($this->_storeCategories[$cacheKey])) {
return $this->_storeCategories[$cacheKey];
}
/**
* Check if parent node of the store still exists
*/
$category = Mage::getModel('catalog/category');
/* #var $category Mage_Catalog_Model_Category */
if (!$category->checkId($parent)) {
if ($asCollection) {
return new Varien_Data_Collection();
}
return array();
}
/* Change ian on 1/4/13 at 11:16 AM - Description: Here we capture the id of first child for use as the 'root' */
$category->load($parent);
/** #var $collection Mage_Catalog_Model_Resource_Category_Collection */
$collection = $category->getChildrenCategories();
if (is_array($collection)) {
$category = array_shift($collection); //get the first category in the array. Unknown key.
$parent = $category->getId();
} else {
$parent = $collection->getFirstItem()->getId();
}
$recursionLevel = max(0, (int) Mage::app()->getStore()->getConfig('catalog/navigation/max_depth'));
$storeCategories = $category->getCategories($parent, $recursionLevel, $sorted, $asCollection, $toLoad);
$this->_storeCategories[$cacheKey] = $storeCategories;
return $storeCategories;
}
}