px-files/_sys/php/px.php
public function mk_link( $linkto, $options = array() ){
		$parsed_url = parse_url($linkto);
		$args = func_get_args();
		$page_info = null;
		if( $this->site() !== false ){
			$page_info = $this->site()->get_page_info($linkto);
			if( !$page_info ){
				$page_info = $this->site()->get_page_info(@$parsed_url['path']);
			}
		}
		if( is_array($options) && array_key_exists('canonical', $options) && !is_null( $options['canonical'] ) && !@empty($options['canonical']) ){
			$href = $this->canonical($linkto);
			$hrefc = $this->canonical($this->req()->get_request_file_path());
		}else{
			$href = $this->href($linkto);
			$hrefc = $this->href($this->req()->get_request_file_path());
		}
		$label = $page_info['title_label'];
		$page_id = $page_info['id'];

		$options = array();
		if( count($args) >= 2 && is_array($args[count($args)-1]) ){
			//  最後の引数が配列なら
			//  オプション連想配列として読み込む
			$options = $args[count($args)-1];
			if( array_key_exists('label', $options) && (is_string(@$options['label']) || (is_object(@$options['label']) && is_callable(@$options['label'])) ) ){
				$label = $options['label'];
				if( !is_array($options) || !array_key_exists('no_escape', $options) || is_null($options['no_escape']) ){
					$options['no_escape'] = true;
				}
			}
		}
		if( array_key_exists(1, $args) && ( @is_string($args[1]) || (@is_object($args[1]) && @is_callable($args[1])) ) ){
			//  第2引数が文字列、または function なら
			//  リンクのラベルとして採用
			$label = $args[1];
			if( !is_array($options) || !array_key_exists('no_escape', $options) || is_null($options['no_escape']) ){
				$options['no_escape'] = true;
			}
		}

		$is_current = false;
		if( $this->site() !== false ){
			if( is_array($options) && array_key_exists('current', $options) && !is_null( $options['current'] ) ){
				$is_current = !@empty($options['current']);
			}elseif($href==$hrefc){
				$is_current = true;
			}elseif( $this->site()->is_page_in_breadcrumb($page_info['id']) ){
				$is_current = true;
			}
		}

		$is_popup = false;
		if( $this->site() !== false ){
			if( strpos( $this->site()->get_page_info($linkto,'layout') , 'popup' ) === 0 ){ // <- 'popup' で始まるlayoutは、ポップアップとして扱う。
				$is_popup = true;
			}
		}

		$label = (!is_null($label)?$label:$href); // labelがnullの場合、リンク先をラベルとする

		$classes = array();
		// CSSのクラスを付加
		if( is_array($options) && array_key_exists('class', $options) && is_string($options['class']) ){
			$options['class'] = preg_split( '/\s+/', trim($options['class']) );
		}
		if( is_array($options) && array_key_exists('class', $options) && is_array($options['class']) ){
			foreach($options['class'] as $class_row){
				array_push($classes, trim($class_row));
			}
		}
		if( $is_current ){
			array_push($classes, 'current');
		}

		if( is_object($label) && is_callable($label) ){
			$label = $label($page_info);
			if( !is_array($options) || !array_key_exists('no_escape', $options) || is_null($options['no_escape']) ){
				$options['no_escape'] = true;
			}
		}
		if( !array_key_exists('no_escape', $options) || !@$options['no_escape'] ){
			// no_escape(エスケープしない)指示がなければ、
			// HTMLをエスケープする。
			$label = htmlspecialchars($label);
		}

		$rtn = '<a href="'.htmlspecialchars($href).'"'.(count($classes)?' class="'.htmlspecialchars(implode(' ', $classes)).'"':'').''.($is_popup?' onclick="window.open(this.href);return false;"':'').'>'.$label.'</a>';
		return $rtn;
	}
