PocketMine (PHP) Command Context possible? - php

As of 1.13 of Minecraft (and im not sure when it came out for bedrock) they added in the "command ui" with syntax and autofilling for commands (see below)
Command Syntax
I know on java edition it is possible to hijack the "Command Context" functions to create custom syntax for a command but on Bedrock it seems to all be stuck as [args: text] Is there any way to change that?

There is a very handy library/virion that handles all this for you. Take a look at https://github.com/CortexPE/Commando and if you need any examples you can look at https://github.com/CortexPE/Hierarchy. With this library you can add custom argument types.
<?php
namespace mohamed205\example\argument;
use CortexPE\Commando\args\StringEnumArgument;
use pocketmine\command\CommandSender;
class ExampleArgument extends StringEnumArgument
{
protected const VALUES = [
// put valid values for your argument here
];
public function parse(string $argument, CommandSender $sender)
{
return $this->getValue($argument);
}
public function getTypeName(): string
{
return "exampleArgument";
}
}

Related

How to write a .phpstorm.meta.php file for CommandBus

I am using a command bus in my project and it works fine except for code completion.
In PhpStorm I always need to hint what will be the type of result from it.
So recently I decided to make a .phpstorm.meta.php file that will handle the code completion typehints for me.
This is what I made based on documentation I found here:
https://www.jetbrains.com/help/phpstorm/ide-advanced-metadata.html#map
<?php
declare(strict_types=1);
namespace PHPSTORM_META {
override(\Acme\BusBundle\Service\QueryBusWrapperInterface::dispatch(0), map([
\App\Query\Action\User\GetUserById => App\Model\User\UserInterface,
]));
}
For reference, here is how this command bus is being used:
class A
{
protected $queryBus;
public function __construct(QueryBusWrapperInterface $queryBus)
{
$this->queryBus = $queryBus;
}
public function foo()
{
$userId = 1; // Get it from somewhere
/** #var UserInterface $user */
$user = $this->queryBus->dispatch(new GetUserById($userId));
$user-> // PhpStorm should hint here
}
}
Problem is, that it does not seem to work at all. If I remove the #var comment PhpStorm no longer hints anything.
Could someone hint me towards what am I doing wrong.
Am I missing something in the meta file?
This isn't going to work, unfortunately.
You can :
Either use the argument type as the method return type directly (with type(0));
Or you can take the literal value of the argument (a string) and use map() to bind it a certain return type (like map(["myString" => \My\Other\Type::class])). Please note that both the key and the value are strings here.
What you can't do is to take the type of the argument (new GetUserById() in your case) and assign different return types depending on what type that is.
I couldn't find an existing request for that on our tracker, so maybe it's worth submitting one: https://youtrack.jetbrains.com/newIssue?project=WI

PHP interface to specify object return value requirements? [duplicate]

