I made a private section on a drupal site by writing a module that checks the RERQUEST_URI for the section as well as user role. The issue I am running into now is how to prevent those nodes/views from appearing in the search.
The content types used in the private section are used in other places in the site.
What's the best way to get Druapl search to ignore the content/not index/not display it in search results?
There is a wonderful article that explains just this on the lullabot site.
It's worth reading the comments to the post too, because people there suggested alternate ways of doing that, also by mean of contrib modules (rather than implementing some hooks in your own code). Code for D6 is in the comment as well.
HTH!
The lullabot article is a bit outdated and contains many blunt approaches. It also contains the answer in the comments - the Search Restrict module which works for DP6 and allows fine-grained and role-based control. Everything else either prevents content from being indexed, which may not be desirable if there are different access levels to content, or affects all search queries equally, which will also not work if there are different access levels.
If the content types used within the Private section are also used elsewhere how are you hoping to filter them out of the search results (note that I've not looked at the lullabot article by mac yet).
Basically, if you look at the details of two nodes, one private and one public, what differentiates them?
Note: I'm assuming that you want the nodes to appear to users with access to the Private area but not to 'anonymous' users.
For Drupal 7.
You can hide the node from search results by using custom field. In my case, I have created a custom field in the name of Archive to the desired content type and with the help of that custom field you can write the my_module_query_alter functionality.
Code
function my_module_query_alter(QueryAlterableInterface $query) {
$is_search = $is_node_search = FALSE;
$node_alias = FALSE;
foreach ( $query->getTables() as $table ) {
if ( $table['table'] == 'search_index' || $table['table'] == 'tracker_user') {
$is_search = TRUE;
}
if ( $table['table'] == 'node' || $table['table'] == 'tracker_user') {
$node_alias = $table['alias'];
$is_node_search = TRUE;
}
}
if ( $is_search && $is_node_search ) {
$nids = [];
// Run entity field query to get nodes that are 'suppressed from public'.
$efq = new EntityFieldQuery();
$efq->entityCondition('entity_type', 'node')
->fieldCondition('field_archive', 'value', 1, '=');
$result = $efq->execute();
if ( isset($result['node']) ) {
$nids = array_keys($result['node']);
}
if ( count($nids) > 0 ) {
$query->condition(sprintf('%s.nid', $node_alias), $nids, 'NOT IN');
}
}
}
Related
I am using Drupal 7 with the search api. I understand that one of the 'common pitfalls' of the search api is 'Changes in related entities don't lead to re-indexing'. I am bringing in a field called 'Collection Reference' in my search api index as 'type = content' . So when the title of a collection changes the search API doesn't realise it changes.
I have tried to sort this using the rules module as discussed - https://www.drupal.org/docs/7/modules/search-api/getting-started/common-pitfalls#indirect-changes - but I have not been able to get it working. Has anybody had any luck with this technique?
I solved the issue.
In my case I have photographs in an index and they have a gallery as an entity field and the galleries were not updating if they were modified in the photo index. So grabbed all of the photos relating to that gallery using SQL then put into a dirty ids array. So the code below:
function hook_entity_presave($entity, $type) {
if ($entity->type == 'MYCONTENTTYPE') {
if ($entity->original->title !== $entity->title) {
$dirty_ids = array();
$nid = $entity->nid;
$result = db_query('SELECT g.entity_id FROM {gallery} g WHERE c.id = :nid', array(':nid' => $nid));
foreach($result as $record) {
$dirty_ids[] = $record->entity_id;
}
if(!empty($dirty_ids)) {
search_api_track_item_change('node', $dirty_ids);
}
}
}
}
I'm working on a moodle module, and when I arrived on this project, the module was already created. The problem is when I'm trying to add it in a course, the module appears in the resources section and I would like to put it in the activities section. How can I do that?
The pop up where I want my module to appear as activity
The code, that separates modules into groups, simply checks the constant prefixed MOD_ARCHETYPE_:
foreach ($modules as $module) {
$activityclass = MOD_CLASS_ACTIVITY;
if ($module->archetype == MOD_ARCHETYPE_RESOURCE) {
$activityclass = MOD_CLASS_RESOURCE;
} else if ($module->archetype === MOD_ARCHETYPE_SYSTEM) {
// System modules cannot be added by user, do not add to dropdown.
continue;
}
$link = $module->link->out(true, $urlparams);
$activities[$activityclass][$link] = $module->title;
}
As we can see, it simply checks "archetype" property.
Find function YOURMODULENAME_supports in /mod/yourmodulename/lib.php
It should have a string like
case FEATURE_MOD_ARCHETYPE: return MOD_ARCHETYPE_RESOURCE;
Comment it out. The module should now be in activity section (default)
Hello gods of Stackoverflow,
Now i hate to be "that guy" who didnt search properly but i am running into a problem that i need a fix for and can't find a solution i can work with because of my lack in coding skills, my knowledge barely tickles the surface.
Here's the thing.
I am using a tool to import feeds into my website (WP all Import) as woocommerceproducts. But in the categorization the feed suppliers made errors which i want to tackle without emailing them everytime i stumble upon one.
i.e: the title contains words like satchel, bag, clutch etc but the product is categorized as 'jewellery > earrings' in the CSV or XML.
The import tool will ask me where to find the product category, i point it to the node {category[1]}
But when the category is missing or faulty i want it to check the title for certain words, and if present change the value of it to that found word.
something like:
[if ({title[1]}contains "satchel") {
category = "bags > satchel",
} else if ({title[1]} contains clutch) {
category = "bags > clutch",
} else {
category = {sub_category[1]} #the normal value if nothing was found
}]
I just can't find the pieces to put the formatting together. I might need to work towards a function that i could expand to generate categories based solely out of presence of certain words in the title but maybe when i get better that would be an option.
I hope i was able to provide a clear view on the problem. The "[ ]" is there because thats how the plugin wants code to be entered instead of a {fieldname[1]}, another example below:
The following was an example of a problem i was able to fix:
i needed to replace values like "0/3months/1/2months" to "0-3 months/1-2months" before i replaced the slash"/" with a pipe"|" for wordpress to recognize it as a seperate value.
[str_replace("/","|",
str_replace("0/3","0-3",
str_replace("1/2","1-2",
str_replace("3/6","3-6",{size[1]}))))]
The fields can also be used to call functions but only in the 'pro' version of the plugin.
Any help is very much appreciated, thanks in advance.
You could use strpos.
Example:
if (strpos($title, "satchel") !== false) {
$category = "bags > satchel";
}
So after an afternoon of poking around, testing stuff, and not knowing alot about php i came up with a solution with help from a friend.
Wp All Import does not allow custom php directly from the field itself, it does however support custom php functions and provides an editor for these on the bottom of the import configuration page. I did the following:
<?php
//Checks Title for keywords and
//uses those to create categories
//We are using our own Main categories so only
//sub and subsub categroies need to be created.
//Call function
[get_subcat_from_title({title[1]},{category[1]})]
//Function
function get_subcat_from_title($title,$defaultcat)
{
if (strpos($title,"Satchel") !== false) {
$cat = "Tassen";
} elseif (strpos($title,"Travel") !== false) {
$cat = "Tassen";
} elseif (strpos($title,"Gusset") !== false) {
$cat = "Tassen";
} else {
$cat = $defaultcat;
}
return $cat;
}
//Checks Title for keywords and uses those to create subcategories
//Call Function
[get_subsubcat_from_title({title[1]},{sub_category[1]})]
//Function
function get_subsubcat_from_title($title,$defaultcat)
{
if (strpos($title,"Satchel") !== false) {
$cat = "Satchel";
} elseif (strpos($title,"Travel") !== false) {
$cat = "Travel";
} elseif (strpos($title,"Gusset") !== false) {
$cat = "Gusset";
} else {
$cat = $defaultcat;
}
return $cat;
}
?>
On the Taxonomies, Tags, Categories option we can create our own hierarchical order like this:
[main category]
+[sub category]
++[sub sub category]
The main category field is given a name we use as our main category.
The sub category is filled with function SUBCAT
The subsub category is filled with function SUBSUBCAT
this way it will create a parent by our own name, a child that has the named 'Tassen' if any keyword is present, and a grandchild with the specific keyword as it's name.
This way i can expand the function using all kinds of statements when the right category isn't present in de provided feed.
thanks #sebastianForsberg for responding.
I hope this helps anyone who comes across a similar problem in the future..
I'm trying to retrieve the number of parking lots from a .txt file, its working on the static site iframe but I want to make a shortcode and place it on wordpress theme function file.
For some reason it's not reading the data...
function GenerateLOT($atts = array()) {
// Default Parameters
extract(shortcode_atts(array(
'id' => 'id'
), $atts));
// Create Default Park / Help
if ($id == '') {
$id = 'PARK IDs: bahnhofgarage;';
}
// Create Park Bahnhofgarage
if ($id == 'bahnhofgarage') {
$completeBahnhof = "//xxx.de/bahnhof.txt";
if(file_exists($completeBahnhof )) {
$fp=file($completeBahnhof );
$Garage = $fp[0];
$valmpl=explode(" ",$Garage);
$Bahnhof_Platz = $valmpl[0];
$Bahnhof_Tendenz = $valmpl[1];
}
$id = $Bahnhof_Platz;
}
return $id;
}
add_shortcode('parking', 'GenerateLOT');
[parking id='bahnhofgarage']
PS: The .txt is working properly retrieving like this: 000 - //bahnhof 27.12.15 12:46:59
For some reason its only displaying the $park == '' text and not the parking lots according shortcode param.
I've used this tutorial: sitepoint.com/wordpress-shortcodes-tutorial/
EDIT: There are 6 parking lots.
EDIT2: Changed park to id on all instances
The problem is that you can't meaningfully use file_exists on remote path. See SO answer to "file_exists() returns false even if file exist (remote URL)" question for details.
You should probably just call file() on that path. It will return FALSE if it encounter an error.
if ($id == 'bahnhofgarage') {
$completeBahnhof = "//xxx.de/bahnhof.txt";
$fp=file($completeBahnhof );
if ($fp !== false) {
$Garage = $fp[0];
// rest of code
On a side note, shortcode_atts() is used to provide default values for shortcode attributes, while you seem to be using it as some sort of mapping between shortcode attributes and internal variable names.
Accessing file on remote server inside shortcode is asking for trouble. Just think what will happen if this server is overloaded, slow to respond or not available anymore. You should really access that file asynchronously. If it is located on your server, access it through file-system path.
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
}
}