Skip to content

Instantly share code, notes, and snippets.

@sebsel
Last active November 5, 2020 09:32
Show Gist options
  • Select an option

  • Save sebsel/3dce47c53ea9785f6ffb07aaa51c35ce to your computer and use it in GitHub Desktop.

Select an option

Save sebsel/3dce47c53ea9785f6ffb07aaa51c35ce to your computer and use it in GitHub Desktop.
Kirby IDE Helper
<?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);
}
}
@Alzy
Copy link

Alzy commented Nov 5, 2020

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?

@sascha-schieferdecker
Copy link

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>

@Alzy
Copy link

Alzy commented Nov 5, 2020

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

@sascha-schieferdecker
Copy link

Only if you really have PHP class named TeamMemberPage. Otherwise use DefaultPage or whatever is listed in _ide_helper_models.php.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment