Compare commits

..

1 Commits

Author SHA1 Message Date
William MARTIN
f88e529b85 Update the form validation of IDF_Form_ReviewFileComment.
Now we can add a general comment without per file comment.

Fix issue 660
2011-04-06 13:07:19 +02:00
359 changed files with 19175 additions and 59480 deletions

1
.gitattributes vendored
View File

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

23
.gitignore vendored
View File

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

66
AUTHORS
View File

@ -1,52 +1,30 @@
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. by Loïc d'Anterroches with the support of Céondo Ltd.
Much appreciated contributors (in alphabetical order): Much appreciated contributors:
Adrien Bustany <madcat@mymadcat.com> Nicolas Lassalle <http://www.beroot.org/> - Subversion support
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>
Matthew Dawson <mjd>
Matías Halles <matias@halles.cl>
Mehdi Kabab <http://pioupioum.fr/>
Nicolas Lassalle <nicolas@beroot.org> - Subversion support
Ozan <uobasar@gmail.com> - Turkish translation
Patrick Georgi <patrick.georgi@coresystems.de>
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/> bohwaz <http://bohwaz.net/>
Benjamin Jorand <benjamin.jorand@gmail.com> - Mercurial support
Baptiste Michaud <bactisme@gmail.com> - Subversion synchronization
Julien Issler
Manuel Eidenberger <eidenberger@gmail.com>
Ciaran Gultnieks
Mehdi Kabab <http://pioupioum.fr/>
Sindre R. Myren
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
And all the nice users who spent time reporting issues and promoting And all the nice users who spent time reporting issues and promoting
the project. The project could not live without them. the project. The project could not live without them.

View File

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

View File

