Question from Pro Drupal 7 Book: Annotate module - drupal-modules

So this is likely a shot in the dark, but for anyone out there who knows a bit of Drupal and better yet has implemented the annotate module from Ch. 2 of Pro Drupal 7 Development
Do you know how to alter the annotate module so all users can annotate? Right now, only the admin can annotate and it's being presented as an extension to editing.
The specific code being used is in this repository (pretty much straight from the book): http://github.com/dsharkey/Drupal-Module-Development--Annotate-Module
Further, I'm not really seeing how the annotate module is told to be presented at all? I believe its by the following lines of PHP (from annotate.admin.inc):
$instance = array(
'field_name' => 'annotation',
'entity_type' => 'node',
'bundle' => $key,
'label' => t('Annotation'),
'widget_type' => 'text_textarea_with_summary',
'settings' => array('display_summary' => TRUE),
'display' => array(
'default' => array(
'type' => 'text_default',
),
'teaser' => array(
'type' => 'text_summary_or_trimmed',
),
),
);
$instance = field_create_instance($instance);
But I'm not sure how that does anything more than create an instance and attach itself to a node. Why does it display where it does (as an option next to edit)?
Thanks all!

I'm not sure what you're referring to when you say "as an option next to edit", but the code you uploaded (and double-checking the book itself, the code used) wouldn't cause that. In fact, you should just see a field below the body field when you edit a node with annotations enabled:
The reason it only shows up when you edit an existing node (and not when you create a new node) is related to your first question about it not letting all users annotate the node: in the hook_node_load() implementation, it specifically checks to see if the user editing the node is the same as the owner of the node; if it isn't, it hides the annotation field:
/**
* Implements hook_node_load()
*/
function annotate_node_load($nodes, $types) {
global $user;
// Check to see if the person viewing the node is the author. If not then
// hide the annotation.
foreach ($nodes as $node) {
if ($user->uid != $node->uid) {
unset($node->annotation);
}
}
}
So the only person who should ever see the annotate field is the owner. If you want to allow anyone with edit access annotate the node, remove that function.
As for allowing anyone to make annotations to the node as a separate function to editing the node itself, that's not what the example was about and is entirely separate from the code used. You'll have to seek elsewhere for that and look at examples like the Drupal.org project Annotate for ways to do it. Basically, the annotations would be their own separate entities that would reference the node, much in the same way comments work.
But if I may be so bold, you've run into a big problem with Pro Drupal 7 Development in that it's not as good a reference for development as the previous editions were: it doesn't explain things very well, spends too much time on minor things and not enough time on really major things, introduces really bad practices (including several in the annotate example), and completely misses large sections of what Drupal 7 introduced. I'd recommend checking out Drupal 7 Module Development instead.

Related

Tell AutoMapper that a field is a top-level member

