<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://docs.moodle.org/dev/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Shinoda</id>
	<title>MoodleDocs - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="https://docs.moodle.org/dev/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Shinoda"/>
	<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/Special:Contributions/Shinoda"/>
	<updated>2026-08-11T21:36:46Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.43.5</generator>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Portfolio_API&amp;diff=6227</id>
		<title>Portfolio API</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Portfolio_API&amp;diff=6227"/>
		<updated>2008-07-22T20:06:08Z</updated>

		<summary type="html">&lt;p&gt;Shinoda: /* Duplication of Cata */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This page describes the specification for a future feature, currently being worked on for [[Roadmap|Moodle 2.0]].  This spec is STILL UNDER CONSTRUCTION.&lt;br /&gt;
&lt;br /&gt;
==Overview==&lt;br /&gt;
&lt;br /&gt;
The Portfolio API is a core set of interfaces that all Moodle code will/should use so that we can easily publish files to all kinds of external document repository systems.&lt;br /&gt;
&lt;br /&gt;
It&#039;s important to remember that portfolios are generally treated as WRITE-ONLY.  All we are doing in Moodle is grabbing stuff and pushing it out to somewhere.  Management of the files and further combining/reflecting is done through the native interface provided by the portfolio system.  Reading of files from a repository is handled by the [[Repository API|Repository API]].&lt;br /&gt;
&lt;br /&gt;
A typical user story:&lt;br /&gt;
&lt;br /&gt;
# When portfolios are enabled, every page or major piece of content in Moodle has a little &amp;quot;Save&amp;quot; button beside it.&lt;br /&gt;
# User clicks one of these buttons&lt;br /&gt;
# User is able to choose from a list of configured portfolios (this step will be skipped if there&#039;s only one).&lt;br /&gt;
# User may be asked to define the format of the captured content (eg pdf, IMS LD, HTML, XML ...)&lt;br /&gt;
# User may be asked to define some metadata to go with the captured content (some will be generated automatically).&lt;br /&gt;
# The content and metadata is COPIED to the external portfolio system&lt;br /&gt;
# User has an option to &amp;quot;Return to the page you left&amp;quot; or &amp;quot;Visit their portfolio&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Note this will be just as useful for teachers as for students.&lt;br /&gt;
&lt;br /&gt;
The formatting possibilities will vary depending on the context of the button and the type of external portfolios.  So for example, the &amp;quot;Save&amp;quot; button on the course page would allow the user to capture the whole course in IMS LD or Moodle backup format, which you would not have on a forum page.&lt;br /&gt;
&lt;br /&gt;
==Architecture==&lt;br /&gt;
&lt;br /&gt;
Here is how it will work:&lt;br /&gt;
&lt;br /&gt;
===Plugins and libraries===&lt;br /&gt;
&lt;br /&gt;
There will be two separate types of plugins &lt;br /&gt;
&lt;br /&gt;
# Portfolio (eg Mahara/Elgg/OSP/Facebook/Download) - this will be portfolio/type/xxx&lt;br /&gt;
# Transport (eg mnet/http/scp/cp/dav etc) - these will be reused across different portfolio plugins&lt;br /&gt;
&lt;br /&gt;
Then there will be different formats that plugins will support (and the part of moodle exporting content must support as well), eg IMS, moodle native, mahara native, pdf, enrypted pdf. These will have good libraries supporting them.&lt;br /&gt;
&lt;br /&gt;
The reason for this is that I can see for abstracting the transport layer to its own plugin type is that it&#039;s pretty likely that the same external system might talk both portfolio and repository.&lt;br /&gt;
&lt;br /&gt;
===Admin===&lt;br /&gt;
&lt;br /&gt;
It is important to be allowed to have multiple instances of (some) plugins.  The workflow for adding a new one is:&lt;br /&gt;
&lt;br /&gt;
*Admin navigates to portfolio config&lt;br /&gt;
*Selects from the list of available portfolio plugins, and clicks &#039;add a new external portfolio&#039; (some may be disabled if there is an instance already and the plugin doesn&#039;t support multiple instances)&lt;br /&gt;
*Configure the plugin - select which transport and content types to use if there are multiple supported and installed, urls, authentication keys, etc.&lt;br /&gt;
*Set permissions (maybe) - handled by roles.&lt;br /&gt;
&lt;br /&gt;
This is not necessary for every type of portfolio, because many will just require the user to authenticate directly and if we do ever want to retain settings for each user we just use user preferences.&lt;br /&gt;
&lt;br /&gt;
===Exporting===&lt;br /&gt;
&lt;br /&gt;
*User is viewing a page that calls portfolio_add_button().  This checks to see if there are any configured portfolio plugin instances, and also (maybe) any permissions related to portfolios, and what the user&#039;s portfolio settings are, and then displays either a single &#039;add to portfolio&#039; button, or a drop down menu of the available systems with the add button.&lt;br /&gt;
*When this button is pressed, the user is redirected to portfolio/add.php, with some post data containing the responsible area (activity module or something like course or blog) callback file and function.&lt;br /&gt;
*On this page, the user is presented with a form to enter metadata about the item, and configure any options. At this point if there are multiple formats available for export (based on the intersection of what the plugin and module support), the user can select which format they want.  The plugin and module can both export mform elements for this page.  The user can at this point also select to send the data and wait (with a warning it might take awhile), or queue it for processing if it&#039;s larger.&lt;br /&gt;
*When the user has submitted the form, they are displayed a summary of what they&#039;re about to export, with &#039;confirm&#039; and &#039;edit&#039; buttons.  Edit just relaunches the form, and confirm goes to the next step.&lt;br /&gt;
*At this point, the portfolio plugin (or transport plugin) might need to take control for a step. For example, facebook or flickr might require the user to log in for the first time and confirm moodle is allowed to access their API&lt;br /&gt;
*When the user has confirmed their summary, a &#039;portfolio_send&#039; event will be triggered.  At this point, one of two things happen.  &lt;br /&gt;
# If the user has elected to wait, the &#039;instant&#039; event is fired, and when the caller gets control again, it displays the status to the user.&lt;br /&gt;
# If the user has elected to queue, the delayed event is fired and the user is notified.&lt;br /&gt;
*The user is given the option to continue to their portfolio, or return to where they were&lt;br /&gt;
*&lt;br /&gt;
*When the event is handled (either through the cron or instant event), the following happens:&lt;br /&gt;
*The event handler is invoked. This is almost certainly going to be a function in lib/portfoliolib.php rather than any handler in the portfolio plugins.  The event handler in turn calls the original callback that was passed to portfolio/add.php (module//lib.php or course/lib.php or something), which prepares the data in the format the user selected and returns control to the event handler.&lt;br /&gt;
*At this point we have all the metadata we need, and we have the content to send, so it&#039;s time to start transport negotiation, which happens in stages. Note that some plugins might not implement all stages, and 3 and 4 might be interchangeable in order, depending on the external system.&lt;br /&gt;
#request&lt;br /&gt;
#authentication&lt;br /&gt;
#content&lt;br /&gt;
#metadata (some control is passed to the portfolio plugin for packaging - either to just write out an xml file and zip up the whole package, or send a series of requests)&lt;br /&gt;
#completion&lt;br /&gt;
*When this is complete, we return control to the event handler (which, if it&#039;s an &#039;instant&#039; one, will return true to the caller, which will be the ajax request)&lt;br /&gt;
&lt;br /&gt;
===Storage===&lt;br /&gt;
&lt;br /&gt;
Obviously during this process, state is going to be lost between webserver requests and also between user input and event handling. Some data will be stored in the user&#039;s session (the result of the metadata form, for example) and some in temporary files on the file system.  These will be stored in dataroot/temp/portfolio/$userid-$timestamp/&lt;br /&gt;
&lt;br /&gt;
===Access/Permissions===&lt;br /&gt;
* Portfolio plugin must be allocatable per context (site/course/group etc)&lt;br /&gt;
* How can we assume all users will have an account on the remote system? We could try and silently authenticate them (or at least see if it&#039;s possible to) in the background at the first call to portfolio_add_button (and then cache the result in the session)&lt;br /&gt;
* Check MNet policy - it assumes everyone with the role can have an account (assuming they_sso_in or whatever it&#039;s called is on) - this doesn&#039;t scale though, other transport mechanisms and or plugin types might not follow this assumption.  I think this really must be defined by the portfolio plugin only, not the transport plugin.&lt;br /&gt;
&lt;br /&gt;
===Event API===&lt;br /&gt;
&lt;br /&gt;
It is probably worth using the event api to handle the sending of data, mostly just because it provides a handy way of detached processing.   However, any portfolio_send event will be &#039;owned&#039; by particular &amp;quot;instances&amp;quot; of plugins - and each plugin that subscribes to portfolio_send event (all of them by definition) will have to check if the event data belongs to any of their instances, which is potentially quite messy.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Technical==&lt;br /&gt;
&lt;br /&gt;
===Abstract Portfolio Baseclass: portfolio_plugin_base===&lt;br /&gt;
&lt;br /&gt;
Mixes providing some basic functionality by means of its own functions, with a number of abstract functions plugins must implement, and with some functions that plugins can also optionally override.&lt;br /&gt;
&lt;br /&gt;
See also: [[Writing_a_Portfolio_Plugin]] for a full list of all methods you must/can/shouldn&#039;t override, as well as associated instructions for what else you need to do to create a new portfolio plugin&lt;br /&gt;
&lt;br /&gt;
===Abstract Caller Baseclass : portfolio_caller_base===&lt;br /&gt;
&lt;br /&gt;
Whenever somewhere in Moodle wants an &#039;add to portfolio&#039; button, they must subclass this.&lt;br /&gt;
&lt;br /&gt;
See also: [[Adding_a_Portfolio_Button_to_a_page]] for a full list of all methods you must/can/shouldn&#039;t override as well as the associated instructions for how to call portfolio_add_button.&lt;br /&gt;
&lt;br /&gt;
===Database Tables===&lt;br /&gt;
&lt;br /&gt;
The actual information about plugins that are installed is just stored in mdl_config.&lt;br /&gt;
&lt;br /&gt;
Additionally, as we&#039;re configuring instances of plugins, rather than just one config set per plugin, we&#039;re not using mdl_config_plugin, but instead our own set of tables:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;portfolio_instance:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;2&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;Field&#039;&#039;&#039;&lt;br /&gt;
|&#039;&#039;&#039;Datatype&#039;&#039;&#039;&lt;br /&gt;
|&#039;&#039;&#039;Comment&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|id&lt;br /&gt;
|integer&lt;br /&gt;
|sequence&lt;br /&gt;
|-&lt;br /&gt;
|plugin&lt;br /&gt;
|varchar(50)&lt;br /&gt;
|name of plugin (should match directory in portfolio/type)&lt;br /&gt;
|-&lt;br /&gt;
|name&lt;br /&gt;
|varchar(255)&lt;br /&gt;
|name of this plugin instance&lt;br /&gt;
|-&lt;br /&gt;
|visible&lt;br /&gt;
|smallint&lt;br /&gt;
|0 or 1&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;portfolio_instance_config:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;2&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;Field&#039;&#039;&#039;&lt;br /&gt;
|&#039;&#039;&#039;Datatype&#039;&#039;&#039;&lt;br /&gt;
|&#039;&#039;&#039;Comment&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|id&lt;br /&gt;
|integer&lt;br /&gt;
|sequence&lt;br /&gt;
|-&lt;br /&gt;
|instance&lt;br /&gt;
|integer&lt;br /&gt;
|(pseudo)fk to portfolio_instance&lt;br /&gt;
|-&lt;br /&gt;
|name&lt;br /&gt;
|varchar(255)&lt;br /&gt;
|config name&lt;br /&gt;
|-&lt;br /&gt;
|value&lt;br /&gt;
|text&lt;br /&gt;
|config value&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;portfolio_instance_user:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;2&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;Field&#039;&#039;&#039;&lt;br /&gt;
|&#039;&#039;&#039;Datatype&#039;&#039;&#039;&lt;br /&gt;
|&#039;&#039;&#039;Comment&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|id&lt;br /&gt;
|integer&lt;br /&gt;
|sequence&lt;br /&gt;
|-&lt;br /&gt;
|instance&lt;br /&gt;
|integer&lt;br /&gt;
|(pseudo)fk to portfolio_instance&lt;br /&gt;
|-&lt;br /&gt;
|userid&lt;br /&gt;
|integer&lt;br /&gt;
|(pseudo)fk to mdl_user&lt;br /&gt;
|-&lt;br /&gt;
|name&lt;br /&gt;
|varchar(255)&lt;br /&gt;
|config name&lt;br /&gt;
|-&lt;br /&gt;
|value&lt;br /&gt;
|text&lt;br /&gt;
|config value&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
All plugins can also implement their own database tables as needed, by creating a db/install.xml and db/upgrade.php inside portfolio/type/xxx/ (See [[Writing_a_Portfolio_Plugin]]) for more information.&lt;br /&gt;
&lt;br /&gt;
===Portfolio Plugins===&lt;br /&gt;
&lt;br /&gt;
#[[Mahara_Portfolio_Plugin|mahara]] (will be done for the initial implementation)&lt;br /&gt;
#download (should be done for the initial implementation) &lt;br /&gt;
&lt;br /&gt;
transport types and formats should be able to be found in a shared location for multiple plugins of both portfolio and repository type to use, but also might be specific to one type of plugin which means that moodle should support looking in multiple locations for these plugins. (eg mahara native format will be in the mahara portfolio plugin, but pdf format will be in a shared library)&lt;br /&gt;
&lt;br /&gt;
===Possible Transport Types===&lt;br /&gt;
&lt;br /&gt;
# mnet (will be done for the initial implementation as part of the Mahara Portfolio Plugin)&lt;br /&gt;
# download (will be done for the initial implementation as part of the Download Portfolio Plugin)&lt;br /&gt;
# http&lt;br /&gt;
# filesystem (could be local/nfs/samba whatever) (cp)&lt;br /&gt;
# ssh based (eg scp - should find and re-use the elgg block code as it deals with using ssh keys nicely)&lt;br /&gt;
# webdav&lt;br /&gt;
# open social? (http://code.google.com/apis/opensocial/)&lt;br /&gt;
&lt;br /&gt;
===Possible Export Formats===&lt;br /&gt;
&lt;br /&gt;
(Note that we don&#039;t necessarily want more than one of these for the initial implementation)&lt;br /&gt;
&lt;br /&gt;
# html&lt;br /&gt;
# pdf&lt;br /&gt;
# encrypted pdf&lt;br /&gt;
# ims?&lt;br /&gt;
# leap/piop? (http://wiki.cetis.ac.uk/LEAP_2.0) -- looking increasingly possible Mahara will speak this, so hopefully for the intial implementation&lt;br /&gt;
# moodle native?&lt;br /&gt;
# mahara native?&lt;br /&gt;
# Dublin Core (Enovation implemented this)&lt;br /&gt;
 &lt;br /&gt;
===Testing===&lt;br /&gt;
&lt;br /&gt;
Nico to help (see Development Approach for TDD-related approach)&lt;br /&gt;
&lt;br /&gt;
==MNET==&lt;br /&gt;
&lt;br /&gt;
This section has moved to [[MNET_Roadmap]]&lt;br /&gt;
&lt;br /&gt;
==Duplication of Data==&lt;br /&gt;
&lt;br /&gt;
Moodle will keep track of what content it transfers and when.  It&#039;ll remember the url of the original export location (alphabetisising the url parameters and removing the sessionkey) and a sha1 hash of the data, so that if the user tries to export the same content, Moodle can warn the user (along with a notification of whether it has changed or not).&lt;br /&gt;
&lt;br /&gt;
At this point we can build support into the API for plugins to offer to differentiate between &#039;replace&#039; and &#039;add&#039;, but won&#039;t implement it for any we write for the initial implementation.&lt;br /&gt;
&lt;br /&gt;
==Assumptions==&lt;br /&gt;
&lt;br /&gt;
* Using Moodle&#039;s built in Event API&lt;br /&gt;
&lt;br /&gt;
==Outstanding questions==&lt;br /&gt;
&lt;br /&gt;
*which parts of Moodle will have this button to start with (in order of necessity)&lt;br /&gt;
*Dependance of transport plugins - eg filesystem might depend on http for sending request/finished pings&lt;br /&gt;
&lt;br /&gt;
==Development Approach==&lt;br /&gt;
* create two base classes&lt;br /&gt;
* create mahara portfolio plugin, relying on mnet&lt;br /&gt;
* create portfolio/add.php and portfolio/lib.php&lt;br /&gt;
* start adding calls to the portfolio_add_button function to various places in moodle, with their callbacks.&lt;br /&gt;
* create a dummy listener in mahara until the mahara side is specified&lt;br /&gt;
&lt;br /&gt;
After a conversation with Nico about testing, we decided the most sensible ordering to start with would be:&lt;br /&gt;
&lt;br /&gt;
# Write portfolio/add.php&lt;br /&gt;
# Write *skeleton functions* to support it in portfolio/lib.php and the class structure&lt;br /&gt;
# Write tests for those methods that are necessary&lt;br /&gt;
# Implement the functions to make the tests pass&lt;br /&gt;
# Keep adding module implementations&lt;br /&gt;
&lt;br /&gt;
==See also==&lt;br /&gt;
* [[Repository API]]&lt;br /&gt;
* [[File API]]&lt;/div&gt;</summary>
		<author><name>Shinoda</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Talk:Mahara_Portfolio_Plugin&amp;diff=27747</id>
		<title>Talk:Mahara Portfolio Plugin</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Talk:Mahara_Portfolio_Plugin&amp;diff=27747"/>
		<updated>2008-07-22T11:41:53Z</updated>

		<summary type="html">&lt;p&gt;Shinoda: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=== Question 1 ===&lt;br /&gt;
&lt;br /&gt;
It occurs to me that maybe Mahara could send back information about where files could be put/blogposts could be stored etc, as part of the reply to the &amp;quot;intent to send&amp;quot; request? In the &amp;quot;happy path&amp;quot;, we wouldn&#039;t expect this information to change, so maybe it&#039;s safe to send back something then? [[User:Nigel McNie|Nigel McNie]] 07:40, 20 July 2008 (CDT)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
We&#039;d have to send back information about where to put any possible content though, because at the intent to send stage, we don&#039;t know what format it is (eg, it might just be a file but could be a LEAP/PIOP component, which would go into a whole another artefact plugin).  we&#039;d essentially have to send back the entire artefact tree.  and then even if we did that, at that point Moodle still doesn&#039;t know what format the user wants, so we&#039;d still have to add another step._&lt;br /&gt;
[[User:Penny_Leach|Penny Leach]]&lt;br /&gt;
&lt;br /&gt;
=== Proposed MNET Changes ===&lt;br /&gt;
&lt;br /&gt;
I think the application2service table is a good idea (no more Mahara &amp;quot;course enrolments&amp;quot;!). But I don&#039;t like the idea that the URL field is in this table. Even though it varies by application, it doesn&#039;t apply to _every_ service, and therefore is redundant much of the time. Furthermore, if more services are added that need their own custom per-application fields, all of a sudden this table is getting very big with a lot of poorly related fields.&lt;br /&gt;
&lt;br /&gt;
A different model that doesn&#039;t suffer the problem is this:&lt;br /&gt;
&lt;br /&gt;
==== application2service ====&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;2&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;Field&#039;&#039;&#039;&lt;br /&gt;
|&#039;&#039;&#039;Datatype&#039;&#039;&#039;&lt;br /&gt;
|&#039;&#039;&#039;Comment&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|id&lt;br /&gt;
|integer&lt;br /&gt;
|sequence&lt;br /&gt;
|-&lt;br /&gt;
|applicationid&lt;br /&gt;
|integer&lt;br /&gt;
|fk to mnet_application&lt;br /&gt;
|-&lt;br /&gt;
|serviceid&lt;br /&gt;
|integer&lt;br /&gt;
|fk to mnet_service&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== application2service_sso ====&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;2&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;Field&#039;&#039;&#039;&lt;br /&gt;
|&#039;&#039;&#039;Datatype&#039;&#039;&#039;&lt;br /&gt;
|&#039;&#039;&#039;Comment&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|id&lt;br /&gt;
|integer&lt;br /&gt;
|sequence&lt;br /&gt;
|-&lt;br /&gt;
|a2sid&lt;br /&gt;
|integer&lt;br /&gt;
|fk to application2service(id)&lt;br /&gt;
|-&lt;br /&gt;
|url&lt;br /&gt;
|char(255)&lt;br /&gt;
|&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
[[User:Nigel McNie|Nigel McNie]] 06:41, 22 July 2008 (CDT)&lt;/div&gt;</summary>
		<author><name>Shinoda</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Talk:Mahara_Portfolio_Plugin&amp;diff=27746</id>
		<title>Talk:Mahara Portfolio Plugin</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Talk:Mahara_Portfolio_Plugin&amp;diff=27746"/>
		<updated>2008-07-22T11:39:16Z</updated>

		<summary type="html">&lt;p&gt;Shinoda: Note about application2service table&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=== Question 1 ===&lt;br /&gt;
&lt;br /&gt;
It occurs to me that maybe Mahara could send back information about where files could be put/blogposts could be stored etc, as part of the reply to the &amp;quot;intent to send&amp;quot; request? In the &amp;quot;happy path&amp;quot;, we wouldn&#039;t expect this information to change, so maybe it&#039;s safe to send back something then? [[User:Nigel McNie|Nigel McNie]] 07:40, 20 July 2008 (CDT)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
We&#039;d have to send back information about where to put any possible content though, because at the intent to send stage, we don&#039;t know what format it is (eg, it might just be a file but could be a LEAP/PIOP component, which would go into a whole another artefact plugin).  we&#039;d essentially have to send back the entire artefact tree.  and then even if we did that, at that point Moodle still doesn&#039;t know what format the user wants, so we&#039;d still have to add another step._&lt;br /&gt;
[[User:Penny_Leach|Penny Leach]]&lt;br /&gt;
&lt;br /&gt;
=== Proposed MNET Changes ===&lt;br /&gt;
&lt;br /&gt;
I think the application2service table is a good idea (no more Mahara &amp;quot;course enrolments&amp;quot;!). But I don&#039;t like the idea that the URL field is in this table. Even though it varies by application, it doesn&#039;t apply to _every_ service, and therefore is redundant much of the time. Furthermore, if more services are added that need their own custom per-application fields, all of a sudden this table is getting very big with a lot of poorly related fields.&lt;br /&gt;
&lt;br /&gt;
A different model that doesn&#039;t suffer the problem is this:&lt;br /&gt;
&lt;br /&gt;
==== application2service ====&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;2&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;Field&#039;&#039;&#039;&lt;br /&gt;
|&#039;&#039;&#039;Datatype&#039;&#039;&#039;&lt;br /&gt;
|&#039;&#039;&#039;Comment&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|id&lt;br /&gt;
|integer&lt;br /&gt;
|sequence&lt;br /&gt;
|-&lt;br /&gt;
|applicationid&lt;br /&gt;
|integer&lt;br /&gt;
|fk to mnet_application&lt;br /&gt;
|-&lt;br /&gt;
|serviceid&lt;br /&gt;
|integer&lt;br /&gt;
|fk to mnet_service&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== application2service_sso ====&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;2&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;Field&#039;&#039;&#039;&lt;br /&gt;
|&#039;&#039;&#039;Datatype&#039;&#039;&#039;&lt;br /&gt;
|&#039;&#039;&#039;Comment&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|id&lt;br /&gt;
|integer&lt;br /&gt;
|sequence&lt;br /&gt;
|-&lt;br /&gt;
|a2sid&lt;br /&gt;
|integer&lt;br /&gt;
|fk to application2service(id)&lt;br /&gt;
|-&lt;br /&gt;
|url&lt;br /&gt;
|char(255)&lt;br /&gt;
|&lt;br /&gt;
|}&lt;/div&gt;</summary>
		<author><name>Shinoda</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Talk:Mahara_Portfolio_Plugin&amp;diff=27744</id>
		<title>Talk:Mahara Portfolio Plugin</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Talk:Mahara_Portfolio_Plugin&amp;diff=27744"/>
		<updated>2008-07-20T12:40:20Z</updated>

		<summary type="html">&lt;p&gt;Shinoda: /* Question 1 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=== Question 1 ===&lt;br /&gt;
&lt;br /&gt;
It occurs to me that maybe Mahara could send back information about where files could be put/blogposts could be stored etc, as part of the reply to the &amp;quot;intent to send&amp;quot; request? In the &amp;quot;happy path&amp;quot;, we wouldn&#039;t expect this information to change, so maybe it&#039;s safe to send back something then? [[User:Nigel McNie|Nigel McNie]] 07:40, 20 July 2008 (CDT)&lt;/div&gt;</summary>
		<author><name>Shinoda</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Talk:Mahara_Portfolio_Plugin&amp;diff=27743</id>
		<title>Talk:Mahara Portfolio Plugin</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Talk:Mahara_Portfolio_Plugin&amp;diff=27743"/>
		<updated>2008-07-20T12:40:00Z</updated>

		<summary type="html">&lt;p&gt;Shinoda: New page: === Question 1 ===  It occurs to me that maybe Mahara could send back information about where files could be put/blogposts could be stored etc, as part of the reply to the &amp;quot;intent to send&amp;quot;...&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=== Question 1 ===&lt;br /&gt;
&lt;br /&gt;
It occurs to me that maybe Mahara could send back information about where files could be put/blogposts could be stored etc, as part of the reply to the &amp;quot;intent to send&amp;quot; request? In the &amp;quot;happy path&amp;quot;, we wouldn&#039;t expect this information to change, so maybe it&#039;s safe to send back something then?&lt;/div&gt;</summary>
		<author><name>Shinoda</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Talk:Repository_API&amp;diff=27279</id>
		<title>Talk:Repository API</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Talk:Repository_API&amp;diff=27279"/>
		<updated>2008-06-17T12:08:00Z</updated>

		<summary type="html">&lt;p&gt;Shinoda: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;(Ideas will be deleted from the comments section as they are resolved or merged into the main spec)&lt;br /&gt;
&lt;br /&gt;
===Missing concept of trusted files===&lt;br /&gt;
Files are not created equal, some of them are to be trusted, some can not be trusted at all. Web browsers trust everything received from the server, files from server may access cookie information and thus scripting technologies may allow them to do anything user can do. We do have to trust our teachers because they are supposed to create the learning content, but we definitely can not trust all students.&lt;br /&gt;
&lt;br /&gt;
Imagine if students were allowed to upload arbitrary files to server, like html file loaded with javascript and the server would happily serve them to all Moodle users. Our solution is to use html cleaning filters for submitted texts and force downloads of student uploaded files. To do this we must know if we trust the files or not. Unfortunately the forced downloads of student uploaded files and cleaning of html texts does not solve all problems, because bugs in browsers and especially browser plug-ins may sometimes be used to work around our protections.&lt;br /&gt;
&lt;br /&gt;
The best solution would be to use separate web addresses for trusted and not trusted files (two wwwroots in config.php), not all sites may afford two different addresses but we should be imo prepared for this.  [[User:Skodak|Skodak]] 16:42, 28 February 2008 (CST)&lt;br /&gt;
&lt;br /&gt;
 Great idea, yes.  In fact couldn&#039;t all the files be served via $CFG-&amp;gt;fileroot all the time?  &lt;br /&gt;
 [[User:Martin Dougiamas|Martin Dougiamas]] 07:08, 29 February 2008 (CST)&lt;br /&gt;
&lt;br /&gt;
userid field could be used for this, but separate flag might be better in order to allow teachers to upload untrusted files (teacher uploads assignment submission for the student).&lt;br /&gt;
&lt;br /&gt;
===Relative file links===&lt;br /&gt;
Flash, Java and SCORM require relative links and directory hierarchy in general - we must support it. Some SCORM packages load hundreds of files per page which means the file serving must be very fast with minimum of db access.&lt;br /&gt;
&lt;br /&gt;
Reading the proposal above it seems the API is about serving of isolated files referenced by repository ids. HTML requires to use relative or absolute locators with file names, we can not use repository ids directly in relative links. In case of scorm we have absolute path to base of SCORM package of given activity and SCORM files use relative links inside the package.&lt;br /&gt;
Solution could be to store relative paths directly in filename field ex:directory1/directory2/filename.ext.&lt;br /&gt;
&lt;br /&gt;
 Yes I agree, we definitely need to support (virtual) directories and slasharguments.&lt;br /&gt;
 We could just match the file argument to a path in the db.  Perhaps add the fileid &lt;br /&gt;
 to the argument path as a primary key: fileid/directory1/directory2/filename.ext&lt;br /&gt;
 [[User:Martin Dougiamas|Martin Dougiamas]] 07:08, 29 February 2008 (CST)&lt;br /&gt;
&lt;br /&gt;
===Virtual directories and files===&lt;br /&gt;
Sometimes the content of files is generated on the fly (csv exports, etc.), there are many special files spread through codebase doing nearly the same, it should be imho possible to use the same file API for these.&lt;br /&gt;
&lt;br /&gt;
Another virtual example is assignment submissions and webdav. I would like to see an option to browse the assignment submissions as directory structure, the top directory would be a list of names of users, inside html files with online assignment and uploaded files. This would allow us to implement simple zip&amp;amp;go or webdav based offline grading solutions. The problem here is that the content of this virtual submissions directly needs to be created on the fly based on user references, the proposed repository structure can not be used for this.&lt;br /&gt;
&lt;br /&gt;
 Very interesting idea! [[User:Martin Dougiamas|Martin Dougiamas]] 07:08, 29 February 2008 (CST)&lt;br /&gt;
&lt;br /&gt;
===Backup/restore relinking===&lt;br /&gt;
We are supporting relinking inside courses only. Till now it was easy to guess if absolute link will work after restore on another server.&lt;br /&gt;
There are several types of files:&lt;br /&gt;
*course files - relinked during restore, works on any server if from the same course&lt;br /&gt;
*module files - not relinked, urls are not permanent, link can not be copypasted (assignments, forum attachments, rss files, etc.)&lt;br /&gt;
*user files - not relinked, links work only on original server (blog attachments, personal files, etc.)&lt;br /&gt;
&lt;br /&gt;
 I think all this will be simplified in the proposed system because everything is &lt;br /&gt;
 represented using the same system: a file with an ACL (backup can quickly &lt;br /&gt;
 determine all the files in one course, probably using one SQL query). &lt;br /&gt;
 [[User:Martin Dougiamas|Martin Dougiamas]] 07:08, 29 February 2008 (CST)&lt;br /&gt;
&lt;br /&gt;
If we are backing up/restoring on the same server, will copies of a course restore without file duplication? I use this a lot so that I can archive one year&#039;s course whilst modifying it for next year. [[User:Matt Gibson|Matt Gibson]] 03:12, 29 April 2008 (CDT)&lt;br /&gt;
&lt;br /&gt;
===Access needed for both file and its instances===&lt;br /&gt;
We need two types of access control - first who can create instances (link files), second who can access the instance (download the file).&lt;br /&gt;
&lt;br /&gt;
 For the first don&#039;t we already have those capabilities? (like mod/forum:createattachment,&lt;br /&gt;
 moodle/course:managefiles) but they probably could use rationalising.   We&#039;ll need new &lt;br /&gt;
 ones per repository, too, of course.  &lt;br /&gt;
 [[User:Martin Dougiamas|Martin Dougiamas]] 07:08, 29 February 2008 (CST)&lt;br /&gt;
&lt;br /&gt;
===Cache lifetime===&lt;br /&gt;
There should be a way to specify cache filetime for each instance of file. For example 0 for uploaded assignments, 1 day for resource file. It might be better to allow modules to decide about this, at present it is hardcoded in file.php.&lt;br /&gt;
&lt;br /&gt;
 Great idea.  [[User:Martin Dougiamas|Martin Dougiamas]] 07:08, 29 February 2008 (CST)&lt;br /&gt;
&lt;br /&gt;
== Hierarchy in tables ? ==&lt;br /&gt;
&lt;br /&gt;
It&#039;s possible that I don&#039;t undertand a key piece of the concept, but I wonder why there is no reference to any &amp;quot;parent id&amp;quot; in the file or file_instance table ?&lt;br /&gt;
In other words, how the hierarchical structure is supposed to be &amp;quot;imported&amp;quot; from repository to Moodle ?&lt;br /&gt;
If the hierarchy is reserved to the course context, and not to the repository context, it seems difficult to allow students to access&lt;br /&gt;
to a complete directory, for example.&lt;br /&gt;
&lt;br /&gt;
On the other hand, maybe it&#039;s only a question for the &amp;quot;local&amp;quot; repository type, and not to the &amp;quot;generic&amp;quot; repository API ?&lt;br /&gt;
[[User:Allegre Guillaume|Allegre Guillaume]] 16:43, 5 March 2008 (CST)&lt;br /&gt;
&lt;br /&gt;
[[User:Martin Dougiamas|Martin Dougiamas]] 12:58, 15 March 2008 (CDT): basically I was thinking we just store a full local path for each file instead of hierarchies.  It wasn&#039;t in the db schema though: I&#039;ve just added it.  Thanks!&lt;br /&gt;
&lt;br /&gt;
As for allowing access to a whole directory, that&#039;s something I&#039;ve not thought about - thanks!  I agree we need to support something like that in the interface.  Hmm ..&lt;br /&gt;
&lt;br /&gt;
== Editing Repository Files / Version Control ? ==&lt;br /&gt;
&lt;br /&gt;
How do you imagine to handle the &amp;quot;editing file&amp;quot; problem ? &lt;br /&gt;
I can see several solutions :&lt;br /&gt;
# the simplest way : write access to a file really allows to edit (re-upload) the file, each instance being modified&lt;br /&gt;
# the &amp;quot;cheap copy&amp;quot; way : optionally, the modification is applied only to new file_instances (or those for which the teacher forces to). Here you have to handle two (then maybe more) revisions of this file.&lt;br /&gt;
This triggers the file revisions (or version control) question.&lt;br /&gt;
&lt;br /&gt;
A related question is about versionned files : &lt;br /&gt;
should it depend only upon the repository layer (for example, a plugin could implement a SVN &amp;quot;repository&amp;quot;) ?&lt;br /&gt;
Or should Moodle be aware of the file &amp;quot;revision number&amp;quot; ? &lt;br /&gt;
[[User:Allegre Guillaume|Allegre Guillaume]] 17:00, 5 March 2008 (CST)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[User:Martin Dougiamas|Martin Dougiamas]] 13:08, 15 March 2008 (CDT):  I don&#039;t think we should start getting into such things, version and editing is the job of the dedicated external repository system and people should use that interface.  &lt;br /&gt;
&lt;br /&gt;
What we do have in Moodle is the file-&amp;gt;updates field.  This specifies when to get a fresh copy.  It would be set when the user has specified they want Moodle to use the &amp;quot;latest version&amp;quot; of the file.  And if the user specified a particular version in the repository interface then that is what gets copied (once) and the file-&amp;gt;updates field is left as zero.&lt;br /&gt;
&lt;br /&gt;
One scenario would be if someone wants to use version 1 in one course and version 2 in another, but since the version is in the URL to the original file (and thus a different remote path) they would be treated as two separate files in Moodle anyway.&lt;br /&gt;
&lt;br /&gt;
Might be a small problem if they said &amp;quot;latest version, no update&amp;quot; in course 1 and then later on said &amp;quot;latest version, no update&amp;quot; in a second course.  I guess that would re-download the latest version (which might have changed) and thus course 1 would have an unexpected update.  We could solve this by alerting the user and giving them a choice, I suppose.&lt;br /&gt;
&lt;br /&gt;
== Replacing Moodle&#039;s File System ==&lt;br /&gt;
&lt;br /&gt;
The API as specified still uses the standard Moodle file system, which has its limitations while providing a simple file access method. But, shouldn&#039;t we also be considering completely (or partially) replacing the Moodle file system with the repository system? To that end, the file interface would be the same to users, but where the files are and how they are accessed would be up to which repository was being used. In this system, the standard Moodle file system would just be one of the available repositories. Then the API could support more robust access controls if available, or very few (as Moodle does now). This could allow for per-directory / per-file privilege granting, common file areas so that courses could access the same copy of a file (rather than copying it into the Moodle file area), etc.&lt;br /&gt;
&lt;br /&gt;
The API could also support multiple repositories and allow choosing a file as a link rather than copying it.&lt;br /&gt;
&lt;br /&gt;
Of course, this would also mean allowing write access to the repository area from Moodle, rather than leaving it as read-only. I know the plan was to do this through the [[Portfolio API]], but that really is limited to a user storage function and not a file management function. I think having an API defined to allow for full file management would be a better solution - even if not supported by all repositories.&lt;br /&gt;
[[User:Mike Churchward|Mike Churchward]] 12:54, 6 March 2008 (CST)&lt;br /&gt;
&lt;br /&gt;
[[User:Martin Dougiamas|Martin Dougiamas]] 12:54, 15 March 2008 (CDT) :&lt;br /&gt;
Actually, Mike, the standard file system is NOT being retained at all.  I&#039;ve clarified this slightly in the docs.  The course-centered structure for files is gone.  All files ARE stored on disk but most of the info regarding their location and access is all governed by a table in the database (so the files could just as easily be in a remote database if you wished).  Files used in multiple areas within Moodle will never be stored more than once in Moodle.&lt;br /&gt;
&lt;br /&gt;
The idea of a read/write interface was how we started, but it&#039;s insanely complex once you try to handle backups (ie how do you make a complete backup suitable for giving to someone else?) and access control (how do you decide access depending on Moodle contexts), and we&#039;ll never do it as well as the original repository does it.  Why should we duplicate the Hive interface (to use an example) in Moodle when Hive has a perfectly good one already, one that handles all the extra stuff like Copyright controls, workflow and so on?   &lt;br /&gt;
&lt;br /&gt;
That said, the current Repository plugin idea is very simple, so that if anyone really wanted to embed management into the &amp;quot;file picker&amp;quot; interface they totally could do it in the plugin.&lt;br /&gt;
---&lt;br /&gt;
&lt;br /&gt;
==Windows network drives==&lt;br /&gt;
I&#039;ve added this to the end of the list of repository types to be supported because its possibly the most useful one I can think of. Our school wants to make the transition to moodle, but getting the files on there is the biggest barrier and there is a lot of stuff sitting on our shared and personal folders which is time consuming to transfer. Integration is a big thing that management want to see, particularly the ability to bulk upload files. This may not be a repository as such because it may be that the best way is to copy the file from the shared folder into the repository rather than where it is so it can be moved/deleted accidentally, but easy access is vital in making the process of uploading a file possible. It would also make Moodle a killer app in that it could make our network drives available from home through a secure web interface. &lt;br /&gt;
&lt;br /&gt;
I&#039;ve linked to Guy Thomas&#039; [http://moodle.org/mod/data/view.php?d=13&amp;amp;rid=991 Windows Share Web Client block] as it is a good start, but sadly only works on Linux. [[User:Matt Gibson|Matt Gibson]] 03:43, 29 April 2008 (CDT)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 Fantastic idea, let&#039;s call it the SMB plugin  - [[User:Martin Dougiamas|Martin Dougiamas]] 21:25, 8 June 2008 (CDT)&lt;br /&gt;
&lt;br /&gt;
==Bulk operations==&lt;br /&gt;
On a similar note, Don Hinkelman&#039;s new course format provides a great bulk-upload feature whereby a whole folder can be uploaded and added to the course as resources with the names of the files as titles, with just a couple of clicks. I know this is extending the repository idea a little, but to be honest, I think that one of the biggest weaknesses of Moodle&#039;s file handling right now is not being able to add an entire folder of files without manually going through each one and laboriously specifying location and title. To make any repository useful, I think three operations should be possible with one or two clicks:&lt;br /&gt;
* Add a whole folder/group of files to the repository at once&lt;br /&gt;
* The above operation, but additionally, have all of the folder/group added to a course and named automatically, all in one go.&lt;br /&gt;
* Find a group of files which are already in the repository and add them to a course all at once, with automatic naming as above.&lt;br /&gt;
Not sure if this is best put here or in the Developemt: File_API bit, but here seemed slightly better. [[User:Matt Gibson|Matt Gibson]] 03:43, 29 April 2008 (CDT)&lt;br /&gt;
&lt;br /&gt;
  This is probably not related to the file API at all.  I&#039;d see it as being a new item on the resource menu (Add multiple resources ...) with some sort of shift-click scenario.  nice idea though.  Can you file it as a tracker item?    [[User:Martin Dougiamas|Martin Dougiamas]] 21:26, 8 June 2008 (CDT)&lt;br /&gt;
&lt;br /&gt;
== Bulk and a new resource type from repository ==&lt;br /&gt;
&lt;br /&gt;
Our school has several campuses and a distance learning unit with well organized and big course resource trees. The repository module could be enormously useful for us.&lt;br /&gt;
&lt;br /&gt;
I have looked at Moodle&#039;s IMS repository a bit, and like the way it is possible to put multiple resources into one access point. If the new repository could have some of the same possibilities, it would be marvellous. The drawback with the IMS is that it opens a new window with all the multiple resources. Instead, it would be OK to be able to share a whole lot of resources, or a whole &amp;quot;resource tree&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
I also like the bulk function, to be able to parse a folder of say, html-files, and add it to the resource tree.&lt;br /&gt;
&lt;br /&gt;
==Further notes==&lt;br /&gt;
&lt;br /&gt;
* WebDAV --[[User:Helen Foster|Helen Foster]] 17:20, 9 June 2008 (CDT)&lt;br /&gt;
&lt;br /&gt;
== &amp;quot;local repository name&amp;quot; ==&lt;br /&gt;
&lt;br /&gt;
I think users will find the word local to be confusing.  For the developer or administrator, local seems to refer to the Moodle server.  But for the teacher or student, they will think that local refers to their own local files system.  I would suggest just using the domain name for that server (like myMoodleSite.org) and list it as the first entry to avoid this confusion.  [[User:Gary Anderson|Gary Anderson]] 02:40, 10 June 2008 (CDT)&lt;br /&gt;
&lt;br /&gt;
== Credentials to third party systems ==&lt;br /&gt;
&lt;br /&gt;
You might want to consider something like oauth - http://oauth.net - to manage credentials of third party sites, rather than asking the user for them. I know I sure wouldn&#039;t want to input my credentials for one system into another! [[User:Nigel McNie|Nigel McNie]] 07:08, 17 June 2008 (CDT)&lt;/div&gt;</summary>
		<author><name>Shinoda</name></author>
	</entry>
</feed>