Merge branch 'develop' into cap--with-notice

This commit is contained in:
Jacson Passold 2018-02-22 17:25:40 -03:00
commit cefcb1ebf9
70 changed files with 3573 additions and 908 deletions

121
docs/permissions.md Normal file
View File

@ -0,0 +1,121 @@
# Tainacan Users Permissions
This page explains how permissions are handled in Tainacan. What are the users roles available and what each one of them can do.
Tainacan handles user permissions in the very same way WordPress does, so if you are used to WordPress Roles and Permissions, you wont have any trouble.
Default WordPress roles are assigned with new capabilities to work with Collections, Items and other Tainacan specific operations. Additionaly Tainacan creates new roles, relative to the core WordPress roles, that have the same Tainacan specific capabilities, but dont have acces to the rest of the administrative panel of WordPress. For example, WordPress Editor can manage everything inside Tainacan, and they can also create and publish pages, in the other hand, Tainacan Editors can't.
If you want to change permissions for specific roles or users, or even create new roles, you can allways use one of the many WordPress plugins available for that.
In short, these are the roles and their main characteristics. A detailed description can be found in the next session.
* Subscriber: Can't really do anything inside tainacan.
* Colaborator / Tainacan Colaborator: Can create items, but not to publish them.
* Author / Tainacan Author: Can create and publish items, but can not edit published items nor edit other user's items.
* Editor / Tainacan Editor: Can create, publish and edit other users's items.
* Administrator: Rules the world.
## Roles and permissions
Here you will find a detailed explanation of what each role can do with each part of Tainacan.
### Collections
These are the capabilities related to collection management.
**Note about Collection moderators**: Collection moderators have the same capabilities an editor has, but only in relation to the collections he or she is moderating. Even if the user is a subscriber, he will act as if he/she was an editor for that specific collection.
| | Admin | Editor | Author | Collaborator |
|------------------------------|-------|--------|--------|--------------|
| Edit Collections | y | y | y | y |
| Delete Collections | y | y | y | y |
| Publish Collections | y | y | y | |
| Edit Published Collections | y | y | y | |
| Delete Published Collections | y | y | y | |
| Edit Others Collections | y | y | | |
| Delete Others Collections | y | y | | |
| Read Private Collections | y | y | | |
| Edit Private Collections | y | y | | |
| Delete Private Collections | y | y | | |
#### Edit Collections
> Capability name: edit_tainacan-collections
Who's got it: Everyone but subscribers
Allows to create and edit one's own collections. Does not allow to publish them.
#### Edit Others Collections
> Capability name: edit_others_tainacan-collections
Who's got it: Administrators, Editors and Tainacan Editors
Allows to edit other user's Collections (and items)
#### Edit Published Collections
> Capability name: edit_published_tainacan-collections
Who's got it: Administrators, Editors and Tainacan Editors
Allows to edit collections details after it was published
#### Edit Private Collections
> Capability name: edit_private_tainacan-collections
Who's got it: Administrators, Editors and Tainacan Editors
Allows to edit collections marked as private
#### Publish Collections
> Capability name: publish_tainacan-collections
Who's got it: Administrators, Editors, Tainacan Editors, Authors and Tainacan Authors
Allows to edit collections marked as private
#### Delete Collections
> Capability name: delete_tainacan-collections
Who's got it: Everyone but subscribers
Allows to delete one's own collections.
#### Delete Others Collections
> Capability name: delete_others_tainacan-collections
Who's got it: Administrators, Editors and Tainacan Editors
Allows to delete other user's Collections (and items)
#### Delete Published Collections
> Capability name: delete_published_tainacan-collections
Who's got it: Administrators, Editors and Tainacan Editors
Allows to delete collections after it was published
#### Delete Private Collections
> Capability name: delete_private_tainacan-collections
Who's got it: Administrators, Editors and Tainacan Editors
Allows to delete collections marked as private
#### Read Private Collections
> Capability name: read_private_tainacan-collections
Who's got it: Administrators, Editors and Tainacan Editors
Allows to view collections marked as private and its items.
### Items
### Categories
### Fields
### Filters

View File