I am trying to take some of the pain out of creating mapping expressions in AutoMapper, using AutoMapper.QueryableExtensions
I have the following, which gives a critical performance gain:
private MapperConfiguration CreateConfiguration() {
return new MapperConfiguration(cfg => cfg.CreateMap<Widget, WidgetNameDto>()
.ForMember(dto => dto.Name,
conf => conf.MapFrom(w => w.Name)));
}
To understand the performance gain, see here: https://github.com/AutoMapper/AutoMapper/blob/master/docs/Queryable-Extensions.md The key is that the query is limited by field at the database level.
It's terrific that this works. But I anticipate needing to do a lot of this kind of projecting. I am trying to take some of the pain out of the syntax in the ForMember clause above.
For example, I've tried this:
public static IMappingExpression<TFrom, TTo> AddProjection<TFrom, TTo, TField>(this IMappingExpression<TFrom, TTo> expression,
Func<TFrom, TField> from,
Func<TTo, TField> to
)
=> expression.ForMember(t => to(t), conf => conf.MapFrom(f => from(f)));
The problem is that everything I do runs into an error:
AutoMapper.AutoMapperConfigurationException : Custom configuration for members is only supported for top-level individual members on a type.
Even if the passed in Funcs are top-level individual members, that fact is lost in the passing, so I hit the error. I've also tried changing Func<Whatever> to Expression<Func<Whatever>>. It doesn't help.
Is there any way I can simplify the syntax of the ForMember clause? Ideally, I would just pass in the two relevant fields.
First, there is no need to add mapping for the fields/properties that match by name - AutoMapper maps them automatically by convention (that's why it is called convention-based object-object mapper). And for including just some of the properties in the projection you could use the Explicit expansion feature.
Second, what you call a pain in the ForMember syntax is in fact a flexibility. For instance, the explicit expansion and other behaviors can be controlled by conf argument, so it's not only for specifying the source.
With that being said, what you ask is possible. You have to change the from/ to type to Expression:
Expression<Func<TFrom, TField>> from,
Expression<Func<TTo, TField>> to
and the implementation simply as follows:
=> expression.ForMember(to, conf => conf.MapFrom(from));

puppet class syntax clarification

Currently trying to understand the puppet manifests written by another person and met the following construction in the class:
postgres_helper::tablespace_grant { $tablespace_grants:
privilege => 'all',
require => [Postgresql::Server::Role[$rolename]]
}
what does $tablespace_grants: means in this case? First i suggested that is some kind of a title, however when i used notice to receive the value of it, it is hash:
Tablespace_grants value is [{name => TS_INDEX_01, role => developer},
{name => TS_DATA01_01, role => developer}]
what does $tablespace_grants: means in this case? First i suggested
that is some kind of a title,
It is a variable reference, used, yes, as the title of a postgres_helper::tablespace_grant resource declaration.
however when i used notice to receive
the value of it, it is hash:
Tablespace_grants value is [{name => TS_INDEX_01, role => developer},
{name => TS_DATA01_01, role => developer}]
Actually, it appears to be an array of hashes. An array may be used as the title of a resource declaration to compactly declare multiple resources, one for each array element. In Puppet 4, however, the elements are required to be strings. Earlier versions of Puppet would stringify hashes presented as resource titles; I am uncertain offhand whether Puppet 4 still falls back on this.
In any case, it is unlikely that the overall declaration means what its original author intended, in any version of Puppet. It looks like the intent is to declare multiple resources, each with properties specified by one of the hashes, but the given code doesn't accomplish that, and it's unclear exactly what the wanted code would be.

resource ordering synchronization issue "->" doesn't work?

I have encounter really weird behaviour which goes against what I have learned, tutorial says etc. So I would be glad if someone could explain why that is happening.
I have a role module which is made up of composition of profiles (role-profile pattern). My role consists:
class role::lab_prg_c2_dn inherits lab_prg_c2 {
class { 'profile::cluster_data_node':
namenode_fqdn => $role::lab_prg_c2::namenode_fqdn,
secondarynamenode_fqdn => $role::lab_prg_c2::secondarynamenode_fqdn,
}
->
class{'bigdatasolution':}
}
First class installs technology and second one installs our components and items which are build on top of technology. Hence the technology need to be installed first, thats the reason for "->" dependency. However this seems to me doesn't work correctly. As components from class 'bigdatasolution' are installed somewhere before the class profile::cluster_data_node finishes.
I tried to use require => Class['profile::cluster_data_node'] but that doesn't make any difference!
The content of class{'bigdatasolution':} :
class bigdatasolution {
$hdfs_default_conf = '/usr/local/hadoop.hdfs.conf'
$hbase_default_conf = '/usr/local/hadoop.hbase.conf'
include symlinks
include bdjar
}
Symlinks - create symlinks for the configuration installed in class profile::cluster_data_node and are not directly managed - it will be presented when actually specified package get installed.
bdjar - add our jar to a technology library so content is as follows:
class bigdatasolution::bdjar {
file { "/usr/lib/hadoop/lib/bigdata-properties.jar":
ensure => present,
mode => 0644,
group => 'root',
owner => 'root',
source => "puppet:///modules/bigdatasolution/bigdata-properties.jar"
}
}
I even tried to put require => "technologycalClass" here but that doesn't help either.
Can someone please help me understand what's wrong and how that should be solved properly?
I Using puppet 3 and ordering is specified explicetly - so no arbitrary ordering set by puppet should happen.
Thanks
If your 'profile::cluster_data_node' class 'includes' other classes/modules they will have no dependency ordering with the 'bigdatasolution' class.
I see you actually do include symlinks and bdjar. Basically every piece of ordering you want to have in puppet, you need to write explicitly.
Here you should replace the include statements with require, that way the class cluster_data_node will require the other two modules to complete before it says it has completed. Include is a pretty lose way of importing things in puppet and in my opinion is best to just avoid it and go with explicit require statements instead.
TL;DR: included modules have no transitive ordering; required modules do.

Ignore certain TypeScript compile errors?

I am wondering if there is a way to ignore certain TypeScript errors upon compilation?
I basically have the same issues most people with large projects have around using the this keyword, and I don't want to put all my classes methods into the constructor.
So I have got an example like so:
TypeScript Example
Which seems to create perfectly valid JS and allows me to get around the this keyword issue, however as you can see in the example the typescript compiler tells me that I cannot compile that code as the keyword this is not valid within that scope. However I don't see why it is an error as it produces okay code.
So is there a way to tell it to ignore certain errors? I am sure given time there will be a nice way to manage the this keyword, but currently I find it pretty dire.
== Edit ==
(Do not read unless you care about context of this question and partial rant)
Just to add some context to all this to show that I'm not just some nut-job (I am sure a lot of you will still think I am) and that I have some good reasons why I want to be able to allow these errors to go through.
Here are some previous questions I have made which highlight some major problems (imo) with TypeScript current this implementation.
Using lawnchair with Typescript
Issue with child scoping of this in Typescript
https://typescript.codeplex.com/discussions/429350 (And some comments I make down the bottom)
The underlying problem I have is that I need to guarantee that all logic is within a consistent scope, I need to be able to access things within knockout, jQuery etc and the local instance of a class. I used to do this with the var self = this; within the class declaration in JavaScript and worked great. As mentioned in some of these previous questions I cannot do that now, so the only way I can guarantee the scope is to use lambda methods, and the only way I can define one of these as a method within a class is within the constructor, and this part is HEAVILY down to personal preference, but I find it horrific that people seem to think that using that syntax is classed as a recommended pattern and not just a work around.
I know TypeScript is in alpha phase and a lot will change, and I HOPE so much that we get some nicer way to deal with this but currently I either make everything a huge mess just to get typescript working (and this is within Hundreds of files which I'm migrating over to TypeScript ) or I just make the call that I know better than the compiler in this case (VERY DANGEROUS I KNOW) so I can keep my code nice and hopefully when a better pattern comes out for handling this I can migrate it then.
Also just on a side note I know a lot of people are loving the fact that TypeScript is embracing and trying to stay as close to the new JavaScript features and known syntax as possible which is great, but typescript is NOT the next version of JavaScript so I don't see a problem with adding some syntactic sugar to the language as people who want to use the latest and greatest official JavaScript implementation can still do so.
The author's specific issue with this seems to be solved but the question is posed about ignoring errors, and for those who end up here looking how to ignore errors:
If properly fixing the error or using more decent workarounds like already suggested here are not an option, as of TypeScript 2.6 (released on Oct 31, 2017), now there is a way to ignore all errors from a specific line using // #ts-ignore comments before the target line.
The mendtioned documentation is succinct enough, but to recap:
// #ts-ignore
const s : string = false
disables error reporting for this line.
However, this should only be used as a last resort when fixing the error or using hacks like (x as any) is much more trouble than losing all type checking for a line.
As for specifying certain errors, the current (mid-2018) state is discussed here, in Design Meeting Notes (2/16/2018) and further comments, which is basically
"no conclusion yet"
and strong opposition to introducing this fine tuning.
I think your question as posed is an XY problem. What you're going for is how can I ensure that some of my class methods are guaranteed to have a correct this context?
For that problem, I would propose this solution:
class LambdaMethods {
constructor(private message: string) {
this.DoSomething = this.DoSomething.bind(this);
}
public DoSomething() {
alert(this.message);
}
}
This has several benefits.
First, you're being explicit about what's going on. Most programmers are probably not going to understand the subtle semantics about what the difference between the member and method syntax are in terms of codegen.
Second, it makes it very clear, from looking at the constructor, which methods are going to have a guaranteed this context. Critically, from a performance, perspective, you don't want to write all your methods this way, just the ones that absolutely need it.
Finally, it preserves the OOP semantics of the class. You'll actually be able to use super.DoSomething from a derived class implementation of DoSomething.
I'm sure you're aware of the standard form of defining a function without the arrow notation. There's another TypeScript expression that generates the exact same code but without the compile error:
class LambdaMethods {
private message: string;
public DoSomething: () => void;
constructor(message: string) {
this.message = message;
this.DoSomething = () => { alert(this.message); };
}
}
So why is this legal and the other one isn't? Well according to the spec: an arrow function expression preserves the this of its enclosing context. So it preserves the meaning of this from the scope it was declared. But declaring a function at the class level this doesn't actually have a meaning.
Here's an example that's wrong for the exact same reason that might be more clear:
class LambdaMethods {
private message: string;
constructor(message: string) {
this.message = message;
}
var a = this.message; // can't do this
}
The way that initializer works by being combined with the constructor is an implementation detail that can't be relied upon. It could change.
I am sure given time there will be a nice way to manage the this keyword, but currently I find it pretty dire.
One of the high-level goals (that I love) in TypeScript is to extend the JavaScript language and work with it, not fight it. How this operates is tricky but worth learning.

How not to repeat myself in Kohana 3's routes?

Let's say I want to make a system which can afford a multilingual web project. The system will consist of the modules that are put in Kohana's standard directory modules. Let's say that the standard access to the particular language can be done via lang parameter (i.e. somesite.com/en/somepage). The problem is that I have to repeat myself in defining my modules routes prepending each uri with (<lang>). Is there any way to avoid that? I thought about a separate language route declaration (for example in bootstap.php file), but I guess it won't solve the problem.
It's all about Kohana 3. Thanks to all.
UPDATE:
I think that the way suggested by The Pixel Developer is what one need if some part of the rule in route repeats everywhere.
Move up a level and extend the route class.
http://github.com/kohana/core/blob/master/classes/kohana/route.php#L69
public static function set($name, $uri, array $regex = NULL)
{
return parent::set($name, '(<lang>)'.$uri, $regex);
}
Not tested, but that's the general idea.
If lang is required in route, why don't you just put it in the default route? Surely that's the easiest way to go about. Something like:
Route::set('default', '<lang>(<controller>(/<action>(/<id>)))', array('lang'=> '[a-z]{2}'))
->defaults(array(
'controller' => 'somepage',
'action' => 'index',
'lang' => 'en',
));
Where lang is any 2 letters alphabets which defaults to 'en'.

Resources