I am trying to call a private static method of a class from inside a closure inside an other method of this same class, and I can't find the right way to do it...
even using use referencing the private method...I am able to reference a private variable and pass it, but no way to reference the private method...
$refMethod = array('App','_onEvent'); with call_user_func($refMethod) will throw the method is private...
I tried with ReflectionClass with PHP 5.4 version also, (WAMP 32bits), but it says that the getClosure method doesn't exists on the instance :(
class App(){
static public function start(){
new Form('myform', array('submit'=>function($form) use($someVar){
if($anyCondition){
// want to call private self::_onEvent here : any suggestion ?
}
}));
}
static private function _onEvent(){
// this is my very private part
}
}
Well I know quite closure has no scope but so...any way to pass the private context (because the closure is inside the class) for accomplish something like this ? Thanks for any lights !
EDIT : I exactly want to do this answer but this just throw the great
Cannot access self:: when no class scope is active
Ok dudes,
it works better with PHP 5.4, my upgrade was not ok, I finally get rid of boring complications when upgrading php version, and now the straight solution works :
calling directly self::privateMethod() won't throw the 'self is nothing in closure...' anymore
Appart from that, did you know that from now (5.4), (0 == 'anystring') is TRUE now, duh ! need to use strict equal everywhere now, wonderfull upgrate :-s
Related
I want to be able to use a method from a Jenkins plugin via its java class
Just to point out I'm not a developer or a groovy/java expert - happy to learn!
The java class that my method is part of is com.cloudbees.jenkins.plugins.bitbucket.BitbucketSCMNavigator
From this I would like to use the method getRepoOwner()
What I've done is set my import and defined a new call to the class:
import com.cloudbees.jenkins.plugins.bitbucket.BitbucketSCMNavigator
def bbSCMNav = new BitbucketSCMNavigator()
When I run this I get the error below:
org.codehaus.groovy.runtime.metaclass.MethodSelectionException: Could not find which method <init>() to invoke from this list:
public com.cloudbees.jenkins.plugins.bitbucket.BitbucketSCMNavigator#<init>(java.lang.String)
public com.cloudbees.jenkins.plugins.bitbucket.BitbucketSCMNavigator#<init>(java.lang.String, java.lang.String, java.lang.String)
I've searched for the error above Could not find which method <init>() to invoke from this list
And I came across this ticket Could not find which method <init>() to invoke from this list on newInstance in groovy closure
Can't say that I entirerly understand the reply if it's helpful to me or not as I say I'm not a developer and groovy and java are relatively new to me but happy to understand if anyone can point me in the right direction with this
The goal of this exercise is to use the method during the run-time of a build to get the output of getRepoOwner() and use that in a variable to construct a URI
This question also seems similar to mine - Calling internal methods of Jenkins plugin (thinBackup)
But I'm not using maven or a pom.xml here
Cheers
Quick Answer
This error Could not find which method < init >() is related to a missing constructor.
Almost all internal jenkins class are ready to use in groovy.
In your case, BitbucketSCMNavigator does not have a default constructor. It have a constructor with one String argument. Check this line
Explanation
I could replicate your error with another internal class org.jenkinsci.plugins.workflow.cps.CpsGroovyShellFactory:
node {
stage('internal') {
org.jenkinsci.plugins.workflow.cps.CpsGroovyShellFactory obj =
new org.jenkinsci.plugins.workflow.cps.CpsGroovyShellFactory();
}
}
hudson.remoting.ProxyException: org.codehaus.groovy.runtime.metaclass.MethodSelectionException: Could not find which method <init>() to invoke from this list:
private org.jenkinsci.plugins.workflow.cps.CpsGroovyShellFactory#<init>(org.jenkinsci.plugins.workflow.cps.CpsFlowExecution, boolean, java.lang.ClassLoader, java.util.List)
But, reviewing this class CpsFlowExecution I could see that CpsGroovyShellFactory does not have a default constructor. It have a constructor with one argument : CpsGroovyShellFactory(this)
So, If I instance the constructor with one argument, no errors appear.
node {
stage('internal') {
org.jenkinsci.plugins.workflow.cps.CpsGroovyShellFactory obj =
new org.jenkinsci.plugins.workflow.cps.CpsGroovyShellFactory(null);
}
}
I wish to have the sub-classes of a super-class "registered" by an arbitrary name - whenever I declare a sub-class I wish to also have it entered into the super-class.sub Map.
Is there any way to accomplish this outside of main()?
// base class
class Mineral{
final String formula;
static Map<String,Mineral> sub = {}
Mineral( this.formula );
}
// sub class - declare and register
class Mica extends Mineral{
Mica( String formula ) : super( formula );
}
Mineral.sub['mica'] = Mica; // oops!
when I run this, I get
Error: line 10 pos 1: unexpected token 'Mineral' Mineral.sub['mica'] = Mica;
assuming that executable code is not allowed outside main().
cannot put within the super-class since other sub-classes may declared later, outside the library.
Dart has no way to run code as part of a library being loaded.
Executable code can only be put inside methods, or in field initializers, and static field initializers are lazy so they won't execute any code until you try to read them.
This is done to ensure quick startup - a Dart program doesn't have to execute any code before starting the main library's "main" method.
So, no, there is no way to initialize something that isn't constant before main is called.
Either
Mineral.sub['mica'] = new Mica();
or
static Map<String,Type> sub = {};
When you assign Mica you assign the Type Mica. new Mica() is an instance of Mica that is of the kind Mineral and can be assigned to the map you declared.
edit
Maybe you want to initialize the sub map:
static Map<String,Mineral> sub = {'mica': new Mica()};
hint: the semicolon is missing in this line in your question.
Say I have an instance of a class Foo, and I want to grab a list of all of its methods that are annotated a certain way. I want to have a reference to the method itself, so I'm not looking to use reflection to invoke the method each time, just to grab a reference to it the first time.
In other words, I want to do the reflection equivalent of this:
class Foo {
a() {print("a");}
}
void main() {
var f = new Foo();
var x = f.a; // Need reflective way of doing this
x(); // prints "a"
}
I have tried using InstanceMirror#getField, but methods are not considered fields so that didn't work. Any ideas?
As far as I understand reflection in Dart, there's no way to get the actual method as you wish to. (I'll very happily delete this answer if someone comes along and shows how to do that.)
The best I can come up with to ameliorate some of what you probably don't like about using reflection to invoke the method is this:
import 'dart:mirrors';
class Foo {
a() {print("a");}
}
void main() {
var f = new Foo();
final fMirror = reflect(f);
final aSym = new Symbol('a');
final x = () => fMirror.invoke(aSym, []);
x(); // prints "a"
}
Again, I know that's not quite what you're looking for, but I believe it's as close as you can get.
Side note: getField invokes the getter and returns the result -- it's actually fine if the getter is implemented as a method. It doesn't work for you here, but for a different reason than you thought.
What you're trying to get would be described as the "closurized" version of the method. That is, you want to get the method as a function, where the receiver is implicit in the function invocation. There isn't a way to get that from the mirror. You could get a methodMirror as
reflect(foo).type.methods[const Symbol("a")]
but you can't invoke the result.
In Module.php I have a some code (simplified version):
namespace Application;
use Zend\Mvc\ModuleRouteListener;
use Zend\Mvc\MvcEvent;
class Module{
public $somevariable = 'test';
public function onBootstrap( MvcEvent $e ) {
$this->somevariable = 'test2';
}
public function getValue(){
return $this->somevariable;
}
}
Next, I want to get value from variable "somevariable" in template layout.phtml. I do this as follows:
echo Application\Module::getValue();
but this doesn't work. What is wrong with that?
P.S. I never programmed much in PHP, so maybe I missed something :-(
you can use
$e->getViewModel()->setVariable('somevariable', 'somethingvalue');
and in the view :
echo $this->layout()->somevariable;
for detail, see this article : http://samsonasik.wordpress.com/2012/07/27/zend-framework-2-mvcevent-layout-view-get-namespace/
If a variable is just a string it doesn't make much sense to go with that approach. And please don't take this offensively, but if you don't have much experience in PHP (you tried to call a static function that is not static), then i wonder why you would start learning PHP with such a high class framework.
And if still you insist on doing that, please follow the official Documentation and read yourself through the whole QuickStart again and again. Check out some of the Modules out there and see how they do stuff.
Try to do the easy stuff first until you hit those points where you really need such functionality.
OK, I'm trying to set a property on a type I'm registering with SM.
Here's the code from the registry in one of my components. This
registry is being added during the configuration from a console app.
When I try to access the EndorsementSpecs property of the instance
AutoMandatoryEndorsementAggregator object, I get the 202. What's
interesting is that I can call
GetAllInstances>() from my
console app and it resolves just fine. Is there something about
accessing this code from within OnCreation that is causing the 202? I
can see everything I expect in WhatDoIHave(). I've also tried a TypeInterceptor with the same results.
//register all open generics
cfg.ConnectImplementationsToTypesClosing(typeof
(MandatoryEndorsementSpecBase<>));
ForSingletonOf<IMandatoryEndorsementAggregator<AutoPolicy>>()
.Use<AutoMandatoryEndorsementAggregator>()
.OnCreation((context, x) =>
{
var specs =
context.GetAllInstances<MandatoryEndorsementSpecBase<AutoPolicy>>();
x.EndorsementSpecs = specs;
})
;
Sorry to deflect your real questions, but are you just trying to inject all instances of MandatoryEndorsementSpecBase into AutoMandatoryEndorsementAggregatory?
If so, you can probably get away with just making it a constructor parameter so that they are all automatically injected.
public AutoMandatoryEndorsementAggregatory(MandatoryEndorsementSpecBase<AutoPolicy>[] endorsementSpecs){
EndorsementSpecs = endorsementSpecs;
}