How can a Tridion command extension find out the command it extends? - tridion

Tridion's user interface allows you to extend specific commands, which is a great way to modify the behavior of certain existing commands. In the configuration file of the editor this is done with a section like this:
<ext:commands>
<ext:command name="TextUnderline" extendingcommand="MyTextUnderline"/>
<ext:command name="TextStrikethrough" extendingcommand="MyTextStrikethrough"/>
I am working on a generic command extension class that can be used to modify the behavior of a number of commands:
<ext:commands>
<ext:command name="TextUnderline" extendingcommand="MyCommandExtension"/>
<ext:command name="TextStrikethrough" extendingcommand="MyCommandExtension"/>
So in this second configuration fragment, we have the same MyCommandExtension extending both TextUnderline and TextStrikethrough.
But now in the JavaScript for my MyCommandExtension, how can I determine which command was originally fired?
MyCommandExtension.prototype.isAvailable = function (selection, pipeline) {
...
console.log(this.properties.name);
...
};
In this scenario the this.properties.name will be logged as a less-than-useful-but-completely-correct:
"DisabledCommand"
I suspect that the information is available somewhere in the pipeline parameter, but haven't found it yet.
How can I find out the original command from MyCommandExtension?

Short answer: I couldn't.
I had to do something similar, and ended up having to extend various commands and set the "current" command as part of my "_execute" call (so I would now call _execute(selection, pipeline, originalCommand) for my command.
N

You cannot find out what the original command is. The assumption is that an extending command is specific to the command it extends and so would know which one it is extending. When creating generic extensions that work on different commands, I can see how it might be useful to know what the configuration would be.
Maybe you could add this as an Enhancement Request?
To work around it for now, you could create a base command with your logic - which takes the name of the command that it extends as a parameter. And then create specific classes for each command you which to extend, which just call the base command and pass in the name.
To put it differently, create a BaseExtendingCommand with all of the required methods - and then both a TextUnderlineExtendingCommand and TextStrikethroughExtendingCommand which call the methods on BaseExtendingCommand (and pass in "TextUnderline" and "TextStrikethrough", respectively, as arguments)

Related

Executing a method which is named via a config file

In short: I have a method name provided via a JSON configuration file. I'd like to call a method using this provided name. The method (with a matching name) will exist in the backend. What's the best way of going about this?
I am not quite sure what I should be searching for as an example.
To detail: I am working with a legacy application, hence the VB.NET. I am building a single PDF file from multiple PDF sources. Most of these are as is, I simply read the configuration and grab the relevant files and the job is done. However some require processing, I'd like the configuration file to pass in a method name to be called that will perform extra processing on the PDF, whatever that may be.
As there can be a lot of PDF files that can vary, I cannot simply use a property such as "PostProcessing: true".
Any ideas?
You could use reflection to reflect method names back and check them against the name passed from the property in the config file.
Like so
Type magicType = Type.GetType("MagicClass");
MethodInfo magicMethod = magicType.GetMethod("ItsMagic");
object magicValue = magicMethod.Invoke(magicClassObject, new object[]{100});
That would work.. but to be honest, I'd go with a case statement as you'll be hardcoding the method names anyway (because they are code), and it'll be strongly typed (less chance of typos and errors).

Using using dynamically

I want to use modules dynamically and I know their name, but creating a module and then applying using like this:
using PyPlot
a = Module(:Plots)
using a
will yield an excpetion telling me that a is not definied. Which is a very unintuitive error message, since when you do this on the repl you can use 'a' afterwards. Just in combination with using it tells you that it is not defined.
The error message is emitted by Base.require, so you should use using Main.a or using .a instead:
require(module::Symbol)
This function is part of the implementation of using / import, if a module is not already
defined in Main. It can also be called directly to force reloading a module, regardless of
whether it has been loaded before (for example, when interactively developing libraries).
...
When searching for files, require first looks for package code under Pkg.dir(), then tries paths
in the global array LOAD_PATH. require is case-sensitive on all platforms, including those with
case-insensitive filesystems like macOS and Windows.
Or just use module keyword to define a module on the fly:
module A
...
end
using A
For an existing module, you could also dynamically use it via eval(using module-name).

trying to use Symfony component and having name space issues

So i am starting a new project and want to use some of the Symfony Components. I have not used name spaces before with PHP, put i am familiar with the concept from my work in java.
i have this simple piece of code and when i run it i get the error:
PHP Fatal error: Class 'Symfony\Component\CssSelector\XPath\Translator' not found in /home/me/scrapes/Symfony/Component/CssSelector/CssSelector/CssSelector.php on line 52
I am thinking it my lack of knowledge of the name space thing.
/home/me/scrapes/Symfony/Component/CssSelector/CssSelector/XPath/Translator.php does exist.
<?php
set_include_path('/home/me/html/inc');
require 'functions.php';
require 'Symfony/Component/DomCrawler/Crawler/Crawler.php';
require 'Symfony/Component/CssSelector/CssSelector/CssSelector.php';
use Symfony\Component\DomCrawler\Crawler;
use Symfony\Component\CssSelector\CssSelector;
$crawler = new Crawler();
$crawler->addContent('<html><body><p>Hello World!</p></body></html>');
print $crawler->filter('body > p')->text();
curl_close($ch);
require 'cleanup.php';
?>
thanks for any help
I think this is caused because, if you look in the files you required (for example Symfony/Component/DomCrawler/Crawler/Crawler.php) you'll see that those files use their own use statements (to load other classes).
Namespaces
Let's start with the namespaces. A namespace is used to easily create classes with the same name in different packages. Let's say I have a package called Foo and a package called Bar. Both packages contain a Client class that is used to do some client work (one to call the Google Maps API for example and the other to call the Facebook Graph API). Let's also assume neither of the packages uses namespaces.
If I execute the following code:
<?php
require 'Foo/Client.php';
require 'Bar/Client.php';
This is not going to work, because both packages declare a Client class. Oops, how is PHP going to know which Client class to use if you do this?
<?php
$client = new Client();
It's not going to know which Client to use, so it gives up and throws an error.
If you use namespaces (declared using the namespace keyword in PHP at the top of your file, directly below <?php) you can prevent this from happening. The Foo package can create a Client class in the Foo namespace and the Bar package in the Bar namespace. Now we can
actually use both files and create a client:
<?php
require 'Foo/Client.php'
require 'Bar/Client.php'
$fooClient = new Foo\Client();
$barClient = new Bar\Client();
This will work fine.
I think you might have encountered the Foo_Client notation in older PHP libraries. This is an old way to create namespaces before PHP natively supported them.
"But", I hear you say, "it's quite cumbersome to write Foo\Bar\Baz\Client() every time I want to instantiated a class".
It is, and that's where the use keyword comes in. When using the use keyword, I can tell PHP I want to use a specific client and just use the class name, like so:
<?php
require 'Foo/Bar/Baz/Client.php'
use Foo\Bar\Baz\Client;
$client = new Client();
This will work, if you use the use Foo\Bar\Baz\Client statement, because you tell PHP "Okay, I want to use the Client class from the Foo\Bar\Baz namespace to be used when I use the Client class.
Autoloading
Now, what happens if you use a lot of different classes and you seperated them into several files (which you should do). You get a lot of different require and use statements on the top of a file. That's where autoloading comes in.
There has been a spl_register_autoloader function for quite some time in PHP. This function is used by PHP to find out which files to use when you instantiate a class that is not known because you did not require the file. This function is used both when creating a class, or, and this is the key part when you use a class.
And that's what's happening in your code. You don't have an autoloader registered that can translate the use statements in the files you required to actual class declarations.
Great, how do I fix it?
To fix it, I suggest you read up on the PHP-FIG and PSR-4. These people created standards (which you can follow but are not obliged to). To create easy to use libraries, such as the Symfony component. After you've done that, read up on Composer. After you've done this, you can drop the require statements from your code and use Composer to autoload all the classes you need.

PHPUnit selenium doesn't support sendKeys?

I was writing test with sendKeys command at Selenium IDE that was fine. But when I was change to PHPUnit Selenium I got an error that was Method sendKeys not defined, so I want to know is PHPUnit-Selenium doesn't support or I need to add a method? If the answer is I need to add senKeys method if so let's me know how to add senKeys method.
I couldn't figure this one out either for a while... the trick is that it's not called sendKeys and you don't use {ENTER} in PHPUnit with Selenium. These are not the functions you are looking for!
Instead, click on the element you wish to type into and then use the keys function like so:
$this->byXpath('//*[#id="theOneToTypeIn"]')->click();
$this->keys('some keys to type'.Keys::ENTER);
Make sure that at the top of your page you include the Keys class as well:
use PHPUnit_Extensions_Selenium2TestCase_Keys as Keys;
The supported keys can be found here: https://code.google.com/p/selenium/wiki/JsonWireProtocol#/session/:sessionId/element/:id/value
I read that the SendKeys are supported the same was as in the JSON wire frame so I would imagine that the constants are the same names as they are in that link... but then I also imagined that all the function names would be the same and here we are.

Eclipse/Flex: update a file every time I launch?

OK my project uses an xml file called Chart-app.xml inside this XML file there is a tag called <version></version> which I keep in the format like: <version>1.2.128</version> I am wondering if I can set it to append to the third number every time I run my project.
So if I ran it now it would be 1.2.129, then if i ran it again it would be 1.2.130
Thanks!!
After reading VonC's answer I don't know anything about ANT or creating custom builds, but he did give me an idea that seems to be working:
I already have a method to tell if the app is running in the ADL (within eclipse), so if it is, I just have my app open the file itself and change the value.
I am not sure there is a native Eclipse way to do this.
You can increment the number within that xml file either:
programmatically, launching a special class which do that, and then call your primary application Class
through a dependency during launch, for instance, you can make a JUnit test suite which will first call a Java class doing the increment, and then call your main method.
But in both case, you would have to somehow code the increment process.
Note: it is easier when you want to increment something each time you build, because you can add a custom builder.

Resources