public function mk_link( $linkto, $options = array() ){
		$parsed_url = parse_url($linkto);
		$args = func_get_args();
		$page_info = null;
		if( $this->site() !== false ){
			$page_info = $this->site()->get_page_info($linkto);
			if( !$page_info ){
				$page_info = $this->site()->get_page_info(@$parsed_url['path']);
			}
		}
		if( is_array($options) && array_key_exists('canonical', $options) && !is_null( $options['canonical'] ) && !@empty($options['canonical']) ){
			$href = $this->canonical($linkto);
			$hrefc = $this->canonical($this->req()->get_request_file_path());
		}else{
			$href = $this->href($linkto);
			$hrefc = $this->href($this->req()->get_request_file_path());
		}
		$label = $page_info['title_label'];
		$page_id = $page_info['id'];

		$options = array();
		if( count($args) >= 2 && is_array($args[count($args)-1]) ){
			//  最後の引数が配列なら
			//  オプション連想配列として読み込む
			$options = $args[count($args)-1];
			if( array_key_exists('label', $options) && (is_string(@$options['label']) || (is_object(@$options['label']) && is_callable(@$options['label'])) ) ){
				$label = $options['label'];
				if( !is_array($options) || !array_key_exists('no_escape', $options) || is_null($options['no_escape']) ){
					$options['no_escape'] = true;
				}
			}
		}
		if( array_key_exists(1, $args) && ( @is_string($args[1]) || (@is_object($args[1]) && @is_callable($args[1])) ) ){
			//  第2引数が文字列、または function なら
			//  リンクのラベルとして採用
			$label = $args[1];
			if( !is_array($options) || !array_key_exists('no_escape', $options) || is_null($options['no_escape']) ){
				$options['no_escape'] = true;
			}
		}

		$is_current = false;
		if( $this->site() !== false ){
			if( is_array($options) && array_key_exists('current', $options) && !is_null( $options['current'] ) ){
				$is_current = !@empty($options['current']);
			}elseif($href==$hrefc){
				$is_current = true;
			}elseif( $this->site()->is_page_in_breadcrumb($page_info['id']) ){
				$is_current = true;
			}
		}

		$is_popup = false;
		if( $this->site() !== false ){
			if( strpos( $this->site()->get_page_info($linkto,'layout') , 'popup' ) === 0 ){ // <- 'popup' で始まるlayoutは、ポップアップとして扱う。
				$is_popup = true;
			}
		}

		$label = (!is_null($label)?$label:$href); // labelがnullの場合、リンク先をラベルとする

		$classes = array();
		// CSSのクラスを付加
		if( is_array($options) && array_key_exists('class', $options) && is_string($options['class']) ){
			$options['class'] = preg_split( '/\s+/', trim($options['class']) );
		}
		if( is_array($options) && array_key_exists('class', $options) && is_array($options['class']) ){
			foreach($options['class'] as $class_row){
				array_push($classes, trim($class_row));
			}
		}
		if( $is_current ){
			array_push($classes, 'current');
		}

		if( is_object($label) && is_callable($label) ){
			$label = $label($page_info);
			if( !is_array($options) || !array_key_exists('no_escape', $options) || is_null($options['no_escape']) ){
				$options['no_escape'] = true;
			}
		}
		if( !array_key_exists('no_escape', $options) || !@$options['no_escape'] ){
			// no_escape(エスケープしない)指示がなければ、
			// HTMLをエスケープする。
			$label = htmlspecialchars($label);
		}

		$rtn = '<a href="'.htmlspecialchars($href).'"'.(count($classes)?' class="'.htmlspecialchars(implode(' ', $classes)).'"':'').''.($is_popup?' onclick="window.open(this.href);return false;"':'').'>'.$label.'</a>';
		return $rtn;
	}
リンクタグ(aタグ)を生成する。

リンク先の パス または ページID を受け取り、aタグを生成して返します。リンク先は、`href()` メソッドを通して調整されます。

このメソッドは、受け取ったパス(またはページID)をもとに、サイトマップからページ情報を取得し、aタグを自動補完します。
例えば、パンくず情報をもとに `class="current"` を付加したり、ページタイトルをラベルとして採用します。

この動作は、引数 `$options` に値を指定して変更することができます。

実装例:
<pre>&lt;?php
// ページ /aaa/bbb.html へのリンクを生成
print $px-&gt;mk_link('/aaa/bbb.html');

// ページ /aaa/bbb.html へのリンクをオプション付きで生成
print $px-&gt;mk_link('/aaa/bbb.html', array(
'label'=>'<span>リンクラベル</span>', //リンクラベルを文字列で指定
'class'=>'class_a class_b', //CSSのクラス名を指定
'no_escape'=>true, //エスケープ処理をキャンセル
'current'=>true //カレント表示にする
));
?&gt;</pre>

第2引数に文字列または関数としてリンクラベルを渡す方法もあります。
この場合、その他のオプションは第3引数に渡すことができます。

実装例:
<pre>&lt;?php
// ページ /aaa/bbb.html へのリンクをオプション付きで生成
print $px-&gt;mk_link('/aaa/bbb.html',
'<span>リンクラベル</span>' , //リンクラベルを文字列で指定
array(
'class'=>'class_a class_b',
'no_escape'=>true,
'current'=>true
)
);
?&gt;</pre>

リンクのラベルはコールバック関数でも指定できます。
コールバック関数には、リンク先のページ情報を格納した連想配列が引数として渡されます。

実装例:
<pre>&lt;?php
//リンクラベルをコールバック関数で指定
print $px-&gt;mk_link(
'/aaa/bbb.html',
function($page_info){return htmlspecialchars($page_info['title_label']);}
);
?&gt;</pre>

@param string $linkto リンク先のパス。PxFWのインストールパスを基点にした絶対パスで指定。
@param array $options options: [as string] Link label, [as function] callback function, [as array] Any options.
<dl>
<dt>mixed $options['label']</dt>
<dd>リンクのラベルを変更します。文字列か、またはコールバック関数が利用できます。</dd>
<dt>bool $options['canonical']</dt>
<dd><code>true</code> または <code>false</code> を指定します。この値が <code>true</code> の場合、リンク先の生成に `$px->href()` の代わりに `$px->canonical()` が使用されます。 デフォルトは <code>false</code> です。</dd>
<dt>bool $options['current']</dt>
<dd><code>true</code> または <code>false</code> を指定します。<code>class="current"</code> を強制的に付加または削除します。このオプションが指定されない場合は、自動的に選択されます。</dd>
<dt>bool $options['no_escape']</dt>
<dd><code>true</code> または <code>false</code> を指定します。この値が <code>false</code> の場合、リンクラベルに含まれるHTML特殊文字が自動的にエスケープされます。デフォルトは、<code>false</code>、<code>$options['label']</code>が指定された場合は自動的に <code>true</code> になります。</dd>
<dt>mixed $options['class']</dt>
<dd>スタイルシートの クラス名 を文字列または配列で指定します。</dd>
</dl>
第2引数にリンクラベルを直接指定することもできます。この場合、オプション配列は第3引数に指定します。

@return string HTMLソース(aタグ)