# Hanna Code 

## Easily insert any complex HTML, Javascript or PHP output in your ProcessWire content by creating your own Hanna code tags.

This module is based loosely on the [WordPress Hana Code Insert](http://wordpress.org/plugins/hana-code-insert/) plugin.

A Hanna code tag looks like `[[hello_world]]`.  The open and close tags are user definable, `[[` and `]]` are just the defaults.
A Hanna code tag with attributes looks like `[[hello_world foo="bar" bar="foo"]]` using HTML style attributes or 
`[[hello_world foo=bar, bar=foo]]` using ProcessWire selector style attributes. After installing the module, you define your 
Hanna codes in Setup > Hanna Code. 

These Hanna codes that you define can then be entered within your body copy (or other text where you allow) and they will
be replaced with the values defined or generated by your Hanna code. A common use case is to embed scripts or other bits
of HTML or codes that would usually be stripped out by an editor like TinyMCE. However, Hanna codes can be more than just
static snippets--they can be dynamic PHP or Javascript that outputs different things according to the request. PHP-based 
Hanna codes have access to the entire ProcessWire API. 

Hanna code accepts named attributes in the tag that can be passed as variables to PHP and Javascript Hanna codes. 
These attributes can be specified either in HTML attribute format or ProcessWire selector format. In either case, quotes
should be used around the attribute value when the value contains whitespace or a comma. 

## How to install

1. Place the module files in /site/modules/TextformatterHannaCode/
2. In your admin, click Modules > Check for new modules
3. Click "install" for **TextformatterHannaCode** (Hanna Code Text Formatter)
4. Now to go Setup > Fields and locate the Textarea field(s) that you want to use Hanna codes with ("body" for instance).
5. When editing the field, click the "details" tab, and select "Hanna Code Text Formatter" as the Textformatter. Save.
6. To add or edit Hanna Codes, ProcessWire must be in debug mode, or Hanna Code must have its “safe mode’ disabled. 
   See the “Security” section below this for more details and instructions
8. Now go to Setup > Hanna Code and start defining your Hanna Codes! You may want to use one of the examples from this document to get started.

## Security

There are major security implications with a tool that will let you enter unfiltered text and code from your web browser.
As a result, Hanna codes are meant for definition only by superusers and we recommend keeping it that way.

Hanna Code editing is a development task and is meant only for sites in development. Access to edit PHP or JS scripts from
a web browser is a big security problem when in the wrong hands. For this reason, editing features
are disabled unless ProcessWire is in debug mode or you have specifically disabled Hanna Code’s “safe mode”.

ProcessWire’s debug mode can be enabled by setting `$config->debug = true` in your /site/config.php file. Or if you
prefer, Hanna Code’s editor can be specifically enabled by setting  `$config->HannaCodeEdit = true;` in /site/config.php.
For live/production sites, be sure to reverse these changes once you are done editing or adding Hanna Codes. 

These considerations are primarily to protect your server just in case a superuser account were ever to be compromised. 

## Tag format

Below is a Hanna code tag named hello_world with no attributes. If you pasted this into your body copy, you would get
whatever the replacement value is that you defined. 
```
[[hello_world]]
```

Below is a Hanna code tag named hello_world being passed attributes of foo, bar and foobar. If this were a PHP-based 
Hanna code, it would receive the variables $foo, $bar and $foobar: 
```
[[hello_world foo="bar" bar="foo" foobar="foo bar"]]
```
Below is the same Hanna code tag as above, but with attributes more like ProcessWire selectors. You can use whatever
format you prefer. Just note that unlike regular ProcessWire selectors, quotes (single or double) are required around
any value that has whitespace. 
```
[[hello_world, foo=bar, bar=foo, foobar="foo bar"]]
```

## How to use

Please make sure that you have completed the *How to install* section first. Then in your admin, go to Setup > Hanna Codes.

Each Hanna code that you add has a type of either: Text/HTML, Javascript or PHP. The Text/HTML type is literally 
self explanatory in that your `[[custom-tag]]` is replaced with exactly the text you paste in. Anywhere that you type your
`[[custom-tag]]` in your body copy will be replaced with exactly the static text you defined. 

More power opens up with the Javascript and/or PHP types of codes. These codes execute at runtime and thus can contain
specific logic to produce different results. In fact, PHP Hanna codes have access to the entire ProcessWire API and are
executed in the same manner as template files. Your PHP-based Hanna code should simply "echo" or "print" the replacement
value. 

### PHP example

- Create a new Hanna code with the *name* "children". 
- Select "PHP" as the *type*. 
- Paste in the following for the *code*:

```
<?php namespace ProcessWire;
foreach($page->children as $child) {
  echo "<p><a href='$child->url'>$child->title</a>";
}
```

- Now go and edit a page that has children. In the body copy, enter `[[children]]` in the place where you want the output to appear. 
- View the page, and you should see the rendered list of links to children. 

### PHP example, part 2

Now lets take the above example further... 

- Go back and edit your "children" Hanna code, as we are going to modify it to respond to a "parent" attribute. Change the code to this:

```
<?php namespace ProcessWire;

if(isset($parent)) {
  // If $parent is an ID or path, lets convert it to a Page
  $parent = $pages->get($parent);
} else {
  // otherwise lets assume the current page is the parent
  $parent = $page; 
}

foreach($parent->children as $child) {
  echo "<p><a href='$child->url'>$child->title</a>";
}
```

- Go back and edit the page where you previously inserted the `[[children]]` tag, and change it to:
`[[children, parent=1]]` (specifying the homepage) or `[[children, parent=/path/to/some/parent/]]` if you want to try something else. 

- View the page and you should now see it showing the children of the homepage (or of another parent you specified). 

**Please see the Javascript and PHP usage notes on the Hanna code entry screen.**

## Using Hanna Code from the API

If you want to populate Hanna Code from the API, you can do so using the render() method, like this:

```
$hanna = $modules->get('TextformatterHannaCode'); 
$page->body = $hanna->render($page->body); 
```

## PHP Usage Notes

1. Your code should `echo` or `print` the value you want to appear as the replacement for the tag.

2. It is not necessary to begin or close your statement with open/close PHP tags. However an opened PHP tag is recommended at least for syntax highlighting. 
   I recommend using `<?php namespace ProcessWire;` as your opening PHP tag.

3. Your code is executed the same way as a ProcessWire template file and all API variables are locally scoped.
   Meaning, you can call upon `$page`, `$pages`, or any other API variables. directly. See also the PHP Properties section.

4. If attributes are specified in the tag, they will appear as locally scoped variables to your PHP code.
   For instance, in the tag `[[hello_world first_name=Karena]]`, your code will have a `$first_name` variable populated with 'Karena'.
   To check for the presence of these attributes, use `isset($first_name);` for example.

5. All attributes are also populated to an `$attr` array of [key=value]. For example: `$attr['first_name'] == 'Karena'`, 
   in case you find this syntax preferable, or necessary.

6. If you use an attribute name that is the same as an API variable name (example: `$page`) then the API variable overrides the attribute name.
   In that case, the attribute value will only be accessible through `$attr` (example: `$attr['page']`).

7. Your code receives an object named `$hanna`. This can be used for getting additional properties, or modifying the larger text value if necessary. 
   See details in the PHP Properties section.

8. The `$page` API variable available to your Hanna code represents the page where the Hanna code exists.
   It is possible for this to be different from `wire('page')`, which represents the page that originated the request.

9. These code snippets are written to `/site/assets/cache/HannaCode/[tag-name].php` and directly executed rather than eval(d).


### PHP Properties

- `$attr`	  
An array of [key=value] attributes passed to your Hanna code.

- `$page`	  
The page where the Hanna code exists.

- `$hanna->name`	  
The name (string) of the current Hanna code.

- `$hanna->field`	  
The Field object representing the text.

- `$hanna->value`	  
The larger text where the Hanna code lives. This property may also be set.

Please note that "name" is a reserved word and may not be used as an attribute name.


## Javascript Usage Notes

1. It is not necessary to include script tags in your code unless you want to. They will be automatically inserted when not already present.

2. If attributes are specified in the tag (or in the attributes section of this page), they will appear as locally scoped variables to your Javascript code. 
   For instance, in the tag [[hello_world first_name=Karena]], your code will have a first_name variable populated with 'Karena'.

3. All attributes are also populated to an attr object of attr.key=value (i.e. attr.first_name == 'Karena'), in case you find this syntax preferable.

4. If using attributes, it is recommended that you define defaults in the Attributes field in the Hanna Code editor (even if blank is the default value).

5. Note that name is a reserved word and may not be used as an attribute name.


## Import/Export

Hanna codes can be exported and then imported somewhere else. To export, click the Export field in the Hanna Code editor and copy the export data to your clipboard. 
Now you may import this data in another Hanna Code installation by clicking the Import button and pasting in the data. Here is one to get you started: 

### Jumplinks Hanna Code (example for import)

This Hanna code is meant to be used in your body copy. It collects all the headline tags in the text and turns them into anchor jump links while outputting
a linked table of contents. It will put the table of contents wherever you type the Hanna code. 

**Import Data:**
```
!HannaCode:jumplinks:eyJuYW1lIjoianVtcGxpbmtzIiwidHlwZSI6IjIiLCJjb2RlIjoiXC8qaGNfYXR0clxuZm9yPVwiaDIgaDNcIlxuaGNfYXR0cipcL1xuJGZvciA9IHN0cl9yZXBsYWNlKCcs
JywgJyAnLCAkZm9yKTtcclxuJGZvciA9IGV4cGxvZGUoJyAnLCAkZm9yKTtcclxuZm9yZWFjaCgkZm9yIGFzICRrID0+ICR2KSAkZm9yWyRrXSA9IHRyaW0oJHYpO1xyXG5cclxuJGZvciA9IGltcGxvZ
GUoJ3wnLCAkZm9yKTtcclxuJGFuY2hvcnMgPSBhcnJheSgpOyBcclxuJHZhbHVlID0gJGhhbm5hLT52YWx1ZTsgXHJcblxyXG5pZihwcmVnX21hdGNoX2FsbCgnezwoJyAuICRmb3IgLiAnKVtePl0qPi
guKz8pPFwvXFwxPn1pJywgJHZhbHVlLCAkbWF0Y2hlcykpIHtcclxuICBmb3JlYWNoKCRtYXRjaGVzWzFdIGFzICRrZXkgPT4gJHRhZykge1xyXG4gICAgJHRleHQgPSAkbWF0Y2hlc1syXVska2V5XTt
cclxuICAgICRhbmNob3IgPSAkc2FuaXRpemVyLT5wYWdlTmFtZSgkdGV4dCwgdHJ1ZSk7XHJcbiAgICAkYW5jaG9yc1skYW5jaG9yXSA9ICR0ZXh0OyBcclxuICAgICRmdWxsID0gJG1hdGNoZXNbMF1b
JGtleV07IFxyXG4gICAgJHZhbHVlID0gc3RyX3JlcGxhY2UoJGZ1bGwsIFwiPGEgbmFtZT0nJGFuY2hvcicgaHJlZj0nIyc+PFwvYT4kZnVsbFwiLCAkdmFsdWUpOyBcclxuICB9ICBcclxuICAkaGFub
mEtPnZhbHVlID0gJHZhbHVlOyBcclxufVxyXG5cclxuaWYoY291bnQoJGFuY2hvcnMpKSB7XHJcbiAgZWNobyBcIjx1bCBjbGFzcz0nanVtcGxpbmtzJz5cIjtcclxuICBmb3JlYWNoKCRhbmNob3JzIG
FzICRhbmNob3IgPT4gJHRleHQpIHtcclxuICAgIGVjaG8gXCI8bGk+PGEgaHJlZj0nJHBhZ2UtPnVybCMkYW5jaG9yJz4kdGV4dDxcL2E+PFwvbGk+XCI7XHJcbiAgfVxyXG4gIGVjaG8gXCI8XC91bD5
cIjtcclxufSBlbHNlIHtcclxuICBlY2hvICcnO1xyXG59In0=/!HannaCode
```

**Usage Examples:**

`[[jumplinks]]` Locates all h2 and h3 headlines, turns them into anchors, and generates a table of contents. This is the default behavior with no attributes.

`[[jumplinks for=h2]]` Here we specify a 'for' attribute. It produces the same behavior as above except only anchors h2 headlines.

`[[jumplinks for="h2 h4"]]` Same as above except only anchors h2 and h4 headlines.


------
Copyright 2021 by Ryan Cramer
(Originally released in 2013)