@ -4,18 +4,6 @@ The installation of InDefero is composed of 2 parts, first the
installation of the [Pluf framework](http://www.pluf.org) and second, installation of the [Pluf framework](http://www.pluf.org) and second,
the installation of InDefero by itself. 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 ## Recommended Layout of the Files
If your server document root is in `/var/www` a good thing is to keep If your server document root is in `/var/www` a good thing is to keep
@ -49,7 +37,6 @@ docroot.
$ sudo pear upgrade-all $ sudo pear upgrade-all
$ sudo pear install --alldeps Mail $ sudo pear install --alldeps Mail
$ sudo pear install --alldeps Mail_mime $ sudo pear install --alldeps Mail_mime
$ sudo pear install --alldeps Console_Getopt
If you already have some of the PEAR packages installed with your If you already have some of the PEAR packages installed with your
distribution, the `Mail` package is often not up-to-date, distribution, the `Mail` package is often not up-to-date,
@ -138,7 +125,6 @@ The documentation is available in the `doc` folder.
* Subversion: `doc/syncsvn.mdtext`. * Subversion: `doc/syncsvn.mdtext`.
* Mercurial: `doc/syncmercurial.mdtext`. * Mercurial: `doc/syncmercurial.mdtext`.
* Git: `doc/syncgit.mdtext`. * Git: `doc/syncgit.mdtext`.
* Monotone: `doc/syncmonotone.mdtext`
## For the Apache Webserver Users ## For the Apache Webserver Users

133
Makefile
View File

@ -22,63 +22,46 @@
# sudo apt-get install python-setuptools # sudo apt-get install python-setuptools
# sudo easy_install -U transifex-client # sudo easy_install -U transifex-client
.PHONY: help
help:
@printf "Rules for generating distributable files :\n"
@for b in `git branch | sed "s/^. //g"`; do \
printf "\t"$$b"-zipfile - Generate a zip archive of the "$$b" branch.\n"; \
done
@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"
#
# 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;") 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
all help:
@echo "Rules for generate tarball :"
@for b in `git branch | sed "s/^. //g"`; do \
echo -e "\t"$$b"_tarball - Generate a zip archive of the "$$b" branch."; \
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"
#
# Internationnalization rule, POT & PO file manipulation
#
.PHONY: pot-update po-update .PHONY: pot-update po-update
pot-update: pluf_path pot-update:
# Backup pot file # Backup pot file
@if [ -e src/IDF/locale/idf.pot ]; then \ @if [ -e src/IDF/locale/idf.pot ]; then \
mv -f src/IDF/locale/idf.pot src/IDF/locale/idf.pot.bak; \ mv -f src/IDF/locale/idf.pot src/IDF/locale/idf.pot.bak; \
fi fi
touch src/IDF/locale/idf.pot; touch src/IDF/locale/idf.pot;
# Extract string # 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 \ @cd src; for phpfile in `find . -iname "*.php"`; do \
printf "Parsing file : "$$phpfile"\n"; \ echo "Parsing file : "$$phpfile; \
xgettext -o idf.pot -p ./IDF/locale/ --from-code=UTF-8 -j \ xgettext -o idf.pot -p ./IDF/locale/ --from-code=UTF-8 -j --keyword --keyword=__ --keyword=_n:1,2 -L PHP $$phpfile ; \
--keyword --keyword=__ --keyword=_n:1,2 -L PHP "$$phpfile" ; \
done done
# Remove tmp folder # Remove tmp folder
rm -Rf src/IDF/gettexttemplates rm -Rf src/IDF/gettexttemplates
# Update PO # Update PO
@make po-update @make po-update
po-update: pluf_path po-update:
@for pofile in `ls src/IDF/locale/*/idf.po`; do \ @for pofile in `ls src/IDF/locale/*/idf.po`; do \
printf "Updating file : "$$pofile"\n"; \ echo "Updating file : "$$pofile; \
msgmerge -v -U "$$pofile" src/IDF/locale/idf.pot; \ msgmerge -v -U $$pofile src/IDF/locale/idf.pot; \
printf "\n"; \ echo ; \
done done
# #
@ -89,22 +72,22 @@ check-tx-config:
@if [ ! -e .tx/config ]; then \ @if [ ! -e .tx/config ]; then \
mkdir -p .tx; \ mkdir -p .tx; \
touch .tx/config; \ touch .tx/config; \
printf "[main]\n" >> .tx/config; \ echo "[main]" >> .tx/config; \
printf "host = http://www.transifex.net\n" >> .tx/config; \ echo "host = http://www.transifex.net" >> .tx/config; \
printf "\n" >> .tx/config; \ echo "" >> .tx/config; \
printf "[indefero.idfpot]\n" >> .tx/config; \ echo "[indefero.idfpot]" >> .tx/config; \
printf "file_filter = src/IDF/locale/<lang>/idf.po\n" >> .tx/config; \ echo "file_filter = src/IDF/locale/<lang>/idf.po" >> .tx/config; \
printf "source_file = src/IDF/locale/idf.pot\n" >> .tx/config; \ echo "source_file = src/IDF/locale/idf.pot" >> .tx/config; \
printf "source_lang = en\n" >> .tx/config; \ echo "source_lang = en" >> .tx/config; \
fi fi
@if [ ! -e $(HOME)/.transifexrc ]; then \ @if [ ! -e $(HOME)/.transifexrc ]; then \
touch $(HOME)/.transifexrc; \ touch $(HOME)/.transifexrc; \
printf "[http://www.transifex.net]\n" >> $(HOME)/.transifexrc; \ echo "[http://www.transifex.net]" >> $(HOME)/.transifexrc; \
printf "username = \n" >> $(HOME)/.transifexrc; \ echo "username = " >> $(HOME)/.transifexrc; \
printf "token = \n" >> $(HOME)/.transifexrc; \ echo "token = " >> $(HOME)/.transifexrc; \
printf "password = \n" >> $(HOME)/.transifexrc; \ echo "password = " >> $(HOME)/.transifexrc; \
printf "hostname = http://www.transifex.net\n" >> $(HOME)/.transifexrc; \ echo "hostname = http://www.transifex.net" >> $(HOME)/.transifexrc; \
printf "You must edit the file ~/.transifexrc to setup your transifex account (login & password) !\n"; \ echo "You must edit the file ~/.transifexrc to setup your transifex account (login & password) !"; \
exit 1; \ exit 1; \
fi fi
@ -115,47 +98,13 @@ po-push: check-tx-config
@tx push -t @tx push -t
po-pull: check-tx-config 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 @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 zipfile of indefero for a specified branch # Generic rule to build a tarball of indefero for a specified branch
# ex: make master_zipfile # ex: make master_tarball
# make develop_zipfile # make dev_tarball
# #
%-zipfile: %_tarball:
@git archive --format=zip --prefix="indefero/" $* \ @git archive --format=zip --prefix="indefero/" $(@:_tarball=) > indefero-$(@:_tarball=)-`git log $(@:_tarball=) -n 1 --pretty=format:%H`.zip
> indefero-$*-`git log $* -n 1 \
--pretty=format:%h`.zip
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.

View File

@ -1,320 +0,0 @@
# 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. please follow the `INSTALL` document which comes with the software.
It contains detailed instructions, including all needed dependencies. It contains detailed instructions, including all needed dependencies.
## Choose your indefero (IDF) setup ## Choose your indefero setup
The monotone plugin can be used in several different ways: The monotone plugin can be used in several different ways:
@ -112,40 +112,14 @@ The monotone plugin can be used in several different ways:
^D ^D
$ chmod 600 usher.conf $ 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 Your indefero www user needs later write access to `usher.conf` and
`projects/`. There are two ways of setting this up: `projects/`. There are two ways of setting this up:
* Make the usher user the web user, for example via Apache's `suexec`. * Make the usher user the web user, for example via Apache's `suexec`
This is however a bit clumsy. * Use acls, like this:
* Preferred: Use Access Control Lists (ACLs), like this:
#
# Linux
#
$ setfacl -m u:www:rw usher.conf $ setfacl -m u:www:rw usher.conf
$ setfacl -m d:u:www:rwx projects/ $ 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 5. Wrap a daemonizer around usher, for example supervise from daemontools
(<http://cr.yp.to/damontools.html>): (<http://cr.yp.to/damontools.html>):

View File

@ -1,284 +0,0 @@
<?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>

Before

Width:  |  Height:  |  Size: 8.6 KiB

View File

@ -1,173 +0,0 @@
<?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>

Before

Width:  |  Height:  |  Size: 8.4 KiB

View File

@ -1,27 +0,0 @@
<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>

View File

@ -1,14 +0,0 @@
#!/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

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

View File

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

View File

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

View File

@ -3,7 +3,7 @@
# #
# ***** BEGIN LICENSE BLOCK ***** # ***** BEGIN LICENSE BLOCK *****
# This file is part of InDefero, an open source project management application. # This file is part of InDefero, an open source project management application.
# Copyright (C) 2008-2011 Céondo Ltd and contributors. # Copyright (C) 2008 Céondo Ltd and contributors.
# #
# InDefero is free software; you can redistribute it and/or modify # InDefero is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by # it under the terms of the GNU General Public License as published by
@ -23,17 +23,14 @@
import os import os
import sys import sys
import subprocess import commands
import traceback
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: if status == 0:
os.execvp('git', ['git', 'shell', '-c', output.strip()]) os.execvp('git', ['git', 'shell', '-c', output.strip()])
else: else:
sys.stderr.write("%s\n" % output.strip()) sys.stderr.write("%s\n" % output)
sys.exit(1) sys.exit(1)

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -3,7 +3,7 @@
/* /*
# ***** BEGIN LICENSE BLOCK ***** # ***** BEGIN LICENSE BLOCK *****
# This file is part of InDefero, an open source project management application. # This file is part of InDefero, an open source project management application.
# Copyright (C) 2008-2011 Céondo Ltd and contributors. # Copyright (C) 2008 Céondo Ltd and contributors.
# #
# InDefero is free software; you can redistribute it and/or modify # InDefero is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by # it under the terms of the GNU General Public License as published by
@ -27,15 +27,17 @@
*/ */
class IDF_Diff class IDF_Diff
{ {
public $path_strip_level = 0; public $repo = '';
public $diff = '';
protected $lines = array(); protected $lines = array();
public $files = array(); public $files = array();
public function __construct($diff, $path_strip_level = 0) public function __construct($diff, $repo='')
{ {
$this->path_strip_level = $path_strip_level; $this->repo = $repo;
$this->lines = IDF_FileUtil::splitIntoLines($diff, true); $this->diff = $diff;
$this->lines = preg_split("/\015\012|\015|\012/", $diff);
} }
public function parse() public function parse()
@ -47,99 +49,118 @@ class IDF_Diff
$files = array(); $files = array();
$indiff = false; // Used to skip the headers in the git patches $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 $i = 0; // Used to skip the end of a git patch with --\nversion number
$diffsize = count($this->lines); foreach ($this->lines as $line) {
while ($i < $diffsize) {
// look for the potential beginning of a diff
if (substr($this->lines[$i], 0, 4) !== '--- ') {
$i++; $i++;
continue; if (0 === strpos($line, '--') and isset($this->lines[$i])
and preg_match('/^\d+\.\d+\.\d+\.\d+$/', $this->lines[$i])) {
break;
} }
if (0 === strpos($line, 'diff --git a')) {
// we're inside a diff candiate $current_file = self::getFile($line);
$oldfileline = $this->lines[$i++];
$newfileline = $this->lines[$i++];
if (substr($newfileline, 0, 4) !== '+++ ') {
// not a valid diff here, move on
continue;
}
// 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] = array();
$files[$current_file]['chunks'] = array(); $files[$current_file]['chunks'] = array();
$files[$current_file]['chunks_def'] = array(); $files[$current_file]['chunks_def'] = array();
$current_chunk = 0;
while ($i < $diffsize && substr($this->lines[$i], 0, 3) === '@@ ') { $indiff = true;
$elems = preg_match('/@@ -(\d+),?(\d*) \+(\d+),?(\d*) @@.*/',
$this->lines[$i++], $results);
if ($elems != 1) {
// hunk is badly formatted
break;
}
$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; continue;
default: } else if (preg_match('#^diff -r [^\s]+ -r [^\s]+ (.+)$#', $line, $matches)) {
break 2; $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]);
} }
$i++; 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);
$files[$current_file]['chunks'][] = array();
$current_chunk++; $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; $this->files = $files;
return $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. * Return the html version of a parsed diff.
*/ */
@ -152,88 +173,56 @@ class IDF_Diff
if (IDF_FileUtil::isSupportedExtension($fileinfo[2])) { if (IDF_FileUtil::isSupportedExtension($fileinfo[2])) {
$pretty = ' prettyprint'; $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; $cc = 1;
$offsets = array();
$contents = array();
foreach ($file['chunks'] as $chunk) { foreach ($file['chunks'] as $chunk) {
foreach ($chunk as $line) { foreach ($chunk as $line) {
list($left, $right, $content) = $line; if ($line[0] and $line[1]) {
if ($left and $right) { $class = 'diff-c';
$class = 'context'; } elseif ($line[0]) {
} elseif ($left) { $class = 'diff-r';
$class = 'removed';
} else { } else {
$class = 'added'; $class = 'diff-a';
} }
$line_content = self::padLine(Pluf_esc($line[2]));
$offsets[] = sprintf('<td>%s</td><td>%s</td>', $left, $right); $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);
$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++; $cc++;
} }
$out .= '</table>';
list($added, $removed) = end($file['chunks_def']);
$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));
}
$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 Pluf_Template::markSafe($out); return Pluf_Template::markSafe($out);
} }
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;
}
}
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)));
}
return $res;
}
/** /**
* Review patch. * Review patch.
* *
@ -256,12 +245,12 @@ class IDF_Diff
*/ */
public function fileCompare($orig, $chunks, $filename, $context=10) public function fileCompare($orig, $chunks, $filename, $context=10)
{ {
$orig_lines = IDF_FileUtil::splitIntoLines($orig); $orig_lines = preg_split("/\015\012|\015|\012/", $orig);
$new_chunks = $this->mergeChunks($orig_lines, $chunks, $context); $new_chunks = $this->mergeChunks($orig_lines, $chunks, $context);
return $this->renderCompared($new_chunks, $filename); return $this->renderCompared($new_chunks, $filename);
} }
private function mergeChunks($orig_lines, $chunks, $context=10) public function mergeChunks($orig_lines, $chunks, $context=10)
{ {
$spans = array(); $spans = array();
$new_chunks = array(); $new_chunks = array();
@ -358,115 +347,40 @@ class IDF_Diff
return $nnew_chunks; return $nnew_chunks;
} }
private function renderCompared($chunks, $filename)
public function renderCompared($chunks, $filename)
{ {
$fileinfo = IDF_FileUtil::getMimeType($filename); $fileinfo = IDF_FileUtil::getMimeType($filename);
$pretty = ''; $pretty = '';
if (IDF_FileUtil::isSupportedExtension($fileinfo[2])) { if (IDF_FileUtil::isSupportedExtension($fileinfo[2])) {
$pretty = ' prettyprint'; $pretty = ' prettyprint';
} }
$out = '';
$cc = 1; $cc = 1;
$left_offsets = array(); $i = 0;
$left_contents = array();
$right_offsets = array();
$right_contents = array();
$max_lineno_left = $max_lineno_right = 0;
foreach ($chunks as $chunk) { foreach ($chunks as $chunk) {
foreach ($chunk as $line) { foreach ($chunk as $line) {
$left = ''; $line1 = '&nbsp;';
$right = ''; $line2 = '&nbsp;';
$content = IDF_FileUtil::emphasizeControlCharacters(Pluf_esc($line[2])); $line[2] = (strlen($line[2])) ? self::padLine(Pluf_esc($line[2])) : '&nbsp;';
if ($line[0] and $line[1]) { if ($line[0] and $line[1]) {
$class = 'context'; $class = 'diff-c';
$left = $right = $content; $line1 = $line2 = $line[2];
} elseif ($line[0]) { } elseif ($line[0]) {
$class = 'removed'; $class = 'diff-r';
$left = $content; $line1 = $line[2];
} else { } else {
$class = 'added'; $class = 'diff-a';
$right = $content; $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);
$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>';
} }
if (count($chunks) > $cc)
$out .= '<tr class="diff-next"><td>...</td><td>&nbsp;</td><td>...</td><td>&nbsp;</td></tr>'."\n";
$cc++; $cc++;
$i++;
} }
$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); return Pluf_Template::markSafe($out);
} }
} }

