Silverstripe 3 - LinkingMode() for Dataobject - silverstripe

I created this function to show dataobjects as page
// DISPLAY ITEM AS PAGE
public function produkt(SS_HTTPRequest $request) {
$urlSegment = $this->request->param('URLSegment');
$item = ShopItem::get()->filter('URLSegment', $urlSegment)->first();
if( $item ) {
$data = array(
'Item' => $item,
'Title' => $item->Title,
'Parent' => Shop::get()->First(),
'Controller' => $this,
'URLSegment' => $item->URLSegment
);
return $this->customise($data)->renderWith(array('ShopItem', 'Page'));
} else {
return $this->httpError(404);
}
}
That's my YML File
---
Name: productRoute
After: 'framework/routes#coreroutes'
---
Director:
rules:
'onlineshop//produkt/$URLSegment!': 'Shop_Controller'
The function is on my Shop_Controller. and the Dataobjects are shown under onlineshop/produkt/blablabla-1
That works fine but in the navigation the link "Onlineshop" is not highlight as section.
I think I need to put the "LinkinMode()" function in my dataobject. But I don't know what the function should contain. return section current or link doesen't work.
Can someone help me?
thank you in advance

You just want to highlight "Onlineshop" which is a Page in your SiteTree, right?
If so, just override the LinkingMode() method inside that Class (extending SiteTree) and make it return section or current for your custom route being active...
You would just need that method on the DataObject itself if you would like to show each DataObject in the Navigation and highlighted when active.
see http://www.ssbits.com/tutorials/2010/dataobjects-as-pages-part-1-keeping-it-simple/

Related

wp_link_query: Classic editor link popup adds custom CPT links again and again

When I integrate my CPT into the link search of the Classic Editor, it is at first displayed correctly.
But if there are more links in the list than can be displayed at the same time (overflow) and I then scroll up and down again, the list is updated by Wordpress via Ajax and my CPT links are appended again, so that the link list becomes longer and longer.
The default Wordpress links (post, page) on the other hand do not, even though my ID and the permalink in the $results array are unique.
There is nothing more than ID, title, permalink and info in the original $results array.
How can I prevent the appending?
add_filter('wp_link_query', array($this, 'wp_link_query'), 10, 2);
[...]
public function wp_link_query($results, $query) {
[...]
$results[] = array(
'ID' => $id,
'title' => $title,
'permalink' => $permalink,
'info' => $info
);
return $results;
}
The solution was to add the custom post type to the link query args first:
add_filter('wp_link_query_args', array($this, 'wp_link_query_args'), 10, 1);
[...]
public function wp_link_query_args($query) {
$query['post_type'][] = 'my_cpt';
return $query;
}
´´´´
But you have to still use the 'wp_link_query' filter to add the "info" of the link popup table. Otherwise Wordpress outputs "Null" for the custom post type.

Display user's data from database on their profile pages

