How do we iterate over the object that implements iterator - php

Iam rendering a menu (using Zend framework) (zend_navigation)
what iam doing is getting the page as label if the page has the value "myPage"
than then iam setting the new URI with the page as expected
$it = new RecursiveIteratorIterator(
$container, RecursiveIteratorIterator::SELF_FIRST);
foreach ($it as &$page) {
$label = $page->label;
if($label = "MyPage"){
$newuri = "mypage.php?stcode=".$stcode."&cde=".$cde;
$page->setUri($newuri);
}
}
In the above statement iam getting an error
"An iterator cannot be used with foreach by reference".
I want to use reference so that based on the label i can point the page to new uri
Now my problem and all the menu items in the menu are getting the same URI .

Does it work without the & ? Objects are passed by reference by default in PHP, so calling setUri should (in theory) modify the original object. Also note that your if statement is doing an assignment ($label = "MyPage") rather than a comparison ($label == "MyPage").
Assuming $container is your Zend Navigation object, the component has methods to make this easier anyway, so you should be able to simplify your code to:
$page = $container->findByLabel('MyPage');
$page->setUri("mypage.php?stcode=".$stcode."&cde=".$cde);
See http://framework.zend.com/manual/en/zend.navigation.containers.html#zend.navigation.containers.finding for some more examples.

Related

OctoberCMS get list of content files

Trying to get content files started with cont*
using :
Content::loadCached('theme', 'listOfContentFiles');
And getting an error.
I can get one but not the list.
Seems there is no direct way of doing it, you can use this code to get list manually and filter it by your self
use Cms\Classes\Content;
use Cms\Classes\Theme;
$activeTheme = Theme::getActiveTheme();
$instance = Content::inTheme($activeTheme);
$items = $instance->newQuery()->lists('fileName');
$loadedItems = [];
foreach ($items as $item) {
// we need to manually filter data you can
// add more logic here for sub directory parsing etc
if(starts_with($item, 'cont_')) {
$loadedItems[] = Content::loadCached($activeTheme, $item);
}
}
dd($loadedItems);
// if you want to make it collection
$result = $instance->newCollection($loadedItems);
it will return you list of content files in active theme by our filter logic.

Why Do I need an Assignment Operator in This Statement?

I'm playing around with some different design patterns to teach myself more about them, and started using DI Containers.
Main Code (index.php)
$container = new \League\Container\Container();
$container->add("config", function(){
return new Config(APP_ROOT . "/config.json");
});
$container->add("GoogleBooks", GoogleBooksProvider::class)
->withArgument( $container['config'] );
$container->add("books", BookRepository::class);
// empty array, as expected
var_dump($container['books']->getProviders());
// this line doesn't add the provider
$container['books']->addProvider( $container['GoogleBooks'] );
// empty array, should expect to have one entry, GoogleBooksProvider
var_dump($container['books']->getProviders());
BookRepository::addProvider
public function addProvider( iProvider $provider ) {
$this->_providers->push($provider);
return $this;
}
That doesn't work as expected, problem described in the code comments. However, if I swap
$container['books']->addProvider( $container['GoogleBooks'] );
with
$container['books'] = $container['books']->addProvider( $container['GoogleBooks'] );
it works correctly, by storing the GoogleBooksProvider in the BookRepository. Why do I need an assignment operator to make that work correctly?
If I do it without putting it in the container, it works as I expected, without the assignment operator.
$br = new BookRepository();
$br->addProvider( new GoogleBooksProvider($container['config']) );
// shows GoogleBooks is in the _providers array
var_dump($br->getProviders());
Since you are adding, but not sharing the service, you fetch a new instance of BookRepository every time you access the container:
var_dump($container['books'] === $container['books']); // false
If you want to share BookRepository, you need to use this:
$container->add("books", BookRepository::class, true);
or (shorter)
$container->singleton("books", BookRepository::class);

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
}
}

Neo4j php addLabels

I am beginner with Neo4j Rest API. I am using Everyman php library to develop my application. I have problem with creating node with labels.
use Everyman\Neo4j\Client,
Everyman\Neo4j\Transport,
Everyman\Neo4j\Node,
Everyman\Neo4j\Relationship;
use Everyman\Neo4j\Cypher;
public function indexAction()
{
$client = new Client('localhost', 7474);
$user = new Node($client);
$user->setProperty('name', 'Rohan Chingula');
$user->save()->addLabels(array('Users'));
}
while I run code I am getting
/var/www/zf2-tutorial/vendor/everyman/neo4jphp/lib/Everyman/Neo4j/Command/SetLabels.php:43
Message:
Cannot set a non-label
Try this:
$userLabel = $client->makeLabel('Users');
$user->save()->addLabels(array($userLabel));
User::addLabels expects an array of Label objects.
https://github.com/jadell/neo4jphp/wiki/Labels#wiki-adding-labels-to-a-node
Aside: if adding a bare string as a label is functionality you would like to see, please submit a feature request: https://github.com/jadell/neo4jphp/issues
I'm no PHP coder, but a quick look at the source suggests you should be passing an array of Label objects not strings. Your code is not using Everyman\Neo4j\Label
$labelSet = implode(':', array_map(function ($label) {
if (!($label instanceof Label)) {
throw new InvalidArgumentException("Cannot set a non-label");

Drupal 7 Render a Comment Object

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.

Categories