View File

@ -1,96 +0,0 @@
<?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 ***** # ***** BEGIN LICENSE BLOCK *****
# This file is part of InDefero, an open source project management application. # This file is part of InDefero, an open source project management application.
# Copyright (C) 2008-2011 Céondo Ltd and contributors. # Copyright (C) 2010 Céondo Ltd and contributors.
# #
# InDefero is free software; you can redistribute it and/or modify # InDefero is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by # it under the terms of the GNU General Public License as published by
@ -65,9 +65,9 @@ class IDF_FileUtil
} }
$table = array(); $table = array();
$i = 1; $i = 1;
foreach (self::splitIntoLines($content) as $line) { foreach (preg_split("/\015\012|\015|\012/", $content) as $line) {
$table[] = '<tr class="c-line"><td class="code-lc" id="L'.$i.'"><a href="#L'.$i.'">'.$i.'</a></td>' $table[] = '<tr class="c-line"><td class="code-lc" id="L'.$i.'"><a href="#L'.$i.'">'.$i.'</a></td>'
.'<td class="code mono'.$pretty.'">'.self::emphasizeControlCharacters(Pluf_esc($line)).'</td></tr>'; .'<td class="code mono'.$pretty.'">'.IDF_Diff::padLine(Pluf_esc($line)).'</td></tr>';
$i++; $i++;
} }
return Pluf_Template::markSafe(implode("\n", $table)); return Pluf_Template::markSafe(implode("\n", $table));
@ -143,53 +143,6 @@ class IDF_FileUtil
return $res; 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. * Find if a given mime type is a text file.
* This uses the output of the self::getMimeType function. * This uses the output of the self::getMimeType function.

View File

@ -1,70 +0,0 @@
<?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

@ -1,47 +0,0 @@
<?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

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

View File

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

View File

