Compare commits

...

535 Commits

Author SHA1 Message Date
Thomas Keller 3cc14ef6a0 Merge branch 'release-1.3' into develop 2012-11-19 00:17:29 +01:00
Thomas Keller 02613203c9 Ease the creation of tarballs a bit. 2012-11-19 00:16:02 +01:00
Thomas Keller 6f4af6b68d Start 1.3.4 development 2012-11-18 23:58:18 +01:00
Thomas Keller ebb8d46420 Release 1.3.3 2012-11-18 23:55:17 +01:00
Thomas Keller 6c5406dd99 Fix a problem in jquery.hotkeys that triggered global hotkeys when one was
in a password text field. Upstream should know of this problem for a long
time already, but hasn't released a fixed version yet, so we're applying
our own patch here (fixes issue 821).
2012-11-18 00:58:27 +01:00
Thomas Keller 4aa4100532 Update French translation from Transifex. 2012-11-18 00:28:30 +01:00
Thomas Keller d90c1a2c23 $prj wasn't defined, so use the project reference that the page has instead (fixes issue 808) 2012-07-20 15:03:57 +02:00
Thomas Keller 22c1f92b2b Use git's "find copies harder" algorithm to - well - find copies in changesets
and render them as such.
2012-07-11 00:17:23 +02:00
Thomas Keller d17098e703 Ensure that PHP doesn't interpret read ini file values and therefor
scrambles the output of hgrc files (issue 523).
2012-06-05 20:55:21 +02:00
Thomas Keller 64c6674762 Copy over all project properties, except a few scm settings and very
project-specific ones, when a new project is based on another one.
2012-05-21 23:33:38 +02:00
Thomas Keller 01febe1411 Merge branch 'release-1.3' into develop 2012-05-15 22:48:56 +02:00
Thomas Keller 839444cc8a Use Pluf's new migration capabilities to prevent problems with the
circular dependency between project and project activity during
new db installations (issue 800).
ATTENTION: IDF now needs Pluf a45dc195 or newer!
2012-05-15 22:43:15 +02:00
Thomas Keller 831439120c Make the current_activity field in IDF_Project nullable and fix
a problem in the migration 25's down method (issue 800)
2012-05-15 22:38:27 +02:00
Thomas Keller 6bb886b92a If ssh public key data contain forward slashes, the SyncGit cron job
did not properly find and update the region which it should have
under its control (thanks to Simon Gareste for the fix!)
2012-05-14 19:38:07 +02:00
Thomas Keller dd3474c06c Add two more targets to dump and restore application backups. 2012-05-12 02:25:33 +02:00
Thomas Keller bcd515eed5 Do not display all project to a user if he has no rights for
_any_ project of the forge, but actually hide all... thanks
to René Klomp for this finding!
2012-05-11 23:26:42 +02:00
Thomas Keller 231dfaa8a6 Merge branch 'release-1.3' of projects.ceondo.com:indefero into develop 2012-05-09 22:21:32 +02:00
Thomas Keller 0826dab575 Start 1.3.3 development. 2012-05-09 22:10:24 +02:00
Thomas Keller 1c037f81a0 Release 1.3.2. 2012-05-09 22:09:13 +02:00
Thomas Keller 71c41fe940 Of course $ids should have been initialized beforehand... 2012-05-07 23:26:23 +02:00
Thomas Keller 8ad0707509 Fix the project display when no projects are available or visible. 2012-05-07 23:12:55 +02:00
Thomas Keller e0dec2278c Merge branch 'feature.issue-due-date' of https://github.com/treffynnon/Indefero into develop 2012-05-06 23:12:52 +02:00
Thomas Keller 7221135849 Merge branch 'release-1.3' into develop 2012-05-06 22:49:48 +02:00
Thomas Keller a2d5b14a2c Start with 1.3.2 development. 2012-05-06 22:49:04 +02:00
Thomas Keller 16de6a0d77 Enter a release date and pin the current version. 2012-05-06 22:34:56 +02:00
Thomas Keller 03404adf64 - move getProjectsWithLabelCounts to IDF_Views (where the other functions
reside as well) and make it static
- refactor out the code from getProjects that determines which projects
  are visible by a user and use the same code to restrict the count that
  we calculate for all available project tags
- calculating the project stats is now no longer O(5n) but simply O(5)
  when it comes to SQL queries (where n is the number of filtered projects);
  remove the member statistic since it makes no sense in this context
