-
-
Save sebsel/3dce47c53ea9785f6ffb07aaa51c35ce to your computer and use it in GitHub Desktop.
<?php define('DS', DIRECTORY_SEPARATOR); | |
// Set this one to your own blueprint root if you changed it. | |
$blueprint_root = __DIR__ . DS . 'site' . DS . 'blueprints'; | |
// For Kirby 3, see the comment below. | |
/** | |
* === Let's build an IDE-helper for Kirby for PHPStorm! | |
* | |
* You can create the IDE-helper by putting this file in your project, then run the following command: | |
* php _ide_helper_generator.php | |
* | |
* This will create an _ide_helper_models.php based in your blueprints and an _ide_helper.php based on | |
* the kirby/extensions/methods.php file (which contains field-methods). TODO: add custom field method-files. | |
* | |
* If you change your blueprints, you should run the command again. | |
* | |
* You should *NOT* add the resulting php-files to your site with `include` or `require`. They are | |
* only meant to be analysed by PHPStorm (or any other IDE of your choice). | |
* | |
* You could add them to Git, you could add `_ide_helper*` to your .gitignore, up to you! | |
* | |
* You can hint your IDE with `/** @var SomeblueprintPage $page * /` in your templates. | |
* | |
* Happy IDE-ing! | |
*/ | |
// Import the Kirby Toolkit to make our life easier | |
require_once __DIR__ . DS . 'kirby' . DS . 'vendor' . DS . 'getkirby' . DS . 'toolkit' . DS . 'bootstrap.php'; | |
$helperFile = new IDEHelperFile('_ide_helper_models.php'); | |
foreach (dir::read($blueprint_root) as $filename) { | |
$blueprint = yaml::read($blueprint_root . DS . $filename); | |
$filename = f::name($filename); | |
$className = $filename == 'site' ? 'Site' : str::ucfirst($filename) . 'Page extends Page'; | |
if (!isset($blueprint['fields'])) { | |
$helperFile->addEmpty($className); | |
continue; | |
} | |
foreach (array_keys($blueprint['fields']) as $field) { | |
$helperFile->add($className, $field, 'Field'); | |
} | |
} | |
$helperFile->save(); | |
/** | |
* Now for Kirby's build in magic methods | |
*/ | |
$helperFile = new IDEHelperFile('_ide_helper.php'); | |
// Yeah, you can add your Field method-files to this array | |
$fieldMethodsFiles[] = __DIR__ . DS . 'kirby' . DS . 'extensions' . DS . 'methods.php'; | |
class Field { public static $methods; } | |
$fieldMethodsReturnTypes = []; | |
foreach ($fieldMethodsFiles as $methodsFile) { | |
require_once $methodsFile; | |
// Just regex them. | |
preg_match_all( | |
'/\@return (.*?)\n \*\/\nfield::\$methods\[\'(.*?)\'\]/', | |
f::read($methodsFile), | |
$matches, | |
PREG_SET_ORDER | |
); | |
foreach ($matches as $match) { | |
$return = $match[1]; | |
$method = $match[2]; | |
$fieldMethodsReturnTypes[$method] = $return; | |
} | |
} | |
foreach (field::$methods as $name => $method) { | |
$func = new ReflectionFunction($method); | |
$args = array_map(function ($arg) { return $arg->name; }, $func->getParameters()); | |
$return = array_key_exists($name, $fieldMethodsReturnTypes) | |
? $fieldMethodsReturnTypes[$name] : ''; | |
$helperFile->add('Field', $name, $return, $args); | |
} | |
// Also add the v:: validator class | |
foreach (v::$validators as $name => $validator) { | |
$func = new ReflectionFunction($validator); | |
$args = array_map(function ($arg) { return $arg->name; }, $func->getParameters()); | |
$helperFile->add('V', $name, 'boolean', $args, true); | |
} | |
$helperFile->save(); | |
/** | |
* Helpers | |
*/ | |
class IDEHelperFile { | |
private $filename; | |
private $methods = []; | |
public function __construct($filename) | |
{ | |
$this->filename = $filename; | |
} | |
public function add($class, $method, $return, $args = [], $static = false) | |
{ | |
$this->methods[$class][$method] = [ | |
'return' => $return, | |
'static' => $static, | |
'args' => $args, | |
]; | |
} | |
public function addEmpty($class) { | |
$this->methods[$class] = []; | |
} | |
public function save() | |
{ | |
$helper = "<?php\n"; | |
foreach ($this->methods as $class => $methods) { | |
$helper .= "\n/**\n"; | |
foreach ($methods as $method => $d) { | |
$helper .= ' * @method '; | |
$helper .= $d['static'] ? 'static' : ''; | |
$helper .= $d['return'] . " $method("; | |
$helper .= $d['args'] ? '$' . implode(', $', $d['args']) : ''; | |
$helper .= ")\n"; | |
} | |
$helper .= " */\nclass $class {}\n"; | |
} | |
f::write($this->filename, $helper); | |
} | |
} |
The irony is that I'm back to writing my code in VIM, so I'm not actually using this myself anymore. Thanks for sharing this new version! :)
I've run this and everything but I'm not really seeing anything new PHPstorm.... is there any other project configuration I need to do on my part with PHPstorm to get hints to show up? Or do these not work on template pages?
You have to give PhpStorm some type hints, then it works fine, like this for example:
Page template
<?php snippet('header') ?>
<?php
/** @var $site \Kirby\Cms\Site */
/** @var $page DefaultPage */
/** @var $pages \Kirby\Cms\Pages */
?>
<?php foreach ($page->children()->listed() as $part) : ?>
<!-- <?php echo $part->intendedTemplate() ?> -->
<?php snippet($part->intendedTemplate(), ['part' => $part]) ?>
<!-- / <?php echo $part->intendedTemplate() ?> -->
<?php endforeach ?>
<?php snippet('footer-start') ?>
<?php snippet('offcanvas') ?>
<?php snippet('footer') ?>
Snippet:
<?php
/* @var $part \Kirby\Cms\Page */
/* @var $site \Kirby\Cms\Site */
?>
<div class="top-wrap uk-position-relative uk-light" id="top">
<?php snippet('menu') ?>
<div class="uk-light uk-flex uk-flex-middle top-wrap-height" id="introtext">
<!-- TOP CONTAINER -->
<div class="uk-container uk-flex uk-flex-right top-container uk-position-relative uk-margin-medium-top" data-uk-parallax="y: 0,50; easing:0; opacity:0.2">
<div class="uk-width-1-2@s uk-padding" data-uk-scrollspy="cls: uk-animation-slide-right-medium; target: > *; delay: 150">
<h1 class="uk-margin-remove-top"><?php echo $part->content()->get('heading') ?></h1>
<p class="subtitle-text uk-visible@s"><?php echo $part->content()->get('text')->nl2br() ?></p>
<div class="uk-text-right">
<a href="<?php echo $part->content()->get('link')->slug() ?>" title="Mehr erfahren"
class="uk-button uk-button-primary uk-border-pill" data-uk-scrollspy-class="uk-animation-fade">
<div class="uk-flex uk-flex-middle">
<div>
<?php echo $part->linktext() ?>
</div>
<div>
<span uk-icon="icon: chevron-right; ratio: 2"></span>
</div>
</div>
</a>
</div>
</div>
</div>
<!-- /TOP CONTAINER -->
<!-- TOP IMAGE -->
<?php if ($file = $part->content()->get('images')->first()->toFile()): ?>
<img srcset="<?= $file->srcset('default') ?>" src="<?php echo $file->url()?>" alt="" data-uk-cover data-uk-img>
<?php endif ?>
<!-- /TOP IMAGE -->
</div>
</div>
So if one of my page blueprints was in say site/blueprints/pages/team-member.yml
I would say something like:
/** @var $page TeamMemberPage */
<div class="content-wrapper">
<h1>
<?= $page->title() ?>
</h1>
...
</div>
I think I'm following.. Just wanna make sure I got a grip on this
Only if you really have PHP class named TeamMemberPage. Otherwise use DefaultPage or whatever is listed in _ide_helper_models.php.
I had problems running this with Kirby 3.3.4 so I modified this with using the autoloading of composer. Maybe it helps someone trying to start Kirby development with PHPStorm.