# Hooks and REST API - Folderline 1.x documentation

> The PHP filters and actions, the JavaScript hooks for the folder tree, and the folderline/v1 REST API.

Folderline stores folders as terms of a private, hierarchical taxonomy, `folderline_folder`, on attachments. A file is in at most one folder. A folder's position among its siblings is the `folderline_order` term meta. Everything below is how add-ons (Folderline Pro is built on these) and your own code work with that.

## Which post types get folders

| Hook | What it's for |
|---|---|
| `folderline_post_types` (filter) | The post types that get folders, each with its own tree. Default `[ 'attachment' ]`; `attachment` is always kept. Folderline itself only brings screens for the Media Library: an add-on that adds a post type brings its screen too. |
| `folderline_taxonomy_args` (filter) | `register_taxonomy()` arguments for a post type's folders (`$args, $post_type`). The taxonomy is `folderline_folder` for attachments and `folderline_{post_type}` for others. |
| `folderline_registered_taxonomy` (action) | After a post type's folder taxonomy is registered (`$taxonomy, $post_type`), on `init`. |

`Extendiment\Folderline\Taxonomy::name( $post_type )` gives a post type's taxonomy, and `Taxonomy::supports( $post_type )` whether it has folders.

## Folders and permissions

| Hook | What it's for |
|---|---|
| `folderline_can_manage` (filter) | Whether the current user may see and use a post type's folders (`$can, $post_type`). Default: `upload_files` for the Media Library, the post type's `edit_posts` capability for others. |
| `folderline_can_edit_folder` (filter) | Whether the current user may rename, move or delete a folder, create subfolders in it or put files in it (`$can, $folder_id, $post_type`). |
| `folderline_hold_back_private_folders` (filter) | Whether Folderline hides, and keeps unchanged, the folders that Folderline Pro's per-user folders keep private to another person (term meta `folderline_pro_owner`), while Folderline Pro isn't active. Default `true`; Folderline Pro returns `false` and applies per-user folders itself. |
| `folderline_folder_query_args` (filter) | The `get_terms()` arguments for the folders shown in a tree (`$args, $post_type`), e.g. to show each person only some folders. |
| `folderline_folder_data` (filter) | One folder's data for the panel (`$data, $term, $post_type`): `id`, `parent`, `name`, `count`, `editable`. Add keys of your own; the panel's JavaScript gets them. |
| `folderline_tree` (filter) | The whole tree sent to the panel and the folder filters (`$tree, $post_type`): `postType`, `folders`, `total`, `unsorted`. |

## Changes

Actions after each change: `folderline_folder_created` (`$id, $post_type, $parent`), `folderline_folder_renamed` (`$id, $post_type, $name`), `folderline_folder_moved` (`$id, $post_type, $parent, $old_parent`), `folderline_before_delete_folders` and `folderline_folders_deleted` (`$ids, $post_type`), and `folderline_assigned` (`$ids, $folder, $post_type`; folder 0 is Unsorted).

To make changes from code, use `Extendiment\Folderline\Folders`: `create( $post_type, $name, $parent )`, `rename()`, `delete( $post_type, $id, 'delete' | 'lift' )`, `move( $post_type, $id, $parent, $index )`, `assign( $post_type, $ids, $folder )`, `folder_of( $id, $post_type )` and `tree( $post_type )`. They run the same checks as the screens and return a `WP_Error` when something isn't allowed. `delete()` checks everything before it changes anything: a `WP_Error` means the folder is still there, and `deleted` lists only the folders actually deleted.

```php
// Put every PDF uploaded by a form plugin into a "Documents" folder.
add_filter( 'folderline_upload_folder', function ( $folder, $attachment_id ) {
	if ( 'application/pdf' === get_post_mime_type( $attachment_id ) ) {
		$term = get_term_by( 'name', 'Documents', 'folderline_folder' );
		return $term ? $term->term_id : $folder;
	}
	return $folder;
}, 10, 2 );
```

## Media Library

| Hook | What it's for |
|---|---|
| `folderline_upload_folder` (filter) | The folder a new upload goes into (`$folder, $attachment_id, $requested`; 0 for none). |
| `folderline_media_query_args` (filter) | The media grid's and media pickers' `WP_Query` arguments after the folder filter is applied (`$args, $props`). |
| `folderline_screen_config` (filter) | The folder panel's configuration on a screen (`window.folderlineScreen`). |
| `folderline_script_config` (filter) | Settings every Folderline script gets (`window.folderlineConfig`). |
| `folderline_enqueue_panel` (action) | The panel was put on a screen (`$post_type, $mode`): enqueue your script here with `folderline-screen` as a dependency. |
| `folderline_settings` (action) | Media → Folder Settings is being set up: add Settings API sections and fields to the `folderline` page. |
| `folderline_settings_after` (action) | Prints after the settings form. |
| `folderline_loaded` (action) | Fires on `plugins_loaded` once Folderline has loaded. Add-ons start here; `FOLDERLINE_VERSION` is defined. |

## The folder tree's JavaScript

`window.folderline` has the API client (`api( path, options )`), the per-post-type folder `store( postType )` with `create()`, `rename()`, `remove()`, `move()`, `assign()` and `refresh()`, the `Tree`, a `dialog()` and a `menu()`. On a screen with the panel, `folderline.screen` has the store, the tree, `select( value )` and `moveItems( ids, folder )`.

Add your hooks with `wp.hooks`, in a script that depends on `folderline-screen`, and namespace them:

| Hook | Arguments | What it's for |
|---|---|---|
| `folderline.menuItems` (filter) | `items, folder, tree` | A folder's menu: add `{ id, label, icon, action }` items. |
| `folderline.folderRow` (action) | `row, folder, tree` | After a folder's row is drawn, e.g. to colour its icon from your own folder data. |
| `folderline.treeDrawn` (action) | `tree` | After the tree is drawn. |
| `folderline.selected` (action) | `value, tree` | A folder (`'all'`, `'none'` or an ID) was opened. |
| `folderline.panelHead` / `folderline.panelFoot` (filter) | `nodes, screen` | Controls in the panel's header and footer. |
| `folderline.gridProps` (filter) | `props, screen` | The media grid's query props for the open folder. |
| `folderline.listArgs` (filter) | `args, screen` | The URL arguments for the open folder on a list screen. |
| `folderline.ready` (action) | `screen` | The panel is up. |

```js
// A "Copy folder ID" item in every folder's menu.
wp.hooks.addFilter( 'folderline.menuItems', 'my-plugin', ( items, folder ) => items.concat( {
	id: 'copy-id',
	label: 'Copy folder ID',
	icon: 'clipboard',
	action: () => navigator.clipboard.writeText( String( folder.id ) ),
} ) );
```

## REST API

`folderline/v1`, for logged-in users with `folderline_can_manage` for the post type (every route takes `post_type`, default `attachment`). Changes answer with the new tree as `tree`.

| Route | What it does |
|---|---|
| `GET /folders` | The tree. |
| `POST /folders` | Create (`name`, `parent`). |
| `POST /folders/{id}` | Rename (`name`). |
| `DELETE /folders/{id}` | Delete (`children`: `delete` or `lift`). |
| `POST /folders/{id}/move` | Move (`parent`, `index`). |
| `POST /assign` | Put files in a folder (`ids`, `folder`; 0 for Unsorted). Answers with `moved` and `skipped`. |
| `POST /state` | Save the panel's state for the current user. |

`folderline_rest_routes` (action, `$namespace, $controller`) is the place to add routes to the same namespace.

Source: https://extendiment.com/plugins/folderline/docs/1.x/hooks