Why is it possible to create an interface without specifying a return type? Why doesn't this make this interface unusable?
This makes it more clear:
Interface run
{
public function getInteger();
}
class MyString implements run
{
public function myNumber()
{
}
public function getInteger()
{
return "Not a number";
}
}
In Java every Interface has a return type like Integer, String or Void
I know that PHP is unfortunately a loosely typed language but isn't there a solution to that problem?
Is it possible to define an Interface with a return type like Integer?
Type hinting for function/method arguments or return values is only supported at PHP7.0 or later
Check the details here:
http://php.net/manual/en/migration70.new-features.php
If you are using PHP5 so the current accepted practice is to use phpdoc comments to indicate the "contract" is present.
/**
* Does something.
* #return int
**/
public function getInteger() { return 1; }
If the code violates the "contract," I suggest finding the original coder and having them fix it and/or filing a bug and/or fixing it yourself if it's in your own codebase.
No, there is not. You said the reason yourself: PHP is loosly typed.
You can have hints in PHPDoc, or check the type in the function you use the interface's functions and throw an InvalidArgumentException if you get something else but an integer.
It should be noted that this is now possible with PHP7 (only Beta1 has been released at time of writing)
It is possible with the following syntax:
interface Run
{
public function getInteger(): int;
}
class MyString implements Run
{
public function myNumber()
{
}
public function getInteger()
{
return "Not a number";
// Throws a fatal "Catchable fatal error: Return value of getInteger() must be of the type integer, string returned in %s on line %d"
}
}
In and of itself what you want is not possible...
In short: If you really need to enforce return types in your code contracts, use a statically typed language.
But thanks to the magic of __get, __set, __call and friends, you could define a base class that enforces type safety (I wouldn't recommend this for anything other than research/playtime) but that will still not help you define type safe interfaces.

Error creating new form elements in Phalcon

I get this error when trying to create a new form element:
Declaration of Phalcon\Forms\FileUpload::render() must be compatible with that of Phalcon\Forms\ElementInterface::render()
This is my code:
namespace Phalcon\Forms;
class FileUpload extends Element implements ElementInterface
{
public function __construct(string $name, $options, array $attributes)
{
}
public function render(array $attributes)
{
return 'my form element html';
}
}
I have tried every different notation of parameters at this point but I still receive the same error.
So I am wondering if it is possible at all to create form elements like this in Phalcon, or if it's just something I missed in the documentation.
http://phalcon.agent-j.ru/en/1.3.0/Phalcon/Forms/Element/
http://docs.phalconphp.com/en/latest/api/Phalcon_Forms_ElementInterface.html
I am using version 1.3.2
In the phalcon documentation this protoytype is defined:
abstract public string render (array $attributes=?);
So i changed my code to this:
public function render($attributes = false)
{
return 'my form element html';
}
i was just not familiar with the =? notation.
Are you using Phalcon 2 right?! In this version signatures should be followed more strictly. I've too got a bunch of errors like this one when I switched to Phalcon 2 but thankfully this version is written Zephir that makes the source code easier to read.
As you can see in the ElementInterface definition, the signatures aren't much consistent yet but we can easily see that render() has just one parameter without the array type hint. Just remove the array type from your interface implementation to match the current signature.

How do I reference PHP functions?

I'm making a plugin system. I have a class extensionmanager that takes the name of a plugin as a constructor parameter. Long story short, this is the code I'm trying to run:
$this->parsedata = function($data) {
$this->extension::parsedata($data);
};
$this-extension is a string with the name of the plugin. I have run static functions in the exact way shown in this example before. Now I'm getting the error unexpected T_PAAMAYIM_NEKUDOTAYIM on that second line (I've heard it roughly translates to "unexpected double colon")
Could anyone help me understand why?
Before the above example I tried to run something like this
$this->parsedata = &$this->extension::parsedata;
Hence the question title. The top example I thought was closer to working so I changed it.
call_user_func may give you a solution. Somewhere in the examples you have this code :
<?php
namespace Foobar;
class Foo {
static public function test() {
print "Hello world!\n";
}
}
call_user_func(__NAMESPACE__ .'\Foo::test'); // As of PHP 5.3.0
call_user_func(array(__NAMESPACE__ .'\Foo', 'test')); // As of PHP 5.3.0
?>
I think you can easily adapt this to call your static function. For example something like :
call_user_func(array($this->extension, 'parseData'), $data);
Do that:
$self = $this;
$this->parsedata = function($data) use ($self) {
{$self->extension}::parsedata($data);
};
Yet, I would suggest to avoid static functions. After all, whoever is going to use your extension manager will need to conform to some interface. Why not take advantage of abstract methods or interfaces to make the user conform to your interface?

Why is it possible to have an interface without a return type in PHP?

Why is it possible to create an interface without specifying a return type? Why doesn't this make this interface unusable?
This makes it more clear:
Interface run
{
public function getInteger();
}
class MyString implements run
{
public function myNumber()
{
}
public function getInteger()
{
return "Not a number";
}
}
In Java every Interface has a return type like Integer, String or Void
I know that PHP is unfortunately a loosely typed language but isn't there a solution to that problem?
Is it possible to define an Interface with a return type like Integer?
Type hinting for function/method arguments or return values is only supported at PHP7.0 or later
Check the details here:
http://php.net/manual/en/migration70.new-features.php
If you are using PHP5 so the current accepted practice is to use phpdoc comments to indicate the "contract" is present.
/**
* Does something.
* #return int
**/
public function getInteger() { return 1; }
If the code violates the "contract," I suggest finding the original coder and having them fix it and/or filing a bug and/or fixing it yourself if it's in your own codebase.
No, there is not. You said the reason yourself: PHP is loosly typed.
You can have hints in PHPDoc, or check the type in the function you use the interface's functions and throw an InvalidArgumentException if you get something else but an integer.
It should be noted that this is now possible with PHP7 (only Beta1 has been released at time of writing)
It is possible with the following syntax:
interface Run
{
public function getInteger(): int;
}
class MyString implements Run
{
public function myNumber()
{
}
public function getInteger()
{
return "Not a number";
// Throws a fatal "Catchable fatal error: Return value of getInteger() must be of the type integer, string returned in %s on line %d"
}
}
In and of itself what you want is not possible...
In short: If you really need to enforce return types in your code contracts, use a statically typed language.
But thanks to the magic of __get, __set, __call and friends, you could define a base class that enforces type safety (I wouldn't recommend this for anything other than research/playtime) but that will still not help you define type safe interfaces.

Categories