Drupal 7 Render a Comment Object - php

So this is the problem I am running into. If I have a comment object, I want to create a renderable array that is using the display settings of that comment. As of now this is what I have:
$commentNew = comment_load($var);
$reply[] = field_view_value('comment', $commentNew, 'comment_body', $commentNew->comment_body['und'][0]);
Which works fine because I dont have any specific settings setup for the body. But I also have image fields and video embed fields that I need to have rendered the way they are setup in the system. How would I go about doing that?

Drupal core does it with the comment_view() function:
$comment = comment_load($var);
$node = node_load($comment->nid);
$view_mode = 'full'; // Or whatever view mode is appropriate
$build = comment_view($comment, $node, $view_mode);
If you need to change a particular field from the default, use hook_comment_view():
function MYMODULE_comment_view($comment, $view_mode, $langcode) {
$comment->content['body'] = array('#markup' => 'something');
}
or just edit the $build array received from comment_view() as you need to if implementing the hook won't work for your use case.

Related

Trying to highlight current menu item in Drupal 8 using hook_preprocess_menu

I have the below function to create active trail functionality. So if I were to have /blog as a "parent" and a post of /blog/mypost, when on mypost the blog link would show as highlighted. I don't want to have to make menu items for all the blog posts. The problem is when caching is turned on (not using settings.local.php and debug turned off) the getRequestUri isn't changing on some pages. It seems to be cached depending on the page. It works fine with page caching turned off but I'd like to get this working with caching. Is there a better way to check for the current path and apply the active class?
function mytheme_preprocess_menu(&$variables, $hook) {
if($variables['theme_hook_original'] == 'menu__main'){
$node = \Drupal::routeMatch()->getParameter('node');
if($node){
$current_path = \Drupal::request()->getRequestUri();
$items = $variables['items'];
foreach ($items as $key => $item) {
// If current path starts with a part of another path i.e. a parent, set active to li.
if (0 === strpos($current_path, $item['url']->toString())) {
// Add active link.
$variables['items'][$key]['attributes']['class'] .= ' menu-item--active-trail';
}
}
}
}
}
I've also tried putting this into a module to try and see if I can get the current path to then do the twig logic in the menu--main.twig.html template but I have the same problem.
function highlight_menu_sections_template_preprocess_default_variables_alter(&$variables) {
$variables['current_path'] = $_SERVER['REQUEST_URI'];
}
After a very long time trying all sorts of things, I found an excellent module which addresses exactly this problem. Install and go, not configuration, it just works:
https://www.drupal.org/project/menu_trail_by_path
Stable versions for D7 and D8.
I tried declaring an active path as part of a custom menu block, and even then my declared trail gets cached. Assuming it's related to the "There is no way to set the active link - override the service if you need more control." statement in this changelog, though why MenuTreeParameters->setActiveTrail() exists is anybody's guess.
For the curious (and for me when I search for this later!), here's my block's build() function:
public function build() {
$menu_tree = \Drupal::menuTree();
$parameters = new MenuTreeParameters();
$parameters->setRoot('menu_link_content:700c69e6-785b-4db7-be49-73188b47b5a3')->setMinDepth(1)->setMaxDepth(1)->onlyEnabledLinks();
// An array of routes and menu_link_content ids to set as active
$define_active_mlid = array(
'view.press_releases.page_1' => 385
);
$route_name = \Drupal::request()->get(RouteObjectInterface::ROUTE_NAME);
if (array_key_exists($route_name, $define_active_mlid)) {
$menu_link = \Drupal::entityTypeManager()->getStorage('menu_link_content')->loadByProperties(array('id' => $define_active_mlid[$route_name]));
$link = array_shift($menu_link);
$parameters->setActiveTrail(array('menu_link_content:' . $link->uuid()));
}
$footer_tree = $menu_tree->load('footer', $parameters);
$manipulators = array(
array('callable' => 'menu.default_tree_manipulators:checkAccess'),
array('callable' => 'menu.default_tree_manipulators:generateIndexAndSort'),
);
$tree = $menu_tree->transform($footer_tree, $manipulators);
$menu = $menu_tree->build($tree);
return array(
'menu' => $menu,
);
}
[adding a new answer since this is a completely different approach than my earlier one]
If a CSS-based solution is acceptable, this seems to work okay:
.page-node-type-press-release {
a[data-drupal-link-system-path="press-room/press-releases"] {
// active CSS styles here
}
}

Creating Multiple Custom Attibutes For Product with google-api-php-client