@ -4,283 +4,348 @@
A REST API for Tainacan Plugin. This API uses the Wordpress REST API.
------
### Routes and Endpoints
#### Summary
1. [Collections](#collections)
1. [Items](#items)
1. [Fields](#fields)
1. [Item Metadata](#item-metadata)
1. [Taxonomies](#taxonomies)
1. [Filters](#filters)
1. [Terms](#terms)
1. [Logs](#logs)
1. [Others](#others)
------
#### Collections
1. Route `wp-json/tainacan/v2/collections/(?P<collection_id>[\d]+)`
1.1. Endpoints supported:
1. Endpoints supported:
1.1.1 GET (Fetch a collection)
1.1.2 DELETE (Delete or Trash a collection and all your dependencies)
```
To delete pass in body of a requisition the parameter is_permanently as true.
To only trash pass false.
```
1.1.3 PATCH or PUT (Update a collection)
1. GET (Fetch a collection)
     
1. DELETE (Delete or Trash a collection and all your dependencies)
*To delete pass in body of a requisition the parameter `is_permanently` as true. To only trash pass false.*
1. PATCH or PUT (Update a collection)
Example of JSON passed in body for updating a collection:
Example of JSON passed in body for updating a collection:
   
```
{
   "name": "string",
   "description": "string",
...
 }
```javascript
{
"name": "string",
"description": "string",
...
}
```
2. Route `wp-json/tainacan/v2/collections`
2.1. Endpoints supported:
1. Endpoints supported:
2.1.1 GET (Fetch all collections)
1. GET (Fetch all collections)
2.1.2 POST (Create a collection).
1. POST (Create a collection).
Example of JSON passed in body for creating a collection:
Example of JSON passed in body for creating a collection:
```javascript
{
  "name": "string",
   "description": "string",
   "status": "string",
   "order": "string",
   "parent": "integer",
   "slug": "string",
   "default_orderby": "string",
   "default_order": "string",
   "columns": "string",
   "default_view_mode": "string"
 }
{
"name": "string",
"description": "string",
"status": "string",
"order": "string",
"parent": "integer",
"slug": "string",
"default_orderby": "string",
"default_order": "string",
"columns": "string",
"default_view_mode": "string"
}
```
------
#### Items
1. Route `wp-json/tainacan/v2/collection/(?P<collection_id>[\d]+)/items`
1.1. Endpoints supported:
1. Endpoints supported:
1.1.1 GET (Fetch all items from a collection)
1. GET (Fetch all items from a collection)
1.1.2 POST (Create a item in a collection)
Example of JSON passed in body for creating a item:
1. POST (Create a item in a collection)
Example of JSON passed in body for creating a item:
```javascript
{
  "title": "string",
   "description": "string",
   "status": "string",
 }
{
"title": "string",
"description": "string",
"status": "string",
}
```
2. Route `wp-json/tainacan/v2/items/(?P<item_id>[\d]+)`
2.1. Endpoints supported:
1. Endpoints supported:
2.1.1 GET (Fetch a item)
1. GET (Fetch a item)
2.1.2 DELETE (Delete or Trash a item and all your dependencies)
1. DELETE (Delete or Trash a item and all your dependencies)
```
To delete pass in body of a requisition the parameter is_permanently as true.
To only trash pass false.
```
*To delete pass in body of a requisition the parameter is_permanently as true. To only trash pass false.*
2.1.3 PATCH or PUT (Update a item)
1. PATCH or PUT (Update a item)
Example of JSON passed in body for updating a item:
Example of JSON passed in body for updating a item:
   
```
{
   "title": "string",
   "description": "string",
...
 }
```javascript
{
"title": "string",
"description": "string",
...
}
```
#### Field
------
#### Fields
1. Route `wp-json/tainacan/v2/collection/(?P<collection_id>[\d]+)/field`
1. Route `wp-json/tainacan/v2/collection/(?P<collection_id>[\d]+)/fields`
1.1. Endpoints supported:
1. Endpoints supported:
1. GET (Fetch all collection field)
1. POST (Create a field in collection and all it items)
1.1.1 POST (Create a field in collection and all your items)
In body of requisition pass a JSON with the attributes of field like:
In body of requisition pass a JSON with the attributes of field like:
```javascript
{
      "name": "string",
      "description": "string",
      "field_type": "string",
      "order": "string",
      "parent": "integer",
      "required": "string",
      "collection_key": "string",
      "multiple": "string",
      "cardinality": "string",
      "privacy": "string",
      "mask": "string",
      "default_value": "string",
      "field_type_options": "string",
   }
{
"name": "string",
"description": "string",
"field_type": "string",
"order": "string",
"parent": "integer",
"required": "string",
"collection_key": "string",
"multiple": "string",
"cardinality": "string",
"privacy": "string",
"mask": "string",
"default_value": "string",
"field_type_options": "string",
}
```
1.1.2 GET (Fetch all collection field)
2. Route `wp-json/tainacan/v2/item/(?P<item_id>[\d]+)/field`
2.1. Endpoints supported:
2. Route `wp-json/tainacan/v2/collection/(?P<collection_id>[\d]+)/fields/(?P<field_id>[\d]+)`
1. Endpoints supported:
1. PATCH or PUT (Update a field in a collection and all it items)
In body of requisition pass a JSON with the attributes you need to update, like:
```javascript
{
"name": "string",
"description": "string",
}
```
------
#### Item Metadata
1. Route `wp-json/tainacan/v2/item/(?P<item_id>[\d]+)/metadata/(?P<metadata_id>[\d]+)`
1. Endpoints supported:
2.1.1 POST (Set a value of item field)
1. PATCH or PUT (Set value of a metadata)
In body of requisition pass a JSON with value e and id of field like:
In body of requisition pass a JSON with values of metadata, like:
```javascript
{
    "field_id": "integer",
    "values": "[any, type]"
 }
{
"values": [
{ "new": "any_type", "prev": "any_type"},
{ "new": "any_type", "prev": ""}
]
}
```
2.1.2 GET (Fetch all item field, with your values)
2. Route `wp-json/tainacan/v2/item/(?P<item_id>[\d]+)/metadata`
1. Enpoints supported:
1. GET (Fetch all item metadata, with it values)
------
#### Taxonomies
1. Route `wp-json/tainacan/v2/taxonomies`
1.1. Endpoints supported:
1. Endpoints supported:
1.1.1. GET (Fetch all taxonomies)
1. GET (Fetch all taxonomies)
1.1.2. POST (Create a taxonomy)
1. POST (Create a taxonomy)
Example of JSON passed in body for creating a taxonomy:
Example of JSON passed in body for creating a taxonomy:
```javascript
{
  "name": "string",
   "description": "string",
   "status": "string",
   "parent": "string",
   "slug": "string",
   "allow_insert": "string",
   "collections_ids": "array"
 }
{
"name": "string",
"description": "string",
"status": "string",
"parent": "string",
"slug": "string",
"allow_insert": "string",
"collections_ids": "array"
}
```
2. Route `wp-json/tainacan/v2/taxonomies/(?P<taxonomy_id>[\d]+)`
2.1. Endpoints supported:
1. Endpoints supported:
2.1.1 GET (Fetch a taxonomy)
1. GET (Fetch a taxonomy)
2.1.2 DELETE (Delete or trash a taxonomy)
```
To delete pass in body of requisition the parameter is_permanently as true.
To only trash pass false.
```
1. DELETE (Delete or trash a taxonomy)
2.1.3 PATCH or PUT (Update a taxonomy)
*To delete pass in body of requisition the parameter is_permanently as true. To only trash pass false.*
1. PATCH or PUT (Update a taxonomy)
Example of JSON passed in body for updating a taxonomy:
Example of JSON passed in body for updating a taxonomy:
   
```javascript
{
   "name": "string",
   "description": "string",
...
 }
{
"name": "string",
"description": "string",
...
}
```
3. Route `wp-json/tainacan/v2/taxonomies/(?P<taxonomy_id>[\d]+)/collection/(?P<collection_id>[\d]+)`
1. Routes supported:
1. PATCH or PUT (Add a Collection in a Taxonomy)
------
#### Filters
1. Route `wp-json/tainacan/v2/filters`
1.1 Endpoints supported:
1. Route `wp-json/tainacan/v2/collection/(?P<collection_id>[\d]+)/field/(?P<field_id>[\d]+)/filters`
1.1.1 POST (Create a filter)
1. Endpoints supported:
Example of JSON passed in body for creating a filter:
1. POST (Create a filter)
```javascript
{
  "collection_id": "int",
  "field_id": "int",
"filter_type": "string",
  "filter": {
    "name": "string",
    "description": "string",
...
  }
}
```
1.1.2 GET (Fetch all filters)
2. Route `wp-json/tainacan/v2/filters/(?P<filter_id>[\d]+)`
2.1. Endpoints supported:
2.1.1 DELETE (Delete or trash a filter)
```
To delete pass in body of requisition the parameter is_permanently as true.
To only trash pass false.
```
2.1.2 PATCH or PUT (Update a filter)
Example of JSON passed in body for updating a filter:
Example of JSON passed in body for creating a filter:
```javascript
{
"name": "string",
...
}
{
"filter_type": "string",
"filter": {
"name": "string",
"description": "string",
...
}
}
```
2.1.3 GET (Fetch a filter)
2. Route `wp-json/tainacan/v2/filters/(?P<filter_id>[\d]+)`
1. Endpoints supported:
1. GET (Fetch a filter)
1. DELETE (Delete or trash a filter)
*To delete pass in body of requisition the parameter is_permanently as true. To only trash pass false.*
1. PATCH or PUT (Update a filter)
Example of JSON passed in body for updating a filter:
```javascript
{
"name": "string",
...
}
```
3. Route `wp-json/tainacan/v2/filters`
1. Endpoints supported:
1. GET (Fetch all filters)
------
#### Terms
1. Route `wp-json/tainacan/v2/taxonomy/(?P<taxonomy_id>[\d]+)/terms`
1.1 Endpoints supported:
1. Endpoints supported:
1. GET (Fetch all tems of a taxonomy)
1.1.1 POST (Create a term in a taxonomy)
Example of JSON passed in body for creating a term:
1. POST (Create a term in a taxonomy)
Example of JSON passed in body for creating a term:
```javascript
{
  "name": "string",
  "user": "int",
...
}
```
   1.1.2 GET (Fetch all tems of a taxonomy)
{
"name": "string",
"user": "int",
...
}
```
2. Route `wp-json/tainacan/v2/taxonomy/(?P<taxonomy_id>[\d]+)/terms/(?P<term_id>[\d]+)`
2.1 Endpoints supported:
1. Endpoints supported:
2.1.1 GET (Fecth a term of a taxonomy)
1. GET (Fecth a term of a taxonomy)
1. DELETE (Delete a term of a taxonoy)
2.1.2 PATCH or PUT (Update a term in a taxonomy)
1. PATCH or PUT (Update a term in a taxonomy)
Example of JSON passed in body for updating a term:
Example of JSON passed in body for updating a term:
```javascript
{
  "name": "string",
...
}
{
"name": "string",
...
}
```
2.1.3 DELETE (Delete a term of a taxonoy)
------
#### Logs
1. Route `wp-json/tainacan/v2/logs`
1. Endpoints supported:
1. GET (Get all logs)
2. Route `wp-json/tainacan/v2/logs/(?P<log_id>[\d]+)`
1. Enpoints supported:
1. GET (Get a log)
------
#### Others
To Create, Read, Update or Delete Media or Users you can use the default routes of Wordpress.
See about Media in [Media | REST API Handbook](https://developer.wordpress.org/rest-api/reference/media/);
See about Users in [Users | REST API Handbook](https://developer.wordpress.org/rest-api/reference/users/).

1054
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -12,6 +12,8 @@
"buefy": "^0.6.3",
"bulma": "^0.6.2",
"mdi": "^2.1.19",
"node-sass": "^4.7.2",
"sass-loader": "^6.0.6",
"vue": "^2.5.13",
"vuex": "^3.0.1"
},
@ -27,6 +29,7 @@
"element-theme-chalk": "^2.1.0",
"file-loader": "^0.9.0",
"postcss-loader": "^2.1.0",
"sass-resources-loader": "^1.3.2",
"style-loader": "^0.19.1",
"vue-custom-element": "^1.0.13",
"vue-loader": "^13.7.1",

View File

@ -1,21 +1,54 @@
<template>
<div id="tainacan-admin-app">
<nav class="navbar is-secondary" role="navigation" aria-label="main navigation">
<div class="navbar-brand">
<router-link class="navbar-item" to="/">
<img src="./images/tainacan_logo_header.png" alt="Taincan Admin" height="32">
</router-link>
<router-link class="navbar-item" to="/collections">Coleções</router-link>
</div>
</nav>
<div class="container">
<router-view></router-view>
<div id="tainacan-admin-app" class="columns is-fullheight">
<primary-menu></primary-menu>
<div class="column is-main-content">
<router-view></router-view>
</div>
</div>
</template>
<script>
import PrimaryMenu from './components/primary-menu.vue';
export default {
name: "AdminPage"
name: "AdminPage",
data(){
return {
logoHeader: '../wp-content/plugins/tainacan/admin/images/tainacan_logo_header.png',
wordpressAdmin: window.location.origin + window.location.pathname.replace('admin.php', ''),
}
},
components: {
PrimaryMenu
}
}
</script>
<style lang="scss">
@import "./scss/_variables.scss";
.is-fullheight {
height: 100%;
margin-bottom: 0px;
margin-top: 0px;
}
.is-main-content {
padding-bottom: 0px;
padding-top: 0px;
margin: 0 auto;
position: relative;
}
#secondary-menu {
background-color: $secondary;
li{
a {color: white !important;}
a:hover {color: $secondary !important;}
}
}
</style>

View File

@ -9,26 +9,42 @@ class Admin {
private $menu_slug = 'tainacan_admin';
public function __construct() {
add_action( 'admin_menu', array(&$this, 'add_admin_menu') );
add_filter( 'admin_body_class', array(&$this, 'admin_body_class') );
add_action('admin_enqueue_scripts', array(&$this, 'add_user_admin_js'));
}
function add_admin_menu() {
$page_suffix = add_menu_page( __('Tainacan', 'tainacan'), __('Tainacan', 'tainacan'), 'edit_posts', $this->menu_slug, array(&$this, 'admin_page') );
add_action( 'load-' . $page_suffix, array(&$this, 'load_admin_page'));
}
function load_admin_page() {
add_action( 'admin_enqueue_scripts', array(&$this, 'add_admin_css') );
add_action( 'admin_enqueue_scripts', array(&$this, 'add_admin_css'), 90 );
}
function login_styles_reset( $style ) {
if ( strpos( $style, 'wp-admin-css') !== FALSE ) {
$style = NULL;
}
return $style;
}
function add_admin_css() {
global $TAINACAN_BASE_URL;
global $TAINACAN_BASE_URL;
wp_enqueue_style('tainacan-admin-page', $TAINACAN_BASE_URL . '/assets/css/tainacan-admin.css' );
$undesired_wp_styles = [ 'admin-menu', 'admin-bar', 'code-editor', 'color-picker',
'customize-controls', 'customize-nav-menus', 'customize-widgets', 'dashboard',
'dashicons', 'deprecated-media', 'edit', 'wp-pointer', 'farbtastic', 'forms', 'common',
'install', 'wp-auth-check', 'site-icon', 'buttons', 'l10n', 'list-tables','login',
'media', 'nav-menus', 'revisions', 'themes', 'widgets', 'wp-admin'];
wp_dequeue_style($undesired_wp_styles);
wp_deregister_style($undesired_wp_styles);
}
function admin_body_class($classes) {
@ -46,23 +62,22 @@ class Admin {
echo "<div id='tainacan-admin-app'></div>";
//wp_enqueue_script( 'tainacan-dev-admin', $TAINACAN_BASE_URL . '/assets/dev_admin-components.js', [] , null, true);
wp_enqueue_script( 'tainacan-user-admin', $TAINACAN_BASE_URL . '/assets/user_admin-components.js', [] , null, true);
$tainacan_admin_i18n = require('tainacan-admin-i18n.php');
$components = ( has_filter( 'tainacan_register_web_components' ) ) ? apply_filters('tainacan_register_web_components') : [];
$settings = [
'root' => esc_url_raw( rest_url() ).'tainacan/v2',
'nonce' => wp_create_nonce( 'wp_rest' ),
'components' => $components,
'i18n' => $tainacan_admin_i18n
];
wp_localize_script( 'tainacan-user-admin', 'wp_settings', $settings );
}
function add_user_admin_js() {
global $TAINACAN_BASE_URL;
$components = ( has_filter( 'tainacan_register_web_components' ) ) ? apply_filters('tainacan_register_web_components') : [];
wp_enqueue_script('wp-settings',$TAINACAN_BASE_URL . '/js/wp-settings.js');
$settings = [
'root' => esc_url_raw( rest_url() ).'tainacan/v2',
'nonce' => wp_create_nonce( 'wp_rest' ),
'components' => $components
];
wp_localize_script( 'wp-settings', 'wp_settings', $settings );
}
}

View File

@ -1,45 +1,78 @@
<template>
<div>
<router-link tag="button" class="button is-primary"
:to="{ path: `/collections/new` }">
Criar Coleção
</router-link>
<b-table
ref="multipleTable"
:data="collections"
style="width: 100%"
@selection-change="handleSelectionChange"
stripe>
<template slot-scope="props">
<section class="section">
<b-field grouped group-multiline>
<button v-if="selectedCollections.length > 0" class="button field is-danger" @click="deleteSelectedCollections()"><span>Deletar coleções selecionadas </span><b-icon icon="delete"></b-icon></button>
<b-select
v-model="collectionsPerPage"
@input="onChangeCollectionsPerPage"
:disabled="collections.length <= 0">
<option value="2">2 coleções por página</option>
<option value="10">10 coleções por página</option>
<option value="15">15 coleções por página</option>
<option value="20">20 coleções por página</option>
</b-select>
<b-table-column field="featured_image" width="55">
<template v-if="props.row.featured_image" slot-scope="scope">
<img class="table-thumb" :src="`${props.row.featured_image}`"/>
</template>
</b-table-column>
</b-field>
<b-table
ref="collectionTable"
:data="collections"
@selection-change="handleSelectionChange"
:checked-rows.sync="selectedCollections"
checkable
:loading="isLoading"
hoverable
striped
selectable
paginated
backend-pagination
:total="totalCollections"
:per-page="collectionsPerPage"
@page-change="onPageChange">
<template slot-scope="props">
<b-table-column label="Nome" field="props.row.name">
<router-link :to="`/collections/${props.row.id}`" tag="a">{{ props.row.name }}</router-link>
</b-table-column>
<b-table-column field="featured_image" width="55">
<template v-if="props.row.featured_image" slot-scope="scope">
<img class="table-thumb" :src="`${props.row.featured_image}`"/>
</template>
</b-table-column>
<b-table-column property="description" label="Descrição" show-overflow-tooltip field="props.row.description">
{{ props.row.description }}
</b-table-column>
<b-table-column label="Nome" field="props.row.name">
{{ props.row.name }}
</b-table-column>
<b-table-column property="description" label="Descrição" show-overflow-tooltip field="props.row.description">
{{ props.row.description }}
</b-table-column>
<b-table-column label="Ações">
<router-link :to="`/collections/${props.row.id}/edit`" tag="a"><b-icon icon="pencil"></router-link>
<a @click.native="showMoreCollection(props.row.id)">
<b-icon icon="dots-vertical">
</a>
</b-table-column>
<b-table-column label="Ações" width="110">
<a @click.prevent.stop="goToCollectionPage(props.row.id)"><b-icon icon="eye"></a>
<a @click.prevent.stop="goToCollectionEditPage(props.row.id)"><b-icon icon="pencil"></a>
<a @click.prevent.stop="deleteOneCollection(props.row.id)"><b-icon icon="delete"></a>
</b-table-column>
</template>
</template>
<!--b-table-column type="selection" width="55">
</b-table-column -->
</b-table>
<!-- Empty state image -->
<template slot="empty">
<section class="section">
<div class="content has-text-grey has-text-centered">
<p>
<b-icon
icon="inbox"
size="is-large">
</b-icon>
</p>
<p>Nenhuma coleção ainda neste repositório.</p>
<router-link tag="button" class="button is-primary"
:to="{ path: `/collections/new` }">
Criar Coleção
</router-link>
</div>
</section>
</template>
</b-table>
</section>
</div>
</template>
@ -50,21 +83,107 @@ export default {
name: 'CollectionsList',
data(){
return {
multipleSelection: []
selectedCollections: [],
tableFields: [],
isLoading: false,
totalCollections: 0,
page: 1,
collectionsPerPage: 2
}
},
methods: {
...mapActions('collection', [
'fetchCollections'
'fetchCollections',
'deleteCollection'
]),
...mapGetters('collection', [
'getCollections'
]),
handleSelectionChange(value) {
this.multipleSelection = value;
deleteOneCollection(collectionId) {
this.$dialog.confirm({
message: 'Deseja realmente deletar esta Coleção?',
onConfirm: () => {
this.deleteCollection(collectionId).then(() => {
this.loadCollections();
this.$toast.open({
duration: 3000,
message: `Coleção deletada`,
position: 'is-bottom',
type: 'is-secondary',
queue: true
})
for (let i = 0; i < this.selectedCollections.length; i++) {
if (this.selectedCollections[i].id == this.collectionId)
this.selectedCollections.splice(i, 1);
}
}).catch(() =>
this.$toast.open({
duration: 3000,
message: `Erro ao deletar coleção`,
position: 'is-bottom',
type: 'is-danger',
queue: true
})
);
}
});
},
showMoreCollection(collectionId) {
deleteSelectedCollections() {
this.$dialog.confirm({
message: 'Deseja realmente todos as coleções selecionadas?',
onConfirm: () => {
for (let collection of this.selectedCollections) {
this.deleteCollection(collection.id)
.then((res) => {
this.loadCollections();
this.$toast.open({
duration: 3000,
message: `Coleção deletada`,
position: 'is-bottom',
type: 'is-secondary',
queue: false
})
}).catch((err) => {
this.$toast.open({
duration: 3000,
message: `Erro ao deletar coleção`,
position: 'is-bottom',
type: 'is-danger',
queue: false
});
});
}
this.selectedCollections = [];
}
});
},
handleSelectionChange(value) {
},
goToCollectionPage(collectionId) {
this.$router.push(`/collections/${collectionId}`);
},
goToCollectionEditPage(collectionId) {
this.$router.push(`/collections/${collectionId}/edit`);
},
onChangeCollectionsPerPage(value) {
this.collectionsPerPage = value;
this.loadCollections();
},
onPageChange(page) {
this.page = page;
this.loadCollections();
},
loadCollections() {
this.isLoading = true;
this.fetchCollections({ 'page': this.page, 'collectionsPerPage': this.collectionsPerPage })
.then((res) => {
this.isLoading = false;
this.totalCollections = res.total;
})
.catch((error) => {
this.isLoading = false;
});
}
},
computed: {
@ -72,8 +191,8 @@ export default {
return this.getCollections();
}
},
created(){
this.fetchCollections();
mounted(){
this.loadCollections();
}
}
@ -86,6 +205,8 @@ export default {
vertical-align: middle !important;
}
tr { cursor: pointer !important; }
</style>

View File

@ -1,37 +1,68 @@
<template>
<div>
<section class="section">
<button v-if="selectedItems.length > 0" class="button field is-danger" @click="deleteSelectedItems()"><span>Deletar itens selecionados </span><b-icon icon="delete"></b-icon></button>
<b-table
ref="itemsTable"
<b-field grouped group-multiline>
<button v-if="selectedItems.length > 0" class="button field is-danger" @click="deleteSelectedItems()"><span>Deletar itens selecionados </span><b-icon icon="delete"></b-icon></button>
<b-dropdown>
<button class="button" slot="trigger">
<span>Campos da tabela</span>
<b-icon icon="menu-down"></b-icon>
</button>
<b-dropdown-item v-for="(column, index) in tableFields"
:key="index"
class="control" custom>
<b-checkbox v-model="column.visible"
:native-value="column.field">
{{ column.label }}
</b-checkbox>
</b-dropdown-item>
</b-dropdown>
<b-select
v-model="itemsPerPage"
@input="onChangeItemsPerPage"
:disabled="items.length <= 0">
<option value="2">2 itens por página</option>
<option value="10">10 itens por página</option>
<option value="15">15 itens por página</option>
<option value="20">20 itens por página</option>
</b-select>
</b-field>
<b-table ref="itemsTable"
:data="items"
@selection-change="handleSelectionChange"
:checked-rows.sync="selectedItems"
checkable
:loading="isLoading"
checkable>
hoverable
striped
selectable
paginated
backend-pagination
:total="totalItems"
:per-page="itemsPerPage"
@page-change="onPageChange"
backend-sorting>
<template slot-scope="props">
<b-table-column field="featured_image" width="55">
<template v-if="props.row.featured_image" slot-scope="scope">
<img class="table-thumb" :src="`${props.row.featured_image}`"/>
<b-table-column v-for="(column, index) in tableFields"
:key="index"
:label="column.label"
:visible="column.visible"
:width="column.field == 'row_actions' ? 110 : column.field == 'featured_image' ? 55 : undefined ">
<template v-if="column.field != 'featured_image' && column.field != 'row_actions'">{{
props.row.metadata[column.slug].multiple == 'yes' ? props.row.metadata[column.slug].value.join(', ') : props.row.metadata[column.slug].value
}}</template>
<template v-if="column.field == 'featured_image'">
<img class="table-thumb" :src="`${ props.row[column.slug] }`"/>
</template>
<template v-if="column.field == 'row_actions'">
<a @click.prevent.stop="goToItemPage(props.row.id)"><b-icon icon="eye"></a>
<a @click.prevent.stop="goToItemEditPage(props.row.id)"><b-icon icon="pencil"></a>
<a @click.prevent.stop="deleteOneItem(props.row.id)"><b-icon icon="delete"></a>
</template>
</b-table-column>
<b-table-column label="Nome" field="title" show-overflow-tooltip>
<router-link
:to="`/collections/${collectionId}/items/${props.row.id}`" tag="a">{{ props.row.title }}
</router-link>
</b-table-column>
<b-table-column field="description" label="Descrição">
{{ props.row.description }}
</b-table-column>
<b-table-column label="Ações">
<router-link :to="`/collections/${collectionId}/items/${props.row.id}/edit`" tag="a"><b-icon icon="pencil"></router-link>
<a><b-icon icon="delete" @click.native="deleteOneItem(props.row.id)"></a>
<a><b-icon icon="dots-vertical" @click.native="showMoreItem(props.row.id)"></a>
</b-table-column>
</template>
@ -66,7 +97,11 @@ export default {
data(){
return {
selectedItems: [],
isLoading: Boolean
tableFields: [],
isLoading: false,
totalItems: 0,
page: 1,
itemsPerPage: 2
}
},
props: {
@ -75,32 +110,40 @@ export default {
methods: {
...mapActions('collection', [
'fetchItems',
'deleteItem'
'deleteItem',
'fetchFields'
]),
...mapGetters('collection', [
'getItems'
'getItems',
'getFields'
]),
deleteOneItem(itemId) {
this.$dialog.confirm({
message: 'Deseja realmente deletar este Item?',
onConfirm: () => {
this.deleteItem(itemId).then(() =>
this.deleteItem(itemId).then((res) => {
this.loadItems();
this.$toast.open({
duration: 3000,
message: `Item deletado`,
position: 'is-bottom',
type: 'is-secondary',
queue: true
})
).catch(() =>
this.$toast.open({
});
for (let i = 0; i < this.selectedItems.length; i++) {
if (this.selectedItems[i].id == this.itemId)
this.selectedItems.splice(i, 1);
}
}).catch(( error ) => {
this.$toast.open({
duration: 3000,
message: `Erro ao deletar item`,
position: 'is-bottom',
type: 'is-danger',
queue: true
})
);
});
}
});
},
@ -112,13 +155,15 @@ export default {
for (let item of this.selectedItems) {
this.deleteItem(item.id)
.then((res) => {
this.loadItems();
this.$toast.open({
duration: 3000,
message: `Item deletado`,
position: 'is-bottom',
type: 'is-secondary',
queue: false
})
});
}).catch((err) => {
this.$toast.open({
duration: 3000,
@ -135,9 +180,31 @@ export default {
});
},
handleSelectionChange() {
},
showMoreItem(itemId) {
onChangeItemsPerPage(value) {
this.itemsPerPage = value;
this.loadItems();
},
goToItemPage(itemId) {
this.$router.push(`/collections/${this.collectionId}/items/${itemId}`);
},
goToItemEditPage(itemId) {
this.$router.push(`/collections/${this.collectionId}/items/${itemId}/edit`);
},
onPageChange(page) {
this.page = page;
this.loadItems();
},
loadItems() {
this.isLoading = true;
this.fetchItems({ 'collectionId': this.collectionId, 'page': this.page, 'itemsPerPage': this.itemsPerPage })
.then((res) => {
this.isLoading = false;
this.totalItems = res.total;
})
.catch((error) => {
this.isLoading = false;
});
}
},
computed: {
@ -145,13 +212,17 @@ export default {
return this.getItems();
}
},
created(){
this.isLoading = true;
this.fetchItems(this.collectionId)
.then(res => this.isLoading = false)
.catch((error) => {
this.isLoading = false;
});
mounted(){
this.loadItems();
this.fetchFields(this.collectionId).then((res) => {
let rawFields = res;
for (let field of rawFields) {
this.tableFields.push(
{ label: field.name, field: field.description, slug: field.slug, visible: true }
);
}
this.tableFields.push({ label: 'Ações', field: 'row_actions', slug: 'actions', visible: true });
}).catch();
}
}
@ -164,6 +235,8 @@ export default {
vertical-align: middle !important;
}
tr { cursor: pointer }
</style>

View File

@ -0,0 +1,96 @@
<template>
<nav id="primary-menu" :class="isCompressed ? 'is-compressed' : ''" role="navigation" aria-label="main navigation" class="column is-2 is-sidebar-menu">
<aside class="menu">
<ul class="menu-list">
<li><router-link tag="a" to="/collections" :class="activeRoute == '/collections' ? 'is-active':''">
<b-icon size="is-small" icon="folder-multiple"></b-icon> <span class="menu-text">{{ $i18n.get('collections')}}</span>
</router-link></li>
<li><router-link tag="a" to="/items" :class="activeRoute == '/items' ? 'is-active':''">
<b-icon size="is-small" icon="note-multiple"></b-icon> <span class="menu-text">{{ $i18n.get('items')}}</span>
</router-link></li>
<li><router-link tag="a" to="/fields" :class="activeRoute == '/fields' ? 'is-active':''">
<b-icon size="is-small" icon="format-list-checks"></b-icon> <span class="menu-text">{{ $i18n.get('fields')}}</span>
</router-link></li>
<li><router-link tag="a" to="/filters" :class="activeRoute == '/filters' ? 'is-active':''">
<b-icon size="is-small" icon="filter"></b-icon> <span class="menu-text">{{ $i18n.get('filters')}}</span>
</router-link></li>
<li><router-link tag="a" to="/categories" :class="activeRoute == '/categories' ? 'is-active':''">
<b-icon size="is-small" icon="shape"></b-icon> <span class="menu-text">{{ $i18n.get('categories')}}</span>
</router-link></li>
<li><router-link tag="a" to="/events" :class="activeRoute == '/events' ? 'is-active':''">
<b-icon size="is-small" icon="calendar"></b-icon> <span class="menu-text">{{ $i18n.get('events')}}</span>
</router-link></li>
<li><a class="navbar-item" :href="wordpressAdmin">
<b-icon size="is-small" icon="wordpress"></b-icon> <span class="menu-text">Wordpress</span>
</a></li>
</ul>
</aside>
</nav>
</template>
<script>
export default {
name: 'PrimaryMenu',
data(){
return {
isCompressed: false,
activeRoute: '/collections'
}
},
watch: {
'$route' (to, from) {
this.isCompressed = (to.params.id != undefined);
this.activeRoute = to.path;
}
},
created () {
this.isCompressed = (this.$route.params.id != undefined);
this.activeRoute = this.$route.path;
}
}
</script>
<style lang="scss" scoped>
@import "../scss/_variables.scss";
#primary-menu {
background-color: $primary;
-webkit-transition: width 0.8s; /* Safari */
transition: all 0.1s;
li{
a {color: white}
a:hover {color: $primary}
a.is-active {
background-color: white;
color: $secondary;
color: $primary;
}
}
&.is-compressed {
width: 64px;
max-width: 64px;
.menu-text {
display: none;
}
box-shadow: -1px 0px 5px #111 inset;
}
@media screen and (max-width: 769px) {
width: 100% !important;
max-width: 100% !important;
.menu-text {
display: none !important;
}
ul {
display: flex;
align-items: stretch;
justify-content: space-between;
}
}
}
</style>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.3 KiB

View File

@ -4,7 +4,6 @@ import Buefy from 'buefy'
Vue.use(Buefy);
import AdminPage from '../admin.vue'
//import { eventBus } from '../../js/event-bus-web-components'
import store from '../../js/store/store'
import router from './router'
@ -17,8 +16,6 @@ router.beforeEach((to, from, next) => {
// FROM DEV
// include vue-custom-element plugin to Vue
import Text from '../../classes/field-types/text/Text.vue';
import Textarea from '../../classes/field-types/textarea/Textarea.vue';
import Selectbox from '../../classes/field-types/selectbox/Selectbox.vue';
@ -27,10 +24,8 @@ import Radio from '../../classes/field-types/radio/Radio.vue';
import Numeric from '../../classes/field-types/numeric/Numeric.vue';
import Date from '../../classes/field-types/date/Date.vue';
import Relationship from '../../classes/field-types/relationship/Relationship.vue';
import TaincanFormItem from '../../classes/field-types/tainacan-form-item.vue';
Vue.component('tainacan-text', Text);
Vue.component('tainacan-textarea', Textarea);
Vue.component('tainacan-selectbox', Selectbox);
@ -43,8 +38,20 @@ Vue.component('tainacan-relationship', Relationship);
Vue.component('tainacan-form-item', TaincanFormItem);
//------------------------------------------------
// I18N PLUGIN
const I18NPlugin = {};
I18NPlugin.install = function (Vue, options = {}) {
Vue.prototype.$i18n = {
get: function (key) {
let string = wp_settings.i18n[key];
return (string != undefined && string != null && string != '' ) ? string : "ERROR: Invalid i18n key!";
}
}
// eventBus.listener();
}
Vue.use(I18NPlugin);
new Vue({
el: '#tainacan-admin-app',

View File

@ -2,10 +2,16 @@ import Vue from 'vue';
import VueRouter from 'vue-router'
import AdminPage from '../admin.vue'
import CollectionsPage from '../pages/collections-page.vue'
import CollectionPage from '../pages/collection-page.vue'
import CollectionEditionPage from '../pages/collection-edition-page.vue'
import ItemsPage from '../pages/items-page.vue'
import ItemPage from '../pages/item-page.vue'
import ItemEditionPage from '../pages/item-edition-page.vue'
import FieldsPage from '../pages/fields-page.vue'
import FiltersPage from '../pages/filters-page.vue'
import CategoriesPage from '../pages/categories-page.vue'
import EventsPage from '../pages/events-page.vue'
import CollectionsList from '../components/collections-list.vue'
import ItemsList from '../components/items-list.vue'
@ -13,15 +19,29 @@ import ItemsList from '../components/items-list.vue'
Vue.use(VueRouter);
const routes = [
{ path: '/', component: CollectionsList, meta: {title: 'Admin Page'} },
{ path: '/collections', component: CollectionsList, meta: {title: 'Collections List'} },
{ path: '/', component: CollectionsPage, meta: {title: 'Admin Page'} },
{ path: '/collections', component: CollectionsPage, meta: {title: 'Collections Page'} },
{ path: '/collections/new', component: CollectionEditionPage, meta: {title: 'Create Collection'} },
{ path: '/collections/:id', component: CollectionPage, meta: {title: 'Collections Page'} },
{ path: '/collections/:id/edit', component: CollectionEditionPage, meta: {title: 'Edit Collection'} },
{ path: '/collections/:id/items/new', component: ItemEditionPage, meta: {title: 'Create Item'} },
{ path: '/collections/:collection_id/items/:id/edit', component: ItemEditionPage, meta: {title: 'Edit Item'} },
{ path: '/collection/:collection_id/items', component: ItemsList, meta: {title: 'Items List'} },
{ path: '/collection/:collection_id/items', component: ItemsPage, meta: {title: 'Items Page'} },
{ path: '/collections/:collection_id/items/:id', component: ItemPage, meta: {title: 'Item Page'} },
{ path: '/items', component: ItemsPage, meta: {title: 'Items Page'} },
{ path: '/filters', component: FiltersPage, meta: {title: 'Filters Page'} },
{ path: '/fields', component: FieldsPage, meta: {title: 'Fields Page'} },
{ path: '/categories', component: CategoriesPage, meta: {title: 'Categories Page'} },
{ path: '/events', component: EventsPage, meta: {title: 'Events Page'} },
{ path: '*', redirect: '/'}
]

View File

@ -0,0 +1,21 @@
<template>
<div>
<h1>Categories Page</h1>
</div>
</template>
<script>
export default {
name: 'CategoriesPage',
data(){
return {
}
}
}
</script>
<style scoped>
</style>

View File

@ -157,7 +157,7 @@ export default {
}
},
created(){
if (this.$route.fullPath.split("/").pop() == "new") {
this.createNewCollection();
} else if (this.$route.fullPath.split("/").pop() == "edit") {

View File

@ -1,6 +1,16 @@
<template>
<div>
<section class="section" v-if="collection != null">
<div class="columns is-fullheight">
<nav id="secondary-menu" role="navigation" aria-label="secondary navigation" class="column is-2 is-sidebar-menu">
<aside class="menu">
<ul class="menu-list">
<li><router-link tag="a" to="">{{ $i18n.get('items')}}</router-link></li>
<li><router-link tag="a" to="">{{ $i18n.get('edit')}}</router-link></li>
<li><router-link tag="a" to="">{{ $i18n.get('fields')}}</router-link></li>
<li><router-link tag="a" to="">{{ $i18n.get('filters')}}</router-link></li>
</ul>
</aside>
</nav>
<section class="container column is-main-content" v-if="collection != null">
<div class="card">
<div class="card-image" v-if="collection.featured_image">
<figure class="image is-4by3">
@ -11,7 +21,6 @@
<div class="media">
<div class="media-content">
<p class="title is-4">{{ collection.name }}</p>
<!--p class="subtitle is-6">@johnsmith</p-->
</div>
</div>
@ -21,16 +30,19 @@
</div>
<footer class="card-footer">
<router-link
tag="a"
class="card-footer-item"
:to="{ path: `/collections/${collection.id}/edit` }">
Editar Coleção
</router-link>
<router-link
tag="a"
class="card-footer-item"
:to="{ path: `/collections/${collection.id}/items/new`, params: { collection_id: collection.id }}">
Criar Item
</router-link>
<router-link
tag="a"
class="card-footer-item"
:to="{ path: `/collection/${collection.id}/items/`, params: { collection_id: collection.id }}">
Ver todos os itens
@ -81,40 +93,6 @@ export default {
</script>
<style scoped>
.element-card{
max-width: 500px;
}
.time {
font-size: 13px;
color: #999;
}
.bottom {
margin-top: 13px;
line-height: 12px;
}
el-button {
padding: 0;
float: right;
}
.image {
width: 100%;
display: block;
}
.clearfix:before,
.clearfix:after {
display: table;
content: "";
}
.clearfix:after {
clear: both
}
</style>

View File

@ -0,0 +1,31 @@
<template>
<div>
<h1>Collections Page</h1>
<router-link tag="button" class="button is-primary"
:to="{ path: `/collections/new` }">
Criar Coleção
</router-link>
<collections-list></collections-list>
</div>
</template>
<script>
import CollectionsList from '../components/collections-list.vue';
export default {
name: 'CollectionsPage',
data(){
return {
}
},
components: {
CollectionsList
}
}
</script>
<style scoped>
</style>

View File

@ -0,0 +1,21 @@
<template>
<div>
<h1>Events (or Activites) Page</h1>
</div>
</template>
<script>
export default {
name: 'EventsPage',
data(){
return {
}
}
}
</script>
<style scoped>
</style>

View File

@ -0,0 +1,21 @@
<template>
<div>
<h1>Fields Page</h1>
</div>
</template>
<script>
export default {
name: 'FieldsPage',
data(){
return {
}
}
}
</script>
<style scoped>
</style>

View File

@ -0,0 +1,21 @@
<template>
<div>
<h1>Filters Page</h1>
</div>
</template>
<script>
export default {
name: 'FiltersPage',
data(){
return {
}
}
}
</script>
<style scoped>
</style>

View File

@ -2,19 +2,6 @@
<div>
<h1 class="is-size-3">Item creation <b-tag v-if="item != null && item != undefined" :type="'is-' + getStatusColor(item.status)" v-text="item.status"></b-tag></h1>
<form label-width="120px">
<b-field label="Título">
<b-input
v-model="form.title"
>
</b-input>
</b-field>
<b-field label="Descrição">
<b-input
type="textarea"
v-model="form.description"
>
</b-input>
</b-field>
<b-field label="Status">
<b-select
v-model="form.status"
@ -75,9 +62,7 @@ export default {
isLoading: false,
form: {
collectionId: Number,
title: '',
status: '',
description: '',
files:[]
},
// Can be obtained from api later
@ -114,15 +99,13 @@ export default {
// Puts loading on Item edition
this.isLoading = true;
let data = {item_id: this.itemId, title: this.form.title, description: this.form.description, status: this.form.status};
let data = {item_id: this.itemId, status: this.form.status};
this.updateItem(data).then(updatedItem => {
this.item = updatedItem;
// Fill this.form data with current data.
this.form.title = this.item.title;
this.form.description = this.item.description;
this.form.status = this.item.status;
this.isLoading = false;
@ -153,15 +136,13 @@ export default {
this.isLoading = true;
// Creates draft Item
let data = {collection_id: this.form.collectionId, title: '', description: '', status: 'auto-draft'};
let data = {collection_id: this.form.collectionId, status: 'auto-draft'};
this.sendItem(data).then(res => {
this.itemId = res.id;
this.item = res;
// Fill this.form data with current data.
this.form.title = this.item.title;
this.form.description = this.item.description;
this.form.status = this.item.status;
this.loadMetadata();
@ -204,8 +185,6 @@ export default {
this.item = res;
// Fill this.form data with current data.
this.form.title = this.item.title;
this.form.description = this.item.description;
this.form.status = this.item.status;
this.loadMetadata();

View File

@ -0,0 +1,21 @@
<template>
<div>
<h1>Items Page</h1>
</div>
</template>
<script>
export default {
name: 'ItemsPage',
data(){
return {
}
}
}
</script>
<style scoped>
</style>

View File

@ -0,0 +1,22 @@
// Import Bulma's core and variables
@import "../../../node_modules/bulma/sass/utilities/_all.sass";
// Tainacan custom colors
$primary: #25a189;
$primary-invert: findColorInvert($primary);
$secondary: #01295c;
$secondary-invert: findColorInvert($primary);
// Setup $colors to use as bulma classes
$colors: (
"white": ($white, $black),
"black": ($black, $white),
"light": ($light, $light-invert),
"dark": ($dark, $dark-invert),
"primary": ($primary, $primary-invert),
"secondary": ($secondary, $secondary-invert),
"info": ($info, $info-invert),
"success": ($success, $success-invert),
"warning": ($warning, $warning-invert),
"danger": ($danger, $danger-invert)
);

View File

@ -1,25 +1,5 @@
// Import Bulma's core
@import "../../../node_modules/bulma/sass/utilities/_all.sass";
// Tainacan custom colors
$primary: #25a189;
$primary-invert: findColorInvert($primary);
$secondary: #01295c;
$secondary-invert: findColorInvert($primary);
// Setup $colors to use as bulma classes
$colors: (
"white": ($white, $black),
"black": ($black, $white),
"light": ($light, $light-invert),
"dark": ($dark, $dark-invert),
"primary": ($primary, $primary-invert),
"secondary": ($secondary, $secondary-invert),
"info": ($info, $info-invert),
"success": ($success, $success-invert),
"warning": ($warning, $warning-invert),
"danger": ($danger, $danger-invert)
);
// Tainacan custom colors and bulma's core
@import "./_variables.scss";
// Links
$link: $primary;
@ -34,7 +14,8 @@ $modal-z: 9999999;
@import "../../../node_modules/bulma/bulma.sass";
@import "../../../node_modules/buefy/src/scss/buefy.scss";
body.tainacan-admin-page #adminmenumain {
// Clears wordpress content
body.tainacan-admin-page #adminmenumain, body.tainacan-admin-page #wpfooter, body.tainacan-admin-page #wp-auth-check-wrap {
display: none;
}
@ -48,6 +29,8 @@ body.tainacan-admin-page #adminmenumain {
width: 100%;
z-index: 999999;
overflow-y: auto;
height: 100%;
margin: 0px !important;
}
/* Rules for sizing the icon. */

View File

@ -0,0 +1,24 @@
<?php
return [
// Tainacan common terms
'repository' => __('Repository', 'tainacan'),
'collections' => __('Collections', 'tainacan'),
'items' => __('Items', 'tainacan'),
'fields' => __('Fields', 'tainacan'),
'filters' => __('Filters', 'tainacan'),
'categories' => __('Categories', 'tainacan'),
'events' => __('Events', 'tainacan'),
'collection' => __('Collection', 'tainacan'),
'item' => __('Item', 'tainacan'),
'field' => __('Field', 'tainacan'),
'filter' => __('Filter', 'tainacan'),
'category' => __('Categorie', 'tainacan'),
'event' => __('Event', 'tainacan'),
// Actions
'edit' => __('Edit', 'tainacan'),
'new' => __('New', 'tainacan'),
]
?>

View File

@ -25,15 +25,22 @@ class TAINACAN_REST_Controller extends WP_REST_Controller {
/**
* @param $entity
*
* @param $map
* @param $context
*
* @return array
*/
protected function get_only_needed_attributes($entity, $map){
protected function get_only_needed_attributes($entity, $map, $context = null){
$entity_prepared = [
'id' => $entity->get_id(),
'description' => $entity->get_description(),
];
if($context === 'edit'){
$entity_prepared['current_user_can_edit'] = $entity->can_edit();
}
if(array_key_exists('modification_date', $map)){
$entity_prepared['modification_date'] = $entity->get_modification_date();
}
@ -81,17 +88,20 @@ class TAINACAN_REST_Controller extends WP_REST_Controller {
'authorid' => 'author_id',
'authorname' => 'author_name',
'search' => 's',
'posttype' => 'post_type',
'status' => 'post_status',
'status' => 'post_status',
'offset' => 'offset',
'metaquery' => 'meta_query',
'datequery' => 'date_query',
'taxquery' => 'taxquery',
'order' => 'order',
'orderby' => 'orderby',
'metakey' => 'meta_key',
'hideempty' => 'hide_empty',
'perpage' => 'posts_per_page',
'paged' => 'paged'
'metavalue' => 'meta_value',
'metavaluenum' => 'meta_value_num',
'metacompare' => 'meta_compare',
'hideempty' => 'hide_empty',
'perpage' => 'posts_per_page',
'paged' => 'paged',
];
$meta_query = [
@ -99,16 +109,30 @@ class TAINACAN_REST_Controller extends WP_REST_Controller {
'value' => 'value',
'compare' => 'compare',
'relation' => 'relation',
'type' => 'type',
];
$date_query = [
'year' => 'year',
'month' => 'month',
'day' => 'month',
'week' => 'week',
'hour' => 'hour',
'minute' => 'minute',
'second' => 'second'
'year' => 'year',
'month' => 'month',
'day' => 'day',
'week' => 'week',
'hour' => 'hour',
'minute' => 'minute',
'second' => 'second',
'compare' => 'compare',
'dayofweek' => 'dayofweek',
'inclusive' => 'inclusive',
'before' => 'before',
'after' => 'after',
];
$tax_query = [
'taxonomy' => 'taxonomy',
'field' => 'field',
'terms' => 'terms',
'operator' => 'operator',
'relation' => 'relation',
];
$args = [];
@ -116,22 +140,70 @@ class TAINACAN_REST_Controller extends WP_REST_Controller {
foreach ($map as $mapped => $mapped_v){
if(isset($request[$mapped])){
if($mapped === 'metaquery'){
foreach ($meta_query as $mapped_meta => $meta_v){
$args[$mapped_v][$meta_v] = $request[$mapped][$mapped_meta];
}
} elseif ($mapped === 'datequery') {
foreach ($date_query as $date_meta => $date_v){
$args[$mapped_v][$date_v] = $request[$mapped][$date_meta];
}
} else {
$args = $this->prepare_meta($mapped, $request, $meta_query, $mapped_v, $args);
} elseif($mapped === 'datequery'){
$args = $this->prepare_meta($mapped, $request, $date_query, $mapped_v, $args);
} elseif($mapped === 'taxquery'){
$args = $this->prepare_meta($mapped, $request, $tax_query, $mapped_v, $args);
}
else {
$args[ $mapped_v ] = $request[ $mapped ];
}
}
}
$args['perm'] = 'readable';
return $args;
}
/**
* @param $mapped
* @param $request
* @param $query
* @param $mapped_v
* @param $args
*
* @return mixed
*/
private function prepare_meta($mapped, $request, $query, $mapped_v, $args){
$request_meta_query = $request[$mapped];
// If is a multidimensional array (array of array)
if($this->contains_array($request_meta_query)) {
foreach ( $request_meta_query as $index1 => $a ) {
foreach ( $query as $mapped_meta => $meta_v ) {
if ( isset( $a[ $meta_v ] ) ) {
$args[ $mapped_v ][ $index1 ][ $meta_v ] = $request[ $mapped ][ $index1 ][ $meta_v ];
}
}
}
} else {
foreach ( $query as $mapped_meta => $meta_v ) {
if(isset($request[$mapped][$meta_v])) {
$args[ $mapped_v ][ $meta_v ] = $request[ $mapped ][ $meta_v ];
}
}
}
return $args;
}
/**
* @param $array
*
* @return bool
*/
protected function contains_array($array){
foreach ($array as $value){
if(is_array($value)){
return true;
}
}
return false;
}
}
?>

View File

@ -92,7 +92,7 @@ class TAINACAN_REST_Collections_Controller extends TAINACAN_REST_Controller {
$collection = new Entities\Collection($collections->post);
array_push($response, $this->get_only_needed_attributes($collection, $map));
array_push($response, $this->get_only_needed_attributes($collection, $map, $request['context']));
}
wp_reset_postdata();
@ -136,7 +136,13 @@ class TAINACAN_REST_Collections_Controller extends TAINACAN_REST_Controller {
*/
public function prepare_item_for_response($item, $request){
if(!empty($item)){
return $item->__toArray();
$item_arr = $item->__toArray();
if($request['context'] === 'edit'){
$item_arr['current_user_can_edit'] = $item->can_edit();
}
return $item_arr;
}
return $item;
@ -150,7 +156,12 @@ class TAINACAN_REST_Collections_Controller extends TAINACAN_REST_Controller {
* @throws Exception
*/
public function get_items_permissions_check($request){
return $this->collections_repository->can_read($this->collection);
if ( 'edit' === $request['context'] && ! current_user_can('edit_tainacan-collections') ) {
return false;
}
return true;
}
/**
@ -346,15 +357,6 @@ class TAINACAN_REST_Collections_Controller extends TAINACAN_REST_Controller {
return false;
}
/**
* @return array|mixed|void
*/
public function get_collection_params() {
$query_params = $this->collections_repository->get_map();
return $query_params;
}
/**
* @param string $method
*

View File

@ -162,7 +162,13 @@ class TAINACAN_REST_Fields_Controller extends TAINACAN_REST_Controller {
*/
public function prepare_item_for_response( $item, $request ) {
if(!empty($item)){
return $item->__toArray();
$item_arr = $item->__toArray();
if($request['context'] === 'edit'){
$item_arr['current_user_can_edit'] = $item->can_edit();
}
return $item_arr;
}
return $item;
@ -197,12 +203,15 @@ class TAINACAN_REST_Fields_Controller extends TAINACAN_REST_Controller {
* @throws Exception
*/
public function get_items_permissions_check( $request ) {
if (isset($request['collection_id'])) {
$collection = $this->collection_repository->fetch($request['collection_id']);
if (isset($request['collection_id'])) {
if ( 'edit' === $request['context'] && ! current_user_can('edit_tainacan-fields') ) {
return false;
}
return true;
if ($collection instanceof Entities\Collection) {
return $collection->can_read();
}
}
return false;

View File

@ -39,12 +39,14 @@ class TAINACAN_REST_Filters_Controller extends TAINACAN_REST_Controller {
}
public function register_routes() {
register_rest_route($this->namespace, '/' . $this->rest_base, array(
register_rest_route($this->namespace, '/collection/(?P<collection_id>[\d]+)/field/(?P<field_id>[\d]+)/' . $this->rest_base, array(
array(
'methods' => WP_REST_Server::CREATABLE,
'callback' => array($this, 'create_item'),
'permission_callback' => array($this, 'create_item_permissions_check')
),
));
register_rest_route($this->namespace, '/' . $this->rest_base, array(
array(
'methods' => WP_REST_Server::READABLE,
'callback' => array($this, 'get_items'),
@ -79,8 +81,8 @@ class TAINACAN_REST_Filters_Controller extends TAINACAN_REST_Controller {
public function prepare_item_for_database( $request ) {
$body = json_decode($request->get_body(), true);
$collection_id = $body['collection_id'];
$field_id = $body['field_id'];
$collection_id = $request['collection_id'];
$field_id = $request['field_id'];
$filter = $body['filter'];
$received_type = $body['filter_type'];
@ -124,17 +126,17 @@ class TAINACAN_REST_Filters_Controller extends TAINACAN_REST_Controller {
if ($this->filter->validate()){
$filter_inserted = $this->filter_repository->insert($this->filter);
return new WP_REST_Response($filter_inserted->__toArray(), 200);
return new WP_REST_Response($this->prepare_item_for_response($filter_inserted, $request), 200);
}
return new WP_REST_Response([
'error_message' => 'One or more attributes are invalid',
'error_message' => __('One or more attributes are invalid', 'tainacan'),
'error' => $this->filter->get_errors()
], 400);
}
return new WP_REST_Response([
'error_message' => 'The body could not be empty.',
'error_message' => __('The body could not be empty', 'tainacan'),
'body' => $request->get_body()
], 400);
}
@ -147,8 +149,8 @@ class TAINACAN_REST_Filters_Controller extends TAINACAN_REST_Controller {
public function create_item_permissions_check( $request ) {
$body = json_decode($request->get_body(), true);
$metadata = $this->field_repository->fetch($body['field_id']);
$collection = $this->collection_repository->fetch($body['collection_id']);
$metadata = $this->field_repository->fetch($request['field_id']);
$collection = $this->collection_repository->fetch($request['collection_id']);
if(($metadata instanceof Entities\Field) && ($collection instanceof Entities\Collection)) {
return $this->filter_repository->can_edit($this->filter) && $metadata->can_edit() && $collection->can_edit();
@ -172,11 +174,11 @@ class TAINACAN_REST_Filters_Controller extends TAINACAN_REST_Controller {
$filter = $this->filter_repository->delete($args);
return new WP_REST_Response($filter->__toArray(), 200);
return new WP_REST_Response($this->prepare_item_for_response($filter, $request), 200);
}
return new WP_REST_Response([
'error_message' => 'The body could not be empty',
'error_message' => __('The body could not be empty', 'tainacan'),
'body' => $request->get_body()
], 400);
}
@ -221,13 +223,13 @@ class TAINACAN_REST_Filters_Controller extends TAINACAN_REST_Controller {
if($prepared_filter->validate()) {
$updated_filter = $this->filter_repository->update( $prepared_filter );
return new WP_REST_Response($updated_filter->__toArray(), 200);
return new WP_REST_Response($this->prepare_item_for_response($updated_filter, $request), 200);
}
return new WP_REST_Response([
'error_message' => __('One or more values are invalid.', 'tainacan'),
'errors' => $prepared_filter->get_errors(),
'filters' => $prepared_filter->__toArray()
'filters' => $this->prepare_item_for_response($prepared_filter, $request)
], 400);
}
@ -261,24 +263,23 @@ class TAINACAN_REST_Filters_Controller extends TAINACAN_REST_Controller {
}
/**
* @param mixed $object
* @param $item
* @param WP_REST_Request $request
*
* @return array|mixed|WP_Error|WP_REST_Response
*/
public function prepare_item_for_response( $object, $request ) {
public function prepare_item_for_response( $item, $request ) {
if(!empty($item)) {
$item_arr = $item->__toArray();
if(is_array($object)){
$filters = [];
foreach ($object as $item){
$filters[] = $item->__toArray();
if($request['context'] === 'edit'){
$item_arr['current_user_can_edit'] = $item->can_edit();
}
return $filters;
return $item_arr;
}
return $object;
return $item;
}
/**
@ -291,7 +292,10 @@ class TAINACAN_REST_Filters_Controller extends TAINACAN_REST_Controller {
$filters = $this->filter_repository->fetch($args, 'OBJECT');
$response = $this->prepare_item_for_response($filters, $request);
$response = [];
foreach ($filters as $filter){
array_push($response, $this->prepare_item_for_response($filter, $request));
}
return new WP_REST_Response($response, 200);
}
@ -315,7 +319,7 @@ class TAINACAN_REST_Filters_Controller extends TAINACAN_REST_Controller {
$filter = $this->filter_repository->fetch($filter_id);
return new WP_REST_Response($filter->__toArray(), 200);
return new WP_REST_Response($this->prepare_item_for_response($filter, $request), 200);
}
/**

View File

@ -85,7 +85,13 @@ class TAINACAN_REST_Item_Metadata_Controller extends TAINACAN_REST_Controller {
* @return array|WP_Error|WP_REST_Response
*/
public function prepare_item_for_response( $item, $request ) {
return $item->__toArray();
$item_arr = $item->__toArray();
if($request['context'] === 'edit'){
$item_arr['current_user_can_edit'] = $item->can_edit();
}
return $item_arr;
}
/**
@ -104,7 +110,7 @@ class TAINACAN_REST_Item_Metadata_Controller extends TAINACAN_REST_Controller {
foreach ($items_metadata as $item_metadata){
$index = array_push($prepared_item, $this->prepare_item_for_response($item_metadata, $request));
$prepared_item[$index-1]['field']['field_type_object'] = $item_metadata->get_field()->get_field_type_object()->__toArray();
$prepared_item[$index-1]['field']['field_type_object'] = $this->prepare_item_for_response( $item_metadata->get_field()->get_field_type_object(), $request);
}
return new WP_REST_Response($prepared_item, 200);
@ -193,9 +199,10 @@ class TAINACAN_REST_Item_Metadata_Controller extends TAINACAN_REST_Controller {
if ( $item_metadata->validate() ) {
if($item->can_edit()) {
$field_updated = $this->item_metadata_repository->insert( $item_metadata );
$prepared_item = $this->prepare_item_for_response($field_updated, $request);
$prepared_item['field']['field_type_object'] = $field_updated->get_field()->get_field_type_object()->__toArray();
$field_updated = $this->item_metadata_repository->update( $item_metadata );
$prepared_item = $this->prepare_item_for_response($field_updated, $request);
$prepared_item['field']['field_type_object'] = $this->prepare_item_for_response($field_updated->get_field()->get_field_type_object(), $request);
}
elseif($field->get_accept_suggestion()) {
$log = $this->item_metadata_repository->suggest( $item_metadata );
@ -212,7 +219,7 @@ class TAINACAN_REST_Item_Metadata_Controller extends TAINACAN_REST_Controller {
return new WP_REST_Response( [
'error_message' => __( 'One or more values are invalid.', 'tainacan' ),
'errors' => $item_metadata->get_errors(),
'item_metadata' => $item_metadata->__toArray(),
'item_metadata' => $this->prepare_item_for_response($item_metadata, $request),
], 400 );
}
}
@ -250,4 +257,4 @@ class TAINACAN_REST_Item_Metadata_Controller extends TAINACAN_REST_Controller {
}
}
?>
?>

View File

@ -78,6 +78,21 @@ class TAINACAN_REST_Items_Controller extends TAINACAN_REST_Controller {
));
}
private function add_metadata_to_item($item_object, $item_array){
$item_metadata = $item_object->get_fields();
foreach($item_metadata as $index => $me){
$field = $me->get_field();
$slug = $field->get_slug();
$item_array['metadata'][$slug]['name'] = $field->get_name();
$item_array['metadata'][$slug]['value'] = $me->get_value();
$item_array['metadata'][$slug]['multiple'] = $field->get_multiple();
}
return $item_array;
}
/**
* @param mixed $item
* @param WP_REST_Request $request
@ -86,7 +101,13 @@ class TAINACAN_REST_Items_Controller extends TAINACAN_REST_Controller {
*/
public function prepare_item_for_response( $item, $request ) {
if(!empty($item)){
return $item->__toArray();
$item_arr = $item->__toArray();
if($request['context'] === 'edit'){
$item_arr['current_user_can_edit'] = $item->can_edit();
}
return $this->add_metadata_to_item($item, $item_arr);
}
return $item;
@ -127,7 +148,10 @@ class TAINACAN_REST_Items_Controller extends TAINACAN_REST_Controller {
$item = new Entities\Item($items->post);
array_push($response, $this->get_only_needed_attributes($item, $map));
$limited_item = $this->get_only_needed_attributes($item, $map, $request['context']);
$limited_item = $this->add_metadata_to_item($item, $limited_item);
array_push($response, $limited_item);
}
wp_reset_postdata();

View File

@ -51,19 +51,11 @@ class TAINACAN_REST_Logs_Controller extends TAINACAN_REST_Controller {
* @return array|WP_Error|WP_REST_Response
*/
public function prepare_item_for_response( $item, $request ) {
$prepared = [];
$map = $this->logs_repository->get_map();
if(is_array($item)){
foreach ($item as $it){
$prepared[] = $this->get_only_needed_attributes($it, $map);
}
return $prepared;
if(!empty($item)){
return $item->__toArray();
}
return $item->__toArray();
return $item;
}
/**
@ -74,15 +66,32 @@ class TAINACAN_REST_Logs_Controller extends TAINACAN_REST_Controller {
public function get_items( $request ) {
$args = $this->prepare_filters($request);
$logs = $this->logs_repository->fetch($args, 'OBJECT');
$logs = $this->logs_repository->fetch($args);
if(!empty($logs)) {
$prepared_logs = $this->prepare_item_for_response( $logs, $request );
$map = $this->logs_repository->get_map();
return new WP_REST_Response($prepared_logs, 200);
$response = [];
if($logs->have_posts()){
while ($logs->have_posts()){
$logs->the_post();
$collection = new Entities\Log($logs->post);
array_push($response, $this->get_only_needed_attributes($collection, $map));
}
wp_reset_postdata();
}
return new WP_REST_Response($logs, 200);
$total_logs = $logs->found_posts;
$max_pages = ceil($total_logs / (int) $logs->query_vars['posts_per_page']);
$rest_response = new WP_REST_Response($response, 200);
$rest_response->header('X-WP-Total', (int) $total_logs);
$rest_response->header('X-WP-TotalPages', (int) $max_pages);
return $rest_response;
}
/**
@ -104,13 +113,9 @@ class TAINACAN_REST_Logs_Controller extends TAINACAN_REST_Controller {
$log = $this->logs_repository->fetch($log_id);
if(!empty($log)) {
$prepared_log = $this->prepare_item_for_response( $log, $request );
$prepared_log = $this->prepare_item_for_response( $log, $request );
return new WP_REST_Response($prepared_log, 200);
}
return new WP_REST_Response($log, 200);
return new WP_REST_Response($prepared_log, 200);
}
/**

View File

@ -81,17 +81,17 @@ class TAINACAN_REST_Taxonomies_Controller extends TAINACAN_REST_Controller {
* @return array|WP_Error|WP_REST_Response
*/
public function prepare_item_for_response( $item, $request ) {
$taxonomies = [];
if(!empty($item)) {
$item_arr = $item->__toArray();
if($request['taxonomy_id']){
return $item->__toArray();
if($request['context'] === 'edit'){
$item_arr['current_user_can_edit'] = $item->can_edit();
}
return $item_arr;
}
foreach ( $item as $it ) {
$taxonomies[] = $it->__toArray();
}
return $taxonomies;
return $item;
}
/**
@ -173,12 +173,12 @@ class TAINACAN_REST_Taxonomies_Controller extends TAINACAN_REST_Controller {
return new WP_REST_Response($deleted, 400);
}
return new WP_REST_Response($deleted->__toArray(), 200);
return new WP_REST_Response($this->prepare_item_for_response($deleted, $request), 200);
}
return new WP_REST_Response([
'error_message' => __('Taxonomy with this id ('. $taxonomy_id .') not found.', 'tainacan'),
'taxonomy' => $taxonomy->__toArray()
'taxonomy' => $this->prepare_item_for_response($taxonomy, $request)
], 400);
}
@ -208,9 +208,12 @@ class TAINACAN_REST_Taxonomies_Controller extends TAINACAN_REST_Controller {
$taxonomies = $this->taxonomy_repository->fetch($args, 'OBJECT');
$taxonomies_prepared = $this->prepare_item_for_response($taxonomies, $request);
$response = [];
foreach ($taxonomies as $taxonomy) {
array_push($response, $this->prepare_item_for_response( $taxonomy, $request ));
}
return new WP_REST_Response($taxonomies_prepared, 200);
return new WP_REST_Response($response, 200);
}
/**
@ -236,12 +239,12 @@ class TAINACAN_REST_Taxonomies_Controller extends TAINACAN_REST_Controller {
if($this->taxonomy->validate()){
$taxonomy = $this->taxonomy_repository->insert($this->taxonomy);
return new WP_REST_Response($taxonomy->__toArray(), 201);
return new WP_REST_Response($this->prepare_item_for_response($taxonomy, $request), 201);
} else {
return new WP_REST_Response([
'error_message' => __('One or more values are invalid.', 'tainacan'),
'errors' => $this->taxonomy->get_errors(),
'item_metadata' => $this->taxonomy->__toArray(),
'item_metadata' => $this->prepare_item_for_response($this->taxonomy, $request),
], 400);
}
} else {
@ -292,13 +295,13 @@ class TAINACAN_REST_Taxonomies_Controller extends TAINACAN_REST_Controller {
if($prepared_taxonomy->validate()){
$updated_taxonomy = $this->taxonomy_repository->update($prepared_taxonomy);
return new WP_REST_Response($updated_taxonomy->__toArray(), 200);
return new WP_REST_Response($this->prepare_item_for_response($updated_taxonomy, $request), 200);
}
return new WP_REST_Response([
'error_message' => __('One or more values are invalid.', 'tainacan'),
'errors' => $prepared_taxonomy->get_errors(),
'taxonomy' => $prepared_taxonomy->__toArray()
'taxonomy' => $this->prepare_item_for_response($prepared_taxonomy, $request)
], 400);
}

View File

@ -109,7 +109,7 @@ class TAINACAN_REST_Terms_Controller extends TAINACAN_REST_Controller {
$term_inserted = $this->terms_repository->fetch($term_id, $taxonomy);
return new WP_REST_Response($term_inserted->__toArray(), 200);
return new WP_REST_Response($this->prepare_item_for_response($term_inserted, $request), 200);
} else {
return new WP_REST_Response([
'error_message' => 'One or more attributes are invalid.',
@ -207,13 +207,13 @@ class TAINACAN_REST_Terms_Controller extends TAINACAN_REST_Controller {
if($prepared_term->validate()){
$updated_term = $this->terms_repository->update($prepared_term, $tax_name);
return new WP_REST_Response($updated_term->__toArray(), 200);
return new WP_REST_Response($this->prepare_item_for_response($updated_term, $request), 200);
}
return new WP_REST_Response([
'error_message' => __('One or more values are invalid.', 'tainacan'),
'errors' => $prepared_term->get_errors(),
'term' => $prepared_term->__toArray()
'term' => $this->prepare_item_for_response($prepared_term, $request)
], 400);
}
@ -252,15 +252,14 @@ class TAINACAN_REST_Terms_Controller extends TAINACAN_REST_Controller {
* @return array|mixed|WP_Error|WP_REST_Response
*/
public function prepare_item_for_response( $item, $request ) {
if(!empty($item)){
$item_arr = $item->__toArray();
if(is_array($item)){
$prepared = [];
foreach ($item as $term){
$prepared[] = $term->__toArray();
if($request['context'] === 'edit'){
$item_arr['current_user_can_edit'] = $item->can_edit();
}
return $prepared;
return $item_arr;
}
return $item;
@ -280,9 +279,12 @@ class TAINACAN_REST_Terms_Controller extends TAINACAN_REST_Controller {
$terms = $this->terms_repository->fetch($args, $taxonomy);
$prepared_terms = $this->prepare_item_for_response($terms, $request);
$response = [];
foreach ($terms as $term) {
array_push($response, $this->prepare_item_for_response( $term, $request ));
}
return new WP_REST_Response($prepared_terms, 200);
return new WP_REST_Response($response, 200);
}
/**
@ -313,7 +315,7 @@ class TAINACAN_REST_Terms_Controller extends TAINACAN_REST_Controller {
$term = $this->terms_repository->fetch($term_id, $taxonomy);
return new WP_REST_Response($term->__toArray(), 200);
return new WP_REST_Response($this->prepare_item_for_response($term, $request), 200);
}
/**

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.3 KiB

View File

@ -8734,6 +8734,4 @@
-webkit-transform: rotate(359deg);
transform: rotate(359deg);
}
}
/*# sourceMappingURL=materialdesignicons.css.map */
}

View File

@ -32,6 +32,15 @@ class Field extends Entity {
function get_name() {
return $this->get_mapped_property('name');
}
/**
* Get field slug
*
* @return string
*/
function get_slug() {
return $this->get_mapped_property('slug');
}
/**
* Return the field order type
@ -153,15 +162,17 @@ class Field extends Entity {
return $this->get_mapped_property('field_type_options');
}
/**
* Return the if the field may be deleted
* Set the field name
*
* @return string
* @param [string] $value
* @return void
*/
function get_can_delete(){
return $this->get_mapped_property('can_delete');
function set_name($value) {
$this->set_mapped_property('name', $value);
}
/**
* Return true if this field allow community suggestions, false otherwise
* @return bool
@ -171,13 +182,19 @@ class Field extends Entity {
}
/**
* Set the field name
* Set the field slug
*
* If you dont set the field slug, it will be set automatically based on the name and
* following WordPress default behavior of creating slugs for posts.
*
* If you set the slug for an existing one, WordPress will append a number at the end of in order
* to make it unique (e.g slug-1, slug-2)
*
* @param [string] $value
* @return void
*/
function set_name($value) {
$this->set_mapped_property('name', $value);
function set_slug($value) {
$this->set_mapped_property('slug', $value);
}
/**
@ -297,16 +314,6 @@ class Field extends Entity {
return $this->set_mapped_property('accept_suggestion', $value);
}
/**
* Set can delete
*
* @param [string] $value
* @return void
*/
function set_can_delete( $value ){
$this->set_mapped_property('can_delete', $value);
}
// helpers
/**
@ -335,4 +342,4 @@ class Field extends Entity {
function is_required() {
return $this->get_required() === 'yes';
}
}
}

View File

@ -32,6 +32,13 @@ class Filter extends Entity {
return $this->get_mapped_property('name');
}
/**
* @return mixed|null
*/
function get_description(){
return $this->get_mapped_property('description');
}
/**
* Return the filter order type
*
@ -50,11 +57,12 @@ class Filter extends Entity {
return $this->get_mapped_property('color');
}
/**
* Return the field
*
* @return Field
*/
/**
* Return the field
*
* @return Field
* @throws \Exception
*/
function get_field() {
$id = $this->get_mapped_property('field');
return new Field( $id );

View File

@ -203,6 +203,13 @@ class Item extends Entity {
$arrayItemMetadata = $this->get_fields();
if( $arrayItemMetadata ){
foreach ( $arrayItemMetadata as $itemMetadata ) {
// avoid core fields to re-validate
$pos = strpos($itemMetadata->get_field()->get_field_type(), 'Core');
if( $pos !== false ){
continue;
}
if( !$itemMetadata->validate() ){
$errors = $itemMetadata->get_errors();
$this->add_error( $itemMetadata->get_field()->get_name(), $errors );
@ -214,4 +221,15 @@ class Item extends Entity {
}
return false;
}
/**
* {@inheritDoc}
* @see \Tainacan\Entities\Entity::validate()
*/
public function validate_core_fields(){
if ( !in_array($this->get_status(), apply_filters('tainacan-status-require-validation', ['publish','future','private'])) )
return true;
return parent::validate();
}
}

View File

@ -84,15 +84,6 @@ class Taxonomy extends Entity {
return $this->get_mapped_property('name');
}
/**
* Return the parent id
*
* @return integer
*/
function get_parent() {
return $this->get_mapped_property('parent');
}
/**
* Return the description
*
@ -142,14 +133,6 @@ class Taxonomy extends Entity {
$this->set_mapped_property('name', $value);
}
/**
* Define the parent ID
*
* @param [integer] $value
*/
function set_parent($value) {
$this->set_mapped_property('parent', $value);
}
/**
* Define the slug

View File

@ -215,9 +215,12 @@ class Collections extends Repository {
* @see \Tainacan\Repositories\Repository::insert()
*/
public function insert($collection){
global $Tainacan_Fields;
$this->pre_update_moderators($collection);
$new_collection = parent::insert($collection);
$Tainacan_Fields->register_core_fields( $new_collection );
$collection->register_collection_item_post_type();
$this->update_moderators($new_collection);
return $new_collection;
@ -264,7 +267,6 @@ class Collections extends Repository {
} elseif(is_array($args)) {
$args = array_merge([
'posts_per_page' => -1,
'post_status' => 'publish',
], $args);
$args = $this->parse_fetch_args($args);

View File

@ -2,6 +2,7 @@
namespace Tainacan\Repositories;
use Tainacan\Entities;
use Tainacan\Field_Types;
defined( 'ABSPATH' ) or die( 'No script kiddies please!' );
@ -15,14 +16,17 @@ class Fields extends Repository {
public $field_types = [];
public $core_fields = [
'Tainacan\Field_Types\Core_Title',
'Tainacan\Field_Types\Core_Description'
];
/**
* Register specific hooks for field repository
*/
function __construct() {
parent::__construct();
add_action('tainacan_activated', array(&$this, 'register_core_fields'));
add_action('wp_trash_post', array( &$this, 'disable_delete_core_fields' ) );
add_action('before_delete_post', array( &$this, 'disable_delete_core_fields' ) );
add_filter('pre_trash_post', array( &$this, 'disable_delete_core_fields' ), 10, 2 );
add_filter('pre_delete_post', array( &$this, 'force_delete_core_fields' ), 10, 3 );
}
public function get_map() {
@ -35,6 +39,13 @@ class Fields extends Repository {
'on_error' => __('The name should be a text value and not empty', 'tainacan'),
'validation' => v::stringType()->notEmpty(),
],
'slug' => [
'map' => 'post_name',
'title' => __('Slug', 'tainacan'),
'type' => 'string',
'description'=> __('A unique and santized string representation of the field', 'tainacan'),
//'validation' => v::stringType(),
],
'order' => [
'map' => 'menu_order',
'title' => __('Order', 'tainacan'),
@ -286,15 +297,13 @@ class Fields extends Repository {
* fetch field by collection, searches all field available
*
* @param Entities\Collection $collection
* @param array $args
* @param array $args WP_Query args plus disabled_fields
* @param string $output The desired output format (@see \Tainacan\Repositories\Repository::fetch_output() for possible values)
*
* @return Array Entities\Field
* @throws \Exception
*/
public function fetch_by_collection(Entities\Collection $collection, $args = [], $output = null){
$this->register_core_fields();
$collection_id = $collection->get_id();
//get parent collections
@ -318,17 +327,24 @@ class Fields extends Repository {
$args['meta_query'] = array( $meta_query );
}
return $this->order_result( $this->fetch( $args, $output ), $collection);
return $this->order_result(
$this->fetch( $args, $output ),
$collection,
isset( $args['disabled_fields'] ) ? $args['disabled_fields'] : false
);
}
/**
* Ordinate the result from fetch response
* Ordinate the result from fetch response if $collection has an ordination,
* fields not ordinated appear on the end of the list
*
*
* @param $result Response from method fetch
* @param Entities\Collection $collection
* @return array or WP_Query ordinatte
* @param bool $disabled_fields Disabled fields wont appear on list collection fields
* @return array or WP_Query ordinate
*/
public function order_result( $result, Entities\Collection $collection ){
public function order_result( $result, Entities\Collection $collection, $disabled_fields = false ){
$order = $collection->get_fields_order();
if($order) {
$order = ( is_array($order) ) ? $order : unserialize($order);
@ -339,9 +355,15 @@ class Fields extends Repository {
foreach ( $result as $item ) {
$id = $item->WP_Post->ID;
$index = array_search ( $id , $order);
$index = array_search ( $id , array_column( $order , 'id') );
if( $index !== false ) {
// skipping fields disabled if the arg is set
if( $disabled_fields && !$order[$index]['enable'] ){
continue;
}
if( $index !== false ){
$result_ordinate[$index] = $item;
} else {
$not_ordinate[] = $item;
@ -361,7 +383,7 @@ class Fields extends Repository {
foreach ( $posts as $item ) {
$id = $item->ID;
$index = array_search ( $id , $order);
$index = array_search ( $id , array_column( $order , 'id') );
if( $index !== false ){
$result_ordinate[$index] = $item;
@ -422,71 +444,133 @@ class Fields extends Repository {
}
/**
* verify and, if is not registered, insert the default fields
* @param Entities\Collection $collection
* @return array
* @throws \ErrorException
*/
public function register_core_fields(){
$update_option = [];
$core_fields = get_option('tainacan_core_fields');
if( $core_fields ) {
return $core_fields;
}
public function register_core_fields( Entities\Collection $collection ){
$fields = $this->get_core_fields( $collection );
// TODO: create a better way to retrieve this data
$data_core_fields = [
'core_title' => [
'name' => 'Title',
'description' => 'title',
'collection_id' => 'default',
'field_type' => 'Tainacan\Field_Types\Core_Title',
'can_delete' => 'no',
'status' => 'publish'
],
'core_description' => [
'name' => 'Description',
'description' => 'description',
'collection_id' => 'default',
'collection_id' => $collection->get_id(),
'field_type' => 'Tainacan\Field_Types\Core_Description',
'can_delete' => 'no',
'status' => 'publish'
],
'core_title' => [
'name' => 'Title',
'description' => 'title',
'collection_id' => $collection->get_id(),
'field_type' => 'Tainacan\Field_Types\Core_Title',
'status' => 'publish'
]
];
foreach ( $data_core_fields as $index => $data_core_field ) {
if( !$core_fields || !isset($core_fields[$index]) ){
$field = new Entities\Field();
foreach ($data_core_field as $attribute => $value) {
$set_ = 'set_' . $attribute;
$field->$set_( $value );
}
if ($field->validate()) {
$field = $this->insert($field);
$update_option[$index] = $field->get_id();
} else {
throw new \ErrorException('The entity wasn\'t validated.' . print_r( $field->get_errors(), true));
}
} else if( isset($core_fields[$index]) ) {
$update_option[$index] = $core_fields[$index];
}
if( $collection->get_parent() !== 0 ){
return false;
}
update_option('tainacan_core_fields', $update_option);
foreach ( $data_core_fields as $index => $data_core_field ) {
if( empty( $fields ) ){
$this->insert_array_field( $data_core_field );
} else {
$exists = false;
foreach ( $fields as $field ){
if ( $field->get_field_type() === $data_core_field['field_type'] ) {
$exists = true;
}
}
return $update_option;
if( !$exists ){
$this->insert_array_field( $data_core_field );
}
}
}
}
/**
* block user from remove core fields
*
* @param $post_id The post ID which is deleting
* @param $before wordpress pass a null value
* @param $post the post which is moving to trash
* @return null/bool
* @throws \ErrorException
*/
public function disable_delete_core_fields( $post_id ){
$core_fields = get_option('tainacan_core_fields');
public function disable_delete_core_fields( $before, $post ){
$field = $this->fetch( $post->ID );
if ( $core_fields && in_array( $post_id, $core_fields ) ) {
throw new \ErrorException('Core fields cannot be deleted.');
if ( $field && in_array( $field->get_field_type(), $this->core_fields ) && is_numeric($field->get_collection_id()) ) {
return false;
}
}
/**
* block user from remove core fields ( if use wp_delete_post)
*
* @param $before wordpress pass a null value
* @param $post the post which is deleting
* @param $force_delete a boolean that force the deleting
* @return null /bool
* @internal param The $post_id post ID which is deleting
*/
public function force_delete_core_fields( $before, $post, $force_delete ){
$field = $this->fetch( $post->ID );
if ( $field && in_array( $field->get_field_type(), $this->core_fields ) && is_numeric($field->get_collection_id()) ) {
return false;
}
}
/**
* returns all core items from a specific collection
*
* @param Entities\Collection $collection
* @return Array|\WP_Query
*/
public function get_core_fields( Entities\Collection $collection ){
$args = [];
$meta_query = array(
array(
'key' => 'collection_id',
'value' => $collection->get_id(),
'compare' => 'IN',
),
array(
'key' => 'field_type',
'value' => $this->core_fields,
'compare' => 'IN',
)
);
$args['meta_query'] = $meta_query;
return $this->fetch( $args, 'OBJECT' );
}
/**
* create a field entity and insert by an associative array ( attribute => value )
*
* @param Array $data the array of attributes to insert a field
* @return int the field id inserted
* @throws \ErrorException
*/
public function insert_array_field( $data ){
$field = new Entities\Field();
foreach ( $data as $attribute => $value ) {
$set_ = 'set_' . $attribute;
$field->$set_( $value );
}
if ( $field->validate( )) {
$field = $this->insert( $field );
return $field->get_id();
} else {
throw new \ErrorException('The entity wasn\'t validated.' . print_r( $field->get_errors(), true));
}
}
}

View File

@ -62,8 +62,9 @@ class Item_Metadata extends Repository {
if ($field_type->core) {
$item = $item_metadata->get_item();
$set_method = 'set_' . $field_type->related_mapped_prop;
$item->$set_method($item_metadata->get_value());
if ($item->validate()) {
$value = $item_metadata->get_value();
$item->$set_method( is_array( $value ) ? $value[0] : $value );
if ($item->validate_core_fields()) {
global $Tainacan_Items;
$Tainacan_Items->insert($item);
} else {
@ -138,9 +139,16 @@ class Item_Metadata extends Repository {
*
* @return mixed
*/
public function update( $object, $new_values = null ) {}
public function update( $object, $new_values = null ) {
return $this->insert($object);
}
/**
* Suggest a value to be inserted as a item Field value, return a pending log
* @param Entities\Item_Metadata_Entity $item_metadata
* @return Entities\Log
*/
public function suggest($item_metadata) {
return Entities\Log::create(false, '', $item_metadata, null, 'pending');
}
}
}

View File

@ -194,36 +194,53 @@ class Items extends Repository {
if (is_numeric($collections)){
$collections = $Tainacan_Collections->fetch($collections);
}
$collections_objects = [];
$cpt = [];
if ($collections instanceof Entities\Collection) {
$cpt = $collections->get_db_identifier();
$collections_objects[] = $collections;
} elseif (is_array($collections)) {
$cpt = [];
foreach ($collections as $collection) {
if (is_numeric($collection)){
$collection = $Tainacan_Collections->fetch($collection);
foreach ($collections as $col) {
if (is_numeric($col)){
$col = $Tainacan_Collections->fetch($col);
}
if ($collection instanceof Entities\Collection){
$cpt[] = $collection->get_db_identifier();
if ($col instanceof Entities\Collection){
$collections_objects[] = $col;
}
}
} else {
return [];
}
foreach ($collections_objects as $collection) {
/**
* If no specific status is defined in the query, WordPress will fetch
* public items and private items for users withe the correct permission.
*
* If a collection is private, it must have the same behavior, despite its
* items are public or not.
*/
if (!isset($args['post_status'])) {
$status_obj = get_post_status_object( $collection->get_status() );
if ( $status_obj->public || current_user_can( $collection->cap->read_private_posts ) ) {
$cpt[] = $collection->get_db_identifier();
}
} else {
$cpt[] = $collection->get_db_identifier();
}
}
if (empty($cpt)){
return [];
$cpt[] = 'please-return-nothing';
}
//TODO: get collection order and order by options
$args = $this->parse_fetch_args($args);
$args = array_merge([
'post_status' => 'publish',
], $args);
$args['post_type'] = $cpt;

View File

@ -23,13 +23,6 @@ class Taxonomies extends Repository {
'on_error' => __('The taxonomy should be a text value and not empty', 'tainacan'),
'validation' => v::stringType()->notEmpty(),
],
'parent' => [
'map' => 'parent',
'title' => __('Parent', 'tainacan'),
'type' => 'integer',
'description' => __('Parent taxonomy', 'tainacan'),
'validation' => ''
],
'description' => [
'map' => 'post_content',
'title' => __('Description', 'tainacan'),

View File

@ -11,6 +11,7 @@ const VENDOR_DIR = __DIR__ . '/../vendor/';
const TAPI_DIR = __DIR__ . '/../api/';
const ENDPOINTS_DIR = __DIR__ . '/../api/endpoints/';
const HELPERS_DIR = __DIR__ . '/../helpers/';
const IMPORTER_DIR = __DIR__ . '/../importer/';
const DIRS = [
CLASSES_DIR,
@ -21,10 +22,12 @@ const DIRS = [
TRAITS_DIR,
TAPI_DIR,
ENDPOINTS_DIR,
IMPORTER_DIR
];
require_once(VENDOR_DIR . 'autoload.php');
require_once(HELPERS_DIR . 'class-tainacan-helpers-html.php');
require_once(IMPORTER_DIR . 'class-tainacan-importer.php');
spl_autoload_register('tainacan_autoload');
@ -44,7 +47,9 @@ function tainacan_autoload($class_name){
elseif ($class_path[0] == 'Tainacan') {
$sliced = array_slice($class_path, 1, count($class_path) -2);
if($sliced) {
if( isset( $class_path[1] ) && $class_path[1] === 'Importer' ){
$dir = IMPORTER_DIR;
} else if($sliced) {
$lower = $sliced[0];
$sliced[0] = strtolower( $lower );

View File

@ -33,8 +33,6 @@ class DevInterface {
global $TAINACAN_BASE_URL;
$components = ( has_filter( 'tainacan_register_web_components' ) ) ? apply_filters('tainacan_register_web_components') : [];
wp_enqueue_script('wp-settings',$TAINACAN_BASE_URL . '/js/wp-settings.js');
$settings = [
'root' => esc_url_raw( rest_url() ).'tainacan/v2',
'nonce' => wp_create_nonce( 'wp_rest' ),
@ -475,6 +473,12 @@ class DevInterface {
foreach ($metalist as $meta) {
$item_meta = new \Tainacan\Entities\Item_Metadata_Entity($entity, $meta);
$pos = strpos($item_meta->get_field()->get_field_type(), 'Core');
if( $pos !== false ){
continue;
}
if (isset($_POST['tnc_metadata_' . $meta->get_id()])) {
$item_meta->set_value($_POST['tnc_metadata_' . $meta->get_id()]);
if ($item_meta->validate()) {

View File

@ -0,0 +1,60 @@
<?php
namespace Tainacan\Importer;
use Tainacan;
class CSV extends Importer {
public $delimiter = ',';
public function __construct() {
parent::__construct();
}
/**
* @return string $delimiter value that divides each column
*/
public function get_delimiter(){
return $this->delimiter;
}
public function set_delimiter( $delimiter ){
$this->delimiter = $delimiter;
}
/**
* @inheritdoc
*/
public function get_fields_source(){
$file = new \SplFileObject( $this->tmp_file, 'r' );
$file->seek(0 );
return $file->fgetcsv( $this->get_delimiter() );
}
/**
*
*/
public function process_item(){
// TODO: process single item
}
/**
* @return mixed
*/
public function get_options(){
// TODO: Implement get_options() method.
}
public function get_total_items(){
if( isset( $this->total_items ) ){
return $this->total_items;
} else {
$file = new \SplFileObject( $this->tmp_file, 'r' );
$file->seek(PHP_INT_MAX);
// -1 removing header
return $this->total_items = $file->key() - 1;
}
}
}

View File

@ -0,0 +1,217 @@
<?php
namespace Tainacan\Importer;
use Tainacan;
abstract class Importer {
private $id;
public $collection;
public $mapping;
public $tmp_file;
public $total_items;
public $limit_query;
public $logs = [];
public function __construct() {
if (!session_id()) {
@session_start();
}
$this->id = uniqid();
$_SESSION['tainacan_importer'][$this->id] = $this;
}
/**
* @return string
*/
public function get_id(){
return $this->id;
}
/**
* @return array
*/
public function get_mapping(){
return $this->mapping;
}
/**
* @param Tainacan\Entities\Collection $collection
*/
public function set_collection( Tainacan\Entities\Collection $collection ){
$this->collection = $collection;
}
/**
* save an associative array with tainacan field id and field from source
*
* @param array $mapping Mapping importer-fields
*/
public function set_mapping( $mapping ){
$this->mapping = $mapping;
}
/**
* @param $file File to be managed by importer
* @return bool
*/
public function set_file( $file ){
$new_file = $this->upload_file( $file );
if ( is_numeric( $new_file ) ) {
$this->tmp_file = get_attached_file( $new_file );
} else {
return false;
}
}
/**
* internal function to upload the file
*
* @param $path_file
* @return array $response
*/
private function upload_file( $path_file ){
$name = basename( $path_file );
$file_array['name'] = $name;
$file_array['tmp_name'] = $path_file;
$file_array['size'] = filesize( $path_file );
return media_handle_sideload( $file_array, 0 );
}
/**
* get the content form url and creates a file
*
* @param $url
* @return array
*/
public function fetch_from_remote( $url ){
$tmp = wp_remote_get( $url );
if( isset( $tmp['body'] ) ){
$file = fopen( $this->get_id().'.txt', 'w' );
fwrite( $file, $tmp['body'] );
fclose( $file );
return $this->set_file( $this->get_id().'.txt' );
}
}
/**
* @return mixed
*/
public function get_collection_fields(){
return $this->collection;
}
/**
* get the fields of file/url to allow mapping
* should returns an array
*
* @return array $fields_source the fields from the source
*/
abstract public function get_fields_source();
/**
* get values for a single item
*
* @return array with field_source's as the index and values for the
* item Ex: [ 'Field1' => 'value1', 'Field2' => [ 'value2','value3' ]
*/
abstract public function process_item();
/**
* @return mixed
*/
abstract public function get_options();
/**
* return the all items found
*
* @return int Total of items
*/
abstract public function get_total_items();
/**
* @param $start
* @param $end
*/
public function process( $start, $end ){
}
/**
* insert processed item from source to Tainacan
*
* @param int $index the source id unique for the item
* @param array $processed_item Associative array with field source's as index with
* its value or values
* @return Tainacan\Entities\Item Item inserted
*/
public function insert( $index, $processed_item ){
global $Tainacan_Items, $Tainacan_Item_Metadata, $Tainacan_Fields;
$item = new Tainacan\Entities\Item();
$itemMetadataArray = [];
if( !isset( $this->mapping ) ){
$this->set_log('error','Mapping is not set');
return false;
}
if( is_array( $processed_item ) ){
foreach ( $processed_item as $field_source => $values ){
$tainacan_field_id = array_search( $field_source, $this->mapping );
$field = $Tainacan_Fields->fetch( $tainacan_field_id );
if( $field instanceof Tainacan\Entities\Field ){
$singleItemMetadata = new Tainacan\Entities\Item_Metadata_Entity();
$singleItemMetadata->set_field( $field );
$singleItemMetadata->set_value( $values );
$itemMetadataArray[] = $singleItemMetadata;
}
}
}
if( !empty( $itemMetadata ) && $this->collection instanceof Tainacan\Entities\Collection ){
$item->set_title( time() );
$item->set_collection( $this->collection );
$insertedItem = $Tainacan_Items->insert( $item );
foreach ( $itemMetadataArray as $itemMetadata ) {
$itemMetadata->set_item( $insertedItem );
$result = $Tainacan_Item_Metadata->insert( $itemMetadata );
if( $result ){
$values = ( is_array( $itemMetadata->get_value() ) ) ? implode( PHP_EOL, $itemMetadata->get_value() ) : $itemMetadata->get_value();
$this->set_log( 'success', 'Item ' . $index .
' has inserted the values: ' . $values . ' on field: ' . $itemMetadata->get_field()->get_name() );
} else {
$this->set_log( 'error', 'Item ' . $index . ' has an error' );
}
}
$item->set_status('publish' );
$Tainacan_Items->update( $item );
return $item;
} else {
$this->set_log( 'error', 'Collection not set');
return false;
}
}
/**
* @param $type
* @param $message
*/
public function set_log ( $type, $message ){
$this->logs[] = [ 'type' => $type, 'message' => $message ];
}
/**
*
*/
public function run(){
}
}

View File

@ -1,12 +1,12 @@
import axios from '../../../axios/axios';
export const fetchItems = ({ commit, state }, collectionId) => {
export const fetchItems = ({ commit, state }, { collectionId, page, itemsPerPage }) => {
return new Promise ((resolve, reject) => {
axios.get('/collection/'+collectionId+'/items')
axios.get('/collection/'+collectionId+'/items?paged='+page+'&perpage='+itemsPerPage)
.then(res => {
let items = res.data;
commit('setItems', items);
resolve(items);
resolve({'items': items, 'total': res.headers['x-wp-total'] });
})
.catch(error => reject(error));
});
@ -18,27 +18,47 @@ export const deleteItem = ({ commit }, item_id ) => {
.then( res => {
commit('deleteItem', { id: item_id });
resolve( res );
}).catch( err => {
}).catch((error) => {
reject( error );
});
});
};
export const fetchCollections = ({ commit }) => {
axios.get('/collections')
export const fetchCollections = ({commit} , { page, collectionsPerPage }) => {
return new Promise((resolve, reject) => {
axios.get('/collections?paged='+page+'&perpage='+collectionsPerPage)
.then(res => {
let collections = res.data;
commit('setCollections', collections);
resolve({'collections': collections, 'total': res.headers['x-wp-total'] });
})
.catch(error => {
console.log(error);
reject(error);
});
});
}
export const fetchFields = ({ commit }, id) => {
return new Promise((resolve, reject) => {
axios.get('/collection/'+id+'/fields')
.then((res) => {
let fields= res.data;
commit('setFields', fields);
resolve (fields);
})
.catch(error => console.log(error));
.catch((error) => {
console.log(error);
reject(error);
});
});
}
export const fetchCollection = ({ commit }, id) => {
return new Promise((resolve, reject) =>{
axios.get('/collections/' + id)
.then(res => {
console.log(res);
let collection = res.data;
commit('setCollection', collection);
resolve( res.data );
@ -49,6 +69,20 @@ export const fetchCollection = ({ commit }, id) => {
});
}
export const deleteCollection = ({ commit }, id) => {
return new Promise((resolve, reject) =>{
axios.delete('/collections/' + id)
.then(res => {
let collection = res.data;
commit('deleteCollection', collection);
resolve( res.data );
})
.catch(error => {
reject(error);
})
});
}
export const updateCollection = ({ commit }, { collection_id, name, description, status }) => {
return new Promise((resolve, reject) => {
axios.patch('/collections/' + collection_id, {

View File

@ -6,6 +6,10 @@ export const getCollections = state => {
return state.collections;
}
export const getFields = state => {
return state.fields;
}
export const getCollection = state => {
return state.collection;
}

View File

@ -5,6 +5,7 @@ import * as mutations from './mutations';
const state = {
items: [],
collections: [],
fields: [],
collection: null
};

View File

@ -9,10 +9,21 @@ export const deleteItem = ( state, item ) => {
}
}
export const deleteCollection = ( state, collection ) => {
let index = state.collections.findIndex(deletedCollection => deletedCollection.id === collection.id);
if (index >= 0) {
state.collections.splice(index, 1);
}
}
export const setCollections = (state, collections) => {
state.collections = collections;
}
export const setFields = (state, fields) => {
state.fields = fields;
}
export const setCollection = (state, collection) => {
state.collection = collection;
}

View File

@ -62,15 +62,13 @@ export const fetchItem = ({ commit }, item_id) => {
});
};
export const sendItem = ( { commit }, { collection_id, title, description, status }) => {
export const sendItem = ( { commit }, { collection_id, status }) => {
return new Promise(( resolve, reject ) => {
axios.post('/collection/'+ collection_id + '/items/', {
title: title,
description: description,
status: status
})
.then( res => {
commit('setItem', { collection_id: collection_id, title: title, description: description, status: status });
commit('setItem', { collection_id: collection_id, status: status });
resolve( res.data );
})
.catch(error => {
@ -80,14 +78,12 @@ export const sendItem = ( { commit }, { collection_id, title, description, statu
};
export const updateItem = ({ commit }, { item_id, title, description, status }) => {
export const updateItem = ({ commit }, { item_id, status }) => {
return new Promise((resolve, reject) => {
axios.patch('/items/' + item_id, {
title: title,
description: description,
status: status
}).then( res => {
commit('setItem', { id: item_id, title: title, description: description, status: status });
commit('setItem', { id: item_id, status: status });
resolve( res.data );
}).catch( error => {
reject( error.response );

View File

@ -1 +0,0 @@
// file to encode params for wordpress

View File

@ -25,13 +25,6 @@ function tnc_enable_dev_wp_interface() {
//return defined('TNC_ENABLE_DEV_WP_INTERFACE') && true === TNC_ENABLE_DEV_WP_INTERFACE ? true : false;
}
// fire actions right after plugin is activate
function tainacan_activate() {
do_action( 'tainacan_activated' );
}
register_activation_hook( __FILE__, 'tainacan_activate' );
// TODO move it somewhere else?
require_once('admin/class-tainacan-admin.php');
global $Tainacan_Admin;

View File

@ -8,6 +8,7 @@ class TAINACAN_UnitTestCase extends \WP_UnitTestCase {
protected $tainacan_entity_factory;
protected $tainacan_field_factory;
protected $tainacan_filter_factory;
protected $tainacan_item_metadata_factory;
protected $user_id;
public function setUp(){

View File

@ -87,11 +87,10 @@ class TAINACAN_REST_Collections_Controller extends TAINACAN_UnitApiTestCase {
//$data is a valid json?
//$this->assertTrue(json_last_error() === JSON_ERROR_NONE);
$other_collection = $data[0];
$one_collection = $data[1];
$this->assertEquals('testeApi', $one_collection['name']);
$this->assertEquals('Other', $other_collection['name']);
$collectionsNames = array_map(function($data) {return $data['name'];}, $data);
$this->assertContains('testeApi', $collectionsNames);
$this->assertContains('Other', $collectionsNames);
}
public function test_delete_or_trash_a_collection(){

View File

@ -32,8 +32,6 @@ class TAINACAN_REST_Terms_Controller extends TAINACAN_UnitApiTestCase {
$request_body = json_encode(
array(
'collection_id' => $collection->get_id(),
'field_id' => $field->get_id(),
'filter_type' => 'range',
'filter' => [
'name' => 'Filter name',
@ -42,7 +40,7 @@ class TAINACAN_REST_Terms_Controller extends TAINACAN_UnitApiTestCase {
)
);
$request = new \WP_REST_Request('POST', $this->namespace . '/filters');
$request = new \WP_REST_Request('POST', $this->namespace . '/collection/' . $collection->get_id() . '/field/' . $field->get_id(). '/filters');
$request->set_body($request_body);

View File

@ -76,8 +76,8 @@ class TAINACAN_REST_Items_Controller extends TAINACAN_UnitApiTestCase {
$first_item = $data[0];
$second_item = $data[1];
$this->assertEquals($item2->get_title(), $first_item['title']);
$this->assertEquals($item1->get_title(), $second_item['title']);
$this->assertEquals($item1->get_title(), $first_item['title']);
$this->assertEquals($item2->get_title(), $second_item['title']);
}
public function test_delete_or_trash_item_from_a_collection(){

View File

@ -98,9 +98,9 @@ class TAINACAN_REST_Metadata_Controller extends TAINACAN_UnitApiTestCase {
$data = $response->get_data();
$field = $data[0];
$fields_names = array_map(function($field) {return $field['name'];}, $data);
$this->assertEquals('Data', $field['name']);
$this->assertContains('Data', $fields_names);
################### Get field of item with value #######################
@ -113,11 +113,13 @@ class TAINACAN_REST_Metadata_Controller extends TAINACAN_UnitApiTestCase {
$data = $response->get_data();
$this->assertTrue(is_array($data) && array_key_exists(0, $data), sprintf('cannot read field, response: %s', print_r($data, true)));
$item_metadata = $data[0];
$field = $item_metadata['field'];
$this->assertEquals('Data', $field['name']);
$this->assertEquals('12/12/2017', $item_metadata['value']);
$fields_names = array_map(function($item_metadata) {return $item_metadata['field']['name'];}, $data);
$values = array_map(function($item_metadata) {return $item_metadata['value'];}, $data);
$this->assertContains('Data', $fields_names);
$this->assertContains('12/12/2017', $values);
}
public function test_update_metadata(){

View File

@ -3,16 +3,240 @@
namespace Tainacan\Tests;
/**
* @group queries
* @group api
* **/
class TAINACAN_REST_Queries extends TAINACAN_UnitApiTestCase {
public function test_collections_queries(){
$this->tainacan_entity_factory->create_entity(
public function test_queries(){
// Populate the database
$collectionA = $this->tainacan_entity_factory->create_entity(
'collection',
[],
[
'name' => 'A',
'description' => 'Collection A',
'status' => 'publish'
],
true
);
// Create Items
$itemA1 = $this->tainacan_entity_factory->create_entity(
'item',
[
'title' => 'Item A-1',
'description' => 'Item in collection A',
'status' => 'publish',
'collection' => $collectionA
],
true
);
$itemA2 = $this->tainacan_entity_factory->create_entity(
'item',
[
'title' => 'Item A-2',
'description' => 'Item in collection A',
'status' => 'private',
'collection' => $collectionA
],
true
);
$itemA3 = $this->tainacan_entity_factory->create_entity(
'item',
[
'title' => 'Item A-3',
'description' => 'Item in collection A',
'status' => 'publish',
'collection' => $collectionA
],
true
);
// Create Metadata and Field Type
$field_type = $this->tainacan_field_factory->create_field('text');
$fieldA1 = $this->tainacan_entity_factory->create_entity(
'field',
[
'name' => 'Field A-1',
'description' => 'Simple field in collection A',
'status' => 'publish',
'collection' => $collectionA,
'field_type' => $field_type
],
true
);
$fieldA2 = $this->tainacan_entity_factory->create_entity(
'field',
[
'name' => 'Field A-2',
'description' => 'Simple field in collection A',
'status' => 'publish',
'collection' => $collectionA,
'field_type' => $field_type
],
true
);
$fieldA3 = $this->tainacan_entity_factory->create_entity(
'field',
[
'name' => 'Field A-3',
'description' => 'Multiple field in a collection A',
'status' => 'publish',
'collection' => $collectionA,
'field_type' => $field_type,
'multiple' => 'yes'
],
true
);
// Create a Item Metadata
$itemA1_metadata1 = $this->tainacan_item_metadata_factory->create_item_metadata($itemA1, $fieldA1, 'E');
$itemA1_metadata2 = $this->tainacan_item_metadata_factory->create_item_metadata($itemA1, $fieldA2, 'X');
$itemA1_metadata3 = $this->tainacan_item_metadata_factory->create_item_metadata($itemA1, $fieldA3, ['Y', 'Z']);
$itemA2_metadata1 = $this->tainacan_item_metadata_factory->create_item_metadata($itemA2, $fieldA1, 'D');
$itemA2_metadata2 = $this->tainacan_item_metadata_factory->create_item_metadata($itemA2, $fieldA2, 'Q');
$itemA2_metadata3 = $this->tainacan_item_metadata_factory->create_item_metadata($itemA2, $fieldA3, ['R', 'S']);
$itemA3_metadata1 = $this->tainacan_item_metadata_factory->create_item_metadata($itemA3, $fieldA1, 'G');
$itemA3_metadata2 = $this->tainacan_item_metadata_factory->create_item_metadata($itemA3, $fieldA2, 'T');
$itemA3_metadata3 = $this->tainacan_item_metadata_factory->create_item_metadata($itemA3, $fieldA3, ['Q', 'V']);
//
$collectionB = $this->tainacan_entity_factory->create_entity(
'collection',
[
'name' => 'B',
'description' => 'Collection B',
'status' => 'publish'
],
true
);
$collectionC = $this->tainacan_entity_factory->create_entity(
'collection',
[
'name' => 'C',
'description' => 'Collection C',
'status' => 'private'
],
true
);
// Fetch a collection with a specific name
$name_query = ['name' => 'B'];
$name_request = new \WP_REST_Request('GET', $this->namespace . '/collections');
$name_request->set_query_params($name_query);
$name_response = $this->server->dispatch($name_request);
$data1 = $name_response->get_data();
$this->assertCount(1, $data1);
$this->assertEquals($collectionB->get_name(), $data1[0]['name']);
// Search collection with a specific keyword and not other keyword
$search_query = ['search' => 'Collection -A'];
$search_request = new \WP_REST_Request('GET', $this->namespace . '/collections');
$search_request->set_query_params($search_query);
$search_response = $this->server->dispatch($search_request);
$data2 = $search_response->get_data();
$this->assertCount(2, $data2);
$names = [$data2[0]['name'], $data2[1]['name']];
$this->assertNotContains('A', $names);
/* Meta Query:
*
* Fetch items from a collection desc ordered by fieldA1 and its only in range A to F.
*
* */
$meta_query = [
'metakey' => $fieldA1->get_id(),
'orderby' => 'meta_value',
'order' => 'DESC',
'metaquery' => array(
array(
'key' => $fieldA1->get_id(),
'value' => array( 'A', 'F' ),
'compare' => 'BETWEEN'
),
),
];
$meta_query_request = new \WP_REST_Request('GET', $this->namespace . '/collection/' . $collectionA->get_id() . '/items');
$meta_query_request->set_query_params($meta_query);
$meta_query_response = $this->server->dispatch($meta_query_request);
$data3 = $meta_query_response->get_data();
$this->assertCount(2, $data3);
$fieldA1_slug = $fieldA1->get_slug();
$values = [$data3[0]['metadata'][$fieldA1_slug]['value'], $data3[1]['metadata'][$fieldA1_slug]['value']];
$this->assertNotContains('G', $values);
// E have to come first, because DESC
$this->assertEquals('E', $data3[0]['metadata'][$fieldA1_slug]['value']);
$this->assertEquals('D', $data3[1]['metadata'][$fieldA1_slug]['value']);
/* Date Query:
*
* Fetch posts for today
*
* */
$today = getdate();
$date_query = [
'datequery' => [
[
'year' => $today['year'],
'month' => $today['mon'],
'day' => $today['mday']
]
]
];
$date_query_request_collections = new \WP_REST_Request('GET', $this->namespace . '/collections');
$date_query_request_collections->set_query_params($date_query);
$date_query_response_collections = $this->server->dispatch($date_query_request_collections);
$data4 = $date_query_response_collections->get_data();
$this->assertCount(3, $data4);
// If we change the date query for a date different of today, it should return nothing
$date_query['datequery'][0]['year'] = 1995;
$date_query_request_collections->set_query_params($date_query);
$date_query_response_collections = $this->server->dispatch($date_query_request_collections);
$data5 = $date_query_response_collections->get_data();
$this->assertCount(0, $data5);
}
}

View File

@ -158,6 +158,70 @@ class Collections extends TAINACAN_UnitTestCase {
$this->assertEquals('draft', $test->get_status());
}
function test_unique_slugs() {
$x = $this->tainacan_entity_factory->create_entity(
'collection',
array(
'name' => 'teste',
'description' => 'adasdasdsa',
'default_order' => 'DESC',
'slug' => 'duplicated_slug',
'status' => 'publish'
),
true
);
$y = $this->tainacan_entity_factory->create_entity(
'collection',
array(
'name' => 'teste',
'description' => 'adasdasdsa',
'default_order' => 'DESC',
'slug' => 'duplicated_slug',
'status' => 'publish'
),
true
);
$this->assertNotEquals($x->get_slug(), $y->get_slug());
// Create as draft and publish later
$x = $this->tainacan_entity_factory->create_entity(
'collection',
array(
'name' => 'teste',
'description' => 'adasdasdsa',
'default_order' => 'DESC',
'slug' => 'duplicated_slug',
),
true
);
$y = $this->tainacan_entity_factory->create_entity(
'collection',
array(
'name' => 'teste',
'description' => 'adasdasdsa',
'default_order' => 'DESC',
'slug' => 'duplicated_slug',
),
true
);
$this->assertEquals($x->get_slug(), $y->get_slug());
global $Tainacan_Collections;
$x->set_status('publish');
$x->validate();
$x = $Tainacan_Collections->insert($x);
$y->set_status('private'); // or publish shoud behave the same
$y->validate();
$y = $Tainacan_Collections->insert($y);
$this->assertNotEquals($x->get_slug(), $y->get_slug());
}
function test_item() {
$x = $this->tainacan_entity_factory->create_entity(
'collection',

View File

@ -28,16 +28,14 @@ class Fields extends TAINACAN_UnitTestCase {
true
);
$type = $this->tainacan_field_factory->create_field('text');
$field = $this->tainacan_entity_factory->create_entity(
'field',
array(
'name' => 'metadado',
'description' => 'descricao',
'collection' => $collection,
'field_type' => $type,
'accept_suggestion' => true
'accept_suggestion' => true,
'field_type' => 'Tainacan\Field_Types\Text',
),
true
);
@ -64,15 +62,13 @@ class Fields extends TAINACAN_UnitTestCase {
true
);
$type = $this->tainacan_field_factory->create_field('text');
$field = $this->tainacan_entity_factory->create_entity(
'field',
array(
'name' => 'metadado',
'description' => 'descricao',
'collection_id' => $collection->get_id(),
'field_type' => $type
'field_type' => 'Tainacan\Field_Types\Text',
),
true
);
@ -82,7 +78,7 @@ class Fields extends TAINACAN_UnitTestCase {
$this->assertEquals($test->get_name(), 'metadado');
$this->assertEquals($test->get_collection_id(), $collection->get_id());
$this->assertEquals('Tainacan\Field_Types\Text', $test->get_field_type());
$this->assertEquals($test->get_field_type_object(), $type);
$this->assertEquals($test->get_field_type(), 'Tainacan\Field_Types\Text');
}
/**
@ -91,14 +87,12 @@ class Fields extends TAINACAN_UnitTestCase {
function test_hierarchy_metadata(){
global $Tainacan_Fields;
$type = $this->tainacan_field_factory->create_field('text');
$this->tainacan_entity_factory->create_entity(
'field',
array(
'name' => 'field default',
'collection_id' => $Tainacan_Fields->get_default_metadata_attribute(),
'field_type' => $type,
'field_type' => 'Tainacan\Field_Types\Text',
'status' => 'publish'
),
true
@ -117,7 +111,7 @@ class Fields extends TAINACAN_UnitTestCase {
array(
'name' => 'field grandfather',
'collection_id' => $collection_grandfather->get_id(),
'field_type' => $type,
'field_type' => 'Tainacan\Field_Types\Text',
'status' => 'publish'
),
true
@ -137,7 +131,7 @@ class Fields extends TAINACAN_UnitTestCase {
array(
'name' => 'field father',
'collection_id' => $collection_father->get_id(),
'field_type' => $type,
'field_type' => 'Tainacan\Field_Types\Text',
'status' => 'publish'
),
true
@ -160,7 +154,7 @@ class Fields extends TAINACAN_UnitTestCase {
array(
'name' => 'field son',
'collection_id' => $collection_son->get_id(),
'field_type' => $type,
'field_type' => 'Tainacan\Field_Types\Text',
'status' => 'publish'
),
true
@ -172,14 +166,25 @@ class Fields extends TAINACAN_UnitTestCase {
$this->assertEquals( 6, sizeof( $retrieve_metadata ) );
}
/**
* test remove core fields
*/
function test_core_fields(){
global $Tainacan_Fields;
$core_fields_ids = $Tainacan_Fields->register_core_fields();
$this->expectException(\ErrorException::class);
if( $core_fields_ids ){
foreach( $core_fields_ids as $core_field_id ){
wp_trash_post( $core_field_id );
$collection_grandfather = $this->tainacan_entity_factory->create_entity(
'collection',
array(
'name' => 'collection field'
),
true
);
$core_fields = $Tainacan_Fields->get_core_fields( $collection_grandfather );
if( $core_fields ){
foreach( $core_fields as $core_field ){
$this->assertFalse(wp_trash_post( $core_field->get_id() ) );
}
}
}
@ -200,6 +205,137 @@ class Fields extends TAINACAN_UnitTestCase {
$class = new RandomType;
$this->assertEquals( 9, sizeof( $Tainacan_Fields->fetch_field_types() ) );
}
/**
*
*/
function test_ordenation_fields(){
global $Tainacan_Collections, $Tainacan_Fields;
$collection = $this->tainacan_entity_factory->create_entity(
'collection',
array(
'name' => 'teste'
),
true
);
$field1 = $this->tainacan_entity_factory->create_entity(
'field',
array(
'name' => 'field1',
'description' => 'descricao',
'collection' => $collection,
'field_type' => 'Tainacan\Field_Types\Text',
'status' => 'publish'
),
true
);
$field2 = $this->tainacan_entity_factory->create_entity(
'field',
array(
'name' => 'field2',
'description' => 'field2',
'collection' => $collection,
'field_type' => 'Tainacan\Field_Types\Text',
'status' => 'publish'
),
true
);
$field3 = $this->tainacan_entity_factory->create_entity(
'field',
array(
'name' => 'field3',
'description' => 'field3',
'collection' => $collection,
'field_type' => 'Tainacan\Field_Types\Text',
'status' => 'publish'
),
true
);
$collection->set_fields_order(
[
array( 'id' => $field3->get_id(), 'enable' => false ),
array( 'id' => $field2->get_id(), 'enable' => true ),
array( 'id' => $field1->get_id(), 'enable' => true )
]);
$update_collection = $Tainacan_Collections->update( $collection );
$fields_ordinate = $Tainacan_Fields->fetch_by_collection( $update_collection, [], 'OBJECT' );
$this->assertEquals( 'field3', $fields_ordinate[0]->get_name() );
$fields_ordinate_enabled = $Tainacan_Fields->fetch_by_collection( $update_collection, [ 'disabled_fields' => true ], 'OBJECT' );
$this->assertEquals( 'field2', $fields_ordinate_enabled[0]->get_name() );
}
function test_unique_slugs() {
$x = $this->tainacan_entity_factory->create_entity(
'field',
array(
'name' => 'teste',
'description' => 'adasdasdsa',
'slug' => 'duplicated_slug',
'status' => 'publish',
'field_type' => 'Tainacan\Field_Types\Text',
),
true
);
$y = $this->tainacan_entity_factory->create_entity(
'field',
array(
'name' => 'teste',
'description' => 'adasdasdsa',
'slug' => 'duplicated_slug',
'status' => 'publish',
'field_type' => 'Tainacan\Field_Types\Text',
),
true
);
$this->assertNotEquals($x->get_slug(), $y->get_slug());
// Create as draft and publish later
$x = $this->tainacan_entity_factory->create_entity(
'field',
array(
'name' => 'teste',
'description' => 'adasdasdsa',
'slug' => 'duplicated_slug',
'field_type' => 'Tainacan\Field_Types\Text',
),
true
);
$y = $this->tainacan_entity_factory->create_entity(
'field',
array(
'name' => 'teste',
'description' => 'adasdasdsa',
'slug' => 'duplicated_slug',
'field_type' => 'Tainacan\Field_Types\Text',
),
true
);
$this->assertEquals($x->get_slug(), $y->get_slug());
global $Tainacan_Fields;
$x->set_status('publish');
$x->validate();
$x = $Tainacan_Fields->insert($x);
$y->set_status('private'); // or publish shoud behave the same
$y->validate();
$y = $Tainacan_Fields->insert($y);
$this->assertNotEquals($x->get_slug(), $y->get_slug());
}
}
/**

View File

@ -54,14 +54,12 @@ class Filters extends TAINACAN_UnitTestCase {
true
);
$type = $this->tainacan_field_factory->create_field('text');
$field = $this->tainacan_entity_factory->create_entity(
'field',
array(
'name' => 'metadado',
'collection_id' => $collection->get_id(),
'field_type' => $type,
'field_type' => 'Tainacan\Field_Types\Text',
'description' => 'descricao',
),
true

121
tests/test-importer.php Normal file
View File

@ -0,0 +1,121 @@
<?php
namespace Tainacan\Tests;
use Tainacan\Importer;
/**
* Class Importer
*
* @package Test_Tainacan
*/
class ImporterTests extends TAINACAN_UnitTestCase {
/**
* @group importer
*/
public function test_instance_csv () {
$collection = $this->tainacan_entity_factory->create_entity(
'collection',
array(
'name' => 'Other',
'description' => 'adasdasdsa',
'default_order' => 'DESC',
'status' => 'publish'
),
true
);
$csv_importer = new Importer\CSV();
$id = $csv_importer->get_id();
$_SESSION['tainacan_importer'][$id]->set_collection( $collection );
// here the session is init already
$this->assertEquals( $collection->get_id(), $_SESSION['tainacan_importer'][$id]->collection->get_id() );
}
/**
* @group importer
*/
public function test_file_csv () {
global $Tainacan_Fields;
$csv_importer = new Importer\CSV();
$id = $csv_importer->get_id();
// open the file "demosaved.csv" for writing
$file = fopen('demosaved.csv', 'w');
// save the column headers
fputcsv($file, array('Column 1', 'Column 2', 'Column 3', 'Column 4', 'Column 5'));
// Sample data
$data = array(
array('Data 11', 'Data 12', 'Data 13', 'Data 14', 'Data 15'),
array('Data 21', 'Data 22', 'Data 23', 'Data 24', 'Data 25'),
array('Data 31', 'Data 32', 'Data 33', 'Data 34', 'Data 35'),
array('Data 41', 'Data 42', 'Data 43', 'Data 44', 'Data 45'),
array('Data 51', 'Data 52', 'Data 53', 'Data 54', 'Data 55')
);
// save each row of the data
foreach ($data as $row){
fputcsv($file, $row);
}
// Close the file
fclose($file);
$_SESSION['tainacan_importer'][$id]->set_file( 'demosaved.csv' );
// file isset on importer
$this->assertTrue( isset( $_SESSION['tainacan_importer'][$id]->tmp_file ) );
// count size of csv
$this->assertEquals( 5, $_SESSION['tainacan_importer'][$id]->get_total_items() );
// get fields to mapping
$headers = $_SESSION['tainacan_importer'][$id]->get_fields_source();
$this->assertEquals( $headers[4], 'Column 5' );
// inserting the collection
$collection = $this->tainacan_entity_factory->create_entity(
'collection',
array(
'name' => 'Other',
'description' => 'adasdasdsa',
'default_order' => 'DESC',
'status' => 'publish'
),
true
);
// set the importer
$_SESSION['tainacan_importer'][$id]->set_collection( $collection );
// get collection fields to map
$fields = $Tainacan_Fields->fetch_by_collection( $collection, [], 'OBJECT' ) ;
//create a random mapping
$map = [];
foreach ( $fields as $index => $field ){
$map[$field->get_id()] = $headers[$index];
}
// set the mapping
$_SESSION['tainacan_importer'][$id]->set_mapping( $map );
// check is equal
$this->assertEquals( $_SESSION['tainacan_importer'][$id]->get_mapping(), $map );
}
/**
* @group importer
*/
public function test_fetch_file(){
$csv_importer = new Importer\CSV();
$id = $csv_importer->get_id();
$_SESSION['tainacan_importer'][$id]->fetch_from_remote( 'http://localhost/wordpress-test/wp-json' );
$this->assertTrue( isset( $_SESSION['tainacan_importer'][$id]->tmp_file ) );
}
}

View File

@ -29,15 +29,13 @@ class Item_Metadata extends TAINACAN_UnitTestCase {
true
);
$type = $this->tainacan_field_factory->create_field('text');
$field = $this->tainacan_entity_factory->create_entity(
'field',
array(
'name' => 'metadado',
'description' => 'descricao',
'collection' => $collection,
'field_type' => $type
'field_type' => 'Tainacan\Field_Types\Text',
),
true
);
@ -81,8 +79,6 @@ class Item_Metadata extends TAINACAN_UnitTestCase {
true
);
$type = $this->tainacan_field_factory->create_field('text');
$field = $this->tainacan_entity_factory->create_entity(
'field',
array(
@ -90,7 +86,7 @@ class Item_Metadata extends TAINACAN_UnitTestCase {
'description' => 'descricao',
'collection' => $collection,
'required' => 'yes',
'field_type' => $type
'field_type' => 'Tainacan\Field_Types\Text',
),
true
);
@ -136,8 +132,6 @@ class Item_Metadata extends TAINACAN_UnitTestCase {
true
);
$type = $this->tainacan_field_factory->create_field('text');
$field = $this->tainacan_entity_factory->create_entity(
'field',
array(
@ -145,7 +139,7 @@ class Item_Metadata extends TAINACAN_UnitTestCase {
'description' => 'descricao',
'collection' => $collection,
'collection_key' => 'yes',
'field_type' => $type
'field_type' => 'Tainacan\Field_Types\Text',
),
true
);
@ -196,8 +190,6 @@ class Item_Metadata extends TAINACAN_UnitTestCase {
);
$type = $this->tainacan_field_factory->create_field('text');
$this->tainacan_entity_factory->create_entity(
'field',
array(
@ -205,7 +197,7 @@ class Item_Metadata extends TAINACAN_UnitTestCase {
'description' => 'descricao',
'collection' => $collection,
'status' => 'publish',
'field_type' => $type
'field_type' => 'Tainacan\Field_Types\Text',
),
true
);
@ -223,12 +215,18 @@ class Item_Metadata extends TAINACAN_UnitTestCase {
);
$item_metadatas = $Tainacan_Item_Metadata->fetch($i, 'OBJECT');
$names = [];
foreach ($item_metadatas as $item_metadata) {
$names[] = $item_metadata->get_field()->get_name();
}
$this->assertTrue(is_array($item_metadatas));
// notice for repository fields
$this->assertEquals(3, sizeof($item_metadatas));
$this->assertEquals('metadado', $item_metadatas[0]->get_field()->get_name());
//first 2 fields are repository fields
$this->assertTrue( in_array('metadado', $names) );
}
}

View File

@ -74,8 +74,6 @@ class Items extends TAINACAN_UnitTestCase {
}
function teste_query(){
$type = $this->tainacan_field_factory->create_field('text');
$collection = $this->tainacan_entity_factory->create_entity(
'collection',
array(
@ -100,7 +98,7 @@ class Items extends TAINACAN_UnitTestCase {
'name' => 'metadado',
'status' => 'publish',
'collection' => $collection,
'field_type' => $type
'field_type' => 'Tainacan\Field_Types\Text',
),
true
);
@ -111,7 +109,7 @@ class Items extends TAINACAN_UnitTestCase {
'name' => 'metadado2',
'status' => 'publish',
'collection' => $collection,
'field_type' => $type
'field_type' => 'Tainacan\Field_Types\Text',
),
true
);
@ -122,7 +120,7 @@ class Items extends TAINACAN_UnitTestCase {
'name' => 'metadado3',
'status' => 'publish',
'collection' => $collection,
'field_type' => $type
'field_type' => 'Tainacan\Field_Types\Text',
),
true
);
@ -229,11 +227,11 @@ class Items extends TAINACAN_UnitTestCase {
'meta_query' => [
[
'key' => $field2->get_id(),
'value' => 'value_2'
'value' => 'value_3'
]
]
], $collection2);
$this->assertEquals(1, $test_query->post_count);
$this->assertEquals(2, $test_query->post_count);
// should return 2 items
$test_query = $Tainacan_Items->fetch([

View File

@ -27,8 +27,6 @@ class Objects extends TAINACAN_UnitTestCase {
$entity = Repository::get_entity_by_post($test);
$this->assertEquals($x->get_db_identifier(), $entity->get_db_identifier());
$type = $this->tainacan_field_factory->create_field('text');
$collection = $this->tainacan_entity_factory->create_entity(
'collection',
array(
@ -53,7 +51,7 @@ class Objects extends TAINACAN_UnitTestCase {
'name' => 'metadado',
'status' => 'publish',
'collection' => $collection,
'field_type' => $type
'field_type' => 'Tainacan\Field_Types\Text',
),
true
);
@ -64,7 +62,7 @@ class Objects extends TAINACAN_UnitTestCase {
'name' => 'metadado2',
'status' => 'publish',
'collection' => $collection,
'field_type' => $type
'field_type' => 'Tainacan\Field_Types\Text',
),
true
);
@ -75,7 +73,7 @@ class Objects extends TAINACAN_UnitTestCase {
'name' => 'metadado3',
'status' => 'publish',
'collection' => $collection,
'field_type' => $type
'field_type' => 'Tainacan\Field_Types\Text',
),
true
);

View File

@ -0,0 +1,162 @@
<?php
namespace Tainacan\Tests;
/**
* Class TestCollections
*
* @package Test_Tainacan
*/
use Tainacan\Entities;
/**
* Test fetch methods to see if they return private objects (items, fiels, collections) correctly
*
* Private items should only be visible by logged users who have the rights
*
*/
/**
* @group privateObjects
*/
class PrivateObjects extends TAINACAN_UnitTestCase {
// TODO Test the same things via API
public function test_private_items () {
$collection = $this->tainacan_entity_factory->create_entity(
'collection',
array(
'name' => 'testePerm',
'status' => 'publish'
),
true
);
$privateItem = $this->tainacan_entity_factory->create_entity(
'item',
array(
'title' => 'testPrivateItem',
'collection' => $collection,
'status' => 'private'
),
true
);
$item = $this->tainacan_entity_factory->create_entity(
'item',
array(
'title' => 'testItem',
'collection' => $collection,
'status' => 'publish'
),
true
);
global $Tainacan_Items;
$items = $Tainacan_Items->fetch([], $collection);
$this->assertEquals(2, $items->found_posts, 'admins should see all 2 items');
$items = $Tainacan_Items->fetch(['post_status' => 'private', 'perm' => 'readable'], $collection);
$this->assertEquals(1, $items->found_posts, 'contributors should not see private items');
$new_contributor_user = $this->factory()->user->create(array( 'role' => 'contributor' ));
wp_set_current_user($new_contributor_user);
$items = $Tainacan_Items->fetch([], $collection);
$this->assertEquals(1, $items->found_posts, 'contributors should not see private items');
$items = $Tainacan_Items->fetch(['post_status' => 'private', 'perm' => 'readable'], $collection);
$this->assertEquals(0, $items->found_posts, 'contributors should not see private items');
$items = $Tainacan_Items->fetch(['post_status' => 'private'], $collection);
$this->assertEquals(1, $items->found_posts, 'contributors should not see private items');
}
public function test_items_in_private_collections () {
$collection = $this->tainacan_entity_factory->create_entity(
'collection',
array(
'name' => 'testePerm',
'status' => 'publish'
),
true
);
$privateCollection = $this->tainacan_entity_factory->create_entity(
'collection',
array(
'name' => 'testePerm',
'status' => 'private'
),
true
);
$item = $this->tainacan_entity_factory->create_entity(
'item',
array(
'title' => 'testItem',
'collection' => $collection,
'status' => 'publish'
),
true
);
$item = $this->tainacan_entity_factory->create_entity(
'item',
array(
'title' => 'testItem',
'collection' => $collection,
'status' => 'publish'
),
true
);
$item = $this->tainacan_entity_factory->create_entity(
'item',
array(
'title' => 'testItem',
'collection' => $privateCollection,
'status' => 'publish'
),
true
);
$item = $this->tainacan_entity_factory->create_entity(
'item',
array(
'title' => 'testItem',
'collection' => $privateCollection,
'status' => 'publish'
),
true
);
$new_contributor_user = $this->factory()->user->create(array( 'role' => 'contributor' ));
wp_set_current_user($new_contributor_user);
global $Tainacan_Items, $Tainacan_Collections;
$items = $Tainacan_Items->fetch([], $collection);
$this->assertEquals(2, $items->found_posts, 'items of a public collections should be visible');
$items = $Tainacan_Items->fetch([], $privateCollection);
$this->assertEquals(0, $items->found_posts, 'items of a private collection should not be visible');
$privateCollection->set_status('publish');
$privateCollection->validate();
$privateCollection = $Tainacan_Collections->insert($privateCollection);
$items = $Tainacan_Items->fetch([], $privateCollection);
$this->assertEquals(2, $items->found_posts, 'items should be visible after collections is made public');
$privateCollection->set_status('private');
$privateCollection->validate();
$privateCollection = $Tainacan_Collections->insert($privateCollection);
$items = $Tainacan_Items->fetch([], $privateCollection);
$this->assertEquals(0, $items->found_posts, 'items should not be visible after collection is made private');
}
}

View File

@ -11,6 +11,7 @@ module.exports = {
publicPath: './src/assets/',
filename: '[name]-components.js'
},
devtool: 'eval-source-map',
module: {
rules: [
{
@ -31,8 +32,16 @@ module.exports = {
},
{
test: /\.css$/,
use: ['style-loader', 'css-loader', 'postcss-loader']
use: ['style-loader', 'css-loader', 'postcss-loader', 'sass-loader'],
},
{
test: /\.scss$/,
loader: 'sass-resources-loader',
options: {
resources: path.resolve(__dirname, './src/admin/scss/_variables.scss')
}
}
]
},
resolve: {
@ -44,11 +53,10 @@ module.exports = {
historyApiFallback: true,
noInfo: true
},
devtool: '#source-map'
}
if (process.env.NODE_ENV === 'production') {
module.exports.devtool = '#eval-source-map'
module.exports.devtool = 'inline-source-map';
// http://vue-loader.vuejs.org/en/workflow/production.html
module.exports.plugins = (module.exports.plugins || []).concat([
new webpack.DefinePlugin({