text:
<!--
#
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements.  See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership.  The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License.  You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
#  KIND, either express or implied.  See the License for the
# specific language governing permissions and limitations
# under the License.
#
-->
# Release Notes

### 1.0.2 (Nov 18, 2015)
* [CB-10035](https://issues.apache.org/jira/browse/CB-10035) Updated `RELEASENOTES` to be newest to oldest
* [CB-4596](https://issues.apache.org/jira/browse/CB-4596) Fix `timestamp` to be `DOMTimeStamp` across the board
* Fixing contribute link.
* [CB-9426](https://issues.apache.org/jira/browse/CB-9426) Fix exception when using device orientation plugin on **browser** platform.

### 1.0.1 (Jun 17, 2015)
* [CB-9128](https://issues.apache.org/jira/browse/CB-9128) cordova-plugin-device-orientation documentation translation: cordova-plugin-device-orientation
* fix npm md issue
* Remove console log message from test

### 1.0.0 (Apr 15, 2015)
* [CB-8746](https://issues.apache.org/jira/browse/CB-8746) gave plugin major version bump
* [CB-8683](https://issues.apache.org/jira/browse/CB-8683) updated windows and tizen specific references of old id to new id
* [CB-8683](https://issues.apache.org/jira/browse/CB-8683) changed plugin-id to pacakge-name
* [CB-8653](https://issues.apache.org/jira/browse/CB-8653) properly updated translated docs to use new id
* [CB-8653](https://issues.apache.org/jira/browse/CB-8653) updated translated docs to use new id
* Use TRAVIS_BUILD_DIR, install paramedic by npm
* [CB-8653](https://issues.apache.org/jira/browse/CB-8653) Updated Readme
* [CB-8659](https://issues.apache.org/jira/browse/CB-8659): ios: 4.0.x Compatibility: Remove use of initWebView method
* [CB-8659](https://issues.apache.org/jira/browse/CB-8659): ios: 4.0.x Compatibility: Remove use of deprecated headers
* force async callbacks
* Updated plugin to be 'windows' instead of 'windows8'
* [CB-8614](https://issues.apache.org/jira/browse/CB-8614) Fixed getCurrentHeading and watchHeading on windows platform
* [CB-8563](https://issues.apache.org/jira/browse/CB-8563) Integrate TravisCI
* [CB-8438](https://issues.apache.org/jira/browse/CB-8438) cordova-plugin-device-orientation documentation translation: cordova-plugin-device-orientation
* [CB-8538](https://issues.apache.org/jira/browse/CB-8538) Added package.json file
* [CB-8458](https://issues.apache.org/jira/browse/CB-8458) Fixes false failure of test, when compass hardware is not available

### 0.3.11 (Feb 04, 2015)
* [CB-8351](https://issues.apache.org/jira/browse/CB-8351) ios: Use argumentForIndex rather than NSArray extension

### 0.3.10 (Dec 02, 2014)
* [CB-7977](https://issues.apache.org/jira/browse/CB-7977) Mention `deviceready` in plugin docs
* [CB-7700](https://issues.apache.org/jira/browse/CB-7700) cordova-plugin-device-orientation documentation translation: cordova-plugin-device-orientation
* [CB-7571](https://issues.apache.org/jira/browse/CB-7571) Bump version of nested plugin to match parent plugin

### 0.3.9 (Sep 17, 2014)
* [CB-7471](https://issues.apache.org/jira/browse/CB-7471) cordova-plugin-device-orientation documentation translation: cordova-plugin-device-orientation
* Fixed problem with watchCompass if pressed twice
* [CB-7086](https://issues.apache.org/jira/browse/CB-7086) Renamed dir, added nested plugin.xml
* added documentation for manual tests
* Fixed problem with watchCompass if pressed twice
* [CB-7086](https://issues.apache.org/jira/browse/CB-7086) Renamed dir, added nested plugin.xml
* added documentation for manual tests
* Updated docs for browser
* Add support for the browser
* [CB-7249](https://issues.apache.org/jira/browse/CB-7249) cordova-plugin-device-orientation documentation translation
* [CB-6960](https://issues.apache.org/jira/browse/CB-6960) Added manual tests
* [CB-6960](https://issues.apache.org/jira/browse/CB-6960) Port compass tests to plugin-test-framework

### 0.3.8 (Aug 06, 2014)
* **FFOS** update compass.js
* [CB-7187](https://issues.apache.org/jira/browse/CB-7187) ios: Add explicit dependency on CoreLocation.framework
* [CB-7187](https://issues.apache.org/jira/browse/CB-7187) Delete unused #import of CDVShared.h

### 0.3.7 (Jun 05, 2014)
* [CB-6799](https://issues.apache.org/jira/browse/CB-6799) Add license
* windows8. makes getHeading callback spec compliant
* [CB-6491](https://issues.apache.org/jira/browse/CB-6491) add CONTRIBUTING.md

### 0.3.6 (Apr 17, 2014)
* [CB-6381](https://issues.apache.org/jira/browse/CB-6381): [WP8] unexpected error object
* [CB-6422](https://issues.apache.org/jira/browse/CB-6422): [windows8] use cordova/exec/proxy
* [CB-6460](https://issues.apache.org/jira/browse/CB-6460): Update license headers
* [CB-6465](https://issues.apache.org/jira/browse/CB-6465): Add license headers to Tizen code
* Add NOTICE file

### 0.3.5 (Feb 05, 2014)
* [ubuntu] request sensors permission
* [ubuntu] add missing files
* Add support for Tizen.
* FFOS info added

### 0.3.4 (Jan 02, 2014)
* [CB-5658](https://issues.apache.org/jira/browse/CB-5658) Add doc/index.md for Compass plugin

### 0.3.3 (Dec 4, 2013)
* add ubuntu platform
* 1. Added amazon-fireos platform. 2. Change to use amazon-fireos as a platform if user agent string contains 'cordova-amazon-fireos'.

### 0.3.2 (Oct 28, 2013)
* orientation plugin
* [CB-5128](https://issues.apache.org/jira/browse/CB-5128): added repo + issue tag to plugin.xml for device orientation plugin
* [CB-4915](https://issues.apache.org/jira/browse/CB-4915) Incremented plugin version on dev branch.

### 0.3.1 (Sept 25, 2013)
* [CB-4889](https://issues.apache.org/jira/browse/CB-4889) renaming id
* [CB-4889](https://issues.apache.org/jira/browse/CB-4889) renaming core in CompassProxy
* [CB-4900](https://issues.apache.org/jira/browse/CB-4900) Windows 8 Compass plugin have extra define breaks plugin loading
* [windows8] commandProxy was moved
* Rename CHANGELOG.md -> RELEASENOTES.md
* [CB-4752](https://issues.apache.org/jira/browse/CB-4752) Incremented plugin version on dev branch.

### 0.3.0 (Sept 5, 2013)
* [CB-3687](https://issues.apache.org/jira/browse/CB-3687) Added blackberry10 support


text:
'use strict';

const qs = require('querystring');

function queryBuilder(params) {
  return 'https://www.bing.com/search?q=' +
    qs.escape(params.query) +
    '&first=' +
    params.pageNumber;
}

module.exports = queryBuilder;

redpajama_set_name: RedPajamaGithub


text:
extern crate byteorder;

#[cfg(any(feature="quickcheck", test))]
extern crate quickcheck;

pub mod any_pointer;
pub mod capability;
pub mod data;
pub mod data_list;
pub mod enum_list;
pub mod list_list;
pub mod message;
pub mod primitive_list;
pub mod private;
pub mod serialize;
pub mod serialize_packed;
pub mod struct_list;
pub mod text;
pub mod text_list;
pub mod traits;

mod util;

/// Eight bytes of memory with opaque interior.
///
/// This type is used to ensure that the data of a message is properly aligned.
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
#[repr(C)]
pub struct Word(u64);

impl Word {
    /// Does this, but faster:
    /// `::std::iter::repeat(Word(0)).take(length).collect()`
    pub fn allocate_zeroed_vec(length: usize) -> Vec<Word> {
        let mut result : Vec<Word> = Vec::with_capacity(length);
        unsafe {
            result.set_len(length);
            let p : *mut u8 = result.as_mut_ptr() as *mut u8;
            ::std::ptr::write_bytes(p, 0u8, length * ::std::mem::size_of::<Word>());
        }
        result
    }

    pub fn bytes_to_words<'a>(bytes: &'a [u8]) -> &'a [Word] {
        unsafe {
            ::std::slice::from_raw_parts(bytes.as_ptr() as *const Word, bytes.len() / 8)
        }
    }

    pub fn bytes_to_words_mut<'a>(bytes: &'a mut [u8]) -> &'a mut [Word] {
        unsafe {
            ::std::slice::from_raw_parts_mut(bytes.as_ptr() as *mut Word, bytes.len() / 8)
        }
    }

    pub fn words_to_bytes<'a>(words: &'a [Word]) -> &'a [u8] {
        unsafe {
            ::std::slice::from_raw_parts(words.as_ptr() as *const u8, words.len() * 8)
        }
    }

    pub fn words_to_bytes_mut<'a>(words: &'a mut [Word]) -> &'a mut [u8] {
        unsafe {
            ::std::slice::from_raw_parts_mut(words.as_mut_ptr() as *mut u8, words.len() * 8)
        }
    }

    #[cfg(test)]
    pub fn from(n: u64) -> Word {
        Word(n)
    }
}

#[cfg(any(feature="quickcheck", test))]
impl quickcheck::Arbitrary for Word {
    fn arbitrary<G: quickcheck::Gen>(g: &mut G) -> Word {
        Word(quickcheck::Arbitrary::arbitrary(g))
    }
}

/// Size of a message. Every generated struct has a method `.total_size()` that returns this.
#[derive(Clone, Copy, PartialEq)]
pub struct MessageSize {
    pub word_count : u64,

    /// Size of the capability table.
    pub cap_count : u32
}

impl MessageSize {
    pub fn plus_eq(&mut self, other : MessageSize) {
        self.word_count += other.word_count;
        self.cap_count += other.cap_count;
    }
}

/// An enum value or union discriminant that was not found among those defined in a schema.
#[derive(PartialEq, Clone, Copy, Debug)]
pub struct NotInSchema(pub u16);

impl ::std::fmt::Display for NotInSchema {
    fn fmt(&self, fmt : &mut ::std::fmt::Formatter) -> ::std::result::Result<(), ::std::fmt::Error> {
        write!(fmt, "Enum value or union discriminant {} was not present in the schema.", self.0)
    }
}

impl ::std::error::Error for NotInSchema {
    fn description(&self) -> &str {
        "Enum value or union disriminant was not present in schema."
    }
}

/// Because messages are lazily validated, the return type of any method that reads a pointer field
/// must be wrapped in a Result.
pub type Result<T> = ::std::result::Result<T, Error>;

/// Things that can go wrong when you read a message.
#[derive(Debug)]
pub enum Error {
    Decode { description : &'static str,
             detail : Option<String> },
    Io(std::io::Error),
}

impl Error {
    pub fn new_decode_error(description : &'static str, detail : Option<String>) -> Error {
        Error::Decode { description : description, detail : detail}
    }
}

impl ::std::convert::From<::std::io::Error> for Error {
    fn from(err : ::std::io::Error) -> Error {
        Error::Io(err)
    }
}

impl ::std::convert::From<NotInSchema> for Error {
    fn from(e : NotInSchema) -> Error {
        Error::new_decode_error("Enum value or union discriminant was not present in schema.",
                                Some(format!("value : {}", e.0)))
    }
}

impl ::std::fmt::Display for Error {
    fn fmt(&self, fmt : &mut ::std::fmt::Formatter) -> ::std::result::Result<(), ::std::fmt::Error> {
        match *self {
            Error::Decode { ref description, detail : Some(ref detail) } => {
                write!(fmt, "{} {}", description, detail)
            },
            Error::Decode { ref description, .. } => write!(fmt, "{}", description),
            Error::Io(ref io) => io.fmt(fmt),
        }
    }
}

impl ::std::error::Error for Error {
    fn description(&self) -> &str {
        match *self {
            Error::Decode { ref description, .. } => description,
            Error::Io(ref io) => ::std::error::Error::description(io),
        }
    }
    fn cause(&self) -> Option<&::std::error::Error> {
        match *self {
            Error::Decode { .. } => None,
            Error::Io(ref io) => io.cause(),
        }
    }
}

/// Helper struct that allows `MessageBuilder::get_segments_for_output()` to avoid heap allocations
/// in the single-segment case.
pub enum OutputSegments<'a> {
    #[doc(hidden)]
    SingleSegment([&'a [Word]; 1]),

    #[doc(hidden)]
    MultiSegment(Vec<&'a [Word]>),
}

impl <'a> ::std::ops::Deref for OutputSegments<'a> {
    type Target = [&'a [Word]];
    fn deref<'b>(&'b self) -> &'b [&'a [Word]] {
        match self {
            &OutputSegments::SingleSegment(ref s) => {
                s
            }
            &OutputSegments::MultiSegment(ref v) => {
                &*v
            }
        }
    }
}


text:
<?php

// change the following paths if necessary
$yiic=dirname(__FILE__).'/../../yii-1.1.10.r3566/framework/yiic.php';
$config=dirname(__FILE__).'/config/console.php';

require_once($yiic);


text:
@interface IJSVGCommandArc : IJSVGCommand <IJSVGCommandProtocol>

@end


text:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">

<title>JestData</title>
<meta name="date" content="2016-03-15">
<link rel="stylesheet" type="text/css" href="../stylesheet.css" title="Style">

JavaScript is disabled on your browser.

Overview

Package

Class

Deprecated

Index

Help

Prev Class

Next Class

Frames

No Frames

All Classes

Summary:

Nested |

Field |

Constr |

Method

Detail:

Field |

Constr |

Method

mvc

Class JestData

java.lang.Object

mvc.Observable

mvc.JestData

Direct Known Subclasses:

Bid, Thing, User

public abstract class JestData
extends Observable

Created by A on 2016-03-05.

Constructor Summary

Constructors

Constructor and Description

JestData()

Method Summary

Methods

Modifier and Type
Method and Description

boolean
equals(java.lang.Object other)

ShareoData
getDataSource()

java.lang.String
getJestID()

Returns the JestID associated with this object.

void
setDataSource(ShareoData model)

void
setJestID(java.lang.String ID)

Methods inherited from class mvc.Observable

addView, notifyViews, removeView

Methods inherited from class java.lang.Object

clone, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait

Constructor Detail

JestData

public JestData()

Method Detail

getJestID

public java.lang.String getJestID()
                           throws NullIDException

Returns the JestID associated with this object. Never returns null, but will instead throw
 an exception.

Returns:

The JestID.

Throws:

NullIDException - No JestID has been set, or it has been set to null.

setJestID

public void setJestID(java.lang.String ID)

getDataSource

public ShareoData getDataSource()

setDataSource

public void setDataSource(ShareoData model)

equals

public boolean equals(java.lang.Object other)

Overrides:

equals in class java.lang.Object

Overview

Package

Class

Deprecated

Index

Help

Prev Class

Next Class

Frames

No Frames

All Classes

Summary:

Nested |

Field |

Constr |

Method

Detail:

Field |

Constr |

Method


text:
package com.sun.xml.internal.ws.api.model.wsdl.editable;

import java.util.Map;

import javax.jws.WebParam.Mode;
import javax.jws.soap.SOAPBinding.Style;

import com.sun.istack.internal.NotNull;
import com.sun.istack.internal.Nullable;
import com.sun.xml.internal.ws.api.model.wsdl.WSDLBoundOperation;

public interface EditableWSDLBoundOperation extends WSDLBoundOperation {

        @Override
    @NotNull EditableWSDLOperation getOperation();

        @Override
    @NotNull EditableWSDLBoundPortType getBoundPortType();

        @Override
    @Nullable EditableWSDLPart getPart(@NotNull String partName, @NotNull Mode mode);

        @Override
    @NotNull Map<String,? extends EditableWSDLPart> getInParts();

        @Override
    @NotNull Map<String,? extends EditableWSDLPart> getOutParts();

        @Override
    @NotNull Iterable<? extends EditableWSDLBoundFault> getFaults();

        /**
         * Add Part
         * @param part Part
         * @param mode Mode
         */
    public void addPart(EditableWSDLPart part, Mode mode);

    /**
     * Add Fault
     * @param fault Fault
     */
    public void addFault(@NotNull EditableWSDLBoundFault fault);

    /**
     * Sets the soapbinding:binding/operation/wsaw:Anonymous.
     *
     * @param anonymous Anonymous value of the operation
     */
        public void setAnonymous(ANONYMOUS anonymous);

        /**
         * Sets input explicit body parts
         * @param b True, if input body part is explicit
         */
        public void setInputExplicitBodyParts(boolean b);

        /**
         * Sets output explicit body parts
         * @param b True, if output body part is explicit
         */
        public void setOutputExplicitBodyParts(boolean b);

        /**
         * Sets fault explicit body parts
         * @param b True, if fault body part is explicit
         */
        public void setFaultExplicitBodyParts(boolean b);

        /**
         * Set request namespace
         * @param ns Namespace
         */
        public void setRequestNamespace(String ns);

        /**
         * Set response namespace
         * @param ns Namespace
         */
        public void setResponseNamespace(String ns);

        /**
         * Set SOAP action
         * @param soapAction SOAP action
         */
        public void setSoapAction(String soapAction);

        /**
         * Set parameter style
         * @param style Style
         */
        public void setStyle(Style style);

        /**
         * Freezes WSDL model to prevent further modification
         * @param root WSDL Model
         */
        public void freeze(EditableWSDLModel root);
}


text:
"""Abstract base class to work with share."""
import abc

import six

@six.add_metaclass(abc.ABCMeta)
class HuaweiBase(object):
    """Interface to work with share."""

    def __init__(self, configuration):
        """Do initialization."""
        self.configuration = configuration

    @abc.abstractmethod
    def create_share(self, share, share_server):
        """Is called to create share."""

    @abc.abstractmethod
    def create_snapshot(self, snapshot, share_server):
        """Is called to create snapshot."""

    @abc.abstractmethod
    def delete_share(self, share, share_server):
        """Is called to remove share."""

    @abc.abstractmethod
    def delete_snapshot(self, snapshot, share_server):
        """Is called to remove snapshot."""

    @abc.abstractmethod
    def allow_access(self, share, access, share_server):
        """Allow access to the share."""

    @abc.abstractmethod
    def deny_access(self, share, access, share_server):
        """Deny access to the share."""

    @abc.abstractmethod
    def ensure_share(self, share, share_server=None):
        """Ensure that share is exported."""

    @abc.abstractmethod
    def extend_share(self, share, new_size, share_server):
        """Extends size of existing share."""

    @abc.abstractmethod
    def shrink_share(self, share, new_size, share_server):
        """Shrinks size of existing share."""

    @abc.abstractmethod
    def manage_existing(self, share, driver_options):
        """Manage existing share."""

    @abc.abstractmethod
    def get_network_allocations_number(self):
        """Get number of network interfaces to be created."""

    @abc.abstractmethod
    def get_pool(self, share):
        """Return pool name where the share resides on."""

    def update_share_stats(self, stats_dict):
        """Retrieve stats info from share group."""

    @abc.abstractmethod
    def setup_server(self, network_info, metadata=None):
        """Set up share server with given network parameters."""

    @abc.abstractmethod
    def teardown_server(self, server_details, security_services=None):
        """Teardown share server."""


text:
export function up(transaction) {
    transaction.sql `CREATE TABLE item (
		id UUID PRIMARY KEY,
		created_at TIMESTAMP WITHOUT TIME ZONE DEFAULT NOW(),
		name TEXT NOT NULL,
		count INTEGER DEFAULT 1 NOT NULL
	)`;
}

export function down(transaction) {
    transaction.sql `DROP TABLE item`;
}


text:
<?xml version="1.0" encoding="utf-8"?>

<menu xmlns:android="http://schemas.android.com/apk/res/android">
    <item
        android:id="@+id/menu_forum_star"
        android:checkable="true"
        android:title="@string/menu_forum_star"
        android:showAsAction="never"/>
    <item
        android:id="@+id/menu_private_messages"
        android:title="@string/menu_private_messages"
        android:actionLayout="@layout/pm_notification"
        android:icon="@drawable/ic_menu_mail"
        android:showAsAction="always"/>
    <item
        android:id="@+id/menu_forum_pin"
        android:checkable="true"
        android:title="@string/menu_forum_pin"
        android:showAsAction="never"/>
    <item
        android:id="@+id/menu_preferences"
        android:title="@string/menu_preferences"
        android:showAsAction="never"/>
    <item
        android:id="@+id/menu_logout"
        android:title="@string/menu_logout"
        android:showAsAction="never"/>
</menu>


text:
![PyPI](https://img.shields.io/pypi/v/django-inline-actions?style=flat-square)
![GitHub Workflow Status (master)](https://img.shields.io/github/workflow/status/escaped/django-inline-actions/Test%20&%20Lint/master?style=flat-square)
![Coveralls github branch](https://img.shields.io/coveralls/github/escaped/django-inline-actions/master?style=flat-square)
![PyPI - Python Version](https://img.shields.io/pypi/pyversions/django-inline-actions?style=flat-square)
![PyPI - License](https://img.shields.io/pypi/l/django-inline-actions?style=flat-square)

django-inline-actions adds actions to each row of the ModelAdmin or InlineModelAdmin.

## Requirements

* Python 3.6.1 or newer

## Screenshot

![Changelist example](https://raw.githubusercontent.com/escaped/django-inline-actions/master/example_changelist.png)
![Inline example](https://raw.githubusercontent.com/escaped/django-inline-actions/master/example_inline.png)

## Installation

1. Install django-inline-actions

   ```sh
   pip install django-inline-actions
   ```

2. Add `inline_actions` to your `INSTALLED_APPS`.

## Integration

Add the `InlineActionsModelAdminMixin` to your `ModelAdmin`.
If you want to have actions on your inlines, add the `InlineActionsMixin` to your `InlineModelAdmin`.
Each action is implemented as a method on the `ModelAdmin`/`InlineModelAdmin` and **must have** the following signature.

```python
def action_name(self, request, obj, parent_obj=None):
```

| Argument     | Description                                       |
|--------------|---------------------------------------------------|
| `request`    | current request                                   |
| `obj`        | instance on which the action was triggered        |
| `parent_obj` | instance of the parent model, only set on inlines |

and should return `None` to return to the current changeform or a `HttpResponse`.
Finally, add your method name to list of actions `inline_actions` defined on the corresponding `ModelAdmin`.
If you want to disable the *actions* column, you have to explicitly set `inline_actions = None`.
To add your actions dynamically, you can use the method `get_inline_actions(self, request, obj=None)` instead.

This module is bundled with two actions for viewing (`inline_actions.actions.ViewAction`) and deleting (`inline_actions.actions.DeleteAction`).
Just add these classes to your admin and you're done.

Additionally, you can add methods to generate a custom label and CSS classes per object.
If you have an inline action called `action_name` then you can define

```python
def get_action_name_label(self, obj):
    return 'some string'

def get_action_name_css(self, obj):
    return 'some string'
```

| Argument | Description                                |
|----------|--------------------------------------------|
| `obj`    | instance on which the action was triggered |

Each defined method has to return a string.

### Example 1

Imagine a simple news application with the following `admin.py`.

```python
from django.contrib import admin
from inline_actions.admin import InlineActionsMixin
from inline_actions.admin import InlineActionsModelAdminMixin

from .models import Article, Author

class ArticleInline(InlineActionsMixin,
                    admin.TabularInline):
    model = Article
    inline_actions = []

    def has_add_permission(self, request, obj=None):
        return False

@admin.register(Author)
class AuthorAdmin(InlineActionsModelAdminMixin,
                  admin.ModelAdmin):
    inlines = [ArticleInline]
    list_display = ('name',)

@admin.register(Article)
class AuthorAdmin(admin.ModelAdmin):
    list_display = ('title', 'status', 'author')
```

We now want to add two simple actions (`view`, `unpublish`) to each article within the `AuthorAdmin`.
The `view` action redirects to the changeform of the selected instance.

```python
from django.core.urlresolvers import reverse
from django.shortcuts import redirect

class ArticleInline(InlineActionsMixin,
                    admin.TabularInline):
    # ...
    inline_actions = ['view']
    # ...

    def view(self, request, obj, parent_obj=None):
        url = reverse(
            'admin:{}_{}_change'.format(
                obj._meta.app_label,
                obj._meta.model_name,
            ),
            args=(obj.pk,)
        )
        return redirect(url)
    view.short_description = _("View")
```

Since `unpublish` depends on `article.status` we must use `get_inline_actions` to add this action dynamically.

```python
from django.contrib import admin, messages
from django.utils.translation import gettext_lazy as _

class ArticleInline(InlineActionsMixin,
                    admin.TabularInline):
    # ...
    def get_inline_actions(self, request, obj=None):
        actions = super(ArticleInline, self).get_inline_actions(request, obj)
        if obj:
            if obj.status == Article.PUBLISHED:
                actions.append('unpublish')
        return actions

    def unpublish(self, request, obj, parent_obj=None):
        obj.status = Article.DRAFT
        obj.save()
        messages.info(request, _("Article unpublished"))
    unpublish.short_description = _("Unpublish")
```

Adding `inline_actions` to the changelist works similar. See the sample project for further details (`test_proj/blog/admin.py`).

### Example 2

Instead of creating separate actions for publishing and unpublishing, we might prefer an action, which toggles between those two states.
`toggle_publish` implements the behaviour described above.

```python
def toggle_publish(self, request, obj, parent_obj=None):
    if obj.status == Article.DRAFT:
        obj.status = Article.PUBLISHED
    else:
        obj.status = Article.DRAFT

    obj.save()

    if obj.status == Article.DRAFT:
        messages.info(request, _("Article unpublished."))
    else:
        messages.info(request, _("Article published."))
```

This might leave the user with an ambiguous button label as it will be called `Toggle publish` regardless of the internal state.
We can specify a dynamic label by adding a special method `get_ACTIONNAME_label`.

```python
def get_toggle_publish_label(self, obj):
    if obj.status == Article.DRAFT:
        return 'Publish'
    return 'Unpublish'
```

So assuming an object in a row has `DRAFT` status, then the button label will be `Toggle publish` and `Toggle unpublish` otherwise.

We can go even fancier when we create a method that will add css classes for each object depending on a status like:

```python
def get_toggle_publish_css(self, obj):
    if obj.status == Article.DRAFT:
        return 'btn-red'
    return 'btn-green'
```

You can make it more eye-candy by using `btn-green` that makes your button green and `btn-red` that makes your button red.
Or you can use those classes to add some javascript logic (i.e. confirmation box).

### Tip on confirmation alerts

When performing a certain critical action or ones which may not be easily reversible it's good to have a confirmation prompt before submitting the action form. To achieve this, one way would be to override `templates/admin/change_list.html` with the following.

```html
{% extends "admin/change_list.html" %}

{% block extrahead %}
    {{ block.super }}
    <script>
        (function() {
            document.addEventListener("DOMContentLoaded", function(event) {
                let inline_actions = document.querySelectorAll(".inline_actions input");
                for (var i=0; i < inline_actions.length; i++) {
                    inline_actions[i].addEventListener("click", function(e) {
                        if(!confirm("Do you really want to " + e.target.value + "?")) {
                            e.preventDefault();
                        }
                    });
                }
            });
        })();
    </script>
{% endblock %}
```

If a staff user has clicked any inline action accidentally, they can safely click no in the confirmation prompt & the inline action form would not be submitted.

## Intermediate forms

The current implementation for using intermediate forms involves some manual handling.
This will be simplified in the next major release!

In order to have an intermediate form, you must add some information about the triggered action.
`django-inline-actions` provides a handy templatetag `render_inline_action_fields`,
which adds these information as hidden fields to a form.

```html
{% extends "admin/base_site.html" %}
{% load inline_action_tags %}

{% block content %}
  <form action="" method="post">
    {% csrf_token %}
    {% render_inline_action_fields %}

    {{ form.as_p }}

    <input type="submit" name="_back" value="Cancel"/>
    <input type="submit" name="_save" value="Update"/>
  </form>
{% endblock %}
```

As the action does not know that an intermediate form is used, we have to include some special handling.
In the case above we have to consider 3 cases:

1. The form has been submitted and we want to redirect to the previous view.
2. Back button has been clicked.
3. Initial access to the intermediate page/form.

The corresponding action could look like

```python
    def change_title(self, request, obj, parent_obj=None):

        # 1. has the form been submitted?
        if '_save' in request.POST:
            form = forms.ChangeTitleForm(request.POST, instance=obj)
            form.save()
            return None  # return back to list view
        # 2. has the back button been pressed?
        elif '_back' in request.POST:
            return None  # return back to list view
        # 3. simply display the form
        else:
            form = forms.ChangeTitleForm(instance=obj)

        return render(
            request,
            'change_title.html',
            context={'form': form}
        )
```

## Example Application

You can see `django-inline-actions` in action using the bundled test application `test_proj`.
Use [`poetry`](https://poetry.eustace.io/) to run it.

```bash
git clone https://github.com/escaped/django-inline-actions.git
cd django-inline-actions/
poetry install
poetry run pip install Django
cd test_proj
poetry run ./manage.py migrate
poetry run ./manage.py createsuperuser
poetry run ./manage.py runserver
```

Open [`http://localhost:8000/admin/`](http://localhost:8000/admin/) in your browser and create an author and some articles.

## How to test your actions?

There are two ways on how to write tests for your actions.
We will use [pytest](https://docs.pytest.org/en/latest/) for the following examples.

### Test the action itself

Before we can call our action on the admin class itself, we have to instantiate the admin environment and pass it to the `ModelAdmin` together with an instance of our model.
Therefore, we implement a fixture called `admin_site`, which is used on each test.

```python
import pytest
from django.contrib.admin import AdminSite

from yourapp.module.admin import MyAdmin

@pytest.fixture
def admin_site():
    return AdminSite()

@pytest.mark.django_db
def test_action_XXX(admin_site):
    """Test action XXX"""
    fake_request = {}  # you might need to use a RequestFactory here
    obj = ...  # create an instance

    admin = MyAdmin(obj, admin_site)

    admin.render_inline_actions(article)
    response = admin.action_XXX(fake_request, obj)
    # assert the state of the application
```

### Test the admin integration

Alternatively, you can test your actions on the real Django admin page.
You will have to log in, navigate to the corresponding admin and trigger a click on the action.
To simplify this process you can use [django-webtest](https://github.com/django-webtest/django-webtest).
Example can be found [here](https://github.com/escaped/django-inline-actions/blob/76b6f6b83c6d1830c2ad71512cd1e85362936dbd/test_proj/blog/tests/test_inline_admin.py#L146).

## Development

This project uses [poetry](https://poetry.eustace.io/) for packaging and
managing all dependencies and [pre-commit](https://pre-commit.com/) to run
[flake8](http://flake8.pycqa.org/), [isort](https://pycqa.github.io/isort/),
[mypy](http://mypy-lang.org/) and [black](https://github.com/python/black).

Additionally, [pdbpp](https://github.com/pdbpp/pdbpp) and [better-exceptions](https://github.com/qix-/better-exceptions) are installed to provide a better debugging experience.
To enable `better-exceptions` you have to run `export BETTER_EXCEPTIONS=1` in your current session/terminal.

Clone this repository and run

```bash
poetry install
poetry run pre-commit install
```

to create a virtual enviroment containing all dependencies.
Afterwards, You can run the test suite using

```bash
poetry run pytest
```

This repository follows the [Conventional Commits](https://www.conventionalcommits.org/)
style.

### Cookiecutter template

This project was created using [cruft](https://github.com/cruft/cruft) and the
[cookiecutter-pyproject](https://github.com/escaped/cookiecutter-pypackage) template.
In order to update this repository to the latest template version run

```sh
cruft update
```

in the root of this repository.


text:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">

<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>org.apache.flume.conf (Apache Flume 1.7.0 API)</title>
<meta name="date" content="2016-10-12">
<link rel="stylesheet" type="text/css" href="../../../../stylesheet.css" title="Style">

org.apache.flume.conf

Interfaces

Configurable

ConfigurableComponent

Classes

BasicConfigurationConstants

ComponentConfiguration

ComponentConfigurationFactory

Configurables

FlumeConfiguration

FlumeConfiguration.AgentConfiguration

FlumeConfiguration.ComponentNameAndConfigKey

FlumeConfigurationError

LogPrivacyUtil

Enums

ComponentConfiguration.ComponentType

FlumeConfigurationError.ErrorOrWarning

FlumeConfigurationErrorType

Exceptions

ConfigurationException


text:
import socketStream from "../socket/socket-stream.js";
import store from "../store/get-store.js";

import type { $scopeT } from "angular";

import * as fp from "@iml/fp";

import { toggleCollection } from "./tree-utils.js";

import { emitOnItem, transformItems } from "./tree-transforms.js";

import type { treeItemT } from "./tree-types.js";

import type { PropagateChange } from "../extend-scope-module.js";

function treeFsCollection($scope: $scopeT, propagateChange: PropagateChange) {
  "ngInject";
  Object.assign(this, {
    onOpen: toggleCollection,
    $onDestroy() {
      fsCollection$.destroy();
      t1.destroy();
    }
  });

  const fn = (x: treeItemT) => x.parentTreeId === this.parentId && x.type === "fs";

  function computePage(meta) {
    const currentPage = meta.offset / meta.limit + 1;
    return (currentPage - 1) * meta.limit;
  }

  const t1 = store.select("tree");

  t1.through(emitOnItem(fn)).through(propagateChange.bind(null, $scope, this, "x"));

  const structFn = fp.always({
    type: "fs",
    parentTreeId: this.parentId
  });

  const fnTo$ = item =>
    socketStream("/filesystem/", {
      jsonMask: "meta,objects(label,id,resource_uri)",
      qs: {
        offset: computePage(item.meta),
        limit: item.meta.limit
      }
    });

  const fsCollection$ = store.select("tree");

  fsCollection$.through(transformItems(fn, structFn, fnTo$)).each(store.dispatch);
}

export default {
  template: `

     File Systems ({{$ctrl.x.meta.total_count}})

    <tree-fs-item
     ng-repeat="fs in $ctrl.x.objects track by fs.id"
     parent="$ctrl.x"
     record="fs"
     ></tree-fs-item>
     <tree-pager meta="$ctrl.x.meta" tree-id="::$ctrl.x.treeId"></tree-pager>

  `,
  bindings: {
    parentId: "<"
  },
  controller: treeFsCollection
};


text:
import { IDocumentStore } from "../../../src/Documents/IDocumentStore";
import { disposeTestDocumentStore, testContext } from "../../Utils/TestUtil";
import { GetLogsConfigurationOperation } from "../../../src/ServerWide/Operations/Logs/GetLogsConfigurationOperation";
import { LogMode } from "../../../src/ServerWide/Operations/Logs/LogMode";
import { throwError } from "../../../src/Exceptions/index";
import { SetLogsConfigurationOperation } from "../../../src/ServerWide/Operations/Logs/SetLogsConfigurationOperation";
import { TimeUtil } from "../../../src/Utility/TimeUtil";
import { assertThat } from "../../Utils/AssertExtensions";

describe("RavenDB_11440", function () {

    let store: IDocumentStore;

    beforeEach(async function () {
        store = await testContext.getDocumentStore();
    });

    afterEach(async () =>
        await disposeTestDocumentStore(store));

    it("canGetLogsConfigurationAndChangeMode", async () => {
        const configuration = await store.maintenance.server.send(new GetLogsConfigurationOperation());

        try {
            let modeToSet: LogMode;

            switch (configuration.currentMode) {
                case "None":
                    modeToSet = "Information";
                    break;
                case "Operations":
                    modeToSet = "Information";
                    break;
                case "Information":
                    modeToSet = "None";
                    break;
                default:
                    throwError("InvalidOperationException", "Invalid mode: " + configuration.currentMode);
            }

            const time = 1000 * 24 * 3600 * 1000;

            const setLogsOperation = new SetLogsConfigurationOperation({
                compress: false,
                mode: modeToSet,
                retentionTime: TimeUtil.millisToTimeSpan(time)
            });

            await store.maintenance.server.send(setLogsOperation);

            const configuration2 = await store.maintenance.server.send(new GetLogsConfigurationOperation());

            assertThat(configuration2.currentMode)
                .isEqualTo(modeToSet);
            assertThat(configuration2.retentionTime)
                .isEqualTo(TimeUtil.millisToTimeSpan(time));
            assertThat(configuration2.mode)
                .isEqualTo(configuration.mode);
            assertThat(configuration2.useUtcTime)
                .isEqualTo(configuration.useUtcTime);
        } finally {
            await store.maintenance.server.send(new SetLogsConfigurationOperation({
                retentionTime: configuration.retentionTime,
                mode: configuration.currentMode,
                compress: false
            }))
        }
    });
});


text:
QuickSpecBegin(SDLOnKeyboardInputSpec)

describe(@"Getter/Setter Tests", ^ {
    it(@"Should set and get correctly", ^ {
        SDLOnKeyboardInput* testNotification = [[SDLOnKeyboardInput alloc] init];

        testNotification.event = [SDLKeyboardEvent ENTRY_SUBMITTED];
        testNotification.data = @"qwertyg";

        expect(testNotification.event).to(equal([SDLKeyboardEvent ENTRY_SUBMITTED]));
        expect(testNotification.data).to(equal(@"qwertyg"));
    });

    it(@"Should get correctly when initialized", ^ {
        NSMutableDictionary* dict = [@{NAMES_notification:
                                           @{NAMES_parameters:
                                                 @{NAMES_event:[SDLKeyboardEvent ENTRY_SUBMITTED],
                                                   NAMES_data:@"qwertyg"},
                                             NAMES_operation_name:NAMES_OnKeyboardInput}} mutableCopy];
        SDLOnKeyboardInput* testNotification = [[SDLOnKeyboardInput alloc] initWithDictionary:dict];

        expect(testNotification.event).to(equal([SDLKeyboardEvent ENTRY_SUBMITTED]));
        expect(testNotification.data).to(equal(@"qwertyg"));
    });

    it(@"Should return nil if not set", ^ {
        SDLOnKeyboardInput* testNotification = [[SDLOnKeyboardInput alloc] init];

        expect(testNotification.event).to(beNil());
        expect(testNotification.data).to(beNil());
    });
});

QuickSpecEnd


text:
/*----------------------------------------------------------------------
       John Robbins - Microsoft Systems Journal Bugslayer Column
----------------------------------------------------------------------*/

#include "pch.h"
#include "BugslayerUtil.h"

// The project internal header file.
#include "Internal.h"

HMODULE * /*BUGSUTIL_DLLINTERFACE*/ __stdcall
                      AllocAndFillProcessModuleList ( HANDLE hHeap    ,
                                                      LPUINT puiCount  )

{
    ASSERT ( FALSE == IsBadWritePtr ( puiCount , sizeof ( LPUINT ) ) ) ;
    if ( TRUE == IsBadWritePtr ( puiCount , sizeof ( LPUINT ) ) )
    {
        SetLastError ( ERROR_INVALID_PARAMETER ) ;
        return ( NULL ) ;
    }

    ASSERT ( NULL != hHeap ) ;
    if ( NULL == hHeap )
    {
        SetLastError ( ERROR_INVALID_PARAMETER ) ;
        return ( NULL ) ;
    }

    // First, ask how many modules are really loaded.
    UINT uiQueryCount ;

    BOOL bRet = GetLoadedModules ( GetCurrentProcessId ( ) ,
                                   0                       ,
                                   NULL                    ,
                                   &uiQueryCount            ) ;
    ASSERT ( TRUE == bRet ) ;
    ASSERT ( 0 != uiQueryCount ) ;

    if ( ( FALSE == bRet ) || ( 0 == uiQueryCount ) )
    {
        return ( NULL ) ;
    }

    // The HMODULE array.
    HMODULE * pModArray ;

    // Allocate the buffer to hold the returned array.
    pModArray = (HMODULE*)HeapAlloc ( hHeap             ,
                                      HEAP_ZERO_MEMORY  ,
                                      uiQueryCount *
                                                   sizeof ( HMODULE ) );

    ASSERT ( NULL != pModArray ) ;
    if ( NULL == pModArray )
    {
        return ( NULL ) ;
    }

    // bRet holds BOOLEAN return values.
    bRet = GetLoadedModules ( GetCurrentProcessId ( ) ,
                              uiQueryCount            ,
                              pModArray               ,
                              puiCount                 ) ;
    // Save off the last error so that the assert can still fire and
    //  not change the value.
    DWORD dwLastError = GetLastError ( ) ;
    ASSERT ( TRUE == bRet ) ;

    if ( FALSE == bRet )
    {
        // Get rid of the last buffer.
        free ( pModArray ) ;
        pModArray = NULL ;
        SetLastError ( dwLastError ) ;
    }
    else
    {
        SetLastError ( ERROR_SUCCESS ) ;
    }
    // All OK, Jumpmaster!
    return ( pModArray ) ;
}


text:
#pragma once

#include "il2cpp-config.h"

#ifndef _MSC_VER
# include <alloca.h>
#else
# include <malloc.h>
#endif

#include <stdint.h>

// System.Type
struct Type_t;
// System.String
struct String_t;

#include "mscorlib_System_Runtime_Remoting_TypeEntry4038027264.h"
#include "mscorlib_System_Runtime_Remoting_WellKnownObjectMod251966751.h"

#ifdef __clang__
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Winvalid-offsetof"
#pragma clang diagnostic ignored "-Wunused-variable"
#endif

// System.Runtime.Remoting.WellKnownServiceTypeEntry
struct  WellKnownServiceTypeEntry_t4251089408  : public TypeEntry_t4038027264
{
public:
	// System.Type System.Runtime.Remoting.WellKnownServiceTypeEntry::obj_type
	Type_t * ___obj_type_2;
	// System.String System.Runtime.Remoting.WellKnownServiceTypeEntry::obj_uri
	String_t* ___obj_uri_3;
	// System.Runtime.Remoting.WellKnownObjectMode System.Runtime.Remoting.WellKnownServiceTypeEntry::obj_mode
	int32_t ___obj_mode_4;

public:
	inline static int32_t get_offset_of_obj_type_2() { return static_cast<int32_t>(offsetof(WellKnownServiceTypeEntry_t4251089408, ___obj_type_2)); }
	inline Type_t * get_obj_type_2() const { return ___obj_type_2; }
	inline Type_t ** get_address_of_obj_type_2() { return &___obj_type_2; }
	inline void set_obj_type_2(Type_t * value)
	{
		___obj_type_2 = value;
		Il2CppCodeGenWriteBarrier(&___obj_type_2, value);
	}

	inline static int32_t get_offset_of_obj_uri_3() { return static_cast<int32_t>(offsetof(WellKnownServiceTypeEntry_t4251089408, ___obj_uri_3)); }
	inline String_t* get_obj_uri_3() const { return ___obj_uri_3; }
	inline String_t** get_address_of_obj_uri_3() { return &___obj_uri_3; }
	inline void set_obj_uri_3(String_t* value)
	{
		___obj_uri_3 = value;
		Il2CppCodeGenWriteBarrier(&___obj_uri_3, value);
	}

	inline static int32_t get_offset_of_obj_mode_4() { return static_cast<int32_t>(offsetof(WellKnownServiceTypeEntry_t4251089408, ___obj_mode_4)); }
	inline int32_t get_obj_mode_4() const { return ___obj_mode_4; }
	inline int32_t* get_address_of_obj_mode_4() { return &___obj_mode_4; }
	inline void set_obj_mode_4(int32_t value)
	{
		___obj_mode_4 = value;
	}
};

#ifdef __clang__
#pragma clang diagnostic pop
#endif


text:
/**
 * <copyright>
 * </copyright>
 *
 * $Id$
 */
package gov.nasa.ensemble.core.model.plan.impl;

import gov.nasa.ensemble.common.CommonUtils;
import gov.nasa.ensemble.core.model.plan.EMember;
import gov.nasa.ensemble.core.model.plan.EPlanElement;
import gov.nasa.ensemble.core.model.plan.PlanPackage;

import org.eclipse.emf.common.notify.Notification;
import org.eclipse.emf.common.notify.NotificationChain;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.emf.ecore.InternalEObject;
import org.eclipse.emf.ecore.impl.ENotificationImpl;
import org.eclipse.emf.ecore.impl.MinimalEObjectImpl;
import org.eclipse.emf.ecore.util.EcoreUtil;

/**
 *
 * An implementation of the model object 'EMember'.
 *
 *

 * The following features are implemented:
 *

 *
{@link gov.nasa.ensemble.core.model.plan.impl.EMemberImpl#getPlanElement Plan Element}

 *
{@link gov.nasa.ensemble.core.model.plan.impl.EMemberImpl#getKey Key}

 *

 *

 *
 * @generated
 */
public abstract class EMemberImpl extends MinimalEObjectImpl.Container implements EMember {

	/**
	 * The default value of the '{@link #getKey() Key}' attribute.
	 *
	 *
	 * @see #getKey()
	 * @generated
	 * @ordered
	 */
	protected static final String KEY_EDEFAULT = null;
	/**
	 * The cached value of the '{@link #getKey() Key}' attribute.
	 *
	 *
	 * @see #getKey()
	 * @generated
	 * @ordered
	 */
	protected String key = KEY_EDEFAULT;

	/**
	 *
	 *
	 * @generated
	 */
	protected EMemberImpl() {
		super();
	}

	/**
	 *
	 *
	 * @generated
	 */
	@Override
	protected EClass eStaticClass() {
		return PlanPackage.Literals.EMEMBER;
	}

	/**
	 *
	 * Return this member's containing plan element if it exists; otherwise return null
	 *
	 * @generated
	 */
	public EPlanElement getPlanElement() {
		if (eContainerFeatureID() != PlanPackage.EMEMBER__PLAN_ELEMENT) return null;
		return (EPlanElement)eContainer();
	}

	/**
	 *
	 *
	 * @generated
	 */
	public EPlanElement basicGetPlanElement() {
		if (eContainerFeatureID() != PlanPackage.EMEMBER__PLAN_ELEMENT) return null;
		return (EPlanElement)eInternalContainer();
	}

	/**
	 *
	 *
	 * @generated
	 */
	public NotificationChain basicSetPlanElement(EPlanElement newPlanElement, NotificationChain msgs) {
		msgs = eBasicSetContainer((InternalEObject)newPlanElement, PlanPackage.EMEMBER__PLAN_ELEMENT, msgs);
		return msgs;
	}

	/**
	 *
	 * Give the member a new plan-element owner, removing backward associations and handling notifications.
	 * @paam newPlanElement the new plan-element owner
	 *
	 * @generated
	 */
	public void setPlanElement(EPlanElement newPlanElement) {
		if (newPlanElement != eInternalContainer() || (eContainerFeatureID() != PlanPackage.EMEMBER__PLAN_ELEMENT && newPlanElement != null)) {
			if (EcoreUtil.isAncestor(this, newPlanElement))
				throw new IllegalArgumentException("Recursive containment not allowed for " + toString());
			NotificationChain msgs = null;
			if (eInternalContainer() != null)
				msgs = eBasicRemoveFromContainer(msgs);
			if (newPlanElement != null)
				msgs = ((InternalEObject)newPlanElement).eInverseAdd(this, PlanPackage.EPLAN_ELEMENT__MEMBERS, EPlanElement.class, msgs);
			msgs = basicSetPlanElement(newPlanElement, msgs);
			if (msgs != null) msgs.dispatch();
		}
		else if (eNotificationRequired())
			eNotify(new ENotificationImpl(this, Notification.SET, PlanPackage.EMEMBER__PLAN_ELEMENT, newPlanElement, newPlanElement));
	}

	/**
	 *
	 *
	 * @generated NOT
	 */
	public abstract String getKey();

	/**
	 *
	 * This allows temporal members to decide dynamically which feature (start, duration, or end)
	 * is computed from the two input by the user.
	 *
	 * @generated NOT
	 */
	@Override
	public boolean isCalculated(EStructuralFeature feature) {
		return false;
	}

	/**
	 *
	 * Return the feature used to determine whether another feature is calculated
	 *
	 * @generated NOT
	 */
	@Override
	public EStructuralFeature getCalculatedVariableFeature() {
		return null;
	}

	/**
	 *
	 *
	 * @generated
	 */
	@Override
	public NotificationChain eInverseAdd(InternalEObject otherEnd, int featureID, NotificationChain msgs) {
		switch (featureID) {
			case PlanPackage.EMEMBER__PLAN_ELEMENT:
				if (eInternalContainer() != null)
					msgs = eBasicRemoveFromContainer(msgs);
				return basicSetPlanElement((EPlanElement)otherEnd, msgs);
		}
		return super.eInverseAdd(otherEnd, featureID, msgs);
	}

	/**
	 *
	 *
	 * @generated
	 */
	@Override
	public NotificationChain eInverseRemove(InternalEObject otherEnd, int featureID, NotificationChain msgs) {
		switch (featureID) {
			case PlanPackage.EMEMBER__PLAN_ELEMENT:
				return basicSetPlanElement(null, msgs);
		}
		return super.eInverseRemove(otherEnd, featureID, msgs);
	}

	/**
	 *
	 *
	 * @generated
	 */
	@Override
	public NotificationChain eBasicRemoveFromContainerFeature(NotificationChain msgs) {
		switch (eContainerFeatureID()) {
			case PlanPackage.EMEMBER__PLAN_ELEMENT:
				return eInternalContainer().eInverseRemove(this, PlanPackage.EPLAN_ELEMENT__MEMBERS, EPlanElement.class, msgs);
		}
		return super.eBasicRemoveFromContainerFeature(msgs);
	}

	/**
	 *
	 * Handle the plan-element and key features.
	 * @param featureID specifies the feature; of interest only if plan-element or key
	 * @return the value of the specified feature
	 *
	 * @generated
	 */
	@Override
	public Object eGet(int featureID, boolean resolve, boolean coreType) {
		switch (featureID) {
			case PlanPackage.EMEMBER__PLAN_ELEMENT:
				if (resolve) return getPlanElement();
				return basicGetPlanElement();
			case PlanPackage.EMEMBER__KEY:
				return getKey();
		}
		return super.eGet(featureID, resolve, coreType);
	}

	/**
	 *
	 * Handle the plan-element feature, setting it to the supplied value
	 * @param featureID specifies the feature; of interest only if plan-element
	 *
	 * @generated
	 */
	@Override
	public void eSet(int featureID, Object newValue) {
		switch (featureID) {
			case PlanPackage.EMEMBER__PLAN_ELEMENT:
				setPlanElement((EPlanElement)newValue);
				return;
		}
		super.eSet(featureID, newValue);
	}

	/**
	 *
	 * Handle the plan-element feature, setting it to the default value of null.
	 * @param featureID specifies the feature; of interest only of plan-element
	 *
	 * @generated
	 */
	@Override
	public void eUnset(int featureID) {
		switch (featureID) {
			case PlanPackage.EMEMBER__PLAN_ELEMENT:
				setPlanElement((EPlanElement)null);
				return;
		}
		super.eUnset(featureID);
	}

	/**
	 *
	 * Handles the plan-element and key features.
	 * @param featureID specifies the feature; of interest only if plan-element or key
	 * @return whether the feature handled has a non-default value
	 *
	 * @generated
	 */
	@Override
	public boolean eIsSet(int featureID) {
		switch (featureID) {
			case PlanPackage.EMEMBER__PLAN_ELEMENT:
				return basicGetPlanElement() != null;
			case PlanPackage.EMEMBER__KEY:
				return KEY_EDEFAULT == null ? key != null : !KEY_EDEFAULT.equals(key);
		}
		return super.eIsSet(featureID);
	}

	/**
	 * Suppress the notification if the old value and new value are the same.
	 * @param notification the notification subject to suppression
	 */
	@Override
	public void eNotify(Notification notification) {
		Object oldValue = notification.getOldValue();
		Object newValue = notification.getNewValue();
		if (!CommonUtils.equals(oldValue, newValue)) {
			super.eNotify(notification);
		}
	}

	/**
	 *
	 * Decorate by adding the key.
	 *
	 * @generated NOT
	 */
	@Override
	public String toString() {
		if (eIsProxy()) return super.toString();

		StringBuffer result = new StringBuffer(super.toString());
		result.append(" (key: ");
		result.append(getKey());
		result.append(')');
		return result.toString();
	}

} //EMemberImpl


text:
<?php

namespace Components\Resources\Models;

use Components\Resources\Helpers\Tags;
use Hubzero\Database\Relational;
use Hubzero\Config\Registry;
use Hubzero\Utility\Str;
use Component;
use Date;
use Lang;
use User;
use App;
use stdClass;

require_once __DIR__ . DS . 'association.php';
require_once __DIR__ . DS . 'type.php';
require_once __DIR__ . DS . 'author.php';
require_once __DIR__ . DS . 'license.php';
require_once __DIR__ . DS . 'screenshot.php';
require_once __DIR__ . DS . 'elements.php';
require_once dirname(__DIR__) . DS . 'helpers' . DS . 'tags.php';

/**
 * Resource entry model
 *
 * @uses \Hubzero\Database\Relational
 */
class Entry extends Relational implements \Hubzero\Search\Searchable
{
	/**
	 * State constants
	 **/
	const STATE_ARCHIVED = -1;
	const STATE_DRAFT    = 2;
	const STATE_PENDING  = 3;
	const STATE_TRASHED  = 4;
	const STATE_DRAFT_INTERNAL = 5;

	/**
	 * The table namespace
	 *
	 * @var  string
	 */
	protected $namespace = '';

	/**
	 * The table name, non-standard naming
	 *
	 * @var  string
	 */
	protected $table = '#__resources';

	/**
	 * Default order by for model
	 *
	 * @var  string
	 */
	public $orderBy = 'id';

	/**
	 * Fields and their validation criteria
	 *
	 * @var  array
	 */
	protected $rules = array(
		'title' => 'notempty'
	);

	/**
	 * Automatic fields to populate every time a row is created
	 *
	 * @var  array
	 */
	public $initiate = array(
		'created',
		'created_by'
	);

	/**
	 * Automatically fillable fields
	 *
	 * @var  array
	 **/
	public $always = array(
		'alias',
		'modified',
		'modified_by',
		'fulltxt',
		'introtext'
	);

	/**
	 * Path to filespace
	 *
	 * @var  string
	 */
	protected $filespace = null;

	/**
	 * Params Registry
	 *
	 * @var  object
	 */
	protected $paramsRegistry = null;

	/**
	 * Attribs Registry
	 *
	 * @var  object
	 */
	protected $attribsRegistry = null;

	/**
	 * Authorization checks flag
	 *
	 * @var  bool
	 */
	protected $_authorized = false;

	/**
	 * Tool
	 *
	 * @var  object
	 */
	public $thistool = null;

	/**
	 * Tool
	 *
	 * @var  object
	 */
	public $curtool = null;

	/**
	 * Tool revision
	 *
	 * @var  string
	 */
	public $revision = null;

	/**
	 * Generates automatic alias field value
	 *
	 * @param   array   $data  the data being saved
	 * @return  string
	 */
	public function automaticAlias($data)
	{
		if (!isset($data['alias']))
		{
			$data['alias'] = '';
		}
		$alias = str_replace(' ', '-', $data['alias']);
		return preg_replace("/[^a-zA-Z0-9\-_]/", '', strtolower($alias));
	}

	/**
	 * Generates automatic created field value
	 *
	 * @return  string
	 */
	public function automaticModified()
	{
		return Date::of('now')->toSql();
	}

	/**
	 * Generates automatic created by field value
	 *
	 * @return  int
	 */
	public function automaticModifiedBy()
	{
		return User::get('id');
	}

	/**
	 * Generates automatic fulltxt field value
	 *
	 * @param   array   $data  the data being saved
	 * @return  string
	 */
	public function automaticFulltxt($data)
	{
		if (!isset($data['fulltxt']))
		{
			$data['fulltxt'] = '';
		}
		return str_replace('
', '
', $data['fulltxt']);
	}

	/**
	 * Generates automatic introtext field value
	 *
	 * @param   array   $data  the data being saved
	 * @return  string
	 */
	public function automaticIntrotext($data)
	{
		if (!isset($data['introtext']))
		{
			$data['introtext'] = $data['fulltxt'];
		}
		$data['introtext'] = \Hubzero\Utility\Str::truncate(strip_tags($data['introtext']), 300);

		return str_replace('
', '
', $data['introtext']);
	}

	/**
	 * Get parent type
	 *
	 * @return  object
	 */
	public function transformType()
	{
		//return $this->belongsToOne(__NAMESPACE__ . '\\Type', 'type_id')->row();
		return Type::oneOrNew($this->get('type'));
	}

	/**
	 * Get logical type
	 *
	 * @return  object
	 */
	public function transformLogicaltype()
	{
		//return $this->belongsToOne(__NAMESPACE__ . '\\Type', 'logicaltype_id')->row();
		return Type::oneOrNew($this->get('logical_type'));
	}

	/**
	 * Get associated license
	 *
	 * @return  object
	 */
	public function license()
	{
		//return $this->oneToOne(__NAMESPACE__ . '\\License', 'license_id');
		return License::oneByName($this->get('license', $this->params->get('license')));
	}

	/**
	 * Get owning group
	 *
	 * @return  object
	 */
	public function transformGroupOwner()
	{
		//return $this->belongsToOne('Hubzero\User\Group', 'group_owner');
		$group = \Hubzero\User\Group::getInstance($this->get('group_owner'));

		if (!$group)
		{
			$group = new \Hubzero\User\Group();
		}

		return $group;
	}

	/**
	 * Get all the groups allowed to access a resource
	 *
	 * @return  array
	 */
	public function transformGroups()
	{
		$allowedgroups = array();

		if ($group_access = $this->get('group_access'))
		{
			$group_access = trim($group_access);
			$group_access = trim($group_access, ';');
			$group_access = explode(';', $group_access);

			$allowedgroups += $group_access;
		}

		if ($this->get('group_owner'))
		{
			$allowedgroups[] = $this->get('group_owner');
		}

		return $allowedgroups;
	}

	/**
	 * Generates a list of screenshots
	 *
	 * @return  object
	 */
	public function screenshots()
	{
		return $this->oneToMany(__NAMESPACE__ . '\\Screenshot', 'resourceid');
	}

	/**
	 * Generates a list of authors
	 *
	 * @return  object
	 */
	public function authors()
	{
		return $this->oneToMany(__NAMESPACE__ . '\\Author', 'subid')->whereEquals('subtable', 'resources');
	}

	/**
	 * Get a list of authors
	 *
	 * @return  string
	 */
	public function authorsList()
	{
		$names = array();

		foreach ($this->authors()->order('ordering', 'asc')->rows() as $contributor)
		{
			if (strtolower($contributor->get('role')) == 'submitter')
			{
				continue;
			}

			// Build the user's name and link to their profile
			$name = htmlentities($contributor->name);
			if ($contributor->get('authorid') > 0)
			{
				$name = 'get('authorid')) . '" data-rel="contributor" class="resource-contributor" title="View the profile of ' . $name . '">' . $name . '';
			}
			if ($contributor->get('role'))
			{
				$name .= ' (' . $contributor->get('role') . ')';
			}

			$names[] = $name;
		}

		return implode(', ', $names);
	}

	/**
	 * Get a list of contributors on this resource by role
	 *
	 * @param   mixed  $idx  Index value
	 * @return  array
	 */
	public function contributors($idx=null)
	{
		$contributors = array();

		if ($idx == 'tool')
		{
			// UUUGGGGHHHHHHHHHH
			// @TODO: Rewrite this
			if ($this->isTool())
			{
				$db = App::get('db');
				$sql = "SELECT n.id, t.name AS name, n.name AS xname, NULL AS xorg, n.givenName, n.givenName AS firstname, n.middleName, n.middleName AS middlename, n.surname, n.surname AS lastname, t.organization, t.*, a.role"
					 . " FROM `#__tool_authors` AS t LEFT JOIN `#__users` AS n ON n.id=t.uid JOIN `#__tool_version` AS v ON v.id=t.version_id"
					 . " LEFT JOIN `#__author_assoc` AS a ON a.authorid=t.uid AND a.subtable='resources' AND a.subid=" . $db->quote($this->get('id'))
					 . " WHERE t.toolname=" . $db->quote($this->get('alias')) . " AND v.state<>3"
					 . " AND t.revision=" . $db->quote($this->get('revision'))
					 . " ORDER BY t.ordering";
				$db->setQuery($sql);
				if ($cons = $db->loadObjectList())
				{
					foreach ($cons as $k => $c)
					{
						if (!$cons[$k]->name)
						{
							$cons[$k]->name = $cons[$k]->xname;
						}
						if (trim($cons[$k]->organization) == '')
						{
							$cons[$k]->organization = $cons[$k]->xorg;
						}
					}
					$contributors = $cons;
				}
			}
		}
		else
		{
			$contributors = $this->authors()
				->ordered()
				->rows();

			if (!$idx)
			{
				return $contributors;
			}

			// Roles
			$op = 'is';
			if (substr($idx, 0, 1) == '!')
			{
				$op = 'not';
				$idx = ltrim($idx, '!');
			}

			$res = array();
			foreach ($contributors as $contributor)
			{
				if ($op == 'is')
				{
					if ($contributor->get('role') == $idx)
					{
						$res[] = $contributor;
					}
				}

				if ($op == 'not')
				{
					if ($contributor->get('role') != $idx)
					{
						$res[] = $contributor;
					}
				}
			}

			$contributors = $res;
		}

		return $contributors;
	}

	/**
	 * Generates a list of parents
	 *
	 * @return  object
	 */
	public function parents()
	{
		$model = new Association();
		return $this->manyToMany(__NAMESPACE__ . '\\Entry', $model->getTableName(), 'child_id', 'parent_id');
	}

	/**
	 * Generates a list of children
	 *
	 * @return  object
	 * @since   2.0.0
	 */
	public function children()
	{
		$model = new Association();
		return $this->manyToMany(__NAMESPACE__ . '\\Entry', $model->getTableName(), 'parent_id', 'child_id');
	}

	/**
	 * Check if a resource has an attachment with the specified path
	 *
	 * @param   string   $path  File path
	 * @return  boolean
	 */
	public function hasChild($path)
	{
		$row = $this->children()
			->whereEquals('standalone', 0)
			->whereEquals('path', $path, 1)
			->orWhere('path', 'LIKE', '%/' . $path, 1)
			->row();

		return $row->get('id') > 0;
	}

	/**
	 * Make this resource a child of another
	 *
	 * @param   mixed    $id  Resource object or ID
	 * @return  boolean
	 */
	public function makeChildOf($id)
	{
		if ($id instanceof Entry)
		{
			$id = $id->get('id');
		}

		if (!$id)
		{
			return false;
		}

		$model = new Association();
		$model->set('parent_id', (int)$id);
		$model->set('child_id', $this->get('id'));
		$model->set('grouping', 0);

		if (!$model->save())
		{
			$this->addError($model->getError());
			return false;
		}

		return true;
	}

	/**
	 * Make this resource a parent of another
	 *
	 * @param   mixed    $id  Resource object or ID
	 * @return  boolean
	 */
	public function makeParentOf($id)
	{
		if ($id instanceof Entry)
		{
			$id = $id->get('id');
		}

		if (!$id)
		{
			return false;
		}

		$model = new Association();
		$model->set('parent_id', $this->get('id'));
		$model->set('child_id', (int)$id);
		$model->set('grouping', 0);

		if (!$model->save())
		{
			$this->addError($model->getError());
			return false;
		}

		return true;
	}

	/**
	 * Is this a tool?
	 *
	 * @return  bool
	 */
	public function isTool()
	{
		return $this->type->isForTools();
	}

	/**
	 * Check if the resource was deleted
	 *
	 * @return  bool
	 */
	public function isDeleted()
	{
		return ($this->get('published') == self::STATE_TRASHED);
	}

	/**
	 * Check if the resource is published
	 *
	 * @return  bool
	 */
	public function isPublished()
	{
		if ($this->isNew())
		{
			return false;
		}

		// Make sure the resource is published and standalone
		if (in_array($this->get('published'), array(self::STATE_UNPUBLISHED, self::STATE_DRAFT, self::STATE_TRASHED, self::STATE_DRAFT_INTERNAL)))
		{
			return false;
		}

		if ($this->get('publish_up')
		 && $this->get('publish_up') != '0000-00-00 00:00:00'
		 && $this->get('publish_up') >= Date::toSql())
		{
			return false;
		}

		if ($this->get('publish_down')
		 && $this->get('publish_down') != '0000-00-00 00:00:00'
		 && $this->get('publish_down') <= Date::toSql())
		{
			return false;
		}

		return true;
	}

	/**
	 * Check if the resource is owned by a group
	 *
	 * @param   mixed  $group
	 * @return  bool
	 */
	public function inGroup($group=null)
	{
		if ($group)
		{
			if (!is_array($group))
			{
				$group = array($group);
			}

			if (in_array($this->get('group_owner'), $group))
			{
				return true;
			}
		}
		else
		{
			if ($this->get('group_owner'))
			{
				return true;
			}
		}

		return false;
	}

	/**
	 * Do some work on the path to make sure it's kosher
	 *
	 * @return  string
	 */
	public function transformPath()
	{
		$path = stripslashes($this->get('path'));

		if (!preg_match("/(?:https?:|mailto:|ftp:|gopher:|news:|file:)/", $path))
		{
			$path = DS . ltrim($path, DS);

			/*if (substr($path, 0, strlen($this->params->get('uploadpath'))) != $this->params->get('uploadpath'))
			{
				$path = DS . trim($this->params->get('uploadpath'), DS) . $path;
			}*/
		}

		return $path;
	}

	/**
	 * Transform attribs
	 *
	 * @return  object
	 */
	public function transformAttribs()
	{
		if (!is_object($this->attribsRegistry))
		{
			$this->attribsRegistry = new Registry($this->get('attribs'));
		}

		return $this->attribsRegistry;
	}

	/**
	 * Transform params
	 *
	 * @return  object
	 */
	public function transformParams()
	{
		if (!is_object($this->paramsRegistry))
		{
			$params = new Registry($this->get('params'));

			$p = Component::params('com_resources');
			$p->merge($params);

			$this->paramsRegistry = $p;
		}

		return $this->paramsRegistry;
	}

	/**
	 * Transform display date
	 *
	 * @return  string
	 */
	public function transformDate()
	{
		if (!$this->get('modified') || $this->get('modified') == '0000-00-00 00:00:00')
		{
			$this->set('modified', $this->get('created'));
		}

		if (!$this->get('publish_up') || $this->get('publish_up') == '0000-00-00 00:00:00')
		{
			$this->set('publish_up', $this->get('created'));
		}

		// Set the display date
		switch ($this->params->get('show_date'))
		{
			case 1:
				$thedate = Date::of($this->get('created'))->toLocal(Lang::txt('DATE_FORMAT_HZ1'));
				break;
			case 2:
				$thedate = Date::of($this->get('modified'))->toLocal(Lang::txt('DATE_FORMAT_HZ1'));
				break;
			case 3:
				$thedate = Date::of($this->get('publish_up'))->toLocal(Lang::txt('DATE_FORMAT_HZ1'));
				break;
			case 0:
			default:
				$thedate = '';
				break;
		}

		return $thedate;
	}

	/**
	 * Transform rating float into text
	 *
	 * @return  string
	 */
	public function transformRating()
	{
		switch ($this->get('rating'))
		{
			case 0.5:
				$cls = 'half-stars';
				break;
			case 1:
				$cls = 'one-stars';
				break;
			case 1.5:
				$cls = 'onehalf-stars';
				break;
			case 2:
				$cls = 'two-stars';
				break;
			case 2.5:
				$cls = 'twohalf-stars';
				break;
			case 3:
				$cls = 'three-stars';
				break;
			case 3.5:
				$cls = 'threehalf-stars';
				break;
			case 4:
				$cls = 'four-stars';
				break;
			case 4.5:
				$cls = 'fourhalf-stars';
				break;
			case 5:
				$cls = 'five-stars';
				break;
			case 0:
			default:
				$cls = 'no-stars';
				break;
		}

		return $cls;
	}

	/**
	 * Transform description
	 *
	 * @return  string
	 */
	public function transformDescription()
	{
		$content = stripslashes($this->get('fulltxt'));
		$content = preg_replace("#<nb:(.*?)>(.*?)</nb:(.*?)>#s", '', $content);
		$content = str_replace(array('="/site/', '="site/'), '="' . str_replace(PATH_ROOT, '', PATH_APP) . '/site/', $content);

		$content = \Html::content('prepare', $content);

		$content = preg_replace('/^()/i', '', $content);

		return $content;
	}

	/**
	 * Transform description
	 *
	 * @return  string
	 */
	public function fields()
	{
		$data = array();

		preg_match_all("#<nb:(.*?)>(.*?)</nb:(.*?)>#s", $this->get('fulltxt'), $matches, PREG_SET_ORDER);
		if (count($matches) > 0)
		{
			foreach ($matches as $match)
			{
				$data[$match[1]] = stripslashes($match[2]);
			}
		}

		$elements = new \Components\Resources\Models\Elements($data, $this->type()->customFields);
		$schema = $elements->getSchema();
		if (is_object($schema))
		{
			if (!isset($schema->fields) || !is_array($schema->fields))
			{
				$schema->fields = array();
			}
			foreach ($schema->fields as $field)
			{
				if (isset($data[$field->name]))
				{
					if ($value = $elements->display($field->type, $data[$field->name]))
					{
						$data[$field->name] = $value;
					}
				}
			}
		}

		return $data;
	}

	/**
	 * Delete a record and any associated data
	 *
	 * @return  bool
	 */
	public function destroy()
	{
		// Remove children
		foreach ($this->children()->rows() as $child)
		{
			if ($child->get('standalone'))
			{
				continue;
			}

			if (!$child->destroy())
			{
				$this->addError($child->getError());
				return false;
			}
		}

		// Remove parent associations
		$parents = Association::all()
			->whereEquals('child_id', $this->get('id'))
			->rows();

		foreach ($parents as $parent)
		{
			if (!$parent->destroy())
			{
				$this->addError($parent->getError());
				return false;
			}
		}

		// Remove any associated files
		$path = $this->filespace();

		if (is_dir($path))
		{
			if (!Filesystem::deleteDirectory($path))
			{
				$this->addError('Unable to delete file(s).');

				return false;
			}
		}

		return parent::destroy();
	}

	/**
	 * Build and return the base path to resource file storage
	 *
	 * @return  string
	 */
	public function basepath()
	{
		static $base;

		if (!$base)
		{
			$base = PATH_APP . DS . trim(Component::params('com_resources')->get('webpath', '/site/resources'), '/');
		}

		return $base;
	}

	/**
	 * Build and return the relative path to resource file storage
	 *
	 * @return  string
	 */
	public function relativepath()
	{
		$date = $this->get('created');

		if ($date && preg_match("/([0-9]{4})-([0-9]{2})-([0-9]{2})[ ]([0-9]{2}):([0-9]{2}):([0-9]{2})/", $date, $regs))
		{
			$date = mktime($regs[4], $regs[5], $regs[6], $regs[2], $regs[3], $regs[1]);
		}
		if ($date)
		{
			$dir_year  = Date::of($date)->format('Y');
			$dir_month = Date::of($date)->format('m');

			if (!is_dir($this->basepath() . DS . $dir_year . DS . $dir_month . DS . Str::pad($this->get('id')))
			 && intval($dir_year) <= 2013
			 && intval($dir_month) <= 11)
			{
				$dir_year  = Date::of($date)->toLocal('Y');
				$dir_month = Date::of($date)->toLocal('m');
			}
		}
		else
		{
			$dir_year  = Date::of('now')->format('Y');
			$dir_month = Date::of('now')->format('m');
		}

		return DS . $dir_year . DS . $dir_month . DS . Str::pad($this->get('id'));
	}

	/**
	 * Build and return the path to resource file storage
	 *
	 * @return  string
	 */
	public function filespace()
	{
		if (!$this->filespace)
		{
			$this->filespace = $this->basepath() . $this->relativepath();
		}

		return $this->filespace;
	}

	/**
	 * Build and return the url
	 *
	 * @return  string
	 */
	public function link()
	{
		return 'index.php?option=com_resources&' . ($this->get('alias') ? 'alias=' . $this->get('alias') : 'id=' . $this->get('id'));
	}

	/**
	 * Build and return the url
	 *
	 * @param   string  $as
	 * @return  string
	 */
	public function tags($as = 'list')
	{
		$cloud = new Tags($this->get('id'));

		if ($as == 'list')
		{
			$tags = array();
			foreach ($cloud->tags() as $tag)
			{
				array_push($tags, $tag->tag);
			}

			return $tags;
		}

		return $cloud->tags();
	}

	/**
	 * Check a user's authorization
	 *
	 * @param   string   $action  Action to check
	 * @return  boolean  True if authorized, false if not
	 */
	public function access($action='view')
	{
		if (!$this->_authorized)
		{
			$this->_authorize();
		}
		return $this->params->get('access-' . strtolower($action) . '-resource');
	}

	/**
	 * Generate URL for tool
	 *
	 * @return  string
	 */
	public function generateToolUrl()
	{
		$lurl = '';
		if (isset($this->revision) && $this->toolpublished)
		{
			$sess = $this->tool ? $this->tool : $this->alias . '_r' . $this->revision;
			$v = (!isset($this->revision) or $this->revision=='dev') ? 'test' : $this->revision;
			$lurl = 'index.php?option=com_tools&app=' . $this->alias . '&task=invoke&version=' . $v;
		}
		elseif (!isset($this->revision) or $this->revision=='dev')
		{
			// serve dev version
			$lurl = 'index.php?option=com_tools&app=' . $this->alias . '&task=invoke&version=dev';
		}
		else
		{
			$lurl = 'index.php?option=com_tools&task=invoke&app=' . $this->alias;
		}
		return $lurl;
	}

	/**
	 * Authorize current user
	 *
	 * @return  void
	 */
	private function _authorize()
	{
		// NOT logged in
		if (User::isGuest())
		{
			// If the resource is published and public
			if ($this->isPublished() && ($this->get('access') == 0 || $this->get('access') == 3))
			{
				// Allow view access
				$this->params->set('access-view-resource', true);
				if ($this->get('access') == 0)
				{
					$this->params->set('access-view-all-resource', true);
				}
			}
			$this->_authorized = true;
			return;
		}

		if ($this->isTool())
		{
			$tconfig = Component::params('com_tools');

			if ($admingroup = trim($tconfig->get('admingroup', '')))
			{
				// Check if they're a member of admin group
				$ugs = \Hubzero\User\Helper::getGroups(User::get('id'));
				if ($ugs && count($ugs) > 0)
				{
					$admingroup = strtolower($admingroup);
					foreach ($ugs as $ug)
					{
						if (strtolower($ug->cn) == $admingroup)
						{
							$this->params->set('access-view-resource', true);
							$this->params->set('access-view-all-resource', true);

							$this->params->set('access-admin-resource', true);
							$this->params->set('access-manage-resource', true);

							$this->params->set('access-create-resource', true);
							$this->params->set('access-delete-resource', true);
							$this->params->set('access-edit-resource', true);
							$this->params->set('access-edit-state-resource', true);
							$this->params->set('access-edit-own-resource', true);
							break;
						}
					}
				}
			}

			if (!$this->params->get('access-admin-resource')
			 && !$this->params->get('access-manage-resource'))
			{
				// If logged in and resource is published and public or registered
				if ($this->isPublished() && ($this->get('access') == 0 || $this->get('access') == 1))
				{
					// Allow view access
					$this->params->set('access-view-resource', true);
					$this->params->set('access-view-all-resource', true);
				}

				if ($this->get('group_owner'))
				{
					// For protected resources, make sure users can see abstract
					if ($this->get('access') < 3)
					{
						$this->params->set('access-view-resource', true);
						$this->params->set('access-view-all-resource', true);
					}
					else if ($this->get('access') == 3)
					{
						$this->params->set('access-view-resource', true);
					}

					// Get the groups the user has access to
					$xgroups = \Hubzero\User\Helper::getGroups(User::get('id'), 'all');
					$usersgroups = array();
					if (!empty($xgroups))
					{
						foreach ($xgroups as $group)
						{
							if ($group->regconfirmed)
							{
								$usersgroups[] = $group->cn;
							}
						}
					}

					// Get the groups that can access this resource
					$allowedgroups = $this->groups;

					// Find what groups the user has in common with the resource, if any
					$common = array_intersect($usersgroups, $allowedgroups);

					// Check if the user is apart of the group that owns the resource
					// or if they have any groups in common
					if (in_array($this->get('group_owner'), $usersgroups) || count($common) > 0)
					{
						$this->params->set('access-view-resource', true);
						$this->params->set('access-view-all-resource', true);
					}
				}

				require_once Component::path('com_tools') . '/tables/tool.php';

				$db = App::get('db');
				$obj = new \Components\Tools\Tables\Tool($db);
				$obj->loadFromName($this->get('alias'));

				// check if user in tool dev team
				if ($developers = $obj->getToolDevelopers($obj->id))
				{
					foreach ($developers as $dv)
					{
						if ($dv->uidNumber == User::get('id'))
						{
							$this->params->set('access-view-resource', true);
							$this->params->set('access-view-all-resource', true);
							$this->params->set('access-create-resource', true);
							$this->params->set('access-delete-resource', true);
							$this->params->set('access-edit-resource', true);
							$this->params->set('access-edit-state-resource', true);
							$this->params->set('access-edit-own-resource', true);
						}
					}
				}
			}

			$this->_authorized = true;
			return;
		}
		else
		{
			// Check if they're a site admin
			$this->params->set('access-admin-resource', User::authorise('core.admin', null));
			$this->params->set('access-manage-resource', User::authorise('core.manage', null));
			if ($this->params->get('access-admin-resource')
			 || $this->params->get('access-manage-resource'))
			{
				$this->params->set('access-view-resource', true);
				$this->params->set('access-view-all-resource', true);

				$this->params->set('access-create-resource', true);
				$this->params->set('access-delete-resource', true);
				$this->params->set('access-edit-resource', true);
				$this->params->set('access-edit-state-resource', true);
				$this->params->set('access-edit-own-resource', true);

				$this->_authorized = true;
				return;
			}

			$author_ids = array();
			foreach ($this->authors as $author)
			{
				$author_ids[] = $author->get('authorid');
			}

			// If they're not an admin

			// If logged in and resource is published and public or registered
			if ($this->isPublished() && ($this->get('access') == 0 || $this->get('access') == 1))
			{
				// Allow view access
				$this->params->set('access-view-resource', true);
				$this->params->set('access-view-all-resource', true);
			}

			// Check if they're the resource creator
			if ($this->get('created_by') == User::get('id'))
			{
				// Give full access
				$this->params->set('access-view-resource', true);
				$this->params->set('access-view-all-resource', true);

				$this->params->set('access-create-resource', true);
				$this->params->set('access-delete-resource', true);
				$this->params->set('access-edit-resource', true);
				$this->params->set('access-edit-state-resource', true);
				$this->params->set('access-edit-own-resource', true);
			}
			// Listed as a contributor
			else if (in_array(User::get('id'), $author_ids))
			{
				// Give full access
				$this->params->set('access-view-resource', true);
				$this->params->set('access-view-all-resource', true);

				$this->params->set('access-create-resource', true);
				$this->params->set('access-delete-resource', true);
				$this->params->set('access-edit-resource', true);
				$this->params->set('access-edit-state-resource', true);
				$this->params->set('access-edit-own-resource', true);
			}
			// Check group access
			else if ($this->get('group_owner')) // && ($this->get('access') == 3 || $this->get('access') == 4))
			{
				// For protected resources, make sure users can see abstract
				if ($this->get('access') < 3)
				{
					$this->params->set('access-view-resource', true);
					$this->params->set('access-view-all-resource', true);
				}
				else if ($this->get('access') == 3)
				{
					$this->params->set('access-view-resource', true);
				}

				// Get the groups the user has access to
				$xgroups = \Hubzero\User\Helper::getGroups(User::get('id'), 'all');

				$usersgroups = array();
				if (!empty($xgroups))
				{
					foreach ($xgroups as $group)
					{
						if ($group->regconfirmed)
						{
							$usersgroups[] = $group->cn;
						}
					}
				}

				// Get the groups that can access this resource
				$allowedgroups = $this->groups;

				// Find what groups the user has in common with the resource, if any
				$common = array_intersect($usersgroups, $allowedgroups);

				// Check if the user is apart of the group that owns the resource
				// or if they have any groups in common
				if (in_array($this->get('group_owner'), $usersgroups) || count($common) > 0)
				{
					$this->params->set('access-view-resource', true);
					$this->params->set('access-view-all-resource', true);
				}
			}
			else
			{
				$this->params->set('access-view-resource', true);
				$this->params->set('access-view-all-resource', true);
			}
		}

		$this->_authorized = true;
	}

	/**
	 * Compile tool information
	 *
	 * @param   string  $revision
	 * @return  void
	 */
	private function compileToolInfo($revision=null)
	{
		if (!Component::isEnabled('com_tools'))
		{
			return;
		}

		if ($this->isTool())
		{
			require_once Component::path('com_tools') . '/tables/version.php';
			require_once Component::path('com_tools') . '/tables/author.php';

			$this->thistool = null;
			$this->curtool  = null;
			$this->revision = null;

			$db = App::get('db');

			$revisions = array();
			$tv = new \Components\Tools\Tables\Version($db);
			$tv->getToolVersions('', $revisions, $this->get('alias'));

			if ($revisions)
			{
				foreach ($revisions as $tool)
				{
					// Archive version, if requested
					if (($revision && $tool->revision == $revision && $revision != 'dev')
					 or ($revision == 'dev' and $tool->state==3))
					{
						$this->thistool = $tool;
					}
					// Current version
					if ($tool->state == 1 && (count($revisions) == 1 || (count($revisions) > 1 && $revisions[1]->version == $tool->version)))
					{
						$this->curtool = $tool;
						$revision = $revision ? $revision : $tool->revision;
					}
					// Dev version
					if (!$revision && count($revisions) == 1 && $tool->state == 3)
					{
						$this->thistool = $tool;
						$revision = 'dev';
					}
				}

				if (!$this->thistool && !$this->curtool && count($revisions) > 1)
				{
					// Tool is retired, display latest unpublished version
					$this->thistool = $revisions[1];
					$revision = $this->thistool->revision;
				}

				// If the revision is the same as the current version
				if ($this->curtool && $this->thistool && $this->thistool == $this->curtool)
				{
					// Display default resource page for current version
					$this->thistool = null;
				}
			}

			$tconfig = Component::params('com_tools');

			// Replace resource info with requested version
			$resource = $this->toObject();
			$tv->compileResource($this->thistool, $this->curtool, $resource, $revision, $tconfig);
			$this->set($resource);

			$this->revision = $revision;
		}
	}

	/**
	 * Applies a where clause for published items
	 *
	 * @return  $this
	 **/
	public function wherePublished()
	{
		$r = $this->getTableName();

		// Set state
		$this->whereEquals('published', self::STATE_PUBLISHED);

		// Honor publishing window
		$now = Date::toSql();

		$this->whereEquals($r . '.publish_up', '0000-00-00 00:00:00', 1)
			->orWhere($r . '.publish_up', 'IS', null, 1)
			->orWhere($r . '.publish_up', '<=', $now, 1)
			->resetDepth()
			->whereEquals($r . '.publish_down', '0000-00-00 00:00:00', 1)
			->orWhere($r . '.publish_down', 'IS', null, 1)
			->orWhere($r . '.publish_down', '>=', $now, 1)
			->resetDepth();

		return $this;
	}

	/**
	 * Generates a list the most recent entries
	 *
	 * @param   integer  $limit
	 * @param   string   $dateField
	 * @param   string   $sort
	 * @return  object
	 */
	public static function getLatest($limit = 10, $dateField = 'created', $sort = 'DESC')
	{
		return self::all()
			->whereEquals('standalone', 1)
			->order($dateField, $sort)
			->limit($limit);
	}

	/**
	 * Get a record by alias or ID
	 *
	 * @param   mixed   $id
	 * @param   string  $revision
	 * @return  object
	 */
	public static function getInstance($id, $revision=null)
	{
		if (is_integer($id))
		{
			$result = self::oneOrNew($id);
		}
		else
		{
			$result = self::oneByAlias($id);

			if (!$result)
			{
				$result = self::blank();
			}
		}

		if ($result->isTool())
		{
			$result->compileToolInfo($revision);
		}

		return $result;
	}

	/**
	 * Build a query based on commonly used filters
	 *
	 * @param   array  $filters
	 * @return  object
	 */
	public static function allWithFilters($filters = array())
	{
		$query = self::all();

		$r = $query->getTableName();
		$a = Author::blank()->getTableName();

		$query
			->select($r . '.*');

		if (isset($filters['standalone']))
		{
			$query->whereEquals($r . '.standalone', $filters['standalone']);
		}

		if (isset($filters['published']))
		{
			$query->whereIn($r . '.published', (array) $filters['published']);
		}

		if (isset($filters['group']))
		{
			$query->whereEquals($r . '.group_owner', (string) $filters['group']);
		}

		if (isset($filters['type']))
		{
			if (!is_numeric($filters['type']))
			{
				$filters['type'] = Type::oneByAlias($filters['type'])->get('id');
			}
			$query->whereEquals($r . '.type', $filters['type']);
		}

		if (isset($filters['tag']) && $filters['tag'])
		{
			$to = \Components\Tags\Models\Objct::blank()->getTableName();
			$tg = \Components\Tags\Models\Tag::blank()->getTableName();

			$cloud = new \Components\Resources\Helpers\Tags();
			$tags = $cloud->parse($filters['tag']);

			$query->join($to, $to . '.objectid', $r . '.id');
			$query->join($tg, $tg . '.id', $to . '.tagid', 'inner');
			$query->whereEquals($to . '.tbl', 'resources');
			$query->whereIn($tg . '.tag', $tags);
		}

		if (isset($filters['search']))
		{
			$query->whereLike($r . '.title', $filters['search'], 1)
				->orWhereLike($r . '.fulltxt', $filters['search'], 1)
				->resetDepth();
		}

		if (isset($filters['created_by']))
		{
			$query->whereEquals($r . '.created_by', $filters['created_by']);
		}

		if (isset($filters['author']))
		{
			$query
				->join($a, $a . '.subid', $r . '.id', 'left')
				->whereEquals($a . '.subtable', 'resources')
				->whereEquals($a . '.authorid', $filters['author']);

			if (isset($filters['notauthorrole']))
			{
				$query->where($a . '.role', '!=', $filters['notauthorrole']);
			}
		}

		if (isset($filters['access']) && !empty($filters['access']))
		{
			if (!is_array($filters['access']) && !is_numeric($filters['access']))
			{
				switch ($filters['access'])
				{
					case 'public':
						$filters['access'] = 0;
						break;
					case 'protected':
						$filters['access'] = 3;
						break;
					case 'private':
						$filters['access'] = 4;
						break;
					case 'all':
					default:
						$filters['access'] = array(0, 1, 2, 3, 4);
						break;
				}
			}

			if (isset($filters['usergroups']) && !empty($filters['usergroups']))
			{
				$query->whereIn($r . '.access', (array) $filters['access'], 1)
					->orWhereIn($r . '.group_owner', (array) $filters['usergroups'], 1)
					->resetDepth();
			}
			else
			{
				$query->whereIn($r . '.access', (array) $filters['access']);
			}
		}
		elseif (isset($filters['usergroups']) && !empty($filters['usergroups']))
		{
			$query->whereIn($r . '.group_owner', (array) $filters['usergroups']);
		}

		if (isset($filters['now']))
		{
			$query->whereEquals($r . '.publish_up', '0000-00-00 00:00:00', 1)
					->orWhere($r . '.publish_up', 'IS', null, 1)
					->orWhere($r . '.publish_up', '<=', $filters['now'], 1)
					->resetDepth()
				->whereEquals($r . '.publish_down', '0000-00-00 00:00:00', 1)
					->orWhere($r . '.publish_down', 'IS', null, 1)
					->orWhere($r . '.publish_down', '>=', $filters['now'], 1)
					->resetDepth();
		}

		if (isset($filters['startdate']) && $filters['startdate'])
		{
			$query->where($r . '.publish_up', '>', $filters['startdate']);
		}
		if (isset($filters['enddate']) && $filters['enddate'])
		{
			$query->where($r . '.publish_up', '<', $filters['enddate']);
		}

		$query->group($r . '.id');

		return $query;
	}

	/**
	 * Generate description
	 *
	 * @return  string
	 */
	public function searchableDescription()
	{
		$description = $this->description . ' ' . $this->introtext;
		$description = html_entity_decode($description);
		$description = \Hubzero\Utility\Sanitize::stripAll($description);
		return $description;
	}

	/**
	 * Get acces level as text
	 *
	 * @return  string
	 */
	public function transformAccessLevel()
	{
		$accessLevel = 'private';

		if ($this->standalone == 1 && $this->isPublished())
		{
			switch ($this->access)
			{
				case 0:
					$accessLevel = 'public';
				break;

				case 1:
					$accessLevel = 'registered';
				break;

				case 4:
				default:
					$accessLevel = 'private';
			}
		}

		return $accessLevel;
	}

	/**
	 * Get the groups allowed to access a resource
	 *
	 * @return  array
	 */
	public function getGroups()
	{
		if ($this->group_access != '')
		{
			$this->group_access = trim($this->group_access);
			$this->group_access = substr($this->group_access, 1, (strlen($this->group_access)-2));
			$allowedgroups = explode(';', $this->group_access);
		}
		else
		{
			$allowedgroups = array();
		}
		$groupOwner = $this->get('group_owner', '');
		if (!empty($groupOwner))
		{
			$allowedgroups[] = $groupOwner;
		}

		return $allowedgroups;
	}

	/**
	 * Namespace used for solr Search
	 *
	 * @return  string
	 */
	public static function searchNamespace()
	{
		$searchNamespace = 'resource';
		return $searchNamespace;
	}

	/**
	 * Generate solr search Id
	 *
	 * @return  string
	 */
	public function searchId()
	{
		$searchId = self::searchNamespace() . '-' . $this->id;
		return $searchId;
	}

	/**
	 * Convert model results into solr readable generic object.
	 *
	 * @return  stdClass
	 */
	public function searchResult()
	{
		$type = $this->type();
		$obj = new stdClass;
		if ($this->isTool())
		{
			$this->compileToolInfo('');
			$toolUrl = $this->generateToolUrl();
			if (!empty($toolUrl))
			{
				$obj->launchlinkurl_s = rtrim(Request::root(), '/') . Route::urlForClient('site', $toolUrl);
			}
		}
		$obj->url = rtrim(Request::root(), '/') . Route::urlForClient('site', $this->link());
		$obj->title = $this->title;
		$id = $this->id;
		$obj->id = $this->searchId();
		$obj->hubtype = self::searchNamespace();
		$obj->type = $type->type;
		$solrDateFormat = 'Y-m-d\TH:i:s\Z';
		$obj->date_created = Date::of($this->get('created'))->format($solrDateFormat);
		$obj->publish_up = Date::of($this->get('publish_up'))->format($solrDateFormat);
		$obj->description = $this->searchableDescription();
		$obj->author = $this
			->authors()
			->select('name')
			->rows()
			->fieldsbyKey('name');

		$obj->access_level = $this->access_level;
		$groups = $this->getGroups();
		$tags = $this->tags(false);

		if ($tags->count() > 0)
		{
			foreach ($tags as $tag)
			{
				$title = $tag->get('raw_tag', '');
				$description = $tag->get('tag', '');
				$label = $tag->get('label', '');
				$obj->tags[] = array(
					'id' => 'tag-' . $tag->id,
					'title' => $title,
					'description' => $description,
					'access_level' => $tag->admin == 0 ? 'public' : 'private',
					'type' => 'resource-tag',
					'badge_b' => $label == 'badge' ? true : false
				);
			}
		}
		else
		{
			$obj->tags[] = array(
				'id' => '',
				'title' => ''
			);
		}

		$fields = $this->fields();
		if (!empty($fields))
		{
			foreach ($fields as $key => $value)
			{
				$fieldName = str_replace(['"', ' ', '='], '', $key) . '_s';
				$obj->$fieldName = $value;
			}
		}

		$publicationDate = !empty($fields['yearofpublication']) ? $fields['yearofpublication'] : '';
		$publicationDate = empty($publicationDate) && !empty($fields['publicationdate']) ? $fields['publicationdate'] : $publicationDate;
		if (strlen($publicationDate) == 4)
		{
			$publicationDate = $publicationDate . '-01-01 00:00:00';
			$publicationDate = Date::of($publicationDate)->format($solrDateFormat);
		}

		$publicationDate = empty($publicationDate) && !empty($obj->publish_up) ? $obj->publish_up : $publicationDate;
		$obj->yearofpublication_s = $publicationDate;
		$obj->journaltitle_s = !empty($fields['journaltitle']) ? $fields['journaltitle'] : '';
		$obj->volumeno_s = !empty($fields['volumeno']) ? $fields['volumeno'] : '';
		$obj->issuenomonth_s = !empty($fields['issuenomonth']) ? $fields['issuenomonth'] : '';
		$obj->pagenumbers_s = !empty($fields['pagenumbers']) ? $fields['pagenumbers'] : '';

		if (!empty($groups))
		{
			foreach ($groups as $g => $group)
			{
				$grp = \Hubzero\User\Group::getInstance($group);
				if ($grp)
				{
					$groups[$g] = $grp->get('gidNumber');
				}
				// Group not found
				else
				{
					unset($groups[$g]);
				}
			}
			$groups = array_unique($groups);
			$obj->owner_type = 'group';
			$obj->owner = $groups;
		}
		else
		{
			$obj->owner_type = 'user';
			$obj->owner = $this->created_by;
		}
		return $obj;
	}

	/**
	 * Get record total
	 *
	 * @return  integer
	 */
	public static function searchTotal()
	{
		$total = self::all()->total();
		return $total;
	}

	/**
	 * Get search results
	 *
	 * @param   integer  $limit
	 * @param   integer  $offset
	 * @return  object
	 */
	public static function searchResults($limit, $offset = 0)
	{
		return self::all()->start($offset)->limit($limit)->rows();
	}
}


text:
<?xml version="1.0" encoding="UTF-8"?>
<!--
   Project:Easy Web Framework
   Description:
   EasyFK stands for Easy Web Framework.It's an open source product for E-Business / E-Commerce.It
   was launched by a chinese Hezhiping(QQ:110476592) in 2015.The goal of EasyFK is to  provide a
   foundation and starting point for reliable, secure , simple-to-use ,cost-effective ,scalable
   and suitable-for-Chinese E-Business / E-Commerce solutions. With EasyFK, you can get started
   right away without the huge deployment and maintenance costs of E-Business / E-Commerce systems.
   Of course, you can customize it or use it as a framework to implement your most challenging business needs.
   EasyFk is licensed under the Apache License Version 2.0.  You may obtain a copy of the License at
   http://www.apache.org/licenses/LICENSE-2.0
   Author:hezhiping   Email:110476592@qq.com
-->

<project name="Basic Applications Build" default="build" basedir=".">
    <import file="../macros.xml"/>

    <filelist id="baseapps-builds" dir="." files="party/build.xml,product/build.xml"/>

    <!-- ================================================================== -->
    <!-- Removes all created files and directories                          -->
    <!-- ================================================================== -->

    <target name="refresh">
        <antcall target="clean-all"/>
        <antcall target="build"/>
    </target>

    <target name="clean-all">
        <antcall target="clean-xtra"/>
        <antcall target="clean"/>
    </target>

    <target name="clean-xtra" depends="">
        <delete verbose="on">
            <fileset dir="." includes="**/.nbattrs,**/*~,**/.#*,**/.DS_Store,**/*.rej,**/*.orig"/>
        </delete>
    </target>

    <target name="tests">
    </target>

    <target name="clean">
        <iterate target="clean" filelist="baseapps-builds"/>
        <delete file="easyfk.jar"/>
        <echo message="[clean] ========== Done Cleaning Basic  Applications =========="/>
    </target>

    <!-- ================================================================== -->
    <!-- Build Components                                                   -->
    <!-- ================================================================== -->

    <target name="build" depends="">
        <echo message="[build] ========== Start Building Basic Applications (Compile) =========="/>

        <iterate inheritall="false" filelist="baseapps-builds"/>

        <echo message="[build] ========== Done Building Basic Applications (Compile) =========="/>
    </target>

    <!-- ================================================================== -->
    <!-- Build JavaDocs                                                     -->
    <!-- ================================================================== -->

    <target name="docs" depends="">
        <echo message="[docs] ========== Start Building Basic Applications (JavaDoc) =========="/>

        <iterate target="docs" filelist="baseapps-builds"/>

        <echo message="[docs] ========== Done Building Basic Applications (JavaDocs) =========="/>
    </target>
</project>


text:
{% extends sitebase.html %}

{% block head %}

<link rel="stylesheet" href="/static/vendor/css/jquery-ui.min.css" type="text/css"/>

{% end %}

{% block content %}

Create equipments

Equipment type:

  <select id='equipment-type-sel' class='form-control'>
    <option selected disabled>Choose an equipment type...</option>
    {% for equipment_type in equipment_types %}
      <option value="{{equipment_type}}">{{equipment_type}}</option>
    {% end %}
  </select>

Equipment external ID:

  <input type='text' id='external-id' class='form-control'/>

  <button id='create-btn' onclick="createEquipment();" class='btn btn-success' disabled>Create</button>

{% end %}