In Drupal 7, is it possible to show a result of a DB query on each users' respective profile page, in some table? I need to do this programmatically within my existing module. So the input to the query would be the ID of a user whose profile is currently being viewed.
Only to show the queried data - no administration, no edits, nothing else.
something along the lines of.. (image)
Also the block or field or whatever would make this possible needs to be configurable through the _permission() hook as to who can or cannot view it.
I thought since this is basically just a query with no extra custom stuff there would be an easy way via the Drupal API.
you can create custom block for that and view it in current user profile
/**
* Implements hook_block_info().
*/
function custom_block_block_info() {
$blocks = array();
$blocks['my_block'] = array(
'info' => t('My Custom Block'),
'status' => TRUE,
'region' => 'Content',
'visibility' => BLOCK_VISIBILITY_LISTED,
'pages' => 'user/*',
);
return $blocks;
}
/**
* Implements hook_block_view().
*/
function custom_block_view($delta = '')
{
// The $delta parameter tells us which block is being requested.
switch ($delta)
{
case 'my_block':
// Create your block content here
$block['subject'] = t('This is just a test block created programatically');
$block['content'] = _user_detail_list();
break;
}
return $block;
}
/**
* Implements costome code we want to print().
*/
function _user_detail_list(){
//enter your query and output in some variable
$value = "<p>User Detail</p>"
return $value;
}
Note :- Here profile is extended with new block
There will be some coding to get what you want, but if you just want style/show the data that's already available with the "user" object then #1 below will do it.
Easy way(#1):
1. Create a view and choose the "user" info that you need shown and give it a path. Then in your sub-theme use the correct template -see the code snippets.
https://www.drupal.org/forum/support/post-installation/2011-04-04/modify-the-default-profile-pagelayout
other ways:
use the user-profile.tpl.php see
https://api.drupal.org/api/drupal/modules%21user%21user-profile.tpl.php/7.x
in your module, you need to call and reach out to the hook_user_view.
https://api.drupal.org/api/drupal/modules%21user%21user.api.php/function/hook_user_view/7.x
Here you fetch user profile data from database then follow it
function modulename_menu() {
$items['user-data'] = array(
'title' => 'User data',
'page callback' => 'user_data',
'access callback' => ('user_is_logged_in'),
'#type' => MENU_NORMAL_ITEM,
);
return $items;
}
function user_data(){
global $user;
$user_fields = user_load($user->uid);
$output = "" //return those $user_fields values into table using theme('table',header,rows)
return $output;
}
https://www.drupal.org/node/156863 (for create table view)
i.e
global $user;
$user_fields = user_load($user->uid);
$firstname = $user_fields->field_firstname['und']['0']['value'];
$lastname = $user_fields->field_lastname['und']['0']['value'];

SilverStripe - Adding 2 TreeDropdownFields, only one works

I've run into a very bizarre issue while creating 2 TreeDropdownFields for a DataObject. For some reason, only 1 of the 2 TreeDropdownFields render correctly in the SilverStripe admin. The other doesn't render as a TreeDropdownField at all but just as a label:
Here is the code:
class HomeBanner extends DataObject {
public static $db = array(
'SortOrder' => 'Int',
'Title' => 'Varchar'
);
public static $has_one = array(
'Image' => 'Image',
'SecondaryImage' => 'Image',
'FirstLink' => 'SiteTree',
'SecondLink' => 'SiteTree'
);
public function getCMSFields() {
$fields = parent::getCMSFields();
$fields->removeFieldFromTab('Root.Main', 'PageID');
$fields->removeFieldFromTab('Root.Main', 'SortOrder');
$fields->addFieldToTab('Root.Main', new TreeDropdownField('FirstLinkID', 'First Link', 'SiteTree'));
$fields->addFieldToTab('Root.Main', new TreeDropdownField('SecondLinkID', 'Second Link', 'SiteTree'));
return $fields;
}
public static $summary_fields = array(
'ID' => 'ID',
'Title' => 'Title',
'Thumbnail' => 'Thumbnail'
);
public function getThumbnail() {
return $this->Image()->CMSThumbnail();
}
}
Here is what I have tried so far:
running dev/build/?flush=true
running ?flush=all and ?flush=1
logging out and logging back in after the dev/build + flushes
logging into the admin in another browser (I typically use Chrome but
logged into the site's admin on FireFox and saw the same problem)
The error logs report nothing -- they're clear
There are no errors in the console for Chrome's dev tools
Adding a third TreeDropdownField will allow the first 2 to render
properly but the third one will just show a label instead of a
TreeDropdownField
This format works, but doesn't save whatever is selected--it clears your choice as soon as you leave the page. Also, it deletes all that was saved already in the admin unless I remove it. I can't make changes or else the items saved get removed.):
$fields->addFieldToTab('Root.Main', new TreeDropdownField('SecondLink', 'Second Link', 'SiteTree', 'ID'));
Does anyone have any ideas as to why this could be happening? It doesn't seem to make sense that you can't have multiple TreeDropdownFields.
Reposting as this turned out to be the answer:
The name “HomeBanner” suggests to me that there should also be a has_one pointing back to HomePage or similar? The cause of this is probably that SilverStripe is automatically trying to set one of the has_one relations to point back to the page that the banner belongs to.
Similar conflicts can also happen when using code like this:
class Page extends SiteTree {
private static $has_many = [
'Banners' => 'Banner'
];
}
class Banner extends DataObject {
private static $has_one = [
'Page' => 'Page',
'LinkedPage' => 'Page'
];
}
As SilverStripe doesn't know whether it should use PageID or LinkedPageID to auto-populate that side of the has_many relation (GridField will try to automatically assign the correct has_one ID).
In these cases, you can use dot-notation to distinguish between them - you’d change it to $has_many = ['Banners' => 'Banner.Page'];. See https://docs.silverstripe.org/en/3/developer_guides/model/relations/#has-many for more info.

Drupal7 | Custom Module | How to Display Template?

I'm having trouble figuring out how to display a template that lives inside of my custom module.
This is what I have:
<?php
function brl_footer_theme($existing, $type, $theme, $path) {
$theme = array();
$theme['brl_footer'] = array(
'render element' => 'content',
'template' => 'brl-footer',
'path' => drupal_get_path('module', 'brl_footer'),
);
return $theme;
}
/**
* Implements hook_block_info().
*/
function brl_footer_block_info() {
$blocks = array();
$blocks['brl_footer'] = array(
'info' => t('Custom Footer'),
);
return $blocks;
}
I have a template file in the module called brl-footer.tpl.php
It contains very basic HTML:
<h1>here's some content</h1>
Is it possible to display my template through the custom block 'brl_footer' that's being created?
The custom block is active and has been assigned to the proper region.
Any help on this would be hugely appreciated -
You'll need to implement hook_block_view to define what gets displayed in your block.
Also, if your template is just static content, you don't need to specify a "render element" or "variables" for your theme hook (though you could still make variables in a preprocess function).

Using Drupal's node form in a new page

In a custom module I want to have a page defined in hook_menu, that shows the add form for a specific content type, with some modifications to the form.
So far it's working, and even saving the new node, but only with the default values I'm setting in the code, i.e. it's not picking up anything the user types into the form. I checked and $form_state['input'] contains the inputted values, but $form_state['values'] doesn't, so the new node gets saved wrong.
Here's the relevant code:
function mymodule_menu() {
return array(
'admin/content/myadd/%' => array(
'title' => 'my custom add page',
'page callback' => 'mymodule_node_add',
'page arguments' => array(3),
'access callback' => TRUE,
'type' => MENU_CALLBACK,
),
);
}
function mymodule_node_add() {
module_load_include('inc', 'node', 'node.pages');
//I'm doing a print here instead of returning because I'm calling this page
//in an AJAX popup, so I don't want the whole page to output, only the form.
print render(drupal_get_form('mymodule_node_add_form'));
}
function mymodule_node_add_form($form, &$form_state) {
if (!isset($form_state['node']) {
global $user;
$node = (object) array(
'uid' => $user->uid,
'type' => 'mycontenttype',
'language' => LANGUAGE_NONE,
);
//this is setting a default value
$node->myfield = array(LANGUAGE_NONE => array(array('value' => arg(3))));
$form_state['build_info']['args'] = array($node);
$form = drupal_build_form('mycontenttype_node_form', $form_state);
$form['actions']['submit']['#submit'][0] = 'mymodule_node_add_form_submit';
//there's a lot more customization of the form here, like adding fields, etc.
}
return $form;
}
function mymodule_node_add_form_submit($form, &$form_state) {
//here's where $form_state['input'] is correct but $form_state['values'] isn't.
$node = node_form_submit_build_node($form, $form_state);
node_save($node);
$form_state['values']['nid'] = $node->nid;
$form_state['nid'] = $node->nid;
$form_state['redirect'] = 'some/other/page';
}
So, am I doing something wrong here? Should I be concerned about form ids being wrong? (my form's id is mymodule_node_add_form, but the actual form might output mycontenttype_node_form), would this affect me?
You want hook_form_alter() (see api.drupal.org). I would try to use the existing content type's form and simply alter it with hook_form_alter(). I would also try to first get it working as a standard, non-AJAX page, so you can get all the advantages of dpm() and other debugging techniques. When you have it down solid, then modify it to take advantage of the AJAX techniques.
mymodule_form_alter(&$form, &$form_state, $form_id) {
// use this with your devel module turned on to verify
// your $form_id and contents of all forms that load on a given page
dpm($form);
// once you verify your $form_id, you can begin accessing your form and altering it
switch( $form_id ) {
case 'my_target_form_id' :
// this part is just pseudocode, I haven't memorized the $form structure,
// you can get it from your dpm().
if( $form['node']->type == 'my_target_content_type' ) {
$form['actions']['submit']['#submit'][0] = 'mymodule_node_add_form_submit';
}
break;
}
}

Resources