2012-05-04 23:31:07 +02:00
Thomas Keller dd2fa6f902 Remove OS9 line ending support again, this was left out for a reason.
Fix tests after issue 804 was fixed.
2012-05-04 01:01:33 +02:00
Thomas Keller b6acf4c0e2 Replace the implementation of splitIntoLines by a new one that does
not need PHP's array_shift which tends to be very slow for arrays
with many thousand entries (fixes issue 804).
2012-05-04 00:48:53 +02:00
Simon Holywell cf1a7e8852 fix migration number after merging in the changes to the develop branch 2012-05-02 12:32:14 +01:00
Simon Holywell c0035061b0 Merge branch 'develop' into feature.issue-due-date 2012-05-02 12:21:44 +01:00
Simon Holywell 6c130cd3ca Fix error where a due date of 0000-00-00 00:00:00 was not equated to empty by forcing to null in model restore() method 2012-05-02 12:18:53 +01:00
Thomas Keller 8db3c45763 Revamp this a little and make it jQuery 1.7 compatible (fixes issue 803) 2012-04-29 00:24:09 +02:00
Simon Holywell 696f2d06d6 Attempt to clean up any code inconsistencies and remove an erroneously committed file 2012-04-27 18:34:34 +01:00
Simon Holywell 158f9288d3 Try to avoid anchors with '#' as target and use
'javascript:void(0);' instead
2012-04-27 14:57:18 +01:00
Simon Holywell e883f22790 Make date shortcut names and titles translatable 2012-04-27 14:54:08 +01:00
Simon Holywell 2b5bf490a5 The {aurl} must be outside the {blocktrans} 2012-04-27 09:36:22 +01:00
Simon Holywell 014d8ca6af Change route to remove ability to pass through due status 2012-04-27 09:31:07 +01:00
Simon Holywell 02a99e2f9c The overdue marker in list views is now translatable 2012-04-27 09:22:36 +01:00
Simon Holywell 23253fc40e Fix the duplication of the date shortcut codes 2012-04-26 17:24:06 +01:00
Simon Holywell d348c45c56 simplify the code in IDF_Views_Issue a little 2012-04-26 17:18:35 +01:00
Simon Holywell 53f6133899 Refactor getIssueCountByDueDate slightly 2012-04-26 17:01:10 +01:00
Simon Holywell c3bbddb1ff Repair the issue due date migration for Postgresql 2012-04-26 16:29:26 +01:00
Simon Holywell a608d7ea0a add an explanatory comment to the Issue model preSave hack 2012-04-26 16:24:35 +01:00
Simon Holywell fde3a0a949 Date validation in the Issue model 2012-04-26 16:22:11 +01:00
Simon Holywell 2bd2b3a463 Repair borked conflicted merge :( 2012-04-26 16:19:11 +01:00
Simon Holywell 7207cdcd46 Merge branch 'feature.issue-due-date' of github.com:treffynnon/Indefero into feature.issue-due-date
Conflicts:
	src/IDF/Form/IssueUpdate.php
2012-04-26 16:16:45 +01:00
Simon Holywell 85f247909e Remove local Date field types and use Pluf newly added ones instead 2012-04-26 16:14:41 +01:00
Thomas Keller e8882292b5 Improve the error we throw at the user if no configuration is found
to calculate the project activities.
2012-04-24 20:37:23 +02:00
Thomas Keller bca3eb332e Reference the issue in which the Postgres issues have been tracked. 2012-04-22 23:11:48 +02:00
Thomas Keller 307c35ff42 Pulled updated French translation from Transifex (thanks to
Jonathan Aillet, again!)
2012-04-22 00:52:33 +02:00
Thomas Keller 786e9f81c0 Added Jonathan's email. 2012-04-21 19:03:25 +02:00
Thomas Keller 8cd19c0f53 Escape the xml file path arg. 2012-04-20 00:50:24 +02:00
Thomas Keller d5394265ba Formatting fix. 2012-04-20 00:12:45 +02:00
Thomas Keller 0919cb83d8 Properly mark 1.3.1 dev version. 2012-04-19 23:40:50 +02:00
Thomas Keller b356625268 Merge branch 'release-1.3' into develop 2012-04-19 23:39:47 +02:00
Thomas Keller 4e8ca58a2e Start 1.4 development 2012-04-19 23:37:53 +02:00
Simon Holywell 6996e1185f Issue #13: Due time handling (local time / UTC)
- Move time strip into the formInit method and out of the model
- Improve the validation of the issue due date on the preSave method of the model
2012-04-19 21:20:51 +01:00
Thomas Keller b7ad4bf47a Apparently the default project for tags is still 0, so make it explicit. 2012-04-19 00:37:09 +02:00
Thomas Keller 75f62663a9 Make the project field in the tags table nullable so it is (hopefully)
optional on setups with enabled foreign key constraints.
2012-04-19 00:14:10 +02:00
Thomas Keller 169fbe6216 Another Postgres issue fixed. 2012-04-18 23:22:32 +02:00
Thomas Keller 84d80af1ce Postgres seems to need every column in the group by, not only the PK. 2012-04-18 23:00:37 +02:00
Thomas Keller d1542c9c00 Another Postgres issue (hopefully fixes issue 800). 2012-04-18 22:09:53 +02:00
Thomas Keller 4da01b2732 Another Postgres nuisance. 2012-04-18 22:05:17 +02:00
Thomas Keller b44ad48fd5 Another PostgreSQL issue (hopefully) fixed. 2012-04-18 07:17:35 +02:00
Thomas Keller 3ae92627bc French translation pulled from transifex. 2012-04-18 00:59:41 +02:00
Thomas Keller d46df5c129 Fix PostgreSQL compatibility issues. 2012-04-18 00:55:29 +02:00
Thomas Keller 316c57f85b Add a recent fix and reorder / rework some sections slightly.
Add a release date.
2012-04-15 23:14:48 +02:00
Thomas Keller f11a7f7618 Fix XSS problem in review and issue details (fixes issue 793) 2012-04-15 22:59:23 +02:00
Thomas Keller bb7544021f Spelling fixes. 2012-04-15 22:31:24 +02:00
Simon Holywell 11b3811e17 Issue #8 Misleading label in issue form (minor) - improve styling 2012-04-13 16:59:09 +01:00
Simon Holywell 3e78376be3 Issue #13 Due time handling (local time / UTC) 2012-04-13 14:07:18 +01:00
Simon Holywell cf2f9d419e Issue #8 Misleading label in issue form (minor) 2012-04-13 13:05:58 +01:00
Simon Holywell a9630cea0d Issue #16 Make the date format uniform with the rest of Indefero 2012-04-13 13:00:40 +01:00
Simon Holywell 4323edcf0c Issue #14 The Atom feed is missing a section label for Due date changes 2012-04-13 11:52:04 +01:00
Simon Holywell 120101c4df Issue #11 Filtering by tickets that are not overdue not possible from the list views 2012-04-13 11:47:39 +01:00
Simon Holywell b9c3ee1a09 Issue #16 Make the date format uniform with the rest of Indefero 2012-04-13 11:27:32 +01:00
Simon Holywell 60cdd2224f Issue #9 No display of due date for anonymous users 2012-04-13 11:27:01 +01:00
Simon Holywell e7643e97e4 Issue #7 Undefined variable duedateStatistics for empty project 2012-04-13 10:55:49 +01:00
Simon Holywell 10e5f350f7 Add in helpful shortcuts menu to issue due dates 2012-04-10 21:46:58 +01:00
Simon Holywell 1690fa8416 Move the default due date time to be configurable in the IDF config file 2012-04-10 12:17:22 +01:00
Simon Holywell 9168a26a72 Merge branch 'develop' into feature.issue-due-date 2012-04-10 11:50:22 +01:00
Thomas Keller 21a0a3ffb5 Two search-related tables weren't migrated previously, now they are
(fixes issue 798)
2012-04-08 20:28:35 +02:00
Thomas Keller 27869698e6 Completed German translation, tests will follow. 2012-04-06 00:33:06 +02:00
Thomas Keller 2da7d4db42 Add Victor to AUTHORS. 2012-03-31 23:48:26 +02:00
Thomas Keller bc64c877de Updates to the French translation (Thanks to Victor Quinault!) 2012-03-31 23:47:27 +02:00
Thomas Keller da7b76e00b Do some work on the German translation. 2012-03-31 23:40:56 +02:00
Simon Holywell 3bf4977460 Closes issue 3: Issues list left hand navigation - controls for issue due date 2012-03-30 15:20:05 +01:00
Simon Holywell 315e06da1b Merge branch 'develop' into feature.issue-due-date
Conflicts:
	src/IDF/templates/idf/base-full.html
	src/IDF/templates/idf/base-simple.html
	src/IDF/templates/idf/base.html
2012-03-30 12:20:07 +01:00
Thomas Keller 74d06b0c31 Updated the i18n files again. 2012-03-30 00:10:58 +02:00
Thomas Keller d924c4e277 Merge branch 'feature.upgrade-jquery' of https://github.com/treffynnon/Indefero into develop 2012-03-25 22:58:19 +02:00
Simon Holywell 3a71d71ef8 Setup the overdue summary graph and issue list view 2012-03-23 17:03:17 +00:00
Simon Holywell 1d15d53eaa Add in the beginings of overdue issue display 2012-03-23 00:29:15 +00:00
Simon Holywell 1b363e4b6d Hide overdue tag on issues that are now complete 2012-03-22 22:19:43 +00:00
Simon Holywell c158131f88 Upgrade to jquery 1.7.2 2012-03-22 11:54:59 +00:00
Simon Holywell 9f578829ea Missed one request for jQuery 1.2.6
The JS in the forge management tab was broken by this change and this
commit brings the version of 1.7.1 to all sections of Indefero
2012-03-22 11:45:05 +00:00
Simon Holywell f7d75f1b94 Move the issue due date migration to position 25 to 19 to avoid collision with the latest updates to the develop branch 2012-03-22 11:36:26 +00:00
Simon Holywell fa95cbd934 Merge branch 'develop' into feature.issue-due-date 2012-03-22 11:01:34 +00:00
Thomas Keller f542a7fef8 Updated with the recent string changes. 2012-03-22 01:19:36 +01:00
Thomas Keller a07d2be837 Pluf's i18n parser stumbles upon nested {literal} tags in {blocktrans} sections,
so rewrite the opening bracket as HTML entity to make both, the parser and the
output function happy.
2012-03-22 01:17:05 +01:00
Thomas Keller b529c05d11 Merge branch 'feature.scilab' into develop 2012-03-22 00:54:53 +01:00
Thomas Keller f8a830802e Merge branch 'develop' of projects.ceondo.com:indefero into feature.scilab
Conflicts:
	NEWS.mdtext
2012-03-22 00:51:39 +01:00
Simon Holywell 47da6adebb Tweak JS to allow multiple date formats 2012-03-11 01:43:45 +00:00
Simon Holywell 69949b2941 Add in a due date column to issue lists and a red overdue flag after the issue summary 2012-03-11 01:15:29 +00:00
Simon Holywell d676727c1e Allow for non-mandantory date time fields 2012-03-10 23:16:12 +00:00
Simon Holywell e0da21cbf8 Normalize case of the due date title across the code 2012-03-08 16:50:40 +00:00
Simon Holywell 214d035d12 Add in support for issue notification emails to include due dates 2012-03-08 15:57:42 +00:00
Simon Holywell f005bc1ddd Improve the issue due date field with JS helpers
- Add jQuery UI datepicker widget to the field
- Duplicate changes on the create an issue template
2012-03-08 15:03:02 +00:00
Simon Holywell 9beffaae7e Merge remote branch 'origin/develop' into feature.issue-due-date 2012-03-08 14:47:01 +00:00
Thomas Keller be2f0b3d62 Merge branch 'feature.upgrade-jquery' into develop
This updates jQuery to the most recent version.
Thanks to Simon for his work here.
2012-03-08 02:13:07 +01:00
Simon Holywell b72e0f71e5 Add myself to the AUTHORS file at the suggestion of Loic in IRC 2012-03-07 09:23:38 +00:00
Simon Holywell 9137cab212 Remove the older version of jquery 2012-03-06 23:04:24 +00:00
Simon Holywell f4a6cd1cdb Upgrade jQuery 1.7.1 and the latest version of jquery.hotkeys 2012-03-06 22:36:00 +00:00
Simon Holywell 0e52a2e673 Setup a simple JS shortcut to insert todays date for the due date 2012-03-05 23:05:12 +00:00
Simon Holywell c2d61083a7 Fix the due date display 2012-03-05 22:34:30 +00:00
Simon Holywell f8a1d26b28 Add in the the migration for the due date field for issues 2012-03-05 21:28:58 +00:00
Simon Holywell f697d97b6a Issue 584: Ability to add a due date to a ticket - beginnings thereof 2012-03-04 22:57:26 +00:00
Thomas Keller 9bd5912884 Fix issue 785. 2012-02-24 01:29:25 +01:00
Thomas Keller 562e6803c5 Remove the superfluous <dl>. 2012-02-21 21:53:42 +01:00
Thomas Keller 850be91695 Send downloads always with content-disposition: attachment header. 2012-01-03 18:12:33 +01:00
Thomas Keller 516640b0cd Duplicate column name in query, do'h! 2012-01-03 17:16:33 +01:00
Thomas Keller 126f94016f Do not accidentially delete the logo if we update the project conf. 2012-01-03 17:09:41 +01:00
Thomas Keller 6bbabaebdd Limit the allowed number of labels to six, otherwise our form upload view
breaks and document that limit.
2012-01-03 16:44:41 +01:00
Thomas Keller 3bec47778a Add submitter email as well to the upload notification. 2012-01-03 16:36:57 +01:00
Thomas Keller 215294fcf3 Wrong URL. 2012-01-03 13:30:25 +01:00
Thomas Keller d32e17df91 Actually validate project labels. 2012-01-03 13:09:44 +01:00
Thomas Keller 51ca50ec36 Note that files that are not enlisted in the manifest are ignored during the upload process. 2012-01-03 12:44:09 +01:00
Thomas Keller 9e45b7f7f5 Add the submitter login name to the webhook notification for uploads. 2012-01-03 12:33:48 +01:00
Thomas Keller 5bcd4e1855 Make it a little easier to style the forge page and to view
horizontal lines at all.
2011-12-27 04:01:28 +01:00
Thomas Keller fb88c08e85 Handle empty option lists gracefully. 2011-12-27 03:50:11 +01:00
Thomas Keller eac353f921 Add / reword the recent changes. 2011-12-27 03:46:36 +01:00
Thomas Keller 91dcc78796 Render tags that are set on many projects larger and tags that are set on
only few projects smaller.
2011-12-27 03:34:53 +01:00
Thomas Keller 5c04c87ff6 Custom forge page rendering with project listing, home link,
improved contextual help.
2011-12-27 03:16:09 +01:00
Thomas Keller 6a3f1aed99 Improve styling (no left margin). 2011-12-24 16:01:11 +01:00
Thomas Keller f4058ddd69 Implement a simple form to save custom markdown-enabled content in the
forge's admin area that is displayed instead of the default project list.
Sanitize the URLs that we're using and make a redirect to the listProjects
page when no custom forge page is enabled.
2011-12-24 15:50:41 +01:00
Thomas Keller 17c6ba97d6 Render the project activity value in the activity bar's title tag. 2011-12-24 03:09:46 +01:00
Thomas Keller 65aa830c87 If a project never saved specific tab access rights so far, the specific
access rights setting is not existant and therefor the projects' activity
calculation is always skipped. This should actually not happen.
2011-12-24 03:03:07 +01:00
Thomas Keller ff77046783 getOne checks for uniqueness, but its perfectly valid to have more than
a single check, do'h!
2011-12-24 02:56:11 +01:00
Thomas Keller 6e305eb541 Add filtering and sorting capabilities to the project list page and
also render the project activity with a small bar graph below the
logo image. Sanitize the tagcloud css.
2011-12-24 02:45:01 +01:00
Thomas Keller 608e7a40e4 Save a link to the latest activity value in the project model and
render a simple green bar as activity measure in the project list
view.
2011-12-24 01:07:25 +01:00
Thomas Keller c0506c460d Merge branch 'develop' of projects.ceondo.com:indefero into develop 2011-12-23 17:38:56 +01:00
Thomas Keller da6df31ee9 Escape the path to the monotone binary in case it contains whitespaces. 2011-12-23 17:37:29 +01:00
Thomas Keller 6875e62942 Add some more documentary to the cronjob. 2011-12-23 01:06:13 +01:00
Thomas Keller c07aee6287 Implement a basic, configurable project activity taxonomy. 2011-12-23 01:03:07 +01:00
Thomas Keller 16573daee0 Migrating the timeline entries according to the new model names was
previously forgotten.
2011-12-20 23:39:40 +01:00
Thomas Keller 5ffe66cbfb Add resource revisions to the timeline and add proper templates and
rendering for resources and resource revisions (this is needed later
on for the taxonomy).
Directly link to individual resource / page revisions from the timeline
as well.
2011-12-20 23:39:01 +01:00
Thomas Keller 0f4c952cbd Merge branch 'feature.scilab' of thomaskeller.biz:/var/www/idf.thomaskeller.biz/repo into feature.scilab 2011-12-13 00:38:03 +01:00
Thomas Keller 52d638e027 Next try. 2011-12-13 00:36:57 +01:00
Thomas Keller 6a20b36700 Instead of breaking for every paragraph (which makes our toc look
really broken, break after the first element after a resource container.

This also means that resource containers cannot be "chained" together
to all float left or right, but we have to draw a line somewhere.
2011-12-13 00:32:11 +01:00
Thomas Keller a83634c166 Render information about the old revision to-be-deleted, not about
the current one.
2011-12-13 00:18:49 +01:00
Thomas Keller 4dd8994270 Clear previous floating for new paragraphs. 2011-12-13 00:12:23 +01:00
Thomas Keller 4d7d99c0bb Neither the logo fields / controls nor the external project url
field is mandatory, so don't render it bold.
2011-12-11 01:44:29 +01:00
Thomas Keller 95faf0468a Add a relation between IDF_Project and IDF_Tag (again), this time
its a many-to-many. We store project tags in IDF_Tag with a project
id "0" (this has minimal to no impact on existing code) and therefor
only need to ensure that the new relation table exists in the migration.

Then just the project summary configuration and the admin's project
create and project update forms and views needed to be adapted to
be able to render, create and update project tags.
2011-12-11 01:38:56 +01:00
William MARTIN 1a67712447 Add links in the issue summary context view to quickly create, and see all open issues 2011-12-07 15:49:26 +01:00
Thomas Keller 14be872724 Note the recent wiki resource feature addition. 2011-12-06 22:49:37 +01:00
Thomas Keller 63bc47e7b7 Save / restore project labels for the forge. 2011-12-06 20:39:15 +01:00
Thomas Keller 0d410605f9 Implement deletion of resource revisions. 2011-12-06 08:38:40 +01:00
Thomas Keller 22dfab253b Implement resource deletion. 2011-12-06 08:13:06 +01:00
Thomas Keller a1c8a49430 text/plain was missing 2011-12-06 02:18:59 +01:00
Thomas Keller 3f0c7c23d2 Finally save pagerevision and resourcerevision relations when a new page
revision is created; fix a couple of bugs and streamline the view logic
for viewPage and viewResource.
2011-12-06 02:16:27 +01:00
Thomas Keller 8fde1e4762 Render resources in markdown context properly and implement all the
documented render options.
2011-12-06 01:39:45 +01:00
Thomas Keller 3897d7facb Wrong URL used. 2011-12-04 00:30:44 +01:00
Thomas Keller 959ea74291 Hrm... better use [[!ResourceName]] to avoid conflicts with Markdown. 2011-12-03 02:32:16 +01:00
Thomas Keller ac4d974abb Define and document the new resource embedding syntax in the FAQ, and while
we're at it, also document that one can put simple relations as crew member
instead of only "soft" issue links.
2011-12-03 02:23:37 +01:00
Thomas Keller dd8833665d XHTML 2011-12-03 02:23:13 +01:00
Thomas Keller d54d195b86 Remove help text configuration for this field which is actually
never rendered in the template.
2011-12-03 02:14:46 +01:00
Thomas Keller b752d1fadb Merge branch 'develop' of projects.ceondo.com:indefero into feature.scilab 2011-12-03 01:21:57 +01:00
Thomas Keller 57f314badb Merge branch 'release-1.2' into develop 2011-12-02 01:28:39 +01:00
Jean-Philippe Fleury 6a44af34e1 Fix issue 773. 2011-12-02 01:20:14 +01:00
Jean-Philippe Fleury 7342566c6e Use positional arguments everywhere where we put more than one
string into a translatable sentence to ease the work on more
exotic translations.
2011-12-02 01:16:00 +01:00
Thomas Keller d6eb7532fd Move the orig_file_ext field from resource to resourcerev where
it actually belongs.  Add an option to download a specific resource
revision as attachment in the view.  Fix a bug that occurred when
displaying an old revision of a resource.  Prepare for proper
deletion of the original file and the connected resource in case
a revision is deleted; mark any previous revision as head in this
case. Left-align the summary label in the resource list view.
2011-12-01 00:30:50 +01:00
Thomas Keller 7267fada64 Merge branch 'release-1.2' into develop 2011-11-30 18:09:35 +01:00
Jean-Philippe Fleury bfc568967b Fix issue 765. 2011-11-30 18:06:36 +01:00
Jean-Philippe Fleury 154597c09c Fix issue 763. 2011-11-30 17:44:03 +01:00
Jean-Philippe Fleury 8f886155b0 Improve the wording in some source strings where we refer to "here"
which might be hard to grasp when read out of context, e.g. for
screen readers.
2011-11-29 00:20:15 +01:00
Jean-Philippe Fleury df1130b4c9 Multiple fixes to English language strings. 2011-11-29 00:13:28 +01:00
Thomas Keller 58ccb93f2d Render a resource preview view with more information about the
resource, such as its summary, its mime type, a preview (available
for some image/* and text/* mime types) and a list of pages where
the specific resource revision is used.
2011-11-26 23:25:46 +01:00
Thomas Keller ff2b19d587 The "exists file from archive in project" check was flawed because
$name was overwritten. So, this was fixed by adding a special
functionality when archive files are uploaded that replace existing
files with equal names; these are now deleted. This is docuemented
more clearly in the FAQ and it is also documented now that files
in the archive that are not listed in the manifest are not extracted.
2011-11-19 01:13:22 +01:00
Thomas Keller ba365af020 "Therefor" (AE, legal) -> "Therefore" (BE, general) 2011-11-17 15:33:02 +01:00
Thomas Keller b2e25fc501 Implemented resource creation. 2011-11-15 20:31:39 +01:00
Thomas Keller f29348c604 Rename a couple of view methods and templates to better accomodate
the upcoming changes.
2011-11-13 01:09:11 +01:00
Thomas Keller b39fe8595c Prepare a new section for 1.3. 2011-11-07 01:16:14 +01:00
Thomas Keller 5fefc26543 Apparently the last merge commit did not contain that. 2011-11-07 01:16:09 +01:00
Thomas Keller a37b222878 Merge branch 'release-1.2' into develop
Bump develop version to 1.3-dev
2011-11-07 00:38:19 +01:00
Thomas Keller c9f2575469 Bump version to 1.2.1-dev 2011-11-07 00:35:15 +01:00
Thomas Keller 5101ae5f35 Set a release date for 1.2 and the version. 2011-11-07 00:06:48 +01:00
Thomas Keller b09a7d2fd2 Move the Wiki* models into the IDF_Wiki_* namespace and adapt all models,
table names and relations accordingly.
Start with a resource and resource revision model and add migrations for
that as well.
Note in NEWS.mdtext that we need a more recent Pluf version to take
advantage of the MySQL introspection implementation.
2011-11-06 01:05:27 +01:00
Thomas Keller aa09862059 Turkish and Brazilian Portuguese translations started.
Russian translation included by default (>= 80% translated).
Remaining translations updated / merged.
2011-11-05 15:13:07 +01:00
Thomas Keller f9629f3f7b Merge branch 'release-1.2' into develop 2011-11-05 14:47:05 +01:00
Thomas Keller 884f50155c Fix issue 740. 2011-11-05 14:46:31 +01:00
Thomas Keller e6e20e4f93 Note the recent changes in NEWS.mdtext. 2011-11-05 14:36:32 +01:00
Thomas Keller 82a2d6a39c Rework the notification functionality in all areas:
- for object changes in each tab / section we send out notifications to
  project owners, members and / or additional addresses (all this is
  configurable) (fixes issues 334, 452, 480 and possible others)
- one can now also receive notifications about download updates
- the notification template that informs about issue updates is no
  longer confusing the reader with the "a new issue has been created
  and assigned to you" phrase if the user who is notified is not
  actually the (new) owner (fixes issue 562)
- send-out notification emails for reviews, wiki updates and review
  updates are now linked via a unique message id to support a threaded
  view in email clients like Thunderbird (this was previously only
  implemented for issue notifications for issue 414)

This commit has been sponsored by SciLab.
2011-11-05 14:15:43 +01:00
Thomas Keller 2b5efb7fee Allow the fine-grained configuration of notification settings for
each section and reword the help texts quite a bit. This will
later be used to collect the correct set of email addresses to
notify a particular audience about changes in a particular section.

Notice that a project admin will have to explicitely opt-in for
"Others" notifications, i.e. unless the checkbox is checked, existing
email addresses won't be notified anymore. This is surely debatable
for existing setups, but makes much more sense for new setups.
Eventually we'll write a small migration script to add the specific
enabled setting for those (existing) projects that have a non-empty
mail list configured.

This commit has been sponsored by SciLab.
2011-11-04 00:46:33 +01:00
Thomas Keller 099e4888e8 Implement archive extraction and file handling and note in NEWS and INSTALL
that PHP's zip extension is now needed.
2011-11-03 01:04:16 +01:00
Thomas Keller 3eca572866 Spelling fix. 2011-11-03 01:01:45 +01:00
Thomas Keller c39f5c2174 Change the format to use <labels> and <label> to match the actual field names better. 2011-11-03 00:59:39 +01:00
Thomas Keller cf684c1514 Pulled the French translation work from Delkia and jpfleury. 2011-11-02 09:54:32 +01:00
Thomas Keller 6c9b6b5309 Merge branch 'develop' of projects.ceondo.com:indefero into develop 2011-11-02 09:53:12 +01:00
Thomas Keller a7f283256a Merge branch 'develop' of projects.ceondo.com:indefero into develop 2011-11-02 09:45:13 +01:00
Thomas Keller 4506e1d2b5 Pulled the French translation work from Delkia and jpfleury. 2011-11-02 09:44:05 +01:00
William MARTIN 70f67e6bc6 Enhancement sort on issue summary view 2011-11-02 09:44:00 +01:00
Thomas Keller c71ed2cecb Start with the archive upload functionality (sponsored by Scilab);
add a new view and plain form to upload an archive; rename the internal
URLs, handlers and templates from submit to create for single downloads
and also add a help section about the new format as well as a detailed
FAQ entry. Archive files get a bigger upload limit (default: 20MB).

Next up: archive uploading, validation and processing.
2011-11-02 00:15:33 +01:00
Thomas Keller 05816cb75a release-1.2 merged in 2011-11-01 01:16:58 +01:00
Thomas Keller 91b189b75f Relation verbs weren't properly translated as they should. 2011-11-01 01:15:23 +01:00
Thomas Keller 623c562054 Give the context area a little top padding which lets it look less attached to the upper window border when the page is scrolled and the element is fixed. 2011-11-01 00:58:13 +01:00
Thomas Keller 2a55024640 Clarify the usage of translated verbs a little. 2011-11-01 00:52:34 +01:00
Thomas Keller 8a9f8c66e8 A first stab at updating the German translation for 1.2. 2011-11-01 00:22:00 +01:00
Thomas Keller 81f433085a Limit the available render width for help texts a little and don't put them right below the previous form element. 2011-11-01 00:11:55 +01:00
Thomas Keller 6e59a0a526 Add Gert to AUTHORS 2011-10-31 23:21:44 +01:00
Gert van Valkenhoef 8397d86313 No longer fail to remove a non-existing post-update hook on repository
creation (fixes issue 752)
2011-10-31 23:19:57 +01:00
Thomas Keller b0ac05b608 Slightly reordered 2011-10-31 23:16:42 +01:00
Thomas Keller 48c3989ae3 Updated POT file with new strings. 2011-10-31 01:19:12 +01:00
Thomas Keller b949b7e83a Properly quote paths. 2011-10-31 00:46:12 +01:00
Thomas Keller ad7fad9fbe Updated russian translation from transifex and added new,
yet unknown author of it to AUTHORS.
2011-10-31 00:29:40 +01:00
Thomas Keller 34fbf6ec5f Merge branch 'develop' into feature.scilab 2011-10-27 23:41:12 +02:00
Thomas Keller d2db3b16d2 Fix issue 748. 2011-10-27 23:32:18 +02:00
Thomas Keller ae11b1de4a split() is deprecated in php 5.3 2011-10-27 23:00:14 +02:00
Thomas Keller 6f620e3f54 Override the prettify css rules not only in the diff view, but in
the code views as well.
2011-10-20 17:29:16 +02:00
Thomas Keller 810b753edf Re-order the issue links so that "New Issue" goes to the very right
just before the search input field. Also rename "Open Issues" to
"All Issues" (since one can view both, open and closed issues under
this view, just like in every other issue list view we have) and
mark "All Issues" as active if we filter by label.
2011-10-10 22:32:08 +02:00
Thomas Keller 958fb1b9ad Merge branch 'develop' of projects.ceondo.com:indefero into develop 2011-10-10 20:56:03 +02:00
Thomas Keller 48992adefa Shuffle around a couple of NEWS entries, fix spelling and formatting
here and there.
2011-10-10 20:54:03 +02:00
Thomas Keller d95e1e13e5 Merge branch 'feature.diff-whitespace' into develop 2011-10-10 15:44:20 +02:00
Thomas Keller 381dc5b8f7 Merge branch 'feature.diff-whitespace' into develop 2011-10-10 00:17:48 +02:00
Thomas Keller 464c1a8ef5 Fix / adapt the side-by-side review diff rendering. 2011-10-09 03:14:43 +02:00
Thomas Keller e5b10a8494 Merge branch 'develop' into feature.diff-whitespace 2011-10-09 02:25:49 +02:00
Thomas Keller ffc49b9ea6 Merge branch 'develop' of projects.ceondo.com:indefero into develop 2011-10-09 02:25:03 +02:00
Thomas Keller 0efc14dd6f The autocompleter for the issue relations feature broke the review view, do'h 2011-10-09 02:22:43 +02:00
Thomas Keller 4fb15ccb7d 6abd0b6f made problems in reviews, need to be reworked anyways in a few. 2011-10-09 02:13:49 +02:00
Thomas Keller 234b70845c Render the TAB char wider, so it is easier recognized as tab 2011-10-09 02:04:13 +02:00
Thomas Keller 6abd0b6faa - Move common static methods out of IDF_Diff and into IDF_FileUtil.
- Make stuff that should be private in IDF_Diff really private
  and comment out a test that was the only call path for a previously
  public method.
- Apply the whitespace emphasizing on the normal file view as well
  and get finally rid of padLine()
2011-10-09 01:54:51 +02:00
Thomas Keller fef2bd15bf Merge branch 'develop' into feature.diff-whitespace 2011-10-09 01:54:05 +02:00
Thomas Keller 74d07d8fb8 Ignore a couple of file patterns more and sort the list for easier reading. 2011-10-09 01:53:37 +02:00
Thomas Keller 473e9153ed Merge branch 'develop' into feature.diff-whitespace 2011-10-09 01:40:59 +02:00
Thomas Keller efa10c9afd Properly quote file names for the system call. 2011-10-09 01:39:05 +02:00
Thomas Keller 7438a2bf19 Improve the rendering of the control characters greatly by using
the Unicode counterparts in th 0x24## plane and add a little bit
of explanation what we are doing there and why we are doing this.
2011-10-09 00:55:42 +02:00
Thomas Keller 2e0995abac Fixed rendering in Firefox which did, unlike Chrome, not expand the last
row's height to fit the up-popping horizontal scrollbar, but all rows
just a little, so the heights did not match. I've reworked this to not
used the ill-advised rowspan any longer, but two separate tables whose
heights match each other now in both browsers.

Also I fixed a bug in the whitespace detection code - utf8 characters
where broken into single bytes, so apparently the [:print:] character
class does not accout for them, even in //u mode, so we're selecting
the characters that we want to make visible on our own (basically
control characters lower than space, I might add more).
2011-10-09 00:13:34 +02:00
Thomas Keller c84afd0f78 Some git diffs (most likely octopus merges) start with diff --cc,
so we have to detect and stop log parsing when this occurs as well.
2011-10-09 00:08:16 +02:00
Thomas Keller 52383edfd0 Merge branch 'develop' of projects.ceondo.com:indefero into feature.scilab 2011-10-08 19:26:46 +02:00
Thomas Keller b1276dff6c Merge branch 'develop' of projects.ceondo.com:indefero into feature.diff-whitespace 2011-10-08 19:25:08 +02:00
Thomas Keller b413b7ee89 Improve the calculation part and reuse the values we have from the diff hunks. 2011-10-06 02:31:36 +02:00
Thomas Keller f19f07ec59 Change the unidiff rendering by letting the actual content be rendered
into a separate container that can overflow and side-scroll for long lines.

This effectively removes the need for all kinds of line-breaking hacks
that have been applied before and only worked when the browser was
actually able to break a word group apart somewhere.

Lines are now always rendered as-is; as a nice side effect the line numbers
are always visible, independently how far one scrolled into one direction,
so the context is always clear. If the rendering area is made smaller, the
table rendering also degrades gracefully and provides horizontal scrolling
for views that did not need them before.

The size that is occupied by the number display is now also automatically
determined by the size that is needed to render the biggest line number
in a column. Empty columns are rendered with a zero size.

Currently all this works nicely with a recent version of Chrome, Firefox
still needs some fine tuning for the vertical positioning. Other browsers
are untested as of now.
2011-10-06 02:06:51 +02:00
Thomas Keller 83761c66c5 The left floating breaks the vertical alignment of the unprintable characters. Remove that workaround, which was introduced to wrap very long lines; it should be replaced by something smarter. 2011-10-06 00:00:07 +02:00
Thomas Keller d0e2977746 Add support for line ending detection in our diff parser.
Line endings are now preserved during the diff parsing. When the diff
is then rendered later on, we replace non-printable characters by their
ordinal counterparts, so a user can easily grasp changes when a hunk
comes with edits that might be invisible at first.

The expected format for the diff test suite has changed from serialized
PHP to var_export, which is easier readable, editable and understandable,
while still keeping parsable as well.

Support for old Macintosh line endings could not be added, mainly because
modern SCMs do not support single \r in their unified diff output either
and working around and parsing these "lines" would have been a major
headache with not much outcome (given the fact that all Macs that have been
sold since 2001 or 2002 have been BSD-based and as such used Unix line
endings by default).

This commit fixes issue 636.
2011-10-05 02:44:04 +02:00
Thomas Keller 1be91e5a2a Do not split Hg's and git's log output into lines - this will make it
impossible for us to detect proper line endings later on.
2011-10-05 02:42:51 +02:00
William MARTIN 15d4d1aa7d Fix issue 713 : Wiki page have now a css for printer output 2011-10-04 22:45:51 +02:00
William MARTIN 708b90fccd Fix url /p/aaa/issues/status/open/ 2011-10-04 21:45:23 +02:00
William MARTIN ac7a4c4aa5 Update NEWS 2011-10-04 21:29:11 +02:00
William MARTIN b90246a239 Merge branch 'feature.issue-of-others' into develop 2011-10-04 20:57:18 +02:00
Thomas Keller a9d327d54f Note that issues can now be filtered in the search view. 2011-10-04 12:50:51 +02:00
Thomas Keller eb8fd0aa55 Merge branch 'feature.search-filter' of projects.ceondo.com:indefero into develop 2011-10-04 12:46:28 +02:00
William MARTIN 813184f06c Fix an issue with "unasigned issues"
Rename the view to userIssues
2011-10-04 10:05:42 +02:00
Thomas Keller ef2d3a9af9 Merge branch 'feature.issue-of-others' of projects.ceondo.com:indefero into feature.issue-of-others 2011-10-04 01:01:31 +02:00
Thomas Keller 9a8bd464a3 Remove a couple of unused calls to get a list of project tags; these
calls are currently done from within the tags-cloud template most of
the time, which is ugly, but the way it works as of now.
2011-10-04 00:47:31 +02:00
Thomas Keller 9e2ea7404b Tags are now returned grouped by class, I seem to have missed this call
when I changed the API...
2011-10-04 00:46:48 +02:00
Thomas Keller 160d11b89b Properly initialize arrays with 0 for IN conditions 2011-10-04 00:37:28 +02:00
William MARTIN d860f299fd The last part of the previous patch. 2011-10-03 10:17:10 +02:00
William MARTIN 33882d4fa7 Update how the myIssue view works.
It's allow to display this view for other members.
In the issue summary, we can now follow make links for each user display in the part "Unresolved: By Assignee".
2011-10-03 10:00:35 +02:00
Thomas Keller 85978a4d18 Implement basic filtering capabilities in the issue search view.
Since IDF's text search component does not allow further restrictions
on the result set, we make a second, filtered query to restrict to
the item state ('open' or 'closed') and optionally a label. All in
all this is all harder than it could be, especially the tag cloud
is very monolithic and should be replaced by a data-driven component
that is less dependent on a single data / query and link usage, but
this would for now require too many changes.

Similar questionable is the code duplication for the index, listStatus
and listLabel view implementations that all do more or less the same.
The search implementation now only uses one implementation for a very
similar use case. It also removes the artificial restriction to 100
results we had previously there and does not query a record for each
single result (as was done with Pluf_Search_ResultSet previously).

On my way through this I tried to generalize a couple of i18n texts
and removed smaller issues like the "trailing comma" in label lists.

This partially fixes issue 548.
2011-10-03 01:54:01 +02:00
Thomas Keller e1e7696d53 Add Stéphane to AUTHORS. 2011-10-02 00:10:14 +02:00
Thomas Keller 695428075b Merge branch 'develop' of projects.ceondo.com:indefero into develop 2011-10-02 00:06:17 +02:00
Thomas Keller e7c2e721b4 The tag cloud was fixed to "issues" for both, the open and closed issue list
which is clearly wrong.
2011-10-02 00:05:08 +02:00
William MARTIN 13fad756ab Fix issue 732
Commit based on Stéphane Baron patch
2011-10-01 22:43:00 +02:00
Thomas Keller 699925f797 Note the recent changes. 2011-09-26 01:42:22 +02:00
Thomas Keller 920432025f Change post-commit webhooks to issue PUTs instead of POST requests
and generalize the HTTP header name for the auth digest; introduce
an option to restore the old behaviour and document that; place a
big warning in NEWS.mdtext about this change.

This change has been sponsored by Scilab.
2011-09-26 01:36:04 +02:00
Thomas Keller 7ff298af79 Call the configured download webhook when new downloads are created
or existing downloads are updated.

This feature is sponsored by Scilab.
2011-09-26 00:51:33 +02:00
Thomas Keller b29acd71cb Add an option to specify a webhook URL for updates in the downloads section
and tweak the help texts for the original source web hook a bit. Also remove
the superfluous inline help code from the SourceConf form that was actually
not used.

This feature was sponsored by Scilab.
2011-09-25 02:03:35 +02:00
Thomas Keller dc50e9b316 Spelling. 2011-09-25 02:02:34 +02:00
Thomas Keller 7f610fd2f3 Add an option to configure an external URL per project, e.g. to allow the
linking of the home page of the project.

This feature was kindly sponsored by Scilab.
2011-09-25 01:27:36 +02:00
Thomas Keller 4ae0019e0f Add a sponsored-by flag in NEWS.mdtext. 2011-09-24 00:40:33 +02:00
Thomas Keller c72ce218f7 Merge branch 'develop' of projects.ceondo.com:indefero into feature.webrepos 2011-09-24 00:19:48 +02:00
Thomas Keller 1f0791df0e Make the '@rev' part in the regex optional (fixes issue 730). 2011-09-12 17:54:40 +02:00
Patrick Georgi 34c9d04a35 Provide http access to git repositories
/p/$project/source/repo for git repos now exposes both
"dumb" and "smart" http protocol access.
2011-08-20 20:07:26 +02:00
Patrick Georgi aa2868eb17 Add basic framework for web based repository access
/p/$project/source/repo/ is assigned to a method that
takes care of providing repository access.
For now, this results in an exception on all SCMs.
2011-08-19 22:05:15 +02:00
Thomas Keller a2c832a130 Improve the 'parents' parsing for git and ignore any empty parts; also
react gracefully if we could not parse the parents for some weird reason.
2011-08-17 20:17:14 +02:00
Thomas Keller b17de014ec Reworked the option / argument handling in the SVN interface to
have less code duplication.
2011-08-13 02:28:15 +02:00
Thomas Keller b1b72190e1 Dropped a few more not needed files. 2011-08-13 01:19:58 +02:00
Thomas Keller 2ff2f888bc - Make the SVN test case work without specific test configuration.
- Rename the test repo to match the test function so we can create
  more test repositories for other tests at a later stage.
- Remove useless hooks and configs from the repo (they are not used
  for our specific test and just need memory).
- Note the fix for issue 721 in NEWS.mdtext.
2011-08-13 01:11:00 +02:00
Patrick Georgi 57c2389aae Make SVN backend more robust
The SVN backend failed when trying to access historical information on deleted files.

There's also an initial test case for the SVN backend, testing this issue
and issue 364, which is about a similar problem for renamed files.
Reverting any of these fixes breaks the test.
2011-08-12 20:53:26 +02:00
Thomas Keller d54c86f813 Note the change from issue 716. 2011-07-27 20:06:56 +02:00
Thomas Keller 05a9697007 Merge branch 'feature.content-md5' into develop 2011-07-27 19:59:18 +02:00
Patrick Georgi 945429abf0 Provide MD5 value of downloads to HTTP client
Content-MD5 is a HTTP header to provide end-to-end integrity checks
(see RFC2616, 14.15). This doesn't protect against malicious
modifications, but against transmissions errors and storage errors
on the server.

The change also removes one redirect when downloading files.
2011-07-24 22:12:36 +02:00
William MARTIN a016bcb51b Merge branch 'develop' of projects.ceondo.com:indefero into develop 2011-07-05 11:31:05 +02:00
William MARTIN f2b1ce795c Fix issue 247 : cron overwrites authorized_keys during cron run 2011-07-05 11:30:23 +02:00
Thomas Keller 3a8c56acc4 Postgres needs a VARCHAR cast, which MySQL doesn't understand, of
course. *sigh*
2011-07-01 13:35:43 +02:00
Thomas Keller 7b2552f940 Postgres (and probably others as well) needs an explicit char cast. 2011-06-30 00:25:29 +02:00
Thomas Keller 324b202215 Fix the rendering of issue changes in a mail template and the issue feed fragment. 2011-06-29 17:41:18 +02:00
Loïc d'Anterroches 2c2da6082a Fixed stupid missing semicolon. 2011-06-29 14:41:57 +02:00
Loïc d'Anterroches dd3fbbd7e4 Fixes to support older PHP versions. 2011-06-29 14:30:17 +02:00
William MARTIN 9bbcd571ec Merge branch 'feature.issue-summary' into develop 2011-06-20 11:37:26 +02:00
William MARTIN bbc185bf3b Add unit test for IDF_Project::getIssueCountByOwner 2011-06-20 11:34:42 +02:00
Thomas Keller d1bcdcda20 Fix the mtn getChanges() test. 2011-06-17 23:50:35 +02:00
William MARTIN 6d55602ef3 Add IDF_Project::getIssueCountByOwner and use it into IDF_Views_Issue::summary 2011-06-15 17:30:23 +02:00
William MARTIN 6e7c9f7c4b Use css instead of &nbsp; 2011-06-15 17:29:29 +02:00
William MARTIN 5427aab456 Change "ifnull" sql function to "coalesce" which is supported by postgresql 2011-06-15 13:52:58 +02:00
Thomas Keller 4879d64989 If git's author name does not contain valid utf-8 bytes, skip the author
lookup in the database, which would otherwise only bring up errors.
2011-06-15 13:50:02 +02:00
William MARTIN dab8ea63fc Mark string for translation 2011-06-15 11:35:30 +02:00
William MARTIN b03d7a04a0 improve rendering of 0% bar 2011-06-15 11:30:11 +02:00
William MARTIN ef5b93e3f7 Fix the special case of a empty issue tracker, for the issue summary. 2011-06-15 11:18:41 +02:00
William MARTIN 69ae1c08ef Add an sub-tab under Issue to add a summury view 2011-06-15 09:11:47 +02:00
Thomas Keller 8e4f828cc6 Spelling. 2011-06-13 12:43:39 +02:00
Thomas Keller c4f92f4569 Access all private methods in a non-static way, now that we have a instance-dependent _diagnoseProblem() method 2011-06-13 12:23:22 +02:00
Thomas Keller c4d2b99656 Wrong object to call commit() on... 2011-06-13 01:59:21 +02:00
Thomas Keller d4fe88adab Disable the fixed context bar if the content is already to big 2011-06-12 17:59:43 +02:00
Thomas Keller 69d0e8313a Merge branch 'develop' of projects.ceondo.com:indefero into develop 2011-06-11 00:48:38 +02:00
Thomas Keller 11a234e135 Fix the branch links users of the Subversion frontend get when they enter
a wrong revision and only display this list if there are any branches
available for all SCMs.
2011-06-11 00:47:54 +02:00
Thomas Keller 2f30e4e2f6 Fix a regression introduced with commit 20c3f14cc: If we can read from a process'
pipe doesn't mean the exit code of the process in question is zero, this is
actually what pclose() returns.
2011-06-11 00:44:32 +02:00
Thomas Keller 118ca9f11f Now that IDF_Scm::getChanges() is implemented for all SCMs, there is no need for the try-catch anymore. 2011-06-10 23:40:58 +02:00
Thomas Keller 24fc41ee0d XML node access didn't work and as such renames and copies weren't properly detected. 2011-06-10 23:40:22 +02:00
William MARTIN c00dbac5e0 Merge branch 'feature.download-md5' into develop 2011-06-10 09:26:20 +02:00
William MARTIN d7857c5126 Rename the migration script 2011-06-10 09:25:17 +02:00
Thomas Keller ac6be0d3c0 Implement IDF_Scm::getChanges() for Subversion (closes issue 622) 2011-06-10 02:23:54 +02:00
Thomas Keller 7ff6f09f67 We can actually differentiate between copies and renames in Hg, so lets
add support for another change type, 'copies'. The previous implementation
for Hg was also slightly flawed in the way that it mixed sources with
targets.
2011-06-10 01:34:33 +02:00
Thomas Keller 00b576c5a3 Merge branch 'feature.issue-links' into develop 2011-06-10 00:39:39 +02:00
Thomas Keller 2a33510c96 \w doesn't match -, so better use [^)] to match server names 2011-06-06 23:24:00 +02:00
Thomas Keller d1f79d906d Do not try to symlink the same file twice (fixes issue 695) 2011-06-06 23:18:06 +02:00
Thomas Keller aa043f14ac Two occurrences forgotten 2011-06-06 23:01:25 +02:00
Thomas Keller 638b28399e Fix issues 695 and 697. Still, public keys aren't added to monotone
databases for some weird reason, so issue 696 is still open.
2011-06-05 02:37:47 +02:00
Thomas Keller 1d86f036a3 Add a warning to not configure a global key for all monotone
instances in usher.conf.
2011-06-05 01:31:21 +02:00
Thomas Keller 2f6e0f0a22 Include examples how to setup ACLs for different platforms. 2011-06-05 01:13:00 +02:00
Thomas Keller 1b1b00a10c The server list no longer renders a bogus server entry in case no
monotone server has been configured yet in the connected usher instance.
Also display a short info text if the server or connection list for
a running monotone server is empty.
2011-06-04 23:15:58 +02:00
Thomas Keller 8693418d39 Revert "Improve error handling and reporting (partially resolves issue 695)"
This reverts commit 8ff15368ce.
2011-06-04 01:14:22 +02:00
Thomas Keller 8ff15368ce Improve error handling and reporting (partially resolves issue 695) 2011-06-04 01:03:30 +02:00
Thomas Keller 32cde534bd Fix some errors in the German translation and unify some of the strings.
Thanks to Daniel Steudler <steudlerdaniel@gmail.com> for some of the
pointers. Fixes issue 694.
2011-06-04 00:31:12 +02:00
Thomas Keller c0e26133bd Keep the context area in the view if a view scrolls down several pages. 2011-06-02 02:04:52 +02:00
Thomas Keller 592c2ff9ff Several f'ups in hg's parseLog() method 2011-06-02 01:21:32 +02:00
Thomas Keller 30efd0a2db Merge branch 'develop' of projects.ceondo.com:indefero into develop 2011-06-02 00:55:17 +02:00
Thomas Keller 20c3f14cc8 git and hg diff views did not show empty context lines, a regression
from the commit(s) from issue 633. The diff parser assumed a properly
formatted diff that denotes empty context lines with a single space in
the first column. This single space however was missing, because the
hg and git backends got the diff through PHP's exec() function and
this returns already line-splitted output, but - and this is the actual
problem - removes trailing whitespace at the end of each line, essentially
making " \n" only "\n". When splitting this string now again with
PREG_SPLIT_NO_EMPTY the empty line was completely lost in the diff output.

To make it clear that an empty line does not mark a context line now, but
should stop the diff parsing, the Diff parser now also defaults to 'false'
as line type.

This commit fixes issue 688.
2011-06-02 00:48:38 +02:00
Thomas Keller 80313c88c8 Properly reverse-sort git's tag list again; the rsort on the original output
of the command looked bogus: since each tag ref is prefixed by an iso date and
since commit 94da55d1 by hash, the whole string was of course sorted by this
date and later hash, but not the tag name. This should now make more sense.
2011-06-02 00:38:14 +02:00
Thomas Keller cab1c09ffc Note that issue 559 has been fixed with the fix for issue 686. 2011-06-02 00:08:13 +02:00
William MARTIN c421919092 Fix php syntax 2011-06-01 11:20:03 +02:00
William MARTIN d350876bc1 Update allowed attributes in the Markdown Prefilter, to be less strict.
Fix issue 578
2011-06-01 10:10:01 +02:00
William MARTIN de09c8af56 Merge branch 'develop' of projects.ceondo.com:indefero into develop 2011-05-31 15:40:14 +02:00
William MARTIN 998f4576fe Fix div collision 2011-05-31 15:39:46 +02:00
William MARTIN 06c57f7da6 Set the SQL type to VARCHAR(32)
Process the md5 of each file during the migrationUpdate all IDF_Upload object to process their md5 during the migration
2011-05-31 14:53:44 +02:00
William MARTIN 4d5418a601 Fix migration methods name 2011-05-31 14:01:39 +02:00
William MARTIN 95cc7f627f Process a md5 on the uploaded file, and display it in the per file view.
- The uploader can check that the uploaded file is correct
- The downloader can check his download too
2011-05-31 13:58:12 +02:00
Thomas Keller 2aab4eea3b Apply (and adapt) the patch from issue 364, which should fix the issue. 2011-05-31 13:41:37 +02:00
Thomas Keller 5bbff9f5a6 Rename the "Go to revision" button in the SVN views to "Switch", so it
doesn't break into the next line.
2011-05-31 13:39:55 +02:00
Thomas Keller b5fcf1636a String improvements. 2011-05-31 13:34:28 +02:00
Thomas Keller 13012be5d7 Merge branch 'develop' of projects.ceondo.com:indefero into develop 2011-05-31 13:14:21 +02:00
Thomas Keller ca2ef814fb Add support for the display of monotone node attributes.
(also fix the way the attributes view is displayed, i.e. do not
 use single strings, but one string in context which is much easier
 to translate)
2011-05-31 13:11:55 +02:00
William MARTIN b9407f6aee Add some nobr, to keep the text formated when the message is long 2011-05-31 11:06:39 +02:00
Thomas Keller 9bcb5f9456 Fix a PHP notice / Pluf exception in case any issue type field is cleared. 2011-05-31 10:51:24 +02:00
Thomas Keller f412099f69 Fix whitespace issues in the timeline. 2011-05-30 14:48:36 +02:00
Thomas Keller 0aa5999bb3 Finalize ticket relations (closes issue 638)
- IssueUpdate.php: use dynamically set field validators for dynamically
  created fields; let relation_type0 and relation_issue0 exist at any time;
  check the validity of a user selection and combine the various input fields
  if possible; do the database updates for links; change the "change" format
  for labels to a more precise structure and no longer trust on a leading
  dash for removed labels
- IssueCreate.php: change the validator calls and field names
- Issue.php (getGroupedRelatedIssues): make it possible to return only a
  flat list of integers for easier processing
- 17AddIssueRelations.php: migrate the previous serialized "changes" format
  for issue comments to the new, more structured format (up and down)
- js-autocomplete.html: add support for multiple input fields
- view.html: output relation changes and wrap the related issues stanzas into
  paragraphs
- NEWS.mdtext: note the addition and the need for a specific version of Pluf
2011-05-30 14:02:10 +02:00
Thomas Keller 16dda0743c Basic storage of relations for new issues has been done; the relations
are also properly displayed at the left side in the issue's detail view.
2011-05-28 23:48:00 +02:00
Thomas Keller d079838818 Improve a translation 2011-05-28 01:36:25 +02:00
Thomas Keller 81ce4688df Let the SVN command line client not store the login credentials we give him. 2011-05-28 01:05:10 +02:00
Thomas Keller ee33cc1832 Address files by name rather than ID in the downloads section (issue 686) 2011-05-28 00:48:24 +02:00
Thomas Keller 82bb18fe10 Merge branch 'release-1.1' into develop 2011-05-26 10:51:16 +02:00
Thomas Keller 8987ca7db6 Timezone always comes last 2011-05-26 10:46:12 +02:00
Thomas Keller 8066fd8982 Start 1.1.3 development 2011-05-26 10:46:00 +02:00
William MARTIN a96d8c05a7 Update the NEWS file and set the version number 2011-05-26 09:57:05 +02:00
William MARTIN 4238a5dd50 Update PO file from transifex 2011-05-26 09:56:25 +02:00
William MARTIN 94da55d15e Fix tags extraction from git repository (issue 675) 2011-05-26 09:56:04 +02:00
Thomas Keller 09979b8551 Rewrite log parsing in Mercurial and fix whitespace bugs on the way:
- tags and branches with spaces are now properly parsed (issue 663)
- use --style instead of --template option of hg to include much more
  output for the log command; use that to query the parent revisions of
  a revision (if any) and also to query the actual changes of a revision
- make the log parser much more robust towards changes in the "header"
  of the log output
2011-05-25 23:26:14 +02:00
Thomas Keller 5b82efa0be Fix a couple of issues with our key parsing / validating code.
- be explicit and expect only ssh-dss or ssh-rsa keys
- allow any character (even line breaks and whitespace) in the optional comment,
  but shrink all of them to simple spaces (fixes issue 679)
- test the newly uploaded key against existing keys only by the base key data,
  not the fully uploaded string (that might contain a changed comment line or
  the like) to avoid duplicates; also only check the keys of the user for
  duplicates, not all existing keys in the forge (if for whatever reason two
  user accounts share a key)
2011-05-25 02:13:50 +02:00
Thomas Keller 8502a36481 Mark two new strings in the latest updates view for translation;
prettify the RSS icon display somewhat.
2011-05-16 23:49:08 +02:00
Thomas Keller bcba64b2a1 Basic model files added. 2011-05-10 17:22:32 +02:00
Thomas Keller e40d922eef Add two targets to easily install and update the IDF database 2011-05-10 17:21:56 +02:00
Thomas Keller 7e226b43d3 More work on the issue relation infrastructure
- actually query data for the incoming query
- exclude the current issue from being linked with itself
- allow multiple issues to be given in the second input field
- add the form fields to the ticket update view as well
2011-05-10 16:21:29 +02:00
Thomas Keller 9171bfd1ab Start with issue 638 (issue links); nothing workable yet. 2011-05-09 13:52:09 +02:00
Thomas Keller be4774c95c Mark two strings for translation. 2011-05-06 14:04:08 +02:00
William MARTIN bbf1a1882a Fix issue 671 : Update the SSH Key preg pattern 2011-05-04 11:24:05 +02:00
William MARTIN 9644784a79 Merge branch 'develop' of projects.ceondo.com:indefero into develop 2011-05-04 11:22:50 +02:00
William MARTIN 1940d5c0b5 Fix issue 671 : Update the SSH Key preg pattern 2011-05-04 11:22:24 +02:00
Thomas Keller 7c7e3cd1f1 Rework idf.php-dist a bit more:
- move "Binary section" into "Path section"
- make individual sections more prominent and therefor
  easier to grasp / scan for
- fix the language and expand the explanations for a
  couple of items
- remove the 'debug_scm' configuration variable
  (it is used nowhere in the source and just confuses people)
- update the copyright
2011-04-28 23:53:15 +02:00
William MARTIN 3e2f95a152 Break too long line
Add space between section
2011-04-28 15:43:09 +02:00
William MARTIN 92de88ba13 Rewrite of the idf.php-dist file
- Add example for each mail and cache backend
- Add major part of option use in each Scm backend with description
2011-04-28 15:12:00 +02:00
Thomas Keller 5322cdf609 Fix an URL in the RSS feed 2011-04-27 15:25:18 +02:00
William MARTIN 02d0f0923e Update the NEWS files 2011-04-27 15:09:04 +02:00
Thomas Keller 765a86ba90 Fix an URL in the RSS feed 2011-04-27 15:01:34 +02:00
William MARTIN 34309e34c3 Enhancement visibility of the RSS feed in the timeline view 2011-04-27 14:39:39 +02:00
Thomas Keller 2176d1cde2 Merge branch 'develop' of projects.ceondo.com:indefero into develop 2011-04-27 00:08:10 +02:00
Thomas Keller 45d53e8d21 Merge branch 'feature.better-home' into develop 2011-04-27 00:07:40 +02:00
Thomas Keller b36b8e3afb Final adjustions to the project logo code
- remove the question mark from the default logo for simplification,
  add a soft drop shadow to make the logo more visible on not so light
  backgrounds
- display the project logo and the lock icon in the project list dropdown
- re-position the project title and display the lock icon (if needed)
  on top of the main logo
The code now works best with uploaded logos of 32x32px^2; smaller logos
will be downsampled and repositioned on a best breed basis.
2011-04-27 00:03:44 +02:00
Thomas Keller 801af66a4e Apparently header() does kind of work for php-cli, but of course breaks horribly.
Luckily Pluf has a little knob (IN_UNIT_TESTS) that can prevent this breakage.
2011-04-19 11:07:58 +02:00
Thomas Keller df6ffdf420 Three more test cases for the mtn interface added
- add tests for getTree(), getChanges() and isCommitLarge()
- anonymize the test data somewhat
- return false instead of null for unknown revisions given to getChanges()
2011-04-15 00:54:11 +02:00
Thomas Keller b3368071ac Continue with the mtn interface tests
- test getRepositorySize() with a test file
- implement tests for inTags(), inBranches(), getFile(),
  getCommit() and getExtraProperties()
- mark the static methods as untestable
2011-04-14 00:48:36 +02:00
Thomas Keller 67b80ee11c Continue with the mtn interface tests
- getPathInfo(), disambiguateRevision() and validateRevision() are done
- we no longer need to check / skip a format_version stanza for the extended
  manifest (there is no such stanza outputted)
2011-04-12 23:47:44 +02:00
William MARTIN dc31155de1 Second pass of code review 2011-04-11 15:37:40 +02:00
Thomas Keller 0bae69908b Spelling 2011-04-07 22:40:32 +02:00
Thomas Keller 47a077bc82 Merge branch 'feature.better-home' of projects.ceondo.com:indefero into feature.better-home 2011-04-07 22:38:40 +02:00
William MARTIN 836ff71364 Update code to fix thomas review's 2011-04-06 15:33:26 +02:00
William MARTIN 0afa07b2bd Merge branch 'develop' of projects.ceondo.com:indefero into develop 2011-04-06 12:01:04 +02:00
William MARTIN 4ee3d471fe Update the form validation of IDF_Form_ReviewFileComment.
Now we can add a general comment without per file comment.
2011-04-06 12:00:55 +02:00
Thomas Keller 29c7fed81b Merge branch 'develop' of git://projects.ceondo.com/indefero into develop 2011-04-06 03:01:40 +02:00
Thomas Keller fb62061e5a Started with a unit test for the monotone interface.
Main test infrastructure is there, still lots of functionality left
for testing. Fixed a possible bug in the SCM interface already:
Pluf_HTTP_Response_NotFound needs a request instance as ctor argument,
which we don't have at this point, therefor we just throw an exception.
2011-04-06 02:59:26 +02:00
William MARTIN 9b92b7139f Fix copyright 2011-04-05 13:20:55 +02:00
William MARTIN 5ea4b02205 Update copyrigt 2011-04-02 21:37:07 +02:00
Thomas Keller 12d3eef3d1 monotone actually requires interface_version 13.0 or higher because of the extended manifest usage 2011-04-02 15:40:18 +02:00
Thomas Keller 576c06ffaf Merge branch 'feature.better-home' of git://projects.ceondo.com/indefero into feature.better-home 2011-04-02 00:17:51 +02:00
William MARTIN 352dc3e179 Add IDF_Form_ProjectConf
Update template
2011-04-01 16:05:32 +02:00
William MARTIN aa164936f4 Remove commented code 2011-04-01 14:19:07 +02:00
William MARTIN 9a93acd1a5 Update the admin template 2011-04-01 14:17:56 +02:00
William MARTIN 587aa11cda Update the index template 2011-04-01 14:14:30 +02:00
William MARTIN d04ecd60c4 Add default logo for project without one 2011-04-01 14:13:42 +02:00
Thomas Keller ecef510f78 Merge branch 'develop' of projects.ceondo.com:indefero into develop 2011-04-01 11:18:01 +02:00
Thomas Keller 4976c20935 Its validateRevision, not isValidRevision, here as well 2011-04-01 11:17:21 +02:00
Thomas Keller 5553c37ccd Merge branch 'release-1.1' into develop 2011-04-01 11:17:06 +02:00
Thomas Keller 346b2c6cf8 Call validateRevision(), not isValidRevision(), fixes issue 657 2011-04-01 11:15:13 +02:00
Thomas Keller aa68fe3485 Note fix for issue 655. 2011-03-30 00:19:18 +02:00
Thomas Keller e408fe8733 Make the function static again; this change silently slipped through. 2011-03-30 00:17:35 +02:00
Thomas Keller 836986462a Add Stewart to AUTHORS. 2011-03-30 00:13:50 +02:00
Stewart Platt 51c6cdb20d Only display those filter options for items the user actually has access to
(fixes issue 655)
2011-03-30 00:12:07 +02:00
Thomas Keller 766232f29b Add missing license header. 2011-03-30 00:00:22 +02:00
Thomas Keller 2ed021f30b Merge branch 'develop' of projects.ceondo.com:indefero into develop 2011-03-28 18:00:23 +02:00
Thomas Keller 899fe561df Merge branch 'release-1.1' into develop 2011-03-28 17:59:08 +02:00
Thomas Keller 67d8936083 Start 1.1.2 development 2011-03-28 17:57:15 +02:00
Thomas Keller 78f5cef5bd Enter a release date (i.e. release) 1.1.1 2011-03-28 17:52:53 +02:00
Fernando Sayago Gil 8928b1654c One new string translated. 2011-03-28 17:46:08 +02:00
William MARTIN 977fa0d1d4 Translate a new string. 2011-03-28 12:46:06 +02:00
Thomas Keller 1d89cec2cf Merge branch 'release-1.1' into develop 2011-03-28 01:26:20 +02:00
Thomas Keller 6c6b7d6bb2 Bump to 1.1.1 (not released yet, though) 2011-03-28 01:21:10 +02:00
Thomas Keller f92e88e9b4 Note the recent fixes 2011-03-28 01:20:54 +02:00
Thomas Keller 6e58899fdf Add the new string to idf.pot and update the German translation
accordingly.
2011-03-28 01:15:22 +02:00
Thomas Keller 1513598420 Add a short sentence about password recovery on the registration page
(fixes issue 652)
2011-03-28 01:13:15 +02:00
Thomas Keller 9cfc060760 Improve a translation. 2011-03-28 00:56:44 +02:00
Patrick Georgi a531e34ec2 Add IDF_EmailAddress to backup 2011-03-25 20:39:11 +01:00
Jean-Philippe Fleury 2cce23b5b4 Fix a typo in the French translation and add myself to AUTHORS. 2011-03-25 13:17:49 +01:00
Sindre Myren e518bc9b68 Updated gitserve.py to work with python 3.x 2011-03-25 11:08:18 +01:00
Thomas Keller 8e02d05ba9 Notice the fix of issue 643 in NEWS 2011-03-25 00:53:12 +01:00
Thomas Keller f131083315 Skip linking to a non-existing diff section for changed binary files
(fixes issue 643)
2011-03-25 00:45:06 +01:00
Thomas Keller 39ba5b37ef Ignore a couple of files for code coverage that should not be covered;
add a simle run-tests script that steals some code from photon to
return the code coverage at the end of the test execution
(we're only at about 8% - lots of work left...)
2011-03-25 00:29:50 +01:00
Thomas Keller 002fa05c7f Merge branch 'release-1.1' into develop 2011-03-25 00:14:26 +01:00
Thomas Keller 1a52133fd4 getArchiveStream() should actually be public (issue 648) 2011-03-25 00:11:44 +01:00
Thomas Keller 30900f7196 monotone zip archive entries now all carry the revision date as mtime (issue 645);
add a test case for the zip render response that works with and without PHP's
zip extension
2011-03-24 23:54:52 +01:00
Thomas Keller b753cf0837 Fix a coment. 2011-03-24 01:19:05 +01:00
Thomas Keller 53ab5b6aff Expand the bootstrap script to setup an empty IDF environment. 2011-03-24 00:41:22 +01:00
Thomas Keller 78a0402351 Prepare the Stdio class for easier testing.
- create an interface that describes the basic methods
- let the real stdio class implement this interface
- inject the stdio instance into IDF_Scm_Monotone and do not
  create it in the constructor
- ensure in IDF_Scm_Monotone_ZipRender that we get the proper
  constructor arguments
On a slighly unrelated note, make _getAuthOptions() in the stdio
implementation private.
2011-03-23 00:47:17 +01:00
Thomas Keller 5b5705fe90 Add a unit test for monotone's basicio parser and compiler.
Also note a couple of quirks and be less strict (for now) when it
comes to hash parsing and stanza lines without values.
2011-03-23 00:26:26 +01:00
Thomas Keller f08b5c5e3f Note syncmonotone.mdtext in INSTALL.mdtext 2011-03-20 14:19:53 +01:00
Thomas Keller aa87acd432 Start 1.2 development. 2011-03-20 13:48:49 +01:00
Thomas Keller 7af7ef8357 Merge branch 'release-1.1' into develop 2011-03-20 13:46:45 +01:00
Thomas Keller 627bc4e45f Enter a release date and the proper version 2011-03-20 12:44:21 +01:00
Thomas Keller 909c76ebfb Note that together with issue 136 also issue 500 was fixed. 2011-03-20 01:10:48 +01:00
Thomas Keller 0899ba8515 Various smaller fixes to the Makefile.
- Rename the %_tarball targets to %-zipfile (which they actually are)
  and use a dash instead of an underscore for easier typing
- Use the short revision id in the file name (the file src/IDF/version.php
  contains the full ID)
- Improve the English for some descriptions and break long lines into
  the next line
2011-03-20 01:07:34 +01:00
Thomas Keller b7c0b40491 Add basic source version tracking.
Indefero's version is now noted in src/IDF/version.php;
just before a release is made, the '-dev' is removed and
after the release is made, the version should be increased and
'-dev' should be added back to denote that the development
for the next version started.

The revision identifier is automatically set when an archive
is created and is based on the revision that the archive creator
gave to git-archive(1). If people follow development, we try to
get the current deployed version with git-log(1) and if that
fails as well, the revision is determined to be 'unknown'.
Version and revision are then rendered as HTML meta tags in
the header of each template. (All this is done by the new
{appversion} tag.)
2011-03-20 00:57:49 +01:00
Fernando Sayago Gil 48257ccfed Spanish translation updated. 2011-03-19 15:20:29 +01:00
William MARTIN 269949a65f French translation updated. 2011-03-19 15:20:00 +01:00
Thomas Keller c2de7123e4 Order the author list alphabetically by first name (makes more sense).
Also add missing authors from git log and a couple of missing emails /
IDF usernames.
2011-03-19 00:19:04 +01:00
Thomas Keller e0c6dcd5a4 Merge branch 'release-1.1' of projects.ceondo.com:indefero into release-1.1 2011-03-18 12:12:19 +01:00
Thomas Keller 734ddda363 Fix issue 618 by returning the input unaltered in case PCRE still fails
to evaluate it with the expanded backtrack limit.
2011-03-18 12:10:42 +01:00
Thomas Keller 02cd448f89 Issue 518 was actually a dupe of issue 469. 2011-03-18 03:05:35 +01:00
Matías Halles 5fc3a987de Mercurial log template and parseLog pattern modification.
Added a template for getting a controlled log; in parseLog, changed the regular
expression to match the pattern used in the template (fixes issues 507 and 508).
2011-03-18 02:47:08 +01:00
Dmitry Dulepov be39d72d3c Fix XML parsing exceptions when revisions with empty log messages are parsed.
This fixes issue 518; Dmitry is added to AUTHORS.
2011-03-18 02:33:54 +01:00
Thomas Keller 045eb766f1 Improve the rendering of the prev / next links in the issue view and note the change in NEWS. 2011-03-18 02:14:22 +01:00
Thomas Keller 22d4bd0e6f Clarify a bugfix entry 2011-03-18 01:28:26 +01:00
Thomas Keller 5a7bf49cbb Well, I forgot the important stuff in the last commit, sigh. Fixes issue 633 for real now. 2011-03-18 01:05:25 +01:00
Thomas Keller a3dd1c45f3 Handle partial incomplete and line-ending munging diffs (resolves issue 633). 2011-03-18 00:55:02 +01:00
Thomas Keller be7725694e Let browsers properly render whitespace and expand the long line fix for unchanged and removed lines (fixes issue 623 again) 2011-03-17 23:23:28 +01:00
Thomas Keller 366d278182 Ignore "bad usage" error code in case `git tag` doesn't know of the `--contains` option. 2011-03-17 23:12:27 +01:00
Loïc d'Anterroches 5f008a14f5 ReFixed in an ugly way the non support of the git --contains option. 2011-03-17 09:28:43 +01:00
Loïc d'Anterroches 21a8c281ec Fixed in an ugly way the non support of the git --contains option. 2011-03-17 09:22:46 +01:00
Thomas Keller 51dde5766d Add a test case for issue 633. 2011-03-17 01:58:01 +01:00
Thomas Keller 61d7b4a58d Setup a basic PHPUnit test environment.
To run all available tests its enough to call

 $ phpunit

from the root workspace directory; the default phpunit configuration
resides in phpunit.xml. A bootstrap script sets some default paths
and can be extended later on with other useful stuff.

Each test class' path should mimic the name and path of the source
class, only that the test class gets an additional "Test" appended so
PHPUnit can find it automatically. The data directory can be used
in a flat manner; for tests that need test data a separate directory
containing these files should be added, and the directory should be
named after the test class itself.

The first test which uses the new infrastructure is a test for the
rewritten diff parser (closes issue 627).
2011-03-17 01:12:32 +01:00
Thomas Keller 19b35565a2 Fix a notice about variable pass by reference 2011-03-17 01:10:59 +01:00
Patrick Georgi baa88412b9 Rewrite the diff parser and reduce the memory footprint.
The diff parser code was rewritten for clarity and speed and now handles
a couple of ugly cornercases, like SVN's property change output and single
change chunks, much better. Since the path parsing was unified as well,
the SCM interface gained a new method `getPathStripLevel()` which determines
how many path components need to be shoven off a file name for the SCM
to form a valid path in the workspace (similar to patch(1)'s --strip option).
Fixes issue 627. Automated tests follow.
2011-03-16 23:50:41 +01:00
Thomas Keller 6fb9b72e22 Use git tag --contains REV for the IDF_Scm::inTags() implementation.
This works similar to git branch --contains REV; additionally give the
revision id and not some possibly symbolic name to the inBranches()
call when we determine the branches a commit is in.
2011-03-16 23:03:36 +01:00
Thomas Keller b75884c57e Use Pluf_SQL instead of raw SQL, the latter caused problems on installations with table prefixes. 2011-03-16 20:58:13 +01:00
Thomas Keller 603188f6ce For now the Chinese and Russian translations are far from being complete. 2011-03-16 10:07:24 +01:00
Thomas Keller 15442140cf Complete the NEWS with stuff from the tracker and format it as Markdown document. 2011-03-16 00:09:37 +01:00
Thomas Keller 9f877d4309 Merge branch 'release-1.1' of git://projects.ceondo.com/indefero into release-1.1 2011-03-15 22:58:23 +01:00
Thomas Keller 8631529268 Re-enable v1.0 URI compatibility wrt update feeds.
The additional filter token introduced 404's for bookmarked feeds;
now the old URLs are re-added and their actions forward the requests
to the new handlers.
Another small change removes a double assignment and puts the
"All Updates" link in the template on top to separate it clearly
from the other filters.

This commit closes issue 605.
2011-03-15 22:54:35 +01:00
Thomas Keller 96bc198b0f Added two more translators to AUTHORS and mark who is in charge for the
Czech translation.
2011-03-14 12:50:58 +01:00
Thomas Keller 146ffb5f4c Merge branch 'release-1.1' of projects.ceondo.com:indefero into release-1.1 2011-03-14 12:39:11 +01:00
Thomas Keller 867c3d3382 Start with a NEWS file and list the changes we've tracked so far since v1.0.
Left to do: Re-order by importance, write a short intro on top, continue with
the yet missing items from the tracker.
2011-03-14 01:21:42 +01:00
Thomas Keller 75b0f27fe2 Fix the transifex URL and re-wrap this section slightly. 2011-03-14 00:11:08 +01:00
Thomas Keller 4b001d8f03 Merge branch 'release-1.1' of git://projects.ceondo.com/indefero into release-1.1 2011-03-14 00:05:26 +01:00
Fernando Sayago Gil a7bec96a80 Update spain translation 2011-03-13 17:43:16 +01:00
William MARTIN a8706e38ca Update french translation 2011-03-13 17:40:48 +01:00
Thomas Keller 265fd41717 Make two translations a little shorter so they don't lead to a line wrap when printed in bold font. 2011-03-13 02:12:09 +01:00
Thomas Keller 67c23ffe24 The word was meant to be translated as noun, not as verb. 2011-03-13 02:10:18 +01:00
Thomas Keller e9a09889e4 Sort the AUTHORS list alphabetically; spelling fixes. 2011-03-13 02:02:40 +01:00
William MARTIN e6756a2072 Fix issue 633 : Unset variable ! 2011-03-11 14:27:37 +01:00
Thomas Keller f4050b8a76 Merge branch 'develop' of projects.ceondo.com:indefero into release-1.1 2011-03-11 11:42:10 +01:00
William MARTIN bb4fa7ca2f Fix issue 629 : Git commit view is missing the branch 2011-03-11 11:38:04 +01:00
William MARTIN 2648603f24 Update the Makefile
- po-pull merge transifex PO with local PO to quick fuzzy entry
- Add of po-stats
2011-03-10 14:17:39 +01:00
Thomas Keller b7a9a1c8fd Update pot file with the recent changes and translate the fuzzies
in the German translation.
2011-03-10 10:22:43 +01:00
William MARTIN d45566d692 Update language for French and Spain 2011-03-10 09:45:35 +01:00
Ciaran Gultnieks 4411086f29 First set of files with English text corrections (partially resolves
issue 631)
2011-03-10 09:23:01 +01:00
William MARTIN 0b3ce03036 Don't show an empty branch field in the commit view
It's a little hack for issue 629, but don't resolve it.
2011-03-09 22:09:32 +01:00
William MARTIN 027886737d Enable Spain and German in the supported language 2011-03-09 21:55:20 +01:00
William MARTIN 35f45015ea Update the spain translation, language is now supported at 100%
Thanks to Fernando Sayago Gil
2011-03-09 21:54:33 +01:00
Thomas Keller 618f412bed Retranslate a few fuzzies. 2011-03-09 14:38:47 +01:00
Thomas Keller 6ab9c754a5 Update the translations with the recent source and i18n changes from tx. 2011-03-09 13:57:06 +01:00
Thomas Keller c59332c8f8 Mark the header string for translation. 2011-03-09 13:54:16 +01:00
Thomas Keller 32d9d04b4b Merge branch 'release-1.1' of projects.ceondo.com:indefero into develop 2011-03-09 13:51:36 +01:00
William MARTIN 62d0fb6eee Fix missing installation for IDF_EmailAddress in the database 2011-03-09 13:46:58 +01:00
Patrick Georgi bc82ee24d8 Fix a MySQL-ism (closes issue 628) 2011-03-09 02:06:44 +01:00
Thomas Keller 6ab1f4a4f0 Fix some spelling mistakes (closes issue 441) 2011-03-09 02:06:27 +01:00
Patrick Georgi 3e6527bab3 Fix a MySQL-ism (closes issue 628) 2011-03-09 01:37:41 +01:00
Thomas Keller 9b7691c1ae Fix some spelling mistakes (closes issue 441) 2011-03-08 14:42:24 +01:00
William MARTIN c3cd494386 Add Project List API 2011-03-07 15:01:51 +01:00
William MARTIN fba5841bdc Merge branch 'develop' of projects.ceondo.com:indefero into develop 2011-03-04 15:18:21 +01:00
William MARTIN da7fc3e7e3 Fix issue 623
File with only one big line can create a very large row table
2011-03-04 15:18:11 +01:00
Thomas Keller 00ebe1633c Merge branch 'develop' of git://projects.ceondo.com/indefero into develop 2011-03-03 23:44:10 +01:00
Thomas Keller f63bfcb4f6 Raise PCRE's backtrack_limit for our regex callback usage to avoid
spurious errors on weird input (fixes issue 618).
2011-03-03 23:42:21 +01:00
Thomas Keller 177cf836b4 Stupid me, the condition needs to work on the count of the children, of course. 2011-03-03 23:41:56 +01:00
Patrick Georgi 04069871bb Fixes to bugs introduced by the multiple mail feature 2011-03-03 21:04:24 +01:00
William MARTIN 31469204e0 Merge branch 'develop' of projects.ceondo.com:indefero into develop 2011-03-03 15:44:01 +01:00
William MARTIN 9b148c8c4a Fix precondition for API Issue Create
One is supposed to always need auth to post a ticket.
2011-03-03 15:43:51 +01:00
Patrick Georgi 98f4eac82a Merge branch 'multiple-mails' into develop 2011-03-03 14:12:03 +01:00
Thomas Keller 29d966cdb3 Reformat slightly; hide the table of contents if there are less than two
jump marks.
2011-03-01 00:21:05 +01:00
Thomas Keller 23d2bd552c Merge branch 'develop' of git://projects.ceondo.com/indefero into develop 2011-03-01 00:02:17 +01:00
Thomas Keller 41cfbbd0d9 Let the table of contents not take more than 33% of the available space;
improve the CSS a bit by making the font a little smaller and by introducing
a margin between every line. Partially closes issue 618.
2011-03-01 00:01:03 +01:00
William MARTIN cc89a7e6f8 Add support of renamed file for IDF_Scm_Git::getchanges() 2011-02-25 11:10:10 +01:00
William MARTIN c486fe98fb Merge branch 'develop' of projects.ceondo.com:indefero into develop 2011-02-24 15:22:00 +01:00
William MARTIN f0ac256ff6 Implementation of IDF_Scm_Git::getChanges() 2011-02-24 15:21:51 +01:00
Thomas Keller e4b3adb2f5 Merge branch 'develop' of projects.ceondo.com:indefero into develop 2011-02-24 13:39:58 +01:00
Thomas Keller 58a5bc46d9 Temporarily disable the change view and diff download for merge
revisions until issue 581 has been fixed properly.
2011-02-24 13:38:42 +01:00
William MARTIN 6e5c3a551d Pluf migrate script need Console_Getopt pear package. 2011-02-24 09:41:58 +01:00
William MARTIN 52f8261d8c Finalize French translation 2011-02-24 09:10:44 +01:00
William MARTIN 721c385993 Merge branch 'develop' of projects.ceondo.com:indefero into develop 2011-02-24 08:59:23 +01:00
William MARTIN 9c80de19d7 Fix url in the tag cloud 2011-02-24 08:58:43 +01:00
Thomas Keller 4ffd11caf5 Add William and me to AUTHORS 2011-02-23 23:59:28 +01:00
Thomas Keller f2c4faf054 * update pot and po files with latest strings from source and tx
* finalize German translation (again)
2011-02-23 23:49:19 +01:00
Thomas Keller bc54b663e0 Improve the english a bit and make the previous error message cleaner 2011-02-23 23:04:47 +01:00
William MARTIN 6f1bb309d4 Apply the UI enhancement of issue tags cloud to wiki and download part too. 2011-02-23 22:35:43 +01:00
William MARTIN cdedaa4604 Fix issue 591
Improve render of issue tag list
2011-02-23 20:20:02 +01:00
William MARTIN 2130b327df Fix issue 616
Patch from Patrick Georgi
2011-02-23 18:24:49 +01:00
William MARTIN 3e238bea0b Enhancement of the invalid revision handler
Show the list of available branch
2011-02-23 18:12:29 +01:00
William MARTIN 266c297632 Merge branch 'develop' of projects.ceondo.com:indefero into develop 2011-02-23 16:23:34 +01:00
William MARTIN 4477b07bc6 Rewrite a string to better handle i18n 2011-02-23 16:22:27 +01:00
Thomas Keller 74b44186d2 Update pot file and translations from source and transifex updates 2011-02-23 16:06:40 +01:00
William MARTIN c2bf1bac38 Remove echo for printf
Check if 'src/IDF/conf/path.php' exist before use it
2011-02-23 15:36:15 +01:00
William MARTIN c279313048 Merge branch 'master' into develop 2011-02-23 14:57:59 +01:00
William MARTIN 0301ba0336 Merge branch 'master' into develop 2011-02-23 14:51:04 +01:00
William MARTIN 5e6d61b3a7 Add more statistics on the projects list page 2011-02-23 14:29:01 +01:00
William MARTIN 4e00051a10 Login form enhancement 2011-02-23 13:31:45 +01:00
Patrick Georgi 38e6e4f8d3 Use all registered email addresses to map Scm users to IDF users. 2011-02-21 10:57:36 +01:00
Patrick Georgi dfa223b39e Manage addition of secondary emails 2011-02-21 10:57:36 +01:00
Patrick Georgi 0a8d771c11 Add UI for adding secondary email addresses 2011-02-21 10:57:36 +01:00
Patrick Georgi 5afd073ff3 If secondary mails exist, print them in account settings, and allow to delete them 2011-02-21 10:57:36 +01:00
Patrick Georgi 46fda14e08 Make sure no secondary email addresses are used for registration or when changing email address 2011-02-21 10:57:36 +01:00
Patrick Georgi bbf9ef8b3d Store secondary email addresses.
Create a place to store additional email addresses and
provide an API to access them
2011-02-21 10:57:36 +01:00
377 changed files with 60203 additions and 19020 deletions

1
.gitattributes vendored 100644
View File

@ -0,0 +1 @@
src/IDF/version.php export-subst

21
.gitignore vendored
View File

@ -1,11 +1,20 @@
*~
tmp
.buildpath
.externalToolBuilders
.project
.settings
.tx/config
attachments
backups
indefero-*.zip
src/IDF/conf/idf.php
src/IDF/conf/idf.test.php
www/test.php
www/media/upload
src/IDF/gettexttemplates
indefero-*.zip
src/IDF/conf/path.php
.tx/config
src/IDF/gettexttemplates
src/IDF/locale/idf.pot.bak
test/config.php
test/test.db
test/tmp
tmp
www/media/upload
www/test.php

64
AUTHORS
View File

@ -1,30 +1,52 @@
InDefero was originally created during summer 2008
InDefero was originally created during summer 2008
by Loïc d'Anterroches with the support of Céondo Ltd.
Much appreciated contributors:
Much appreciated contributors (in alphabetical order):
Nicolas Lassalle <http://www.beroot.org/> - Subversion support
bohwaz <http://bohwaz.net/>
Benjamin Jorand <benjamin.jorand@gmail.com> - Mercurial support
Baptiste Michaud <bactisme@gmail.com> - Subversion synchronization
Julien Issler
Adrien Bustany <madcat@mymadcat.com>
Andrew Nguyen <andrew-git-indefero@na-consulting.net>
Baptiste Durand-Bret <bathizte@ozazar.org>
Baptiste Michaud <bactisme@gmail.com> - Subversion sync
Benjamin Danon <benjamin@sphax3d.org> - French translation
Benjamin Jorand <benjamin.jorand@gmail.com> - Mercurial support
Brenda Wallace <shiny@cpan.org>
Brian Armstrong <brianar>
Charles Melbye <charlie@yourwiki.net>
Ciaran Gultnieks <ciaran@ciarang.com>
Daniel Steudler <steudlerdaniel@gmail.com>
David Feeney <davidf>
Denis Kot <denis.kot@gmail.com> - Russian translation
Dmitry Dulepov <dmitryd>
Fernando Sayago Gil <mikados.mikados@gmail.com> - Spanish translation
Gert van Valkenhoef <gertvv>
Jakub Viták <mainiak@gmail.com> - Czech translation
Janez Troha <http://www.dz0ny.info> - Slovenian translation
Jean-Philippe Fleury <jpfleury>
Jerry <lxb429@gmail.com> - Chinese translation
Jonathan Aillet <jonathan.aillet@gmail.com> - French translation
Julien Issler <julien@issler.net>
Litew <litew9@gmail.com> - Russian translation
Ludovic Bellière <xrogaan>
Manuel Eidenberger <eidenberger@gmail.com>
Ciaran Gultnieks
Matthew Dawson <mjd>
Matías Halles <matias@halles.cl>
Mehdi Kabab <http://pioupioum.fr/>
Sindre R. Myren
Nicolas Lassalle <nicolas@beroot.org> - Subversion support
Ozan <uobasar@gmail.com> - Turkish translation
Patrick Georgi <patrick.georgi@coresystems.de>
Adrien Bustany
Charles Melbye
Baptiste Durand-Bret
Andrew Nguyen
David Feeney
Denis Kot <denis.kot@gmail.com>
Samuel Suther
Ludovic Bellière
Brian Armstrong
Raphaël Emourgeon
Jakub Viták
Vladimir Solomatin
Pedro Kiefer <pedro@kiefer.com.br> - Brazilian Portuguese translation
Raphaël Emourgeon <raphael>
Samuel Suther <info@suther.de> - German translation
Simon Holywell <treffynnon@php.net>
Sindre R. Myren <sindrero@stud.ntnu.no>
Stewart Platt <stew@futurete.ch>
Stéphane Baron <sbaron>
Thomas Keller <me@thomaskeller.biz> - Monotone support
Victor Quinault <victor.quinault@gmail.com> - French translation
Vladimir Solomatin <slash>
William Martin <william.martin@lcpc.fr>
Xavier Brochard <xavier@alternatif.org>
bohwaz <http://bohwaz.net/>
And all the nice users who spent time reporting issues and promoting
the project. The project could not live without them.

View File

@ -104,12 +104,13 @@ without first talking to us.
## I am a translator
We currently use (transifex)[http://trac.transifex.org] to help our
users to translate indefero. You don't have to use it, but it's an
easy way to do the job. You can visit the indefero page at transifex
here : http://www.transifex.net/projects/p/indefero/c/indefero/
We currently use [transifex](http://trac.transifex.org) to help our
users translate indefero. You don't have to use it, but it's an easy
way to do the job. You can visit the indefero page at transifex here:
http://www.transifex.net/projects/p/indefero/
Please understand that your changes will not be commited instantly,
but are sent to the maintainers e-mails before. Then, your changes
will not be in the main repository until da-loic push the changes. In
that way, try to do big changes with less submissions.
will not be in the main repository until the maintainer pushs the
changes. In that way, try to do big changes with less submissions.

View File

@ -4,6 +4,18 @@ The installation of InDefero is composed of 2 parts, first the
installation of the [Pluf framework](http://www.pluf.org) and second,
the installation of InDefero by itself.
## PHP modules for indefero
Indefero needs additional PHP modules to function correctly, namely
- gd (for graphic operations)
- zip (for upload archive processing)
The package names of these modules might vary between distributions,
for Debian they are
$ apt-get install php5-gd php5-zip
## Recommended Layout of the Files
If your server document root is in `/var/www` a good thing is to keep
@ -37,6 +49,7 @@ docroot.
$ sudo pear upgrade-all
$ sudo pear install --alldeps Mail
$ sudo pear install --alldeps Mail_mime
$ sudo pear install --alldeps Console_Getopt
If you already have some of the PEAR packages installed with your
distribution, the `Mail` package is often not up-to-date,
@ -125,6 +138,7 @@ The documentation is available in the `doc` folder.
* Subversion: `doc/syncsvn.mdtext`.
* Mercurial: `doc/syncmercurial.mdtext`.
* Git: `doc/syncgit.mdtext`.
* Monotone: `doc/syncmonotone.mdtext`
## For the Apache Webserver Users
@ -222,4 +236,4 @@ functions. You need to prevent the overload as it does not make sense
anyway (magic in the background is bad!).
See the [corresponding ticket][reglink].
[reglink]: http://projects.ceondo.com/p/indefero/issues/481/
[reglink]: http://projects.ceondo.com/p/indefero/issues/481/

134
Makefile
View File

@ -22,46 +22,63 @@
# sudo apt-get install python-setuptools
# sudo easy_install -U transifex-client
PLUF_PATH=$(shell php -r "require_once('src/IDF/conf/path.php'); echo PLUF_PATH;")
all help:
@echo "Rules for generate tarball :"
.PHONY: help
help:
@printf "Rules for generating distributable files :\n"
@for b in `git branch | sed "s/^. //g"`; do \
echo -e "\t"$$b"_tarball - Generate a zip archive of the "$$b" branch."; \
printf "\t"$$b"-zipfile - Generate a zip archive of the "$$b" branch.\n"; \
done
@echo -e "\nRules for internationnalization :";
@echo -e "\tpot-update - Update the POT file from HTML template and PHP source, then merge it with PO file"
@echo -e "\tpot-push - Send the POT file on transifex server"
@echo -e "\tpo-update - Merge POT file into PO file. POT is not regenerated."
@echo -e "\tpo-push - Send the all PO file on transifex server"
@echo -e "\tpo-pull - Get all PO file from transifex server"
@printf "\nRules for internationalization :\n";
@printf "\tpot-update - Update the POT file from HTML templates and PHP sources, then merge it with PO file.\n"
@printf "\tpot-push - Send the POT file to the transifex server.\n"
@printf "\tpo-update - Merge the POT file into the PO file. The POT is not regenerated.\n"
@printf "\tpo-push - Send the all PO files to the transifex server.\n"
@printf "\tpo-pull - Get all PO files from the transifex server.\n"
@printf "\tpo-stats - Show translation statistics of all PO files.\n"
@printf "\nRules for managing the database :\n";
@printf "\tdb-install - Install the database schema.\n"
@printf "\tdb-update - Update the database schema.\n"
@printf "\tdb-backup-foo - Create a named backup 'foo' with data from the current database.\n"
@printf "\tdb-restore-foo - Restore schema and the data from a named backup 'foo' to an empty database.\n"
#
# Internationnalization rule, POT & PO file manipulation
#
# Internationalization rule, POT & PO file manipulation
#
.PHONY: pluf_path
pluf_path:
ifeq (src/IDF/conf/path.php, $(wildcard src/IDF/conf/path.php))
PLUF_PATH=$(shell php -r "require_once('src/IDF/conf/path.php'); echo PLUF_PATH;")
else
@printf "File 'src/IDF/conf/path.php' don't exist. Please configure it !\n"
@exit 1
endif
.PHONY: pot-update po-update
pot-update:
pot-update: pluf_path
# Backup pot file
@if [ -e src/IDF/locale/idf.pot ]; then \
mv -f src/IDF/locale/idf.pot src/IDF/locale/idf.pot.bak; \
fi
touch src/IDF/locale/idf.pot;
# Extract string
@cd src; php $(PLUF_PATH)/extracttemplates.php IDF/conf/idf.php IDF/gettexttemplates
@cd src; php "$(PLUF_PATH)/extracttemplates.php" IDF/conf/idf.php IDF/gettexttemplates
@cd src; for phpfile in `find . -iname "*.php"`; do \
echo "Parsing file : "$$phpfile; \
xgettext -o idf.pot -p ./IDF/locale/ --from-code=UTF-8 -j --keyword --keyword=__ --keyword=_n:1,2 -L PHP $$phpfile ; \
printf "Parsing file : "$$phpfile"\n"; \
xgettext -o idf.pot -p ./IDF/locale/ --from-code=UTF-8 -j \
--keyword --keyword=__ --keyword=_n:1,2 -L PHP "$$phpfile" ; \
done
# Remove tmp folder
rm -Rf src/IDF/gettexttemplates
# Update PO
@make po-update
po-update:
po-update: pluf_path
@for pofile in `ls src/IDF/locale/*/idf.po`; do \
echo "Updating file : "$$pofile; \
msgmerge -v -U $$pofile src/IDF/locale/idf.pot; \
echo ; \
printf "Updating file : "$$pofile"\n"; \
msgmerge -v -U "$$pofile" src/IDF/locale/idf.pot; \
printf "\n"; \
done
#
@ -72,22 +89,22 @@ check-tx-config:
@if [ ! -e .tx/config ]; then \
mkdir -p .tx; \
touch .tx/config; \
echo "[main]" >> .tx/config; \
echo "host = http://www.transifex.net" >> .tx/config; \
echo "" >> .tx/config; \
echo "[indefero.idfpot]" >> .tx/config; \
echo "file_filter = src/IDF/locale/<lang>/idf.po" >> .tx/config; \
echo "source_file = src/IDF/locale/idf.pot" >> .tx/config; \
echo "source_lang = en" >> .tx/config; \
printf "[main]\n" >> .tx/config; \
printf "host = http://www.transifex.net\n" >> .tx/config; \
printf "\n" >> .tx/config; \
printf "[indefero.idfpot]\n" >> .tx/config; \
printf "file_filter = src/IDF/locale/<lang>/idf.po\n" >> .tx/config; \
printf "source_file = src/IDF/locale/idf.pot\n" >> .tx/config; \
printf "source_lang = en\n" >> .tx/config; \
fi
@if [ ! -e $(HOME)/.transifexrc ]; then \
@if [ ! -e $(HOME)/.transifexrc ]; then \
touch $(HOME)/.transifexrc; \
echo "[http://www.transifex.net]" >> $(HOME)/.transifexrc; \
echo "username = " >> $(HOME)/.transifexrc; \
echo "token = " >> $(HOME)/.transifexrc; \
echo "password = " >> $(HOME)/.transifexrc; \
echo "hostname = http://www.transifex.net" >> $(HOME)/.transifexrc; \
echo "You must edit the file ~/.transifexrc to setup your transifex account (login & password) !"; \
printf "[http://www.transifex.net]\n" >> $(HOME)/.transifexrc; \
printf "username = \n" >> $(HOME)/.transifexrc; \
printf "token = \n" >> $(HOME)/.transifexrc; \
printf "password = \n" >> $(HOME)/.transifexrc; \
printf "hostname = http://www.transifex.net\n" >> $(HOME)/.transifexrc; \
printf "You must edit the file ~/.transifexrc to setup your transifex account (login & password) !\n"; \
exit 1; \
fi
@ -98,13 +115,52 @@ po-push: check-tx-config
@tx push -t
po-pull: check-tx-config
# Save PO
@for pofile in `ls src/IDF/locale/*/idf.po`; do \
cp $$pofile $$pofile".save"; \
done
# Get new one
@tx pull -a
# Merge Transifex PO into local PO (so fuzzy entry is correctly saved)
@for pofile in `ls src/IDF/locale/*/idf.po`; do \
msgmerge -U $$pofile".save" $$pofile; \
rm -f $$pofile; \
mv $$pofile".save" $$pofile; \
done
po-stats:
@msgfmt --statistics -v src/IDF/locale/idf.pot
@for pofile in `ls src/IDF/locale/*/idf.po`; do \
msgfmt --statistics -v $$pofile; \
done
#
# Generic rule to build a tarball of indefero for a specified branch
# ex: make master_tarball
# make dev_tarball
# Generic rule to build a zipfile of indefero for a specified branch
# ex: make master_zipfile
# make develop_zipfile
#
%_tarball:
@git archive --format=zip --prefix="indefero/" $(@:_tarball=) > indefero-$(@:_tarball=)-`git log $(@:_tarball=) -n 1 --pretty=format:%H`.zip
%-zipfile:
@git archive --format=zip --prefix="indefero/" $* \
> indefero-$*-`git log $* -n 1 \
--pretty=format:%h`.zip
%-tarfile:
@git archive --format=tar --prefix="indefero/" $* \
> indefero-$*-`git log $* -n 1 \
--pretty=format:%h`.tar
db-install:
@cd src && php "$(PLUF_PATH)/migrate.php" --conf=IDF/conf/idf.php -a -d -i
db-update:
@cd src && php "$(PLUF_PATH)/migrate.php" --conf=IDF/conf/idf.php -a -d
db-backup-%:
@[ -e backups ] || mkdir backups
@cd src && php "$(PLUF_PATH)/migrate.php" --conf=IDF/conf/idf.php -a -b ../backups $*
@echo Files for named backup $* have been saved into backups/ directory.
db-restore-%:
@cd src && php "$(PLUF_PATH)/migrate.php" --conf=IDF/conf/idf.php -a -r ../backups $*
@echo Files for named backup $* have been restored from the backups/ directory.

328
NEWS.mdtext 100644
View File

@ -0,0 +1,328 @@
# InDefero 1.4 - xxx xxx xx xx:xx 2012 UTC
## New Features
- Indefero can now record the due date of an issue and lets
you filter and search by overdue issues (fixes issue 584,
thanks to Simon Holywell!)
# InDefero 1.3.3 - Sun Nov 18 22:54:00 UTC 2012
**ATTENTION**: InDefero needs Pluf [a45dc195](http://projects.ceondo.com/p/pluf/source/commit/a45dc195)
or newer to run properly!
## Bugfixes
- A long standing bug in the Mercurial plugin that lead to corruption
of boolean configuration values in the `hgrc` of the served repository
has been fixed (issue 523).
- If an anonymous or authenticated user had no access to any project in a
forge, all projects were listed for him (but still no one was actually
accessible). This has been fixed.
- Fixed a problem where the SyncGit plugin doesn't properly updates the
authorized_keys file when the public key data contained slashes (thanks
to Simon Gareste for the fix!)
- Under PostgreSQL indefero could not be set up because of a circular
foreign key dependency. This has been fixed (issue 800).
- Under PostgreSQL new projects could not be created due to a failing
foreign key relation. Adding project tags was not possible for a similar
reason. This has been fixed (issue 800, continued).
- If a project was created based on the settings of an existing project,
not all settings, like for example the new notification settings, have
been copied. This has been changed insofar that now all properties except
the project's URL, logo and individual SCM settings are copied by default.
- Wiki pages couldn't be properly saved with E_NOTICE enabled because
of a syntax error (fixes issue 808).
- Indefero now shows detected copies in git changesets.
- A user is no longer redirected to the Help page if he enters 'H' in the
password text field on the login page (fixes issue 821).
# InDefero 1.3.2 - Wed May 09 20:05 2012 UTC
## Bugfixes
- Fix two bugs in the project list view if no project
is visible to the user or available in the forge (issue 805)
# InDefero 1.3.1 - Sun May 06 20:32 2012 UTC
## Bugfixes
- Compatiblity fixes for PostgreSQL (issue 800)
- Fix TOC generation in wiki (issue 803)
- Make the display of large files and diffs faster (issue 804)
- Make the project list faster and its tag list more accurate by not
counting projects that are invisible to the current user
## Language and Translations
- French translation updated (thanks to Jonathan Aillet!)
# InDefero 1.3 - Sun Apr 15 21:10 2012 UTC
This new major release of Indefero is possible thanks to the sponsor of
[Scilab Enterprises](http://www.scilab-enterprises.com/).
Scilab Enterprises is proud to share with the Indefero community the new
changes which greatly improves the overall quality of the Indefero
forge.
**ATTENTION**: InDefero now requires a PHP 5.3 compatible setup! You also
need Pluf [4121ca4](http://projects.ceondo.com/p/pluf/source/commit/4121ca4)
or newer to properly run this version of Indefero!
## Changes
- Indefero's post-commit web hook now by default issues HTTP PUT instead of
HTTP POST requests and carries the authentication digest in the new
`Web-Hook-Hmac` header. The old behaviour can be re-enabled by setting the
`$cfg['webhook_processing']` flag to "compat", we urge you to change the
implementations of this web hook as this setting is likely to be removed
in future versions of Indefero.
- Indefero now needs PHP's zip module which is usually not enabled by default.
- Previously configured email notifications now have to be explicitely
activated in the project's administrative area.
## New Features
- It is now possible to upload and embed resources like images or text
files into wiki pages. If no preview for a resource's mime type is
available, than a download link is provided for it instead.
- The notification system has been overhauled; it is now possible to configure
what kind of user group, project administrators, members and / or additional
mail addresses are notified about updates in a certain section, such as
issues, downloads, reviews, and so on. We now also ensure that notification
emails for one object are uniquely identifyable to support a grouped view
in email clients that support that. (fixes issues 334, 452, 480, and 791)
- Indefero can now be configured to record activity metrics for all projects
in a forge. This needs a special cron job named `activitycron.php`
(under `scripts`) that is run on a regular basis. The metrics can be
fine-tuned via `activity_section_weights` and `activity_lookback` in
`idf.php` and the result is visible as green bar in the project list view.
- The forge's project list has been overhauled - its now possible to attach
labels on projects and to filter and order the project list by various
criteria. Additionally, projects can now get an external project URL
configured that is displayed as linkable icon right beside the project name
(if available)
- Forge administrators can furthermore configure an alternative entry page
for the forge that is displayed instead of the plain project list. This
page accepts standard Markdown syntax and has support for the new
`projectlist` macro that allows the (partial) inline rendering of the
known global project list.
- It is now also possible to configure a web hook that informs an external
URL about new and updated downloads for a specific project, similar to the
available post-commit web hook.
- One can now upload multiple files at once by using a special archive format
which Indefero processes in the background and for which individual upload
records are created.
## Bugfixes
- Indefero no longer confuses a non-owner of an issue with a notification that
a particular ticket has been opened and assigned to him (fixes issue 562)
- The diff view now renders properly in Firefox when a minimum font size
is configured or the user zooms the web page (fixes issue 773)
- Ensure that IDF does not break UTF-8 encoded strings when
shortening them for view rendering (issue 785)
- Two XSS holes in the issue and review details views are closed (fixes issue 793)
## Language and Translations
- Multiple fixes to English source strings (fixes issues 763, 766, and 772,
thanks to JP Fleury!)
- Updates to the French translation (thanks to Victor Quinault)
# InDefero 1.2 - Sun Nov 6 23:04:00 UTC 2011
ATTENTION: You need Pluf [46b7f251](http://projects.ceondo.com/p/pluf/source/commit/46b7f251)
or newer to properly run this version of Indefero!
## New Features
- Indefero's issue tracker can now bi-directionally link issues with variable,
configurable terms, such as "is related to", "is blocked by" or
"is duplicated by" (issue 638)
- When you search for issues, the results can further be refined by issue state
(open or closed) and label (partially implements issue 548)
- Source and diff views now make characters like line endings, tabs and other
"invisible" control characters visible on hover and cope with long lines much
better (issue 636)
- Mercurial source views now show parent revisions (if any) and detailed change
information
- Subversion source views now show detailed change information (issue 622)
- File download URLs now contain the file name rather than the upload id;
old links still work though (issues 559 and 686)
- monotone file and directory attributes are displayed in the tree and file view
(needs a monotone with an interface version of 13.1 or newer)
- The context area is now kept in view when a page scrolls down several pages
- A summary section has been added to the issue tracker with statistics about
open / closed issues, unresolved issues grouped by tags and owners
- The project list and title has gathered a customizable icon for each project
- The download section now provides MD5 checksums for uploaded files
- Wiki pages now come with a designated stylesheet for printer output (issue 713)
## Bugfixes
- Git's cron job doesn't erase manually added keys anymore (issue 247)
- The SVN interface acts more robust if an underlying repository has been
restructured (issues 364 and 721)
- monotone zip archive entries now all carry the revision date as mtime (issue 645)
- The timeline only now only displays filter options for items a user has
actually access to (issue 655)
- The log, tags and branches parsers for Mercurial are more robust now (issue 663)
- Several SSH public key parsing issues have been fixed and the check for existing,
uploaded keys has been improved (issue 679)
- Diff views now show empty context lines for git and hg again (issue 688)
- The SVN command line client no longer accidential tries to store the login
credentials we give him as arguments for the user executing the SVN command
- The usher section in the forge administration no longer displays a bogus
server enty in case no monotone server is configured in the connected
usher instance
- A timeout that popped up when Usher is restarted has been fixed (issue 695)
- The SyncMonotone plugin now cleans up partial artifacts it created during the
addition of a new project or monotone key, in case an error popped up in the
middle (issue 697)
- Indefero now sends the MD5 checksum as HTTP header when downloading a file from the
download area; additionally, a unneeded redirect has been removed (issue 716)
- Source links without a specific revision did not work due to a wrong regex
(issue 730)
- Avatar URL generation use correctly the configuration (issue 732)
- The SyncGit plugin no longer fails to remove a non-existing post-update hook
on repository creation (issue 752)
- When uploading a project logo, an existing uploaded file with the same name
no longer leads to an error, but is simple overwritten (fixes issue 740)
- The error detection and reporting in the SyncMonotone plugin has been improved
- The branch links users of the Subversion frontend get when they enter a wrong
revision are fixed; this list is now also only displayed (for any SCM) if
there are actually branches available in the repository
- If git's author name is not encoded in an UTF-8 compatible encoding, skip the
author lookup, as we have no information what the author string is actually
encoded in
- Indefero no longer displays an empty parents paragraph in the commit view for
root revisions of a git repository
- Indefero now only shows the tags of the closed and not the open issues in the
closed issues list
## Documentation
- The documentation on the setup of the monotone plugin has been improved.
## Translations
- The Russian translation has been enabled by default (thanks for all the great
work, Denis Kot and Litew!)
- Brazilian Portuguese translation started (thanks to Pedro Kiefer!)
- Turkish translation started (thanks to Ozan!)
# InDefero 1.1.2 - Thu May 26 07:42:25 2011 UTC
## Bugfixes
- Fix tags extraction from git repository (issue 675)
- Fix SSH validation method (issue 671)
- Fix malformed URL in the RSS (issue 666)
- Fix validateRevision call for Mercurial Scm (issue 657)
## Translations
- Missing word in French translation (issue 672)
- Update Spanish translation
# InDefero 1.1.1 - Mon Mar 28 15:52 2011 UTC
## Bugfixes
- Fix an incompatibility with Python 3.1 in gitserve.py (issue 554)
- Fix PHP error when the commit view shows a commit with changed binary files (issue 643)
- A migration problem prevented the preferences page being displayed properly (issues 644 and 653)
- Fix PHP error when trying to create Mercurial source archives (issue 648)
- Improve the French translation (issue 651)
- Registration page missed a link to password recovery that was mentioned in a form error (issue 652)
# InDefero 1.1 - Sun Mar 20 11:44 2011 UTC
## New Features
* _Version control_:
- Support for the monotone Version Control system (see [[InstallationScmMonotone]])
- Display detailed changeset information in the commit details (git, mtn) (issue 544)
- Show branch in the commit details (git, mtn, hg) (issue 450)
- Render branch and tag names in a popup and make them filterable (git, hg, mtn) (issue 601)
* _Issue tracking_:
- Forge-wide and per-project watch lists of starred issues (issue 589)
- Configure a default issue template for each project (issues 212 and 540)
- Pick default issue labels from the configured project settings (issue 556)
- Navigate to a preceding / following issue in the issue detail view
- Many new text syntaxes to auto-link revisions (see [[AutomaticLinks]], issue 569)
* _Documentation wiki_:
- Automatically create a table of contents on wiki pages (issue 350)
- Allow the usage of text labels for Wiki text links (issue 456)
* _Other_:
- Enhanced user profile page (issue 510)
- Manage multiple (commit) emails in the account settings (issues 136 and 500)
- Filter the timeline and its feed by item type (issue 543)
- Add multiple email addresses for project notifications (issue 372)
- Direct links to other projects via the new `Project List` dropdown
- InDefero gained a favicon (issue 594)
## Bugfixes
- Fix `Need SSH_ORIGINAL_COMMAND in environment` error for git sync (issue 198)
- Added an option to disable lengthy project size calculation in the forge (issue 403)
- Fix a problem when deleting an orphaned git repository (issue 467)
- Ignore XML parsing problems when trying to retrieve commit messages for svn (issues 469 and 518)
- Sort the project list by the display name of the project (issue 477)
- Project creation form now has a short description field as well (issue 479)
- Add more file extensions supported by our in-tree prettify version (issues 490 and 567)
- Improve the parsing of hg's log output (issues 507 and 508)
- Do not clean `<ins>` and `<del>` HTML markup from user input (issue 509)
- Improve HTML validation by switching from `strict` to `transitional` DOCTYPE (issue 511)
- Properly handle git commits without a changelog title (issue 520)
- Improve BSD compatibility in shell scripts (issue 526)
- Properly render inner whitespaces in viewed issue attachments (issue 528)
- Support for uploading SSH keys without optional comment (issue 531)
- Recognize irc: and git: protocols in Markdown renderer (issue 546)
- New config option `git_core_quotepath` to handle non-ASCII git file names (issue 553)
- Ensured that active views are rendered in the menu as such (issue 555)
- Add CSS for nested and mixed ordered and unordered lists (issue 557)
- Directories are now sorted before files in source tree views (issue 573)
- File attachments now have explicit view and download links in issue views (issue 575)
- Display anonymous access URL when user has no SSH key registered (issue 588)
- Improve the rendering of tag lists in issue views (issue 591)
- Improved error page when a commit or branch was not found (issue 609)
- Disable browser autocomplete of password fields in the account settings (issue 616)
- Improvements in the automatic linker parser (issue 618)
- The `createIssue` API method did not check the API authentication (issue 619)
- Reduce the memory footprint and compatibility of the internal diff parser (issues 627 and 633)
- Print the git branches and tags in bold which contain the currently displayed revision
## Documentation
- Document how to contribute to Indefero in `CONTRIBUTE.mdtext` (issue 486)
- Note possible problems with mbstring.func_overload in `INSTALL.mdtext` (issue 481)
- Improve links to Markdown documentation (issue 489)
- Explain purpose of `idf_strong_key_check` in `idf.php-dist` (issue 516)
## Translations
- Spanish translation added
- Started with a Simplified Chinese translation (issue 521)
- Started with a Russian translation
- Updates and fixes to the French translation (issue 574)
- Updates and fixes to the German translation
- English source language has been improved (issues 441, 478, and 631)
# InDefero 1.0 - Tue Apr 20 07:00 2010 UTC
First stable release.

View File

@ -25,7 +25,7 @@ If you install monotone from source (<http://monotone.ca/downloads.php>),
please follow the `INSTALL` document which comes with the software.
It contains detailed instructions, including all needed dependencies.
## Choose your indefero setup
## Choose your indefero (IDF) setup
The monotone plugin can be used in several different ways:
@ -112,14 +112,40 @@ The monotone plugin can be used in several different ways:
^D
$ chmod 600 usher.conf
**ATTENTION:** Do _not_ configure a default monotone server key in `usher.conf`,
otherwise the individual server key that IDF creates for each project is
not used and this could cause problems.
Your indefero www user needs later write access to `usher.conf` and
`projects/`. There are two ways of setting this up:
* Make the usher user the web user, for example via Apache's `suexec`
* Use acls, like this:
* Make the usher user the web user, for example via Apache's `suexec`.
This is however a bit clumsy.
* Preferred: Use Access Control Lists (ACLs), like this:
#
# Linux
#
$ setfacl -m u:www:rw usher.conf
$ setfacl -m d:u:www:rwx projects/
$ setfacl -m d:u:usher:rwx projects/
#
# FreeBSD
#
$ setfacl -m user:www:rw::allow usher.conf
$ setfacl -m user:www:rwxp:fd:allow projects/
$ setfacl -m user:usher:rwxp:fd:allow projects/
#
# Mac OS X
#
chmod +a '_www allow read,write' usher.conf
chmod +a '_www allow read,write,delete,add_file,add_subdirectory,file_inherit,directory_inherit' projects/
chmod +a 'usher allow read,write,delete,add_file,add_subdirectory,file_inherit,directory_inherit' projects/
In each example's last line, `usher` is the user which is executing
the usher instance. **It is very important to add this line, otherwise
usher won't be able to read and write into the initial file system
setup IDF creates!**
5. Wrap a daemonizer around usher, for example supervise from daemontools
(<http://cr.yp.to/damontools.html>):

View File

@ -0,0 +1,284 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="190.51302"
height="182.16527"
id="svg2"
version="1.1"
inkscape:version="0.47 r22583"
sodipodi:docname="external_link.svg"
inkscape:export-filename="/Users/tommyd/Entwicklung/Open Source/indefero/www/media/idf/img/external_link.png"
inkscape:export-xdpi="7.4108529"
inkscape:export-ydpi="7.4108529"
enable-background="new">
<defs
id="defs4">
<inkscape:path-effect
effect="skeletal"
id="path-effect4079"
is_visible="true"
pattern="M 0,5 10,10 10,0 z"
copytype="single_stretched"
prop_scale="1"
scale_y_rel="false"
spacing="0"
normal_offset="0"
tang_offset="0"
prop_units="false"
vertical_pattern="false"
fuse_tolerance="0" />
<inkscape:path-effect
effect="skeletal"
id="path-effect4071"
is_visible="true"
pattern="M 0,5 10,10 10,0 z"
copytype="single_stretched"
prop_scale="1"
scale_y_rel="false"
spacing="0"
normal_offset="0"
tang_offset="0"
prop_units="false"
vertical_pattern="false"
fuse_tolerance="0" />
<marker
inkscape:stockid="Arrow1Lend"
orient="auto"
refY="0"
refX="0"
id="Arrow1Lend"
style="overflow:visible">
<path
id="path3627"
d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;marker-start:none"
transform="matrix(-0.8,0,0,-0.8,-10,0)" />
</marker>
<inkscape:path-effect
effect="skeletal"
id="path-effect3619"
is_visible="true"
pattern="M 0,5 10,10 10,0 z"
copytype="single_stretched"
prop_scale="1"
scale_y_rel="false"
spacing="0"
normal_offset="0"
tang_offset="0"
prop_units="false"
vertical_pattern="false"
fuse_tolerance="0" />
<inkscape:path-effect
effect="skeletal"
id="path-effect3615"
is_visible="true"
pattern="M 0,5 10,10 10,0 z"
copytype="single_stretched"
prop_scale="1"
scale_y_rel="false"
spacing="0"
normal_offset="0"
tang_offset="0"
prop_units="false"
vertical_pattern="false"
fuse_tolerance="0" />
<inkscape:path-effect
effect="skeletal"
id="path-effect3611"
is_visible="true"
pattern="M 0,5 10,10 10,0 z"
copytype="single_stretched"
prop_scale="1"
scale_y_rel="false"
spacing="0"
normal_offset="0"
tang_offset="0"
prop_units="false"
vertical_pattern="false"
fuse_tolerance="0" />
<inkscape:path-effect
effect="skeletal"
id="path-effect3607"
is_visible="true"
pattern="M 0,5 10,10 10,0 z"
copytype="single_stretched"
prop_scale="1"
scale_y_rel="false"
spacing="0"
normal_offset="0"
tang_offset="0"
prop_units="false"
vertical_pattern="false"
fuse_tolerance="0" />
<inkscape:path-effect
effect="skeletal"
id="path-effect3603"
is_visible="true"
pattern="M 0,5 10,10 10,0 z"
copytype="single_stretched"
prop_scale="1"
scale_y_rel="false"
spacing="0"
normal_offset="0"
tang_offset="0"
prop_units="false"
vertical_pattern="false"
fuse_tolerance="0" />
<inkscape:path-effect
effect="skeletal"
id="path-effect3599"
is_visible="true"
pattern="M 0,5 10,10 10,0 z"
copytype="single_stretched"
prop_scale="1"
scale_y_rel="false"
spacing="0"
normal_offset="0"
tang_offset="0"
prop_units="false"
vertical_pattern="false"
fuse_tolerance="0" />
<inkscape:path-effect
effect="skeletal"
id="path-effect3595"
is_visible="true"
pattern="M 0,5 10,10 10,0 z"
copytype="single_stretched"
prop_scale="1"
scale_y_rel="false"
spacing="0"
normal_offset="0"
tang_offset="0"
prop_units="false"
vertical_pattern="false"
fuse_tolerance="0" />
<inkscape:perspective
sodipodi:type="inkscape:persp3d"
inkscape:vp_x="0 : 526.18109 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_z="744.09448 : 526.18109 : 1"
inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
id="perspective10" />
<inkscape:perspective
id="perspective4900"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" />
<filter
inkscape:collect="always"
id="filter4921"
x="-0.12982728"
width="1.2596545"
y="-0.092135489"
height="1.184271"
color-interpolation-filters="sRGB">
<feGaussianBlur
inkscape:collect="always"
stdDeviation="6.8004762"
id="feGaussianBlur4923" />
</filter>
<inkscape:perspective
id="perspective4933"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" />
<filter
color-interpolation-filters="sRGB"
inkscape:collect="always"
id="filter4921-3"
x="-0.12982728"
width="1.2596545"
y="-0.092135489"
height="1.184271">
<feGaussianBlur
inkscape:collect="always"
stdDeviation="6.8004762"
id="feGaussianBlur4923-8" />
</filter>
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="1"
inkscape:pageshadow="2"
inkscape:zoom="1.78"
inkscape:cx="138.94497"
inkscape:cy="111.09667"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="false"
inkscape:window-width="1389"
inkscape:window-height="803"
inkscape:window-x="47"
inkscape:window-y="0"
inkscape:window-maximized="0" />
<metadata
id="metadata7">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:groupmode="layer"
id="layer2"
inkscape:label="Ebene"
transform="translate(16.297732,13.906157)"
style="display:inline"
sodipodi:insensitive="true">
<g
id="g2818-7"
style="fill:#e6e6e6;fill-opacity:1;stroke:#a0a0a0;stroke-width:2.26057386;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;filter:url(#filter4921-3)"
transform="matrix(0.97722285,0,0,-0.85847241,-166.837,487.59193)">
<rect
ry="9.2957697"
rx="8.07693"
y="389.50504"
x="171.42857"
height="177.14285"
width="125.71429"
id="rect2816-9"
style="opacity:0.79710143;fill:#000000;fill-opacity:1;stroke:#a0a0a0;stroke-width:2.26057386;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
</g>
</g>
<g
inkscape:label="Ebene 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(-155.26623,-395.13431)"
style="display:inline;">
<rect
style="fill:#e6e6e6;fill-opacity:1;fill-rule:nonzero;stroke:#a0a0a0;stroke-width:2.41343927;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
id="rect4985"
width="129.92365"
height="152.95734"
x="168.88869"
y="407.28156"
rx="9.9356585"
ry="11.003931" />
<path
style="fill:#00000f;fill-opacity:0.94117647;stroke:none;stroke-width:2.17028474999999998;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
d="m 205.32036,460.1042 67.83031,0 0,-32.45771 71.54343,60.58773 -72.50161,61.39918 0,-33.26916 -66.75258,0 0,-56.26004"
id="path4081"
sodipodi:nodetypes="cccccccc" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 8.6 KiB

173
logo/no_logo.svg 100644
View File

@ -0,0 +1,173 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
sodipodi:docname="no_logo.svg"
inkscape:version="0.47 r22583"
id="svg2985"
height="32"
width="32"
version="1.1"
inkscape:export-filename="/Users/tommyd/Entwicklung/indefero/www/media/idf/img/no_logo.png"
inkscape:export-xdpi="89.989998"
inkscape:export-ydpi="89.989998">
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1440"
inkscape:window-height="852"
id="namedview9"
showgrid="false"
inkscape:zoom="16.0625"
inkscape:cx="8.5507561"
inkscape:cy="16.122403"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="0"
inkscape:current-layer="g2847"
showguides="true"
inkscape:guide-bbox="true">
<sodipodi:guide
orientation="1,0"
position="16,25.836575"
id="guide3752" />
<sodipodi:guide
orientation="0,1"
position="-18.677042,16"
id="guide3754" />
</sodipodi:namedview>
<defs
id="defs2987">
<inkscape:perspective
sodipodi:type="inkscape:persp3d"
inkscape:vp_x="0 : 16 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_z="32 : 16 : 1"
inkscape:persp3d-origin="16 : 10.666667 : 1"
id="perspective13" />
<inkscape:perspective
id="perspective2863"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" />
<inkscape:perspective
id="perspective3676"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" />
<inkscape:perspective
id="perspective3717"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" />
<filter
inkscape:collect="always"
id="filter3816"
x="-0.14434362"
width="1.2886872"
y="-0.11562817"
height="1.2312563">
<feGaussianBlur
inkscape:collect="always"
stdDeviation="1.1799243"
id="feGaussianBlur3818" />
</filter>
</defs>
<metadata
id="metadata2990">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:groupmode="layer"
id="layer2"
inkscape:label="shadow"
style="display:inline"
sodipodi:insensitive="true">
<g
transform="translate(0.44042901,0.78704792)"
id="g2847-8"
style="opacity:0.79710143;fill:#000000;stroke:#000000;stroke-opacity:1;filter:url(#filter3816)">
<g
id="g3838-0"
style="fill:#000000;stroke:#000000;stroke-opacity:1" />
<g
id="g2401-2"
transform="matrix(0.21219597,0,0,0.21219597,-70.751966,-27.73328)"
style="fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:2.4000001;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
inkscape:export-filename="/home/loa/Projects/indefero/logo/powered-by-indefero.png"
inkscape:export-xdpi="12.330909"
inkscape:export-ydpi="12.330909">
<path
id="path2383-4"
d="m 396.19089,173.14471 c -7.67621,0.80661 -14.40195,5.39406 -19.58101,10.89131 -7.23597,7.88004 -11.69742,18.07908 -13.32198,28.60362 -1.7236,11.28173 -0.25925,23.20635 5.07686,33.37271 3.78607,7.24384 9.53161,13.92339 17.29701,16.96772 3.86478,1.53937 8.98362,1.03284 11.67912,-2.41036 2.64357,-3.5671 2.69463,-8.234 2.85756,-12.48867 0.045,-7.61054 -0.54749,-15.25544 0.45618,-22.83193 0.87131,-9.50623 4.03944,-18.56751 6.71612,-27.66851 1.16242,-4.44333 2.25094,-9.02808 1.97499,-13.64988 -0.48817,-4.62476 -3.58059,-9.31042 -8.2964,-10.4067 -1.57489,-0.44882 -3.23412,-0.48948 -4.85845,-0.37931 z"
style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:2.4000001;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
inkscape:connector-curvature="0" />
<path
id="path2391-8"
d="m 433.14691,149.28687 c 7.2059,2.76589 12.51512,8.93778 16.09494,15.58815 4.94991,9.48434 6.61962,20.49058 5.46486,31.07695 -1.25505,11.34342 -5.75582,22.48271 -13.54134,30.92159 -5.53192,6.01709 -12.81048,10.98198 -21.09918,11.91276 -4.13154,0.4866 -8.94486,-1.32748 -10.65734,-5.35104 -1.63027,-4.12976 -0.4717,-8.65084 0.47212,-12.80269 1.92628,-7.36287 4.47721,-14.59393 5.4687,-22.17201 1.61875,-9.40784 0.90381,-18.98034 0.67386,-28.46402 0.0272,-4.59278 0.1624,-9.30303 1.62515,-13.69592 1.66851,-4.34082 5.86829,-8.06645 10.70716,-7.90484 1.63738,-0.0259 3.25061,0.36424 4.79107,0.89107 z"
style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:2.4000001;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
inkscape:connector-curvature="0" />
</g>
</g>
</g>
<g
inkscape:groupmode="layer"
id="layer3"
inkscape:label="logo"
style="display:inline">
<g
id="layer1"
transform="translate(-0.06540759,0.09444087)">
<g
id="g2847">
<g
id="g3838" />
<g
id="g2401"
transform="matrix(0.21219597,0,0,0.21219597,-70.751966,-27.73328)"
style="fill:#e6e6e6;fill-opacity:1;stroke:#a0a0a0;stroke-width:2.4000001;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
inkscape:export-filename="/home/loa/Projects/indefero/logo/powered-by-indefero.png"
inkscape:export-xdpi="12.330909"
inkscape:export-ydpi="12.330909">
<path
id="path2383"
d="m 396.19089,173.14471 c -7.67621,0.80661 -14.40195,5.39406 -19.58101,10.89131 -7.23597,7.88004 -11.69742,18.07908 -13.32198,28.60362 -1.7236,11.28173 -0.25925,23.20635 5.07686,33.37271 3.78607,7.24384 9.53161,13.92339 17.29701,16.96772 3.86478,1.53937 8.98362,1.03284 11.67912,-2.41036 2.64357,-3.5671 2.69463,-8.234 2.85756,-12.48867 0.045,-7.61054 -0.54749,-15.25544 0.45618,-22.83193 0.87131,-9.50623 4.03944,-18.56751 6.71612,-27.66851 1.16242,-4.44333 2.25094,-9.02808 1.97499,-13.64988 -0.48817,-4.62476 -3.58059,-9.31042 -8.2964,-10.4067 -1.57489,-0.44882 -3.23412,-0.48948 -4.85845,-0.37931 z"
style="fill:#e6e6e6;fill-opacity:1;fill-rule:nonzero;stroke:#a0a0a0;stroke-width:2.4000001;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
inkscape:connector-curvature="0" />
<path
id="path2391"
d="m 433.14691,149.28687 c 7.2059,2.76589 12.51512,8.93778 16.09494,15.58815 4.94991,9.48434 6.61962,20.49058 5.46486,31.07695 -1.25505,11.34342 -5.75582,22.48271 -13.54134,30.92159 -5.53192,6.01709 -12.81048,10.98198 -21.09918,11.91276 -4.13154,0.4866 -8.94486,-1.32748 -10.65734,-5.35104 -1.63027,-4.12976 -0.4717,-8.65084 0.47212,-12.80269 1.92628,-7.36287 4.47721,-14.59393 5.4687,-22.17201 1.61875,-9.40784 0.90381,-18.98034 0.67386,-28.46402 0.0272,-4.59278 0.1624,-9.30303 1.62515,-13.69592 1.66851,-4.34082 5.86829,-8.06645 10.70716,-7.90484 1.63738,-0.0259 3.25061,0.36424 4.79107,0.89107 z"
style="fill:#e6e6e6;fill-opacity:1;fill-rule:nonzero;stroke:#a0a0a0;stroke-width:2.4000001;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
inkscape:connector-curvature="0" />
</g>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 8.4 KiB

27
phpunit.xml 100644
View File

@ -0,0 +1,27 @@
<phpunit backupGlobals="true"
backupStaticAttributes="false"
bootstrap="test/bootstrap.php"
convertErrorsToExceptions="true"
convertNoticesToExceptions="true"
convertWarningsToExceptions="true"
strict="false"
verbose="true">
<testsuites>
<testsuite name="Everything">
<directory>test/IDF/</directory>
</testsuite>
</testsuites>
<filter>
<whitelist>
<directory suffix=".php">src/IDF</directory>
<exclude>
<directory suffix=".php">src/IDF/Tests</directory>
<directory suffix=".php">src/IDF/conf</directory>
<file>src/IDF/version.php</file>
</exclude>
</whitelist>
</filter>
</phpunit>

14
run-tests 100755
View File

@ -0,0 +1,14 @@
#!/usr/bin/env php
<?php
$xmlfile = dirname(__FILE__) .'/test/report.xml';
passthru('phpunit --coverage-clover='.escapeshellarg($xmlfile));
$xml = simplexml_load_string(file_get_contents($xmlfile));
unlink($xmlfile);
printf(
'>>> code coverage %s/%s (%s%%)'."\n",
$xml->project->metrics['coveredstatements'],
$xml->project->metrics['statements'],
round(($xml->project->metrics['coveredstatements']/(float)$xml->project->metrics['statements']) * 100.0, 2)
);

View File

@ -0,0 +1,48 @@
<?php
/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
# ***** BEGIN LICENSE BLOCK *****
# This file is part of InDefero, an open source project management application.
# Copyright (C) 2008-2011 Céondo Ltd and contributors.
#
# InDefero is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# InDefero is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#
# ***** END LICENSE BLOCK ***** */
/**
* This script recalculates the "project activity" for all of the
* forge's projects for the given date.
* If no date is given, yesterday's date is used.
*
* This script should run once a day. You can configure its behaviour
* with $cfg['activity_section_weights'] and $cfg['activity_lookback'].
*
* If the script runs more than once with the same date argument,
* previously recorded project activity values are replaced with the
* newly created ones.
*/
require dirname(__FILE__).'/../src/IDF/conf/path.php';
require 'Pluf.php';
Pluf::start(dirname(__FILE__).'/../src/IDF/conf/idf.php');
$date = new DateTime('yesterday');
if (count($_SERVER['argv']) > 1) {
$date = new DateTime($_SERVER['argv'][1]);
}
echo 'recalculating project activity for '.$date->format('Y-m-d')."\n";
IDF_ActivityTaxonomy::recalculateTaxnomies($date);

View File

@ -3,7 +3,7 @@
/*
# ***** BEGIN LICENSE BLOCK *****
# This file is part of InDefero, an open source project management application.
# Copyright (C) 2008 Céondo Ltd and contributors.
# Copyright (C) 2008-2011 Céondo Ltd and contributors.
#
# InDefero is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by

View File

@ -3,7 +3,7 @@
/*
# ***** BEGIN LICENSE BLOCK *****
# This file is part of InDefero, an open source project management application.
# Copyright (C) 2008-2010 Céondo Ltd and contributors.
# Copyright (C) 2008-2011 Céondo Ltd and contributors.
#
# InDefero is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by

View File

@ -3,7 +3,7 @@
/*
# ***** BEGIN LICENSE BLOCK *****
# This file is part of InDefero, an open source project management application.
# Copyright (C) 2008 Céondo Ltd and contributors.
# Copyright (C) 2008-2011 Céondo Ltd and contributors.
#
# InDefero is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by

View File

@ -1,9 +1,9 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
#
# ***** BEGIN LICENSE BLOCK *****
# This file is part of InDefero, an open source project management application.
# Copyright (C) 2008 Céondo Ltd and contributors.
# Copyright (C) 2008-2011 Céondo Ltd and contributors.
#
# InDefero is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@ -23,14 +23,17 @@
import os
import sys
import commands
import traceback
import subprocess
SCRIPTDIR = os.path.abspath(__file__).rsplit(os.path.sep, 1)[0]
GITSERVEPHP = '%s/gitserve.php' % SCRIPTDIR
process = subprocess.Popen(['php', GITSERVEPHP, sys.argv[1]],
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
output = str.encode("\n").join(process.communicate()).strip()
status = process.wait()
n = len("/gitserve.py")
GITSERVEPHP = '%s/gitserve.php' % traceback.extract_stack(limit=1)[0][0][0:-n]
status, output = commands.getstatusoutput('php %s %s' % (GITSERVEPHP, sys.argv[1]))
if status == 0:
os.execvp('git', ['git', 'shell', '-c', output.strip()])
else:
sys.stderr.write("%s\n" % output)
sys.stderr.write("%s\n" % output.strip())
sys.exit(1)

View File

@ -4,7 +4,7 @@
/*
# ***** BEGIN LICENSE BLOCK *****
# This file is part of InDefero, an open source project management application.
# Copyright (C) 2008-2010 Céondo Ltd and contributors.
# Copyright (C) 2008-2011 Céondo Ltd and contributors.
#
# InDefero is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by

View File

@ -3,7 +3,7 @@
/*
# ***** BEGIN LICENSE BLOCK *****
# This file is part of InDefero, an open source project management application.
# Copyright (C) 2008-2010 Céondo Ltd and contributors.
# Copyright (C) 2008-2011 Céondo Ltd and contributors.
#
# InDefero is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by

View File

@ -3,7 +3,7 @@
/*
# ***** BEGIN LICENSE BLOCK *****
# This file is part of InDefero, an open source project management application.
# Copyright (C) 2008 Céondo Ltd and contributors.
# Copyright (C) 2008-2011 Céondo Ltd and contributors.
#
# InDefero is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by

View File

@ -3,7 +3,7 @@
/*
# ***** BEGIN LICENSE BLOCK *****
# This file is part of InDefero, an open source project management application.
# Copyright (C) 2008-2010 Céondo Ltd and contributors.
# Copyright (C) 2008-2011 Céondo Ltd and contributors.
#
# InDefero is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by

View File

@ -3,7 +3,7 @@
/*
# ***** BEGIN LICENSE BLOCK *****
# This file is part of InDefero, an open source project management application.
# Copyright (C) 2008-2010 Céondo Ltd and contributors.
# Copyright (C) 2008-2011 Céondo Ltd and contributors.
#
# InDefero is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by

View File

@ -0,0 +1,165 @@
<?php
/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
# ***** BEGIN LICENSE BLOCK *****
# This file is part of InDefero, an open source project management application.
# Copyright (C) 2008-2011 Céondo Ltd and contributors.
#
# InDefero is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# InDefero is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#
# ***** END LICENSE BLOCK ***** */
/**
* Class that calculates the activity value for all projects on a
* specific date and time.
*
* We do this by counting adds or updates of database objects in
* the particular section (according to the timeline) and relate this
* value to the overall activity of a section in the forge.
*
* To illustrate the behaviour, a simple example could be a forge with
* only two projects that both have only issue tracking enabled.
* The first project created or updated 10 tickets during the past period,
* the other 20. The activity index for the first should therefor be
* calculated as 0.33 and the second as 0.66.
* Note that this simple example doesn't take activity in other
* sections into account, so the the total activity of all projects
* for a certain time period might add up to more than 1.0.
*
* @author tommyd
*/
class IDF_ActivityTaxonomy
{
public static function recalculateTaxnomies(DateTime $date)
{
$sectionWeights = Pluf::f('activity_section_weights', null);
$lookback = Pluf::f('activity_lookback', null);
if ($sectionWeights === null || $lookback === null) {
throw new LogicException('activity configuration is missing in idf.php');
}
//
// query and normalize the section weights
//
$allWeights = array_sum($sectionWeights);
if ($allWeights == 0) {
throw new LogicException('the sum of all "activity_section_weights" must not be 0');
}
foreach ($sectionWeights as $section => $weight) {
$sectionWeights[$section] = $weight / (float) $allWeights;
}
//
// determine the date boundaries
//
if ($lookback < 1) {
throw new LogicException('lookback must be greater or equal to 1');
}
$dateCopy = new DateTime();
$dateCopy->setTimestamp($date->getTimestamp());
$dateBoundaries = array(
$dateCopy->format('Y-m-d 23:59:59'),
$dateCopy->sub(new DateInterval('P'.$lookback.'D'))->format('Y-m-d 00:00:00')
);
//
// now recalculate the values for all projects
//
$projects = Pluf::factory('IDF_Project')->getList();
foreach ($projects as $project) {
self::recalculateTaxonomy($date, $project, $dateBoundaries, $sectionWeights);
}
}
private static function recalculateTaxonomy(DateTime $date, IDF_Project $project, array $dateBoundaries, array $sectionWeights)
{
$conf = new IDF_Conf();
$conf->setProject($project);
$sectionClasses = array(
'source' => array('IDF_Commit'),
'issues' => array('IDF_Issue'),
'wiki' => array('IDF_Wiki_Page', 'IDF_Wiki_Resource'),
'review' => array('IDF_Review'),
'downloads' => array('IDF_Upload')
);
$value = 0;
foreach ($sectionWeights as $section => $weight) {
// skip closed / non-existant sections
if ($conf->getVal($section.'_access_rights') === 'none')
continue;
if (!array_key_exists($section, $sectionClasses))
continue;
$sectionValue = self::calculateActivityValue(
$dateBoundaries, $sectionClasses[$section], $project->id);
$value = ((1 - $weight) * $value) + ($weight * $sectionValue);
}
echo "project {$project->name} has an activity value of $value\n";
$sql = new Pluf_SQL('project=%s AND date=%s', array($project->id, $date->format('Y-m-d')));
$activity = Pluf::factory('IDF_ProjectActivity')->getOne(array('filter' => $sql->gen()));
if ($activity == null) {
$activity = new IDF_ProjectActivity();
$activity->project = $project;
$activity->date = $date->format('Y-m-d');
$activity->value = $value;
$activity->create();
} else {
$activity->value = $value;
$activity->update();
}
}
private static function calculateActivityValue(array $dateBoundaries, array $classes, $projectId)
{
$allCount = self::countActivityFor($dateBoundaries, $classes);
if ($allCount == 0) return 0;
$prjCount = self::countActivityFor($dateBoundaries, $classes, $projectId);
return $prjCount / (float) $allCount;
}
private static function countActivityFor(array $dateBoundaries, array $classes, $projectId = null)
{
static $cache = array();
$argIdent = md5(serialize(func_get_args()));
if (array_key_exists($argIdent, $cache)) {
return $cache[$argIdent];
}
$cache[$argIdent] = 0;
list($higher, $lower) = $dateBoundaries;
$db = Pluf::db();
$classes_esc = array();
foreach ($classes as $class) {
$classes_esc[] = $db->esc($class);
}
$sql = new Pluf_SQL('model_class IN ('.implode(',', $classes_esc).') '.
'AND creation_dtime >= %s AND creation_dtime <= %s',
array($lower, $higher));
if ($projectId !== null) {
$sql->SAnd(new Pluf_SQL('project=%s', array($projectId)));
}
$cache[$argIdent] = Pluf::factory('IDF_Timeline')->getCount(array('filter' => $sql->gen()));
return $cache[$argIdent];
}
}

View File

@ -3,7 +3,7 @@
/*
# ***** BEGIN LICENSE BLOCK *****
# This file is part of InDefero, an open source project management application.
# Copyright (C) 2008 Céondo Ltd and contributors.
# Copyright (C) 2008-2011 Céondo Ltd and contributors.
#
# InDefero is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@ -235,7 +235,7 @@ class IDF_Commit extends Pluf_Model
</tr>
<tr class="extra">
<td colspan="2">
<div class="helptext right">'.sprintf(__('Commit&nbsp;%s, by %s'), '<a href="'.$url.'" class="mono">'.$this->scm_id.'</a>', $user).'</div></td></tr>';
<div class="helptext right">'.sprintf(__('Commit %1$s, by %2$s'), '<a href="'.$url.'" class="mono">'.$this->scm_id.'</a>', $user).'</div></td></tr>';
return Pluf_Template::markSafe($out);
}
@ -287,6 +287,12 @@ class IDF_Commit extends Pluf_Model
$url = str_replace(array('%p', '%r'),
array($project->shortname, $this->scm_id),
$conf->getVal('webhook_url', ''));
// trigger a POST instead of the standard PUT if we're asked for
$method = 'PUT';
if (Pluf::f('webhook_processing', '') === 'compat') {
$method = 'POST';
}
$payload = array('to_send' => array(
'project' => $project->shortname,
'rev' => $this->scm_id,
@ -297,41 +303,51 @@ class IDF_Commit extends Pluf_Model
'creation_date' => $this->creation_dtime,
),
'project_id' => $project->id,
'authkey' => $project->getPostCommitHookKey(),
'authkey' => $project->getWebHookKey(),
'url' => $url,
'method' => $method,
);
$item = new IDF_Queue();
$item->type = 'new_commit';
$item->payload = $payload;
$item->create();
if ('' == $conf->getVal('source_notification_email', '')) {
return;
}
$current_locale = Pluf_Translation::getLocale();
$langs = Pluf::f('languages', array('en'));
Pluf_Translation::loadSetLocale($langs[0]);
$context = new Pluf_Template_Context(
array(
'c' => $this,
'project' => $this->get_project(),
'url_base' => Pluf::f('url_base'),
)
);
$tmpl = new Pluf_Template('idf/source/commit-created-email.txt');
$text_email = $tmpl->render($context);
$addresses = explode(',', $conf->getVal('source_notification_email'));
foreach ($addresses as $address) {
$email = new Pluf_Mail(Pluf::f('from_email'),
$from_email = Pluf::f('from_email');
$recipients = $project->getNotificationRecipientsForTab('source');
foreach ($recipients as $address => $language) {
if (!empty($this->author) && $this->author->email === $address) {
continue;
}
Pluf_Translation::loadSetLocale($language);
$context = new Pluf_Template_Context(array(
'commit' => $this,
'project' => $project,
'url_base' => Pluf::f('url_base'),
));
// commits are usually not updated, therefor we do not
// distinguish between create and update here
$tplfile = 'idf/source/commit-created-email.txt';
$subject = __('New Commit %1$s - %2$s (%3$s)');
$tmpl = new Pluf_Template($tplfile);
$text_email = $tmpl->render($context);
$email = new Pluf_Mail($from_email,
$address,
sprintf(__('New Commit %s - %s (%s)'),
sprintf($subject,
$this->scm_id, $this->summary,
$this->get_project()->shortname));
$project->shortname));
$email->addTextMessage($text_email);
$email->sendMail();
}
Pluf_Translation::loadSetLocale($current_locale);
}
}

View File

@ -3,7 +3,7 @@
/*
# ***** BEGIN LICENSE BLOCK *****
# This file is part of InDefero, an open source project management application.
# Copyright (C) 2008 Céondo Ltd and contributors.
# Copyright (C) 2008-2011 Céondo Ltd and contributors.
#
# InDefero is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@ -44,9 +44,9 @@ class IDF_Conf extends Pluf_Model
array(
'type' => 'Pluf_DB_Field_Sequence',
//It is automatically added.
'blank' => true,
'blank' => true,
),
'project' =>
'project' =>
array(
'type' => 'Pluf_DB_Field_Foreignkey',
'model' => 'IDF_Project',
@ -84,7 +84,7 @@ class IDF_Conf extends Pluf_Model
function initCache()
{
$this->datacache = new ArrayObject();
$this->datacache = array();
$sql = new Pluf_SQL('project=%s', $this->_project->id);
foreach ($this->getList(array('filter' => $sql->gen())) as $val) {
$this->datacache[$val->vkey] = $val->vdesc;
@ -97,7 +97,7 @@ class IDF_Conf extends Pluf_Model
*/
function setVal($key, $value)
{
if (!is_null($this->getVal($key, null))
if (!is_null($this->getVal($key, null))
and $value == $this->getVal($key)) {
return;
}
@ -129,4 +129,12 @@ class IDF_Conf extends Pluf_Model
$this->initCache();
}
}
function getKeys()
{
if ($this->datacache === null) {
$this->initCache();
}
return array_keys($this->datacache);
}
}

View File

@ -3,7 +3,7 @@
/*
# ***** BEGIN LICENSE BLOCK *****
# This file is part of InDefero, an open source project management application.
# Copyright (C) 2008 Céondo Ltd and contributors.
# Copyright (C) 2008-2011 Céondo Ltd and contributors.
#
# InDefero is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by

View File

@ -3,7 +3,7 @@
/*
# ***** BEGIN LICENSE BLOCK *****
# This file is part of InDefero, an open source project management application.
# Copyright (C) 2008 Céondo Ltd and contributors.
# Copyright (C) 2008-2011 Céondo Ltd and contributors.
#
# InDefero is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@ -27,17 +27,15 @@
*/
class IDF_Diff
{
public $repo = '';
public $diff = '';
public $path_strip_level = 0;
protected $lines = array();
public $files = array();
public function __construct($diff, $repo='')
public function __construct($diff, $path_strip_level = 0)
{
$this->repo = $repo;
$this->diff = $diff;
$this->lines = preg_split("/\015\012|\015|\012/", $diff);
$this->path_strip_level = $path_strip_level;
$this->lines = IDF_FileUtil::splitIntoLines($diff, true);
}
public function parse()
@ -49,178 +47,191 @@ class IDF_Diff
$files = array();
$indiff = false; // Used to skip the headers in the git patches
$i = 0; // Used to skip the end of a git patch with --\nversion number
foreach ($this->lines as $line) {
$i++;
if (0 === strpos($line, '--') and isset($this->lines[$i])
and preg_match('/^\d+\.\d+\.\d+\.\d+$/', $this->lines[$i])) {
break;
$diffsize = count($this->lines);
while ($i < $diffsize) {
// look for the potential beginning of a diff
if (substr($this->lines[$i], 0, 4) !== '--- ') {
$i++;
continue;
}
if (0 === strpos($line, 'diff --git a')) {
$current_file = self::getFile($line);
$files[$current_file] = array();
$files[$current_file]['chunks'] = array();
$files[$current_file]['chunks_def'] = array();
$current_chunk = 0;
$indiff = true;
// we're inside a diff candiate
$oldfileline = $this->lines[$i++];
$newfileline = $this->lines[$i++];
if (substr($newfileline, 0, 4) !== '+++ ') {
// not a valid diff here, move on
continue;
} else if (preg_match('#^diff -r [^\s]+ -r [^\s]+ (.+)$#', $line, $matches)) {
$current_file = $matches[1];
$files[$current_file] = array();
$files[$current_file]['chunks'] = array();
$files[$current_file]['chunks_def'] = array();
$current_chunk = 0;
$indiff = true;
continue;
} else if (!$indiff && 0 === strpos($line, '=========')) {
// ignore pseudo stanzas with a hint of a binary file
if (preg_match("/^# (.+) is binary/", $this->lines[$i]))
continue;
// by default always use the new name of a possibly renamed file
$current_file = self::getMtnFile($this->lines[$i+1]);
// mtn 0.48 and newer set /dev/null as file path for dropped files
// so we display the old name here
if ($current_file == "/dev/null") {
$current_file = self::getMtnFile($this->lines[$i]);
}
// use new file name by default
preg_match("/^\+\+\+ ([^\t\n\r]+)/", $newfileline, $m);
$current_file = $m[1];
if ($current_file === '/dev/null') {
// except if it's /dev/null, use the old one instead
// eg. mtn 0.48 and newer
preg_match("/^--- ([^\t\r\n]+)/", $oldfileline, $m);
$current_file = $m[1];
}
if ($this->path_strip_level > 0) {
$fileparts = explode('/', $current_file, $this->path_strip_level+1);
$current_file = array_pop($fileparts);
}
$current_chunk = 0;
$files[$current_file] = array();
$files[$current_file]['chunks'] = array();
$files[$current_file]['chunks_def'] = array();
while ($i < $diffsize && substr($this->lines[$i], 0, 3) === '@@ ') {
$elems = preg_match('/@@ -(\d+),?(\d*) \+(\d+),?(\d*) @@.*/',
$this->lines[$i++], $results);
if ($elems != 1) {
// hunk is badly formatted
break;
}
if ($current_file == "/dev/null") {
throw new Exception(
"could not determine path from diff"
);
}
$files[$current_file] = array();
$files[$current_file]['chunks'] = array();
$files[$current_file]['chunks_def'] = array();
$current_chunk = 0;
$indiff = true;
continue;
} else if (0 === strpos($line, 'Index: ')) {
$current_file = self::getSvnFile($line);
$files[$current_file] = array();
$files[$current_file]['chunks'] = array();
$files[$current_file]['chunks_def'] = array();
$current_chunk = 0;
$indiff = true;
continue;
}
if (!$indiff) {
continue;
}
if (0 === strpos($line, '@@ ')) {
$files[$current_file]['chunks_def'][] = self::getChunk($line);
$delstart = $results[1];
$dellines = $results[2] === '' ? 1 : $results[2];
$addstart = $results[3];
$addlines = $results[4] === '' ? 1 : $results[4];
$files[$current_file]['chunks_def'][] = array(
array($delstart, $dellines), array($addstart, $addlines)
);
$files[$current_file]['chunks'][] = array();
while ($i < $diffsize && ($addlines >= 0 || $dellines >= 0)) {
$linetype = $this->lines[$i] != '' ? $this->lines[$i][0] : false;
$content = substr($this->lines[$i], 1);
switch ($linetype) {
case ' ':
$files[$current_file]['chunks'][$current_chunk][] =
array($delstart, $addstart, $content);
$dellines--;
$addlines--;
$delstart++;
$addstart++;
break;
case '+':
$files[$current_file]['chunks'][$current_chunk][] =
array('', $addstart, $content);
$addlines--;
$addstart++;
break;
case '-':
$files[$current_file]['chunks'][$current_chunk][] =
array($delstart, '', $content);
$dellines--;
$delstart++;
break;
case '\\':
// no new line at the end of this file; remove pseudo new line from last line
$cur = count($files[$current_file]['chunks'][$current_chunk]) - 1;
$files[$current_file]['chunks'][$current_chunk][$cur][2] =
rtrim($files[$current_file]['chunks'][$current_chunk][$cur][2], "\r\n");
continue;
default:
break 2;
}
$i++;
}
$current_chunk++;
$lline = $files[$current_file]['chunks_def'][$current_chunk-1][0][0];
$rline = $files[$current_file]['chunks_def'][$current_chunk-1][1][0];
continue;
}
if (0 === strpos($line, '---') or 0 === strpos($line, '+++')) {
continue;
}
if (0 === strpos($line, '-')) {
$files[$current_file]['chunks'][$current_chunk-1][] = array($lline, '', substr($line, 1));
$lline++;
continue;
}
if (0 === strpos($line, '+')) {
$files[$current_file]['chunks'][$current_chunk-1][] = array('', $rline, substr($line, 1));
$rline++;
continue;
}
if (0 === strpos($line, ' ')) {
$files[$current_file]['chunks'][$current_chunk-1][] = array($lline, $rline, substr($line, 1));
$rline++;
$lline++;
continue;
}
if ($line == '') {
$files[$current_file]['chunks'][$current_chunk-1][] = array($lline, $rline, $line);
$rline++;
$lline++;
continue;
}
}
$this->files = $files;
return $files;
}
public static function getFile($line)
{
$line = substr(trim($line), 10);
$n = (int) strlen($line)/2;
return trim(substr($line, 3, $n-3));
}
public static function getSvnFile($line)
{
return substr(trim($line), 7);
}
public static function getMtnFile($line)
{
preg_match("/^[+-]{3} ([^\t]+)/", $line, $m);
return $m[1];
}
/**
* Return the html version of a parsed diff.
*/
public function as_html()
{
$out = '';
foreach ($this->files as $filename=>$file) {
foreach ($this->files as $filename => $file) {
$pretty = '';
$fileinfo = IDF_FileUtil::getMimeType($filename);
if (IDF_FileUtil::isSupportedExtension($fileinfo[2])) {
$pretty = ' prettyprint';
}
$out .= "\n".'<table class="diff" summary="">'."\n";
$out .= '<tr id="diff-'.md5($filename).'"><th colspan="3">'.Pluf_esc($filename).'</th></tr>'."\n";
$cc = 1;
$offsets = array();
$contents = array();
foreach ($file['chunks'] as $chunk) {
foreach ($chunk as $line) {
if ($line[0] and $line[1]) {
$class = 'diff-c';
} elseif ($line[0]) {
$class = 'diff-r';
list($left, $right, $content) = $line;
if ($left and $right) {
$class = 'context';
} elseif ($left) {
$class = 'removed';
} else {
$class = 'diff-a';
$class = 'added';
}
$line_content = self::padLine(Pluf_esc($line[2]));
$out .= sprintf('<tr class="diff-line"><td class="diff-lc">%s</td><td class="diff-lc">%s</td><td class="%s%s mono">%s</td></tr>'."\n", $line[0], $line[1], $class, $pretty, $line_content);
$offsets[] = sprintf('<td>%s</td><td>%s</td>', $left, $right);
$content = IDF_FileUtil::emphasizeControlCharacters(Pluf_esc($content));
$contents[] = sprintf('<td class="%s%s mono">%s</td>', $class, $pretty, $content);
}
if (count($file['chunks']) > $cc) {
$offsets[] = '<td class="next">...</td><td class="next">...</td>';
$contents[] = '<td class="next"></td>';
}
if (count($file['chunks']) > $cc)
$out .= '<tr class="diff-next"><td>...</td><td>...</td><td>&nbsp;</td></tr>'."\n";
$cc++;
}
$out .= '</table>';
}
return Pluf_Template::markSafe($out);
}
list($added, $removed) = end($file['chunks_def']);
public static function padLine($line)
{
$line = str_replace("\t", ' ', $line);
$n = strlen($line);
for ($i=0;$i<$n;$i++) {
if (substr($line, $i, 1) != ' ') {
break;
$added = $added[0] + $added[1];
$leftwidth = 0;
if ($added > 0)
$leftwidth = ((ceil(log10($added)) + 1) * 8) + 17;
$removed = $removed[0] + $removed[1];
$rightwidth = 0;
if ($removed > 0)
$rightwidth = ((ceil(log10($removed)) + 1) * 8) + 17;
// we need to correct the width of a single column a little
// to take less space and to hide the empty one
$class = '';
if ($leftwidth == 0) {
$class = 'left-hidden';
$rightwidth -= floor(log10($removed));
}
else if ($rightwidth == 0) {
$class = 'right-hidden';
$leftwidth -= floor(log10($added));
}
}
return str_repeat('&nbsp;', $i).substr($line, $i);
}
/**
* @return array array(array(start, n), array(start, n))
*/
public static function getChunk($line)
{
$elts = explode(' ', $line);
$res = array();
for ($i=1;$i<3;$i++) {
$res[] = explode(',', trim(substr($elts[$i], 1)));
$inner_linecounts =
'<table class="diff-linecounts '.$class.'">' ."\n".
'<colgroup><col width="'.$leftwidth.'" /><col width="'. $rightwidth.'" /></colgroup>' ."\n".
'<tr class="line">' .
implode('</tr>'."\n".'<tr class="line">', $offsets).
'</tr>' ."\n".
'</table>' ."\n";
$inner_contents =
'<table class="diff-contents">' ."\n".
'<tr class="line">' .
implode('</tr>'."\n".'<tr class="line">', $contents) .
'</tr>' ."\n".
'</table>' ."\n";
$out .= '<table class="diff unified">' ."\n".
'<colgroup><col width="'.($leftwidth + $rightwidth + 1).'" /><col width="*" /></colgroup>' ."\n".
'<tr id="diff-'.md5($filename).'">'.
'<th colspan="2">'.Pluf_esc($filename).'</th>'.
'</tr>' ."\n".
'<tr>' .
'<td>'. $inner_linecounts .'</td>'. "\n".
'<td><div class="scroll">'. $inner_contents .'</div></td>'.
'</tr>' ."\n".
'</table>' ."\n";
}
return $res;
return Pluf_Template::markSafe($out);
}
/**
@ -245,12 +256,12 @@ class IDF_Diff
*/
public function fileCompare($orig, $chunks, $filename, $context=10)
{
$orig_lines = preg_split("/\015\012|\015|\012/", $orig);
$orig_lines = IDF_FileUtil::splitIntoLines($orig);
$new_chunks = $this->mergeChunks($orig_lines, $chunks, $context);
return $this->renderCompared($new_chunks, $filename);
}
public function mergeChunks($orig_lines, $chunks, $context=10)
private function mergeChunks($orig_lines, $chunks, $context=10)
{
$spans = array();
$new_chunks = array();
@ -347,40 +358,115 @@ class IDF_Diff
return $nnew_chunks;
}
public function renderCompared($chunks, $filename)
private function renderCompared($chunks, $filename)
{
$fileinfo = IDF_FileUtil::getMimeType($filename);
$pretty = '';
if (IDF_FileUtil::isSupportedExtension($fileinfo[2])) {
$pretty = ' prettyprint';
}
$out = '';
$cc = 1;
$i = 0;
$left_offsets = array();
$left_contents = array();
$right_offsets = array();
$right_contents = array();
$max_lineno_left = $max_lineno_right = 0;
foreach ($chunks as $chunk) {
foreach ($chunk as $line) {
$line1 = '&nbsp;';
$line2 = '&nbsp;';
$line[2] = (strlen($line[2])) ? self::padLine(Pluf_esc($line[2])) : '&nbsp;';
if ($line[0] and $line[1]) {
$class = 'diff-c';
$line1 = $line2 = $line[2];
} elseif ($line[0]) {
$class = 'diff-r';
$line1 = $line[2];
} else {
$class = 'diff-a';
$line2 = $line[2];
}
$out .= sprintf('<tr class="diff-line"><td class="diff-lc">%s</td><td class="%s mono%s"><code>%s</code></td><td class="diff-lc">%s</td><td class="%s mono%s"><code>%s</code></td></tr>'."\n", $line[0], $class, $pretty, $line1, $line[1], $class, $pretty, $line2);
}
if (count($chunks) > $cc)
$out .= '<tr class="diff-next"><td>...</td><td>&nbsp;</td><td>...</td><td>&nbsp;</td></tr>'."\n";
$cc++;
$i++;
}
return Pluf_Template::markSafe($out);
$left = '';
$right = '';
$content = IDF_FileUtil::emphasizeControlCharacters(Pluf_esc($line[2]));
if ($line[0] and $line[1]) {
$class = 'context';
$left = $right = $content;
} elseif ($line[0]) {
$class = 'removed';
$left = $content;
} else {
$class = 'added';
$right = $content;
}
$left_offsets[] = sprintf('<td>%s</td>', $line[0]);
$right_offsets[] = sprintf('<td>%s</td>', $line[1]);
$left_contents[] = sprintf('<td class="%s%s mono">%s</td>', $class, $pretty, $left);
$right_contents[] = sprintf('<td class="%s%s mono">%s</td>', $class, $pretty, $right);
$max_lineno_left = max($max_lineno_left, $line[0]);
$max_lineno_right = max($max_lineno_right, $line[1]);
}
if (count($chunks) > $cc) {
$left_offsets[] = '<td class="next">...</td>';
$right_offsets[] = '<td class="next">...</td>';
$left_contents[] = '<td></td>';
$right_contents[] = '<td></td>';
}
$cc++;
}
$leftwidth = 1;
if ($max_lineno_left > 0)
$leftwidth = ((ceil(log10($max_lineno_left)) + 1) * 8) + 17;
$rightwidth = 1;
if ($max_lineno_right > 0)
$rightwidth = ((ceil(log10($max_lineno_right)) + 1) * 8) + 17;
$inner_linecounts_left =
'<table class="diff-linecounts">' ."\n".
'<colgroup><col width="'.$leftwidth.'" /></colgroup>' ."\n".
'<tr class="line">' .
implode('</tr>'."\n".'<tr class="line">', $left_offsets).
'</tr>' ."\n".
'</table>' ."\n";
$inner_linecounts_right =
'<table class="diff-linecounts">' ."\n".
'<colgroup><col width="'.$rightwidth.'" /></colgroup>' ."\n".
'<tr class="line">' .
implode('</tr>'."\n".'<tr class="line">', $right_offsets).
'</tr>' ."\n".
'</table>' ."\n";
$inner_contents_left =
'<table class="diff-contents">' ."\n".
'<tr class="line">' .
implode('</tr>'."\n".'<tr class="line">', $left_contents) .
'</tr>' ."\n".
'</table>' ."\n";
$inner_contents_right =
'<table class="diff-contents">' ."\n".
'<tr class="line">' .
implode('</tr>'."\n".'<tr class="line">', $right_contents) .
'</tr>' ."\n".
'</table>' ."\n";
$out =
'<table class="diff context">' ."\n".
'<colgroup>' .
'<col width="'.($leftwidth + 1).'" /><col width="*" />' .
'<col width="'.($rightwidth + 1).'" /><col width="*" />' .
'</colgroup>' ."\n".
'<tr id="diff-'.md5($filename).'">'.
'<th colspan="4">'.Pluf_esc($filename).'</th>'.
'</tr>' ."\n".
'<tr>' .
'<th colspan="2">'.__('Old').'</th><th colspan="2">'.__('New').'</th>' .
'</tr>'.
'<tr>' .
'<td>'. $inner_linecounts_left .'</td>'. "\n".
'<td><div class="scroll">'. $inner_contents_left .'</div></td>'. "\n".
'<td>'. $inner_linecounts_right .'</td>'. "\n".
'<td><div class="scroll">'. $inner_contents_right .'</div></td>'. "\n".
'</tr>' ."\n".
'</table>' ."\n";
return Pluf_Template::markSafe($out);
}
}

View File

@ -0,0 +1,96 @@
<?php
/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
# ***** BEGIN LICENSE BLOCK *****
# This file is part of InDefero, an open source project management application.
# Copyright (C) 2008-2011 Céondo Ltd and contributors.
#
# InDefero is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# InDefero is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#
# ***** END LICENSE BLOCK ***** */
/**
* Storage of Email addresses
*
*/
class IDF_EmailAddress extends Pluf_Model
{
public $_model = __CLASS__;
function init()
{
$this->_a['table'] = 'idf_emailaddresses';
$this->_a['model'] = __CLASS__;
$this->_a['cols'] = array(
// It is mandatory to have an "id" column.
'id' =>
array(
'type' => 'Pluf_DB_Field_Sequence',
//It is automatically added.
'blank' => true,
),
'user' =>
array(
'type' => 'Pluf_DB_Field_Foreignkey',
'model' => 'Pluf_User',
'blank' => false,
'verbose' => __('user'),
),
'address' =>
array(
'type' => 'Pluf_DB_Field_Email',
'blank' => false,
'verbose' => __('email'),
'unique' => true,
),
);
// WARNING: Not using getSqlTable on the Pluf_User object to
// avoid recursion.
$t_users = $this->_con->pfx.'users';
$this->_a['views'] = array(
'join_user' =>
array(
'join' => 'LEFT JOIN '.$t_users
.' ON '.$t_users.'.id='.$this->_con->qn('user'),
'select' => $this->getSelect().', '
.$t_users.'.login AS login',
'props' => array('login' => 'login'),
)
);
}
function get_email_addresses_for_user($user)
{
$addr = $user->get_idf_emailaddress_list();
$addr[] = (object)array("address" => $user->email, "id" => -1, "user" => $user);
return $addr;
}
function get_user_for_email_address($email)
{
$sql = new Pluf_SQL('email=%s', array($email));
$users = Pluf::factory('Pluf_User')->getList(array('filter'=>$sql->gen()));
if ($users->count() > 0) {
return $users[0];
}
$sql = new Pluf_SQL('address=%s', array($email));
$matches = Pluf::factory('IDF_EmailAddress')->getList(array('filter'=>$sql->gen()));
if ($matches->count() > 0) {
return new Pluf_User($matches[0]->user);
}
return null;
}
}

View File

@ -3,7 +3,7 @@
/*
# ***** BEGIN LICENSE BLOCK *****
# This file is part of InDefero, an open source project management application.
# Copyright (C) 2010 Céondo Ltd and contributors.
# Copyright (C) 2008-2011 Céondo Ltd and contributors.
#
# InDefero is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@ -65,9 +65,9 @@ class IDF_FileUtil
}
$table = array();
$i = 1;
foreach (preg_split("/\015\012|\015|\012/", $content) as $line) {
foreach (self::splitIntoLines($content) as $line) {
$table[] = '<tr class="c-line"><td class="code-lc" id="L'.$i.'"><a href="#L'.$i.'">'.$i.'</a></td>'
.'<td class="code mono'.$pretty.'">'.IDF_Diff::padLine(Pluf_esc($line)).'</td></tr>';
.'<td class="code mono'.$pretty.'">'.self::emphasizeControlCharacters(Pluf_esc($line)).'</td></tr>';
$i++;
}
return Pluf_Template::markSafe(implode("\n", $table));
@ -143,6 +143,53 @@ class IDF_FileUtil
return $res;
}
/**
* Splits a string into separate lines while retaining the individual
* line ending character for every line.
*
* OS 9 line endings are not supported.
*
* @param string content
* @param boolean if true, skip completely empty lines
* @return string
*/
public static function splitIntoLines($content, $skipEmpty = false)
{
$last_off = 0;
$lines = array();
while (preg_match("/\r\n|\n/", $content, $m, PREG_OFFSET_CAPTURE, $last_off)) {
$next_off = strlen($m[0][0]) + $m[0][1];
$line = substr($content, $last_off, $next_off - $last_off);
$last_off = $next_off;
if ($line !== $m[0][0] || !$skipEmpty) $lines[] = $line;
}
$line = substr($content, $last_off);
if ($line !== false && strlen($line) > 0) $lines[] = $line;
return $lines;
}
/**
* This translates most of the C0 ASCII control characters into
* their visual counterparts in the 0x24## unicode plane
* (http://en.wikipedia.org/wiki/C0_and_C1_control_codes).
*
* We could add DEL (0x7F) to this set, but unfortunately this
* is not nicely mapped to 0x247F in the control plane, but 0x2421
* and adding an if expression below just for this is a little bit
* of a hassle. And of course, the more esoteric ones from C1 are
* missing as well...
*
* @param string $content
* @return string
*/
public static function emphasizeControlCharacters($content)
{
return preg_replace(
'/([\x00-\x1F])/ue',
'"<span class=\"ctrl-char\" title=\"0x".bin2hex("\\1")."\">&#x24".bin2hex("\\1")."</span>"',
$content);
}
/**
* Find if a given mime type is a text file.
* This uses the output of the self::getMimeType function.

70
src/IDF/Forge.php 100644
View File

@ -0,0 +1,70 @@
<?php
/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
# ***** BEGIN LICENSE BLOCK *****
# This file is part of InDefero, an open source project management application.
# Copyright (C) 2008-2011 Céondo Ltd and contributors.
#
# InDefero is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# InDefero is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#
# ***** END LICENSE BLOCK ***** */
/**
* A lightweight model for the singleton forge entity
*/
class IDF_Forge
{
public $_model = __CLASS__;
public $id = 1;
/**
* @var IDF_Gconf
*/
private $conf;
private function __construct() {
$this->conf = new IDF_Gconf();
$this->conf->setModel($this);
}
public static function instance() {
return new IDF_Forge();
}
public function getProjectLabels($default = '') {
return $this->conf->getVal('project_labels', $default);
}
public function setProjectLabels($labels) {
$this->conf->setVal('project_labels', $labels);
}
public function setCustomForgePageEnabled($enabled) {
$this->conf->setVal('custom_forge_page_enabled', $enabled);
}
public function isCustomForgePageEnabled($default = false) {
return $this->conf->getVal('custom_forge_page_enabled', $default);
}
public function getCustomForgePageContent($default = '') {
return $this->conf->getVal('custom_forge_page_content', $default);
}
public function setCustomForgePageContent($content) {
$this->conf->setVal('custom_forge_page_content', $content);
}
}

View File

@ -0,0 +1,47 @@
<?php
/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
# ***** BEGIN LICENSE BLOCK *****
# This file is part of InDefero, an open source project management application.
# Copyright(C) 2008-2011 Céondo Ltd and contributors.
#
# InDefero is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
#(at your option) any later version.
#
# InDefero is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#
# ***** END LICENSE BLOCK ***** */
/**
* Configuration of the forge's start page.
*/
class IDF_Form_Admin_ForgeConf extends Pluf_Form
{
public function initFields($extra=array())
{
$this->fields['enabled'] = new Pluf_Form_Field_Boolean(
array('required' => false,
'label' => __('Custom forge page enabled'),
'widget' => 'Pluf_Form_Widget_CheckboxInput',
));
$this->fields['content'] = new Pluf_Form_Field_Varchar(
array('required' => true,
'label' => __('Content'),
'widget' => 'Pluf_Form_Widget_TextareaInput',
'widget_attrs' => array(
'cols' => 68,
'rows' => 26,
),
));
}
}

View File

@ -0,0 +1,62 @@
<?php
/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
# ***** BEGIN LICENSE BLOCK *****
# This file is part of InDefero, an open source project management application.
# Copyright(C) 2008-2011 Céondo Ltd and contributors.
#
# InDefero is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
#(at your option) any later version.
#
# InDefero is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#
# ***** END LICENSE BLOCK ***** */
/**
* Configuration of forge labels.
*/
class IDF_Form_Admin_LabelConf extends Pluf_Form
{
const init_project_labels = 'UI:GUI = Applications with graphical user interfaces
UI:CLI = Applications with no graphical user interfaces
License:BSD = Applications with BSD license
License:GPL = Applications with GPL license
';
public function initFields($extra=array())
{
$this->fields['project_labels'] = new Pluf_Form_Field_Varchar(
array('required' => true,
'label' => __('Predefined project labels'),
'initial' => self::init_project_labels,
'widget_attrs' => array('rows' => 13,
'cols' => 75),
'widget' => 'Pluf_Form_Widget_TextareaInput',
));
}
public function clean_project_labels()
{
$labels = preg_split("/\s*\n\s*/", $this->cleaned_data['project_labels'], -1, PREG_SPLIT_NO_EMPTY);
for ($i=0; $i<count($labels); ++$i) {
$labels[$i] = trim($labels[$i]);
if (!preg_match('/^[\w-]+(:[\w-]+)?(\s*=\s*[^=]+)?$/', $labels[$i])) {
throw new Pluf_Form_Invalid(sprintf(
__('The label "%s" is invalid: A label must only consist of alphanumeric '.
'characters and dashes, and can optionally contain a ":" with a group prefix.'),
$labels[$i]));
}
}
return implode("\n", $labels);
}
}

View File

@ -3,7 +3,7 @@
/*
# ***** BEGIN LICENSE BLOCK *****
# This file is part of InDefero, an open source project management application.
# Copyright (C) 2008 Céondo Ltd and contributors.
# Copyright (C) 2008-2011 Céondo Ltd and contributors.
#
# InDefero is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@ -72,6 +72,13 @@ class IDF_Form_Admin_ProjectCreate extends Pluf_Form
'widget_attrs' => array('size' => '35'),
));
$this->fields['external_project_url'] = new Pluf_Form_Field_Varchar(
array('required' => false,
'label' => __('External URL'),
'widget_attrs' => array('size' => '35'),
'initial' => '',
));
$this->fields['scm'] = new Pluf_Form_Field_Varchar(
array('required' => true,
'label' => __('Repository type'),
@ -127,6 +134,18 @@ class IDF_Form_Admin_ProjectCreate extends Pluf_Form
'widget' => 'Pluf_Form_Widget_TextareaInput',
));
for ($i=1;$i<7;$i++) {
$this->fields['label'.$i] = new Pluf_Form_Field_Varchar(
array('required' => false,
'label' => __('Labels'),
'initial' => '',
'widget_attrs' => array(
'maxlength' => 50,
'size' => 20,
),
));
}
$projects = array('--' => '--');
foreach (Pluf::factory('IDF_Project')->getList(array('order' => 'name ASC')) as $proj) {
$projects[$proj->name] = $proj->shortname;
@ -182,7 +201,7 @@ class IDF_Form_Admin_ProjectCreate extends Pluf_Form
// we accept only starting with http(s):// to avoid people
// trying to access the local filesystem.
if (!preg_match('#^(http|https)://#', $url)) {
throw new Pluf_Form_Invalid(__('Only a remote repository available throught http or https are allowed. For example "http://somewhere.com/svn/trunk".'));
throw new Pluf_Form_Invalid(__('Only a remote repository available through HTTP or HTTPS is allowed. For example "http://somewhere.com/svn/trunk".'));
}
return $url;
}
@ -199,7 +218,7 @@ class IDF_Form_Admin_ProjectCreate extends Pluf_Form
$mtn_master_branch)) {
throw new Pluf_Form_Invalid(__(
'The master branch is empty or contains illegal characters, '.
'please use only letters, digits, dashs and dots as separators.'
'please use only letters, digits, dashes and dots as separators.'
));
}
@ -235,6 +254,11 @@ class IDF_Form_Admin_ProjectCreate extends Pluf_Form
return $shortname;
}
public function clean_external_project_url()
{
return IDF_Form_ProjectConf::checkWebURL($this->cleaned_data['external_project_url']);
}
public function clean()
{
if ($this->cleaned_data['scm'] != 'svn') {
@ -278,11 +302,29 @@ class IDF_Form_Admin_ProjectCreate extends Pluf_Form
if (!$this->isValid()) {
throw new Exception(__('Cannot save the model from an invalid form.'));
}
// Add a tag for each label
$tagids = array();
for ($i=1;$i<7;$i++) {
if (strlen($this->cleaned_data['label'.$i]) > 0) {
if (strpos($this->cleaned_data['label'.$i], ':') !== false) {
list($class, $name) = explode(':', $this->cleaned_data['label'.$i], 2);
list($class, $name) = array(trim($class), trim($name));
} else {
$class = 'Other';
$name = trim($this->cleaned_data['label'.$i]);
}
$tag = IDF_Tag::addGlobal($name, $class);
$tagids[] = $tag->id;
}
}
$project = new IDF_Project();
$project->name = $this->cleaned_data['name'];
$project->shortname = $this->cleaned_data['shortname'];
$project->shortdesc = $this->cleaned_data['shortdesc'];
$tagids = array();
if ($this->cleaned_data['template'] != '--') {
// Find the template project
$sql = new Pluf_SQL('shortname=%s',
@ -290,51 +332,63 @@ class IDF_Form_Admin_ProjectCreate extends Pluf_Form
$tmpl = Pluf::factory('IDF_Project')->getOne(array('filter' => $sql->gen()));
$project->private = $tmpl->private;
$project->description = $tmpl->description;
foreach ($tmpl->get_tags_list() as $tag) {
$tagids[] = $tag->id;
}
} else {
$project->private = $this->cleaned_data['private_project'];
$project->description = __('Click on the Project Management tab to set the description of your project.');
// Add a tag for each label
for ($i=1;$i<7;$i++) {
if (strlen($this->cleaned_data['label'.$i]) > 0) {
if (strpos($this->cleaned_data['label'.$i], ':') !== false) {
list($class, $name) = explode(':', $this->cleaned_data['label'.$i], 2);
list($class, $name) = array(trim($class), trim($name));
} else {
$class = 'Other';
$name = trim($this->cleaned_data['label'.$i]);
}
$tag = IDF_Tag::addGlobal($name, $class);
$tagids[] = $tag->id;
}
}
}
$project->create();
$project->batchAssoc('IDF_Tag', $tagids);
$conf = new IDF_Conf();
$conf->setProject($project);
$keys = array('scm', 'svn_remote_url', 'svn_username',
'svn_password', 'mtn_master_branch');
foreach ($keys as $key) {
$this->cleaned_data[$key] = (!empty($this->cleaned_data[$key])) ?
$this->cleaned_data[$key] : '';
$conf->setVal($key, $this->cleaned_data[$key]);
}
if ($this->cleaned_data['template'] != '--') {
$tmplconf = new IDF_Conf();
$tmplconf->setProject($tmpl);
// We need to get all the configuration variables we want from
// the old project and put them into the new project.
$props = array(
'labels_download_predefined' => IDF_Form_UploadConf::init_predefined,
'labels_download_one_max' => IDF_Form_UploadConf::init_one_max,
'labels_wiki_predefined' => IDF_Form_WikiConf::init_predefined,
'labels_wiki_one_max' => IDF_Form_WikiConf::init_one_max,
'labels_issue_template' => IDF_Form_IssueTrackingConf::init_template,
'labels_issue_open' => IDF_Form_IssueTrackingConf::init_open,
'labels_issue_closed' => IDF_Form_IssueTrackingConf::init_closed,
'labels_issue_predefined' => IDF_Form_IssueTrackingConf::init_predefined,
'labels_issue_one_max' => IDF_Form_IssueTrackingConf::init_one_max,
'webhook_url' => '',
'downloads_access_rights' => 'all',
'review_access_rights' => 'all',
'wiki_access_rights' => 'all',
'source_access_rights' => 'all',
'issues_access_rights' => 'all',
'downloads_notification_email' => '',
'review_notification_email' => '',
'wiki_notification_email' => '',
'source_notification_email' => '',
'issues_notification_email' => '',
);
foreach ($props as $prop => $def) {
$conf->setVal($prop, $tmplconf->getVal($prop, $def));
$allKeys = $tmplconf->getKeys();
$scm = $this->cleaned_data['scm'];
$ignoreKeys = array('scm', 'external_project_url', 'logo');
// copy over all existing variables, except scm-related data and
// the project url / logo
foreach ($allKeys as $key) {
if (in_array($key, $ignoreKeys) || strpos($key, $scm.'_') === 0) {
continue;
}
$conf->setVal($key, $tmplconf->getVal($key));
}
}
$keys = array(
'scm', 'svn_remote_url', 'svn_username',
'svn_password', 'mtn_master_branch',
'external_project_url'
);
foreach ($keys as $key) {
$this->cleaned_data[$key] = !empty($this->cleaned_data[$key]) ?
$this->cleaned_data[$key] : '';
$conf->setVal($key, $this->cleaned_data[$key]);
}
$project->created();
if ($this->cleaned_data['template'] == '--') {

View File

@ -3,7 +3,7 @@
/*
# ***** BEGIN LICENSE BLOCK *****
# This file is part of InDefero, an open source project management application.
# Copyright (C) 2008 Céondo Ltd and contributors.
# Copyright (C) 2008-2011 Céondo Ltd and contributors.
#
# InDefero is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by

View File

@ -3,7 +3,7 @@
/*
# ***** BEGIN LICENSE BLOCK *****
# This file is part of InDefero, an open source project management application.
# Copyright (C) 2008 Céondo Ltd and contributors.
# Copyright (C) 2008-2011 Céondo Ltd and contributors.
#
# InDefero is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@ -53,6 +53,13 @@ class IDF_Form_Admin_ProjectUpdate extends Pluf_Form
'widget_attrs' => array('size' => '35'),
));
$this->fields['external_project_url'] = new Pluf_Form_Field_Varchar(
array('required' => false,
'label' => __('External URL'),
'widget_attrs' => array('size' => '35'),
'initial' => $conf->getVal('external_project_url'),
));
if ($this->project->getConf()->getVal('scm') == 'mtn') {
$this->fields['mtn_master_branch'] = new Pluf_Form_Field_Varchar(
array('required' => false,
@ -63,6 +70,26 @@ class IDF_Form_Admin_ProjectUpdate extends Pluf_Form
));
}
$tags = $this->project->get_tags_list();
for ($i=1;$i<7;$i++) {
$initial = '';
if (isset($tags[$i-1])) {
if ($tags[$i-1]->class != 'Other') {
$initial = (string) $tags[$i-1];
} else {
$initial = $tags[$i-1]->name;
}
}
$this->fields['label'.$i] = new Pluf_Form_Field_Varchar(
array('required' => false,
'label' => __('Labels'),
'initial' => $initial,
'widget_attrs' => array(
'maxlength' => 50,
'size' => 20,
),
));
}
$this->fields['owners'] = new Pluf_Form_Field_Varchar(
array('required' => false,
'label' => __('Project owners'),
@ -88,7 +115,7 @@ class IDF_Form_Admin_ProjectUpdate extends Pluf_Form
$mtn_master_branch)) {
throw new Pluf_Form_Invalid(__(
'The master branch is empty or contains illegal characters, '.
'please use only letters, digits, dashs and dots as separators.'
'please use only letters, digits, dashes and dots as separators.'
));
}
@ -115,22 +142,52 @@ class IDF_Form_Admin_ProjectUpdate extends Pluf_Form
return IDF_Form_MembersConf::checkBadLogins($this->cleaned_data['members']);
}
public function clean_external_project_url()
{
return IDF_Form_ProjectConf::checkWebURL($this->cleaned_data['external_project_url']);
}
public function save($commit=true)
{
if (!$this->isValid()) {
throw new Exception(__('Cannot save the model from an invalid form.'));
}
// Add a tag for each label
$tagids = array();
for ($i=1;$i<7;$i++) {
if (strlen($this->cleaned_data['label'.$i]) > 0) {
if (strpos($this->cleaned_data['label'.$i], ':') !== false) {
list($class, $name) = explode(':', $this->cleaned_data['label'.$i], 2);
list($class, $name) = array(trim($class), trim($name));
} else {
$class = 'Other';
$name = trim($this->cleaned_data['label'.$i]);
}
$tag = IDF_Tag::addGlobal($name, $class);
$tagids[] = $tag->id;
}
}
$this->project->batchAssoc('IDF_Tag', $tagids);
IDF_Form_MembersConf::updateMemberships($this->project,
$this->cleaned_data);
$this->project->membershipsUpdated();
$this->project->name = $this->cleaned_data['name'];
$this->project->shortdesc = $this->cleaned_data['shortdesc'];
$this->project->update();
$keys = array('mtn_master_branch');
$conf = $this->project->getConf();
$keys = array('mtn_master_branch', 'external_project_url');
foreach ($keys as $key) {
if (!empty($this->cleaned_data[$key])) {
$this->project->getConf()->setVal($key, $this->cleaned_data[$key]);
if (array_key_exists($key, $this->cleaned_data)) {
if (!empty($this->cleaned_data[$key])) {
$conf->setVal($key, $this->cleaned_data[$key]);
}
else {
$conf->delVal($key);
}
}
}
}

View File

@ -3,7 +3,7 @@
/*
# ***** BEGIN LICENSE BLOCK *****
# This file is part of InDefero, an open source project management application.
# Copyright (C) 2008 Céondo Ltd and contributors.
# Copyright (C) 2008-2011 Céondo Ltd and contributors.
#
# InDefero is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@ -68,7 +68,7 @@ class IDF_Form_Admin_UserCreate extends Pluf_Form
array('required' => true,
'label' => __('Email'),
'initial' => '',
'help_text' => __('Double check the email address as the password is directly sent to the user.'),
'help_text' => __('Double check the email address as the password is sent directly to the user.'),
));
$this->fields['language'] = new Pluf_Form_Field_Varchar(

View File

@ -3,7 +3,7 @@
/*
# ***** BEGIN LICENSE BLOCK *****
# This file is part of InDefero, an open source project management application.
# Copyright (C) 2008 Céondo Ltd and contributors.
# Copyright (C) 2008-2011 Céondo Ltd and contributors.
#
# InDefero is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@ -78,7 +78,7 @@ class IDF_Form_Admin_UserUpdate extends Pluf_Form
'label' => __('Password'),
'initial' => '',
'widget' => 'Pluf_Form_Widget_PasswordInput',
'help_text' => Pluf_Template::markSafe(__('Leave blank if you do not want to change the password.').'<br />'.__('The password must be hard for other people to find it, but easy for the user to remember.')),
'help_text' => Pluf_Template::markSafe(__('Leave blank if you do not want to change the password.').'<br />'.__('The password must be hard for other people to guess, but easy for the user to remember.')),
'widget_attrs' => array(
'maxlength' => 50,
'size' => 15,
@ -173,7 +173,7 @@ class IDF_Form_Admin_UserUpdate extends Pluf_Form
'initial' => $this->user->active,
'widget' => 'Pluf_Form_Widget_CheckboxInput',
'widget_attrs' => $attrs,
'help_text' => __('If the user is not getting the confirmation email or is abusing the system, you can directly enable or disable his account here.'),
'help_text' => __('If the user is not getting the confirmation email or is abusing the system, you can directly enable or disable their account here.'),
));
}

View File

@ -3,19 +3,19 @@
/*
# ***** BEGIN LICENSE BLOCK *****
# This file is part of InDefero, an open source project management application.
# Copyright (C) 2010 Céondo Ltd and contributors.
# Copyright (C) 2008-2011 Céondo Ltd and contributors.
#
# Plume Framework is free software; you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation; either version 2.1 of the License, or
# InDefero is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# Plume Framework is distributed in the hope that it will be useful,
# InDefero is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
# GNU General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#

View File

@ -3,7 +3,7 @@
/*
# ***** BEGIN LICENSE BLOCK *****
# This file is part of InDefero, an open source project management application.
# Copyright (C) 2008 Céondo Ltd and contributors.
# Copyright (C) 2008-2011 Céondo Ltd and contributors.
#
# InDefero is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@ -36,6 +36,7 @@ class IDF_Form_IssueCreate extends Pluf_Form
public $user = null;
public $project = null;
public $show_full = false;
public $relation_types = null;
public function initFields($extra=array())
{
@ -45,9 +46,12 @@ class IDF_Form_IssueCreate extends Pluf_Form
or $this->user->hasPerm('IDF.project-member', $this->project)) {
$this->show_full = true;
}
$this->relation_types = $this->project->getRelationsFromConfig();
$contentTemplate = $this->project->getConf()->getVal(
'labels_issue_template', IDF_Form_IssueTrackingConf::init_template
);
$this->fields['summary'] = new Pluf_Form_Field_Varchar(
array('required' => true,
'label' => __('Summary'),
@ -76,11 +80,11 @@ class IDF_Form_IssueCreate extends Pluf_Form
// case of someone allowing the upload path to be accessible
// to everybody.
for ($i=1;$i<4;$i++) {
$filename = substr($md5, 0, 2).'/'.substr($md5, 2, 2).'/'.substr($md5, 4).'/%s.dummy';
$filename = substr($md5, 0, 2).'/'.substr($md5, 2, 2).'/'.substr($md5, 4).'/%s.dummy';
$this->fields['attachment'.$i] = new Pluf_Form_Field_File(
array('required' => false,
'label' => __('Attach a file'),
'move_function_params' =>
'move_function_params' =>
array('upload_path' => $upload_path,
'upload_path_create' => true,
'file_name' => $filename,
@ -108,6 +112,26 @@ class IDF_Form_IssueCreate extends Pluf_Form
'size' => 15,
),
));
$this->fields['due_dtime'] = new Pluf_Form_Field_Date(
array('required' => false,
'label' => __('Due date'),
'initial' => '',
'widget_attrs' => array('size' => 15,),
));
$this->fields['relation_type0'] = new Pluf_Form_Field_Varchar(
array('required' => false,
'label' => __('This issue'),
'initial' => current($this->relation_types),
'widget_attrs' => array('size' => 15),
));
$this->fields['relation_issue0'] = new Pluf_Form_Field_Varchar(
array('required' => false,
'label' => null,
'initial' => '',
'widget_attrs' => array('size' => 10),
));
/*
* get predefined tags for issues from current project
@ -181,7 +205,7 @@ class IDF_Form_IssueCreate extends Pluf_Form
$this->cleaned_data['label'.$i] = trim($this->cleaned_data['label'.$i]);
if (strpos($this->cleaned_data['label'.$i], ':') !== false) {
list($class, $name) = explode(':', $this->cleaned_data['label'.$i], 2);
list($class, $name) = array(mb_strtolower(trim($class)),
list($class, $name) = array(mb_strtolower(trim($class)),
trim($name));
} else {
$class = 'other';
@ -196,7 +220,7 @@ class IDF_Form_IssueCreate extends Pluf_Form
else $count[$class] += 1;
if (in_array($class, $onemax) and $count[$class] > 1) {
if (!isset($this->errors['label'.$i])) $this->errors['label'.$i] = array();
$this->errors['label'.$i][] = sprintf(__('You cannot provide more than label from the %s class to an issue.'), $class);
$this->errors['label'.$i][] = sprintf(__('You cannot provide more than one label from the %s class to an issue.'), $class);
throw new Pluf_Form_Invalid(__('You provided an invalid label.'));
}
}
@ -215,10 +239,10 @@ class IDF_Form_IssueCreate extends Pluf_Form
function clean_status()
{
// Check that the status is in the list of official status
$tags = $this->project->getTagsFromConfig('labels_issue_open',
$tags = $this->project->getTagsFromConfig('labels_issue_open',
IDF_Form_IssueTrackingConf::init_open,
'Status');
$tags = array_merge($this->project->getTagsFromConfig('labels_issue_closed',
$tags = array_merge($this->project->getTagsFromConfig('labels_issue_closed',
IDF_Form_IssueTrackingConf::init_closed,
'Status')
, $tags);
@ -235,6 +259,63 @@ class IDF_Form_IssueCreate extends Pluf_Form
return $this->cleaned_data['status'];
}
// this method is not called from Pluf_Form directly, but shared for
// among all similar fields
function clean_relation_type($value)
{
$relation_type = trim($value);
if (empty($relation_type))
return '';
$found = false;
foreach ($this->relation_types as $type) {
if ($type == $relation_type) {
$found = true;
break;
}
}
if (!$found) {
throw new Pluf_Form_Invalid(__('You provided an invalid relation type.'));
}
return $relation_type;
}
function clean_relation_type0()
{
return $this->clean_relation_type($this->cleaned_data['relation_type0']);
}
// this method is not called from Pluf_Form directly, but shared for
// among all similar fields
function clean_relation_issue($value)
{
$issues = trim($value);
if (empty($issues))
return '';
$issue_ids = preg_split('/\s*,\s*/', $issues, -1, PREG_SPLIT_NO_EMPTY);
foreach ($issue_ids as $issue_id) {
if (!ctype_digit($issue_id) || (int)$issue_id < 1) {
throw new Pluf_Form_Invalid(sprintf(
__('The value "%s" is not a valid issue id.'), $issue_id
));
}
$issue = new IDF_Issue($issue_id);
if ($issue->id != $issue_id || $issue->project != $this->project->id) {
throw new Pluf_Form_Invalid(sprintf(
__('The issue "%s" does not exist.'), $issue_id
));
}
}
return implode(', ', $issue_ids);
}
function clean_relation_issue0()
{
return $this->clean_relation_issue($this->cleaned_data['relation_issue0']);
}
/**
* Clean the attachments post failure.
*/
@ -293,11 +374,36 @@ class IDF_Form_IssueCreate extends Pluf_Form
$issue->status = new IDF_Tag($_t[0]); // first one is the default
$issue->owner = null;
}
$issue->due_dtime = $this->cleaned_data['due_dtime'];
$issue->summary = trim($this->cleaned_data['summary']);
$issue->create();
foreach ($tags as $tag) {
$issue->setAssoc($tag);
}
// add relations (if any)
if (!empty($this->cleaned_data['relation_type0'])) {
$verb = $this->cleaned_data['relation_type0'];
$other_verb = $this->relation_types[$verb];
$related_issues = preg_split('/\s*,\s*/', $this->cleaned_data['relation_issue0'], -1, PREG_SPLIT_NO_EMPTY);
foreach ($related_issues as $related_issue_id) {
$related_issue = new IDF_Issue($related_issue_id);
$rel = new IDF_IssueRelation();
$rel->issue = $issue;
$rel->verb = $verb;
$rel->other_issue = $related_issue;
$rel->submitter = $this->user;
$rel->create();
$other_rel = new IDF_IssueRelation();
$other_rel->issue = $related_issue;
$other_rel->verb = $other_verb;
$other_rel->other_issue = $issue;
$other_rel->submitter = $this->user;
$other_rel->create();
}
}
// add the first comment
$comment = new IDF_IssueComment();
$comment->issue = $issue;

View File

@ -3,7 +3,7 @@
/*
# ***** BEGIN LICENSE BLOCK *****
# This file is part of InDefero, an open source project management application.
# Copyright (C) 2008 Céondo Ltd and contributors.
# Copyright (C) 2008-2011 Céondo Ltd and contributors.
#
# InDefero is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@ -72,6 +72,23 @@ Performance = Performance issue
Usability = Affects program usability
Maintainability = Hinders future changes';
const init_one_max = 'Type, Priority, Milestone';
// ATTENTION: if you change something here, change the values below as well!
const init_relations = 'is related to
blocks, is blocked by
duplicates, is duplicated by';
// These are actually all noop's, but we have no other chance to
// tell IDF's translation mechanism to mark the strings as translatable
// FIXME: IDF should get a internal translation system for strings like
// that, that can also be easily expanded by users
private function noop()
{
__('is related to');
__('blocks');
__('is blocked by');
__('duplicates');
__('is duplicated by');
}
public function initFields($extra=array())
{
@ -113,11 +130,20 @@ Maintainability = Hinders future changes';
$this->fields['labels_issue_one_max'] = new Pluf_Form_Field_Varchar(
array('required' => false,
'label' => __('Each issue may have at most one label with each of these classes'),
'initial' => self::init_one_max,
'label' => __('Each issue may have at most one label with each of these classes.'),
'initial' => self::init_one_max,
'widget_attrs' => array('size' => 60),
));
$this->fields['issue_relations'] = new Pluf_Form_Field_Varchar(
array('required' => true,
'label' => __('Issue relations'),
'initial' => self::init_relations,
'help_text' => __('You can define bidirectional relations like "is related to" or "blocks, is blocked by". For standard relations pre-configured translations exist, new relations should however be defined in a language that is understood by all project members.'),
'widget_attrs' => array('rows' => 7,
'cols' => 75),
'widget' => 'Pluf_Form_Widget_TextareaInput',
));
}
}

View File

@ -3,7 +3,7 @@
/*
# ***** BEGIN LICENSE BLOCK *****
# This file is part of InDefero, an open source project management application.
# Copyright (C) 2008 Céondo Ltd and contributors.
# Copyright (C) 2008-2011 Céondo Ltd and contributors.
#
# InDefero is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@ -39,6 +39,7 @@ class IDF_Form_IssueUpdate extends IDF_Form_IssueCreate
or $this->user->hasPerm('IDF.project-member', $this->project)) {
$this->show_full = true;
}
$this->relation_types = $this->project->getRelationsFromConfig();
if ($this->show_full) {
$this->fields['summary'] = new Pluf_Form_Field_Varchar(
array('required' => true,
@ -69,11 +70,11 @@ class IDF_Form_IssueUpdate extends IDF_Form_IssueCreate
// case of someone allowing the upload path to be accessible
// to everybody.
for ($i=1;$i<4;$i++) {
$filename = substr($md5, 0, 2).'/'.substr($md5, 2, 2).'/'.substr($md5, 4).'/%s.dummy';
$filename = substr($md5, 0, 2).'/'.substr($md5, 2, 2).'/'.substr($md5, 4).'/%s.dummy';
$this->fields['attachment'.$i] = new Pluf_Form_Field_File(
array('required' => false,
'label' => __('Attach a file'),
'move_function_params' =>
'move_function_params' =>
array('upload_path' => $upload_path,
'upload_path_create' => true,
'file_name' => $filename,
@ -102,6 +103,59 @@ class IDF_Form_IssueUpdate extends IDF_Form_IssueCreate
'size' => 15,
),
));
$due_dtime = substr($this->issue->due_dtime, 0, 10);
$this->fields['due_dtime'] = new Pluf_Form_Field_Date(
array('required' => false,
'label' => __('Due date'),
'initial' => $due_dtime,
'widget_attrs' => array('size' => 15,),
));
$idx = 0;
// note: clean_relation_type0 and clean_relation_issue0 already
// exist in the base class
$this->fields['relation_type'.$idx] = new Pluf_Form_Field_Varchar(
array('required' => false,
'label' => __('This issue'),
'initial' => current($this->relation_types),
'widget_attrs' => array('size' => 15),
));
$this->fields['relation_issue'.$idx] = new Pluf_Form_Field_Varchar(
array('required' => false,
'label' => null,
'initial' => '',
'widget_attrs' => array('size' => 10),
));
++$idx;
$relatedIssues = $this->issue->getGroupedRelatedIssues(array(), true);
foreach ($relatedIssues as $verb => $ids) {
$this->fields['relation_type'.$idx] = new Pluf_Form_Field_Varchar(
array('required' => false,
'label' => __('This issue'),
'initial' => $verb,
'widget_attrs' => array('size' => 15),
));
$m = 'clean_relation_type'.$idx;
$this->$m = create_function('$form', '
return $form->clean_relation_type($form->cleaned_data["relation_type'.$idx.'"]);
');
$this->fields['relation_issue'.$idx] = new Pluf_Form_Field_Varchar(
array('required' => false,
'label' => null,
'initial' => implode(', ', $ids),
'widget_attrs' => array('size' => 10),
));
$m = 'clean_relation_issue'.$idx;
$this->$m = create_function('$form', '
return $form->clean_relation_issue($form->cleaned_data["relation_issue'.$idx.'"]);
');
++$idx;
}
$tags = $this->issue->get_tags_list();
for ($i=1;$i<7;$i++) {
$initial = '';
@ -155,6 +209,51 @@ class IDF_Form_IssueUpdate extends IDF_Form_IssueCreate
public function clean()
{
$this->cleaned_data = parent::clean();
// normalize the user's input by removing dublettes and by combining
// ids from identical verbs in different input fields into one array
$normRelatedIssues = array();
for ($idx = 0; isset($this->cleaned_data['relation_type'.$idx]); ++$idx) {
$verb = $this->cleaned_data['relation_type'.$idx];
if (empty($verb))
continue;
$ids = preg_split('/\s*,\s*/', $this->cleaned_data['relation_issue'.$idx],
-1, PREG_SPLIT_NO_EMPTY);
if (count($ids) == 0)
continue;
if (!array_key_exists($verb, $normRelatedIssues))
$normRelatedIssues[$verb] = array();
foreach ($ids as $id) {
if (!in_array($id, $normRelatedIssues[$verb]))
$normRelatedIssues[$verb][] = $id;
}
}
// now look at any added / removed ids
$added = $removed = array();
$relatedIssues = $this->issue->getGroupedRelatedIssues(array(), true);
$added = array_diff_key($normRelatedIssues, $relatedIssues);
$removed = array_diff_key($relatedIssues, $normRelatedIssues);
$keysToLookAt = array_keys(
array_intersect_key($relatedIssues, $normRelatedIssues)
);
foreach ($keysToLookAt as $key) {
$a = array_diff($normRelatedIssues[$key], $relatedIssues[$key]);
if (count($a) > 0)
$added[$key] = $a;
$r = array_diff($relatedIssues[$key], $normRelatedIssues[$key]);
if (count($r) > 0)
$removed[$key] = $r;
}
// cache the added / removed data, so we do not have to
// calculate that again
$this->cleaned_data['_added_issue_relations'] = $added;
$this->cleaned_data['_removed_issue_relations'] = $removed;
// As soon as we know that at least one change was done, we
// return the cleaned data and do not go further.
if (strlen(trim($this->cleaned_data['content']))) {
@ -174,6 +273,9 @@ class IDF_Form_IssueUpdate extends IDF_Form_IssueCreate
or ((!is_null($owner) and !is_null($this->issue->get_owner())) and $owner->id != $this->issue->get_owner()->id)) {
return $this->cleaned_data;
}
if (trim($this->issue->due_dtime) != trim($this->cleaned_data['due_dtime'])) {
return $this->cleaned_data;
}
$tags = array();
for ($i=1;$i<7;$i++) {
if (strlen($this->cleaned_data['label'.$i]) > 0) {
@ -214,6 +316,11 @@ class IDF_Form_IssueUpdate extends IDF_Form_IssueCreate
return $this->cleaned_data;
}
}
if (count($this->cleaned_data['_added_issue_relations']) != 0 ||
count($this->cleaned_data['_removed_issue_relations']) != 0) {
return $this->cleaned_data;
}
}
// no changes!
throw new Pluf_Form_Invalid(__('No changes were entered.'));
@ -255,20 +362,22 @@ class IDF_Form_IssueUpdate extends IDF_Form_IssueCreate
foreach ($tags as $tag) {
if (!Pluf_Model_InArray($tag, $oldtags)) {
if (!isset($changes['lb'])) $changes['lb'] = array();
if (!isset($changes['lb']['add'])) $changes['lb']['add'] = array();
if ($tag->class != 'Other') {
$changes['lb'][] = (string) $tag; //new tag
$changes['lb']['add'][] = (string) $tag; //new tag
} else {
$changes['lb'][] = (string) $tag->name;
$changes['lb']['add'][] = (string) $tag->name;
}
}
}
foreach ($oldtags as $tag) {
if (!Pluf_Model_InArray($tag, $tags)) {
if (!isset($changes['lb'])) $changes['lb'] = array();
if (!isset($changes['lb']['rem'])) $changes['lb']['rem'] = array();
if ($tag->class != 'Other') {
$changes['lb'][] = '-'.(string) $tag; //new tag
$changes['lb']['rem'][] = (string) $tag; //new tag
} else {
$changes['lb'][] = '-'.(string) $tag->name;
$changes['lb']['rem'][] = (string) $tag->name;
}
}
}
@ -286,11 +395,56 @@ class IDF_Form_IssueUpdate extends IDF_Form_IssueCreate
or ((!is_null($owner) and !is_null($this->issue->get_owner())) and $owner->id != $this->issue->get_owner()->id)) {
$changes['ow'] = (is_null($owner)) ? '---' : $owner->login;
}
if (trim($this->issue->due_dtime) != trim($this->cleaned_data['due_dtime'])) {
$changes['du'] = Pluf_Template_dateFormat($this->cleaned_data['due_dtime']);
}
// Issue relations - additions
foreach ($this->cleaned_data['_added_issue_relations'] as $verb => $ids) {
$other_verb = $this->relation_types[$verb];
foreach ($ids as $id) {
$related_issue = new IDF_Issue($id);
$rel = new IDF_IssueRelation();
$rel->issue = $this->issue;
$rel->verb = $verb;
$rel->other_issue = $related_issue;
$rel->submitter = $this->user;
$rel->create();
$other_rel = new IDF_IssueRelation();
$other_rel->issue = $related_issue;
$other_rel->verb = $other_verb;
$other_rel->other_issue = $this->issue;
$other_rel->submitter = $this->user;
$other_rel->create();
}
if (!isset($changes['rel'])) $changes['rel'] = array();
if (!isset($changes['rel']['add'])) $changes['rel']['add'] = array();
$changes['rel']['add'][] = $verb.' '.implode(', ', $ids);
}
// Issue relations - removals
foreach ($this->cleaned_data['_removed_issue_relations'] as $verb => $ids) {
foreach ($ids as $id) {
$db = &Pluf::db();
$table = Pluf::factory('IDF_IssueRelation')->getSqlTable();
$sql = new Pluf_SQL('verb=%s AND (
(issue=%s AND other_issue=%s) OR
(other_issue=%s AND issue=%s))',
array($verb,
$this->issue->id, $id,
$this->issue->id, $id));
$db->execute('DELETE FROM '.$table.' WHERE '.$sql->gen());
}
if (!isset($changes['rel'])) $changes['rel'] = array();
if (!isset($changes['rel']['rem'])) $changes['rel']['rem'] = array();
$changes['rel']['rem'][] = $verb.' '.implode(', ', $ids);
}
// Update the issue
$this->issue->batchAssoc('IDF_Tag', $tagids);
$this->issue->summary = trim($this->cleaned_data['summary']);
$this->issue->status = $status;
$this->issue->owner = $owner;
$this->issue->due_dtime = $this->cleaned_data['due_dtime'];
}
// Create the comment
$comment = new IDF_IssueComment();