@ -3,7 +3,7 @@
/* /*
# ***** BEGIN LICENSE BLOCK ***** # ***** BEGIN LICENSE BLOCK *****
# This file is part of InDefero, an open source project management application. # This file is part of InDefero, an open source project management application.
# Copyright (C) 2008-2011 Céondo Ltd and contributors. # Copyright (C) 2008 Céondo Ltd and contributors.
# #
# InDefero is free software; you can redistribute it and/or modify # InDefero is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by # it under the terms of the GNU General Public License as published by
@ -53,13 +53,6 @@ class IDF_Form_Admin_ProjectUpdate extends Pluf_Form
'widget_attrs' => array('size' => '35'), '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') { if ($this->project->getConf()->getVal('scm') == 'mtn') {
$this->fields['mtn_master_branch'] = new Pluf_Form_Field_Varchar( $this->fields['mtn_master_branch'] = new Pluf_Form_Field_Varchar(
array('required' => false, array('required' => false,
@ -70,26 +63,6 @@ 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( $this->fields['owners'] = new Pluf_Form_Field_Varchar(
array('required' => false, array('required' => false,
'label' => __('Project owners'), 'label' => __('Project owners'),
@ -115,7 +88,7 @@ class IDF_Form_Admin_ProjectUpdate extends Pluf_Form
$mtn_master_branch)) { $mtn_master_branch)) {
throw new Pluf_Form_Invalid(__( throw new Pluf_Form_Invalid(__(
'The master branch is empty or contains illegal characters, '. 'The master branch is empty or contains illegal characters, '.
'please use only letters, digits, dashes and dots as separators.' 'please use only letters, digits, dashs and dots as separators.'
)); ));
} }
@ -142,52 +115,22 @@ class IDF_Form_Admin_ProjectUpdate extends Pluf_Form
return IDF_Form_MembersConf::checkBadLogins($this->cleaned_data['members']); 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) public function save($commit=true)
{ {
if (!$this->isValid()) { if (!$this->isValid()) {
throw new Exception(__('Cannot save the model from an invalid form.')); 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, IDF_Form_MembersConf::updateMemberships($this->project,
$this->cleaned_data); $this->cleaned_data);
$this->project->membershipsUpdated(); $this->project->membershipsUpdated();
$this->project->name = $this->cleaned_data['name']; $this->project->name = $this->cleaned_data['name'];
$this->project->shortdesc = $this->cleaned_data['shortdesc']; $this->project->shortdesc = $this->cleaned_data['shortdesc'];
$this->project->update(); $this->project->update();
$conf = $this->project->getConf(); $keys = array('mtn_master_branch');
$keys = array('mtn_master_branch', 'external_project_url');
foreach ($keys as $key) { foreach ($keys as $key) {
if (array_key_exists($key, $this->cleaned_data)) {
if (!empty($this->cleaned_data[$key])) { if (!empty($this->cleaned_data[$key])) {
$conf->setVal($key, $this->cleaned_data[$key]); $this->project->getConf()->setVal($key, $this->cleaned_data[$key]);
}
else {
$conf->delVal($key);
}
} }
} }
} }

View File

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

View File

@ -3,7 +3,7 @@
/* /*
# ***** BEGIN LICENSE BLOCK ***** # ***** BEGIN LICENSE BLOCK *****
# This file is part of InDefero, an open source project management application. # This file is part of InDefero, an open source project management application.
# Copyright (C) 2008-2011 Céondo Ltd and contributors. # Copyright (C) 2008 Céondo Ltd and contributors.
# #
# InDefero is free software; you can redistribute it and/or modify # InDefero is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by # 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'), 'label' => __('Password'),
'initial' => '', 'initial' => '',
'widget' => 'Pluf_Form_Widget_PasswordInput', '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 guess, 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 find it, but easy for the user to remember.')),
'widget_attrs' => array( 'widget_attrs' => array(
'maxlength' => 50, 'maxlength' => 50,
'size' => 15, 'size' => 15,
@ -173,7 +173,7 @@ class IDF_Form_Admin_UserUpdate extends Pluf_Form
'initial' => $this->user->active, 'initial' => $this->user->active,
'widget' => 'Pluf_Form_Widget_CheckboxInput', 'widget' => 'Pluf_Form_Widget_CheckboxInput',
'widget_attrs' => $attrs, '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 their account here.'), '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.'),
)); ));
} }

View File

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

View File

@ -3,7 +3,7 @@
/* /*
# ***** BEGIN LICENSE BLOCK ***** # ***** BEGIN LICENSE BLOCK *****
# This file is part of InDefero, an open source project management application. # This file is part of InDefero, an open source project management application.
# Copyright (C) 2008-2011 Céondo Ltd and contributors. # Copyright (C) 2008 Céondo Ltd and contributors.
# #
# InDefero is free software; you can redistribute it and/or modify # InDefero is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by # it under the terms of the GNU General Public License as published by
@ -36,7 +36,6 @@ class IDF_Form_IssueCreate extends Pluf_Form
public $user = null; public $user = null;
public $project = null; public $project = null;
public $show_full = false; public $show_full = false;
public $relation_types = null;
public function initFields($extra=array()) public function initFields($extra=array())
{ {
@ -46,12 +45,9 @@ class IDF_Form_IssueCreate extends Pluf_Form
or $this->user->hasPerm('IDF.project-member', $this->project)) { or $this->user->hasPerm('IDF.project-member', $this->project)) {
$this->show_full = true; $this->show_full = true;
} }
$this->relation_types = $this->project->getRelationsFromConfig();
$contentTemplate = $this->project->getConf()->getVal( $contentTemplate = $this->project->getConf()->getVal(
'labels_issue_template', IDF_Form_IssueTrackingConf::init_template 'labels_issue_template', IDF_Form_IssueTrackingConf::init_template
); );
$this->fields['summary'] = new Pluf_Form_Field_Varchar( $this->fields['summary'] = new Pluf_Form_Field_Varchar(
array('required' => true, array('required' => true,
'label' => __('Summary'), 'label' => __('Summary'),
@ -113,20 +109,6 @@ class IDF_Form_IssueCreate extends Pluf_Form
), ),
)); ));
$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 * get predefined tags for issues from current project
* *
@ -214,7 +196,7 @@ class IDF_Form_IssueCreate extends Pluf_Form
else $count[$class] += 1; else $count[$class] += 1;
if (in_array($class, $onemax) and $count[$class] > 1) { if (in_array($class, $onemax) and $count[$class] > 1) {
if (!isset($this->errors['label'.$i])) $this->errors['label'.$i] = array(); if (!isset($this->errors['label'.$i])) $this->errors['label'.$i] = array();
$this->errors['label'.$i][] = sprintf(__('You cannot provide more than one label from the %s class to an issue.'), $class); $this->errors['label'.$i][] = sprintf(__('You cannot provide more than label from the %s class to an issue.'), $class);
throw new Pluf_Form_Invalid(__('You provided an invalid label.')); throw new Pluf_Form_Invalid(__('You provided an invalid label.'));
} }
} }
@ -253,63 +235,6 @@ class IDF_Form_IssueCreate extends Pluf_Form
return $this->cleaned_data['status']; 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. * Clean the attachments post failure.
*/ */
@ -373,30 +298,6 @@ class IDF_Form_IssueCreate extends Pluf_Form
foreach ($tags as $tag) { foreach ($tags as $tag) {
$issue->setAssoc($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 // add the first comment
$comment = new IDF_IssueComment(); $comment = new IDF_IssueComment();
$comment->issue = $issue; $comment->issue = $issue;

View File

@ -3,7 +3,7 @@
/* /*
# ***** BEGIN LICENSE BLOCK ***** # ***** BEGIN LICENSE BLOCK *****
# This file is part of InDefero, an open source project management application. # This file is part of InDefero, an open source project management application.
# Copyright (C) 2008-2011 Céondo Ltd and contributors. # Copyright (C) 2008 Céondo Ltd and contributors.
# #
# InDefero is free software; you can redistribute it and/or modify # InDefero is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by # it under the terms of the GNU General Public License as published by
@ -72,23 +72,6 @@ Performance = Performance issue
Usability = Affects program usability Usability = Affects program usability
Maintainability = Hinders future changes'; Maintainability = Hinders future changes';
const init_one_max = 'Type, Priority, Milestone'; 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()) public function initFields($extra=array())
{ {
@ -130,20 +113,11 @@ duplicates, is duplicated by';
$this->fields['labels_issue_one_max'] = new Pluf_Form_Field_Varchar( $this->fields['labels_issue_one_max'] = new Pluf_Form_Field_Varchar(
array('required' => false, array('required' => false,
'label' => __('Each issue may have at most one label with each of these classes.'), 'label' => __('Each issue 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), '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 ***** # ***** BEGIN LICENSE BLOCK *****
# This file is part of InDefero, an open source project management application. # This file is part of InDefero, an open source project management application.
# Copyright (C) 2008-2011 Céondo Ltd and contributors. # Copyright (C) 2008 Céondo Ltd and contributors.
# #
# InDefero is free software; you can redistribute it and/or modify # InDefero is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by # it under the terms of the GNU General Public License as published by
@ -39,7 +39,6 @@ class IDF_Form_IssueUpdate extends IDF_Form_IssueCreate
or $this->user->hasPerm('IDF.project-member', $this->project)) { or $this->user->hasPerm('IDF.project-member', $this->project)) {
$this->show_full = true; $this->show_full = true;
} }
$this->relation_types = $this->project->getRelationsFromConfig();
if ($this->show_full) { if ($this->show_full) {
$this->fields['summary'] = new Pluf_Form_Field_Varchar( $this->fields['summary'] = new Pluf_Form_Field_Varchar(
array('required' => true, array('required' => true,
@ -103,52 +102,6 @@ class IDF_Form_IssueUpdate extends IDF_Form_IssueCreate
'size' => 15, '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(); $tags = $this->issue->get_tags_list();
for ($i=1;$i<7;$i++) { for ($i=1;$i<7;$i++) {
$initial = ''; $initial = '';
@ -202,51 +155,6 @@ class IDF_Form_IssueUpdate extends IDF_Form_IssueCreate
public function clean() public function clean()
{ {
$this->cleaned_data = parent::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 // As soon as we know that at least one change was done, we
// return the cleaned data and do not go further. // return the cleaned data and do not go further.
if (strlen(trim($this->cleaned_data['content']))) { if (strlen(trim($this->cleaned_data['content']))) {
@ -306,11 +214,6 @@ class IDF_Form_IssueUpdate extends IDF_Form_IssueCreate
return $this->cleaned_data; 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! // no changes!
throw new Pluf_Form_Invalid(__('No changes were entered.')); throw new Pluf_Form_Invalid(__('No changes were entered.'));
@ -352,22 +255,20 @@ class IDF_Form_IssueUpdate extends IDF_Form_IssueCreate
foreach ($tags as $tag) { foreach ($tags as $tag) {
if (!Pluf_Model_InArray($tag, $oldtags)) { if (!Pluf_Model_InArray($tag, $oldtags)) {
if (!isset($changes['lb'])) $changes['lb'] = array(); if (!isset($changes['lb'])) $changes['lb'] = array();
if (!isset($changes['lb']['add'])) $changes['lb']['add'] = array();
if ($tag->class != 'Other') { if ($tag->class != 'Other') {
$changes['lb']['add'][] = (string) $tag; //new tag $changes['lb'][] = (string) $tag; //new tag
} else { } else {
$changes['lb']['add'][] = (string) $tag->name; $changes['lb'][] = (string) $tag->name;
} }
} }
} }
foreach ($oldtags as $tag) { foreach ($oldtags as $tag) {
if (!Pluf_Model_InArray($tag, $tags)) { if (!Pluf_Model_InArray($tag, $tags)) {
if (!isset($changes['lb'])) $changes['lb'] = array(); if (!isset($changes['lb'])) $changes['lb'] = array();
if (!isset($changes['lb']['rem'])) $changes['lb']['rem'] = array();
if ($tag->class != 'Other') { if ($tag->class != 'Other') {
$changes['lb']['rem'][] = (string) $tag; //new tag $changes['lb'][] = '-'.(string) $tag; //new tag
} else { } else {
$changes['lb']['rem'][] = (string) $tag->name; $changes['lb'][] = '-'.(string) $tag->name;
} }
} }
} }
@ -385,47 +286,6 @@ 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)) { 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; $changes['ow'] = (is_null($owner)) ? '---' : $owner->login;
} }
// 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 // Update the issue
$this->issue->batchAssoc('IDF_Tag', $tagids); $this->issue->batchAssoc('IDF_Tag', $tagids);
$this->issue->summary = trim($this->cleaned_data['summary']); $this->issue->summary = trim($this->cleaned_data['summary']);

View File

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

View File

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

View File

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

View File

@ -1,211 +0,0 @@
<?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 ***** # ***** BEGIN LICENSE BLOCK *****
# This file is part of InDefero, an open source project management application. # This file is part of InDefero, an open source project management application.
# Copyright (C) 2008-2011 Céondo Ltd and contributors. # Copyright (C) 2008 Céondo Ltd and contributors.
# #
# InDefero is free software; you can redistribute it and/or modify # InDefero is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by # 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, 'max_length' => 15,
'min_length' => 3, 'min_length' => 3,
'initial' => $login, 'initial' => $login,
'help_text' => __('The login must be between 3 and 15 characters long and contain only letters and digits.'), 'help_text' => __('The login must be between 3 and 15 characters long and contains only letters and digits.'),
'widget_attrs' => array( 'widget_attrs' => array(
'maxlength' => 15, 'maxlength' => 15,
'size' => 10, 'size' => 10,
@ -52,7 +52,7 @@ class IDF_Form_Register extends Pluf_Form
array('required' => true, array('required' => true,
'label' => __('Your email'), 'label' => __('Your email'),
'initial' => '', 'initial' => '',
'help_text' => __('We will never send you any unsolicited emails. We hate spam too!'), 'help_text' => __('We will never send you any unsolicited emails. We hate spams too!'),
)); ));
$this->fields['terms'] = new Pluf_Form_Field_Boolean( $this->fields['terms'] = new Pluf_Form_Field_Boolean(
@ -93,8 +93,10 @@ class IDF_Form_Register extends Pluf_Form
function clean_email() function clean_email()
{ {
$this->cleaned_data['email'] = mb_strtolower(trim($this->cleaned_data['email'])); $this->cleaned_data['email'] = mb_strtolower(trim($this->cleaned_data['email']));
if (Pluf::factory('IDF_EmailAddress')->get_user_for_email_address($this->cleaned_data['email']) != null) { $guser = new Pluf_User();
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'))); $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']));
} }
return $this->cleaned_data['email']; return $this->cleaned_data['email'];
} }

View File

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

View File

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

View File

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

View File

@ -3,7 +3,7 @@
/* /*
# ***** BEGIN LICENSE BLOCK ***** # ***** BEGIN LICENSE BLOCK *****
# This file is part of InDefero, an open source project management application. # This file is part of InDefero, an open source project management application.
# Copyright (C) 2008-2011 Céondo Ltd and contributors. # Copyright (C) 2008 Céondo Ltd and contributors.
# #
# InDefero is free software; you can redistribute it and/or modify # InDefero is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by # it under the terms of the GNU General Public License as published by
@ -64,8 +64,6 @@ class IDF_Form_ReviewFileComment extends Pluf_Form
if ($this->user->hasPerm('IDF.project-owner', $this->project) if ($this->user->hasPerm('IDF.project-owner', $this->project)
or $this->user->hasPerm('IDF.project-member', $this->project)) { or $this->user->hasPerm('IDF.project-member', $this->project)) {
$this->show_full = true; $this->show_full = true;
} else {
$this->show_full = false;
} }
if ($this->show_full) { if ($this->show_full) {
$this->fields['summary'] = new Pluf_Form_Field_Varchar( $this->fields['summary'] = new Pluf_Form_Field_Varchar(

View File

@ -3,7 +3,7 @@
/* /*
# ***** BEGIN LICENSE BLOCK ***** # ***** BEGIN LICENSE BLOCK *****
# This file is part of InDefero, an open source project management application. # This file is part of InDefero, an open source project management application.
# Copyright (C) 2008-2011 Céondo Ltd and contributors. # Copyright (C) 2008 Céondo Ltd and contributors.
# #
# InDefero is free software; you can redistribute it and/or modify # InDefero is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by # it under the terms of the GNU General Public License as published by
@ -49,10 +49,13 @@ class IDF_Form_SourceConf extends Pluf_Form
'widget' => 'Pluf_Form_Widget_PasswordInput', '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( $this->fields['webhook_url'] = new Pluf_Form_Field_Url(
array('required' => false, array('required' => false,
'label' => __('Webhook URL'), 'label' => __('Webhook URL'),
'initial' => $this->conf->getVal('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), 'widget_attrs' => array('size' => 35),
)); ));

View File

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

View File

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

View File

@ -3,7 +3,7 @@
/* /*
# ***** BEGIN LICENSE BLOCK ***** # ***** BEGIN LICENSE BLOCK *****
# This file is part of InDefero, an open source project management application. # This file is part of InDefero, an open source project management application.
# Copyright (C) 2008-2011 Céondo Ltd and contributors. # Copyright (C) 2008 Céondo Ltd and contributors.
# #
# InDefero is free software; you can redistribute it and/or modify # InDefero is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by # it under the terms of the GNU General Public License as published by
@ -79,12 +79,11 @@ class IDF_Form_Upload extends Pluf_Form
public function clean_file() 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')))); $extra = strtolower(implode('|', explode(' ', Pluf::f('idf_extra_upload_ext'))));
if (strlen($extra)) $extra .= '|'; 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'])) { 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']); @unlink(Pluf::f('upload_path').'/'.$this->project->shortname.'/files/'.$this->cleaned_data['file']);
throw new Pluf_Form_Invalid(__('For security reasons, you cannot upload a file with this extension.')); throw new Pluf_Form_Invalid(__('For security reason, you cannot upload a file with this extension.'));
} }
return $this->cleaned_data['file']; return $this->cleaned_data['file'];
} }
@ -117,7 +116,7 @@ class IDF_Form_Upload extends Pluf_Form
else $count[$class] += 1; else $count[$class] += 1;
if (in_array($class, $onemax) and $count[$class] > 1) { if (in_array($class, $onemax) and $count[$class] > 1) {
if (!isset($this->errors['label'.$i])) $this->errors['label'.$i] = array(); if (!isset($this->errors['label'.$i])) $this->errors['label'.$i] = array();
$this->errors['label'.$i][] = sprintf(__('You cannot provide more than one label from the %s class to a download.'), $class); $this->errors['label'.$i][] = sprintf(__('You cannot provide more than label from the %s class to an issue.'), $class);
throw new Pluf_Form_Invalid(__('You provided an invalid label.')); throw new Pluf_Form_Invalid(__('You provided an invalid label.'));
} }
} }

View File

@ -1,227 +0,0 @@
<?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

@ -1,158 +0,0 @@
<?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 ***** # ***** BEGIN LICENSE BLOCK *****
# This file is part of InDefero, an open source project management application. # This file is part of InDefero, an open source project management application.
# Copyright (C) 2008-2011 Céondo Ltd and contributors. # Copyright (C) 2008 Céondo Ltd and contributors.
# #
# InDefero is free software; you can redistribute it and/or modify # InDefero is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by # it under the terms of the GNU General Public License as published by
@ -64,14 +64,6 @@ Deprecated = Most users should NOT download this';
'widget_attrs' => array('size' => 60), '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 ***** # ***** BEGIN LICENSE BLOCK *****
# This file is part of InDefero, an open source project management application. # This file is part of InDefero, an open source project management application.
# Copyright (C) 2008-2011 Céondo Ltd and contributors. # Copyright (C) 2008 Céondo Ltd and contributors.
# #
# InDefero is free software; you can redistribute it and/or modify # InDefero is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by # 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( $this->fields['email'] = new Pluf_Form_Field_Email(
array('required' => true, array('required' => true,
'label' => __('Your email'), 'label' => __('Your mail'),
'initial' => $this->user->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.'), 'help_text' => __('If you change your email address, an email will be sent to the new address to confirm it.'),
)); ));
@ -79,7 +79,6 @@ class IDF_Form_UserAccount extends Pluf_Form
'widget' => 'Pluf_Form_Widget_PasswordInput', '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.')), '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( 'widget_attrs' => array(
'autocomplete' => 'off',
'maxlength' => 50, 'maxlength' => 50,
'size' => 15, 'size' => 15,
), ),
@ -90,7 +89,6 @@ class IDF_Form_UserAccount extends Pluf_Form
'initial' => '', 'initial' => '',
'widget' => 'Pluf_Form_Widget_PasswordInput', 'widget' => 'Pluf_Form_Widget_PasswordInput',
'widget_attrs' => array( 'widget_attrs' => array(
'autocomplete' => 'off',
'maxlength' => 50, 'maxlength' => 50,
'size' => 15, 'size' => 15,
), ),
@ -163,44 +161,8 @@ class IDF_Form_UserAccount extends Pluf_Form
'widget_attrs' => array('rows' => 3, 'widget_attrs' => array('rows' => 3,
'cols' => 40), 'cols' => 40),
'widget' => 'Pluf_Form_Widget_TextareaInput', 'widget' => 'Pluf_Form_Widget_TextareaInput',
'help_text' => __('Paste an SSH or monotone public key. Be careful to not provide your private key here!') 'help_text' => __('Paste a 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)));
} }
/** /**
@ -226,7 +188,26 @@ class IDF_Form_UserAccount extends Pluf_Form
$new_email = $this->cleaned_data['email']; $new_email = $this->cleaned_data['email'];
unset($this->cleaned_data['email']); unset($this->cleaned_data['email']);
if ($old_email != $new_email) { if ($old_email != $new_email) {
$this->send_validation_mail($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->user->setFromFormData($this->cleaned_data); $this->user->setFromFormData($this->cleaned_data);
// Add key as needed. // Add key as needed.
@ -238,9 +219,6 @@ class IDF_Form_UserAccount extends Pluf_Form
$key->create(); $key->create();
} }
} }
if ('' !== $this->cleaned_data['secondary_mail']) {
$this->send_validation_mail($this->cleaned_data['secondary_mail'], true);
}
if ($commit) { if ($commit) {
$this->user->update(); $this->user->update();
@ -317,15 +295,8 @@ class IDF_Form_UserAccount extends Pluf_Form
return ''; return '';
} }
$keysearch = ''; if (preg_match('#^ssh\-[a-z]{3}\s\S+(\s\S+)?$#', $key)) {
if (preg_match('#^(ssh\-(?:dss|rsa)\s+\S+)(.*)#', $key, $m)) { $key = str_replace(array("\n", "\r"), '', $key);
$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)) { if (Pluf::f('idf_strong_key_check', false)) {
@ -344,9 +315,7 @@ class IDF_Form_UserAccount extends Pluf_Form
} }
} }
} }
else if (preg_match('#^\[pubkey [^\]]+\]\s*(\S+)\s*\[end\]$#', $key, $m)) { else if (preg_match('#^\[pubkey [^\]]+\]\s*\S+\s*\[end\]$#', $key)) {
$keysearch = '%'.$m[1].'%';
if (Pluf::f('idf_strong_key_check', false)) { if (Pluf::f('idf_strong_key_check', false)) {
// if monotone can read it, it should be valid // if monotone can read it, it should be valid
@ -368,7 +337,7 @@ class IDF_Form_UserAccount extends Pluf_Form
} }
else { else {
throw new Pluf_Form_Invalid( throw new Pluf_Form_Invalid(
__('Public key looks like neither an SSH '. __('Public key looks neither like a SSH '.
'nor monotone public key.')); 'nor monotone public key.'));
} }
@ -376,7 +345,7 @@ class IDF_Form_UserAccount extends Pluf_Form
if ($user) { if ($user) {
$ruser = Pluf::factory('Pluf_User', $user); $ruser = Pluf::factory('Pluf_User', $user);
if ($ruser->id > 0) { if ($ruser->id > 0) {
$sql = new Pluf_SQL('content LIKE %s AND user=%s', array($keysearch, $ruser->id)); $sql = new Pluf_SQL('content=%s', array($key));
$keys = Pluf::factory('IDF_Key')->getList(array('filter' => $sql->gen())); $keys = Pluf::factory('IDF_Key')->getList(array('filter' => $sql->gen()));
if (count($keys) > 0) { if (count($keys) > 0) {
throw new Pluf_Form_Invalid( throw new Pluf_Form_Invalid(
@ -424,22 +393,15 @@ class IDF_Form_UserAccount extends Pluf_Form
function clean_email() function clean_email()
{ {
$this->cleaned_data['email'] = mb_strtolower(trim($this->cleaned_data['email'])); $this->cleaned_data['email'] = mb_strtolower(trim($this->cleaned_data['email']));
$user = Pluf::factory('IDF_EmailAddress')->get_user_for_email_address($this->cleaned_data['email']); $guser = new Pluf_User();
if ($user != null and $user->id != $this->user->id) { $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) {
throw new Pluf_Form_Invalid(sprintf(__('The email "%s" is already used.'), $this->cleaned_data['email'])); throw new Pluf_Form_Invalid(sprintf(__('The email "%s" is already used.'), $this->cleaned_data['email']));
} }
return $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() function clean_public_key()
{ {
$this->cleaned_data['public_key'] = $this->cleaned_data['public_key'] =

View File

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

View File

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

View File

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

View File

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

View File

@ -1,169 +0,0 @@
<?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

@ -1,64 +0,0 @@
<?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

@ -1,161 +0,0 @@
<?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 ***** # ***** BEGIN LICENSE BLOCK *****
# This file is part of InDefero, an open source project management application. # This file is part of InDefero, an open source project management application.
# Copyright (C) 2008-2011 Céondo Ltd and contributors. # Copyright (C) 2008 Céondo Ltd and contributors.
# #
# InDefero is free software; you can redistribute it and/or modify # InDefero is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by # it under the terms of the GNU General Public License as published by
@ -27,7 +27,7 @@
* This add a corresponding revision. * This add a corresponding revision.
* *
*/ */
class IDF_Form_WikiPageUpdate extends Pluf_Form class IDF_Form_WikiUpdate extends Pluf_Form
{ {
public $user = null; public $user = null;
public $project = null; public $project = null;
@ -120,7 +120,7 @@ class IDF_Form_WikiPageUpdate extends Pluf_Form
} }
$sql = new Pluf_SQL('project=%s AND title=%s', $sql = new Pluf_SQL('project=%s AND title=%s',
array($this->project->id, $title)); array($this->project->id, $title));
$pages = Pluf::factory('IDF_Wiki_Page')->getList(array('filter'=>$sql->gen())); $pages = Pluf::factory('IDF_WikiPage')->getList(array('filter'=>$sql->gen()));
if ($pages->count() > 0 and $pages[0]->id != $this->page->id) { if ($pages->count() > 0 and $pages[0]->id != $this->page->id) {
throw new Pluf_Form_Invalid(__('A page with this title already exists.')); throw new Pluf_Form_Invalid(__('A page with this title already exists.'));
} }
@ -158,7 +158,7 @@ class IDF_Form_WikiPageUpdate extends Pluf_Form
else $count[$class] += 1; else $count[$class] += 1;
if (in_array($class, $onemax) and $count[$class] > 1) { if (in_array($class, $onemax) and $count[$class] > 1) {
if (!isset($this->errors['label'.$i])) $this->errors['label'.$i] = array(); if (!isset($this->errors['label'.$i])) $this->errors['label'.$i] = array();
$this->errors['label'.$i][] = sprintf(__('You cannot provide more than one label from the %s class to a page.'), $class); $this->errors['label'.$i][] = sprintf(__('You cannot provide more than label from the %s class to a page.'), $class);
throw new Pluf_Form_Invalid(__('You provided an invalid label.')); throw new Pluf_Form_Invalid(__('You provided an invalid label.'));
} }
} }
@ -229,7 +229,7 @@ class IDF_Form_WikiPageUpdate extends Pluf_Form
} }
$this->page->update(); $this->page->update();
// add the new revision // add the new revision
$rev = new IDF_Wiki_PageRevision(); $rev = new IDF_WikiRevision();
$rev->wikipage = $this->page; $rev->wikipage = $this->page;
$rev->content = $this->cleaned_data['content']; $rev->content = $this->cleaned_data['content'];
$rev->submitter = $this->user; $rev->submitter = $this->user;