According to that answer https://support.google.com/merchants/answer/4588281?hl=en-GB
if I want set multiple promotions ids for the product with the API I can specify multiple lines of:
<sc:attribute name="promotion_id">PROMOTION_ID</sc:attribute>
I am using this lib https://github.com/google/google-api-php-client
My question is how can i do it with this library. Should I use custom attributes? for example.
$feed_entry = new Google_Service_Content_Product();
$promotions_ids = array (20,21,22);
foreach ($promotions_ids as $promotion_id ) {
$promotion = new Google_Service_Content_ProductCustomAttribute();
$promotion->setName('promotion_id');
$promotion->setValue($promotion_id);
$feed_entry->setCustomAttributes($promotion);
}
But that would just set this attribute over again for different ids. I am not even sure if I am doing this in a right way. Probably missing something. The full code example would be really helpful.
I couldn't find a definitive code sample for PHP. That being said, if you look at API libraries for other languages you find that:
For Java it uses a List<ProductCustomAttribute>:
public Product setCustomAttributes(java.util.List<ProductCustomAttribute> customAttributes)
Source
For JavaScript it uses a map:
setCustomAttributes(map)
setCustomAttributes({ 'size': 'Large', 'color': 'Green' })
Source
Conclusion:
there's a very good chance the PHP method in question uses an array of Google_Service_Content_ProductCustomAttribute objects:
public function setCustomAttributes($customAttributes)
$feed_entry = new Google_Service_Content_Product();
$promotions_ids = array (20,21,22);
$customAttributes = array();
foreach ($promotions_ids as $promotion_id ) {
$promotion = new Google_Service_Content_ProductCustomAttribute();
$promotion->setName('promotion_id');
$promotion->setValue($promotion_id);
$customAttributes[] = $promotion;
}
$feed_entry->setCustomAttributes($customAttributes);
Try it!

How would I format Zend_Form_Element_Radio so the label comes after the input

