Address pages in custom fields

I have the following custom field which fetches categories defined in site.txt.

<?php

class CategoryField extends SelectField {

  public function __construct() {
    $this->type    = 'text';
    $this->icon    = 'chevron-down';
    $this->label   = 'Categories';
    $this->options = array();

    foreach(kirby()->site()->categories()->split() as $category) {      
        $this->options[$category] = $category;     
    }
  }
}

While this works fine, I’d much rather define those categories in the parent page of the article where they are going to be used. Only, I can’t figure out how to address that parent page from the custom field. Any ideas?

Thx, Sonja

Have you tried, if you can get the page object with the following?

$page = $this->page();

// cause then you might be able to do:

foreach($this->page()->parent()->categories()->split() as $category) {      
  $this->options[$category] = $category;     
}

It’s used it panel/apps/fields/tags/tags.php - maybe that can help.

thx, @distantnative, I think I tried almost anything I could think of including your suggestion but nothing worked; well, I try again, maybe I just made some stupid mistake.

[Edit] No, the result is still the same, and I get an error message regarding the parent method; at least I would have thought that $this->page() would give me some sort of result because I have seen it being used in other fields …

@distantnative: you’re right,$this->page()works, only not where I put it but within an input function, so I simply copied the select field like so and only added the options:

class CategoryField extends BaseField {

  public function __construct() {
    $this->type    = 'select';
    $this->icon    = 'chevron-down';
    $this->label   = 'category';
    $this->options = array();

  }  
public function options() {
    return FieldOptions::build($this);
  }
  public function option($value, $text, $selected = false) {
    return new Brick('option', $this->i18n($text), array(
      'value'    => $value,
      'selected' => $selected
    ));
  }
  	public function input() {
  		$select = new Brick('select');
  		$select->addClass('selectbox');
  		$select->attr(array(
	      'name'         => $this->name(),
	      'id'           => $this->id(),
	      'required'     => $this->required(),
	      'autocomplete' => $this->autocomplete(),
	      'autofocus'    => $this->autofocus(),
	      'readonly'     => $this->readonly(),
	      'disabled'     => $this->disabled(),
	    ));
  	    
    $select = $select->append($this->option('', '', $this->value() == ''));

    
  	
  	if($this->readonly()) {
           $select->attr('tabindex', '-1');
    }


    $categories = $this->page()->parent()->categories()->split();
    foreach($categories as $category)  {
      $this->options[$category] = $category;
    }

    foreach($this->options() as $value => $text) {
      $select->append($this->option($value, $text, $this->value() == $value));
    }

    $inner = new Brick('div');
    $inner->addClass('selectbox-wrapper');
    $inner->append($select);

    $wrapper = new Brick('div');
    $wrapper->addClass('input input-with-selectbox');
    $wrapper->append($inner);

    if($this->readonly()) {
      $wrapper->addClass('input-is-readonly');
    } else {
      $wrapper->attr('data-focus', 'true');
    }

    return $wrapper;
  	
  }
  public function validate() {
    return array_key_exists($this->value(), $this->options());
  }

}

This still leaves me with the problem, that the field cannot be saved in the panel and I haven’t figured out why, it always get a red border around it. Any ideas?

Are you sure that $this->options() in the validate() method still has your categories included?

You’re right, if I delete the validate() method, I can at least save the page though not sure if I should do that.