View File

@ -3,7 +3,7 @@
/*
# ***** BEGIN LICENSE BLOCK *****
# This file is part of InDefero, an open source project management application.
# Copyright (C) 2008 Céondo Ltd and contributors.
# Copyright (C) 2008-2011 Céondo Ltd and contributors.
#
# InDefero is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by

View File

@ -3,7 +3,7 @@
/*
# ***** BEGIN LICENSE BLOCK *****
# This file is part of InDefero, an open source project management application.
# Copyright (C) 2008 Céondo Ltd and contributors.
# Copyright (C) 2008-2011 Céondo Ltd and contributors.
#
# InDefero is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@ -86,7 +86,7 @@ class IDF_Form_Password extends Pluf_Form
$return_url = Pluf_HTTP_URL_urlForView('IDF_Views::passwordRecoveryInputCode');
$tmpl = new Pluf_Template('idf/user/passrecovery-email.txt');
$cr = new Pluf_Crypt(md5(Pluf::f('secret_key')));
$code = trim($cr->encrypt($user->email.':'.$user->id.':'.time()),
$code = trim($cr->encrypt($user->email.':'.$user->id.':'.time().':primary'),
'~');
$code = substr(md5(Pluf::f('secret_key').$code), 0, 2).$code;
$url = Pluf::f('url_base').Pluf_HTTP_URL_urlForView('IDF_Views::passwordRecovery', array($code), array(), false);

View File

@ -3,7 +3,7 @@
/*
# ***** BEGIN LICENSE BLOCK *****
# This file is part of InDefero, an open source project management application.
# Copyright (C) 2008 Céondo Ltd and contributors.
# Copyright (C) 2008-2011 Céondo Ltd and contributors.
#
# InDefero is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by

View File

@ -3,7 +3,7 @@
/*
# ***** BEGIN LICENSE BLOCK *****
# This file is part of InDefero, an open source project management application.
# Copyright (C) 2008 Céondo Ltd and contributors.
# Copyright (C) 2008-2011 Céondo Ltd and contributors.
#
# InDefero is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by

View File

@ -0,0 +1,211 @@
<?php
/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
# ***** BEGIN LICENSE BLOCK *****
# This file is part of InDefero, an open source project management application.
# Copyright(C) 2008-2011 Céondo Ltd and contributors.
#
# InDefero is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
#(at your option) any later version.
#
# InDefero is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#
# ***** END LICENSE BLOCK ***** */
/**
* Configuration of the project.
*/
class IDF_Form_ProjectConf extends Pluf_Form
{
public $project = null;
public function initFields($extra=array())
{
$this->project = $extra['project'];
$conf = $this->project->getConf();
// Basic part
$this->fields['name'] = new Pluf_Form_Field_Varchar(array('required' => true,
'label' => __('Name'),
'initial' => $this->project->name,
));
$this->fields['shortdesc'] = new Pluf_Form_Field_Varchar(array('required' => true,
'label' => __('Short Description'),
'initial' => $this->project->shortdesc,
'widget_attrs' => array('size' => '68'),
));
$this->fields['description'] = new Pluf_Form_Field_Varchar(array('required' => true,
'label' => __('Description'),
'initial' => $this->project->description,
'widget_attrs' => array('cols' => 68,
'rows' => 26,
),
'widget' => 'Pluf_Form_Widget_TextareaInput',
));
$this->fields['external_project_url'] = new Pluf_Form_Field_Varchar(array('required' => false,
'label' => __('External URL'),
'widget_attrs' => array('size' => '68'),
'initial' => $conf->getVal('external_project_url'),
));
$tags = $this->project->get_tags_list();
for ($i=1;$i<7;$i++) {
$initial = '';
if (isset($tags[$i-1])) {
if ($tags[$i-1]->class != 'Other') {
$initial = (string) $tags[$i-1];
} else {
$initial = $tags[$i-1]->name;
}
}
$this->fields['label'.$i] = new Pluf_Form_Field_Varchar(
array('required' => false,
'label' => __('Labels'),
'initial' => $initial,
'widget_attrs' => array(
'maxlength' => 50,
'size' => 20,
),
));
}
// Logo part
$upload_path = Pluf::f('upload_path', false);
if (false === $upload_path) {
throw new Pluf_Exception_SettingError(__('The "upload_path" configuration variable was not set.'));
}
$upload_path .= '/' . $this->project->shortname;
$filename = '/%s';
$this->fields['logo'] = new Pluf_Form_Field_File(array('required' => false,
'label' => __('Update the logo'),
'initial' => '',
'help_text' => __('The logo must be a picture with a size of 32 by 32.'),
'max_size' => Pluf::f('max_upload_size', 5 * 1024),
'move_function_params' =>
array('upload_path' => $upload_path,
'upload_path_create' => true,
'upload_overwrite' => true,
'file_name' => $filename,
)
));
$this->fields['logo_remove'] = new Pluf_Form_Field_Boolean(array('required' => false,
'label' => __('Remove the current logo'),
'initial' => false,
'widget' => 'Pluf_Form_Widget_CheckboxInput',
));
}
/**
* If we have uploaded a file, but the form failed remove it.
*
*/
function failed()
{
if (!empty($this->cleaned_data['logo'])
&& file_exists(Pluf::f('upload_path').'/'.$this->cleaned_data['logo'])) {
unlink(Pluf::f('upload_path').'/'.$this->cleaned_data['logo']);
}
}
public function clean()
{
if (!isset($this->cleaned_data['logo_remove'])) {
$this->cleaned_data['logo_remove'] = false;
}
return $this->cleaned_data;
}
public function clean_logo()
{
if (empty($this->cleaned_data['logo'])) {
return '';
}
$meta = getimagesize(Pluf::f('upload_path') . '/' . $this->project->shortname . $this->cleaned_data['logo']);
if ($meta === false) {
throw new Pluf_Form_Invalid(__('Could not determine the size of the uploaded picture.'));
}
if ($meta[0] !== 32 || $meta[1] !== 32) {
throw new Pluf_Form_Invalid(__('The picture must have a size of 32 by 32.'));
}
return $this->cleaned_data['logo'];
}
public function clean_external_project_url()
{
return self::checkWebURL($this->cleaned_data['external_project_url']);
}
public static function checkWebURL($url)
{
$url = trim($url);
if (empty($url)) {
return '';
}
$parsed = parse_url($url);
if ($parsed === false || !array_key_exists('scheme', $parsed) ||
($parsed['scheme'] != 'http' && $parsed['scheme'] != 'https')) {
throw new Pluf_Form_Invalid(__('The entered URL is invalid. Only http and https URLs are allowed.'));
}
return $url;
}
public function save($commit=true)
{
// Add a tag for each label
$tagids = array();
for ($i=1;$i<7;$i++) {
if (strlen($this->cleaned_data['label'.$i]) > 0) {
if (strpos($this->cleaned_data['label'.$i], ':') !== false) {
list($class, $name) = explode(':', $this->cleaned_data['label'.$i], 2);
list($class, $name) = array(trim($class), trim($name));
} else {
$class = 'Other';
$name = trim($this->cleaned_data['label'.$i]);
}
$tag = IDF_Tag::addGlobal($name, $class);
$tagids[] = $tag->id;
}
}
// Basic part
$this->project->name = $this->cleaned_data['name'];
$this->project->shortdesc = $this->cleaned_data['shortdesc'];
$this->project->description = $this->cleaned_data['description'];
$this->project->batchAssoc('IDF_Tag', $tagids);
$this->project->update();
$conf = $this->project->getConf();
if (!empty($this->cleaned_data['logo'])) {
$conf->setVal('logo', $this->cleaned_data['logo']);
}
if (!empty($this->cleaned_data['external_project_url'])) {
$conf->setVal('external_project_url', $this->cleaned_data['external_project_url']);
}
else {
$conf->delVal('external_project_url');
}
if ($this->cleaned_data['logo_remove'] === true) {
@unlink(Pluf::f('upload_path') . '/' . $this->project->shortname . $conf->getVal('logo'));
$conf->delVal('logo');
}
}
}