I have been trying to implement the solution in an earlier version of this question at:
How would I format Zend_Form_Element_Radio so the label follows the input?
By creating an extended helper MyLib_View_Helper_FormRadio but must be missing something obvious with this!
My question is how do I get Zend_Form_Element_Radio() to use this now instead of the version of the helper in Zend_View_Helper_FormRadio?
I thought initially that this was done by creating the element with
$radio = new MyLib_View_Helper_FormRadio();
but realised its not.
Changing the way the label and input are ordered in the Zend_View_Helper_FormRadio.php does the trick but I realise that the Zend files should not be altered.
If anyone can help me with t his I would be very grateful!
In your MyLib_View_Helper_FormRadio class, you have a method, like this (it's an example):
public function formRadioCustom($name, $value = null, $attribs = null,
$options = null, $listsep = "<br />\n"){...}
So to call it instead of formRadio of Zend_View_Helper_FormRadio, if I'm not mistaken, you have to do:
$element->addDecorators(array(array('ViewHelper',array('helper' => 'formRadioCustom'))));
And in your bootstrap add a method to add helper like this:
protected function _initViewHelpers() {
$view = new Zend_View();
$view->->addHelperPath('MyLib/View/Helper/', 'MyLib_View_Helper');
}

set upload folder in dataobject to the title of the related page - Silverstripe 3.1

hi i've got a gallery page. this gallery page has a gallery image object with an has_many relation.
private static $has_many = array(
'GalleryImages' => 'GalleryObject'
);
my gallery object has an image upload field. I want to set the upload folder to the title of the gallery page
i tried this with no result
$visual->setFolderName('Galerie/'.$this->Gallery()->Title);
and this (what i would prefer)
public function getGalleryTitle() {
$galleryTitle = $this->Gallery()->Title->First();
$uploadFolder = str_replace(' ', '-', $this->$galleryTitle);
return $uploadFolder;
}
$visual->setFolderName('Galerie/'.$this->$uploadFolder);
the second returns and error (undefined variable uploadFolder ?!) and my upload folder is now set to "Galerie/DataList"
can someone tell me how to convert the output of $uploadFolder so that i get back the title?
EDIT:
GalleryHolder: http://www.sspaste.com/paste/show/5267dea3579a6
GalleryPage: http://www.sspaste.com/paste/show/5267dee4c9752
GalleryObject: http://www.sspaste.com/paste/show/5267df0af1a65
you where almost there..
Here is your edited getGalleryTitle() function.
It is basically checking if the GalleryObject has a parent Gallery via $this->GalleryID. Since it is a has_one relation the column will be named GalleryID.
Then we get the Gallery object with $this->Gallery() and get it's title with $gallery->Title.
I've also replaced your str_replace with SilverStripe's URLSegmentFilter class. Which will removed spaces and other special characters non welcome in URL, a better solution.
public function getGalleryTitle()
{
if ( $this->GalleryID )
{
$gallery = $this->Gallery();
$filter = new URLSegmentFilter();
return $filter->filter( $gallery->Title );
}
else{
return 'default';
}
}
Then in the getCMSFields() function, when creating your UploadField we just call the getGalleryTitle() function that returns the string for the folder name.
$visual = new UploadField('Visual', _t('Dict.IMAGE', 'Image'));
$visual->setFolderName('Galerie/'.$this->getGalleryTitle());
A few notes..
$this references the current Object instance, so you can't use $this->$galleryTitle to access a variable you just created in your function, $galleryTitle by itself is enough.
You were calling $this->$uploadFolder in setFolderName, this doesn't work for the same reason, and also, using $uploadFolder by itself wouldn't work since this variable was created in the scope of another function. So we just call the function we defined on our Object with $this->getGalleryTitle() since it returns the value we want.
This should work fine, but keep in mind that if the Title of the Gallery changes at some point, the folder name will change too. So you might end up with images uploaded in many different folders for the same gallery... I personally wouldn't advise it, unless you implement some kind of "Title locking system" or some way to keep the "correct" or first "valid/acceptable" Gallery title in a separate object property that can't be edited and use this in the folder name.
I usually only use the ID in those case ($gallery->ID), as this will not change.
edit
Another version of getGalleryTitle() that should work even if the GalleryObject isn't saved yet.
public function getGalleryTitle()
{
$parentID = Session::get('CMSMain')['currentPage'];
if ( $parentID )
{
$gallery = Page::get()->byID( $parentID );
$filter = new URLSegmentFilter();
return $filter->filter( $gallery->Title );
}
else{
return 'default';
}
}
First, I check to see whether we're on the CMSSettingsPage or in a ModelAdmin page (Should you be using them). You want to get all the information about which class the controller is managing as it's data record. (If you have firebug, FB($this) in getCMSFields() on the related DataObject (DO) will show you the page managed under DataRecord)
Controller::curr()->currentPage() will get you the current page the DO is being managed on, and ->URLSegment will get the page url name, though you could use Title or MenuTitle also.
Here is an example which will set up a folder underneath assets/Headers to save images in. Running this on the HomePage (ie URL Segment 'home') will create and save objects into the folder /assets/Headers/home.
if (Controller::curr()->class == 'CMSSettingsController' || Controller::curr() instanceof Modeladmin) {
$uploadField->setFolderName('Headers');
}
else
{
$uploadField->setFolderName('Headers/' . Controller::curr()->currentPage()->URLSegment);
}

Edit content in ckeditor

iam using ckeditor in my website to add the content to the pages.
But I'm not able to understand how I get this content in ckeditor for editing it later...
How to load content into the ckeditor? Iam using the following code to load the editor:
if ( !#file_exists( '../../ckeditor/ckeditor.php' ) )
{
if ( #file_exists('../../ckeditor/ckeditor.js') || #file_exists('../../../ckeditor/ckeditor_source.js') )
printNotFound('CKEditor 3.1+');
else
printNotFound('CKEditor');
}
include_once '../../ckeditor/ckeditor.php';
include_once '../../ckfinder/ckfinder.php';
// This is a check for the CKEditor class. If not defined, the paths in lines 57 and 70 must be checked.
if (!class_exists('CKEditor'))
{
printNotFound('CKEditor');
}
else
{
$ckeditor = new CKEditor();
$ckeditor->basePath = '../../ckeditor/';
$ckfinder = new CKFinder();
$ckfinder->BasePath = '../../ckfinder/'; // Note: BasePath property in CKFinder class starts with capital letter
$ckfinder->SetupCKEditorObject($ckeditor);
$ckeditor->editor('message');
}
One way is to pre-populate the <textarea> field with the appropriate (htmlentities() processed) HTML content. CKEditor will automatically fetch the data, and insert it into the WYSIWYG editor.
See the Integration chapter in the developers guide
For those who not found the answer, the "editor" method of ckeditor allow to load default value
public function editor($name, $value = "", $config = array(), $events = array())
Just pass your default value in the second parameters.

Categories