passing a parameter from a content type to a module - twig

I assumed this would be easy but I am stumped.
I have a custom content type that includes an id field. I render these with a basic page template.
I have written a small module that creates a block which is populated with data from an external API. Everything works except I cannot seem to figure out how to pass the value of the id from the content of a given page to my module so it can make the API call.
It would be a couple of lines of code in straight php, it can't be that complicated in Drupal 8 and twig can it?

I managed to find a solution here
I am re-posting it in case it is useful to anyone else.
If you are generating a custom block you can access content fields via the routing system inside your block build function like this:
public function build() {
if ($node = \Drupal::routeMatch()->getParameter('node')) {
$field_my_custom_value = $node->field_my_custom_value->value;
}
//do something with the variable, like make the API call
//Make sure to set the cache to the context or even to zero if you need
return array(
'#markup' => $this->t('my content to render'),
'#cache' => array(
'contexts' => ['contexts' => ['route']],
),
);
}

I think you can reach what you want with a HOOK_preprocess.
use:
YOUR_MODULE_preprocess_node(&$variables){ ... } or
YOUR_MODULE_preprocess_block(&$variables){ ... }
to access your variable from the content type and pass it to your function oder template.

Related

How to use a librarie in views in Codeigniter4

i trie to use a own library in a view, but it failed with "undefined property: CodeIgniter\View\View::$mylib"
This is the Base Controller
protected $mylib;
/**
* Constructor.
*/
public function initController(\CodeIgniter\HTTP\RequestInterface $request, \CodeIgniter\HTTP\ResponseInterface $response, \Psr\Log\LoggerInterface $logger)
{
// Do Not Edit This Line
parent::initController($request, $response, $logger);
//--------------------------------------------------------------------
// Preload any models, libraries, etc, here.
//--------------------------------------------------------------------
// E.g.:
// $this->session = \Config\Services::session();
//Include our librarie with http-request
$this->mylib = new mylib(service('request'));
}
In the Controller i use it in this way, here i can work with my libray without any trouble. The testfunction will return a simple text.
namespace App\Controllers;
//Important to add our librarie (session, rbac, login etc.)
use App\Libraries\mylib;
...
die("Test: $this->mylib->testfunction());
If i try the same in my view file i recieve the error.
die("Test: $this->mylib->testfunction());
What i do wrong?
Update
In the meantime i find a way to work with my library in the views
at top of my view-file i add this
use App\Libraries\mylib;
$this->mylib = new mylib(service('request'));
It works, but is there a way to make the whole thing easier so that I don't have to write these lines in every view-file but maybe only once in e.g. Base-Controller?
What i do wrong?
You're assuming that because you created that Library in the Controller that it is automatically accessible in a View, which is incorrect, regardless if it's a class property of the Controller or not.
Anything that is not already in the View needs to be passed in when you "use" it (i.e. the view() function's second parameter). So you can either create the Library in the Controller and pass the entire object into the View, or continue creating it directly in the View as you're doing now.
The first option tends to be a little cleaner.

Can't pass GET parameter while unit testing Zend Framework 2

I'm having hard time trying to unit test (phpUnit) one of my modules in ZF2. What I'm trying to do is determine whether a classname is present on one of the elements on page when a GET parameter is passed to the controller.
It all works from the browser, however I can't get the GET parameter to be recognized at all when trying to unit test.
This is my code for unit testing:
<?php
namespace ComponentManager\Controller;
use Zend\Test\PHPUnit\Controller\AbstractHttpControllerTestCase;
class ComponentManagerControllerTest extends AbstractHttpControllerTestCase
{
public function setUp()
{
$this->setApplicationConfig(
include 'config/application.config.php'
);
parent::setUp();
}
public function testAdminComponentCodeCanBeAccessed()
{
$this->dispatch('/ComponentManager/requestComponent/product/details-1/details-1', 'GET', array('admin' => 1));
// I also tried: $this->dispatch('/ComponentManager/requestComponent/product/details-1/details-1?admin=1');
$this->assertResponseStatusCode(200);
$this->assertMatchedRouteName('ComponentManager/path');
$this->assertControllerName('ComponentManager\Controller\ComponentManager');
$this->assertControllerClass('ComponentManagerController');
$this->assertActionName('requestComponent');
$this->assertModuleName('ComponentManager');
// test will fail here
$this->assertQuery('div.config-active-wrapper');
}
}
The "div.config-active-wrapper" selector works fine when I remove the check for admin parameter presence in GET but when I re-add it, the GET parameter doesn't get recognised at all. Any ideas?
The problem here was that unit testing is a CLI operation and no superglobals are being populated while in CLI. Simple and stupid :P
A solution is to not use superglobals like $_GET here but to pass this "admin" parameter via some ACL and a controller instead.

How to access values from alfresco-global.properties in freemarker and YUI javascript files

I have numerous custom variables in Alfresco's alfresco-global.properties file that I'd like to use throughout various freemarker ftl files as well as the various YUI files, which will greatly alter the behavior of Share and how it displays information.
I have the property values accessible through various javascript calls (for example, getNetworkName() will return the custom app.network.name variable set in the properties), but I am uncertain of how I'd expose these javascript functions to either freemarker or the YUI files, or if I even need to, as opposed to just accessing the variables directly.
If you have defined global variables and functions you don't need to do anything special to access them from YUI.
You can optionally do something like this to take advantage of YUI's sandboxing ability so that each sandbox can't affect the other by changing the global configuration:
YUI_config = {
app: {
network: {
name: 'foo' // or getNetworkName()
}
}
};
YUI().use('node', function (Y) {
console.log(Y.config.app.network.name); // foo
Y.config.app.network.name = 'bar';
});
YUI().use('tabview', function (Y) {
console.log(Y.config.app.network.name); // still foo!
});

Orchard Custom User Part is not stored in Database

I can't seem to store additional data in a separate contentpart attached to User. I have done the following:
Created a module
In the module I created a Model for ProfilePart and ProfilePartRecord
In the migration I created a table for ProfilePartRecord (from type ContentPartRecord)
In the migration I altered the typedefinition for User, by setting WithPart ProfilePart
I created a driver class, that has 2 edit methods, one for get and one for post (code snippets are below
I also created a handler that adds a storage filter for profilePartRepository of type ProfilePartRecord
Module Structure
Drivers/ProfilePartDriver.cs
Handlers/ProfileHandler.cs
Models/ProfilePart.cs
Models/ProfilePartRecord.cs
Views/EditorTemplates/Parts/profile.cshtml
Migrations.cs
Placement.info
Since I think the issue is in the Driver. This is my code:
Is it going wrong because the part is attached to User? Or am I missing something else.
public class ProfilePartDriver:ContentPartDriver
{
protected override string Prefix
{
get { return "Profile"; }
}
//GET
protected override DriverResult Editor(ProfilePart part, dynamic shapeHelper)
{
return ContentShape("Parts_Profile_Edit", () =>
shapeHelper.EditorTemplate(TemplateName: "Parts/Profile", Model: part, Prefix: Prefix));
}
//POST
protected override DriverResult Editor(ProfilePart part, IUpdateModel updater, dynamic shapeHelper)
{
updater.TryUpdateModel(part, Prefix, null, null);
return Editor(part, shapeHelper);
}
}
I have used Skywalker's blog. There is one chapter about registering customers by using the User and adding your own content parts to it. Worked nice for me.
First of all - is your ProfilePart editor shown at all when you go to Dashboard and edit a given user? I noticed you're using Parts_Profile_Edit as a shape key, but actually use EditorTemplates/Parts/Profile.cshtml as a template. It's perfectly correct, but note that Placement.info file uses shape keys, so you have to use Parts_Profile_Edit as a shape name in there. Otherwise it won't get displayed.
Second - have you tried debugging to see if the second driver Editor method (the one for handling POST) is being called at all?
Like Bertrand suggested, I'd look into one of the existing modules that work (afaik there is one for user profile in the Gallery) and see the difference. It might be something small, eg. a typo.

Kohana multiple default controllers based on roles

I want to display completely different layouts for users in different roles on the root url of my application. I am currently achieving this using the following lines in bootstrap.php.
if (Auth::instance()->logged_in()){
Route::set('default', '(<controller>(/<action>(/<id>)))')
->defaults(array('controller' => 'profile','action' => 'index',));
}
else{
Route::set('default', '(<controller>(/<action>(/<id>)))')
->defaults(array('controller' => 'welcome','action' => 'index',));
}
What is the best practice to achieve this in Kohana? Is it ok to add more lines for different roles in bootstrap.php.
Thanks
you should consider using lambdacallback-route-logic
If allows you to modify the requested URL dynamically and much more cleaner than writing something in bootstrap.php
Why dont change basic template in ONE controller (and using the same route)? I think, your controller code doesn't differs if user logged in or not.
I do it like this:
Create an abstract class Controller_Rolebased where in before() method you can implement Role checking.
And then for example:
class Controller_Profile extends Controller_Rolebased
{
protected $_accept_roles = array('user', 'admin'); // this array Controller_Rolebased class will use in before method.

Resources