IdHandler Service Contract

Besides displaying the names of objects, some pages also want to provide links to the objects. Unfortunately, there currently is no way to do so.

First, we need to know that package_id of the package responsible for the object, then we would need to figure out the url to that package instance. This can be done, but even then we would need the local url to the page being able to display a certain object. Since a package may have more than one type of objects (i.e. file folders, files, file versions), we can not simply store additional package information about which page to call to display an object.

The solution to this kind of problem is by not resolving the url at all during display-time, but doing so at the time the user actually wants to see an object. The links would simply direct to /o/$object_id, which is a global virtual-url-handling page that will figure out the package instance url and then relying upon a Service Contract to get the local url - that means every package holding displayable objects should implement this interface for its objects:

declare
    v_id        integer;
begin
    v_id :=  acs_sc_contract.new(
            contract_name => 'AcsObject',
            contract_desc => 'Acs Object Id Handler'
    );
    v_id := acs_sc_msg_type.new(
            msg_type_name => 'AcsObject.PageUrl.InputType',
            msg_type_spec => 'object_id:integer'
    );
    v_id := acs_sc_msg_type.new(
            msg_type_name => 'AcsObject.PageUrl.OutputType',
            msg_type_spec => 'page_url:string'
    );
    v_id := acs_sc_operation.new(
            contract_name => 'AcsObject',
            operation_name => 'PageUrl',
            operation_desc => 'Returns the package specific url to a page
that displays an object',
            operation_iscacheable_p => 'f',
            operation_nargs => 1,
            operation_inputtype => 'AcsObject.PageUrl.InputType',
            operation_outputtype => 'AcsObject.PageUrl.OutputType'
    );

    v_id := acs_sc_impl.new (
              'AcsObject',
              'apm_package_idhandler',
              'acs-kernel'
    );
    v_id := acs_sc_impl.new_alias (
              'AcsObject',
              'apm_package_idhandler',
              'PageUrl',
              'apm_pageurl',
              'TCL'
    );
    acs_sc_binding.new (
              contract_name => 'AcsObject',
              impl_name => 'apm_package_idhandler'
    );                             

    v_id := acs_sc_impl.new (
              'AcsObject',
              'user_idhandler',
              'acs-kernel'
    );
    v_id := acs_sc_impl.new_alias (
              'AcsObject',
              'user_idhandler',
              'PageUrl',
              'acs_user::pageurl',
              'TCL'
    );
    acs_sc_binding.new (
              contract_name => 'AcsObject',
              impl_name => 'user_idhandler'
    );                             
end;
The appropriate tcl-procs look like the following:
ad_proc -public apm_pageurl { object_id } {
    Service Contract Proc to resolve a URL for a package_id
} {
    return
}

namespace eval acs_user {
    ad_proc -public pageurl { object_id } {
        Service Contract Proc to resolve a URL for a user_id
    } {
        return "shared/community-member?user_id=$object_id"
    }
}
Note that the name of the implementation has to be the object-type followed by _idhandler.
timo@studio-k4.de