View File

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

View File

@ -3,7 +3,7 @@
/* /*
# ***** BEGIN LICENSE BLOCK ***** # ***** BEGIN LICENSE BLOCK *****
# This file is part of InDefero, an open source project management application. # This file is part of InDefero, an open source project management application.
# Copyright (C) 2008-2011 Céondo Ltd and contributors. # Copyright (C) 2008 Céondo Ltd and contributors.
# #
# InDefero is free software; you can redistribute it and/or modify # InDefero is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by # it under the terms of the GNU General Public License as published by
@ -169,24 +169,6 @@ 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 * Returns an HTML fragment used to display this issue in the
* timeline. * timeline.
@ -211,7 +193,7 @@ class IDF_Issue extends Pluf_Model
$ic = (in_array($this->status, $request->project->getTagIdsByStatus('closed'))) ? 'issue-c' : 'issue-o'; $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 .= 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"> $out .= "\n".'<tr class="extra"><td colspan="2">
<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>'; <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>';
return Pluf_Template::markSafe($out); return Pluf_Template::markSafe($out);
} }
@ -221,7 +203,7 @@ class IDF_Issue extends Pluf_Model
.Pluf_HTTP_URL_urlForView('IDF_Views_Issue::view', .Pluf_HTTP_URL_urlForView('IDF_Views_Issue::view',
array($request->project->shortname, array($request->project->shortname,
$this->id)); $this->id));
$title = sprintf(__('%1$s: Issue %2$d created - %3$s'), $title = sprintf(__('%s: Issue %d created - %s'),
$request->project->name, $request->project->name,
$this->id, $this->summary); $this->id, $this->summary);
$cts = $this->get_comments_list(array('order' => 'id ASC', $cts = $this->get_comments_list(array('order' => 'id ASC',
@ -256,72 +238,91 @@ class IDF_Issue extends Pluf_Model
*/ */
public function notify($conf, $create=true) public function notify($conf, $create=true)
{ {
$project = $this->get_project(); $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]);
}
}
$current_locale = Pluf_Translation::getLocale(); $current_locale = Pluf_Translation::getLocale();
$id = '<'.md5($this->id.md5(Pluf::f('secret_key'))).'@'.Pluf::f('mail_host', 'localhost').'>';
$from_email = Pluf::f('from_email'); if ($create) {
$comments = $this->get_comments_list(array('order' => 'id DESC')); if (null != $this->get_owner() and $this->owner != $this->submitter) {
$messageId = '<'.md5('issue'.$this->id.md5(Pluf::f('secret_key'))).'@'.Pluf::f('mail_host', 'localhost').'>'; $email_lang = array($this->get_owner()->email,
$recipients = $project->getNotificationRecipientsForTab('issues'); $this->get_owner()->language);
if (!in_array($email_lang, $to_email)) {
// the submitter (might be skipped later on if he is the one who also $to_email[] = $email_lang;
// 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;
} }
$comments = $this->get_comments_list(array('order' => 'id ASC'));
// additional users who starred the issue $context = new Pluf_Template_Context(
foreach ($this->get_interested_list() as $interested) { array(
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, 'issue' => $this,
'owns_issue' => $owner !== null && $owner->email === $address,
// the initial comment for create, the last for update
'comment' => $comments[0], 'comment' => $comments[0],
'comments' => $comments, 'project' => $prj,
'project' => $project,
'url_base' => Pluf::f('url_base'), 'url_base' => Pluf::f('url_base'),
)); )
);
$tplfile = 'idf/issues/issue-created-email.txt'; foreach ($to_email as $email_lang) {
$subject = __('Issue %1$s - %2$s (%3$s)'); Pluf_Translation::loadSetLocale($email_lang[1]);
$headers = array('Message-ID' => $messageId); $email = new Pluf_Mail(Pluf::f('from_email'), $email_lang[0],
if (!$create) { sprintf(__('Issue %s - %s (%s)'),
$tplfile = 'idf/issues/issue-updated-email.txt'; $this->id, $this->summary, $prj->shortname));
$subject = __('Updated Issue %1$s - %2$s (%3$s)'); $tmpl = new Pluf_Template('idf/issues/issue-created-email.txt');
$headers = array('References' => $messageId); $email->addTextMessage($tmpl->render($context));
} $email->addHeaders(array('Message-ID'=>$id));
$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(); $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();
}
}
Pluf_Translation::loadSetLocale($current_locale); Pluf_Translation::loadSetLocale($current_locale);
} }
} }

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,43 +0,0 @@
<?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

@ -1,90 +0,0 @@
<?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

@ -1,63 +0,0 @@
<?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

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

View File

@ -1,51 +0,0 @@
<?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

@ -1,68 +0,0 @@
<?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

@ -1,60 +0,0 @@
<?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

@ -1,42 +0,0 @@
<?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

@ -1,40 +0,0 @@
<?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

@ -1,47 +0,0 @@
<?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

@ -1,46 +0,0 @@
<?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

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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