View File

@ -3,7 +3,7 @@
/*
# ***** BEGIN LICENSE BLOCK *****
# This file is part of InDefero, an open source project management application.
# Copyright (C) 2008 Céondo Ltd and contributors.
# Copyright (C) 2008-2011 Céondo Ltd and contributors.
#
# InDefero is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@ -42,7 +42,7 @@ class IDF_Form_Register extends Pluf_Form
'max_length' => 15,
'min_length' => 3,
'initial' => $login,
'help_text' => __('The login must be between 3 and 15 characters long and contains only letters and digits.'),
'help_text' => __('The login must be between 3 and 15 characters long and contain only letters and digits.'),
'widget_attrs' => array(
'maxlength' => 15,
'size' => 10,
@ -52,7 +52,7 @@ class IDF_Form_Register extends Pluf_Form
array('required' => true,
'label' => __('Your email'),
'initial' => '',
'help_text' => __('We will never send you any unsolicited emails. We hate spams too!'),
'help_text' => __('We will never send you any unsolicited emails. We hate spam too!'),
));
$this->fields['terms'] = new Pluf_Form_Field_Boolean(
@ -93,10 +93,8 @@ class IDF_Form_Register extends Pluf_Form
function clean_email()
{
$this->cleaned_data['email'] = mb_strtolower(trim($this->cleaned_data['email']));
$guser = new Pluf_User();
$sql = new Pluf_SQL('email=%s', $this->cleaned_data['email']);
if ($guser->getCount(array('filter' => $sql->gen())) > 0) {
throw new Pluf_Form_Invalid(sprintf(__('The email "%s" is already used. If you need, click on the help link to recover your password.'), $this->cleaned_data['email']));
if (Pluf::factory('IDF_EmailAddress')->get_user_for_email_address($this->cleaned_data['email']) != null) {
throw new Pluf_Form_Invalid(sprintf(__('The email "%1$s" is already used. If you need to, you can <a href="%2$s">recover your password</a>.'), $this->cleaned_data['email'], Pluf_HTTP_URL_urlForView('IDF_Views::passwordRecoveryAsk')));
}
return $this->cleaned_data['email'];
}

View File

@ -3,7 +3,7 @@
/*
# ***** BEGIN LICENSE BLOCK *****
# This file is part of InDefero, an open source project management application.
# Copyright (C) 2008 Céondo Ltd and contributors.
# Copyright (C) 2008-2011 Céondo Ltd and contributors.
#
# InDefero is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@ -69,7 +69,7 @@ class IDF_Form_RegisterConfirmation extends Pluf_Form
'label' => __('Your password'),
'initial' => '',
'widget' => 'Pluf_Form_Widget_PasswordInput',
'help_text' => __('Your password must be hard for other people to find it, but easy for you to remember.'),
'help_text' => __('Your password must be hard for other people to guess, but easy for you to remember.'),
'widget_attrs' => array(
'maxlength' => 50,
'size' => 15,
@ -107,7 +107,7 @@ class IDF_Form_RegisterConfirmation extends Pluf_Form
throw new Pluf_Form_Invalid($error);
}
if ($users[0]->active) {
throw new Pluf_Form_Invalid(__('This account has already been confirmed. Maybe should you try to recover your password using the help link.'));
throw new Pluf_Form_Invalid(sprintf(__('This account has already been confirmed. Maybe should you try to <a href="%s">recover your password</a>.'), Pluf_HTTP_URL_urlForView('IDF_Views::passwordRecoveryAsk')));
}
$this->_user_id = $email_id[1];
return $this->cleaned_data['key'];

View File

@ -3,7 +3,7 @@
/*
# ***** BEGIN LICENSE BLOCK *****
# This file is part of InDefero, an open source project management application.
# Copyright (C) 2008 Céondo Ltd and contributors.
# Copyright (C) 2008-2011 Céondo Ltd and contributors.
#
# InDefero is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by

View File

@ -3,7 +3,7 @@
/*
# ***** BEGIN LICENSE BLOCK *****
# This file is part of InDefero, an open source project management application.
# Copyright (C) 2008 Céondo Ltd and contributors.
# Copyright (C) 2008-2011 Céondo Ltd and contributors.
#
# InDefero is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by

View File

@ -3,7 +3,7 @@
/*
# ***** BEGIN LICENSE BLOCK *****
# This file is part of InDefero, an open source project management application.
# Copyright (C) 2008 Céondo Ltd and contributors.
# Copyright (C) 2008-2011 Céondo Ltd and contributors.
#
# InDefero is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@ -52,7 +52,7 @@ class IDF_Form_ReviewFileComment extends Pluf_Form
));
}
$this->fields['content'] = new Pluf_Form_Field_Varchar(
array('required' => true,
array('required' => false,
'label' => __('General comment'),
'initial' => '',
'widget' => 'Pluf_Form_Widget_TextareaInput',
@ -64,6 +64,8 @@ class IDF_Form_ReviewFileComment extends Pluf_Form
if ($this->user->hasPerm('IDF.project-owner', $this->project)
or $this->user->hasPerm('IDF.project-member', $this->project)) {
$this->show_full = true;
} else {
$this->show_full = false;
}
if ($this->show_full) {
$this->fields['summary'] = new Pluf_Form_Field_Varchar(
@ -94,24 +96,40 @@ class IDF_Form_ReviewFileComment extends Pluf_Form
*/
public function clean()
{
foreach ($this->files as $filename => $def) {
if (!empty($this->cleaned_data[md5($filename)])) {
return $this->cleaned_data;
$isOk = false;
foreach($this->files as $filename => $def) {
$this->cleaned_data[md5($filename)] = trim($this->cleaned_data[md5($filename)]);
if(!empty($this->cleaned_data[md5($filename)])) {
$isOk = true;
}
}
throw new Pluf_Form_Invalid(__('You need to provide comments on at least one file.'));
if(!empty($this->cleaned_data['content'])) {
$isOk = true;
}
if (!$isOk) {
throw new Pluf_Form_Invalid(__('You need to provide your general comment about the proposal, or comments on at least one file.'));
}
return $this->cleaned_data;
}
function clean_content()
{
$content = trim($this->cleaned_data['content']);
if (!$this->show_full and strlen($content) == 0) {
throw new Pluf_Form_Invalid(__('You need to provide your general comment about the proposal.'));
if(empty($content)) {
if ($this->fields['status']->initial != $this->fields['status']->value) {
return __('The status have been updated.');
}
} else {
return $content;
}
return $content;
throw new Pluf_Form_Invalid(__('This field is required.'));
}
/**
* Save the model in the database.
*

View File

@ -3,7 +3,7 @@
/*
# ***** BEGIN LICENSE BLOCK *****
# This file is part of InDefero, an open source project management application.
# Copyright (C) 2008 Céondo Ltd and contributors.
# Copyright (C) 2008-2011 Céondo Ltd and contributors.
#
# InDefero is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@ -49,13 +49,10 @@ class IDF_Form_SourceConf extends Pluf_Form
'widget' => 'Pluf_Form_Widget_PasswordInput',
));
}
Pluf::loadFunction('Pluf_HTTP_URL_urlForView');
$url = Pluf_HTTP_URL_urlForView('idf_faq').'#webhooks';
$this->fields['webhook_url'] = new Pluf_Form_Field_Url(
array('required' => false,
'label' => __('Webhook URL'),
'initial' => $this->conf->getVal('webhook_url', ''),
'help_text' => sprintf(__('Learn more about the <a href="%s">post-commit web hooks</a>.'), $url),
'widget_attrs' => array('size' => 35),
));

View File

@ -3,7 +3,7 @@
/*
# ***** BEGIN LICENSE BLOCK *****
# This file is part of InDefero, an open source project management application.
# Copyright (C) 2008 Céondo Ltd and contributors.
# Copyright (C) 2008-2011 Céondo Ltd and contributors.
#
# InDefero is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@ -57,20 +57,44 @@ class IDF_Form_TabsConf extends Pluf_Form
'widget' => 'Pluf_Form_Widget_SelectInput',
));
}
$ak = array('downloads_notification_email',
'review_notification_email',
'wiki_notification_email',
'source_notification_email',
'issues_notification_email',);
foreach ($ak as $key) {
$this->fields[$key] = new IDF_Form_Field_EmailList(
array('required' => false,
'label' => $key,
'initial' => $this->conf->getVal($key, ''),
'widget_attrs' => array('size' => 40),
));
}
$sections = array(
'downloads_notification',
'review_notification',
'wiki_notification',
'source_notification',
'issues_notification',
);
foreach ($sections as $section) {
$this->fields[$section.'_owners_enabled'] = new Pluf_Form_Field_Boolean(
array('required' => false,
'label' => __('Project owners'),
'initial' => $this->conf->getVal($section.'_owners_enabled', false),
'widget' => 'Pluf_Form_Widget_CheckboxInput',
));
$this->fields[$section.'_members_enabled'] = new Pluf_Form_Field_Boolean(
array('required' => false,
'label' => __('Project members'),
'initial' => $this->conf->getVal($section.'_members_enabled', false),
'widget' => 'Pluf_Form_Widget_CheckboxInput',
));
$this->fields[$section.'_email_enabled'] = new Pluf_Form_Field_Boolean(
array('required' => false,
'label' => __('Others'),
'initial' => $this->conf->getVal($section.'_email_enabled', false),
'widget' => 'Pluf_Form_Widget_CheckboxInput',
));
if ($this->conf->getVal($section.'_email_enabled', false)) {
$attrs['readonly'] = 'readonly';
}
$this->fields[$section.'_email'] = new IDF_Form_Field_EmailList(
array('required' => false,
'label' => null,
'initial' => $this->conf->getVal($section.'_email', ''),
'widget_attrs' => array('size' => 20),
));
}
$this->fields['private_project'] = new Pluf_Form_Field_Boolean(
array('required' => false,

View File

@ -3,7 +3,7 @@
/*
# ***** BEGIN LICENSE BLOCK *****
# This file is part of InDefero, an open source project management application.
# Copyright (C) 2008 Céondo Ltd and contributors.
# Copyright (C) 2008-2011 Céondo Ltd and contributors.
#
# InDefero is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@ -96,7 +96,7 @@ class IDF_Form_UpdateUpload extends Pluf_Form
$this->cleaned_data['label'.$i] = trim($this->cleaned_data['label'.$i]);
if (strpos($this->cleaned_data['label'.$i], ':') !== false) {
list($class, $name) = explode(':', $this->cleaned_data['label'.$i], 2);
list($class, $name) = array(mb_strtolower(trim($class)),
list($class, $name) = array(mb_strtolower(trim($class)),
trim($name));
} else {
$class = 'other';
@ -106,7 +106,7 @@ class IDF_Form_UpdateUpload extends Pluf_Form
else $count[$class] += 1;
if (in_array($class, $onemax) and $count[$class] > 1) {
if (!isset($this->errors['label'.$i])) $this->errors['label'.$i] = array();
$this->errors['label'.$i][] = sprintf(__('You cannot provide more than label from the %s class to an issue.'), $class);
$this->errors['label'.$i][] = sprintf(__('You cannot provide more than one label from the %s class to an issue.'), $class);
throw new Pluf_Form_Invalid(__('You provided an invalid label.'));
}
}
@ -146,6 +146,9 @@ class IDF_Form_UpdateUpload extends Pluf_Form
$this->upload->modif_dtime = gmdate('Y-m-d H:i:s');
$this->upload->update();
$this->upload->batchAssoc('IDF_Tag', $tags);
// Send the notification
$this->upload->notify($this->project->getConf(), false);
/**
* [signal]
*
@ -166,7 +169,7 @@ class IDF_Form_UpdateUpload extends Pluf_Form
*
*/
$params = array('upload' => $this->upload);
Pluf_Signal::send('IDF_Upload::update',
Pluf_Signal::send('IDF_Upload::update',
'IDF_Form_UpdateUpload', $params);
return $this->upload;
}

View File

@ -3,7 +3,7 @@
/*
# ***** BEGIN LICENSE BLOCK *****
# This file is part of InDefero, an open source project management application.
# Copyright (C) 2008 Céondo Ltd and contributors.
# Copyright (C) 2008-2011 Céondo Ltd and contributors.
#
# InDefero is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@ -79,11 +79,12 @@ class IDF_Form_Upload extends Pluf_Form
public function clean_file()
{
// FIXME: we do the same in IDF_Form_WikiResourceCreate and a couple of other places as well
$extra = strtolower(implode('|', explode(' ', Pluf::f('idf_extra_upload_ext'))));
if (strlen($extra)) $extra .= '|';
if (!preg_match('/\.('.$extra.'png|jpg|jpeg|gif|bmp|psd|tif|aiff|asf|avi|bz2|css|doc|eps|gz|jar|mdtext|mid|mov|mp3|mpg|ogg|pdf|ppt|ps|qt|ra|ram|rm|rtf|sdd|sdw|sit|sxi|sxw|swf|tgz|txt|wav|xls|xml|war|wmv|zip)$/i', $this->cleaned_data['file'])) {
@unlink(Pluf::f('upload_path').'/'.$this->project->shortname.'/files/'.$this->cleaned_data['file']);
throw new Pluf_Form_Invalid(__('For security reason, you cannot upload a file with this extension.'));
throw new Pluf_Form_Invalid(__('For security reasons, you cannot upload a file with this extension.'));
}
return $this->cleaned_data['file'];
}
@ -106,7 +107,7 @@ class IDF_Form_Upload extends Pluf_Form
$this->cleaned_data['label'.$i] = trim($this->cleaned_data['label'.$i]);
if (strpos($this->cleaned_data['label'.$i], ':') !== false) {
list($class, $name) = explode(':', $this->cleaned_data['label'.$i], 2);
list($class, $name) = array(mb_strtolower(trim($class)),
list($class, $name) = array(mb_strtolower(trim($class)),
trim($name));
} else {
$class = 'other';
@ -116,7 +117,7 @@ class IDF_Form_Upload extends Pluf_Form
else $count[$class] += 1;
if (in_array($class, $onemax) and $count[$class] > 1) {
if (!isset($this->errors['label'.$i])) $this->errors['label'.$i] = array();
$this->errors['label'.$i][] = sprintf(__('You cannot provide more than label from the %s class to an issue.'), $class);
$this->errors['label'.$i][] = sprintf(__('You cannot provide more than one label from the %s class to a download.'), $class);
throw new Pluf_Form_Invalid(__('You provided an invalid label.'));
}
}
@ -129,7 +130,7 @@ class IDF_Form_Upload extends Pluf_Form
*/
function failed()
{
if (!empty($this->cleaned_data['file'])
if (!empty($this->cleaned_data['file'])
and file_exists(Pluf::f('upload_path').'/'.$this->project->shortname.'/files/'.$this->cleaned_data['file'])) {
@unlink(Pluf::f('upload_path').'/'.$this->project->shortname.'/files/'.$this->cleaned_data['file']);
}

View File

@ -0,0 +1,227 @@
<?php
/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
# ***** BEGIN LICENSE BLOCK *****
# This file is part of InDefero, an open source project management application.
# Copyright (C) 2008-2011 Céondo Ltd and contributors.
#
# InDefero is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# InDefero is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#
# ***** END LICENSE BLOCK ***** */
/**
* Upload and process an archive file.
*
*/
class IDF_Form_UploadArchive extends Pluf_Form
{
public $user = null;
public $project = null;
private $archiveHelper = null;
public function initFields($extra=array())
{
$this->user = $extra['user'];
$this->project = $extra['project'];
$this->fields['archive'] = new Pluf_Form_Field_File(
array('required' => true,
'label' => __('Archive file'),
'initial' => '',
'max_size' => Pluf::f('max_upload_archive_size', 20971520),
'move_function_params' => array(
'upload_path' => Pluf::f('upload_path').'/'.$this->project->shortname.'/archives',
'upload_path_create' => true,
'upload_overwrite' => true,
)));
}
public function clean_archive()
{
$this->archiveHelper = new IDF_Form_UploadArchiveHelper(
Pluf::f('upload_path').'/'.$this->project->shortname.'/archives/'.$this->cleaned_data['archive']);
// basic archive validation
$this->archiveHelper->validate();
// extension validation
$fileNames = $this->archiveHelper->getEntryNames();
foreach ($fileNames as $fileName) {
$extra = strtolower(implode('|', explode(' ', Pluf::f('idf_extra_upload_ext'))));
if (strlen($extra)) $extra .= '|';
if (!preg_match('/\.('.$extra.'png|jpg|jpeg|gif|bmp|psd|tif|aiff|asf|avi|bz2|css|doc|eps|gz|jar|mdtext|mid|mov|mp3|mpg|ogg|pdf|ppt|ps|qt|ra|ram|rm|rtf|sdd|sdw|sit|sxi|sxw|swf|tgz|txt|wav|xls|xml|war|wmv|zip)$/i', $fileName)) {
@unlink(Pluf::f('upload_path').'/'.$this->project->shortname.'/files/'.$this->cleaned_data['archive']);
throw new Pluf_Form_Invalid(sprintf(__('For security reasons, you cannot upload a file (%s) with this extension.'), $fileName));
}
}
// label and file name validation
$conf = new IDF_Conf();
$conf->setProject($this->project);
$onemax = array();
foreach (explode(',', $conf->getVal('labels_download_one_max', IDF_Form_UploadConf::init_one_max)) as $class) {
if (trim($class) != '') {
$onemax[] = mb_strtolower(trim($class));
}
}
foreach ($fileNames as $fileName) {
$meta = $this->archiveHelper->getMetaData($fileName);
$count = array();
foreach ($meta['labels'] as $label) {
$label = trim($label);
if (strpos($label, ':') !== false) {
list($class, $name) = explode(':', $label, 2);
list($class, $name) = array(mb_strtolower(trim($class)),
trim($name));
} else {
$class = 'other';
$name = $label;
}
if (!isset($count[$class])) $count[$class] = 1;
else $count[$class] += 1;
if (in_array($class, $onemax) and $count[$class] > 1) {
throw new Pluf_Form_Invalid(
sprintf(__('You cannot provide more than label from the %1$s class to a download (%2$s).'), $class, $name)
);
}
}
$sql = new Pluf_SQL('file=%s AND project=%s', array($fileName, $this->project->id));
$upload = Pluf::factory('IDF_Upload')->getOne(array('filter' => $sql->gen()));
$meta = $this->archiveHelper->getMetaData($fileName);
if ($upload != null && $meta['replaces'] !== $fileName) {
throw new Pluf_Form_Invalid(
sprintf(__('A file with the name "%s" has already been uploaded and is not marked to be replaced.'), $fileName));
}
}
return $this->cleaned_data['archive'];
}
/**
* If we have uploaded a file, but the form failed remove it.
*
*/
function failed()
{
if (!empty($this->cleaned_data['archive'])
and file_exists(Pluf::f('upload_path').'/'.$this->project->shortname.'/archives/'.$this->cleaned_data['archive'])) {
@unlink(Pluf::f('upload_path').'/'.$this->project->shortname.'/archives/'.$this->cleaned_data['archive']);
}
}
/**
* Save the model in the database.
*
* @param bool Commit in the database or not. If not, the object
* is returned but not saved in the database.
*/
function save($commit=true)
{
if (!$this->isValid()) {
throw new Exception(__('Cannot save the model from an invalid form.'));
}
$uploadDir = Pluf::f('upload_path').'/'.$this->project->shortname.'/files/';
$fileNames = $this->archiveHelper->getEntryNames();
foreach ($fileNames as $fileName) {
$meta = $this->archiveHelper->getMetaData($fileName);
// add a tag for each label
$tags = array();
foreach ($meta['labels'] as $label) {
$label = trim($label);
if (strlen($label) > 0) {
if (strpos($label, ':') !== false) {
list($class, $name) = explode(':', $label, 2);
list($class, $name) = array(trim($class), trim($name));
} else {
$class = 'Other';
$name = $label;
}
$tags[] = IDF_Tag::add($name, $this->project, $class);
}
}
// process a possible replacement
if (!empty($meta['replaces'])) {
$sql = new Pluf_SQL('file=%s AND project=%s', array($meta['replaces'], $this->project->id));
$oldUpload = Pluf::factory('IDF_Upload')->getOne(array('filter' => $sql->gen()));
if ($oldUpload) {
if ($meta['replaces'] === $fileName) {
$oldUpload->delete();
} else {
$tags = $this->project->getTagsFromConfig('labels_download_predefined',
IDF_Form_UploadConf::init_predefined);
// the deprecate tag is - by definition - always the last one
$deprecatedTag = array_pop($tags);
$oldUpload->setAssoc($deprecatedTag);
}
}
}
// extract the file
$this->archiveHelper->extract($fileName, $uploadDir);
// create the upload
$upload = new IDF_Upload();
$upload->project = $this->project;
$upload->submitter = $this->user;
$upload->summary = trim($meta['summary']);
$upload->changelog = trim($meta['description']);
$upload->file = $fileName;
$upload->filesize = filesize($uploadDir.$fileName);
$upload->downloads = 0;
$upload->create();
foreach ($tags as $tag) {
$upload->setAssoc($tag);
}
// send the notification
$upload->notify($this->project->getConf());
/**
* [signal]
*
* IDF_Upload::create
*
* [sender]
*
* IDF_Form_Upload
*
* [description]
*
* This signal allows an application to perform a set of tasks
* just after the upload of a file and after the notification run.
*
* [parameters]
*
* array('upload' => $upload);
*
*/
$params = array('upload' => $upload);
Pluf_Signal::send('IDF_Upload::create', 'IDF_Form_Upload',
$params);
}
// finally unlink the uploaded archive
@unlink(Pluf::f('upload_path').'/'.$this->project->shortname.'/archives/'.$this->cleaned_data['archive']);
}
}

View File

@ -0,0 +1,158 @@
<?php
/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
# ***** BEGIN LICENSE BLOCK *****
# This file is part of InDefero, an open source project management application.
# Copyright (C) 2008-2011 Céondo Ltd and contributors.
#
# InDefero is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# InDefero is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#
# ***** END LICENSE BLOCK ***** */
class IDF_Form_UploadArchiveHelper
{
private $file = null;
private $entries = array();
public function __construct($file)
{
$this->file = $file;
}
/**
* Validates the archive; throws a invalid form exception in case the
* archive contains invalid data or cannot be read.
*/
public function validate()
{
if (!file_exists($this->file)) {
throw new Pluf_Form_Invalid(__('The archive does not exist.'));
}
$za = new ZipArchive();
$res = $za->open($this->file);
if ($res !== true) {
throw new Pluf_Form_Invalid(
sprintf(__('The archive could not be read (code %d).'), $res));
}
$manifest = $za->getFromName('manifest.xml');
if ($manifest === false) {
throw new Pluf_Form_Invalid(__('The archive does not contain a manifest.xml.'));
}
libxml_use_internal_errors(true);
$xml = @simplexml_load_string($manifest);
if ($xml === false) {
$error = libxml_get_last_error();
throw new Pluf_Form_Invalid(
sprintf(__('The archive\'s manifest is invalid: %s'), $error->message));
}
foreach (@$xml->file as $idx => $file)
{
$entry = array(
'name' => (string)@$file->name,
'summary' => (string)@$file->summary,
'description' => (string)@$file->description,
'replaces' => (string)@$file->replaces,
'labels' => array(),
'stream' => null
);
if (empty($entry['name'])) {
throw new Pluf_Form_Invalid(
sprintf(__('The entry %d in the manifest is missing a file name.'), $idx));
}
if (empty($entry['summary'])) {
throw new Pluf_Form_Invalid(
sprintf(__('The entry %d in the manifest is missing a summary.'), $idx));
}
if ($entry['name'] === 'manifest.xml') {
throw new Pluf_Form_Invalid(__('The manifest must not reference itself.'));
}
if ($za->locateName($entry['name']) === false) {
throw new Pluf_Form_Invalid(
sprintf(__('The entry %s in the manifest does not exist in the archive.'), $entry['name']));
}
if (in_array($entry['name'], $this->entries)) {
throw new Pluf_Form_Invalid(
sprintf(__('The entry %s in the manifest is referenced more than once.'), $entry['name']));
}
if ($file->labels) {
foreach (@$file->labels->label as $label) {
$entry['labels'][] = (string)$label;
}
}
// FIXME: remove this once we allow more than six labels everywhere
if (count($entry['labels']) > 6) {
throw new Pluf_Form_Invalid(
sprintf(__('The entry %s in the manifest has more than the six allowed labels set.'), $entry['name']));
}
$this->entries[$entry['name']] = $entry;
}
$za->close();
}
/**
* Returns all entry names
*
* @return array of string
*/
public function getEntryNames()
{
return array_keys($this->entries);
}
/**
* Returns meta data for the given entry
*
* @param string $name
* @throws Exception
*/
public function getMetaData($name)
{
if (!array_key_exists($name, $this->entries)) {
throw new Exception('unknown file ' . $name);
}
return $this->entries[$name];
}
/**
* Extracts the file entry $name at $path
*
* @param string $name
* @param string $path
* @throws Exception
*/
public function extract($name, $path)
{
if (!array_key_exists($name, $this->entries)) {
throw new Exception('unknown file ' . $name);
}
$za = new ZipArchive();
$za->open($this->file);
$za->extractTo($path, $name);
$za->close();
}
}

View File

@ -3,7 +3,7 @@
/*
# ***** BEGIN LICENSE BLOCK *****
# This file is part of InDefero, an open source project management application.
# Copyright (C) 2008 Céondo Ltd and contributors.
# Copyright (C) 2008-2011 Céondo Ltd and contributors.
#
# InDefero is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@ -60,10 +60,18 @@ Deprecated = Most users should NOT download this';
$this->fields['labels_download_one_max'] = new Pluf_Form_Field_Varchar(
array('required' => false,
'label' => __('Each download may have at most one label with each of these classes'),
'initial' => self::init_one_max,
'initial' => self::init_one_max,
'widget_attrs' => array('size' => 60),
));
$this->conf = $extra['conf'];
$this->fields['upload_webhook_url'] = new Pluf_Form_Field_Url(
array('required' => false,
'label' => __('Webhook URL'),
'initial' => $this->conf->getVal('upload_webhook_url', ''),
'widget_attrs' => array('size' => 60),
));
}
}

View File

@ -3,7 +3,7 @@
/*
# ***** BEGIN LICENSE BLOCK *****
# This file is part of InDefero, an open source project management application.
# Copyright (C) 2008 Céondo Ltd and contributors.
# Copyright (C) 2008-2011 Céondo Ltd and contributors.
#
# InDefero is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@ -56,7 +56,7 @@ class IDF_Form_UserAccount extends Pluf_Form
$this->fields['email'] = new Pluf_Form_Field_Email(
array('required' => true,
'label' => __('Your mail'),
'label' => __('Your email'),
'initial' => $this->user->email,
'help_text' => __('If you change your email address, an email will be sent to the new address to confirm it.'),
));
@ -79,6 +79,7 @@ class IDF_Form_UserAccount extends Pluf_Form
'widget' => 'Pluf_Form_Widget_PasswordInput',
'help_text' => Pluf_Template::markSafe(__('Leave blank if you do not want to change your password.').'<br />'.__('Your password must be hard for other people to find it, but easy for you to remember.')),
'widget_attrs' => array(
'autocomplete' => 'off',
'maxlength' => 50,
'size' => 15,
),
@ -89,6 +90,7 @@ class IDF_Form_UserAccount extends Pluf_Form
'initial' => '',
'widget' => 'Pluf_Form_Widget_PasswordInput',
'widget_attrs' => array(
'autocomplete' => 'off',
'maxlength' => 50,
'size' => 15,
),
@ -161,8 +163,44 @@ class IDF_Form_UserAccount extends Pluf_Form
'widget_attrs' => array('rows' => 3,
'cols' => 40),
'widget' => 'Pluf_Form_Widget_TextareaInput',
'help_text' => __('Paste a SSH or monotone public key. Be careful to not provide your private key here!')
'help_text' => __('Paste an SSH or monotone public key. Be careful to not provide your private key here!')
));
$this->fields['secondary_mail'] = new Pluf_Form_Field_Email(
array('required' => false,
'label' => __('Add a secondary email address'),
'initial' => '',
'help_text' => __('You will get an email to confirm that you own the address you specify.'),
));
}
private function send_validation_mail($new_email, $secondary_mail=false)
{
if ($secondary_mail) {
$type = "secondary";
} else {
$type = "primary";
}
$cr = new Pluf_Crypt(md5(Pluf::f('secret_key')));
$encrypted = trim($cr->encrypt($new_email.':'.$this->user->id.':'.time().':'.$type), '~');
$key = substr(md5(Pluf::f('secret_key').$encrypted), 0, 2).$encrypted;
$url = Pluf::f('url_base').Pluf_HTTP_URL_urlForView('IDF_Views_User::changeEmailDo', array($key), array(), false);
$urlik = Pluf::f('url_base').Pluf_HTTP_URL_urlForView('IDF_Views_User::changeEmailInputKey', array(), array(), false);
$context = new Pluf_Template_Context(
array('key' => Pluf_Template::markSafe($key),
'url' => Pluf_Template::markSafe($url),
'urlik' => Pluf_Template::markSafe($urlik),
'email' => $new_email,
'user'=> $this->user,
)
);
$tmpl = new Pluf_Template('idf/user/changeemail-email.txt');
$text_email = $tmpl->render($context);
$email = new Pluf_Mail(Pluf::f('from_email'), $new_email,
__('Confirm your new email address.'));
$email->addTextMessage($text_email);
$email->sendMail();
$this->user->setMessage(sprintf(__('A validation email has been sent to "%s" to validate the email address change.'), Pluf_esc($new_email)));
}
/**
@ -188,26 +226,7 @@ class IDF_Form_UserAccount extends Pluf_Form
$new_email = $this->cleaned_data['email'];
unset($this->cleaned_data['email']);
if ($old_email != $new_email) {
$cr = new Pluf_Crypt(md5(Pluf::f('secret_key')));
$encrypted = trim($cr->encrypt($new_email.':'.$this->user->id.':'.time()), '~');
$key = substr(md5(Pluf::f('secret_key').$encrypted), 0, 2).$encrypted;
$url = Pluf::f('url_base').Pluf_HTTP_URL_urlForView('IDF_Views_User::changeEmailDo', array($key), array(), false);
$urlik = Pluf::f('url_base').Pluf_HTTP_URL_urlForView('IDF_Views_User::changeEmailInputKey', array(), array(), false);
$context = new Pluf_Template_Context(
array('key' => Pluf_Template::markSafe($key),
'url' => Pluf_Template::markSafe($url),
'urlik' => Pluf_Template::markSafe($urlik),
'email' => $new_email,
'user'=> $this->user,
)
);
$tmpl = new Pluf_Template('idf/user/changeemail-email.txt');
$text_email = $tmpl->render($context);
$email = new Pluf_Mail(Pluf::f('from_email'), $new_email,
__('Confirm your new email address.'));
$email->addTextMessage($text_email);
$email->sendMail();
$this->user->setMessage(sprintf(__('A validation email has been sent to "%s" to validate the email address change.'), Pluf_esc($new_email)));
$this->send_validation_mail($new_email);
}
$this->user->setFromFormData($this->cleaned_data);
// Add key as needed.
@ -219,6 +238,9 @@ class IDF_Form_UserAccount extends Pluf_Form
$key->create();
}
}
if ('' !== $this->cleaned_data['secondary_mail']) {
$this->send_validation_mail($this->cleaned_data['secondary_mail'], true);
}
if ($commit) {
$this->user->update();
@ -295,8 +317,15 @@ class IDF_Form_UserAccount extends Pluf_Form
return '';
}
if (preg_match('#^ssh\-[a-z]{3}\s\S+(\s\S+)?$#', $key)) {
$key = str_replace(array("\n", "\r"), '', $key);
$keysearch = '';
if (preg_match('#^(ssh\-(?:dss|rsa)\s+\S+)(.*)#', $key, $m)) {
$basekey = preg_replace('/\s+/', ' ', $m[1]);
$comment = trim(preg_replace('/[\r\n]/', ' ', $m[2]));
$keysearch = $basekey.'%';
$key = $basekey;
if (!empty($comment))
$key .= ' '.$comment;
if (Pluf::f('idf_strong_key_check', false)) {
@ -315,7 +344,9 @@ class IDF_Form_UserAccount extends Pluf_Form
}
}
}
else if (preg_match('#^\[pubkey [^\]]+\]\s*\S+\s*\[end\]$#', $key)) {
else if (preg_match('#^\[pubkey [^\]]+\]\s*(\S+)\s*\[end\]$#', $key, $m)) {
$keysearch = '%'.$m[1].'%';
if (Pluf::f('idf_strong_key_check', false)) {
// if monotone can read it, it should be valid
@ -337,7 +368,7 @@ class IDF_Form_UserAccount extends Pluf_Form
}
else {
throw new Pluf_Form_Invalid(
__('Public key looks neither like a SSH '.
__('Public key looks like neither an SSH '.
'nor monotone public key.'));
}
@ -345,7 +376,7 @@ class IDF_Form_UserAccount extends Pluf_Form
if ($user) {
$ruser = Pluf::factory('Pluf_User', $user);
if ($ruser->id > 0) {
$sql = new Pluf_SQL('content=%s', array($key));
$sql = new Pluf_SQL('content LIKE %s AND user=%s', array($keysearch, $ruser->id));
$keys = Pluf::factory('IDF_Key')->getList(array('filter' => $sql->gen()));
if (count($keys) > 0) {
throw new Pluf_Form_Invalid(
@ -393,15 +424,22 @@ class IDF_Form_UserAccount extends Pluf_Form
function clean_email()
{
$this->cleaned_data['email'] = mb_strtolower(trim($this->cleaned_data['email']));
$guser = new Pluf_User();
$sql = new Pluf_SQL('email=%s AND id!=%s',
array($this->cleaned_data['email'], $this->user->id));
if ($guser->getCount(array('filter' => $sql->gen())) > 0) {
$user = Pluf::factory('IDF_EmailAddress')->get_user_for_email_address($this->cleaned_data['email']);
if ($user != null and $user->id != $this->user->id) {
throw new Pluf_Form_Invalid(sprintf(__('The email "%s" is already used.'), $this->cleaned_data['email']));
}
return $this->cleaned_data['email'];
}
function clean_secondary_mail()
{
$this->cleaned_data['secondary_mail'] = mb_strtolower(trim($this->cleaned_data['secondary_mail']));
if (Pluf::factory('IDF_EmailAddress')->get_user_for_email_address($this->cleaned_data['secondary_mail']) != null) {
throw new Pluf_Form_Invalid(sprintf(__('The email "%s" is already used.'), $this->cleaned_data['secondary_mail']));
}
return $this->cleaned_data['secondary_mail'];
}
function clean_public_key()
{
$this->cleaned_data['public_key'] =

View File

@ -3,7 +3,7 @@
/*
# ***** BEGIN LICENSE BLOCK *****
# This file is part of InDefero, an open source project management application.
# Copyright (C) 2008 Céondo Ltd and contributors.
# Copyright (C) 2008-2011 Céondo Ltd and contributors.
#
# InDefero is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@ -53,7 +53,7 @@ class IDF_Form_UserChangeEmail extends Pluf_Form
* Throw a Pluf_Form_Invalid exception if the key is not valid.
*
* @param string Key
* @return array array($new_email, $user_id, time())
* @return array array($new_email, $user_id, time(), [primary|secondary])
*/
public static function validateKey($key)
{
@ -63,7 +63,7 @@ class IDF_Form_UserChangeEmail extends Pluf_Form
throw new Pluf_Form_Invalid(__('The validation key is not valid. Please copy/paste it from your confirmation email.'));
}
$cr = new Pluf_Crypt(md5(Pluf::f('secret_key')));
return explode(':', $cr->decrypt($encrypted), 3);
return explode(':', $cr->decrypt($encrypted), 4);
}

View File

@ -3,7 +3,7 @@
/*
# ***** BEGIN LICENSE BLOCK *****
# This file is part of InDefero, an open source project management application.
# Copyright (C) 2008 Céondo Ltd and contributors.
# Copyright (C) 2008-2011 Céondo Ltd and contributors.
#
# InDefero is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by

View File

@ -3,7 +3,7 @@
/*
# ***** BEGIN LICENSE BLOCK *****
# This file is part of InDefero, an open source project management application.
# Copyright (C) 2008 Céondo Ltd and contributors.
# Copyright (C) 2008-2011 Céondo Ltd and contributors.
#
# InDefero is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@ -27,7 +27,7 @@
* This create a new page and the corresponding revision.
*
*/
class IDF_Form_WikiCreate extends Pluf_Form
class IDF_Form_WikiPageCreate extends Pluf_Form
{
public $user = null;
public $project = null;
@ -107,9 +107,9 @@ Add your content here. Format your content with:
if (preg_match('/[^a-zA-Z0-9\-]/', $title)) {
throw new Pluf_Form_Invalid(__('The title contains invalid characters.'));
}
$sql = new Pluf_SQL('project=%s AND title=%s',
$sql = new Pluf_SQL('project=%s AND title=%s',
array($this->project->id, $title));
$pages = Pluf::factory('IDF_WikiPage')->getList(array('filter'=>$sql->gen()));
$pages = Pluf::factory('IDF_Wiki_Page')->getList(array('filter'=>$sql->gen()));
if ($pages->count() > 0) {
throw new Pluf_Form_Invalid(__('A page with this title already exists.'));
}
@ -137,7 +137,7 @@ Add your content here. Format your content with:
$this->cleaned_data['label'.$i] = trim($this->cleaned_data['label'.$i]);
if (strpos($this->cleaned_data['label'.$i], ':') !== false) {
list($class, $name) = explode(':', $this->cleaned_data['label'.$i], 2);
list($class, $name) = array(mb_strtolower(trim($class)),
list($class, $name) = array(mb_strtolower(trim($class)),
trim($name));
} else {
$class = 'other';
@ -147,7 +147,7 @@ Add your content here. Format your content with:
else $count[$class] += 1;
if (in_array($class, $onemax) and $count[$class] > 1) {
if (!isset($this->errors['label'.$i])) $this->errors['label'.$i] = array();
$this->errors['label'.$i][] = sprintf(__('You cannot provide more than label from the %s class to a page.'), $class);
$this->errors['label'.$i][] = sprintf(__('You cannot provide more than one label from the %s class to a page.'), $class);
throw new Pluf_Form_Invalid(__('You provided an invalid label.'));
}
}
@ -181,9 +181,9 @@ Add your content here. Format your content with:
$tags[] = IDF_Tag::add($name, $this->project, $class);
}
}
}
}
// Create the page
$page = new IDF_WikiPage();
$page = new IDF_Wiki_Page();
$page->project = $this->project;
$page->submitter = $this->user;
$page->summary = trim($this->cleaned_data['summary']);
@ -193,7 +193,7 @@ Add your content here. Format your content with:
$page->setAssoc($tag);
}
// add the first revision
$rev = new IDF_WikiRevision();
$rev = new IDF_Wiki_PageRevision();
$rev->wikipage = $page;
$rev->content = $this->cleaned_data['content'];
$rev->submitter = $this->user;

View File

@ -3,7 +3,7 @@
/*
# ***** BEGIN LICENSE BLOCK *****
# This file is part of InDefero, an open source project management application.
# Copyright (C) 2008 Céondo Ltd and contributors.
# Copyright (C) 2008-2011 Céondo Ltd and contributors.
#
# InDefero is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@ -27,7 +27,7 @@
* This is a hard delete of the page and the revisions.
*
*/
class IDF_Form_WikiDelete extends Pluf_Form
class IDF_Form_WikiPageDelete extends Pluf_Form
{
protected $page = null;

View File

@ -3,7 +3,7 @@
/*
# ***** BEGIN LICENSE BLOCK *****
# This file is part of InDefero, an open source project management application.
# Copyright (C) 2008 Céondo Ltd and contributors.
# Copyright (C) 2008-2011 Céondo Ltd and contributors.
#
# InDefero is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@ -27,13 +27,13 @@
* This add a corresponding revision.
*
*/
class IDF_Form_WikiUpdate extends Pluf_Form
class IDF_Form_WikiPageUpdate extends Pluf_Form
{
public $user = null;
public $project = null;
public $page = null;
public $show_full = false;
public function initFields($extra=array())
{
@ -118,9 +118,9 @@ class IDF_Form_WikiUpdate extends Pluf_Form
if (preg_match('/[^a-zA-Z0-9\-]/', $title)) {
throw new Pluf_Form_Invalid(__('The title contains invalid characters.'));
}
$sql = new Pluf_SQL('project=%s AND title=%s',
$sql = new Pluf_SQL('project=%s AND title=%s',
array($this->project->id, $title));
$pages = Pluf::factory('IDF_WikiPage')->getList(array('filter'=>$sql->gen()));
$pages = Pluf::factory('IDF_Wiki_Page')->getList(array('filter'=>$sql->gen()));
if ($pages->count() > 0 and $pages[0]->id != $this->page->id) {
throw new Pluf_Form_Invalid(__('A page with this title already exists.'));
}
@ -148,7 +148,7 @@ class IDF_Form_WikiUpdate extends Pluf_Form
$this->cleaned_data['label'.$i] = trim($this->cleaned_data['label'.$i]);
if (strpos($this->cleaned_data['label'.$i], ':') !== false) {
list($class, $name) = explode(':', $this->cleaned_data['label'.$i], 2);
list($class, $name) = array(mb_strtolower(trim($class)),
list($class, $name) = array(mb_strtolower(trim($class)),
trim($name));
} else {
$class = 'other';
@ -158,7 +158,7 @@ class IDF_Form_WikiUpdate extends Pluf_Form
else $count[$class] += 1;
if (in_array($class, $onemax) and $count[$class] > 1) {
if (!isset($this->errors['label'.$i])) $this->errors['label'.$i] = array();
$this->errors['label'.$i][] = sprintf(__('You cannot provide more than label from the %s class to a page.'), $class);
$this->errors['label'.$i][] = sprintf(__('You cannot provide more than one label from the %s class to a page.'), $class);
throw new Pluf_Form_Invalid(__('You provided an invalid label.'));
}
}
@ -229,7 +229,7 @@ class IDF_Form_WikiUpdate extends Pluf_Form
}
$this->page->update();
// add the new revision
$rev = new IDF_WikiRevision();
$rev = new IDF_Wiki_PageRevision();
$rev->wikipage = $this->page;
$rev->content = $this->cleaned_data['content'];
$rev->submitter = $this->user;

View File

@ -0,0 +1,169 @@
<?php
/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
# ***** BEGIN LICENSE BLOCK *****
# This file is part of InDefero, an open source project management application.
# Copyright (C) 2008-2011 Céondo Ltd and contributors.
#
# InDefero is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# InDefero is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#
# ***** END LICENSE BLOCK ***** */
/**
* Create a new resource.
*
* This create a new resource and the corresponding revision.
*
*/
class IDF_Form_WikiResourceCreate extends Pluf_Form
{
public $user = null;
public $project = null;
public $show_full = false;
public function initFields($extra=array())
{
$this->project = $extra['project'];
$this->user = $extra['user'];
$initname = (!empty($extra['name'])) ? $extra['name'] : __('ResourceName');
$this->fields['title'] = new Pluf_Form_Field_Varchar(
array('required' => true,
'label' => __('Resource title'),
'initial' => $initname,
'widget_attrs' => array(
'maxlength' => 200,
'size' => 67,
),
'help_text' => __('The resource name must contains only letters, digits and the dash (-) character.'),
));
$this->fields['summary'] = new Pluf_Form_Field_Varchar(
array('required' => true,
'label' => __('Description'),
'help_text' => __('This one line description is displayed in the list of resources.'),
'initial' => '',
'widget_attrs' => array(
'maxlength' => 200,
'size' => 67,
),
));
$this->fields['file'] = new Pluf_Form_Field_File(
array('required' => true,
'label' => __('File'),
'initial' => '',
'max_size' => Pluf::f('max_upload_size', 2097152),
'move_function_params' => array('upload_path' => $this->getTempUploadPath(),
'upload_path_create' => true,
'upload_overwrite' => true),
));
}
public function clean_title()
{
$title = $this->cleaned_data['title'];
if (preg_match('/[^a-zA-Z0-9\-]/', $title)) {
throw new Pluf_Form_Invalid(__('The title contains invalid characters.'));
}
$sql = new Pluf_SQL('project=%s AND title=%s',
array($this->project->id, $title));
$resources = Pluf::factory('IDF_Wiki_Resource')->getList(array('filter'=>$sql->gen()));
if ($resources->count() > 0) {
throw new Pluf_Form_Invalid(__('A resource with this title already exists.'));
}
return $title;
}
public function clean_file()
{
// FIXME: we do the same in IDF_Form_Upload and a couple of other places as well
$extra = strtolower(implode('|', explode(' ', Pluf::f('idf_extra_upload_ext'))));
if (strlen($extra)) $extra .= '|';
if (!preg_match('/\.('.$extra.'png|jpg|jpeg|gif|bmp|psd|tif|aiff|asf|avi|bz2|css|doc|eps|gz|jar|mdtext|mid|mov|mp3|mpg|ogg|pdf|ppt|ps|qt|ra|ram|rm|rtf|sdd|sdw|sit|sxi|sxw|swf|tgz|txt|wav|xls|xml|war|wmv|zip)$/i', $this->cleaned_data['file'])) {
@unlink($this->getTempUploadPath().$this->cleaned_data['file']);
throw new Pluf_Form_Invalid(__('For security reasons, you cannot upload a file with this extension.'));
}
return $this->cleaned_data['file'];
}
/**
* If we have uploaded a file, but the form failed remove it.
*
*/
function failed()
{
if (!empty($this->cleaned_data['file'])
and file_exists($this->getTempUploadPath().$this->cleaned_data['file'])) {
@unlink($this->getTempUploadPath().$this->cleaned_data['file']);
}
}
/**
* Save the model in the database.
*
* @param bool Commit in the database or not. If not, the object
* is returned but not saved in the database.
* @return Object Model with data set from the form.
*/
function save($commit=true)
{
if (!$this->isValid()) {
throw new Exception(__('Cannot save the model from an invalid form.'));
}
$tempFile = $this->getTempUploadPath().$this->cleaned_data['file'];
list($mimeType, , $extension) = IDF_FileUtil::getMimeType($tempFile);
// create the resource
$resource = new IDF_Wiki_Resource();
$resource->project = $this->project;
$resource->submitter = $this->user;
$resource->summary = trim($this->cleaned_data['summary']);
$resource->title = trim($this->cleaned_data['title']);
$resource->mime_type = $mimeType;
$resource->create();
// add the first revision
$rev = new IDF_Wiki_ResourceRevision();
$rev->wikiresource = $resource;
$rev->submitter = $this->user;
$rev->summary = __('Initial resource creation');
$rev->filesize = filesize($tempFile);
$rev->fileext = $extension;
$rev->create();
$finalFile = $rev->getFilePath();
if (!@mkdir(dirname($finalFile), 0755, true)) {
@unlink($tempFile);
$rev->delete();
$resource->delete();
throw new Exception('could not create final resource path');
}
if (!@rename($tempFile, $finalFile)) {
@unlink($tempFile);
$rev->delete();
$resource->delete();
throw new Exception('could not move resource to final location');
}
return $resource;
}
private function getTempUploadPath()
{
return Pluf::f('upload_path').'/'.$this->project->shortname.'/wiki/temp/';
}
}

View File

@ -0,0 +1,64 @@
<?php
/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
# ***** BEGIN LICENSE BLOCK *****
# This file is part of InDefero, an open source project management application.
# Copyright (C) 2008-2011 Céondo Ltd and contributors.
#
# InDefero is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# InDefero is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#
# ***** END LICENSE BLOCK ***** */
/**
* Delete a documentation page.
*
* This is a hard delete of the page and the revisions.
*
*/
class IDF_Form_WikiResourceDelete extends Pluf_Form
{
protected $resource = null;
public function initFields($extra=array())
{
$this->resource = $extra['resource'];
$this->fields['confirm'] = new Pluf_Form_Field_Boolean(
array('required' => true,
'label' => __('Yes, I understand that the resource and all its revisions will be deleted.'),
'initial' => '',
));
}
/**
* Check the confirmation.
*/
public function clean_confirm()
{
if (!$this->cleaned_data['confirm']) {
throw new Pluf_Form_Invalid(__('You need to confirm the deletion.'));
}
return $this->cleaned_data['confirm'];
}
function save($commit=true)
{
if (!$this->isValid()) {
throw new Exception(__('Cannot save the model from an invalid form.'));
}
$this->resource->delete();
return true;
}
}

View File

@ -0,0 +1,161 @@
<?php
/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
# ***** BEGIN LICENSE BLOCK *****
# This file is part of InDefero, an open source project management application.
# Copyright (C) 2008-2011 Céondo Ltd and contributors.
#
# InDefero is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# InDefero is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#
# ***** END LICENSE BLOCK ***** */
/**
* Update a documentation page.
*
* This add a corresponding revision.
*
*/
class IDF_Form_WikiResourceUpdate extends Pluf_Form
{
public $user = null;
public $project = null;
public $page = null;
public $show_full = false;
public function initFields($extra=array())
{
$this->resource = $extra['resource'];
$this->user = $extra['user'];
$this->project = $extra['project'];
$this->fields['summary'] = new Pluf_Form_Field_Varchar(
array('required' => true,
'label' => __('Description'),
'help_text' => __('This one line description is displayed in the list of resources.'),
'initial' => $this->resource->summary,
'widget_attrs' => array(
'maxlength' => 200,
'size' => 67,
),
));
$this->fields['file'] = new Pluf_Form_Field_File(
array('required' => true,
'label' => __('File'),
'initial' => '',
'max_size' => Pluf::f('max_upload_size', 2097152),
'move_function_params' => array('upload_path' => $this->getTempUploadPath(),
'upload_path_create' => true,
'upload_overwrite' => true),
));
$this->fields['comment'] = new Pluf_Form_Field_Varchar(
array('required' => true,
'label' => __('Comment'),
'help_text' => __('One line to describe the changes you made.'),
'initial' => '',
'widget_attrs' => array(
'maxlength' => 200,
'size' => 67,
),
));
}
public function clean_file()
{
// FIXME: we do the same in IDF_Form_Upload and a couple of other places as well
$extra = strtolower(implode('|', explode(' ', Pluf::f('idf_extra_upload_ext'))));
if (strlen($extra)) $extra .= '|';
if (!preg_match('/\.('.$extra.'png|jpg|jpeg|gif|bmp|psd|tif|aiff|asf|avi|bz2|css|doc|eps|gz|jar|mdtext|mid|mov|mp3|mpg|ogg|pdf|ppt|ps|qt|ra|ram|rm|rtf|sdd|sdw|sit|sxi|sxw|swf|tgz|txt|wav|xls|xml|war|wmv|zip)$/i', $this->cleaned_data['file'])) {
@unlink($this->getTempUploadPath().$this->cleaned_data['file']);
throw new Pluf_Form_Invalid(__('For security reasons, you cannot upload a file with this extension.'));
}
list($mimeType, , $extension) = IDF_FileUtil::getMimeType($this->getTempUploadPath().$this->cleaned_data['file']);
if ($this->resource->mime_type != $mimeType) {
throw new Pluf_Form_Invalid(sprintf(
__('The mime type of the uploaded file "%1$s" does not match the mime type of this resource "%2$s"'),
$mimeType, $this->resource->mime_type
));
}
$this->cleaned_data['fileext'] = $extension;
if (md5_file($this->getTempUploadPath().$this->cleaned_data['file']) ===
md5_file($this->resource->get_current_revision()->getFilePath())) {
throw new Pluf_Form_Invalid(__('The current version of the resource and the uploaded file are equal.'));
}
return $this->cleaned_data['file'];
}
/**
* If we have uploaded a file, but the form failed remove it.
*
*/
function failed()
{
if (!empty($this->cleaned_data['file'])
and file_exists($this->getTempUploadPath().$this->cleaned_data['file'])) {
@unlink($this->getTempUploadPath().$this->cleaned_data['file']);
}
}
/**
* Save the model in the database.
*
* @param bool Commit in the database or not. If not, the object
* is returned but not saved in the database.
* @return Object Model with data set from the form.
*/
function save($commit=true)
{
if (!$this->isValid()) {
throw new Exception(__('Cannot save the model from an invalid form.'));
}
$tempFile = $this->getTempUploadPath().$this->cleaned_data['file'];
$this->resource->summary = trim($this->cleaned_data['summary']);
$this->resource->update();
// add the new revision
$rev = new IDF_Wiki_ResourceRevision();
$rev->wikiresource = $this->resource;
$rev->submitter = $this->user;
$rev->summary = $this->cleaned_data['comment'];
$rev->filesize = filesize($tempFile);
$rev->fileext = $this->cleaned_data['fileext'];
$rev->create();
$finalFile = $rev->getFilePath();
if (!is_dir(dirname($finalFile))) {
@unlink($tempFile);
$rev->delete();
throw new Exception('resource path does not exist');
}
if (!@rename($tempFile, $finalFile)) {
@unlink($tempFile);
$rev->delete();
throw new Exception('could not move resource to final location');
}
return $this->resource;
}
private function getTempUploadPath()
{
return Pluf::f('upload_path').'/'.$this->project->shortname.'/wiki/temp/';
}
}

View File

@ -3,7 +3,7 @@
/*
# ***** BEGIN LICENSE BLOCK *****
# This file is part of InDefero, an open source project management application.
# Copyright (C) 2008 Céondo Ltd and contributors.
# Copyright (C) 2008-2011 Céondo Ltd and contributors.
#
# InDefero is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by

View File

@ -3,7 +3,7 @@
/*
# ***** BEGIN LICENSE BLOCK *****
# This file is part of InDefero, an open source project management application.
# Copyright (C) 2008 Céondo Ltd and contributors.
# Copyright (C) 2008-2011 Céondo Ltd and contributors.
#
# InDefero is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@ -91,6 +91,13 @@ class IDF_Issue extends Pluf_Model
'model' => 'IDF_Tag',
'verbose' => __('labels'),
),
'due_dtime' =>
array(
'type' => 'Pluf_DB_Field_Datetime',
'blank' => true,
'is_null' => true,
'verbose' => __('due date'),
),
'status' =>
array(
'type' => 'Pluf_DB_Field_Foreignkey',
@ -149,11 +156,28 @@ class IDF_Issue extends Pluf_Model
IDF_Search::remove($this);
}
function restore()
{
// Note: If a due date has not been set then it should
// be set to null and not a useless/confusing date so...
if ('0000-00-00 00:00:00' === $this->due_dtime) {
$this->due_dtime = null;
}
}
function preSave($create=false)
{
if ($this->id == '') {
$this->creation_dtime = gmdate('Y-m-d H:i:s');
}
// Note: If a due date is supplied then it must have
// a time appended to it so that calculations of when
// an issue falls overdue are accurate. In this case
// 23:59:59 is added to signify the end of the day.
if ($this->due_dtime and !empty($this->due_dtime)) {
$this->due_dtime = date('Y-m-d 23:59:59',
strtotime($this->due_dtime));
}
$this->modif_dtime = gmdate('Y-m-d H:i:s');
}
@ -169,6 +193,24 @@ class IDF_Issue extends Pluf_Model
}
}
function getGroupedRelatedIssues($opts = array(), $idsOnly = false)
{
$rels = $this->get_related_issues_list(array_merge($opts, array(
'view' => 'with_other_issue',
)));
$res = array();
foreach ($rels as $rel) {
$verb = $rel->verb;
if (!array_key_exists($verb, $res)) {
$res[$verb] = array();
}
$res[$verb][] = $idsOnly ? $rel->other_issue : $rel;
}
return $res;
}
/**
* Returns an HTML fragment used to display this issue in the
* timeline.
@ -193,7 +235,7 @@ class IDF_Issue extends Pluf_Model
$ic = (in_array($this->status, $request->project->getTagIdsByStatus('closed'))) ? 'issue-c' : 'issue-o';
$out .= sprintf(__('<a href="%1$s" class="%2$s" title="View issue">Issue %3$d</a>, %4$s'), $url, $ic, $this->id, Pluf_esc($this->summary)).'</td>';
$out .= "\n".'<tr class="extra"><td colspan="2">
<div class="helptext right">'.sprintf(__('Creation of <a href="%s" class="%s">issue&nbsp;%d</a>, by %s'), $url, $ic, $this->id, $user).'</div></td></tr>';
<div class="helptext right">'.sprintf(__('Creation of <a href="%1$s" class="%2$s">issue %3$d</a>, by %4$s'), $url, $ic, $this->id, $user).'</div></td></tr>';
return Pluf_Template::markSafe($out);
}
@ -203,7 +245,7 @@ class IDF_Issue extends Pluf_Model
.Pluf_HTTP_URL_urlForView('IDF_Views_Issue::view',
array($request->project->shortname,
$this->id));
$title = sprintf(__('%s: Issue %d created - %s'),
$title = sprintf(__('%1$s: Issue %2$d created - %3$s'),
$request->project->name,
$this->id, $this->summary);
$cts = $this->get_comments_list(array('order' => 'id ASC',
@ -238,91 +280,72 @@ class IDF_Issue extends Pluf_Model
*/
public function notify($conf, $create=true)
{
$prj = $this->get_project();
$to_email = array();
if ('' != $conf->getVal('issues_notification_email', '')) {
$langs = Pluf::f('languages', array('en'));
$addresses = explode(',', $conf->getVal('issues_notification_email'));
foreach ($addresses as $address) {
$to_email[] = array($address, $langs[0]);
}
}
$project = $this->get_project();
$current_locale = Pluf_Translation::getLocale();
$id = '<'.md5($this->id.md5(Pluf::f('secret_key'))).'@'.Pluf::f('mail_host', 'localhost').'>';
if ($create) {
if (null != $this->get_owner() and $this->owner != $this->submitter) {
$email_lang = array($this->get_owner()->email,
$this->get_owner()->language);
if (!in_array($email_lang, $to_email)) {
$to_email[] = $email_lang;
}
}
$comments = $this->get_comments_list(array('order' => 'id ASC'));
$context = new Pluf_Template_Context(
array(
'issue' => $this,
'comment' => $comments[0],
'project' => $prj,
'url_base' => Pluf::f('url_base'),
)
);
foreach ($to_email as $email_lang) {
Pluf_Translation::loadSetLocale($email_lang[1]);
$email = new Pluf_Mail(Pluf::f('from_email'), $email_lang[0],
sprintf(__('Issue %s - %s (%s)'),
$this->id, $this->summary, $prj->shortname));
$tmpl = new Pluf_Template('idf/issues/issue-created-email.txt');
$email->addTextMessage($tmpl->render($context));
$email->addHeaders(array('Message-ID'=>$id));
$email->sendMail();
}
} else {
$comments = $this->get_comments_list(array('order' => 'id DESC'));
$email_sender = '';
if (isset($comments[0])) {
$email_sender = $comments[0]->get_submitter()->email;
}
foreach ($this->get_interested_list() as $interested) {
$email_lang = array($interested->email,
$interested->language);
if (!in_array($email_lang, $to_email)) {
$to_email[] = $email_lang;
}
}
$email_lang = array($this->get_submitter()->email,
$this->get_submitter()->language);
if (!in_array($email_lang, $to_email)) {
$to_email[] = $email_lang;
}
if (null != $this->get_owner()) {
$email_lang = array($this->get_owner()->email,
$this->get_owner()->language);
if (!in_array($email_lang, $to_email)) {
$to_email[] = $email_lang;
}
}
$context = new Pluf_Template_Context(
array(
'issue' => $this,
'comments' => $comments,
'project' => $prj,
'url_base' => Pluf::f('url_base'),
));
foreach ($to_email as $email_lang) {
if ($email_lang[0] == $email_sender) {
continue; // Do not notify the one having created
// the comment
}
Pluf_Translation::loadSetLocale($email_lang[1]);
$email = new Pluf_Mail(Pluf::f('from_email'), $email_lang[0],
sprintf(__('Updated Issue %s - %s (%s)'),
$this->id, $this->summary, $prj->shortname));
$tmpl = new Pluf_Template('idf/issues/issue-updated-email.txt');
$email->addTextMessage($tmpl->render($context));
$email->addHeaders(array('References'=>$id));
$email->sendMail();
}
$from_email = Pluf::f('from_email');
$comments = $this->get_comments_list(array('order' => 'id DESC'));
$messageId = '<'.md5('issue'.$this->id.md5(Pluf::f('secret_key'))).'@'.Pluf::f('mail_host', 'localhost').'>';
$recipients = $project->getNotificationRecipientsForTab('issues');
// the submitter (might be skipped later on if he is the one who also
// submitted the last comment)
if (!array_key_exists($this->get_submitter()->email, $recipients)) {
$recipients[$this->get_submitter()->email] = $this->get_submitter()->language;
}
// the owner of the issue, if we have one
$owner = $this->get_owner();
if (null != $owner && !array_key_exists($owner->email, $recipients)) {
$recipients[$owner->email] = $owner->language;
}
// additional users who starred the issue
foreach ($this->get_interested_list() as $interested) {
if (array_key_exists($interested->email, $recipients))
continue;
$recipients[$interested->email] = $interested->language;
}
foreach ($recipients as $address => $language) {
// do not notify the creator of the last comment,
// i.e. the user who triggered this notification
if ($comments[0]->get_submitter()->email === $address) {
continue;
}
Pluf_Translation::loadSetLocale($language);
$context = new Pluf_Template_Context(array(
'issue' => $this,
'owns_issue' => $owner !== null && $owner->email === $address,
// the initial comment for create, the last for update
'comment' => $comments[0],
'comments' => $comments,
'project' => $project,
'url_base' => Pluf::f('url_base'),
));
$tplfile = 'idf/issues/issue-created-email.txt';
$subject = __('Issue %1$s - %2$s (%3$s)');
$headers = array('Message-ID' => $messageId);
if (!$create) {
$tplfile = 'idf/issues/issue-updated-email.txt';
$subject = __('Updated Issue %1$s - %2$s (%3$s)');
$headers = array('References' => $messageId);
}
$tmpl = new Pluf_Template($tplfile);
$text_email = $tmpl->render($context);
$email = new Pluf_Mail($from_email, $address,
sprintf($subject, $this->id, $this->summary, $project->shortname));
$email->addTextMessage($text_email);
$email->addHeaders($headers);
$email->sendMail();
}
Pluf_Translation::loadSetLocale($current_locale);
}
}
}

View File

@ -3,7 +3,7 @@
/*
# ***** BEGIN LICENSE BLOCK *****
# This file is part of InDefero, an open source project management application.
# Copyright (C) 2008 Céondo Ltd and contributors.
# Copyright (C) 2008-2011 Céondo Ltd and contributors.
#
# InDefero is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@ -153,12 +153,23 @@ class IDF_IssueComment extends Pluf_Model
$out .= __('Status:'); break;
case 'ow':
$out .= __('Owner:'); break;
case 'du':
$out .= __('Due date:'); break;
case 'lb':
$out .= __('Labels:'); break;
case 'rel':
$out .= __('Relations:'); break;
}
$out .= '</strong>&nbsp;';
if ($w == 'lb') {
$out .= Pluf_esc(implode(', ', $v));
if ($w == 'lb' || $w == 'rel') {
foreach ($v as $t => $ls) {
foreach ($ls as $l) {
if ($t == 'rem') $out .= '<s>';
$out .= Pluf_esc($l);
if ($t == 'rem') $out .= '</s>';
$out .= ' ';
}
}
} else {
$out .= Pluf_esc($v);
}
@ -168,7 +179,7 @@ class IDF_IssueComment extends Pluf_Model
}
$out .= '</td></tr>';
$out .= "\n".'<tr class="extra"><td colspan="2">
<div class="helptext right">'.sprintf(__('Comment on <a href="%s" class="%s">issue&nbsp;%d</a>, by %s'), $url, $ic, $issue->id, $user).'</div></td></tr>';
<div class="helptext right">'.sprintf(__('Comment on <a href="%1$s" class="%2$s">issue %3$d</a>, by %4$s'), $url, $ic, $issue->id, $user).'</div></td></tr>';
return Pluf_Template::markSafe($out);
}
@ -179,7 +190,7 @@ class IDF_IssueComment extends Pluf_Model
.Pluf_HTTP_URL_urlForView('IDF_Views_Issue::view',
array($request->project->shortname,
$issue->id));
$title = sprintf(__('%s: Comment on issue %d - %s'),
$title = sprintf(__('%1$s: Comment on issue %2$d - %3$s'),
Pluf_esc($request->project->name),
$issue->id, Pluf_esc($issue->summary));
$url .= '#ic'.$this->id;

View File

@ -3,7 +3,7 @@
/*
# ***** BEGIN LICENSE BLOCK *****
# This file is part of InDefero, an open source project management application.
# Copyright (C) 2008 Céondo Ltd and contributors.
# Copyright (C) 2008-2011 Céondo Ltd and contributors.
#
# InDefero is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by

View File

@ -0,0 +1,100 @@
<?php
/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
# ***** BEGIN LICENSE BLOCK *****
# This file is part of InDefero, an open source project management application.
# Copyright (C) 2008-2011 Céondo Ltd and contributors.
#
# InDefero is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# InDefero is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#
# ***** END LICENSE BLOCK ***** */
/**
* A relation of one issue to another
*/
class IDF_IssueRelation extends Pluf_Model
{
public $_model = __CLASS__;
function init()
{
$this->_a['table'] = 'idf_issuerelations';
$this->_a['model'] = __CLASS__;
$this->_a['cols'] = array(
// It is mandatory to have an "id" column.
'id' =>
array(
'type' => 'Pluf_DB_Field_Sequence',
'blank' => true,
),
'issue' =>
array(
'type' => 'Pluf_DB_Field_Foreignkey',
'model' => 'IDF_Issue',
'blank' => false,
'verbose' => __('issue'),
'relate_name' => 'related_issues',
),
'verb' =>
array(
'type' => 'Pluf_DB_Field_Text',
'blank' => false,
'verbose' => __('verb'),
),
'other_issue' =>
array(
'type' => 'Pluf_DB_Field_Foreignkey',
'model' => 'IDF_Issue',
'blank' => false,
'verbose' => __('other issue'),
'relate_name' => 'related_other_issues',
),
'submitter' =>
array(
'type' => 'Pluf_DB_Field_Foreignkey',
'model' => 'Pluf_User',
'blank' => false,
'verbose' => __('submitter'),
),
'creation_dtime' =>
array(
'type' => 'Pluf_DB_Field_Datetime',
'blank' => true,
'verbose' => __('creation date'),
),
);
$this->_a['idx'] = array(
'creation_dtime_idx' =>
array(
'col' => 'creation_dtime',
'type' => 'normal',
),
);
$issuetbl = $this->_con->pfx.'idf_issues';
$this->_a['views'] = array(
'with_other_issue' => array(
'join' => 'INNER JOIN '.$issuetbl.' ON other_issue='.$issuetbl.'.id',
'select' => $this->getSelect().', summary',
'props' => array('summary' => 'other_summary'),
));
}
function preSave($create=false)
{
if ($this->id == '') {
$this->creation_dtime = gmdate('Y-m-d H:i:s');
}
}
}

View File

@ -3,7 +3,7 @@
/*
# ***** BEGIN LICENSE BLOCK *****
# This file is part of InDefero, an open source project management application.
# Copyright (C) 2008 Céondo Ltd and contributors.
# Copyright (C) 2008-2011 Céondo Ltd and contributors.
#
# InDefero is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@ -80,7 +80,10 @@ class IDF_Key extends Pluf_Model
if (preg_match('#^\[pubkey ([^\]]+)\]\s*(\S+)\s*\[end\]$#', $this->content, $m)) {
return array('mtn', $m[1], $m[2]);
}
else if (preg_match('#^ssh\-[a-z]{3}\s(\S+)(?:\s(\S+))?$#', $this->content, $m)) {
else if (preg_match('#^ssh\-(?:dss|rsa)\s(\S+)(?:\s(.*))?$#', $this->content, $m)) {
if (!isset($m[2])) {
$m[2] = "";
}
return array('ssh', $m[2], $m[1]);
}

View File

@ -3,7 +3,7 @@
/*
# ***** BEGIN LICENSE BLOCK *****
# This file is part of InDefero, an open source project management application.
# Copyright (C) 2008 Céondo Ltd and contributors.
# Copyright (C) 2008-2011 Céondo Ltd and contributors.
#
# InDefero is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@ -85,8 +85,11 @@ class IDF_Middleware
'issuetext' => 'IDF_Template_IssueComment',
'timeline' => 'IDF_Template_TimelineFragment',
'markdown' => 'IDF_Template_Markdown',
'markdown_forge' => 'IDF_Template_MarkdownForge',
'showuser' => 'IDF_Template_ShowUser',
'ashowuser' => 'IDF_Template_AssignShowUser',
'appversion' => 'IDF_Template_AppVersion',
'upload' => 'IDF_Template_Tag_UploadUrl',
));
$params['modifiers'] = array_merge($params['modifiers'],
array(
@ -100,6 +103,7 @@ class IDF_Middleware
function IDF_Middleware_ContextPreProcessor($request)
{
$forge = IDF_Forge::instance();
$c = array();
$c['request'] = $request;
$c['isAdmin'] = ($request->user->administrator or $request->user->staff);
@ -113,6 +117,7 @@ function IDF_Middleware_ContextPreProcessor($request)
}
$c['usherConfigured'] = Pluf::f("mtn_usher_conf", null) !== null;
$c['allProjects'] = IDF_Views::getProjects($request->user);
$c['customForgePageEnabled'] = $forge->isCustomForgePageEnabled();
return $c;
}

View File

@ -3,7 +3,7 @@
/*
# ***** BEGIN LICENSE BLOCK *****
# This file is part of InDefero, an open source project management application.
# Copyright (C) 2008 Céondo Ltd and contributors.
# Copyright (C) 2008-2011 Céondo Ltd and contributors.
#
# InDefero is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by

View File

@ -3,7 +3,7 @@
/*
# ***** BEGIN LICENSE BLOCK *****
# This file is part of InDefero, an open source project management application.
# Copyright (C) 2008 Céondo Ltd and contributors.
# Copyright (C) 2008-2011 Céondo Ltd and contributors.
#
# InDefero is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by

View File

@ -3,7 +3,7 @@
/*
# ***** BEGIN LICENSE BLOCK *****
# This file is part of InDefero, an open source project management application.
# Copyright (C) 2008 Céondo Ltd and contributors.
# Copyright (C) 2008-2011 Céondo Ltd and contributors.
#
# InDefero is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by

View File

@ -3,7 +3,7 @@
/*
# ***** BEGIN LICENSE BLOCK *****
# This file is part of InDefero, an open source project management application.
# Copyright (C) 2008 Céondo Ltd and contributors.
# Copyright (C) 2008-2011 Céondo Ltd and contributors.
#
# InDefero is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by

View File

@ -3,7 +3,7 @@
/*
# ***** BEGIN LICENSE BLOCK *****
# This file is part of InDefero, an open source project management application.
# Copyright (C) 2008 Céondo Ltd and contributors.
# Copyright (C) 2008-2011 Céondo Ltd and contributors.
#
# InDefero is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by

View File

@ -3,7 +3,7 @@
/*
# ***** BEGIN LICENSE BLOCK *****
# This file is part of InDefero, an open source project management application.
# Copyright (C) 2008 Céondo Ltd and contributors.
# Copyright (C) 2008-2011 Céondo Ltd and contributors.
#
# InDefero is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by

View File

@ -0,0 +1,43 @@
<?php
/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
# ***** BEGIN LICENSE BLOCK *****
# This file is part of InDefero, an open source project management application.
# Copyright (C) 2008-2011 Céondo Ltd and contributors.
#
# InDefero is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# InDefero is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#
# ***** END LICENSE BLOCK ***** */
/**
* Add the new IDF_Gconf model.
*
*/
function IDF_Migrations_16AddUserMail_up($params=null)
{
$db = Pluf::db();
$schema = new Pluf_DB_Schema($db);
$schema->model = new IDF_EmailAddress();
$schema->createTables();
}
function IDF_Migrations_16AddUserMail_down($params=null)
{
$db = Pluf::db();
$schema = new Pluf_DB_Schema($db);
$schema->model = new IDF_EmailAddress();
$schema->dropTables();
}

View File

@ -0,0 +1,90 @@
<?php
/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
# ***** BEGIN LICENSE BLOCK *****
# This file is part of InDefero, an open source project management application.
# Copyright (C) 2008-2011 Céondo Ltd and contributors.
#
# InDefero is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# InDefero is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#
# ***** END LICENSE BLOCK ***** */
/**
* Add the new IDF_IssueRelation model.
*
*/
function IDF_Migrations_17AddIssueRelations_up($params=null)
{
$db = Pluf::db();
$schema = new Pluf_DB_Schema($db);
$schema->model = new IDF_IssueRelation();
$schema->createTables();
// change the serialization format for added / removed labels in IDF_IssueComment
$comments = Pluf::factory('IDF_IssueComment')->getList();
foreach ($comments as $comment) {
if (!isset($comment->changes['lb'])) continue;
$changes = $comment->changes;
$adds = $removals = array();
foreach ($comment->changes['lb'] as $lb) {
if (substr($lb, 0, 1) == '-')
$removals[] = substr($lb, 1);
else
$adds[] = $lb;
}
$changes['lb'] = array();
if (count($adds) > 0)
$changes['lb']['add'] = $adds;
if (count($removals) > 0)
$changes['lb']['rem'] = $removals;
$comment->changes = $changes;
$comment->update();
}
}
function IDF_Migrations_17AddIssueRelations_down($params=null)
{
$db = Pluf::db();
$schema = new Pluf_DB_Schema($db);
$schema->model = new IDF_IssueRelation();
$schema->dropTables();
// change the serialization format for added / removed labels in IDF_IssueComment
$comments = Pluf::factory('IDF_IssueComment')->getList();
foreach ($comments as $comment) {
$changes = $comment->changes;
if (empty($changes))
continue;
if (isset($changes['lb'])) {
$labels = array();
foreach ($changes['lb'] as $type => $lbs) {
if (!is_array($lbs)) {
$labels[] = $lbs;
continue;
}
foreach ($lbs as $lb) {
$labels[] = ($type == 'rem' ? '-' : '') . $lb;
}
}
$changes['lb'] = $labels;
}
// while we're at it, remove any 'rel' changes
unset($changes['rel']);
$comment->changes = $changes;
$comment->update();
}
}

View File

@ -0,0 +1,63 @@
<?php
/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
# ***** BEGIN LICENSE BLOCK *****
# This file is part of InDefero, an open source project management application.
# Copyright (C) 2008-2011 Céondo Ltd and contributors.
#
# InDefero is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# InDefero is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#
# ***** END LICENSE BLOCK ***** */
/**
* Add the md5 column for the download model.
*/
function IDF_Migrations_18DownloadMD5_up($params=null)
{
// Add the row
$table = Pluf::factory('IDF_Upload')->getSqlTable();
$sql = array();
$sql['PostgreSQL'] = 'ALTER TABLE '.$table.' ADD COLUMN "md5" VARCHAR(32) DEFAULT \'\'';
$sql['MySQL'] = 'ALTER TABLE '.$table.' ADD COLUMN `md5` VARCHAR(32) DEFAULT \'\'';
$db = Pluf::db();
$engine = Pluf::f('db_engine');
if (!isset($sql[$engine])) {
throw new Exception('SQLite complex migration not supported.');
}
$db->execute($sql[$engine]);
// Process md5 of already uploaded file
$files = Pluf::factory('IDF_Upload')->getList();
foreach ($files as $f) {
$f->md5 = md5_file (Pluf::f('upload_path') . '/' . $f->get_project()->shortname . '/files/' . $f->file);
$f->update();
}
}
function IDF_Migrations_18DownloadMD5_down($params=null)
{
// Remove the row
$table = Pluf::factory('IDF_Upload')->getSqlTable();
$sql = array();
$sql['PostgreSQL'] = 'ALTER TABLE '.$table.' DROP COLUMN "md5"';
$sql['MySQL'] = 'ALTER TABLE '.$table.' DROP COLUMN `md5`';
$db = Pluf::db();
$engine = Pluf::f('db_engine');
if (!isset($sql[$engine])) {
throw new Exception('SQLite complex migration not supported.');
}
$db->execute($sql[$engine]);
}

View File

@ -0,0 +1,74 @@
<?php
/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
# ***** BEGIN LICENSE BLOCK *****
# This file is part of InDefero, an open source project management application.
# Copyright (C) 2008-2011 Céondo Ltd and contributors.
#
# InDefero is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# InDefero is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#
# ***** END LICENSE BLOCK ***** */
function IDF_Migrations_19WikiPageAssocs_up($params=null)
{
$engine = Pluf::f('db_engine');
if (!in_array($engine, array('MySQL', 'PostgreSQL'))) {
throw new Exception('unsupported engine '.$engine);
}
$db = Pluf::db();
$intro = new Pluf_DB_Introspect($db);
if (in_array($db->pfx.'idf_tag_idf_wiki_page_assoc', $intro->listTables())) {
echo '19 skipping up migration - relation table has correct name already'."\n";
return;
}
$db->execute('ALTER TABLE '.$db->pfx.'idf_tag_idf_wikipage_assoc RENAME TO '.$db->pfx.'idf_tag_idf_wiki_page_assoc');
$db->execute('ALTER TABLE '.$db->pfx.'idf_wikipage_pluf_user_assoc RENAME TO '.$db->pfx.'idf_wiki_page_pluf_user_assoc');
if ($engine === 'PostgreSQL') {
$db->execute('ALTER TABLE '.$db->pfx.'idf_tag_idf_wiki_page_assoc RENAME COLUMN idf_wikipage_id TO idf_wiki_page_id');
$db->execute('ALTER TABLE '.$db->pfx.'idf_wiki_page_pluf_user_assoc RENAME COLUMN idf_wikipage_id TO idf_wiki_page_id');
} else if ($engine === 'MySQL') {
$db->execute('ALTER TABLE '.$db->pfx.'idf_tag_idf_wiki_page_assoc CHANGE idf_wikipage_id idf_wiki_page_id MEDIUMINT NOT NULL');
$db->execute('ALTER TABLE '.$db->pfx.'idf_wiki_page_pluf_user_assoc CHANGE idf_wikipage_id idf_wiki_page_id MEDIUMINT NOT NULL');
}
}
function IDF_Migrations_19WikiPageAssocs_down($params=null)
{
$engine = Pluf::f('db_engine');
if (!in_array($engine, array('MySQL', 'PostgreSQL'))) {
throw new Exception('unsupported engine '.$engine);
}
$db = Pluf::db();
$intro = new Pluf_DB_Introspect($db);
if (in_array($db->pfx.'idf_tag_idf_wikipage_assoc', $intro->listTables())) {
echo '19 skipping down migration - relation table has correct name already'."\n";
return;
}
$db->execute('ALTER TABLE '.$db->pfx.'idf_tag_idf_wiki_page_assoc RENAME TO '.$db->pfx.'idf_tag_idf_wikipage_assoc');
$db->execute('ALTER TABLE '.$db->pfx.'idf_wiki_page_pluf_user_assoc RENAME TO '.$db->pfx.'idf_wikipage_pluf_user_assoc');
if ($engine === 'PostgreSQL') {
$db->execute('ALTER TABLE '.$db->pfx.'idf_tag_idf_wikipage_assoc RENAME COLUMN idf_wiki_page_id TO idf_wikipage_id');
$db->execute('ALTER TABLE '.$db->pfx.'idf_wikipage_pluf_user_assoc RENAME COLUMN idf_wiki_page_id TO idf_wikipage_id');
} else if ($engine === 'MySQL') {
$db->execute('ALTER TABLE '.$db->pfx.'idf_tag_idf_wikipage_assoc CHANGE idf_wiki_page_id idf_wikipage_id MEDIUMINT NOT NULL');
$db->execute('ALTER TABLE '.$db->pfx.'idf_wikipage_pluf_user_assoc CHANGE idf_wiki_page_id idf_wikipage_id MEDIUMINT NOT NULL');
}
}

View File

@ -3,7 +3,7 @@
/*
# ***** BEGIN LICENSE BLOCK *****
# This file is part of InDefero, an open source project management application.
# Copyright (C) 2008 Céondo Ltd and contributors.
# Copyright (C) 2008-2011 Céondo Ltd and contributors.
#
# InDefero is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by

View File

@ -0,0 +1,51 @@
<?php
/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
# ***** BEGIN LICENSE BLOCK *****
# This file is part of InDefero, an open source project management application.
# Copyright (C) 2008-2011 Céondo Ltd and contributors.
#
# InDefero is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# InDefero is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#
# ***** END LICENSE BLOCK ***** */
/**
* Add the new IDF_Wiki_Resource and IDF_Wiki_ResourceRevision models.
*
*/
function IDF_Migrations_20AddWikiResources_up($params=null)
{
$db = Pluf::db();
$schema = new Pluf_DB_Schema($db);
$schema->model = new IDF_Wiki_Resource();
$schema->createTables();
$schema->model = new IDF_Wiki_ResourceRevision();
$schema->createTables();
}
function IDF_Migrations_20AddWikiResources_down($params=null)
{
$db = Pluf::db();
$schema = new Pluf_DB_Schema($db);
$schema->model = new IDF_Wiki_ResourceRevision();
$schema->dropTables();
$schema->model = new IDF_Wiki_Resource();
$schema->dropTables();
}

View File

@ -0,0 +1,68 @@
<?php
/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
# ***** BEGIN LICENSE BLOCK *****
# This file is part of InDefero, an open source project management application.
# Copyright (C) 2008-2011 Céondo Ltd and contributors.
#
# InDefero is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# InDefero is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#
# ***** END LICENSE BLOCK ***** */
function IDF_Migrations_21WikiPageRevisionName_up($params=null)
{
$engine = Pluf::f('db_engine');
if (!in_array($engine, array('MySQL', 'PostgreSQL'))) {
throw new Exception('unsupported engine '.$engine);
}
$db = Pluf::db();
$intro = new Pluf_DB_Introspect($db);
if (in_array($db->pfx.'idf_wikipagerevs', $intro->listTables())) {
echo '21 skipping up migration - table has correct name already'."\n";
return;
}
$db->execute('ALTER TABLE '.$db->pfx.'idf_wikirevisions RENAME TO '.$db->pfx.'idf_wikipagerevs');
$db->execute("UPDATE ".$db->pfx."idf_timeline SET model_class='IDF_Wiki_Page' WHERE model_class LIKE 'IDF_WikiPage'");
$db->execute("UPDATE ".$db->pfx."idf_timeline SET model_class='IDF_Wiki_PageRevision' WHERE model_class LIKE 'IDF_WikiRevision'");
$db->execute("UPDATE ".$db->pfx."idf_search_occs SET model_class='IDF_Wiki_Page' WHERE model_class LIKE 'IDF_WikiPage'");
$db->execute("UPDATE ".$db->pfx."idf_search_occs SET model_class='IDF_Wiki_PageRevision' WHERE model_class LIKE 'IDF_WikiRevision'");
$db->execute("UPDATE ".$db->pfx."pluf_search_stats SET model_class='IDF_Wiki_Page' WHERE model_class LIKE 'IDF_WikiPage'");
$db->execute("UPDATE ".$db->pfx."pluf_search_stats SET model_class='IDF_Wiki_PageRevision' WHERE model_class LIKE 'IDF_WikiRevision'");
}
function IDF_Migrations_21WikiPageRevisionName_down($params=null)
{
$engine = Pluf::f('db_engine');
if (!in_array($engine, array('MySQL', 'PostgreSQL'))) {
throw new Exception('unsupported engine '.$engine);
}
$db = Pluf::db();
$intro = new Pluf_DB_Introspect($db);
if (in_array($db->pfx.'idf_wikirevisions', $intro->listTables())) {
echo '21 skipping down migration - table has correct name already'."\n";
return;
}
$db->execute('ALTER TABLE '.$db->pfx.'idf_wikipagerevs RENAME TO '.$db->pfx.'idf_wikirevisions');
$db->execute("UPDATE ".$db->pfx."idf_timeline SET model_class='IDF_WikiPage' WHERE model_class LIKE 'IDF_Wiki_Page'");
$db->execute("UPDATE ".$db->pfx."idf_timeline SET model_class='IDF_WikiRevision' WHERE model_class LIKE 'IDF_Wiki_PageRevision'");
$db->execute("UPDATE ".$db->pfx."idf_search_occs SET model_class='IDF_WikiPage' WHERE model_class LIKE 'IDF_Wiki_Page'");
$db->execute("UPDATE ".$db->pfx."idf_search_occs SET model_class='IDF_WikiRevision' WHERE model_class LIKE 'IDF_Wiki_PageRevision'");
$db->execute("UPDATE ".$db->pfx."pluf_search_stats SET model_class='IDF_WikiPage' WHERE model_class LIKE 'IDF_Wiki_Page'");
$db->execute("UPDATE ".$db->pfx."pluf_search_stats SET model_class='IDF_WikiRevision' WHERE model_class LIKE 'IDF_Wiki_PageRevision'");
}

View File

@ -0,0 +1,60 @@
<?php
/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
# ***** BEGIN LICENSE BLOCK *****
# This file is part of InDefero, an open source project management application.
# Copyright (C) 2008-2011 Céondo Ltd and contributors.
#
# InDefero is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# InDefero is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#
# ***** END LICENSE BLOCK ***** */
function IDF_Migrations_22ProjectTagRelationTable_up($params=null)
{
$db = Pluf::db();
$table = $db->pfx.'idf_project_idf_tag_assoc';
if (!in_array($db->engine, array('MySQL', 'PostgreSQL'))) {
throw new Exception('unsupported engine '.$engine);
}
$intro = new Pluf_DB_Introspect($db);
if (in_array($table, $intro->listTables())) {
echo '21 skipping up migration - table already exists'."\n";
return;
}
$schema = Pluf::factory('Pluf_DB_Schema_'.$db->engine, $db);
$sql = $schema->getSqlCreate(new IDF_Project());
$db->execute($sql[$table]);
}
function IDF_Migrations_22ProjectTagRelationTable_down($params=null)
{
$db = Pluf::db();
$table = $db->pfx.'idf_project_idf_tag_assoc';
if (!in_array($db->engine, array('MySQL', 'PostgreSQL'))) {
throw new Exception('unsupported engine '.$engine);
}
$intro = new Pluf_DB_Introspect($db);
if (!in_array($table, $intro->listTables())) {
echo '22 skipping down migration - table does not exist'."\n";
return;
}
$schema = Pluf::factory('Pluf_DB_Schema_'.$db->engine, $db);
$sql = $schema->getSqlDelete(new IDF_Project());
$db->execute($sql[$table]);
}

View File

@ -0,0 +1,42 @@
<?php
/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
# ***** BEGIN LICENSE BLOCK *****
# This file is part of InDefero, an open source project management application.
# Copyright (C) 2008-2011 Céondo Ltd and contributors.
#
# InDefero is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# InDefero is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#
# ***** END LICENSE BLOCK ***** */
/**
* Add the new IDF_ProjectActivity model.
*
*/
function IDF_Migrations_23ProjectActivity_up($params=null)
{
$db = Pluf::db();
$schema = new Pluf_DB_Schema($db);
$schema->model = new IDF_ProjectActivity();
$schema->createTables();
}
function IDF_Migrations_23ProjectActivity_down($params=null)
{
$db = Pluf::db();
$schema = new Pluf_DB_Schema($db);
$schema->model = new IDF_ProjectActivity();
$schema->dropTables();
}

View File

@ -0,0 +1,40 @@
<?php
/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
# ***** BEGIN LICENSE BLOCK *****
# This file is part of InDefero, an open source project management application.
# Copyright (C) 2008-2011 Céondo Ltd and contributors.
#
# InDefero is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# InDefero is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#
# ***** END LICENSE BLOCK ***** */
function IDF_Migrations_24CurrentProjectActivity_up($params=null)
{
$engine = Pluf::f('db_engine');
$db = Pluf::db();
if ($engine === 'PostgreSQL') {
$db->execute('ALTER TABLE '.$db->pfx.'idf_projects ADD COLUMN current_activity INTEGER');
} else if ($engine === 'MySQL') {
$db->execute('ALTER TABLE '.$db->pfx.'idf_projects ADD COLUMN current_activity MEDIUMINT');
}
}
function IDF_Migrations_24CurrentProjectActivity_down($params=null)
{
$db = Pluf::db();
$db->execute('ALTER TABLE '.$db->pfx.'idf_projects DROP COLUMN current_activity');
}

View File

@ -0,0 +1,47 @@
<?php
/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
# ***** BEGIN LICENSE BLOCK *****
# This file is part of InDefero, an open source project management application.
# Copyright (C) 2008-2011 Céondo Ltd and contributors.
#
# InDefero is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# InDefero is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#
# ***** END LICENSE BLOCK ***** */
function IDF_Migrations_25NullableProjectInTag_up($params=null)
{
$engine = Pluf::f('db_engine');
$db = Pluf::db();
if ($engine === 'PostgreSQL') {
$db->execute('ALTER TABLE '.$db->pfx.'idf_tags ALTER COLUMN project DROP NOT NULL');
} else if ($engine === 'MySQL') {
$db->execute('ALTER TABLE '.$db->pfx.'idf_tags MODIFY project MEDIUMINT NULL');
// this is only needed for non-transactional setups where MySQL set 0 as default value
$db->execute('UPDATE '.$db->pfx.'idf_tags SET project=NULL WHERE project=0');
}
}
function IDF_Migrations_25NullableProjectInTag_down($params=null)
{
$engine = Pluf::f('db_engine');
$db = Pluf::db();
if ($engine === 'PostgreSQL') {
$db->execute('ALTER TABLE '.$db->pfx.'idf_tags ALTER COLUMN project SET NOT NULL');
} else if ($engine === 'MySQL') {
$db->execute('ALTER TABLE '.$db->pfx.'idf_tags MODIFY project MEDIUMINT NOT NULL');
}
}

View File

@ -0,0 +1,46 @@
<?php
/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
# ***** BEGIN LICENSE BLOCK *****
# This file is part of InDefero, an open source project management application.
# Copyright (C) 2008-2012 Céondo Ltd and contributors.
#
# InDefero is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# InDefero is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#
# ***** END LICENSE BLOCK ***** */
function IDF_Migrations_26NullableActivityInProject_up($params=null)
{
$engine = Pluf::f('db_engine');
$db = Pluf::db();
if ($engine === 'PostgreSQL') {
$db->execute('ALTER TABLE '.$db->pfx.'idf_projects ALTER COLUMN current_activity DROP NOT NULL');
} else if ($engine === 'MySQL') {
$db->execute('ALTER TABLE '.$db->pfx.'idf_projects MODIFY current_activity MEDIUMINT NULL');
// this is only needed for non-transactional setups where MySQL set 0 as default value
$db->execute('UPDATE '.$db->pfx.'idf_projects SET current_activity=NULL WHERE current_activity=0');
}
}
function IDF_Migrations_26NullableActivityInProject_down($params=null)
{
$engine = Pluf::f('db_engine');
$db = Pluf::db();
if ($engine === 'PostgreSQL') {
$db->execute('ALTER TABLE '.$db->pfx.'idf_projects ALTER COLUMN current_activity SET NOT NULL');
} else if ($engine === 'MySQL') {
$db->execute('ALTER TABLE '.$db->pfx.'idf_projects MODIFY current_activity MEDIUMINT NOT NULL');
}
}

View File

@ -0,0 +1,55 @@
<?php
/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
# ***** BEGIN LICENSE BLOCK *****
# This file is part of InDefero, an open source project management application.
# Copyright (C) 2008-2011 Céondo Ltd and contributors.
#
# InDefero is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# InDefero is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#
# ***** END LICENSE BLOCK ***** */
/**
* Add the private column for the project.
*/
function IDF_Migrations_27IssueDueDate_up($params=null)
{
$table = Pluf::factory('IDF_Issue')->getSqlTable();
$sql = array();
$sql['PostgreSQL'] = 'ALTER TABLE '.$table.' ADD COLUMN "due_dtime" TIMESTAMP';
$sql['MySQL'] = 'ALTER TABLE '.$table.' ADD COLUMN `due_dtime` DATETIME';
$db = Pluf::db();
$engine = Pluf::f('db_engine');
if (!isset($sql[$engine])) {
throw new Exception('SQLite complex migration not supported.');
}
$db->execute($sql[$engine]);
}
function IDF_Migrations_27IssueDueDate_down($params=null)
{
$table = Pluf::factory('IDF_Issue')->getSqlTable();
$sql = array();
$sql['PostgreSQL'] = 'ALTER TABLE '.$table.' DROP COLUMN "due_dtime"';
$sql['MySQL'] = 'ALTER TABLE '.$table.' DROP COLUMN `due_dtime`';
$db = Pluf::db();
$engine = Pluf::f('db_engine');
if (!isset($sql[$engine])) {
throw new Exception('SQLite complex migration not supported.');
}
$db->execute($sql[$engine]);
}

View File

@ -3,7 +3,7 @@
/*
# ***** BEGIN LICENSE BLOCK *****
# This file is part of InDefero, an open source project management application.
# Copyright (C) 2008 Céondo Ltd and contributors.
# Copyright (C) 2008-2011 Céondo Ltd and contributors.
#
# InDefero is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by

View File

@ -3,7 +3,7 @@
/*
# ***** BEGIN LICENSE BLOCK *****
# This file is part of InDefero, an open source project management application.
# Copyright (C) 2008 Céondo Ltd and contributors.
# Copyright (C) 2008-2011 Céondo Ltd and contributors.
#
# InDefero is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by

View File

@ -3,7 +3,7 @@
/*
# ***** BEGIN LICENSE BLOCK *****
# This file is part of InDefero, an open source project management application.
# Copyright (C) 2008 Céondo Ltd and contributors.
# Copyright (C) 2008-2011 Céondo Ltd and contributors.
#
# InDefero is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by

View File

@ -3,7 +3,7 @@
/*
# ***** BEGIN LICENSE BLOCK *****
# This file is part of InDefero, an open source project management application.
# Copyright (C) 2008 Céondo Ltd and contributors.
# Copyright (C) 2008-2011 Céondo Ltd and contributors.
#
# InDefero is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by

View File

@ -3,7 +3,7 @@
/*
# ***** BEGIN LICENSE BLOCK *****
# This file is part of InDefero, an open source project management application.
# Copyright (C) 2008 Céondo Ltd and contributors.
# Copyright (C) 2008-2011 Céondo Ltd and contributors.
#
# InDefero is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by

View File

@ -3,7 +3,7 @@
/*
# ***** BEGIN LICENSE BLOCK *****
# This file is part of InDefero, an open source project management application.
# Copyright (C) 2008 Céondo Ltd and contributors.
# Copyright (C) 2008-2011 Céondo Ltd and contributors.
#
# InDefero is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@ -22,14 +22,14 @@
# ***** END LICENSE BLOCK ***** */
/**
* Add the download of files.
* Add wiki functionality.
*/
function IDF_Migrations_7Wiki_up($params=null)
{
$models = array(
'IDF_WikiPage',
'IDF_WikiRevision',
'IDF_Wiki_Page',
'IDF_Wiki_PageRevision',
);
$db = Pluf::db();
$schema = new Pluf_DB_Schema($db);
@ -42,8 +42,8 @@ function IDF_Migrations_7Wiki_up($params=null)
function IDF_Migrations_7Wiki_down($params=null)
{
$models = array(
'IDF_WikiRevision',
'IDF_WikiPage',
'IDF_Wiki_PageRevision',
'IDF_Wiki_Page',
);
$db = Pluf::db();
$schema = new Pluf_DB_Schema($db);

View File

@ -3,7 +3,7 @@
/*
# ***** BEGIN LICENSE BLOCK *****
# This file is part of InDefero, an open source project management application.
# Copyright (C) 2008 Céondo Ltd and contributors.
# Copyright (C) 2008-2011 Céondo Ltd and contributors.
#
# InDefero is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by

Some files were not shown because too many files have changed in this diff Show More