I've tried it with
https://www.drupal.org/project/remove_querystring_from_static_resource
But it doesn't work well for me .
How can I achieve that programmatically?
The following is the test result:
This trouble is usually encountered when static resources (eg. images, css & javascript files) are accessed using a query string.
Eg: http://example.com/image.png?something=test
Those query strings are used for avoiding browser caching. Their values are changed, so the browser should do a new request instead of getting cached resource.
You should remove those query strings (?something=test in my example) and use some suitable Cache-Control headers.
Edit:
Try this code.
Replace THEMENAME with your theme name.
/**
* Implements template_process_html().
* Remove Query Strings from CSS & JS filenames
*/
function THEMENAME_process_html( &$variables) {
$variables['styles'] = preg_replace('/\.css\?[^"]+/', '.css', $variables['styles']);
$variables['scripts'] = preg_replace('/\.js\?[^"]+/', '.js', $variables['scripts']);
}
/**
* Implement hook_image_style
* Override theme image style to remove query string.
* #param $variables
*/
function THEMENAME_image_style($variables) {
// Determine the dimensions of the styled image.
$dimensions = array(
'width' => $variables['width'],
'height' => $variables['height'],
);
image_style_transform_dimensions($variables['style_name'], $dimensions);
$variables['width'] = $dimensions['width'];
$variables['height'] = $dimensions['height'];
// Determine the URL for the styled image.
$variables['path'] = image_style_url($variables['style_name'], $variables['path']);
// Remove query string for image.
$variables['path'] = preg_replace('/\?.*/', '', $variables['path']);
return theme('image', $variables);
}
Finally I solved the issue with this code:
use Drupal\Core\Asset\AttachedAssetsInterface;
/**
* Implements hook_css_alter().
*/
function bootstrap_css_alter(&$css, AttachedAssetsInterface $assets){
foreach ($css as &$file) {
if ($file['type'] != 'external') {
$file['type'] = 'external';
$file['data'] = '/' . $file['data'];
}
}
}
/**
* Implements hook_js_alter().
*/
function bootstrap_js_alter(&$javascript, AttachedAssetsInterface $assets){
foreach ($javascript as &$file) {
if ($file['type'] != 'external') {
$file['type'] = 'external';
$file['data'] = '/' . $file['data'];
}
}
}
Put this code to your yourthemename.theme file.
it works perfect on drupal 8
Hope this help you guys.
Related
I have added some custom code in a block using PHP code format to show that block on a specific page. I have checked all the things working fine on Devel PHP page but contents are not showing on page. The code below fetches the field value of a destination node.
$refer = $_SERVER[HTTP_REFERER];
$parsed = parse_url($refer);
$alias = array_pop($parsed);
$dst = \Drupal::service('path.alias_manager')->getPathByAlias($alias , $langcode);
$nid = array_pop(explode('/', $dst));
$dest_node = node_load($nid);
$body = $dest_node->get('body')->getValue();
print $body; //have tried other printing methods also but invain
Hope this clarifies the question.
Thanks
Are you sure that it works in Devel? I've just tried to execute your code, and this line:
$body = $dest_node->get('body')->getValue();
returns Array.
Try to use this one instead:
$body = $dest_node->body->value;
First of all, your first block of code (getting current node) can be replaced with just one line:
$node = \Drupal::service('current_route_match')->getParameter('node');
And the whole block can be changed in the following way:
if ($node = \Drupal::service('current_route_match')->getParameter('node')) {
print $node->body->value;
}
P.S. And it's definitely a bad idea to use PHP text filter. You may easily write your own custom module providing required block. The simplest block plugin requires several lines of code:
/**
* #file
* Contains \Drupal\my_module\Plugin\Block\MyBlock.
*/
namespace Drupal\my_module\Plugin\Block;
use Drupal\Core\Block\BlockBase;
/**
* Provides my super block.
*
* #Block(
* id = "my_module_block",
* admin_label = #Translation("My Block"),
* category = #Translation("My Module"),
* )
*/
class MyBlock extends BlockBase{
/**
* Builds and returns the renderable array for this block plugin.
*
* #return array
* A renderable array representing the content of the block.
*
* #see \Drupal\block\BlockViewBuilder
*/
public function build() {
if ($node = \Drupal::service('current_route_match')->getParameter('node')) {
return [ '#markup' => $node->body->value ];
}
}
}
This file MyBlock.php must be placed in /src/Plugin/Block/ directory inside your custom module named my_module.
I'm making a Silverstripe build task to get many images from an external gallery, and create/upload them into the /assets/images/gallery folder with the necessary database links to the GalleryPage.
So I load the list of Urls, display the images to the browser, now how do I save an image into the assets folder with the necessary GalleryPage database links?
class ImportGalleryTask extends BuildTask {
public function writeImage($data) {
//$data->Title
//$data->Filename
//$data->Url
//this is the external url that I can output as an image to the browser
//
// folder to save image is 'assets/images/gallery'
//
// ? save into folder and database and associate to PageImageBelongsToID ?
}
}
You can use copy to copy a remote file to your local filesystem. PHP must be configured to support allow_url_fopen though.
So, your resulting function might look like this:
/**
* #param $data
* #return null|Image return written Image object or `null` if failed
*/
public function writeImage($data)
{
// The target folder for the image
$folder = Folder::find_or_make('images/gallery');
// assuming that $data->Filename contains just the file-name without path
$targetPath = $folder->getFullPath() . $data->Filename;
// Check if an image with this name already exists
// ATTENTION: This will overwrite existing images!
// If you don't want this, you need to implement this differently
if(
file_exists($targetPath) &&
$image = Image::get()->where(array(
'"Name" = ?' => $data->Filename,
'"ParentID" = ?' => $folder->ID
))->first()
){
// just copy the new file over…
copy($data->Url, $targetPath);
// … and delete all cached images
$image->deleteFormattedImages();
// and we're done
return $image;
}
// Try to copy the file
if (!copy($data->Url, $targetPath)) {
return null;
}
// Write the file to the DB
$image = Image::create(array(
'Name' => $data->Filename,
'ParentID' => $folder->ID,
'Filename' => $folder->getRelativePath() . $data->Filename
));
$image->write();
return $image;
}
I'm using Symfony 2.8 & DomCrawler to parse a web site and I'm having a problem reading data attributes from a HTML entity. It might be as simple as a specific convention for data attributes, but I've not been able to find any references or examples on the web that discuss how to retrieve data attributes via DomCrawler.
Here are the details:
I have encountered an instance of this construct in the HTML I am parsing (from another web site, so I can't modify this HTML):
<div class='slideshowclass' id='slideshow'>
<div data-thumb='http://www.example.com/thumbs/1.jpg'
data-src='http://www.example.com/thumbs/1.jpg'></div>
<div data-thumb='http://www.example.com/thumbs/2.jpg'
data-src='http://www.example.com/thumbs/2.jpg'></div>
<div data-thumb='http://www.example.com/thumbs/3.jpg'
data-src='http://www.example.com/thumbs/3.jpg'></div>
<div data-thumb='http://www.example.com/thumbs/4.jpg'
data-src='http://www.example.com/thumbs/4.jpg'></div>
<div data-thumb='http://www.example.com/thumbs/5.jpg'
data-src='http://www.example.com/thumbs/5.jpg'></div>
<div data-thumb='http://www.example.com/thumbs/6.jpg'
data-src='http://www.example.com/6.jpg'></div>
</div>
I'm using this code to search the block of div's and return the data-src values:
function getList( Crawler $pWebDoc ) {
$list = $pWebDoc->filter( 'div#slideshow');
if ( !$list )
return null;
$retlist = null;
$x = $list->count();
if ( $x > 0 ) {
/* #var $item Crawler */
$retlist = $list->children()->each( function (Crawler $item, $i ) {
return ( "$i:" . $item->attr( 'data-src' ));
});
}
return ( $retlist );
}
From the DomCrawler docs I expect the attr function to return the data-src attribute value, but it returns null; the return from my function being an array of 6 elements with just the number and not additional text.
Thanks in advance for your help.
This can be easily done using the DOMDocument and XPath libraries. XPath does provide the capability of returning array's of values instead of nodes.
/**
* Filters the list of nodes with an XPath expression.
*
* The XPath expression should already be processed to apply it in the context of each node.
*
* #param string $xpath
*
* #return Crawler
*/
private function filterRelativeXPath($xpath)
{
$prefixes = $this->findNamespacePrefixes($xpath);
$crawler = $this->createSubCrawler(null);
foreach ($this->nodes as $node) {
$domxpath = $this->createDOMXPath($node->ownerDocument, $prefixes);
$crawler->add($domxpath->query($xpath, $node));
}
return $crawler;
}
This function is from Crawler.php. My experience has been that the Crawler wasn't happy with complex xpath expressions, which resulted in switching from the DomCrawler to using xpath / dom directly.
Your base xpath query would be like //div/#data-src
I created a little module with the DB fields "tag", "tag_url" and "tag_weight" and a form to fill them up.
Now I want to output the DB values in a custom block, but I dont know how to create it the correct way :-/
/**
* Implements hook_block_info().
*
* This hook declares what blocks are provided by the module.
*/
function myModule_block_info() {
$blocks['example_uppercase'] = array(
// info: The name of the block.
'info' => t('Example: uppercase this please'),
'status' => TRUE,
);
return $blocks;
}
/**
* Implements hook_block_view().
*
* This hook generates the contents of the blocks themselves.
*/
function myModule_block_view($delta = '') {
//The $delta parameter tells us which block is being requested.
switch ($delta) {
case 'example_uppercase':
//Select items from DB
$result = db_select('myModule','ht')
->fields('ht',array('tag','tag_url','tag_weight'))
->execute();
**$block['content'] = foreach($result as $value) { echo $value->tag; }**
break;
}
return $block;
}
When I am trying to do this, I get:
PHP Parse error: syntax error, unexpected T_FOREACH in
/.module on line 49
How to print out the database values to the block?
I figured out that i need to do it that way:
https://drupal.org/node/1104498
I want to copy a js file in my theme folder instead of hacking the module. This is my code:
/*update js files */
$scripts = drupal_add_js();
unset($scripts['module']['sites/all/modules/imagefield_crop/imagefield_crop.js']);
$scripts['module']['sites/all/themes/zen/zen/js/imagefield_crop.js'] = array('preprocess' => 1, 'cache' => 1);
$vars['scripts'] = drupal_get_js('header', $scripts);
IT works for lightbox2 but it doesn't work for imagefield_crop.js
I've cleaned all Drupal caches and browser cache but my browser continues to load the original js in the module directory.
thanks
Update: This is the array $scripts
['module']
...
[sites/all/modules/imagefield_crop/Jcrop/js/jquery.Jcrop.js] => Array
(
[cache] => 1
[defer] =>
[preprocess] => 1
)
Given the updated question after the discussion in the comments, it seems like you are mixing up the involved js files. Imagefield_crop adds two different ones:
jquery.Jcrop.js, which is an imported library file providing the crop functionality in general (in context of jquery) - normally, you should not have a reason to replace this.
'imagefield_crop.js', which is the one providing the 'bridging' to allow the above library to work properly in the Drupal context - my understanding was that you wanted to replace this one.
Both are needed for the functionality to work. Your posted code would only replace the second one, and unless you accidentally posted the wrong code snippet in your question update, it seems to work.
If you wanted to replace both (or only the first one), you'd need to extend/adjust your unsetting logic to do so.
Hello here is the possible solutions it might help though I've never done this before
/**
* Implementation of hook_theme_registry_alter().
* Based on the jquery_update module.
*
* Make this page preprocess function runs *last*,
* so that a theme can't call drupal_get_js().
*/
function MYMODULE_theme_registry_alter(&$theme_registry) {
if (isset($theme_registry['page'])) {
// See if our preprocess function is loaded, if so remove it.
if ($key = array_search('MYMODULE_preprocess_page',
$theme_registry['page']['preprocess functions'])) {
unset($theme_registry['page']['preprocess functions'][$key]);
}
// Now add it on at the end of the array so that it runs last.
$theme_registry['page']['preprocess functions'][] = 'MYMODULE_preprocess_page';
}
}
/**
* Implementation of moduleName_preprocess_hook().
* Based on the jquery_update module functions. *
* Strips out JS and CSS for a path.
*/
function MYMODULE_preprocess_page(&$variables, $arg = 'my_page', $delta=0) {
// I needed a one hit wonder. Can be altered to use function arguments
// to increase it's flexibility.
if(arg($delta) == $arg) {
$scripts = drupal_add_js();
$css = drupal_add_css();
// Only do this for pages that have JavaScript on them.
if (!empty($variables['scripts'])) {
$path = drupal_get_path('module', 'admin_menu');
unset($scripts['module'][$path . '/admin_menu.js']);
$variables['scripts'] = drupal_get_js('header', $scripts);
}
// Similar process for CSS but there are 2 Css realted variables.
// $variables['css'] and $variables['styles'] are both used.
if (!empty($variables['css'])) {
$path = drupal_get_path('module', 'admin_menu');
unset($css['all']['module'][$path . '/admin_menu.css']);
unset($css['all']['module'][$path . '/admin_menu.color.css']);
$variables['styles'] = drupal_get_css($css);
}
}
}
http://www.mediacurrent.com/blogs/remove-or-replace-jscss-page