Commit 03e2965e2112c154ee2e7f4c75db3af04a1c49f0

Authored by Leandro Santos
2 parents f710300a c5265b67

Merge branches 'master' and 'AI3269_link-article' into AI3269_link-article

Showing 1485 changed files with 91831 additions and 157969 deletions   Show diff stats

Too many changes.

To preserve performance only 100 of 1485 files displayed.

1 --ignore-dir=log 1 --ignore-dir=log
2 --ignore-dir=tmp 2 --ignore-dir=tmp
3 --ignore-dir=pkg 3 --ignore-dir=pkg
  4 +--ignore-dir=public/javascripts/cache
  5 +--ignore-dir=public/stylesheets/cache
@@ -1,250 +0,0 @@ @@ -1,250 +0,0 @@
1 -If you are not listed here, but should be, please write to the noosfero mailing  
2 -list: http://listas.softwarelivre.org/cgi-bin/mailman/listinfo/noosfero-dev  
3 -(this list requires subscription to post, but since you are an author of  
4 -noosfero, that's not a problem).  
5 -  
6 -Developers  
7 -==========  
8 -  
9 -Ábner Silva de Oliveira <abner.oliveira@serpro.gov.br>  
10 -Alan Freihof Tygel <alantygel@gmail.com>  
11 -alcampelo <alcampelo@alcampelo.(none)>  
12 -Alessandro Palmeira <alessandro.palmeira@gmail.com>  
13 -Alessandro Palmeira + Caio C. Salgado <alessandro.palmeira@gmail.com>  
14 -Alessandro Palmeira + Caio Salgado <alessandro.palmeira@gmail.com>  
15 -Alessandro Palmeira + Caio Salgado <caio.csalgado@gmail.com>  
16 -Alessandro Palmeira + Caio Salgado + Diego Araújo + João M. M. da Silva <diegoamc90@gmail.com>  
17 -Alessandro Palmeira + Carlos Morais <alessandro.palmeira@gmail.com>  
18 -Alessandro Palmeira + Daniel Alves <alessandro.palmeira@gmail.com>  
19 -Alessandro Palmeira + Daniel Alves + Diego Araújo <diegoamc90@gmail.com>  
20 -Alessandro Palmeira + Daniel Alves + Diego Araújo + Guilherme Rojas <danpaulalves@gmail.com>  
21 -Alessandro Palmeira + Diego Araujo <alessandro.palmeira@gmail.com>  
22 -Alessandro Palmeira + Diego Araújo <alessandro.palmeira@gmail.com>  
23 -Alessandro Palmeira + Diego Araujo + Daniela Feitosa <alessandro.palmeira@gmail.com>  
24 -Alessandro Palmeira + Diego Araujo <diegoamc90@gmail.com>  
25 -Alessandro Palmeira + Diego Araújo <diegoamc90@gmail.com>  
26 -Alessandro Palmeira + Diego Araujo + Eduardo Morais <alessandro.palmeira@gmail.com>  
27 -Alessandro Palmeira + Diego Araújo + João M. M. da Silva <alessandro.palmeira@gmail.com>  
28 -Alessandro Palmeira + Diego Araújo + João M. M. da Silva <diegoamc90@gmail.com>  
29 -Alessandro Palmeira + Diego Araujo + João M. M. da Silva + Paulo Meirelles <alessandro.palmeira@gmail.com>  
30 -Alessandro Palmeira + Diego Araújo + Pedro Leal <diegoamc90@gmail.com>  
31 -Alessandro Palmeira + Diego Araújo + Pedro Leal + João M. M. da Silva <diegoamc90@gmail.com>  
32 -Alessandro Palmeira + Diego Araujo + Rafael Manzo <alessandro.palmeira@gmail.com>  
33 -Alessandro Palmeira + Eduardo Morais <alessandro.palmeira@gmail.com>  
34 -Alessandro Palmeira + Guilherme Rojas <alessandro.palmeira@gmail.com>  
35 -Alessandro Palmeira + Jefferson Fernandes <alessandro.palmeira@gmail.com>  
36 -Alessandro Palmeira + João M. M. da Silva <alessandro.palmeira@gmail.com>  
37 -Alessandro Palmeira + Joao M. M. da Silva + Diego Araujo <alessandro.palmeira@gmail.com>  
38 -Alessandro Palmeira + João M. M. da Silva + Renan Teruo <alessandro.palmeira@gmail.com>  
39 -Alessandro Palmeira + João M. M. Silva <alessandro.palmeira@gmail.com>  
40 -Alessandro Palmeira + Paulo Meirelles <alessandro.palmeira@gmail.com>  
41 -Alessandro Palmeira + Paulo Meirelles + João M. M. da Silva <alessandro.palmeira@gmail.com>  
42 -Alessandro Palmeira + Rafael Manzo <alessandro.palmeira@gmail.com>  
43 -Ana Losnak <analosnak@gmail.com>  
44 -Antonio Terceiro + Carlos Morais <terceiro@colivre.coop.br>  
45 -Antonio Terceiro + Paulo Meirelles <terceiro@colivre.coop.br>  
46 -Antonio Terceiro <terceiro@colivre.coop.br>  
47 -Arthur Del Esposte <arthurmde@gmail.com>  
48 -Arthur Del Esposte <arthurmde@yahoo.com.br>  
49 -Aurelio A. Heckert <aurelio@colivre.coop.br>  
50 -Braulio Bhavamitra <brauliobo@gmail.com>  
51 -Bráulio Bhavamitra <brauliobo@gmail.com>  
52 -Braulio Bhavamitra <braulio@eita.org.br>  
53 -Caio <caio.csalgado@gmail.com>  
54 -Caio + Diego + Pedro + João <caio.csalgado@gmail.com>  
55 -Caio Formiga <caio.formiga@gmail.com>  
56 -Caio, Pedro <caio.csalgado@gmail.com>  
57 -Caio Salgado + Alessandro Palmeira <caio.csalgado@gmail.com>  
58 -Caio Salgado <caio.csalgado@gmail.com>  
59 -Caio Salgado + Carlos Morais + Diego Araújo + Pedro Leal <diegoamc90@gmail.com>  
60 -Caio Salgado + Diego Araujo <caio.csalgado@gmail.com>  
61 -Caio Salgado + Diego Araújo <caio.csalgado@gmail.com>  
62 -Caio Salgado + Diego Araújo <diegoamc90@gmail.com>  
63 -Caio Salgado + Diego Araújo + Jefferson Fernandes <caio.csalgado@gmail.com>  
64 -Caio Salgado + Diego Araújo + João M. M. da Silva <caio.csalgado@gmail.com>  
65 -Caio Salgado + Diego Araújo + Pedro Leal <caio.csalgado@gmail.com>  
66 -Caio Salgado + Diego Araújo + Pedro Leal <diegoamc90@gmail.com>  
67 -Caio Salgado + Diego Araújo + Rafael Manzo <diegoamc90@gmail.com>  
68 -Caio Salgado + Jefferson Fernandes <caio.csalgado@gmail.com>  
69 -Caio Salgado + Jefferson Fernandes <jeffs.fernandes@gmail.com>  
70 -Caio Salgado + Rafael Manzo <caio.csalgado@gmail.com>  
71 -Caio Salgado + Renan Teruo <caio.csalgado@gmail.com>  
72 -Caio Salgado + Renan Teruo <caio.salgado@gmail.com>  
73 -Caio Salgado + Renan Teruo + Jefferson Fernandes <jeffs.fernandes@gmail.com>  
74 -Caio Salgado + Renan Teruo <renanteruoc@gmail.com>  
75 -Caio SBA <caio@colivre.coop.br>  
76 -Caio Tiago Oliveira <caiotiago@colivre.coop.br>  
77 -Carlos Andre de Souza <carlos.andre.souza@msn.com>  
78 -Carlos Morais <carlos88morais@gmail.com>  
79 -Carlos Morais + Diego Araújo <diegoamc90@gmail.com>  
80 -Carlos Morais + Eduardo Morais <carlos88morais@gmail.com>  
81 -Carlos Morais + Paulo Meirelles <carlos88morais@gmail.com>  
82 -Carlos Morais + Pedro Leal <carlos88morais@gmail.com>  
83 -Daniela Feitosa <dani@dohko.(none)>  
84 -Daniel Alves + Diego Araújo <danpaulalves@gmail.com>  
85 -Daniel Alves + Diego Araújo <diegoamc90@gmail.com>  
86 -Daniel Alves + Diego Araújo + Guilherme Rojas <danpaulalves@gmail.com>  
87 -Daniel Alves + Diego Araújo + Guilherme Rojas <diegoamc90@gmail.com>  
88 -Daniel Alves + Diego Araújo + Guilherme Rojas <guilhermehrojas@gmail.com>  
89 -Daniel Alves + Guilherme Rojas <danpaulalves@gmail.com>  
90 -Daniel Alves + Rafael Manzo <rr.manzo@gmail.com>  
91 -Daniela Soares Feitosa <danielafeitosa@colivre.coop.br>  
92 -Daniel Bucher <daniel.bucher88@gmail.com>  
93 -Daniel Cunha <daniel@colivre.coop.br>  
94 -David Carlos <ddavidcarlos1392@gmail.com>  
95 -diegoamc <diegoamc90@gmail.com>  
96 -Diego Araújo + Alessandro Palmeira <diegoamc90@gmail.com>  
97 -Diego Araújo + Alessandro Palmeira + João M. M. da Silva <diegoamc90@gmail.com>  
98 -Diego Araújo + Alessandro Palmeira + Rafael Manzo <rr.manzo@gmail.com>  
99 -Diego Araujo + Caio Salgado <diegoamc90@gmail.com>  
100 -Diego Araújo + Daniel Alves + Rafael Manzo <rr.manzo@gmail.com>  
101 -Diego Araújo <diegoamc90@gmail.com>  
102 -Diego Araújo + Eduardo Morais + Paulo Meirelles <diegoamc90@gmail.com>  
103 -Diego Araújo + Guilherme Rojas <diegoamc90@gmail.com>  
104 -Diego Araújo + Jefferson Fernandes <diegoamc90@gmail.com>  
105 -Diego Araujo + Jefferson Fernandes <jeffs.fernandes@gmail.com>  
106 -Diego Araújo + João Machini <diegoamc90@gmail.com>  
107 -Diego Araújo + João Machini <digoamc90@gmail.com>  
108 -Diego Araújo + João M. M. da Silva + Alessandro Palmeira <jaodsilv@linux.ime.usp.br>  
109 -Diego Araújo + João M. M. da Silva <diegoamc90@gmail.com>  
110 -Diego Araújo + João M. M. da Silva + João Machini <diegoamc90@gmail.com>  
111 -Diego Araújo + João M. M. da Silva + Pedro Leal <diegoamc90@gmail.com>  
112 -Diego Araújo + Paulo Meirelles <diegoamc90@gmail.com>  
113 -Diego Araújo + Pedro Leal <diegoamc90@gmail.com>  
114 -Diego Araujo + Rafael Manzo <diegoamc90@gmail.com>  
115 -Diego Araújo + Rafael Manzo <diegoamc90@gmail.com>  
116 -Diego Araújo + Renan Teruo + Alessandro Palmeira <diegoamc90@gmail.com>  
117 -Diego Araújo + Renan Teruo <diegoamc90@gmail.com>  
118 -Diego Araujo + Rodrigo Souto + Rafael Manzo <rr.manzo@gmail.com>  
119 -Diego + Jefferson <diegoamc90@gmail.com>  
120 -Diego Martinez <diegoamc90@gmail.com>  
121 -Diego Martinez <diego@diego-K55A.(none)>  
122 -Diego + Renan <renanteruoc@gmail.com>  
123 -Eduardo Tourinho Edington <eduardo.edington@serpro.gov.br>  
124 -Evandro Jr <evandrojr@gmail.com>  
125 -Evandro Junior <evandrojr@gmail.com>  
126 -Fabio Teixeira <fabio1079@gmail.com>  
127 -Fernanda Lopes <nanda.listas+psl@gmail.com>  
128 -Francisco Marcelo A. Lima Júnior <francisco.lima-junior@serpro.gov.br>  
129 -Francisco Marcelo de Araujo Lima Junior <79350259591@serpro-1457614.(none)>  
130 -Francisco Marcelo de Araújo Lima Júnior <francisco.lima-junior@serpro.gov.br>  
131 -Francisco Marcelo de Araújo Lima Júnior <maljunior@gmail.com>  
132 -Gabriela Navarro <navarro1703@gmail.com>  
133 -Grazieno Pellegrino <grazieno@gmail.com>  
134 -Gust <darksshades@hotmail.com>  
135 -Hugo Melo <hugo@riseup.net>  
136 -Isaac Canan <isaac@intelletto.com.br>  
137 -Italo Valcy <italo@dcc.ufba.br>  
138 -Jefferson Fernandes + Diego Araujo + Rafael Manzo <jeffs.fernandes@gmail.com>  
139 -Jefferson Fernandes + Joao M. M. da Silva <jeffs.fernandes@gmail.com>  
140 -Jefferson Fernandes + Joao M. M. Silva <jeffs.fernandes@gmail.com>  
141 -João da Silva + Eduardo Morais + Rafael Manzo <rr.manzo@gmail.com>  
142 -João da Silva <jaodsilv@linux.ime.usp.br>  
143 -João Marco Maciel da Silva + Rafael Manzo + Renan Teruo <jaodsilv@linux.ime.usp.br>  
144 -João M. M. da Silva + Alessandro Palmeira + Diego Araújo + Caio Salgado <jaodsilv@linux.ime.usp.br>  
145 -João M. M. da Silva + Alessandro Palmeira + Diego Araújo <jaodsilv@linux.ime.usp.br>  
146 -Joao M. M. da Silva + Alessandro Palmeira <jaodsilv@linux.ime.usp.br>  
147 -João M. M. da Silva + Alessandro Palmeira <jaodsilv@linux.ime.usp.br>  
148 -João M. M. da Silva + Alessandro Palmeira + João Machini <jaodsilv@linux.ime.usp.br>  
149 -João M. M. da Silva + Caio Salgado + Alessandro Palmeira <jaodsilv@linux.ime.usp.br>  
150 -João M. M. da Silva + Caio Salgado <jaodsilv@linux.ime.usp.br>  
151 -João M. M. da Silva + Carlos Morais <jaodsilv@linux.ime.usp.br>  
152 -João M. M. da Silva + Diego Araújo <diegoamc90@gmail.com>  
153 -João M. M. da Silva + Diego Araújo <jaodsilv@linux.ime.usp.br>  
154 -João M. M. da Silva + Diego Araújo + Pedro Leal <jaodsilv@linux.ime.usp.br>  
155 -João M. M. da Silva <jaodsilv@linux.ime.usp.br>  
156 -Joao M. M. da Silva + Jefferson Fernandes <jaodsilv@linux.ime.usp.br>  
157 -João M. M. da Silva + Jefferson Fernandes <jaodsilv@linux.ime.usp.br>  
158 -João M. M. da Silva + João M. Miranda <jaodsilv@linux.ime.usp.br>  
159 -João M. M. da Silva + Paulo Meirelles <jaodsilv@linux.ime.usp.br>  
160 -João M. M. da Silva + Pedro Leal <jaodsilv@linux.ime.usp.br>  
161 -João M. M. da Silva + Rafael Manzo + Diego Araújo <jaodsilv@linux.ime.usp.br>  
162 -João M. M. da Silva + Rafael Manzo <jaodsilv@linux.ime.usp.br>  
163 -João M. M. da Silva + Renan Teruo <jaodsilv@linux.ime.usp.br>  
164 -João M. M. Silva + Caio Salgado <jaodsilv@linux.ime.usp.br>  
165 -João M. M. Silva + Diego Araújo <jaodsilv@linux.ime.usp.br>  
166 -Joao M. M. Silva + Jefferson Fernandes <jaodsilv@linux.ime.usp.br>  
167 -João M. M. Silva + Paulo Meirelles <jaodsilv@linux.ime.usp.br>  
168 -João M. M. Silva + Rafael Manzo <jaodsilv@linux.ime.usp.br>  
169 -João M. M. Silva + Renan Teruo <jaodsilv@linux.ime.usp.br>  
170 -Joenio Costa <joenio@colivre.coop.br>  
171 -Josef Spillner <josef.spillner@tu-dresden.de>  
172 -Junior Silva <junior@bajor.localhost.localdomain>  
173 -Junior Silva <juniorsilva1001@gmail.com>  
174 -Junior Silva <juniorsilva7@juniorsilva-Aspire-5750Z.(none)>  
175 -Junior Silva <juniorsilva@colivre.coop.br>  
176 -juniorsilva <juniorsilva@QonoS.localhost.localdomain>  
177 -Keilla Menezes <keilla@colivre.coop.br>  
178 -Larissa Reis <larissa@colivre.coop.br>  
179 -Larissa Reis <reiss.larissa@gmail.com>  
180 -Leandro Nunes dos Santos <81665687568@serpro-1541727.Home>  
181 -Leandro Nunes dos Santos <81665687568@serpro-1541727.(none)>  
182 -Leandro Nunes dos Santos <leandronunes@gmail.com>  
183 -Leandro Nunes dos Santos <leandro.santos@serpro.gov.br>  
184 -LinguÁgil 2010 <linguagil.bahia@gmail.com>  
185 -Lucas Melo <lucas@colivre.coop.br>  
186 -Lucas Melo <lucaspradomelo@gmail.com>  
187 -Luciano <lucianopcbr@gmail.com>  
188 -Luis David Aguilar Carlos <ludwig9003@gmail.com>  
189 -Luiz Fernando de Freitas Matos <luiz@luizff.matos@gmail.com>  
190 -Marcos Ramos <ms.ramos@outlook.com>  
191 -Martín Olivera <molivera@solar.org.ar>  
192 -Moises Machado <moises@colivre.coop.br>  
193 -Naíla Alves <naila@colivre.coop.br>  
194 -Nanda Lopes <nanda.listas+psl@gmail.com>  
195 -Paulo Meirelles + Alessandro Palmeira + João M. M. da Silva <paulo@softwarelivre.org>  
196 -Paulo Meirelles + Alessandro Palmeira <paulo@softwarelivre.org>  
197 -Paulo Meirelles + Carlos Morais <paulo@softwarelivre.org>  
198 -Paulo Meirelles + Diego Araújo <paulo@softwarelivre.org>  
199 -Paulo Meirelles + João M. M. da Silva <paulo@softwarelivre.org>  
200 -Paulo Meirelles <paulo@softwarelivre.org>  
201 -Paulo Meirelles + Rafael Manzo <paulo@softwarelivre.org>  
202 -Rafael Gomes <rafaelgomes@techfree.com.br>  
203 -Rafael Manzo + Alessandro Palmeira <rr.manzo@gmail.com>  
204 -Rafael Manzo + Daniel Alves <danpaulalves@gmail.com>  
205 -Rafael Manzo + Diego Araújo <rr.manzo@gmail.com>  
206 -Rafael Manzo + João M. M. Silva <rr.manzo@gmail.com>  
207 -Rafael Manzo + Paulo Meirelles <rr.manzo@gmail.com>  
208 -Rafael Martins <rmmartins@gmail.com>  
209 -Rafael Reggiani Manzo + Caio Salgado + Jefferson Fernandes <rr.manzo@gmail.com>  
210 -Rafael Reggiani Manzo + Diego Araujo <diegoamc90@gmail.com>  
211 -Rafael Reggiani Manzo + Diego Araujo <rr.manzo@gmail.com>  
212 -Rafael Reggiani Manzo + Diego Araújo <rr.manzo@gmail.com>  
213 -Rafael Reggiani Manzo + João M. M. da Silva <rr.manzo@gmail.com>  
214 -Rafael Reggiani Manzo <rr.manzo@gmail.com>  
215 -Raphaël Rousseau <raph@r4f.org>  
216 -Raquel Lira <raquel.lira@gmail.com>  
217 -Renan Teruo + Caio Salgado <renanteruoc@gmail.com>  
218 -Renan Teruoc + Diego Araujo <renanteruoc@gmail.com>  
219 -Renan Teruo + Diego Araujo <renanteruoc@gmail.com>  
220 -Renan Teruo + Diego Araújo <renanteruoc@gmail.com>  
221 -Renan Teruo + Paulo Meirelles <renanteruoc@gmail.com>  
222 -Renan Teruo + Rafael Manzo <renanteruoc@gmail.com>  
223 -Rodrigo Souto + Ana Losnak + Daniel Bucher + Caio Almeida + Leandro Nunes + Daniela Feitosa + Mariel Zasso <noosfero-br@listas.softwarelivre.org>  
224 -Rodrigo Souto <diguliu@gmail.com>  
225 -Rodrigo Souto <rodrigo@colivre.coop.br>  
226 -Ronny Kursawe <kursawe.ronny@googlemail.com>  
227 -root <root@debian.sdr.serpro>  
228 -Samuel R. C. Vale <srcvale@holoscopio.com>  
229 -Valessio Brito <contato@valessiobrito.com.br>  
230 -Valessio Brito <contato@valessiobrito.info>  
231 -Valessio Brito <valessio@gmail.com>  
232 -vfcosta <vfcosta@gmail.com>  
233 -Victor Carvalho <victorhugodf.ac@gmail.com>  
234 -Victor Costa <vfcosta@gmail.com>  
235 -Victor Hugo Alves de Carvalho <victorhugodf.ac@gmail.com>  
236 -Vinicius Cubas Brand <viniciuscb@gmail.com>  
237 -Visita <visita@debian.(none)>  
238 -Yann Lugrin <yann.lugrin@liquid-concept.ch>  
239 -  
240 -Ideas, specifications and incentive  
241 -===================================  
242 -Daniel Tygel <dtygel@fbes.org.br>  
243 -Guilherme Rocha <guilherme@gf7.com.br>  
244 -Raphael Rousseau <raph@r4f.org>  
245 -Théo Bondolfi <move@cooperation.net>  
246 -Vicente Aguiar <vicenteaguiar@colivre.coop.br>  
247 -  
248 -Arts  
249 -===================================  
250 -Nara Oliveira <narananet@gmail.com>  
1 -If you are not listed here, but should be, please write to the noosfero mailing list: http://listas.softwarelivre.org/cgi-bin/mailman/listinfo/noosfero-dev (this list requires subscription to post, but since you are an author of noosfero, that's not a problem). 1 +If you are not listed here, but should be, please write to the noosfero mailing
  2 +list: http://listas.softwarelivre.org/cgi-bin/mailman/listinfo/noosfero-dev
  3 +(this list requires subscription to post, but since you are an author of
  4 +noosfero, that's not a problem).
2 5
3 Developers 6 Developers
4 ========== 7 ==========
5 8
  9 +Ábner Silva de Oliveira <abner.oliveira@serpro.gov.br>
6 Alan Freihof Tygel <alantygel@gmail.com> 10 Alan Freihof Tygel <alantygel@gmail.com>
  11 +alcampelo <alcampelo@alcampelo.(none)>
7 Alessandro Palmeira <alessandro.palmeira@gmail.com> 12 Alessandro Palmeira <alessandro.palmeira@gmail.com>
8 Alessandro Palmeira + Caio C. Salgado <alessandro.palmeira@gmail.com> 13 Alessandro Palmeira + Caio C. Salgado <alessandro.palmeira@gmail.com>
9 Alessandro Palmeira + Caio Salgado <alessandro.palmeira@gmail.com> 14 Alessandro Palmeira + Caio Salgado <alessandro.palmeira@gmail.com>
@@ -35,9 +40,14 @@ Alessandro Palmeira + João M. M. Silva &lt;alessandro.palmeira@gmail.com&gt; @@ -35,9 +40,14 @@ Alessandro Palmeira + João M. M. Silva &lt;alessandro.palmeira@gmail.com&gt;
35 Alessandro Palmeira + Paulo Meirelles <alessandro.palmeira@gmail.com> 40 Alessandro Palmeira + Paulo Meirelles <alessandro.palmeira@gmail.com>
36 Alessandro Palmeira + Paulo Meirelles + João M. M. da Silva <alessandro.palmeira@gmail.com> 41 Alessandro Palmeira + Paulo Meirelles + João M. M. da Silva <alessandro.palmeira@gmail.com>
37 Alessandro Palmeira + Rafael Manzo <alessandro.palmeira@gmail.com> 42 Alessandro Palmeira + Rafael Manzo <alessandro.palmeira@gmail.com>
  43 +analosnak <analosnak@gmail.com>
  44 +Ana Losnak <analosnak@gmail.com>
  45 +Andre Bernardes <andrebsguedes@gmail.com>
38 Antonio Terceiro + Carlos Morais <terceiro@colivre.coop.br> 46 Antonio Terceiro + Carlos Morais <terceiro@colivre.coop.br>
39 Antonio Terceiro + Paulo Meirelles <terceiro@colivre.coop.br> 47 Antonio Terceiro + Paulo Meirelles <terceiro@colivre.coop.br>
40 Antonio Terceiro <terceiro@colivre.coop.br> 48 Antonio Terceiro <terceiro@colivre.coop.br>
  49 +Arthur Del Esposte <arthurmde@gmail.com>
  50 +Arthur Del Esposte <arthurmde@yahoo.com.br>
41 Aurelio A. Heckert <aurelio@colivre.coop.br> 51 Aurelio A. Heckert <aurelio@colivre.coop.br>
42 Braulio Bhavamitra <brauliobo@gmail.com> 52 Braulio Bhavamitra <brauliobo@gmail.com>
43 Bráulio Bhavamitra <brauliobo@gmail.com> 53 Bráulio Bhavamitra <brauliobo@gmail.com>
@@ -65,6 +75,8 @@ Caio Salgado + Renan Teruo &lt;caio.salgado@gmail.com&gt; @@ -65,6 +75,8 @@ Caio Salgado + Renan Teruo &lt;caio.salgado@gmail.com&gt;
65 Caio Salgado + Renan Teruo + Jefferson Fernandes <jeffs.fernandes@gmail.com> 75 Caio Salgado + Renan Teruo + Jefferson Fernandes <jeffs.fernandes@gmail.com>
66 Caio Salgado + Renan Teruo <renanteruoc@gmail.com> 76 Caio Salgado + Renan Teruo <renanteruoc@gmail.com>
67 Caio SBA <caio@colivre.coop.br> 77 Caio SBA <caio@colivre.coop.br>
  78 +Caio Tiago Oliveira <caiotiago@colivre.coop.br>
  79 +Carlos Andre de Souza <carlos.andre.souza@msn.com>
68 Carlos Morais <carlos88morais@gmail.com> 80 Carlos Morais <carlos88morais@gmail.com>
69 Carlos Morais + Diego Araújo <diegoamc90@gmail.com> 81 Carlos Morais + Diego Araújo <diegoamc90@gmail.com>
70 Carlos Morais + Eduardo Morais <carlos88morais@gmail.com> 82 Carlos Morais + Eduardo Morais <carlos88morais@gmail.com>
@@ -78,7 +90,9 @@ Daniel Alves + Diego Araújo + Guilherme Rojas &lt;guilhermehrojas@gmail.com&gt; @@ -78,7 +90,9 @@ Daniel Alves + Diego Araújo + Guilherme Rojas &lt;guilhermehrojas@gmail.com&gt;
78 Daniel Alves + Guilherme Rojas <danpaulalves@gmail.com> 90 Daniel Alves + Guilherme Rojas <danpaulalves@gmail.com>
79 Daniel Alves + Rafael Manzo <rr.manzo@gmail.com> 91 Daniel Alves + Rafael Manzo <rr.manzo@gmail.com>
80 Daniela Soares Feitosa <danielafeitosa@colivre.coop.br> 92 Daniela Soares Feitosa <danielafeitosa@colivre.coop.br>
  93 +Daniel Bucher <daniel.bucher88@gmail.com>
81 Daniel Cunha <daniel@colivre.coop.br> 94 Daniel Cunha <daniel@colivre.coop.br>
  95 +David Carlos <ddavidcarlos1392@gmail.com>
82 diegoamc <diegoamc90@gmail.com> 96 diegoamc <diegoamc90@gmail.com>
83 Diego Araújo + Alessandro Palmeira <diegoamc90@gmail.com> 97 Diego Araújo + Alessandro Palmeira <diegoamc90@gmail.com>
84 Diego Araújo + Alessandro Palmeira + João M. M. da Silva <diegoamc90@gmail.com> 98 Diego Araújo + Alessandro Palmeira + João M. M. da Silva <diegoamc90@gmail.com>
@@ -105,17 +119,27 @@ Diego Araújo + Renan Teruo &lt;diegoamc90@gmail.com&gt; @@ -105,17 +119,27 @@ Diego Araújo + Renan Teruo &lt;diegoamc90@gmail.com&gt;
105 Diego Araujo + Rodrigo Souto + Rafael Manzo <rr.manzo@gmail.com> 119 Diego Araujo + Rodrigo Souto + Rafael Manzo <rr.manzo@gmail.com>
106 Diego + Jefferson <diegoamc90@gmail.com> 120 Diego + Jefferson <diegoamc90@gmail.com>
107 Diego Martinez <diegoamc90@gmail.com> 121 Diego Martinez <diegoamc90@gmail.com>
108 -Diego Martinez <diego@diego-K55A.(none)>  
109 Diego + Renan <renanteruoc@gmail.com> 122 Diego + Renan <renanteruoc@gmail.com>
  123 +Eduardo Tourinho Edington <eduardo.edington@serpro.gov.br>
  124 +Evandro Jr <evandrojr@gmail.com>
  125 +Evandro Junior <evandrojr@gmail.com>
  126 +Fabio Teixeira <fabio1079@gmail.com>
110 Fernanda Lopes <nanda.listas+psl@gmail.com> 127 Fernanda Lopes <nanda.listas+psl@gmail.com>
111 Francisco Marcelo A. Lima Júnior <francisco.lima-junior@serpro.gov.br> 128 Francisco Marcelo A. Lima Júnior <francisco.lima-junior@serpro.gov.br>
112 Francisco Marcelo de Araujo Lima Junior <79350259591@serpro-1457614.(none)> 129 Francisco Marcelo de Araujo Lima Junior <79350259591@serpro-1457614.(none)>
  130 +Francisco Marcelo de Araújo Lima Júnior <francisco.lima-junior@serpro.gov.br>
  131 +Francisco Marcelo de Araújo Lima Júnior <maljunior@gmail.com>
  132 +Gabriela Navarro <navarro1703@gmail.com>
113 Grazieno Pellegrino <grazieno@gmail.com> 133 Grazieno Pellegrino <grazieno@gmail.com>
  134 +Gust <darksshades@hotmail.com>
  135 +Hebert Douglas <hebertdougl@gmail.com>
  136 +Hugo Melo <hugo@riseup.net>
114 Isaac Canan <isaac@intelletto.com.br> 137 Isaac Canan <isaac@intelletto.com.br>
115 Italo Valcy <italo@dcc.ufba.br> 138 Italo Valcy <italo@dcc.ufba.br>
116 Jefferson Fernandes + Diego Araujo + Rafael Manzo <jeffs.fernandes@gmail.com> 139 Jefferson Fernandes + Diego Araujo + Rafael Manzo <jeffs.fernandes@gmail.com>
117 Jefferson Fernandes + Joao M. M. da Silva <jeffs.fernandes@gmail.com> 140 Jefferson Fernandes + Joao M. M. da Silva <jeffs.fernandes@gmail.com>
118 Jefferson Fernandes + Joao M. M. Silva <jeffs.fernandes@gmail.com> 141 Jefferson Fernandes + Joao M. M. Silva <jeffs.fernandes@gmail.com>
  142 +João da Silva + Eduardo Morais + Rafael Manzo <rr.manzo@gmail.com>
119 João da Silva <jaodsilv@linux.ime.usp.br> 143 João da Silva <jaodsilv@linux.ime.usp.br>
120 João Marco Maciel da Silva + Rafael Manzo + Renan Teruo <jaodsilv@linux.ime.usp.br> 144 João Marco Maciel da Silva + Rafael Manzo + Renan Teruo <jaodsilv@linux.ime.usp.br>
121 João M. M. da Silva + Alessandro Palmeira + Diego Araújo + Caio Salgado <jaodsilv@linux.ime.usp.br> 145 João M. M. da Silva + Alessandro Palmeira + Diego Araújo + Caio Salgado <jaodsilv@linux.ime.usp.br>
@@ -146,21 +170,35 @@ João M. M. Silva + Rafael Manzo &lt;jaodsilv@linux.ime.usp.br&gt; @@ -146,21 +170,35 @@ João M. M. Silva + Rafael Manzo &lt;jaodsilv@linux.ime.usp.br&gt;
146 João M. M. Silva + Renan Teruo <jaodsilv@linux.ime.usp.br> 170 João M. M. Silva + Renan Teruo <jaodsilv@linux.ime.usp.br>
147 Joenio Costa <joenio@colivre.coop.br> 171 Joenio Costa <joenio@colivre.coop.br>
148 Josef Spillner <josef.spillner@tu-dresden.de> 172 Josef Spillner <josef.spillner@tu-dresden.de>
  173 +Jose Pedro <1jpsneto@gmail.com>
  174 +Junior Silva <junior@bajor.localhost.localdomain>
  175 +Junior Silva <junior@sedeantigo.colivre.coop.br>
149 Junior Silva <juniorsilva1001@gmail.com> 176 Junior Silva <juniorsilva1001@gmail.com>
150 Junior Silva <juniorsilva7@juniorsilva-Aspire-5750Z.(none)> 177 Junior Silva <juniorsilva7@juniorsilva-Aspire-5750Z.(none)>
  178 +Junior Silva <juniorsilva@colivre.coop.br>
  179 +juniorsilva <juniorsilva@QonoS.localhost.localdomain>
151 Keilla Menezes <keilla@colivre.coop.br> 180 Keilla Menezes <keilla@colivre.coop.br>
152 Larissa Reis <larissa@colivre.coop.br> 181 Larissa Reis <larissa@colivre.coop.br>
153 Larissa Reis <reiss.larissa@gmail.com> 182 Larissa Reis <reiss.larissa@gmail.com>
  183 +Leandro Alves <leandrosustenido@gmail.com>
  184 +Leandro Nunes dos Santos <81665687568@serpro-1541727.Home>
  185 +Leandro Nunes dos Santos <81665687568@serpro-1541727.(none)>
154 Leandro Nunes dos Santos <leandronunes@gmail.com> 186 Leandro Nunes dos Santos <leandronunes@gmail.com>
155 Leandro Nunes dos Santos <leandro.santos@serpro.gov.br> 187 Leandro Nunes dos Santos <leandro.santos@serpro.gov.br>
156 LinguÁgil 2010 <linguagil.bahia@gmail.com> 188 LinguÁgil 2010 <linguagil.bahia@gmail.com>
157 Lucas Melo <lucas@colivre.coop.br> 189 Lucas Melo <lucas@colivre.coop.br>
158 Lucas Melo <lucaspradomelo@gmail.com> 190 Lucas Melo <lucaspradomelo@gmail.com>
  191 +Luciano <lucianopcbr@gmail.com>
  192 +Luciano Prestes Cavalcanti <lucianopcbr@gmail.com>
159 Luis David Aguilar Carlos <ludwig9003@gmail.com> 193 Luis David Aguilar Carlos <ludwig9003@gmail.com>
  194 +Luiz Fernando de Freitas Matos <luiz@luizff.matos@gmail.com>
  195 +Marcos Ramos <ms.ramos@outlook.com>
160 Martín Olivera <molivera@solar.org.ar> 196 Martín Olivera <molivera@solar.org.ar>
  197 +Michal Čihař <michal@cihar.com>
161 Moises Machado <moises@colivre.coop.br> 198 Moises Machado <moises@colivre.coop.br>
162 Naíla Alves <naila@colivre.coop.br> 199 Naíla Alves <naila@colivre.coop.br>
163 Nanda Lopes <nanda.listas+psl@gmail.com> 200 Nanda Lopes <nanda.listas+psl@gmail.com>
  201 +Parley Martins <parleypachecomartins@gmail.com>
164 Paulo Meirelles + Alessandro Palmeira + João M. M. da Silva <paulo@softwarelivre.org> 202 Paulo Meirelles + Alessandro Palmeira + João M. M. da Silva <paulo@softwarelivre.org>
165 Paulo Meirelles + Alessandro Palmeira <paulo@softwarelivre.org> 203 Paulo Meirelles + Alessandro Palmeira <paulo@softwarelivre.org>
166 Paulo Meirelles + Carlos Morais <paulo@softwarelivre.org> 204 Paulo Meirelles + Carlos Morais <paulo@softwarelivre.org>
@@ -183,20 +221,28 @@ Rafael Reggiani Manzo + João M. M. da Silva &lt;rr.manzo@gmail.com&gt; @@ -183,20 +221,28 @@ Rafael Reggiani Manzo + João M. M. da Silva &lt;rr.manzo@gmail.com&gt;
183 Rafael Reggiani Manzo <rr.manzo@gmail.com> 221 Rafael Reggiani Manzo <rr.manzo@gmail.com>
184 Raphaël Rousseau <raph@r4f.org> 222 Raphaël Rousseau <raph@r4f.org>
185 Raquel Lira <raquel.lira@gmail.com> 223 Raquel Lira <raquel.lira@gmail.com>
  224 +Raquel <rcordioli@gmail.com>
186 Renan Teruo + Caio Salgado <renanteruoc@gmail.com> 225 Renan Teruo + Caio Salgado <renanteruoc@gmail.com>
187 Renan Teruoc + Diego Araujo <renanteruoc@gmail.com> 226 Renan Teruoc + Diego Araujo <renanteruoc@gmail.com>
188 Renan Teruo + Diego Araujo <renanteruoc@gmail.com> 227 Renan Teruo + Diego Araujo <renanteruoc@gmail.com>
189 Renan Teruo + Diego Araújo <renanteruoc@gmail.com> 228 Renan Teruo + Diego Araújo <renanteruoc@gmail.com>
190 Renan Teruo + Paulo Meirelles <renanteruoc@gmail.com> 229 Renan Teruo + Paulo Meirelles <renanteruoc@gmail.com>
191 Renan Teruo + Rafael Manzo <renanteruoc@gmail.com> 230 Renan Teruo + Rafael Manzo <renanteruoc@gmail.com>
192 -Rodrigo Souto <diguliu@gmail.com> 231 +Rodrigo Souto + Ana Losnak + Daniel Bucher + Caio Almeida + Leandro Nunes + Daniela Feitosa + Mariel Zasso <noosfero-br@listas.softwarelivre.org>
193 Rodrigo Souto <rodrigo@colivre.coop.br> 232 Rodrigo Souto <rodrigo@colivre.coop.br>
194 Ronny Kursawe <kursawe.ronny@googlemail.com> 233 Ronny Kursawe <kursawe.ronny@googlemail.com>
195 root <root@debian.sdr.serpro> 234 root <root@debian.sdr.serpro>
196 Samuel R. C. Vale <srcvale@holoscopio.com> 235 Samuel R. C. Vale <srcvale@holoscopio.com>
  236 +Tallys Martins <tallysmartins@gmail.com>
  237 +tallys <tallys@tallys.(none)>
  238 +Thiago Zoroastro <thiago.zoroastro@bol.com.br>
  239 +Valessio Brito <contato@valessiobrito.com.br>
  240 +Valessio Brito <contato@valessiobrito.info>
197 Valessio Brito <valessio@gmail.com> 241 Valessio Brito <valessio@gmail.com>
198 vfcosta <vfcosta@gmail.com> 242 vfcosta <vfcosta@gmail.com>
  243 +Victor Carvalho <victorhugodf.ac@gmail.com>
199 Victor Costa <vfcosta@gmail.com> 244 Victor Costa <vfcosta@gmail.com>
  245 +Victor Hugo Alves de Carvalho <victorhugodf.ac@gmail.com>
200 Vinicius Cubas Brand <viniciuscb@gmail.com> 246 Vinicius Cubas Brand <viniciuscb@gmail.com>
201 Visita <visita@debian.(none)> 247 Visita <visita@debian.(none)>
202 Yann Lugrin <yann.lugrin@liquid-concept.ch> 248 Yann Lugrin <yann.lugrin@liquid-concept.ch>
DEVELOPMENT.md 0 → 100644
@@ -0,0 +1,124 @@ @@ -0,0 +1,124 @@
  1 +# Noosfero Development Policy
  2 +
  3 +## Developer Roles
  4 +
  5 +* *Developers* are everyone that is contributing code to Noosfero.
  6 +* *Committers* are the people with direct commit access to the Noosfero source
  7 + code. They are responsible for reviewing contributions from other developers
  8 + and integrating them in the Noosfero code base. They are the members of the
  9 + [Noosfero group on Gitlab](https://gitlab.com/groups/noosfero/members).
  10 +* *Release managers* are the people that are managing the release of a new
  11 + Noosfero version and/or the maintainance work of an existing Noosfero stable
  12 + branch. See MAINTAINANCE.md for details on the maintaince policy.
  13 +
  14 +## Development process
  15 +
  16 +* Every new feature or non-trivial bugfix should be reviewed by at least one
  17 + committer. This must be the case even if the original author is a committer.
  18 +
  19 + * In the case the original author is a committer, he/she should feel free to
  20 + commit directly if after 1 week nobody has provided any kind of feedback.
  21 +
  22 + * Developers who are not committers should feel free to ping committers if
  23 + they do not get feedback on their contributions after 1 week.
  24 +
  25 + * On GitLab, one can just add a comment to the merge request; one can also
  26 + @-mention specific committers or other developers who have expertise on
  27 + the area of the contribution.
  28 +
  29 + * Committers should follow the activity of the project, and try to help
  30 + reviewing contributions from others as much as possible.
  31 +
  32 + * On GitLab one can get emails for all activity on a project by setting the
  33 + [notification settings](https://gitlab.com/profile/notifications) to
  34 + "watch".
  35 +
  36 + * Anyone can help by reviewing contributions. Committers are the only ones
  37 + who can give the final approval to a contribution, but everyone is welcome
  38 + to help with code review, testing, etc.
  39 +
  40 + * See note above about setting up notification on GitLab.
  41 +
  42 +* Committers should feel free to push trivial (or urgent) changes directly.
  43 + There are no strict rule on what makes a change trivial or urgent; committers
  44 + are expected to exercise good judgement on a case by case basis.
  45 +
  46 + * Usually changes to the database are not trivial.
  47 +
  48 +* In the case of unsolvable conflict between commiters regarding any change to
  49 + the code, the current release manager(s) will have the final say in the
  50 + matter.
  51 +
  52 +* Release managers are responsible for stablishing a release schedule, and
  53 + about deciding when and what to release.
  54 +
  55 + * Release managers should announce release schedules to the project mailing
  56 + lists in advance.
  57 +
  58 + * The release schedule may include a period of feature freeze, during which
  59 + no new features or any other changes that are not pre-approved by the
  60 + release manager must be committed to the repository.
  61 +
  62 + * Committers must respect the release schedule and feature freezes.
  63 +
  64 +## Maintainance process
  65 +
  66 +### Not all feature releases will be maintained as a stable release
  67 +
  68 +We will be choosing specific release series to be maintained as stable
  69 +releases.
  70 +
  71 +This means that a given release is not guaranteed to be maintained as a stable
  72 +release, but does *not* mean it won't be. Any committer (or anyone, really) can
  73 +decide to maintain a given release as stable and seek help from others to do
  74 +so.
  75 +
  76 +### No merges from stable branches to master
  77 +
  78 +*All* changes must be submitted against the master branch first, and when
  79 +applicable, backported to the desired stable releases. Exceptions to this rules
  80 +are bug fixes that only apply to a given stable branch and not to master.
  81 +
  82 +In the past we had non-trivial changes accepted into stable releases while
  83 +master was way ahead (e.g. during the rails3 migration period), that made the
  84 +merge back into master very painful. By eliminating the need to do these
  85 +merges, we save time for the people responsible for the release, and eliminate
  86 +the possibility of human errors or oversights causing changes to be accepted
  87 +into stable that will be a problem to merge back into master.
  88 +
  89 +By getting all fixes in master first, we improve the chances that a future
  90 +release will not present regressions against bugs that should already be fixed,
  91 +but the fixes got lost in a big, complicated merge (and those won't exist
  92 +anymore, at least not from stable branches to master).
  93 +
  94 +After a fix gets into master, backporting changes into a stable release branch
  95 +is the responsibility of whoever is maintaing that branch, and those interested
  96 +in it. The stable branch release manager(s) are entitled the final say on any
  97 +matters related to that branch.
  98 +
  99 +## Apendix A: how to become a committer
  100 +
  101 +Every developer that wants to be a committer should create [an issue on
  102 +Gitlab](https://gitlab.com/noosfero/noosfero/issues) requesting to be added as
  103 +a committer. This request must include information about the requestor's
  104 +previous contributions to the project.
  105 +
  106 +If 2 or more commiters consider second the request, the requestor is accepted
  107 +as new commiter and added to the Noosfero group.
  108 +
  109 +The existing committers are free to choose whatever criteria they want to
  110 +second the request, but they must be sure that the new committer is a
  111 +responsible developer and knows what she/he is doing. They must be aware that
  112 +seconding these requests means seconding the actions of the new committer: if
  113 +the new committer screw up, her/his seconds screwed up.
  114 +
  115 +## Apendix B: how to become a release manager
  116 +
  117 +A new release manager for the development version of Noosfero (i.e. the one
  118 +that includes new features, a.k.a. the master branch) is apointed by the
  119 +current release manager, and must be a committer first.
  120 +
  121 +Release managers for stable branches are self-appointed, i.e. whoever takes the
  122 +work takes the role. In case of a conflict (e.g. 2+ different people want to do
  123 +the work but can't agree on working together), the development release manager
  124 +decides.
1 source "https://rubygems.org" 1 source "https://rubygems.org"
2 -gem 'rails'  
3 -gem 'fast_gettext'  
4 -gem 'acts-as-taggable-on'  
5 -gem 'prototype-rails'  
6 -gem 'prototype_legacy_helper', '0.0.0', :path => 'vendor/prototype_legacy_helper'  
7 -gem 'rails_autolink'  
8 -gem 'pg'  
9 -gem 'rmagick'  
10 -gem 'RedCloth'  
11 -gem 'will_paginate'  
12 -gem 'ruby-feedparser'  
13 -gem 'daemons'  
14 -gem 'thin'  
15 -gem 'hpricot'  
16 -gem 'nokogiri' 2 +gem 'rails', '~> 3.2.19'
  3 +gem 'fast_gettext', '~> 0.6.8'
  4 +gem 'acts-as-taggable-on', '~> 3.0.2'
  5 +gem 'prototype-rails', '~> 3.2.1'
  6 +gem 'prototype_legacy_helper', '0.0.0', :path => 'vendor/prototype_legacy_helper'
  7 +gem 'rails_autolink', '~> 1.1.5'
  8 +gem 'pg', '~> 0.13.2'
  9 +gem 'rmagick', '~> 2.13.1'
  10 +gem 'RedCloth', '~> 4.2.9'
  11 +gem 'will_paginate', '~> 3.0.3'
  12 +gem 'ruby-feedparser', '~> 0.7'
  13 +gem 'daemons', '~> 1.1.5'
  14 +gem 'thin', '~> 1.3.1'
  15 +gem 'hpricot', '~> 0.8.6'
  16 +gem 'nokogiri', '~> 1.5.5'
17 gem 'rake', :require => false 17 gem 'rake', :require => false
18 -gem 'rest-client' 18 +gem 'rest-client', '~> 1.6.7'
  19 +gem 'exception_notification', '~> 4.0.1'
  20 +gem 'gettext', '~> 2.2.1', :require => false, :group => :development
  21 +gem 'locale', '~> 2.0.5'
19 22
20 # FIXME list here all actual dependencies (i.e. the ones in debian/control), 23 # FIXME list here all actual dependencies (i.e. the ones in debian/control),
21 # with their GEM names (not the Debian package names) 24 # with their GEM names (not the Debian package names)
22 25
23 group :production do 26 group :production do
24 - gem 'dalli' 27 + gem 'dalli', '~> 2.7.0'
25 end 28 end
26 29
27 group :test do 30 group :test do
28 - gem 'rspec'  
29 - gem 'rspec-rails'  
30 - gem 'mocha', :require => false 31 + gem 'rspec', '~> 2.10.0'
  32 + gem 'rspec-rails', '~> 2.10.1'
  33 + gem 'mocha', '~> 1.1.0', :require => false
31 end 34 end
32 35
33 group :cucumber do 36 group :cucumber do
34 - gem 'rake'  
35 - gem 'cucumber-rails', :require => false  
36 - gem 'capybara'  
37 - gem 'cucumber'  
38 - gem 'database_cleaner'  
39 - gem 'selenium-webdriver' 37 + gem 'cucumber-rails', '~> 1.0.6', :require => false
  38 + gem 'capybara', '~> 2.1.0'
  39 + gem 'cucumber', '~> 1.0.6'
  40 + gem 'database_cleaner', '~> 1.2.0'
  41 + gem 'selenium-webdriver', '~> 2.39.0'
40 end 42 end
41 43
42 -# include plugin gemfiles  
43 -Dir.glob(File.join('config', 'plugins', '*')).each do |plugin|  
44 - plugin_gemfile = File.join(plugin, 'Gemfile')  
45 - eval File.read(plugin_gemfile) if File.exists?(plugin_gemfile) 44 +# include gemfiles from enabled plugins
  45 +# plugins in baseplugins/ are not included on purpose. They should not have any
  46 +# dependencies.
  47 +Dir.glob('config/plugins/*/Gemfile').each do |gemfile|
  48 + eval File.read(gemfile)
46 end 49 end
Gemfile.lock
@@ -1,187 +0,0 @@ @@ -1,187 +0,0 @@
1 -PATH  
2 - remote: vendor/prototype_legacy_helper  
3 - specs:  
4 - prototype_legacy_helper (0.0.0)  
5 -  
6 -GEM  
7 - remote: https://rubygems.org/  
8 - specs:  
9 - RedCloth (4.2.9)  
10 - actionmailer (3.2.6)  
11 - actionpack (= 3.2.6)  
12 - mail (~> 2.4.4)  
13 - actionpack (3.2.6)  
14 - activemodel (= 3.2.6)  
15 - activesupport (= 3.2.6)  
16 - builder (~> 3.0.0)  
17 - erubis (~> 2.7.0)  
18 - journey (~> 1.0.1)  
19 - rack (~> 1.4.0)  
20 - rack-cache (~> 1.2)  
21 - rack-test (~> 0.6.1)  
22 - sprockets (~> 2.1.3)  
23 - activemodel (3.2.6)  
24 - activesupport (= 3.2.6)  
25 - builder (~> 3.0.0)  
26 - activerecord (3.2.6)  
27 - activemodel (= 3.2.6)  
28 - activesupport (= 3.2.6)  
29 - arel (~> 3.0.2)  
30 - tzinfo (~> 0.3.29)  
31 - activeresource (3.2.6)  
32 - activemodel (= 3.2.6)  
33 - activesupport (= 3.2.6)  
34 - activesupport (3.2.6)  
35 - i18n (~> 0.6)  
36 - multi_json (~> 1.0)  
37 - acts-as-taggable-on (3.0.2)  
38 - rails (>= 3, < 5)  
39 - arel (3.0.2)  
40 - builder (3.0.0)  
41 - capybara (2.1.0)  
42 - mime-types (>= 1.16)  
43 - nokogiri (>= 1.3.3)  
44 - rack (>= 1.0.0)  
45 - rack-test (>= 0.5.4)  
46 - xpath (~> 2.0)  
47 - childprocess (0.3.3)  
48 - ffi (~> 1.0.6)  
49 - cucumber (1.0.6)  
50 - builder (>= 2.1.2)  
51 - diff-lcs (>= 1.1.2)  
52 - gherkin (~> 2.4.18)  
53 - json (>= 1.4.6)  
54 - term-ansicolor (>= 1.0.6)  
55 - cucumber-rails (1.0.6)  
56 - capybara (>= 1.1.1)  
57 - cucumber (>= 1.0.6)  
58 - nokogiri (>= 1.5.0)  
59 - daemons (1.1.5)  
60 - dalli (2.7.0)  
61 - database_cleaner (1.2.0)  
62 - diff-lcs (1.1.3)  
63 - erubis (2.7.0)  
64 - eventmachine (0.12.11)  
65 - fast_gettext (0.6.8)  
66 - ffi (1.0.11)  
67 - gherkin (2.4.21)  
68 - json (>= 1.4.6)  
69 - hike (1.2.1)  
70 - hpricot (0.8.6)  
71 - i18n (0.6.0)  
72 - journey (1.0.3)  
73 - json (1.7.3)  
74 - mail (2.4.4)  
75 - i18n (>= 0.4.0)  
76 - mime-types (~> 1.16)  
77 - treetop (~> 1.4.8)  
78 - metaclass (0.0.1)  
79 - mime-types (1.19)  
80 - mocha (0.11.3)  
81 - metaclass (~> 0.0.1)  
82 - multi_json (1.3.6)  
83 - nokogiri (1.5.5)  
84 - pg (0.13.2)  
85 - polyglot (0.3.3)  
86 - prototype-rails (3.2.1)  
87 - rails (~> 3.2)  
88 - rack (1.4.1)  
89 - rack-cache (1.2)  
90 - rack (>= 0.4)  
91 - rack-ssl (1.3.2)  
92 - rack  
93 - rack-test (0.6.1)  
94 - rack (>= 1.0)  
95 - rails (3.2.6)  
96 - actionmailer (= 3.2.6)  
97 - actionpack (= 3.2.6)  
98 - activerecord (= 3.2.6)  
99 - activeresource (= 3.2.6)  
100 - activesupport (= 3.2.6)  
101 - bundler (~> 1.0)  
102 - railties (= 3.2.6)  
103 - rails_autolink (1.1.5)  
104 - rails (> 3.1)  
105 - railties (3.2.6)  
106 - actionpack (= 3.2.6)  
107 - activesupport (= 3.2.6)  
108 - rack-ssl (~> 1.3.2)  
109 - rake (>= 0.8.7)  
110 - rdoc (~> 3.4)  
111 - thor (>= 0.14.6, < 2.0)  
112 - rake (0.9.2.2)  
113 - rdoc (3.9.4)  
114 - rest-client (1.6.7)  
115 - mime-types (>= 1.16)  
116 - rmagick (2.13.1)  
117 - rspec (2.10.0)  
118 - rspec-core (~> 2.10.0)  
119 - rspec-expectations (~> 2.10.0)  
120 - rspec-mocks (~> 2.10.0)  
121 - rspec-core (2.10.1)  
122 - rspec-expectations (2.10.0)  
123 - diff-lcs (~> 1.1.3)  
124 - rspec-mocks (2.10.1)  
125 - rspec-rails (2.10.1)  
126 - actionpack (>= 3.0)  
127 - activesupport (>= 3.0)  
128 - railties (>= 3.0)  
129 - rspec (~> 2.10.0)  
130 - ruby-feedparser (0.7)  
131 - rubyzip (1.1.2)  
132 - selenium-webdriver (2.39.0)  
133 - childprocess (>= 0.2.5)  
134 - multi_json (~> 1.0)  
135 - rubyzip (~> 1.0)  
136 - websocket (~> 1.0.4)  
137 - sprockets (2.1.3)  
138 - hike (~> 1.2)  
139 - multi_json (~> 1.0)  
140 - rack (~> 1.0)  
141 - tilt (~> 1.1, != 1.3.0)  
142 - term-ansicolor (1.0.7)  
143 - thin (1.3.1)  
144 - daemons (>= 1.0.9)  
145 - eventmachine (>= 0.12.6)  
146 - rack (>= 1.0.0)  
147 - thor (0.15.3)  
148 - tilt (1.3.3)  
149 - treetop (1.4.10)  
150 - polyglot  
151 - polyglot (>= 0.3.1)  
152 - tzinfo (0.3.33)  
153 - websocket (1.0.7)  
154 - will_paginate (3.0.3)  
155 - xpath (2.0.0)  
156 - nokogiri (~> 1.3)  
157 -  
158 -PLATFORMS  
159 - ruby  
160 -  
161 -DEPENDENCIES  
162 - RedCloth  
163 - acts-as-taggable-on  
164 - capybara  
165 - cucumber  
166 - cucumber-rails  
167 - daemons  
168 - dalli  
169 - database_cleaner  
170 - fast_gettext  
171 - hpricot  
172 - mocha  
173 - nokogiri  
174 - pg  
175 - prototype-rails  
176 - prototype_legacy_helper (= 0.0.0)!  
177 - rails  
178 - rails_autolink  
179 - rake  
180 - rest-client  
181 - rmagick  
182 - rspec  
183 - rspec-rails  
184 - ruby-feedparser  
185 - selenium-webdriver  
186 - thin  
187 - will_paginate  
INSTALL.https.md
1 -Setup Noosfero to use HTTPS  
2 -=========================== 1 +# Setup Noosfero to use HTTPS
3 2
4 This document assumes that you have a fully and clean Noosfero 3 This document assumes that you have a fully and clean Noosfero
5 installation as explained at the `INSTALL.md` file. 4 installation as explained at the `INSTALL.md` file.
6 5
7 -SSL certificate  
8 -+++++++++++++++ 6 +## Creating a self-signed SSL certificate
9 7
10 You should get a valid SSL certificate, but if you want to test 8 You should get a valid SSL certificate, but if you want to test
11 your setup before, you could generate a self-signed certificate 9 your setup before, you could generate a self-signed certificate
@@ -17,99 +15,106 @@ as below: @@ -17,99 +15,106 @@ as below:
17 # openssl req -new -x509 -nodes -sha1 -days $[10*365] -key noosfero.key > noosfero.cert 15 # openssl req -new -x509 -nodes -sha1 -days $[10*365] -key noosfero.key > noosfero.cert
18 # cat noosfero.key noosfero.cert > noosfero.pem 16 # cat noosfero.key noosfero.cert > noosfero.pem
19 17
  18 +## Web server configuration
  19 +
20 There are two ways of using SSL with Noosfero: 1) If you are not using 20 There are two ways of using SSL with Noosfero: 1) If you are not using
21 Varnish; and 2) If you are using Varnish. 21 Varnish; and 2) If you are using Varnish.
22 22
23 -1) If you are are not using Varnish  
24 -+++++++++++++++++++++++++++++++++++ 23 +### 1) If you are are not using Varnish
25 24
26 Simply do a redirect in apache to force all connections with SSL: 25 Simply do a redirect in apache to force all connections with SSL:
27 26
28 - <VirtualHost *:8080>  
29 - ServerName test.stoa.usp.br  
30 -  
31 - Redirect / https://example.com/  
32 - </VirtualHost> 27 +```
  28 +<VirtualHost *:8080>
  29 + ServerName test.stoa.usp.br
  30 + Redirect / https://example.com/
  31 +</VirtualHost>
  32 +```
33 33
34 And set a vhost to receive then: 34 And set a vhost to receive then:
35 35
36 - <VirtualHost *:443>  
37 - ServerName example.com  
38 -  
39 - SSLEngine On  
40 - SSLCertificateFile /etc/ssl/certs/cert.pem  
41 - SSLCertificateKeyFile /etc/ssl/private/cert.key  
42 -  
43 - Include /etc/noosfero/apache/virtualhost.conf  
44 - </VirtualHost> 36 +```
  37 +<VirtualHost *:443>
  38 + ServerName example.com
  39 + SSLEngine On
  40 + SSLCertificateFile /etc/ssl/certs/cert.pem
  41 + SSLCertificateKeyFile /etc/ssl/private/cert.key
  42 + Include /etc/noosfero/apache/virtualhost.conf
  43 +</VirtualHost>
  44 +```
45 45
46 Be aware that if you had configured varnish, the requests won't reach 46 Be aware that if you had configured varnish, the requests won't reach
47 it with this configuration. 47 it with this configuration.
48 48
49 -2) If you are using Varnish  
50 -+++++++++++++++++++++++++++  
51 -  
52 -Varnish isn't able to communicate with the SSL protocol, so we will  
53 -need some one who do this and Pound[1] can do the job. In order to  
54 -install it in Debian based systems: 49 +### 2) If you are using Varnish
55 50
56 - $ sudo apt-get install pound 51 +Varnish isn't able to communicate with the SSL protocol, so we will need some
  52 +one else who do this and [Pound](http://www.apsis.ch/pound) can do the job. In
  53 +order to install it in Debian based systems:
57 54
58 -Set Varnish to listen in other port than 80: 55 +```
  56 +$ sudo apt-get install pound
  57 +```
59 58
60 -/etc/defaults/varnish  
61 ---------------------- 59 +Set Varnish to listen in other port than 80 in `/etc/defaults/varnish`:
62 60
63 - DAEMON_OPTS="-a localhost:6081 \  
64 - -T localhost:6082 \  
65 - -f /etc/varnish/default.vcl \  
66 - -S /etc/varnish/secret \  
67 - -s file,/var/lib/varnish/$INSTANCE/varnish_storage.bin,1G" 61 +```
  62 +DAEMON_OPTS="-a localhost:6081 \
  63 + -T localhost:6082 \
  64 + -f /etc/varnish/default.vcl \
  65 + -S /etc/varnish/secret \
  66 + -s file,/var/lib/varnish/$INSTANCE/varnish_storage.bin,1G"
  67 +```
68 68
69 Configure Pound: 69 Configure Pound:
70 70
71 - # cp /usr/share/noosfero/etc/pound.cfg /etc/pound/  
72 -  
73 -Edit /etc/pound.cfg and set the IP and domain of your server. 71 +```
  72 +# cp /usr/share/noosfero/etc/pound.cfg /etc/pound/
  73 +```
74 74
75 -Configure Pound to start at system initialization: 75 +Edit `/etc/pound.cfg` and set the IP and domain of your server.
76 76
77 -/etc/default/pound 77 +Configure Pound to start at system initialization. At `/etc/default/pound`:
78 ------------------ 78 ------------------
79 79
80 - startup=1 80 +```
  81 +startup=1
  82 +```
81 83
82 -Set Apache to only listen to localhost: 84 +Set Apache to only listen to localhost, at `/etc/apache2/ports.conf`:
83 85
84 -/etc/apache2/ports.conf  
85 ------------------------  
86 -  
87 - Listen 127.0.0.1:8080 86 +```
  87 +Listen 127.0.0.1:8080
  88 +```
88 89
89 Restart the services: 90 Restart the services:
90 91
91 - $ sudo service apache2 restart  
92 - $ sudo service varnish restart 92 +```
  93 +$ sudo service apache2 restart
  94 +$ sudo service varnish restart
  95 +```
93 96
94 Start pound: 97 Start pound:
95 98
96 - $ sudo service pound start  
97 -  
98 -[1] http://www.apsis.ch/pound 99 +```
  100 +$ sudo service pound start
  101 +```
99 102
100 -Noosfero XMPP chat  
101 -++++++++++++++++++ 103 +## Noosfero XMPP chat
102 104
103 If you want to use chat over HTTPS, then you should add the domain 105 If you want to use chat over HTTPS, then you should add the domain
104 -and IP of your server in the /etc/hosts file, example: 106 +and IP of your server in the /etc/hosts file, example
105 107
106 -/etc/hosts  
107 ----------- 108 +`/etc/hosts:`
108 109
109 - 192.168.1.86 mydomain.example.com 110 +```
  111 +192.168.1.86 mydomain.example.com
  112 +```
110 113
111 -Also, it's recomended that you remove lines above from the file 114 +Also, it's recomended that you remove the lines below from the file
112 `/etc/apache2/sites-enabled/noosfero`: 115 `/etc/apache2/sites-enabled/noosfero`:
113 116
114 - RewriteEngine On  
115 - Include /usr/share/noosfero/util/chat/apache/xmpp.conf 117 +```
  118 +RewriteEngine On
  119 +Include /usr/share/noosfero/util/chat/apache/xmpp.conf
  120 +```
INSTALL.locales.md 0 → 100644
@@ -0,0 +1,29 @@ @@ -0,0 +1,29 @@
  1 +Using custom locales
  2 +====================
  3 +
  4 +Personalized translations go into the `config/custom_locales/` directory.
  5 +Custom locales can be identified by the rails environment, schema name in a
  6 +multitenancy setup or domain name until the first dot (e.g env1.coop.br for the
  7 +example below).
  8 +
  9 +Currently, the only filename prefix for the localization file which is
  10 +processed is "environment". For instance, a POT file would be called
  11 +"environment.pot".
  12 +
  13 +The structure of an environment named env1 with custom translations for both
  14 +Portuguese and Spanish and an environment named env2 with custom Russian
  15 +translation would be:
  16 +
  17 + config/
  18 + custom_locales/
  19 + env1/
  20 + environment.pot
  21 + pt/
  22 + environment.po
  23 + es/
  24 + environment.po
  25 + env2/
  26 + environment.pot
  27 + ru/
  28 + environment.po
  29 +
@@ -186,8 +186,8 @@ Apache instalation @@ -186,8 +186,8 @@ Apache instalation
186 186
187 # apt-get install apache2 187 # apt-get install apache2
188 188
189 -Apache configuration  
190 --------------------- 189 +Configuration - noosfero at /
  190 +-----------------------------
191 191
192 First you have to enable the following some apache modules: 192 First you have to enable the following some apache modules:
193 193
@@ -257,6 +257,62 @@ Now restart your apache server (as root): @@ -257,6 +257,62 @@ Now restart your apache server (as root):
257 257
258 # invoke-rc.d apache2 restart 258 # invoke-rc.d apache2 restart
259 259
  260 +Configuration - noosfero at a /subdirectory
  261 +-------------------------------------------
  262 +
  263 +This section describes how to configure noosfero at a subdirectory, what is
  264 +specially useful when you want Noosfero to share a domain name with other
  265 +applications. For example you can host noosfero at yourdomain.com/social, a
  266 +webmail application at yourdomain.com/webmail, and have a static HTML website
  267 +at yourdomain.com/.
  268 +
  269 +**NOTE:** Some plugins might not work well with this setting. Before deploying
  270 +this setting, make sure you test that everything you need works properly with
  271 +it.
  272 +
  273 +The configuration is similar to the main configuration instructions, except for
  274 +the following points. In the description below, replace '/subdirectory' with
  275 +the actual subdirectory you want.
  276 +
  277 +1) add a `prefix: /subdirectory` line to your thin configuration file (thin.yml).
  278 +
  279 +1.1) remember to restart the noosfero application server whenever you make
  280 +changes to that configuration file.
  281 +
  282 + # service noosfero restart
  283 +
  284 +2) add a line saying `export RAILS_RELATIVE_URL_ROOT=/subdirectory` to
  285 +/etc/default/noosfero (you can create it with just this line if it does not
  286 +exist already).
  287 +
  288 +3) You should add the following apache configuration to an existing virtual
  289 +host (plus the `<Proxy balancer://noosfero>` section as displayed above):
  290 +
  291 +```
  292 +Alias /subdirectory /path/to/noosfero/public
  293 +<Directory "/path/to/noosfero/public">
  294 + Options FollowSymLinks
  295 + AllowOverride None
  296 + Order Allow,Deny
  297 + Allow from all
  298 +
  299 + Include /path/to/noosfero/etc/noosfero/apache/cache.conf
  300 +
  301 + RewriteEngine On
  302 + RewriteBase /subdirectory
  303 + # Rewrite index to check for static index.html
  304 + RewriteRule ^$ index.html [QSA]
  305 + # Rewrite to check for Rails cached page
  306 + RewriteRule ^([^.]+)$ $1.html [QSA]
  307 + RewriteCond %{REQUEST_FILENAME} !-f
  308 + RewriteRule ^(.*)$ http://localhost:3000%{REQUEST_URI} [P,QSA,L]
  309 +</Directory>
  310 +```
  311 +
  312 +3.1) remember to reload the apache server whenever any apache configuration
  313 +file changes.
  314 +
  315 + # sudo service apache2 reload
260 316
261 Enabling exception notifications 317 Enabling exception notifications
262 ================================ 318 ================================
1 #!/usr/bin/env rake 1 #!/usr/bin/env rake
  2 +
2 # Add your own tasks in files placed in lib/tasks ending in .rake, 3 # Add your own tasks in files placed in lib/tasks ending in .rake,
3 # for example lib/tasks/capistrano.rake, and they will automatically be available to Rake. 4 # for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.
4 5
5 require File.expand_path('../config/application', __FILE__) 6 require File.expand_path('../config/application', __FILE__)
6 7
7 Noosfero::Application.load_tasks 8 Noosfero::Application.load_tasks
  9 +
  10 +[
  11 + "baseplugins/*/{tasks,lib/tasks,rails/tasks}/**/*.rake",
  12 + "config/plugins/*/{tasks,lib/tasks,rails/tasks}/**/*.rake",
  13 + "config/plugins/*/vendor/plugins/*/{tasks,lib/tasks,rails/tasks}/**/*.rake",
  14 +].map do |pattern|
  15 + Dir.glob(pattern).sort
  16 +end.flatten.each do |taskfile|
  17 + load taskfile
  18 +end
@@ -3,7 +3,7 @@ @@ -3,7 +3,7 @@
3 3
4 VAGRANTFILE_API_VERSION = "2" 4 VAGRANTFILE_API_VERSION = "2"
5 Vagrant.configure(VAGRANTFILE_API_VERSION) do |config| 5 Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
6 - config.vm.box = "debian-wheezy" 6 + config.vm.box = ENV.fetch('VAGRANT_BOX', "debian-wheezy")
7 config.vm.network :forwarded_port, host: 3000, guest: 3000 7 config.vm.network :forwarded_port, host: 3000, guest: 3000
8 config.vm.provision :shell do |shell| 8 config.vm.provision :shell do |shell|
9 shell.inline = 'su vagrant -c /vagrant/script/vagrant' 9 shell.inline = 'su vagrant -c /vagrant/script/vagrant'
app/controllers/admin/admin_panel_controller.rb
@@ -71,4 +71,22 @@ class AdminPanelController &lt; AdminController @@ -71,4 +71,22 @@ class AdminPanelController &lt; AdminController
71 end 71 end
72 end 72 end
73 end 73 end
  74 +
  75 + def manage_organizations_status
  76 + scope = environment.organizations
  77 + @filter = params[:filter] || 'any'
  78 + @title = "Organization profiles"
  79 + @title = @title+" - "+@filter if @filter != 'any'
  80 +
  81 + if @filter == 'enabled'
  82 + scope = scope.visible
  83 + elsif @filter == 'disabled'
  84 + scope = scope.disabled
  85 + end
  86 +
  87 + scope = scope.order('name ASC')
  88 +
  89 + @q = params[:q]
  90 + @collection = find_by_contents(:organizations, scope, @q, {:per_page => 10, :page => params[:npage]})[:results]
  91 + end
74 end 92 end
app/controllers/admin/categories_controller.rb
@@ -45,9 +45,11 @@ class CategoriesController &lt; AdminController @@ -45,9 +45,11 @@ class CategoriesController &lt; AdminController
45 if request.post? 45 if request.post?
46 @category.update_attributes!(params[:category]) 46 @category.update_attributes!(params[:category])
47 @saved = true 47 @saved = true
  48 + session[:notice] = _("Category %s saved." % @category.name)
48 redirect_to :action => 'index' 49 redirect_to :action => 'index'
49 end 50 end
50 rescue Exception => e 51 rescue Exception => e
  52 + session[:notice] = _('Could not save category.')
51 render :action => 'edit' 53 render :action => 'edit'
52 end 54 end
53 end 55 end
app/controllers/admin/environment_design_controller.rb
@@ -3,9 +3,7 @@ class EnvironmentDesignController &lt; BoxOrganizerController @@ -3,9 +3,7 @@ class EnvironmentDesignController &lt; BoxOrganizerController
3 protect 'edit_environment_design', :environment 3 protect 'edit_environment_design', :environment
4 4
5 def available_blocks 5 def available_blocks
6 - # TODO EnvironmentStatisticsBlock is DEPRECATED and will be removed from  
7 - # the Noosfero core soon, see ActionItem3045  
8 - @available_blocks ||= [ ArticleBlock, LoginBlock, EnvironmentStatisticsBlock, RecentDocumentsBlock, EnterprisesBlock, CommunitiesBlock, SellersSearchBlock, LinkListBlock, FeedReaderBlock, SlideshowBlock, HighlightsBlock, FeaturedProductsBlock, CategoriesBlock, RawHTMLBlock, TagsBlock ] 6 + @available_blocks ||= [ ArticleBlock, LoginBlock, RecentDocumentsBlock, EnterprisesBlock, CommunitiesBlock, SellersSearchBlock, LinkListBlock, FeedReaderBlock, SlideshowBlock, HighlightsBlock, FeaturedProductsBlock, CategoriesBlock, RawHTMLBlock, TagsBlock ]
9 @available_blocks += plugins.dispatch(:extra_blocks, :type => Environment) 7 @available_blocks += plugins.dispatch(:extra_blocks, :type => Environment)
10 end 8 end
11 9
app/controllers/admin/features_controller.rb
@@ -51,4 +51,10 @@ class FeaturesController &lt; AdminController @@ -51,4 +51,10 @@ class FeaturesController &lt; AdminController
51 redirect_to :action => 'manage_fields' 51 redirect_to :action => 'manage_fields'
52 end 52 end
53 53
  54 + def search_members
  55 + arg = params[:q].downcase
  56 + result = environment.people.find(:all, :conditions => ['LOWER(name) LIKE ? OR identifier LIKE ?', "%#{arg}%", "%#{arg}%"])
  57 + render :text => prepare_to_token_input(result).to_json
  58 + end
  59 +
54 end 60 end
app/controllers/admin/plugin_admin_controller.rb 0 → 100644
@@ -0,0 +1,5 @@ @@ -0,0 +1,5 @@
  1 +class PluginAdminController < AdminController
  2 +
  3 + protect 'edit_environment_features', :environment
  4 +
  5 +end
app/controllers/admin/templates_controller.rb
@@ -40,8 +40,67 @@ class TemplatesController &lt; AdminController @@ -40,8 +40,67 @@ class TemplatesController &lt; AdminController
40 end 40 end
41 end 41 end
42 42
  43 + def set_community_as_default
  44 + begin
  45 + community = environment.communities.find(params[:template_id])
  46 + rescue ActiveRecord::RecordNotFound
  47 + message = _('Community not found. The template could no be changed.')
  48 + community = nil
  49 + end
  50 +
  51 + message = _('%s defined as default') % community.name if set_as_default(community)
  52 + session[:notice] = message
  53 +
  54 + redirect_to :action => 'index'
  55 + end
  56 +
  57 + def set_person_as_default
  58 + begin
  59 + person = environment.people.find(params[:template_id])
  60 + rescue ActiveRecord::RecordNotFound
  61 + message = _('Person not found. The template could no be changed.')
  62 + person = nil
  63 + end
  64 +
  65 + message = _('%s defined as default') % person.name if set_as_default(person)
  66 + session[:notice] = message
  67 +
  68 + redirect_to :action => 'index'
  69 + end
  70 +
  71 + def set_enterprise_as_default
  72 + begin
  73 + enterprise = environment.enterprises.find(params[:template_id])
  74 + rescue ActiveRecord::RecordNotFound
  75 + message = _('Enterprise not found. The template could no be changed.')
  76 + enterprise = nil
  77 + end
  78 +
  79 + message = _('%s defined as default') % enterprise.name if set_as_default(enterprise)
  80 + session[:notice] = message
  81 +
  82 + redirect_to :action => 'index'
  83 + end
  84 +
43 private 85 private
44 86
  87 + def set_as_default(obj)
  88 + return nil if obj.nil?
  89 + case obj.class.name
  90 + when 'Community' then
  91 + environment.community_default_template = obj
  92 + environment.save!
  93 + when 'Person' then
  94 + environment.person_default_template = obj
  95 + environment.save!
  96 + when 'Enterprise' then
  97 + environment.enterprise_default_template = obj
  98 + environment.save!
  99 + else
  100 + nil
  101 + end
  102 + end
  103 +
45 def create_organization_template(klass) 104 def create_organization_template(klass)
46 identifier = params[:name].to_slug 105 identifier = params[:name].to_slug
47 template = klass.new(:name => params[:name], :identifier => identifier, :is_template => true) 106 template = klass.new(:name => params[:name], :identifier => identifier, :is_template => true)
app/controllers/application_controller.rb
@@ -7,6 +7,12 @@ class ApplicationController &lt; ActionController::Base @@ -7,6 +7,12 @@ class ApplicationController &lt; ActionController::Base
7 before_filter :detect_stuff_by_domain 7 before_filter :detect_stuff_by_domain
8 before_filter :init_noosfero_plugins 8 before_filter :init_noosfero_plugins
9 before_filter :allow_cross_domain_access 9 before_filter :allow_cross_domain_access
  10 + before_filter :login_required, :if => :private_environment?
  11 + before_filter :verify_members_whitelist, :if => [:private_environment?, :user]
  12 +
  13 + def verify_members_whitelist
  14 + render_access_denied unless user.is_admin? || environment.in_whitelist?(user)
  15 + end
10 16
11 after_filter :set_csrf_cookie 17 after_filter :set_csrf_cookie
12 18
@@ -34,7 +40,7 @@ class ApplicationController &lt; ActionController::Base @@ -34,7 +40,7 @@ class ApplicationController &lt; ActionController::Base
34 40
35 theme_layout = theme_option(:layout) 41 theme_layout = theme_option(:layout)
36 if theme_layout 42 if theme_layout
37 - theme_view_file('layouts/'+theme_layout) || theme_layout 43 + (theme_view_file('layouts/'+theme_layout) || theme_layout).to_s
38 else 44 else
39 'application' 45 'application'
40 end 46 end
@@ -121,6 +127,9 @@ class ApplicationController &lt; ActionController::Base @@ -121,6 +127,9 @@ class ApplicationController &lt; ActionController::Base
121 127
122 # TODO: move this logic somewhere else (Domain class?) 128 # TODO: move this logic somewhere else (Domain class?)
123 def detect_stuff_by_domain 129 def detect_stuff_by_domain
  130 + # Sets text domain based on request host for custom internationalization
  131 + FastGettext.text_domain = Domain.custom_locale(request.host)
  132 +
124 @domain = Domain.find_by_name(request.host) 133 @domain = Domain.find_by_name(request.host)
125 if @domain.nil? 134 if @domain.nil?
126 @environment = Environment.default 135 @environment = Environment.default
@@ -187,4 +196,8 @@ class ApplicationController &lt; ActionController::Base @@ -187,4 +196,8 @@ class ApplicationController &lt; ActionController::Base
187 {:results => scope.paginate(paginate_options)} 196 {:results => scope.paginate(paginate_options)}
188 end 197 end
189 198
  199 + def private_environment?
  200 + @environment.enabled?(:restrict_to_members)
  201 + end
  202 +
190 end 203 end
app/controllers/my_profile/cms_controller.rb
@@ -4,6 +4,12 @@ class CmsController &lt; MyProfileController @@ -4,6 +4,12 @@ class CmsController &lt; MyProfileController
4 4
5 include ArticleHelper 5 include ArticleHelper
6 6
  7 + def search_tags
  8 + arg = params[:term].downcase
  9 + result = ActsAsTaggableOn::Tag.find(:all, :conditions => ['LOWER(name) LIKE ?', "%#{arg}%"])
  10 + render :text => prepare_to_token_input_by_label(result).to_json, :content_type => 'application/json'
  11 + end
  12 +
7 def self.protect_if(*args) 13 def self.protect_if(*args)
8 before_filter(*args) do |c| 14 before_filter(*args) do |c|
9 user, profile = c.send(:user), c.send(:profile) 15 user, profile = c.send(:user), c.send(:profile)
@@ -143,6 +149,7 @@ class CmsController &lt; MyProfileController @@ -143,6 +149,7 @@ class CmsController &lt; MyProfileController
143 end 149 end
144 150
145 @article.profile = profile 151 @article.profile = profile
  152 + @article.author = user
146 @article.last_changed_by = user 153 @article.last_changed_by = user
147 @article.created_by = user 154 @article.created_by = user
148 155
@@ -167,6 +174,8 @@ class CmsController &lt; MyProfileController @@ -167,6 +174,8 @@ class CmsController &lt; MyProfileController
167 174
168 post_only :set_home_page 175 post_only :set_home_page
169 def set_home_page 176 def set_home_page
  177 + return render_access_denied unless user.can_change_homepage?
  178 +
170 article = params[:id].nil? ? nil : profile.articles.find(params[:id]) 179 article = params[:id].nil? ? nil : profile.articles.find(params[:id])
171 profile.update_attribute(:home_page, article) 180 profile.update_attribute(:home_page, article)
172 181
@@ -195,7 +204,7 @@ class CmsController &lt; MyProfileController @@ -195,7 +204,7 @@ class CmsController &lt; MyProfileController
195 :profile => profile, 204 :profile => profile,
196 :parent => @parent, 205 :parent => @parent,
197 :last_changed_by => user, 206 :last_changed_by => user,
198 - :created_by => user, 207 + :author => user,
199 }, 208 },
200 :without_protection => true 209 :without_protection => true
201 ) 210 )
@@ -205,6 +214,7 @@ class CmsController &lt; MyProfileController @@ -205,6 +214,7 @@ class CmsController &lt; MyProfileController
205 if @errors.any? 214 if @errors.any?
206 render :action => 'upload_files', :parent_id => @parent_id 215 render :action => 'upload_files', :parent_id => @parent_id
207 else 216 else
  217 + session[:notice] = _('File(s) successfully uploaded')
208 if @back_to 218 if @back_to
209 redirect_to @back_to 219 redirect_to @back_to
210 elsif @parent 220 elsif @parent
@@ -220,7 +230,7 @@ class CmsController &lt; MyProfileController @@ -220,7 +230,7 @@ class CmsController &lt; MyProfileController
220 @article = profile.articles.find(params[:id]) 230 @article = profile.articles.find(params[:id])
221 if request.post? 231 if request.post?
222 @article.destroy 232 @article.destroy
223 - session[:notice] = _("\"#{@article.name}\" was removed.") 233 + session[:notice] = _("\"%s\" was removed." % @article.name)
224 referer = Rails.application.routes.recognize_path URI.parse(request.referer).path rescue nil 234 referer = Rails.application.routes.recognize_path URI.parse(request.referer).path rescue nil
225 if referer and referer[:controller] == 'cms' and referer[:action] != 'edit' 235 if referer and referer[:controller] == 'cms' and referer[:action] != 'edit'
226 redirect_to referer 236 redirect_to referer
app/controllers/my_profile/friends_controller.rb 100644 → 100755
@@ -20,7 +20,7 @@ class FriendsController &lt; MyProfileController @@ -20,7 +20,7 @@ class FriendsController &lt; MyProfileController
20 20
21 class << self 21 class << self
22 def per_page 22 def per_page
23 - 10 23 + 12
24 end 24 end
25 end 25 end
26 def per_page 26 def per_page
app/controllers/my_profile/memberships_controller.rb
@@ -21,6 +21,9 @@ class MembershipsController &lt; MyProfileController @@ -21,6 +21,9 @@ class MembershipsController &lt; MyProfileController
21 @back_to = params[:back_to] || url_for(:action => 'index') 21 @back_to = params[:back_to] || url_for(:action => 'index')
22 if request.post? && @community.valid? 22 if request.post? && @community.valid?
23 @community = Community.create_after_moderation(user, params[:community].merge({:environment => environment})) 23 @community = Community.create_after_moderation(user, params[:community].merge({:environment => environment}))
  24 + if @community.new_record?
  25 + session[:notice] = _('Your new community creation request will be evaluated by an administrator. You will be notified.')
  26 + end
24 redirect_to @back_to 27 redirect_to @back_to
25 return 28 return
26 end 29 end
app/controllers/my_profile/profile_design_controller.rb
@@ -3,7 +3,16 @@ class ProfileDesignController &lt; BoxOrganizerController @@ -3,7 +3,16 @@ class ProfileDesignController &lt; BoxOrganizerController
3 needs_profile 3 needs_profile
4 4
5 protect 'edit_profile_design', :profile 5 protect 'edit_profile_design', :profile
6 - 6 +
  7 + before_filter :protect_fixed_block, :only => [:save, :move_block]
  8 +
  9 + def protect_fixed_block
  10 + block = boxes_holder.blocks.find(params[:id].gsub(/^block-/, ''))
  11 + if block.fixed && !current_person.is_admin?
  12 + render_access_denied
  13 + end
  14 + end
  15 +
7 def available_blocks 16 def available_blocks
8 blocks = [ ArticleBlock, TagsBlock, RecentDocumentsBlock, ProfileInfoBlock, LinkListBlock, MyNetworkBlock, FeedReaderBlock, ProfileImageBlock, LocationBlock, SlideshowBlock, ProfileSearchBlock, HighlightsBlock ] 17 blocks = [ ArticleBlock, TagsBlock, RecentDocumentsBlock, ProfileInfoBlock, LinkListBlock, MyNetworkBlock, FeedReaderBlock, ProfileImageBlock, LocationBlock, SlideshowBlock, ProfileSearchBlock, HighlightsBlock ]
9 18
app/controllers/my_profile/profile_editor_controller.rb
@@ -16,14 +16,16 @@ class ProfileEditorController &lt; MyProfileController @@ -16,14 +16,16 @@ class ProfileEditorController &lt; MyProfileController
16 if request.post? 16 if request.post?
17 params[:profile_data][:fields_privacy] ||= {} if profile.person? && params[:profile_data].is_a?(Hash) 17 params[:profile_data][:fields_privacy] ||= {} if profile.person? && params[:profile_data].is_a?(Hash)
18 Profile.transaction do 18 Profile.transaction do
19 - Image.transaction do  
20 - if @profile_data.update_attributes(params[:profile_data])  
21 - redirect_to :action => 'index', :profile => profile.identifier  
22 - else  
23 - profile.identifier = params[:profile] if profile.identifier.blank? 19 + Image.transaction do
  20 + begin
  21 + @plugins.dispatch(:profile_editor_transaction_extras)
  22 + @profile_data.update_attributes!(params[:profile_data])
  23 + redirect_to :action => 'index', :profile => profile.identifier
  24 + rescue Exception => ex
  25 + profile.identifier = params[:profile] if profile.identifier.blank?
  26 + end
24 end 27 end
25 end 28 end
26 - end  
27 end 29 end
28 end 30 end
29 31
@@ -72,10 +74,51 @@ class ProfileEditorController &lt; MyProfileController @@ -72,10 +74,51 @@ class ProfileEditorController &lt; MyProfileController
72 if request.post? 74 if request.post?
73 if @profile.destroy 75 if @profile.destroy
74 session[:notice] = _('The profile was deleted.') 76 session[:notice] = _('The profile was deleted.')
75 - redirect_to :controller => 'home' 77 + if(params[:return_to])
  78 + redirect_to params[:return_to]
  79 + else
  80 + redirect_to :controller => 'home'
  81 + end
76 else 82 else
77 session[:notice] = _('Could not delete profile') 83 session[:notice] = _('Could not delete profile')
78 end 84 end
79 end 85 end
80 end 86 end
  87 +
  88 + def deactivate_profile
  89 + if environment.admins.include?(current_person)
  90 + profile = environment.profiles.find(params[:id])
  91 + if profile.disable
  92 + profile.save
  93 + session[:notice] = _("The profile '#{profile.name}' was deactivated.")
  94 + else
  95 + session[:notice] = _('Could not deactivate profile.')
  96 + end
  97 + end
  98 +
  99 + redirect_to_previous_location
  100 + end
  101 +
  102 + def activate_profile
  103 + if environment.admins.include?(current_person)
  104 + profile = environment.profiles.find(params[:id])
  105 +
  106 + if profile.enable
  107 + session[:notice] = _("The profile '#{profile.name}' was activated.")
  108 + else
  109 + session[:notice] = _('Could not activate the profile.')
  110 + end
  111 + end
  112 +
  113 + redirect_to_previous_location
  114 + end
  115 +
  116 + protected
  117 +
  118 + def redirect_to_previous_location
  119 + back = request.referer
  120 + back = "/" if back.nil?
  121 +
  122 + redirect_to back
  123 + end
81 end 124 end
app/controllers/my_profile/profile_members_controller.rb
@@ -20,7 +20,7 @@ class ProfileMembersController &lt; MyProfileController @@ -20,7 +20,7 @@ class ProfileMembersController &lt; MyProfileController
20 redirect_to :action => :last_admin 20 redirect_to :action => :last_admin
21 elsif @person.define_roles(@roles, profile) 21 elsif @person.define_roles(@roles, profile)
22 session[:notice] = _('Roles successfuly updated') 22 session[:notice] = _('Roles successfuly updated')
23 - redirect_to :controller => 'profile_editor' 23 + redirect_to :action => 'index'
24 else 24 else
25 session[:notice] = _('Couldn\'t change the roles') 25 session[:notice] = _('Couldn\'t change the roles')
26 redirect_to :action => 'index' 26 redirect_to :action => 'index'
app/controllers/my_profile/tasks_controller.rb
@@ -4,6 +4,7 @@ class TasksController &lt; MyProfileController @@ -4,6 +4,7 @@ class TasksController &lt; MyProfileController
4 4
5 def index 5 def index
6 @filter = params[:filter_type].blank? ? nil : params[:filter_type] 6 @filter = params[:filter_type].blank? ? nil : params[:filter_type]
  7 + @task_types = Task.pending_types_for(profile)
7 @tasks = Task.to(profile).without_spam.pending.of(@filter).order_by('created_at', 'asc').paginate(:per_page => Task.per_page, :page => params[:page]) 8 @tasks = Task.to(profile).without_spam.pending.of(@filter).order_by('created_at', 'asc').paginate(:per_page => Task.per_page, :page => params[:page])
8 @failed = params ? params[:failed] : {} 9 @failed = params ? params[:failed] : {}
9 end 10 end
app/controllers/public/account_controller.rb
@@ -2,7 +2,7 @@ class AccountController &lt; ApplicationController @@ -2,7 +2,7 @@ class AccountController &lt; ApplicationController
2 2
3 no_design_blocks 3 no_design_blocks
4 4
5 - before_filter :login_required, :only => [:activation_question, :accept_terms, :activate_enterprise] 5 + before_filter :login_required, :only => [:activation_question, :accept_terms, :activate_enterprise, :change_password]
6 before_filter :redirect_if_logged_in, :only => [:login, :signup] 6 before_filter :redirect_if_logged_in, :only => [:login, :signup]
7 before_filter :protect_from_bots, :only => :signup 7 before_filter :protect_from_bots, :only => :signup
8 8
@@ -15,11 +15,23 @@ class AccountController &lt; ApplicationController @@ -15,11 +15,23 @@ class AccountController &lt; ApplicationController
15 15
16 def activate 16 def activate
17 @user = User.find_by_activation_code(params[:activation_code]) if params[:activation_code] 17 @user = User.find_by_activation_code(params[:activation_code]) if params[:activation_code]
18 - if @user and @user.activate  
19 - @message = _("Your account has been activated, now you can log in!")  
20 - check_redirection  
21 - session[:join] = params[:join] unless params[:join].blank?  
22 - render :action => 'login', :userlogin => @user.login 18 + if @user
  19 + unless @user.environment.enabled?('admin_must_approve_new_users')
  20 + if @user.activate
  21 + @message = _("Your account has been activated, now you can log in!")
  22 + check_redirection
  23 + session[:join] = params[:join] unless params[:join].blank?
  24 + render :action => 'login', :userlogin => @user.login
  25 + end
  26 + else
  27 + if @user.create_moderate_task
  28 + session[:notice] = _('Thanks for registering. The administrators were notified.')
  29 + @register_pending = true
  30 + @user.activation_code = nil
  31 + @user.save!
  32 + redirect_to :controller => :home
  33 + end
  34 + end
23 else 35 else
24 session[:notice] = _("It looks like you're trying to activate an account. Perhaps have already activated this account?") 36 session[:notice] = _("It looks like you're trying to activate an account. Perhaps have already activated this account?")
25 redirect_to :controller => :home 37 redirect_to :controller => :home
@@ -85,6 +97,7 @@ class AccountController &lt; ApplicationController @@ -85,6 +97,7 @@ class AccountController &lt; ApplicationController
85 @user.return_to = session[:return_to] 97 @user.return_to = session[:return_to]
86 @person = Person.new(params[:profile_data]) 98 @person = Person.new(params[:profile_data])
87 @person.environment = @user.environment 99 @person.environment = @user.environment
  100 +
88 if request.post? 101 if request.post?
89 if may_be_a_bot 102 if may_be_a_bot
90 set_signup_start_time_for_now 103 set_signup_start_time_for_now
@@ -103,11 +116,20 @@ class AccountController &lt; ApplicationController @@ -103,11 +116,20 @@ class AccountController &lt; ApplicationController
103 invitation.update_attributes!({:friend => @user.person}) 116 invitation.update_attributes!({:friend => @user.person})
104 invitation.finish 117 invitation.finish
105 end 118 end
  119 +
  120 + unless params[:file].nil?
  121 + image = Image::new :uploaded_data=> params[:file][:image]
  122 +
  123 + @user.person.image = image
  124 + @user.person.save
  125 + end
  126 +
106 if @user.activated? 127 if @user.activated?
107 self.current_user = @user 128 self.current_user = @user
108 check_join_in_community(@user) 129 check_join_in_community(@user)
109 go_to_signup_initial_page 130 go_to_signup_initial_page
110 else 131 else
  132 + session[:notice] = _('Thanks for registering!')
111 @register_pending = true 133 @register_pending = true
112 end 134 end
113 end 135 end
@@ -171,7 +193,7 @@ class AccountController &lt; ApplicationController @@ -171,7 +193,7 @@ class AccountController &lt; ApplicationController
171 else 193 else
172 @change_password.errors[:base] << _('Could not find any user with %s equal to "%s".') % [fields_label, params[:value]] 194 @change_password.errors[:base] << _('Could not find any user with %s equal to "%s".') % [fields_label, params[:value]]
173 end 195 end
174 - rescue ActiveRecord::RecordInvald 196 + rescue ActiveRecord::RecordInvalid
175 @change_password.errors[:base] << _('Could not perform password recovery for the user.') 197 @change_password.errors[:base] << _('Could not perform password recovery for the user.')
176 end 198 end
177 end 199 end
app/controllers/public/catalog_controller.rb
@@ -11,7 +11,7 @@ class CatalogController &lt; PublicController @@ -11,7 +11,7 @@ class CatalogController &lt; PublicController
11 protected 11 protected
12 12
13 def check_enterprise_and_environment 13 def check_enterprise_and_environment
14 - unless profile.kind_of?(Enterprise) && @profile.environment.enabled?('products_for_enterprises') 14 + unless profile.enterprise? && @profile.environment.enabled?('products_for_enterprises')
15 redirect_to :controller => 'profile', :profile => profile.identifier, :action => 'index' 15 redirect_to :controller => 'profile', :profile => profile.identifier, :action => 'index'
16 end 16 end
17 end 17 end
app/controllers/public/chat_controller.rb
@@ -19,9 +19,13 @@ class ChatController &lt; PublicController @@ -19,9 +19,13 @@ class ChatController &lt; PublicController
19 def avatar 19 def avatar
20 profile = environment.profiles.find_by_identifier(params[:id]) 20 profile = environment.profiles.find_by_identifier(params[:id])
21 filename, mimetype = profile_icon(profile, :minor, true) 21 filename, mimetype = profile_icon(profile, :minor, true)
22 - data = File.read(File.join(Rails.root, 'public', filename))  
23 - render :text => data, :layout => false, :content_type => mimetype  
24 - expires_in 24.hours 22 + if filename =~ /^(https?:)?\/\//
  23 + redirect_to filename
  24 + else
  25 + data = File.read(File.join(Rails.root, 'public', filename))
  26 + render :text => data, :layout => false, :content_type => mimetype
  27 + expires_in 24.hours
  28 + end
25 end 29 end
26 30
27 def index 31 def index
app/controllers/public/contact_controller.rb
1 class ContactController < PublicController 1 class ContactController < PublicController
2 2
3 - before_filter :login_required  
4 -  
5 needs_profile 3 needs_profile
6 4
7 def new 5 def new
8 - @contact 6 + @contact = build_contact
9 if request.post? && params[:confirm] == 'true' 7 if request.post? && params[:confirm] == 'true'
10 - @contact = user.build_contact(profile, params[:contact])  
11 @contact.city = (!params[:city].blank? && City.exists?(params[:city])) ? City.find(params[:city]).name : nil 8 @contact.city = (!params[:city].blank? && City.exists?(params[:city])) ? City.find(params[:city]).name : nil
12 @contact.state = (!params[:state].blank? && State.exists?(params[:state])) ? State.find(params[:state]).name : nil 9 @contact.state = (!params[:state].blank? && State.exists?(params[:state])) ? State.find(params[:state]).name : nil
13 if @contact.deliver 10 if @contact.deliver
@@ -16,8 +13,17 @@ class ContactController &lt; PublicController @@ -16,8 +13,17 @@ class ContactController &lt; PublicController
16 else 13 else
17 session[:notice] = _('Contact not sent') 14 session[:notice] = _('Contact not sent')
18 end 15 end
  16 + end
  17 + end
  18 +
  19 + protected
  20 +
  21 + def build_contact
  22 + params[:contact] ||= {}
  23 + if logged_in?
  24 + user.build_contact profile, params[:contact]
19 else 25 else
20 - @contact = user.build_contact(profile) 26 + Contact.new params[:contact].merge(dest: profile)
21 end 27 end
22 end 28 end
23 29
app/controllers/public/content_viewer_controller.rb
@@ -74,7 +74,7 @@ class ContentViewerController &lt; ApplicationController @@ -74,7 +74,7 @@ class ContentViewerController &lt; ApplicationController
74 end 74 end
75 75
76 def versions_diff 76 def versions_diff
77 - path = params[:page].join('/') 77 + path = params[:page]
78 @page = profile.articles.find_by_path(path) 78 @page = profile.articles.find_by_path(path)
79 @v1, @v2 = @page.versions.find_by_version(params[:v1]), @page.versions.find_by_version(params[:v2]) 79 @v1, @v2 = @page.versions.find_by_version(params[:v1]), @page.versions.find_by_version(params[:v2])
80 end 80 end
@@ -126,7 +126,7 @@ class ContentViewerController &lt; ApplicationController @@ -126,7 +126,7 @@ class ContentViewerController &lt; ApplicationController
126 elsif !@page.display_to?(user) 126 elsif !@page.display_to?(user)
127 if !profile.public? 127 if !profile.public?
128 private_profile_partial_parameters 128 private_profile_partial_parameters
129 - render :template => 'profile/_private_profile', :status => 403 129 + render :template => 'profile/_private_profile', :status => 403, :formats => [:html]
130 allowed = false 130 allowed = false
131 else #if !profile.visible? 131 else #if !profile.visible?
132 render_access_denied 132 render_access_denied
app/controllers/public/profile_controller.rb
@@ -17,7 +17,11 @@ class ProfileController &lt; PublicController @@ -17,7 +17,11 @@ class ProfileController &lt; PublicController
17 end 17 end
18 @tags = profile.article_tags 18 @tags = profile.article_tags
19 unless profile.display_info_to?(user) 19 unless profile.display_info_to?(user)
20 - profile.visible? ? private_profile : invisible_profile 20 + if profile.visible?
  21 + private_profile
  22 + else
  23 + invisible_profile
  24 + end
21 end 25 end
22 end 26 end
23 27
@@ -61,13 +65,13 @@ class ProfileController &lt; PublicController @@ -61,13 +65,13 @@ class ProfileController &lt; PublicController
61 65
62 def friends 66 def friends
63 if is_cache_expired?(profile.friends_cache_key(params)) 67 if is_cache_expired?(profile.friends_cache_key(params))
64 - @friends = profile.friends.includes(relations_to_include).paginate(:per_page => per_page, :page => params[:npage]) 68 + @friends = profile.friends.includes(relations_to_include).paginate(:per_page => per_page, :page => params[:npage], :total_entries => profile.friends.count)
65 end 69 end
66 end 70 end
67 71
68 def members 72 def members
69 if is_cache_expired?(profile.members_cache_key(params)) 73 if is_cache_expired?(profile.members_cache_key(params))
70 - @members = profile.members_by_name.includes(relations_to_include).paginate(:per_page => members_per_page, :page => params[:npage]) 74 + @members = profile.members_by_name.includes(relations_to_include).paginate(:per_page => members_per_page, :page => params[:npage], :total_entries => profile.members.count)
71 end 75 end
72 end 76 end
73 77
@@ -315,7 +319,7 @@ class ProfileController &lt; PublicController @@ -315,7 +319,7 @@ class ProfileController &lt; PublicController
315 abuse_report = AbuseReport.new(params[:abuse_report]) 319 abuse_report = AbuseReport.new(params[:abuse_report])
316 if !params[:content_type].blank? 320 if !params[:content_type].blank?
317 article = params[:content_type].constantize.find(params[:content_id]) 321 article = params[:content_type].constantize.find(params[:content_id])
318 - abuse_report.content = instance_eval(&article.reported_version) 322 + abuse_report.content = article_reported_version(article)
319 end 323 end
320 324
321 user.register_report(abuse_report, profile) 325 user.register_report(abuse_report, profile)
@@ -394,6 +398,7 @@ class ProfileController &lt; PublicController @@ -394,6 +398,7 @@ class ProfileController &lt; PublicController
394 398
395 def private_profile 399 def private_profile
396 private_profile_partial_parameters 400 private_profile_partial_parameters
  401 + render :action => 'index', :status => 403
397 end 402 end
398 403
399 def invisible_profile 404 def invisible_profile
app/controllers/public/search_controller.rb
@@ -90,10 +90,14 @@ class SearchController &lt; PublicController @@ -90,10 +90,14 @@ class SearchController &lt; PublicController
90 end 90 end
91 91
92 def events 92 def events
93 - year = (params[:year] ? params[:year].to_i : Date.today.year)  
94 - month = (params[:month] ? params[:month].to_i : Date.today.month)  
95 - day = (params[:day] ? params[:day].to_i : Date.today.day)  
96 - @date = build_date(year, month, day) 93 + if params[:year].blank? && params[:year].blank? && params[:day].blank?
  94 + @date = Date.today
  95 + else
  96 + year = (params[:year] ? params[:year].to_i : Date.today.year)
  97 + month = (params[:month] ? params[:month].to_i : Date.today.month)
  98 + day = (params[:day] ? params[:day].to_i : 1)
  99 + @date = build_date(year, month, day)
  100 + end
97 date_range = (@date - 1.month).at_beginning_of_month..(@date + 1.month).at_end_of_month 101 date_range = (@date - 1.month).at_beginning_of_month..(@date + 1.month).at_end_of_month
98 102
99 @events = [] 103 @events = []
app/helpers/application_helper.rb
@@ -304,7 +304,7 @@ module ApplicationHelper @@ -304,7 +304,7 @@ module ApplicationHelper
304 def partial_for_class(klass, prefix=nil, suffix=nil) 304 def partial_for_class(klass, prefix=nil, suffix=nil)
305 raise ArgumentError, 'No partial for object. Is there a partial for any class in the inheritance hierarchy?' if klass.nil? 305 raise ArgumentError, 'No partial for object. Is there a partial for any class in the inheritance hierarchy?' if klass.nil?
306 name = klass.name.underscore 306 name = klass.name.underscore
307 - controller.view_paths.reverse_each do |view_path| 307 + controller.view_paths.each do |view_path|
308 partial = partial_for_class_in_view_path(klass, view_path, prefix, suffix) 308 partial = partial_for_class_in_view_path(klass, view_path, prefix, suffix)
309 return partial if partial 309 return partial if partial
310 end 310 end
@@ -312,13 +312,13 @@ module ApplicationHelper @@ -312,13 +312,13 @@ module ApplicationHelper
312 raise ArgumentError, 'No partial for object. Is there a partial for any class in the inheritance hierarchy?' 312 raise ArgumentError, 'No partial for object. Is there a partial for any class in the inheritance hierarchy?'
313 end 313 end
314 314
315 - def view_for_profile_actions(klass)  
316 - raise ArgumentError, 'No profile actions view for this class.' if klass.nil?  
317 -  
318 - name = klass.name.underscore  
319 - return "blocks/profile_info_actions/" + name + '.html.erb' if File.exists?(Rails.root.join('app', 'views', 'blocks', 'profile_info_actions', name + '.html.erb'))  
320 -  
321 - view_for_profile_actions(klass.superclass) 315 + def render_profile_actions klass
  316 + name = klass.to_s.underscore
  317 + begin
  318 + render "blocks/profile_info_actions/#{name}"
  319 + rescue ActionView::MissingTemplate
  320 + render_profile_actions klass.superclass
  321 + end
322 end 322 end
323 323
324 def user 324 def user
@@ -433,19 +433,19 @@ module ApplicationHelper @@ -433,19 +433,19 @@ module ApplicationHelper
433 end 433 end
434 434
435 def theme_site_title 435 def theme_site_title
436 - theme_include('site_title') 436 + @theme_site_title ||= theme_include 'site_title'
437 end 437 end
438 438
439 def theme_header 439 def theme_header
440 - theme_include('header') 440 + @theme_header ||= theme_include 'header'
441 end 441 end
442 442
443 def theme_footer 443 def theme_footer
444 - theme_include('footer') 444 + @theme_footer ||= theme_include 'footer'
445 end 445 end
446 446
447 def theme_extra_navigation 447 def theme_extra_navigation
448 - theme_include('navigation') 448 + @theme_extra_navigation ||= theme_include 'navigation'
449 end 449 end
450 450
451 def is_testing_theme 451 def is_testing_theme
@@ -482,7 +482,12 @@ module ApplicationHelper @@ -482,7 +482,12 @@ module ApplicationHelper
482 '/images/icons-app/enterprise-'+ size.to_s() +'.png' 482 '/images/icons-app/enterprise-'+ size.to_s() +'.png'
483 end 483 end
484 else 484 else
485 - '/images/icons-app/person-'+ size.to_s() +'.png' 485 + pixels = Image.attachment_options[:thumbnails][size].split('x').first
  486 + gravatar_profile_image_url(
  487 + profile.email,
  488 + :size => pixels,
  489 + :d => gravatar_default
  490 + )
486 end 491 end
487 filename = default_or_themed_icon(icon) 492 filename = default_or_themed_icon(icon)
488 end 493 end
@@ -602,7 +607,7 @@ module ApplicationHelper @@ -602,7 +607,7 @@ module ApplicationHelper
602 end 607 end
603 608
604 def gravatar_default 609 def gravatar_default
605 - (respond_to?(:theme_option) && theme_option.present? && theme_option['gravatar']) || NOOSFERO_CONF['gravatar'] 610 + (respond_to?(:theme_option) && theme_option.present? && theme_option['gravatar']) || NOOSFERO_CONF['gravatar'] || 'mm'
606 end 611 end
607 612
608 attr_reader :environment 613 attr_reader :environment
@@ -669,13 +674,14 @@ module ApplicationHelper @@ -669,13 +674,14 @@ module ApplicationHelper
669 html.join "\n" 674 html.join "\n"
670 end 675 end
671 676
  677 + def theme_javascript_src
  678 + script = File.join theme_path, 'theme.js'
  679 + script if File.exists? File.join(Rails.root, 'public', script)
  680 + end
  681 +
672 def theme_javascript_ng 682 def theme_javascript_ng
673 - script = File.join(theme_path, 'theme.js')  
674 - if File.exists?(File.join(Rails.root, 'public', script))  
675 - javascript_include_tag script  
676 - else  
677 - nil  
678 - end 683 + script = theme_javascript_src
  684 + javascript_include_tag script if script
679 end 685 end
680 686
681 def file_field_or_thumbnail(label, image, i) 687 def file_field_or_thumbnail(label, image, i)
@@ -856,8 +862,9 @@ module ApplicationHelper @@ -856,8 +862,9 @@ module ApplicationHelper
856 end 862 end
857 863
858 def base_url 864 def base_url
859 - environment.top_url 865 + environment.top_url(request.scheme)
860 end 866 end
  867 + alias :top_url :base_url
861 868
862 def helper_for_article(article) 869 def helper_for_article(article)
863 article_helper = ActionView::Base.new 870 article_helper = ActionView::Base.new
@@ -902,13 +909,15 @@ module ApplicationHelper @@ -902,13 +909,15 @@ module ApplicationHelper
902 end 909 end
903 910
904 def page_title 911 def page_title
905 - (@page ? @page.title + ' - ' : '') +  
906 - (@topic ? @topic.title + ' - ' : '') +  
907 - (@section ? @section.title + ' - ' : '') +  
908 - (@toc ? _('Online Manual') + ' - ' : '') +  
909 - (controller.controller_name == 'chat' ? _('Chat') + ' - ' : '') +  
910 - (profile ? profile.short_name : environment.name) +  
911 - (@category ? " - #{@category.full_name}" : '') 912 + CGI.escapeHTML(
  913 + (@page ? @page.title + ' - ' : '') +
  914 + (@topic ? @topic.title + ' - ' : '') +
  915 + (@section ? @section.title + ' - ' : '') +
  916 + (@toc ? _('Online Manual') + ' - ' : '') +
  917 + (controller.controller_name == 'chat' ? _('Chat') + ' - ' : '') +
  918 + (profile ? profile.short_name : environment.name) +
  919 + (@category ? " - #{@category.full_name}" : '')
  920 + )
912 end 921 end
913 922
914 # DEPRECATED. Do not use this. 923 # DEPRECATED. Do not use this.
@@ -937,9 +946,9 @@ module ApplicationHelper @@ -937,9 +946,9 @@ module ApplicationHelper
937 # from Article model for an ArticleBlock. 946 # from Article model for an ArticleBlock.
938 def reference_to_article(text, article, anchor=nil) 947 def reference_to_article(text, article, anchor=nil)
939 if article.profile.domains.empty? 948 if article.profile.domains.empty?
940 - href = "/#{article.url[:profile]}/" 949 + href = "#{Noosfero.root}/#{article.url[:profile]}/"
941 else 950 else
942 - href = "http://#{article.profile.domains.first.name}/" 951 + href = "http://#{article.profile.domains.first.name}#{Noosfero.root}/"
943 end 952 end
944 href += article.url[:page].join('/') 953 href += article.url[:page].join('/')
945 href += '#' + anchor if anchor 954 href += '#' + anchor if anchor
@@ -1095,7 +1104,7 @@ module ApplicationHelper @@ -1095,7 +1104,7 @@ module ApplicationHelper
1095 result 1104 result
1096 end 1105 end
1097 1106
1098 - def manage_link(list, kind) 1107 + def manage_link(list, kind, title)
1099 if list.present? 1108 if list.present?
1100 link_to_all = nil 1109 link_to_all = nil
1101 if list.count > 5 1110 if list.count > 5
@@ -1108,19 +1117,19 @@ module ApplicationHelper @@ -1108,19 +1117,19 @@ module ApplicationHelper
1108 if link_to_all 1117 if link_to_all
1109 link << link_to_all 1118 link << link_to_all
1110 end 1119 end
1111 - render :partial => "shared/manage_link", :locals => {:link => link, :kind => kind.to_s} 1120 + render :partial => "shared/manage_link", :locals => {:link => link, :kind => kind.to_s, :title => title}
1112 end 1121 end
1113 end 1122 end
1114 1123
1115 def manage_enterprises 1124 def manage_enterprises
1116 return '' unless user && user.environment.enabled?(:display_my_enterprises_on_user_menu) 1125 return '' unless user && user.environment.enabled?(:display_my_enterprises_on_user_menu)
1117 - manage_link(user.enterprises, :enterprises).to_s 1126 + manage_link(user.enterprises, :enterprises, _('My enterprises')).to_s
1118 end 1127 end
1119 1128
1120 def manage_communities 1129 def manage_communities
1121 return '' unless user && user.environment.enabled?(:display_my_communities_on_user_menu) 1130 return '' unless user && user.environment.enabled?(:display_my_communities_on_user_menu)
1122 administered_communities = user.communities.more_popular.select {|c| c.admins.include? user} 1131 administered_communities = user.communities.more_popular.select {|c| c.admins.include? user}
1123 - manage_link(administered_communities, :communities).to_s 1132 + manage_link(administered_communities, :communities, _('My communities')).to_s
1124 end 1133 end
1125 1134
1126 def admin_link 1135 def admin_link
@@ -1225,20 +1234,7 @@ module ApplicationHelper @@ -1225,20 +1234,7 @@ module ApplicationHelper
1225 def add_zoom_to_images 1234 def add_zoom_to_images
1226 stylesheet_link_tag('jquery.fancybox') + 1235 stylesheet_link_tag('jquery.fancybox') +
1227 javascript_include_tag('jquery.fancybox.pack') + 1236 javascript_include_tag('jquery.fancybox.pack') +
1228 - javascript_tag("jQuery(function($) {  
1229 - $(window).load( function() {  
1230 - $('#article .article-body img').each( function(index) {  
1231 - var original = original_image_dimensions($(this).attr('src'));  
1232 - if ($(this).width() < original['width'] || $(this).height() < original['height']) {  
1233 - $(this).wrap('<div class=\"zoomable-image\" />');  
1234 - $(this).parent('.zoomable-image').attr('style', $(this).attr('style'));  
1235 - $(this).attr('style', '');  
1236 - $(this).after(\'<a href=\"' + $(this).attr('src') + '\" class=\"zoomify-image\"><span class=\"zoomify-text\">%s</span></a>');  
1237 - }  
1238 - });  
1239 - $('.zoomify-image').fancybox();  
1240 - });  
1241 - });" % _('Zoom in')) 1237 + javascript_tag("apply_zoom_to_images(#{_('Zoom in').to_json})")
1242 end 1238 end
1243 1239
1244 def render_dialog_error_messages(instance_name) 1240 def render_dialog_error_messages(instance_name)
@@ -1293,11 +1289,13 @@ module ApplicationHelper @@ -1293,11 +1289,13 @@ module ApplicationHelper
1293 end 1289 end
1294 1290
1295 def delete_article_message(article) 1291 def delete_article_message(article)
1296 - if article.folder?  
1297 - _("Are you sure that you want to remove the folder \"#{article.name}\"? Note that all the items inside it will also be removed!")  
1298 - else  
1299 - _("Are you sure that you want to remove the item \"#{article.name}\"?")  
1300 - end 1292 + CGI.escapeHTML(
  1293 + if article.folder?
  1294 + _("Are you sure that you want to remove the folder \"%s\"? Note that all the items inside it will also be removed!") % article.name
  1295 + else
  1296 + _("Are you sure that you want to remove the item \"%s\"?") % article.name
  1297 + end
  1298 + )
1301 end 1299 end
1302 1300
1303 def expirable_link_to(expired, content, url, options = {}) 1301 def expirable_link_to(expired, content, url, options = {})
@@ -1318,10 +1316,8 @@ module ApplicationHelper @@ -1318,10 +1316,8 @@ module ApplicationHelper
1318 return '' if templates.count == 0 1316 return '' if templates.count == 0
1319 return hidden_field_tag("#{field_name}[template_id]", templates.first.id) if templates.count == 1 1317 return hidden_field_tag("#{field_name}[template_id]", templates.first.id) if templates.count == 1
1320 1318
1321 - counter = 0  
1322 radios = templates.map do |template| 1319 radios = templates.map do |template|
1323 - counter += 1  
1324 - content_tag('li', labelled_radio_button(link_to(template.name, template.url, :target => '_blank'), "#{field_name}[template_id]", template.id, counter==1)) 1320 + content_tag('li', labelled_radio_button(link_to(template.name, template.url, :target => '_blank'), "#{field_name}[template_id]", template.id, environment.is_default_template?(template)))
1325 end.join("\n") 1321 end.join("\n")
1326 1322
1327 content_tag('div', content_tag('label', _('Profile organization'), :for => 'template-options', :class => 'formlabel') + 1323 content_tag('div', content_tag('label', _('Profile organization'), :for => 'template-options', :class => 'formlabel') +
@@ -1373,7 +1369,7 @@ module ApplicationHelper @@ -1373,7 +1369,7 @@ module ApplicationHelper
1373 @message = _("The content here is available to %s's friends only.") % profile.short_name 1369 @message = _("The content here is available to %s's friends only.") % profile.short_name
1374 else 1370 else
1375 @action = :join 1371 @action = :join
1376 - @message = _('The contents in this community is available to members only.') 1372 + @message = _('The contents in this profile is available to members only.')
1377 end 1373 end
1378 @no_design_blocks = true 1374 @no_design_blocks = true
1379 end 1375 end
@@ -1385,7 +1381,7 @@ module ApplicationHelper @@ -1385,7 +1381,7 @@ module ApplicationHelper
1385 # are old things that do not support it we are keeping this hot spot. 1381 # are old things that do not support it we are keeping this hot spot.
1386 html = @plugins.pipeline(:parse_content, html, source).first 1382 html = @plugins.pipeline(:parse_content, html, source).first
1387 end 1383 end
1388 - html 1384 + html && html.html_safe
1389 end 1385 end
1390 1386
1391 def convert_macro(html, source) 1387 def convert_macro(html, source)
@@ -1415,4 +1411,14 @@ module ApplicationHelper @@ -1415,4 +1411,14 @@ module ApplicationHelper
1415 content_tag('ul', article.versions.map {|v| link_to("r#{v.version}", @page.url.merge(:version => v.version))}) 1411 content_tag('ul', article.versions.map {|v| link_to("r#{v.version}", @page.url.merge(:version => v.version))})
1416 end 1412 end
1417 1413
  1414 + def labelled_colorpicker_field(human_name, object_name, method, options = {})
  1415 + options[:id] ||= 'text-field-' + FormsHelper.next_id_number
  1416 + content_tag('label', human_name, :for => options[:id], :class => 'formlabel') +
  1417 + colorpicker_field(object_name, method, options.merge(:class => 'colorpicker_field'))
  1418 + end
  1419 +
  1420 + def colorpicker_field(object_name, method, options = {})
  1421 + text_field(object_name, method, options.merge(:class => 'colorpicker_field'))
  1422 + end
  1423 +
1418 end 1424 end
app/helpers/article_helper.rb
@@ -3,6 +3,12 @@ module ArticleHelper @@ -3,6 +3,12 @@ module ArticleHelper
3 include PrototypeHelper 3 include PrototypeHelper
4 include TokenHelper 4 include TokenHelper
5 5
  6 + def article_reported_version(article)
  7 + search_path = Rails.root.join('app', 'views', 'shared', 'reported_versions')
  8 + partial_path = File.join('shared', 'reported_versions', 'profile', partial_for_class_in_view_path(article.class, search_path))
  9 + render_to_string(:partial => partial_path, :locals => {:article => article})
  10 + end
  11 +
6 def custom_options_for_article(article, tokenized_children) 12 def custom_options_for_article(article, tokenized_children)
7 @article = article 13 @article = article
8 14
@@ -71,18 +77,69 @@ module ArticleHelper @@ -71,18 +77,69 @@ module ArticleHelper
71 content_tag('div', 77 content_tag('div',
72 radio_button(:article, :published, false) + 78 radio_button(:article, :published, false) +
73 content_tag('label', _('Private'), :for => 'article_published_false', :id => "label_private") 79 content_tag('label', _('Private'), :for => 'article_published_false', :id => "label_private")
74 - ) +  
75 - (article.profile.community? ? content_tag('div',  
76 - content_tag('label', _('Fill in the search field to add the exception users to see this content'), :id => "text-input-search-exception-users") +  
77 - token_input_field_tag(:q, 'search-article-privacy-exceptions', {:action => 'search_article_privacy_exceptions'},  
78 - {:focus => false, :hint_text => _('Type in a search term for a user'), :pre_populate => tokenized_children})) :  
79 - '')) 80 + ) +
  81 + privacity_exceptions(article, tokenized_children)
  82 + )
  83 + end
  84 +
  85 + def privacity_exceptions(article, tokenized_children)
  86 + content_tag('div',
  87 + content_tag('div',
  88 + (
  89 + if article.profile
  90 + add_option_to_followers(article, tokenized_children)
  91 + else
  92 + ''
  93 + end
  94 + )
  95 + ),
  96 + :style => "margin-left:10px"
  97 + )
  98 + end
  99 +
  100 + def add_option_to_followers(article, tokenized_children)
  101 + label_message = article.profile.organization? ? _('For all community members') : _('For all your friends')
  102 +
  103 + check_box(
  104 + :article,
  105 + :show_to_followers,
  106 + {:class => "custom_privacy_option"}
  107 + ) +
  108 + content_tag(
  109 + 'label',
  110 + label_message,
  111 + :for => 'article_show_to_followers',
  112 + :id => 'label_show_to_followers'
  113 + ) +
  114 + (article.profile.community? ?
  115 + content_tag(
  116 + 'div',
  117 + content_tag(
  118 + 'label',
  119 + _('Fill in the search field to add the exception users to see this content'),
  120 + :id => "text-input-search-exception-users"
  121 + ) +
  122 + token_input_field_tag(
  123 + :q,
  124 + 'search-article-privacy-exceptions',
  125 + {:action => 'search_article_privacy_exceptions'},
  126 + {
  127 + :focus => false,
  128 + :hint_text => _('Type in a search term for a user'),
  129 + :pre_populate => tokenized_children
  130 + }
  131 + )
  132 + ) : '')
80 end 133 end
81 134
82 def prepare_to_token_input(array) 135 def prepare_to_token_input(array)
83 array.map { |object| {:id => object.id, :name => object.name} } 136 array.map { |object| {:id => object.id, :name => object.name} }
84 end 137 end
85 138
  139 + def prepare_to_token_input_by_label(array)
  140 + array.map { |object| {:label => object.name, :value => object.name} }
  141 + end
  142 +
86 def cms_label_for_new_children 143 def cms_label_for_new_children
87 _('New article') 144 _('New article')
88 end 145 end
app/helpers/block_helper.rb
@@ -6,19 +6,20 @@ module BlockHelper @@ -6,19 +6,20 @@ module BlockHelper
6 content_tag 'h3', content_tag('span', h(title)), :class => tag_class 6 content_tag 'h3', content_tag('span', h(title)), :class => tag_class
7 end 7 end
8 8
9 - def highlights_block_config_image_fields(block, image={}) 9 + def highlights_block_config_image_fields(block, image={}, row_number=nil)
10 " 10 "
11 - <tr class=\"image-data-line\"> 11 + <tr class=\"image-data-line\" data-row-number='#{row_number}'>
12 <td> 12 <td>
13 #{select_tag 'block[images][][image_id]', content_tag(:option) + option_groups_from_collection_for_select(block.folder_choices, :images, :name, :id, :name, image[:image_id].to_i).html_safe} 13 #{select_tag 'block[images][][image_id]', content_tag(:option) + option_groups_from_collection_for_select(block.folder_choices, :images, :name, :id, :name, image[:image_id].to_i).html_safe}
14 </td> 14 </td>
15 <td>#{text_field_tag 'block[images][][address]', image[:address], :class => 'highlight-address', :size => 20}</td> 15 <td>#{text_field_tag 'block[images][][address]', image[:address], :class => 'highlight-address', :size => 20}</td>
16 <td>#{text_field_tag 'block[images][][position]', image[:position], :class => 'highlight-position', :size => 1}</td> 16 <td>#{text_field_tag 'block[images][][position]', image[:position], :class => 'highlight-position', :size => 1}</td>
17 - </tr><tr class=\"image-title\"> 17 + </tr><tr class=\"image-title\" data-row-number='#{row_number}'>
18 <td colspan=\"3\"><label>#{ 18 <td colspan=\"3\"><label>#{
19 content_tag('span', _('Title')) + 19 content_tag('span', _('Title')) +
20 text_field_tag('block[images][][title]', image[:title], :class => 'highlight-title', :size => 45) 20 text_field_tag('block[images][][title]', image[:title], :class => 'highlight-title', :size => 45)
21 }</label></td> 21 }</label></td>
  22 + <td>#{link_to '', '#', :class=>'button icon-button icon-delete delete-highlight', :confirm=>_('Are you sure you want to remove this highlight')}</td>
22 </tr> 23 </tr>
23 " 24 "
24 end 25 end
app/helpers/blog_helper.rb
@@ -17,13 +17,13 @@ module BlogHelper @@ -17,13 +17,13 @@ module BlogHelper
17 _('Configure blog') 17 _('Configure blog')
18 end 18 end
19 19
20 - def list_posts(articles, format = 'full') 20 + def list_posts(articles, format = 'full', paginate = true)
21 pagination = will_paginate(articles, { 21 pagination = will_paginate(articles, {
22 :param_name => 'npage', 22 :param_name => 'npage',
23 :previous_label => _('&laquo; Newer posts'), 23 :previous_label => _('&laquo; Newer posts'),
24 :next_label => _('Older posts &raquo;'), 24 :next_label => _('Older posts &raquo;'),
25 :params => {:action=>"view_page", :page=>articles.first.parent.path.split('/'), :controller=>"content_viewer"} 25 :params => {:action=>"view_page", :page=>articles.first.parent.path.split('/'), :controller=>"content_viewer"}
26 - }) if articles.present? 26 + }) if articles.present? && paginate
27 content = [] 27 content = []
28 artic_len = articles.length 28 artic_len = articles.length
29 articles.each_with_index{ |art,i| 29 articles.each_with_index{ |art,i|
@@ -45,9 +45,9 @@ module BlogHelper @@ -45,9 +45,9 @@ module BlogHelper
45 45
46 def display_post(article, format = 'full') 46 def display_post(article, format = 'full')
47 no_comments = (format == 'full') ? false : true 47 no_comments = (format == 'full') ? false : true
  48 + title = article_title(article, :no_comments => no_comments)
48 html = send("display_#{format}_format", FilePresenter.for(article)).html_safe 49 html = send("display_#{format}_format", FilePresenter.for(article)).html_safe
49 -  
50 - article_title(article, :no_comments => no_comments) + html 50 + title + html
51 end 51 end
52 52
53 def display_full_format(article) 53 def display_full_format(article)
app/helpers/boxes_helper.rb
@@ -170,49 +170,54 @@ module BoxesHelper @@ -170,49 +170,54 @@ module BoxesHelper
170 else 170 else
171 "before-block-#{block.id}" 171 "before-block-#{block.id}"
172 end 172 end
173 -  
174 - content_tag('div', '&nbsp;', :id => id, :class => 'block-target' ) + drop_receiving_element(id, :url => { :action => 'move_block', :target => id }, :accept => box.acceptable_blocks, :hoverclass => 'block-target-hover') 173 + if block.nil? or modifiable?(block)
  174 + content_tag('div', '&nbsp;', :id => id, :class => 'block-target' ) + drop_receiving_element(id, :url => { :action => 'move_block', :target => id }, :accept => box.acceptable_blocks, :hoverclass => 'block-target-hover')
  175 + else
  176 + ""
  177 + end
175 end 178 end
176 179
177 # makes the given block draggable so it can be moved away. 180 # makes the given block draggable so it can be moved away.
178 def block_handle(block) 181 def block_handle(block)
179 - draggable_element("block-#{block.id}", :revert => true) 182 + modifiable?(block) ? draggable_element("block-#{block.id}", :revert => true) : ""
180 end 183 end
181 184
182 def block_edit_buttons(block) 185 def block_edit_buttons(block)
183 buttons = [] 186 buttons = []
184 nowhere = 'javascript: return false;' 187 nowhere = 'javascript: return false;'
185 188
186 - if block.first?  
187 - buttons << icon_button('up-disabled', _("Can't move up anymore."), nowhere)  
188 - else  
189 - buttons << icon_button('up', _('Move block up'), { :action => 'move_block_up', :id => block.id }, { :method => 'post' })  
190 - end 189 + if modifiable?(block)
  190 + if block.first?
  191 + buttons << icon_button('up-disabled', _("Can't move up anymore."), nowhere)
  192 + else
  193 + buttons << icon_button('up', _('Move block up'), { :action => 'move_block_up', :id => block.id }, { :method => 'post' })
  194 + end
191 195
192 - if block.last?  
193 - buttons << icon_button('down-disabled', _("Can't move down anymore."), nowhere)  
194 - else  
195 - buttons << icon_button(:down, _('Move block down'), { :action => 'move_block_down' ,:id => block.id }, { :method => 'post'})  
196 - end 196 + if block.last?
  197 + buttons << icon_button('down-disabled', _("Can't move down anymore."), nowhere)
  198 + else
  199 + buttons << icon_button(:down, _('Move block down'), { :action => 'move_block_down' ,:id => block.id }, { :method => 'post'})
  200 + end
197 201
198 - holder = block.owner  
199 - # move to opposite side  
200 - # FIXME too much hardcoded stuff  
201 - if holder.layout_template == 'default'  
202 - if block.box.position == 2 # area 2, left side => move to right side  
203 - buttons << icon_button('right', _('Move to the opposite side'), { :action => 'move_block', :target => 'end-of-box-' + holder.boxes[2].id.to_s, :id => block.id }, :method => 'post' )  
204 - elsif block.box.position == 3 # area 3, right side => move to left side  
205 - buttons << icon_button('left', _('Move to the opposite side'), { :action => 'move_block', :target => 'end-of-box-' + holder.boxes[1].id.to_s, :id => block.id }, :method => 'post' ) 202 + holder = block.owner
  203 + # move to opposite side
  204 + # FIXME too much hardcoded stuff
  205 + if holder.layout_template == 'default'
  206 + if block.box.position == 2 # area 2, left side => move to right side
  207 + buttons << icon_button('right', _('Move to the opposite side'), { :action => 'move_block', :target => 'end-of-box-' + holder.boxes[2].id.to_s, :id => block.id }, :method => 'post' )
  208 + elsif block.box.position == 3 # area 3, right side => move to left side
  209 + buttons << icon_button('left', _('Move to the opposite side'), { :action => 'move_block', :target => 'end-of-box-' + holder.boxes[1].id.to_s, :id => block.id }, :method => 'post' )
  210 + end
206 end 211 end
207 - end  
208 212
209 - if block.editable?  
210 - buttons << colorbox_icon_button(:edit, _('Edit'), { :action => 'edit', :id => block.id })  
211 - end 213 + if block.editable?
  214 + buttons << colorbox_icon_button(:edit, _('Edit'), { :action => 'edit', :id => block.id })
  215 + end
212 216
213 - if !block.main?  
214 - buttons << icon_button(:delete, _('Remove block'), { :action => 'remove', :id => block.id }, { :method => 'post', :confirm => _('Are you sure you want to remove this block?')})  
215 - buttons << icon_button(:clone, _('Clone'), { :action => 'clone_block', :id => block.id }, { :method => 'post' }) 217 + if !block.main?
  218 + buttons << icon_button(:delete, _('Remove block'), { :action => 'remove', :id => block.id }, { :method => 'post', :confirm => _('Are you sure you want to remove this block?')})
  219 + buttons << icon_button(:clone, _('Clone'), { :action => 'clone_block', :id => block.id }, { :method => 'post' })
  220 + end
216 end 221 end
217 222
218 if block.respond_to?(:help) 223 if block.respond_to?(:help)
@@ -248,5 +253,7 @@ module BoxesHelper @@ -248,5 +253,7 @@ module BoxesHelper
248 classes 253 classes
249 end 254 end
250 255
251 - 256 + def modifiable?(block)
  257 + return !block.fixed || environment.admins.include?(user)
  258 + end
252 end 259 end
app/helpers/categories_helper.rb
1 module CategoriesHelper 1 module CategoriesHelper
2 2
3 -  
4 - COLORS = [  
5 - [ N_('Do not display at the menu'), nil ],  
6 - [ N_('Orange'), 1],  
7 - [ N_('Green'), 2],  
8 - [ N_('Purple'), 3],  
9 - [ N_('Red'), 4],  
10 - [ N_('Dark Green'), 5],  
11 - [ N_('Blue Oil'), 6],  
12 - [ N_('Blue'), 7],  
13 - [ N_('Brown'), 8],  
14 - [ N_('Light Green'), 9],  
15 - [ N_('Light Blue'), 10],  
16 - [ N_('Dark Blue'), 11],  
17 - [ N_('Blue Pool'), 12],  
18 - [ N_('Beige'), 13],  
19 - [ N_('Yellow'), 14],  
20 - [ N_('Light Brown'), 15]  
21 - ]  
22 -  
23 TYPES = [ 3 TYPES = [
24 [ _('General Category'), Category.to_s ], 4 [ _('General Category'), Category.to_s ],
25 [ _('Product Category'), ProductCategory.to_s ], 5 [ _('Product Category'), ProductCategory.to_s ],
26 [ _('Region'), Region.to_s ], 6 [ _('Region'), Region.to_s ],
27 ] 7 ]
28 8
29 - def select_color_for_category  
30 - if @category.top_level?  
31 - labelled_form_field(_('Display at the menu?'), select('category', 'display_color', CategoriesHelper::COLORS.map {|item| [gettext(item[0]), item[1]] }))  
32 - else  
33 - ""  
34 - end  
35 - end  
36 -  
37 - def display_color_for_category(category)  
38 - color = category.display_color  
39 - if color.nil?  
40 - ""  
41 - else  
42 - "[" + gettext(CategoriesHelper::COLORS.find {|item| item[1] == color}.first) + "]"  
43 - end  
44 - end  
45 -  
46 def select_category_type(field) 9 def select_category_type(field)
47 value = params[field] 10 value = params[field]
48 labelled_form_field(_('Type of category'), select_tag('type', options_for_select(TYPES, value))) 11 labelled_form_field(_('Type of category'), select_tag('type', options_for_select(TYPES, value)))
49 end 12 end
50 13
  14 + def category_color_style(category)
  15 + return '' if category.nil? or category.display_color.blank?
  16 + 'background-color: #'+category.display_color+';'
  17 + end
  18 +
51 #FIXME make this test 19 #FIXME make this test
52 def selected_category_link(cat) 20 def selected_category_link(cat)
53 js_remove = "jQuery('#selected-category-#{cat.id}').remove();" 21 js_remove = "jQuery('#selected-category-#{cat.id}').remove();"
app/helpers/content_viewer_helper.rb
@@ -10,7 +10,7 @@ module ContentViewerHelper @@ -10,7 +10,7 @@ module ContentViewerHelper
10 end 10 end
11 11
12 def number_of_comments(article) 12 def number_of_comments(article)
13 - display_number_of_comments(article.comments.without_spam.count) 13 + display_number_of_comments(article.comments_count - article.spam_comments_count.to_i)
14 end 14 end
15 15
16 def article_title(article, args = {}) 16 def article_title(article, args = {})
@@ -26,7 +26,7 @@ module ContentViewerHelper @@ -26,7 +26,7 @@ module ContentViewerHelper
26 end 26 end
27 title << content_tag('span', 27 title << content_tag('span',
28 content_tag('span', show_date(article.published_at), :class => 'date') + 28 content_tag('span', show_date(article.published_at), :class => 'date') +
29 - content_tag('span', _(", by %s") % link_to(article.author_name, article.author_url), :class => 'author') + 29 + content_tag('span', _(", by %s") % (article.author ? link_to(article.author_name, article.author_url) : article.author_name), :class => 'author') +
30 content_tag('span', comments, :class => 'comments'), 30 content_tag('span', comments, :class => 'comments'),
31 :class => 'created-at' 31 :class => 'created-at'
32 ) 32 )
@@ -45,7 +45,7 @@ module ContentViewerHelper @@ -45,7 +45,7 @@ module ContentViewerHelper
45 { article.environment.locales[translation.language] => { :href => url_for(translation.url) } } 45 { article.environment.locales[translation.language] => { :href => url_for(translation.url) } }
46 end 46 end
47 content_tag(:div, link_to(_('Translations'), '#', 47 content_tag(:div, link_to(_('Translations'), '#',
48 - :onmouseover => "toggleSubmenu(this, '#{_('Translations')}', #{links.to_json}); return false", 48 + :onmouseover => "toggleSubmenu(this, '#{_('Translations')}', #{CGI::escape_html(links.to_json)}); return false",
49 :class => 'article-translations-menu simplemenu-trigger up'), 49 :class => 'article-translations-menu simplemenu-trigger up'),
50 :class => 'article-translations') 50 :class => 'article-translations')
51 end 51 end
app/helpers/folder_helper.rb
@@ -5,15 +5,17 @@ module FolderHelper @@ -5,15 +5,17 @@ module FolderHelper
5 include ShortFilename 5 include ShortFilename
6 include ArticleHelper 6 include ArticleHelper
7 7
8 - def list_articles(articles, recursive = false)  
9 - if !articles.blank?  
10 - articles = articles.paginate( 8 + def list_contents(configure={})
  9 + configure[:recursive] ||= false
  10 + configure[:list_type] ||= :folder
  11 + if !configure[:contents].blank?
  12 + configure[:contents] = configure[:contents].paginate(
11 :order => "updated_at DESC", 13 :order => "updated_at DESC",
12 :per_page => 10, 14 :per_page => 10,
13 :page => params[:npage] 15 :page => params[:npage]
14 ) 16 )
15 17
16 - render :file => 'shared/articles_list', :locals => {:articles => articles, :recursive => recursive} 18 + render :file => 'shared/content_list', :locals => configure
17 else 19 else
18 content_tag('em', _('(empty folder)')) 20 content_tag('em', _('(empty folder)'))
19 end 21 end
@@ -23,21 +25,33 @@ module FolderHelper @@ -23,21 +25,33 @@ module FolderHelper
23 articles.select {|article| article.display_to?(user)} 25 articles.select {|article| article.display_to?(user)}
24 end 26 end
25 27
26 - def display_article_in_listing(article, recursive = false, level = 0)  
27 - article = FilePresenter.for article  
28 - article_link = if article.image?  
29 - link_to('&nbsp;' * (level * 4) + image_tag(icon_for_article(article)) + short_filename(article.name), article.url.merge(:view => true)) 28 + def display_content_in_listing(configure={})
  29 + recursive = configure[:recursive] || false
  30 + list_type = configure[:list_type] || :folder
  31 + level = configure[:level] || 0
  32 + content = FilePresenter.for configure[:content]
  33 + content_link = if content.image?
  34 + link_to('&nbsp;' * (level * 4) +
  35 + image_tag(icon_for_article(content)) + short_filename(content.name),
  36 + content.url.merge(:view => true)
  37 + )
30 else 38 else
31 - link_to('&nbsp;' * (level * 4) + short_filename(article.name), article.url.merge(:view => true), :class => icon_for_article(article)) 39 + link_to('&nbsp;' * (level * 4) +
  40 + short_filename(content.name),
  41 + content.url.merge(:view => true), :class => icon_for_article(content)
  42 + )
32 end 43 end
33 result = content_tag( 44 result = content_tag(
34 'tr', 45 'tr',
35 - content_tag('td', article_link )+  
36 - content_tag('td', show_date(article.updated_at), :class => 'last-update'),  
37 - :class => 'sitemap-item' 46 + content_tag('td', content_link ) +
  47 + content_tag('td', show_date(content.updated_at), :class => 'last-update'),
  48 + :class => "#{list_type}-item"
38 ) 49 )
39 if recursive 50 if recursive
40 - result + article.children.map {|item| display_article_in_listing(item, recursive, level + 1) }.join('') 51 + result + content.children.map {|item|
  52 + display_content_in_listing :content=>item, :recursive=>recursive,
  53 + :list_type=>list_type, :level=>level+1
  54 + }.join("\n")
41 else 55 else
42 result 56 result
43 end 57 end
app/helpers/layout_helper.rb
@@ -2,12 +2,31 @@ module LayoutHelper @@ -2,12 +2,31 @@ module LayoutHelper
2 2
3 def body_classes 3 def body_classes
4 # Identify the current controller and action for the CSS: 4 # Identify the current controller and action for the CSS:
  5 + (logged_in? ? " logged-in" : "") +
5 " controller-#{controller.controller_name}" + 6 " controller-#{controller.controller_name}" +
6 " action-#{controller.controller_name}-#{controller.action_name}" + 7 " action-#{controller.controller_name}-#{controller.action_name}" +
7 " template-#{@layout_template || if profile.blank? then 'default' else profile.layout_template end}" + 8 " template-#{@layout_template || if profile.blank? then 'default' else profile.layout_template end}" +
8 (!profile.nil? && profile.is_on_homepage?(request.path,@page) ? " profile-homepage" : "") 9 (!profile.nil? && profile.is_on_homepage?(request.path,@page) ? " profile-homepage" : "")
9 end 10 end
10 11
  12 + def html_tag_classes
  13 + [
  14 + body_classes, (
  15 + profile.blank? ? nil : [
  16 + 'profile-type-is-' + profile.class.name.downcase,
  17 + 'profile-name-is-' + profile.identifier,
  18 + ]
  19 + ), 'theme-' + current_theme,
  20 + @plugins.dispatch(:html_tag_classes).map do |content|
  21 + if content.respond_to?(:call)
  22 + instance_exec(&content)
  23 + else
  24 + content.html_safe
  25 + end
  26 + end
  27 + ].flatten.compact.join(' ')
  28 + end
  29 +
11 def noosfero_javascript 30 def noosfero_javascript
12 plugins_javascripts = @plugins.map { |plugin| [plugin.js_files].flatten.map { |js| plugin.class.public_path(js) } }.flatten 31 plugins_javascripts = @plugins.map { |plugin| [plugin.js_files].flatten.map { |js| plugin.class.public_path(js) } }.flatten
13 32
@@ -17,6 +36,8 @@ module LayoutHelper @@ -17,6 +36,8 @@ module LayoutHelper
17 unless plugins_javascripts.empty? 36 unless plugins_javascripts.empty?
18 output += javascript_include_tag plugins_javascripts, :cache => "cache/plugins-#{Digest::MD5.hexdigest plugins_javascripts.to_s}" 37 output += javascript_include_tag plugins_javascripts, :cache => "cache/plugins-#{Digest::MD5.hexdigest plugins_javascripts.to_s}"
19 end 38 end
  39 + output += theme_javascript_ng.to_s
  40 +
20 output 41 output
21 end 42 end
22 43
@@ -27,6 +48,7 @@ module LayoutHelper @@ -27,6 +48,7 @@ module LayoutHelper
27 'thickbox', 48 'thickbox',
28 'lightbox', 49 'lightbox',
29 'colorbox', 50 'colorbox',
  51 + 'inputosaurus',
30 pngfix_stylesheet_path, 52 pngfix_stylesheet_path,
31 ] + tokeninput_stylesheets 53 ] + tokeninput_stylesheets
32 plugins_stylesheets = @plugins.select(&:stylesheet?).map { |plugin| plugin.class.public_path('style.css') } 54 plugins_stylesheets = @plugins.select(&:stylesheet?).map { |plugin| plugin.class.public_path('style.css') }
@@ -83,6 +105,10 @@ module LayoutHelper @@ -83,6 +105,10 @@ module LayoutHelper
83 theme_path + '/style.css' 105 theme_path + '/style.css'
84 end 106 end
85 107
  108 + def layout_template
  109 + if profile then profile.layout_template else environment.layout_template end
  110 + end
  111 +
86 def addthis_javascript 112 def addthis_javascript
87 if NOOSFERO_CONF['addthis_enabled'] 113 if NOOSFERO_CONF['addthis_enabled']
88 '<script src="https://s7.addthis.com/js/152/addthis_widget.js"></script>' 114 '<script src="https://s7.addthis.com/js/152/addthis_widget.js"></script>'
@@ -90,7 +116,7 @@ module LayoutHelper @@ -90,7 +116,7 @@ module LayoutHelper
90 end 116 end
91 117
92 def meta_description_tag(article=nil) 118 def meta_description_tag(article=nil)
93 - article ? truncate(strip_tags(article.body.to_s), :length => 200) : environment.name 119 + article ? CGI.escapeHTML(truncate(strip_tags(article.body.to_s), :length => 200)) : environment.name
94 end 120 end
95 end 121 end
96 122
app/helpers/person_notifier_helper.rb
@@ -1,15 +0,0 @@ @@ -1,15 +0,0 @@
1 -module PersonNotifierHelper  
2 -  
3 - include ApplicationHelper  
4 -  
5 - private  
6 -  
7 - def path_to_image(source)  
8 - top_url + source  
9 - end  
10 -  
11 - def top_url  
12 - top_url = @profile.environment ? @profile.environment.top_url : ''  
13 - end  
14 -  
15 -end  
app/helpers/profile_helper.rb
1 module ProfileHelper 1 module ProfileHelper
2 2
3 - def display_field(title, profile, field, force = false) 3 + COMMON_CATEGORIES = ActiveSupport::OrderedHash.new
  4 + COMMON_CATEGORIES[:content] = [:blogs, :image_galleries, :events, :article_tags]
  5 + COMMON_CATEGORIES[:interests] = [:interests]
  6 + COMMON_CATEGORIES[:general] = nil
  7 +
  8 + PERSON_CATEGORIES = ActiveSupport::OrderedHash.new
  9 + PERSON_CATEGORIES[:basic_information] = [:nickname, :sex, :birth_date, :location, :privacy_setting, :created_at]
  10 + PERSON_CATEGORIES[:contact] = [:contact_phone, :cell_phone, :comercial_phone, :contact_information, :email, :personal_website, :jabber_id]
  11 + PERSON_CATEGORIES[:location] = [:address, :address_reference, :zip_code, :city, :state, :district, :country, :nationality]
  12 + PERSON_CATEGORIES[:work] = [:organization, :organization_website, :professional_activity]
  13 + PERSON_CATEGORIES[:study] = [:schooling, :formation, :area_of_study]
  14 + PERSON_CATEGORIES[:network] = [:friends, :communities, :enterprises]
  15 + PERSON_CATEGORIES.merge!(COMMON_CATEGORIES)
  16 +
  17 + ORGANIZATION_CATEGORIES = ActiveSupport::OrderedHash.new
  18 + ORGANIZATION_CATEGORIES[:basic_information] = [:display_name, :created_at, :foundation_year, :type, :language, :members_count, :location, :address_reference, :historic_and_current_context, :admins]
  19 + ORGANIZATION_CATEGORIES[:contact] = [:contact_person, :contact_phone, :contact_email, :organization_website, :jabber_id]
  20 + ORGANIZATION_CATEGORIES[:economic] = [:business_name, :acronym, :economic_activity, :legal_form, :products, :activities_short_description, :management_information]
  21 + ORGANIZATION_CATEGORIES.merge!(COMMON_CATEGORIES)
  22 +
  23 + CATEGORY_MAP = ActiveSupport::OrderedHash.new
  24 + CATEGORY_MAP[:person] = PERSON_CATEGORIES
  25 + CATEGORY_MAP[:organization] = ORGANIZATION_CATEGORIES
  26 +
  27 + FORCE = {
  28 + :person => [:privacy_setting],
  29 + :organization => [:privacy_setting, :location],
  30 + }
  31 +
  32 + MULTIPLE = {
  33 + :person => [:blogs, :image_galleries, :interests],
  34 + :organization => [:blogs, :image_galleries, :interests],
  35 + }
  36 +
  37 + CUSTOM_LABELS = {
  38 + :zip_code => _('ZIP code'),
  39 + :email => _('e-Mail'),
  40 + :jabber_id => _('Jabber'),
  41 + :birth_date => _('Date of birth'),
  42 + :created_at => _('Profile created at'),
  43 + :members_count => _('Members'),
  44 + :privacy_setting => _('Privacy setting'),
  45 + :article_tags => _('Tags')
  46 + }
  47 +
  48 + EXCEPTION = {
  49 + :person => [:image, :preferred_domain, :description, :tag_list],
  50 + :organization => [:image, :preferred_domain, :description, :tag_list, :address, :zip_code, :city, :state, :country, :district]
  51 + }
  52 +
  53 + def general_fields
  54 + categorized_fields = CATEGORY_MAP[kind].values.flatten
  55 + profile.class.fields.map(&:to_sym) - categorized_fields - EXCEPTION[kind]
  56 + end
  57 +
  58 + def kind
  59 + if profile.kind_of?(Person)
  60 + :person
  61 + else
  62 + :organization
  63 + end
  64 + end
  65 +
  66 + def title(field, entry = nil)
  67 + return self.send("#{field}_custom_title", entry) if MULTIPLE[kind].include?(field) && entry.present?
  68 + CUSTOM_LABELS[field.to_sym] || _(field.to_s.humanize)
  69 + end
  70 +
  71 + def display_field(field)
  72 + force = FORCE[kind].include?(field)
  73 + multiple = MULTIPLE[kind].include?(field)
4 unless force || profile.may_display_field_to?(field, user) 74 unless force || profile.may_display_field_to?(field, user)
5 return '' 75 return ''
6 end 76 end
7 - value = profile.send(field)  
8 - if !value.blank?  
9 - if block_given?  
10 - value = yield(value)  
11 - end  
12 - content_tag('tr', content_tag('td', title, :class => 'field-name') + content_tag('td', value)) 77 + value = begin profile.send(field) rescue nil end
  78 + return '' if value.blank?
  79 + if value.kind_of?(Hash)
  80 + content = self.send("treat_#{field}", value)
  81 + content_tag('tr', content_tag('td', title(field), :class => 'field-name') + content_tag('td', content))
13 else 82 else
14 - '' 83 + entries = multiple ? value : [] << value
  84 + entries.map do |entry|
  85 + content = self.send("treat_#{field}", entry)
  86 + unless content.blank?
  87 + content_tag('tr', content_tag('td', title(field, entry), :class => 'field-name') + content_tag('td', content))
  88 + end
  89 + end.join("\n")
15 end 90 end
16 end 91 end
17 92
18 - def display_contact(profile)  
19 - fields = []  
20 - fields << display_field(_('Address:'), profile, :address).html_safe  
21 - fields << display_field(_('ZIP code:'), profile, :zip_code).html_safe  
22 - fields << display_field(_('Contact phone:'), profile, :contact_phone).html_safe  
23 - fields << display_field(_('e-Mail:'), profile, :email) { |email| link_to_email(email) }.html_safe  
24 - fields << display_field(_('Personal website:'), profile, :personal_website).html_safe  
25 - fields << display_field(_('Jabber:'), profile, :jabber_id).html_safe  
26 - if fields.reject!(&:blank?).empty?  
27 - ''  
28 - else  
29 - content_tag('tr', content_tag('th', _('Contact'), { :colspan => 2 })) + fields.join.html_safe 93 + def treat_email(email)
  94 + link_to_email(email)
  95 + end
  96 +
  97 + def treat_organization_website(url)
  98 + link_to(url, url)
  99 + end
  100 +
  101 + def treat_sex(gender)
  102 + { 'male' => _('Male'), 'female' => _('Female') }[gender]
  103 + end
  104 +
  105 + def treat_date(date)
  106 + show_date(date.to_date)
  107 + end
  108 + alias :treat_birth_date :treat_date
  109 + alias :treat_created_at :treat_date
  110 +
  111 + def treat_friends(friends)
  112 + link_to friends.count, :controller => 'profile', :action => 'friends'
  113 + end
  114 +
  115 + def treat_communities(communities)
  116 + link_to communities.count, :controller => "profile", :action => 'communities'
  117 + end
  118 +
  119 + def treat_enterprises(enterprises)
  120 + if environment.disabled?('disable_asset_enterprises')
  121 + link_to enterprises.count, :controller => "profile", :action => 'enterprises'
  122 + end
  123 + end
  124 +
  125 + def treat_members_count(count)
  126 + link_to count, :controller => 'profile', :action => 'members'
  127 + end
  128 +
  129 + def treat_products(products)
  130 + if profile.kind_of?(Enterprise) && profile.environment.enabled?('products_for_enterprises')
  131 + link_to _('Products/Services'), :controller => 'catalog', :action => 'index'
30 end 132 end
31 end 133 end
32 134
33 - def display_work_info(profile)  
34 - organization = display_field(_('Organization:'), profile, :organization)  
35 - organization_site = display_field(_('Organization website:'), profile, :organization_website) { |url| link_to(url, url) }  
36 - if organization.blank? && organization_site.blank?  
37 - '' 135 + def treat_admins(admins)
  136 + profile.admins.map { |admin| link_to(admin.short_name, admin.url)}.join(', ')
  137 + end
  138 +
  139 + def treat_blogs(blog)
  140 + link_to(n_('One post', '%{num} posts', blog.posts.published.count) % { :num => blog.posts.published.count }, blog.url)
  141 + end
  142 +
  143 + def treat_image_galleries(gallery)
  144 + link_to(n_('One picture', '%{num} pictures', gallery.images.published.count) % { :num => gallery.images.published.count }, gallery.url)
  145 + end
  146 +
  147 + def treat_events(events)
  148 + link_to events.published.count, :controller => 'events', :action => 'events'
  149 + end
  150 +
  151 + def treat_article_tags(tags)
  152 + tag_cloud @tags, :id, { :action => 'tags' }, :max_size => 18, :min_size => 10
  153 + end
  154 +
  155 + def treat_interests(interest)
  156 + link_to interest.name, :controller => 'search', :action => 'category_index', :category_path => interest.explode_path
  157 + end
  158 +
  159 + def article_custom_title(article)
  160 + article.name
  161 + end
  162 + alias :blogs_custom_title :article_custom_title
  163 + alias :image_galleries_custom_title :article_custom_title
  164 +
  165 + def interests_custom_title(interest)
  166 + ''
  167 + end
  168 +
  169 + def method_missing(method, *args, &block)
  170 + if method.to_s =~ /^treat_(.+)$/
  171 + args[0]
  172 + elsif method.to_s =~ /^display_(.+)$/ && CATEGORY_MAP[kind].has_key?($1.to_sym)
  173 + category = $1.to_sym
  174 + fields = category == :general ? general_fields : CATEGORY_MAP[kind][category]
  175 + contents = []
  176 +
  177 + fields.each do |field|
  178 + contents << display_field(field).html_safe
  179 + end
  180 +
  181 + contents = contents.delete_if(&:blank?)
  182 +
  183 + unless contents.empty?
  184 + content_tag('tr', content_tag('th', title(category), { :colspan => 2 })) + contents.join.html_safe
  185 + else
  186 + ''
  187 + end
38 else 188 else
39 - content_tag('tr', content_tag('th', _('Work'), { :colspan => 2 })) + organization + organization_site 189 + super
40 end 190 end
41 end 191 end
42 192
app/helpers/role_helper.rb
1 module RoleHelper 1 module RoleHelper
  2 +
  3 + def role_available_permissions(role)
  4 + role.kind == "Environment" ? ['Environment', 'Profile'] : [role.kind]
  5 + end
  6 +
2 end 7 end
app/helpers/search_helper.rb
@@ -21,6 +21,12 @@ module SearchHelper @@ -21,6 +21,12 @@ module SearchHelper
21 'more_comments' => _('More comments') 21 'more_comments' => _('More comments')
22 } 22 }
23 23
  24 + COMMON_PROFILE_LIST_BLOCK = [
  25 + :enterprises,
  26 + :people,
  27 + :communities
  28 + ]
  29 +
24 # FIXME remove it after search_controler refactored 30 # FIXME remove it after search_controler refactored
25 include EventsHelper 31 include EventsHelper
26 32
@@ -94,7 +100,7 @@ module SearchHelper @@ -94,7 +100,7 @@ module SearchHelper
94 compact_link = display?(asset, :compact) ? (display == 'compact' ? _('Compact') : link_to(_('Compact'), params.merge(:display => 'compact'))) : nil 100 compact_link = display?(asset, :compact) ? (display == 'compact' ? _('Compact') : link_to(_('Compact'), params.merge(:display => 'compact'))) : nil
95 map_link = display?(asset, :map) ? (display == 'map' ? _('Map') : link_to(_('Map'), params.merge(:display => 'map'))) : nil 101 map_link = display?(asset, :map) ? (display == 'map' ? _('Map') : link_to(_('Map'), params.merge(:display => 'map'))) : nil
96 full_link = display?(asset, :full) ? (display == 'full' ? _('Full') : link_to(_('Full'), params.merge(:display => 'full'))) : nil 102 full_link = display?(asset, :full) ? (display == 'full' ? _('Full') : link_to(_('Full'), params.merge(:display => 'full'))) : nil
97 - content_tag('div', 103 + content_tag('div',
98 content_tag('strong', _('Display')) + ': ' + [compact_link, map_link, full_link].compact.join(' | ').html_safe, 104 content_tag('strong', _('Display')) + ': ' + [compact_link, map_link, full_link].compact.join(' | ').html_safe,
99 :class => 'search-customize-options' 105 :class => 'search-customize-options'
100 ) 106 )
app/helpers/sweeper_helper.rb
@@ -56,12 +56,12 @@ module SweeperHelper @@ -56,12 +56,12 @@ module SweeperHelper
56 if profile 56 if profile
57 profile.blocks.each {|block| 57 profile.blocks.each {|block|
58 conditions = block.class.expire_on 58 conditions = block.class.expire_on
59 - blocks_to_expire << block unless (conditions[:profile] & causes).empty? 59 + blocks_to_expire << block unless (conditions[:profile] & causes).blank?
60 } 60 }
61 end 61 end
62 environment.blocks.each {|block| 62 environment.blocks.each {|block|
63 conditions = block.class.expire_on 63 conditions = block.class.expire_on
64 - blocks_to_expire << block unless (conditions[:environment] & causes).empty? 64 + blocks_to_expire << block unless (conditions[:environment] & causes).blank?
65 } 65 }
66 66
67 blocks_to_expire.uniq! 67 blocks_to_expire.uniq!
app/helpers/tinymce_helper.rb 0 → 100644
@@ -0,0 +1,51 @@ @@ -0,0 +1,51 @@
  1 +module TinymceHelper
  2 + include MacrosHelper
  3 +
  4 + def tinymce_js
  5 + output = ''
  6 + output += javascript_include_tag 'tinymce/js/tinymce/tinymce.min.js'
  7 + output += javascript_include_tag 'tinymce/js/tinymce/jquery.tinymce.min.js'
  8 + output += javascript_include_tag 'tinymce.js'
  9 + output += include_macro_js_files.to_s
  10 + output
  11 + end
  12 +
  13 + def tinymce_init_js options = {}
  14 + options.merge! :document_base_url => top_url,
  15 + :content_css => "/stylesheets/tinymce.css,#{macro_css_files}",
  16 + :plugins => %w[compat3x advlist autolink lists link image charmap print preview hr anchor pagebreak
  17 + searchreplace wordcount visualblocks visualchars code fullscreen
  18 + insertdatetime media nonbreaking save table contextmenu directionality
  19 + emoticons template paste textcolor colorpicker textpattern],
  20 + :language => tinymce_language
  21 +
  22 + options[:toolbar1] = "insertfile undo redo | copy paste | bold italic underline | styleselect fontsizeselect | forecolor backcolor | alignleft aligncenter alignright alignjustify | bullist numlist outdent indent | link image"
  23 + if options[:mode] == 'simple'
  24 + options[:menubar] = false
  25 + else
  26 + options[:menubar] = 'edit insert view tools'
  27 + options[:toolbar2] = 'print preview code media | table'
  28 +
  29 + options[:toolbar2] += ' | macros'
  30 + macros_with_buttons.each do |macro|
  31 + options[:toolbar2] += " #{macro.identifier}"
  32 + end
  33 + end
  34 +
  35 + options[:macros_setup] = macros_with_buttons.map do |macro|
  36 + <<-EOS
  37 + ed.addButton('#{macro.identifier}', {
  38 + title: #{macro_title(macro).to_json},
  39 + onclick: #{generate_macro_config_dialog macro},
  40 + image : '#{macro.configuration[:icon_path]}'
  41 + });
  42 + EOS
  43 + end
  44 +
  45 + #cleanup non tinymce options
  46 + options = options.except :mode
  47 +
  48 + "noosfero.tinymce.init(#{options.to_json})"
  49 + end
  50 +
  51 +end
app/helpers/token_helper.rb
@@ -18,6 +18,7 @@ module TokenHelper @@ -18,6 +18,7 @@ module TokenHelper
18 options[:on_add] ||= 'null' 18 options[:on_add] ||= 'null'
19 options[:on_delete] ||= 'null' 19 options[:on_delete] ||= 'null'
20 options[:on_ready] ||= 'null' 20 options[:on_ready] ||= 'null'
  21 + options[:query_param] ||= 'q'
21 22
22 result = text_field_tag(name, nil, text_field_options.merge(html_options.merge({:id => element_id}))) 23 result = text_field_tag(name, nil, text_field_options.merge(html_options.merge({:id => element_id})))
23 result += javascript_tag("jQuery('##{element_id}') 24 result += javascript_tag("jQuery('##{element_id}')
@@ -30,7 +31,7 @@ module TokenHelper @@ -30,7 +31,7 @@ module TokenHelper
30 searchDelay: #{options[:search_delay].to_json}, 31 searchDelay: #{options[:search_delay].to_json},
31 preventDuplicates: #{options[:prevent_duplicates].to_json}, 32 preventDuplicates: #{options[:prevent_duplicates].to_json},
32 backspaceDeleteItem: #{options[:backspace_delete_item].to_json}, 33 backspaceDeleteItem: #{options[:backspace_delete_item].to_json},
33 - queryParam: #{name.to_json}, 34 + queryParam: #{options[:query_param].to_json},
34 tokenLimit: #{options[:token_limit].to_json}, 35 tokenLimit: #{options[:token_limit].to_json},
35 onResult: #{options[:on_result]}, 36 onResult: #{options[:on_result]},
36 onAdd: #{options[:on_add]}, 37 onAdd: #{options[:on_add]},
@@ -48,4 +49,4 @@ module TokenHelper @@ -48,4 +49,4 @@ module TokenHelper
48 result 49 result
49 end 50 end
50 51
51 -end  
52 \ No newline at end of file 52 \ No newline at end of file
  53 +end
app/models/article.rb
@@ -2,7 +2,14 @@ require &#39;hpricot&#39; @@ -2,7 +2,14 @@ require &#39;hpricot&#39;
2 2
3 class Article < ActiveRecord::Base 3 class Article < ActiveRecord::Base
4 4
5 - attr_accessible :name, :body, :abstract, :profile, :tag_list, :parent, :allow_members_to_edit, :translation_of_id, :language, :license_id, :parent_id, :display_posts_in_current_language, :category_ids, :posts_per_page, :moderate_comments, :accept_comments, :feed, :published, :source, :highlighted, :notify_comments, :display_hits, :slug, :external_feed_builder, :display_versions, :external_link, :image_builder 5 + attr_accessible :name, :body, :abstract, :profile, :tag_list, :parent,
  6 + :allow_members_to_edit, :translation_of_id, :language,
  7 + :license_id, :parent_id, :display_posts_in_current_language,
  8 + :category_ids, :posts_per_page, :moderate_comments,
  9 + :accept_comments, :feed, :published, :source,
  10 + :highlighted, :notify_comments, :display_hits, :slug,
  11 + :external_feed_builder, :display_versions, :external_link,
  12 + :image_builder, :show_to_followers
6 13
7 acts_as_having_image 14 acts_as_having_image
8 15
@@ -40,6 +47,12 @@ class Article &lt; ActiveRecord::Base @@ -40,6 +47,12 @@ class Article &lt; ActiveRecord::Base
40 # xss_terminate plugin can't sanitize array fields 47 # xss_terminate plugin can't sanitize array fields
41 before_save :sanitize_tag_list 48 before_save :sanitize_tag_list
42 49
  50 + before_create do |article|
  51 + if article.author
  52 + article.author_name = article.author.name
  53 + end
  54 + end
  55 +
43 belongs_to :profile 56 belongs_to :profile
44 validates_presence_of :profile_id, :name 57 validates_presence_of :profile_id, :name
45 validates_presence_of :slug, :path, :if => lambda { |article| !article.name.blank? } 58 validates_presence_of :slug, :path, :if => lambda { |article| !article.name.blank? }
@@ -48,6 +61,7 @@ class Article &lt; ActiveRecord::Base @@ -48,6 +61,7 @@ class Article &lt; ActiveRecord::Base
48 61
49 validates_uniqueness_of :slug, :scope => ['profile_id', 'parent_id'], :message => N_('The title (article name) is already being used by another article, please use another title.'), :if => lambda { |article| !article.slug.blank? } 62 validates_uniqueness_of :slug, :scope => ['profile_id', 'parent_id'], :message => N_('The title (article name) is already being used by another article, please use another title.'), :if => lambda { |article| !article.slug.blank? }
50 63
  64 + belongs_to :author, :class_name => 'Person'
51 belongs_to :last_changed_by, :class_name => 'Person', :foreign_key => 'last_changed_by_id' 65 belongs_to :last_changed_by, :class_name => 'Person', :foreign_key => 'last_changed_by_id'
52 belongs_to :created_by, :class_name => 'Person', :foreign_key => 'created_by_id' 66 belongs_to :created_by, :class_name => 'Person', :foreign_key => 'created_by_id'
53 67
@@ -155,14 +169,17 @@ class Article &lt; ActiveRecord::Base @@ -155,14 +169,17 @@ class Article &lt; ActiveRecord::Base
155 self.profile 169 self.profile
156 end 170 end
157 171
158 - def self.human_attribute_name(attrib, options = {}) 172 + def self.human_attribute_name_with_customization(attrib, options={})
159 case attrib.to_sym 173 case attrib.to_sym
160 when :name 174 when :name
161 _('Title') 175 _('Title')
162 else 176 else
163 - _(self.superclass.human_attribute_name(attrib)) 177 + _(self.human_attribute_name_without_customization(attrib))
164 end 178 end
165 end 179 end
  180 + class << self
  181 + alias_method_chain :human_attribute_name, :customization
  182 + end
166 183
167 def css_class_list 184 def css_class_list
168 [self.class.name.to_css_class] 185 [self.class.name.to_css_class]
@@ -280,13 +297,6 @@ class Article &lt; ActiveRecord::Base @@ -280,13 +297,6 @@ class Article &lt; ActiveRecord::Base
280 end 297 end
281 end 298 end
282 299
283 - def reported_version(options = {})  
284 - article = self  
285 - search_path = Rails.root.join('app', 'views', 'shared', 'reported_versions')  
286 - partial_path = File.join('shared', 'reported_versions', partial_for_class_in_view_path(article.class, search_path))  
287 - lambda { render_to_string(:partial => partial_path, :locals => {:article => article}) }  
288 - end  
289 -  
290 # returns the data of the article. Must be overriden in each subclass to 300 # returns the data of the article. Must be overriden in each subclass to
291 # provide the correct content for the article. 301 # provide the correct content for the article.
292 def data 302 def data
@@ -335,7 +345,7 @@ class Article &lt; ActiveRecord::Base @@ -335,7 +345,7 @@ class Article &lt; ActiveRecord::Base
335 def belongs_to_blog? 345 def belongs_to_blog?
336 self.parent and self.parent.blog? 346 self.parent and self.parent.blog?
337 end 347 end
338 - 348 +
339 def belongs_to_forum? 349 def belongs_to_forum?
340 self.parent and self.parent.forum? 350 self.parent and self.parent.forum?
341 end 351 end
@@ -447,6 +457,7 @@ class Article &lt; ActiveRecord::Base @@ -447,6 +457,7 @@ class Article &lt; ActiveRecord::Base
447 if self.parent && !self.parent.published? 457 if self.parent && !self.parent.published?
448 return false 458 return false
449 end 459 end
  460 +
450 true 461 true
451 else 462 else
452 false 463 false
@@ -461,10 +472,10 @@ class Article &lt; ActiveRecord::Base @@ -461,10 +472,10 @@ class Article &lt; ActiveRecord::Base
461 ['TextArticle', 'TextileArticle', 'TinyMceArticle'] 472 ['TextArticle', 'TextileArticle', 'TinyMceArticle']
462 end 473 end
463 474
464 - scope :published, :conditions => { :published => true }  
465 - scope :folders, lambda {|profile|{:conditions => { :type => profile.folder_types} }}  
466 - scope :no_folders, lambda {|profile|{:conditions => ['type NOT IN (?)', profile.folder_types]}}  
467 - scope :galleries, :conditions => { :type => 'Gallery' } 475 + scope :published, :conditions => ['articles.published = ?', true]
  476 + scope :folders, lambda {|profile|{:conditions => ['articles.type IN (?)', profile.folder_types] }}
  477 + scope :no_folders, lambda {|profile|{:conditions => ['articles.type NOT IN (?)', profile.folder_types]}}
  478 + scope :galleries, :conditions => [ "articles.type IN ('Gallery')" ]
468 scope :images, :conditions => { :is_image => true } 479 scope :images, :conditions => { :is_image => true }
469 scope :text_articles, :conditions => [ 'articles.type IN (?)', text_article_types ] 480 scope :text_articles, :conditions => [ 'articles.type IN (?)', text_article_types ]
470 scope :with_types, lambda { |types| { :conditions => [ 'articles.type IN (?)', types ] } } 481 scope :with_types, lambda { |types| { :conditions => [ 'articles.type IN (?)', types ] } }
@@ -474,18 +485,21 @@ class Article &lt; ActiveRecord::Base @@ -474,18 +485,21 @@ class Article &lt; ActiveRecord::Base
474 scope :more_recent, :order => "created_at DESC" 485 scope :more_recent, :order => "created_at DESC"
475 486
476 def self.display_filter(user, profile) 487 def self.display_filter(user, profile)
477 - return {:conditions => ['published = ?', true]} if !user 488 + return {:conditions => ['articles.published = ?', true]} if !user
478 {:conditions => [" articles.published = ? OR 489 {:conditions => [" articles.published = ? OR
479 articles.last_changed_by_id = ? OR 490 articles.last_changed_by_id = ? OR
480 articles.profile_id = ? OR 491 articles.profile_id = ? OR
481 - ?",  
482 - true, user.id, user.id, user.has_permission?(:view_private_content, profile)] } 492 + ? OR articles.show_to_followers = ? AND ?",
  493 + true, user.id, user.id, user.has_permission?(:view_private_content, profile),
  494 + true, user.follows?(profile)]}
483 end 495 end
484 496
  497 +
485 def display_unpublished_article_to?(user) 498 def display_unpublished_article_to?(user)
486 user == author || allow_view_private_content?(user) || user == profile || 499 user == author || allow_view_private_content?(user) || user == profile ||
487 user.is_admin?(profile.environment) || user.is_admin?(profile) || 500 user.is_admin?(profile.environment) || user.is_admin?(profile) ||
488 - article_privacy_exceptions.include?(user) 501 + article_privacy_exceptions.include?(user) ||
  502 + (self.show_to_followers && user.follows?(profile))
489 end 503 end
490 504
491 def display_to?(user = nil) 505 def display_to?(user = nil)
@@ -501,6 +515,7 @@ class Article &lt; ActiveRecord::Base @@ -501,6 +515,7 @@ class Article &lt; ActiveRecord::Base
501 end 515 end
502 516
503 def allow_post_content?(user = nil) 517 def allow_post_content?(user = nil)
  518 + return true if allow_edit_topic?(user)
504 user && (user.has_permission?('post_content', profile) || allow_publish_content?(user) && (user == author)) 519 user && (user.has_permission?('post_content', profile) || allow_publish_content?(user) && (user == author))
505 end 520 end
506 521
@@ -520,9 +535,14 @@ class Article &lt; ActiveRecord::Base @@ -520,9 +535,14 @@ class Article &lt; ActiveRecord::Base
520 end 535 end
521 536
522 def allow_edit?(user) 537 def allow_edit?(user)
  538 + return true if allow_edit_topic?(user)
523 allow_post_content?(user) || user && allow_members_to_edit && user.is_member_of?(profile) 539 allow_post_content?(user) || user && allow_members_to_edit && user.is_member_of?(profile)
524 end 540 end
525 541
  542 + def allow_edit_topic?(user)
  543 + self.belongs_to_forum? && (user == author) && user.present? && user.is_member_of?(profile)
  544 + end
  545 +
526 def moderate_comments? 546 def moderate_comments?
527 moderate_comments == true 547 moderate_comments == true
528 end 548 end
@@ -637,35 +657,36 @@ class Article &lt; ActiveRecord::Base @@ -637,35 +657,36 @@ class Article &lt; ActiveRecord::Base
637 can_display_versions? && display_versions 657 can_display_versions? && display_versions
638 end 658 end
639 659
640 - def author(version_number = nil)  
641 - if version_number  
642 - version = self.versions.find_by_version(version_number)  
643 - author_id = version.last_changed_by_id if version  
644 - else  
645 - author_id = self.created_by_id  
646 - end 660 + def get_version(version_number = nil)
  661 + version_number ? versions.find(:first, :order => 'version', :offset => version_number - 1) : versions.earliest
  662 + end
647 663
648 - environment.people.find_by_id(author_id) 664 + def author_by_version(version_number = nil)
  665 + version_number ? profile.environment.people.find_by_id(get_version(version_number).author_id) : author
649 end 666 end
650 667
651 def author_name(version_number = nil) 668 def author_name(version_number = nil)
652 - person = author(version_number)  
653 - person ? person.name : (setting[:author_name] || _('Unknown')) 669 + person = author_by_version(version_number)
  670 + if version_number
  671 + person ? person.name : _('Unknown')
  672 + else
  673 + person ? person.name : (setting[:author_name] || _('Unknown'))
  674 + end
654 end 675 end
655 676
656 def author_url(version_number = nil) 677 def author_url(version_number = nil)
657 - person = author(version_number) 678 + person = author_by_version(version_number)
658 person ? person.url : nil 679 person ? person.url : nil
659 end 680 end
660 681
661 def author_id(version_number = nil) 682 def author_id(version_number = nil)
662 - person = author(version_number) 683 + person = author_by_version(version_number)
663 person ? person.id : nil 684 person ? person.id : nil
664 end 685 end
665 686
666 def version_license(version_number = nil) 687 def version_license(version_number = nil)
667 return license if version_number.nil? 688 return license if version_number.nil?
668 - profile.environment.licenses.find_by_id(versions.find_by_version(version_number).license_id) 689 + profile.environment.licenses.find_by_id(get_version(version_number).license_id)
669 end 690 end
670 691
671 alias :active_record_cache_key :cache_key 692 alias :active_record_cache_key :cache_key
app/models/block.rb
1 class Block < ActiveRecord::Base 1 class Block < ActiveRecord::Base
2 2
3 - attr_accessible :title, :display, :limit, :box_id, :posts_per_page, :visualization_format, :language, :display_user, :box 3 + attr_accessible :title, :display, :limit, :box_id, :posts_per_page, :visualization_format, :language, :display_user, :box, :fixed
4 4
5 # to be able to generate HTML 5 # to be able to generate HTML
6 include ActionView::Helpers::UrlHelper 6 include ActionView::Helpers::UrlHelper
@@ -64,7 +64,7 @@ class Block &lt; ActiveRecord::Base @@ -64,7 +64,7 @@ class Block &lt; ActiveRecord::Base
64 end 64 end
65 65
66 def display_to_user?(user) 66 def display_to_user?(user)
67 - display_user == 'all' || (user.nil? && display_user == 'not_logged') || (user && display_user == 'logged') 67 + display_user == 'all' || (user.nil? && display_user == 'not_logged') || (user && display_user == 'logged') || (user && display_user == 'followers' && user.follows?(owner))
68 end 68 end
69 69
70 def display_always(context) 70 def display_always(context)
@@ -75,7 +75,7 @@ class Block &lt; ActiveRecord::Base @@ -75,7 +75,7 @@ class Block &lt; ActiveRecord::Base
75 if context[:article] 75 if context[:article]
76 return context[:article] == owner.home_page 76 return context[:article] == owner.home_page
77 else 77 else
78 - return context[:request_path] == '/' 78 + return home_page_path?(context[:request_path])
79 end 79 end
80 end 80 end
81 81
@@ -83,7 +83,7 @@ class Block &lt; ActiveRecord::Base @@ -83,7 +83,7 @@ class Block &lt; ActiveRecord::Base
83 if context[:article] 83 if context[:article]
84 return context[:article] != owner.home_page 84 return context[:article] != owner.home_page
85 else 85 else
86 - return context[:request_path] != '/' + (owner.kind_of?(Profile) ? owner.identifier : '') 86 + return !home_page_path?(context[:request_path])
87 end 87 end
88 end 88 end
89 89
@@ -110,11 +110,14 @@ class Block &lt; ActiveRecord::Base @@ -110,11 +110,14 @@ class Block &lt; ActiveRecord::Base
110 # * <tt>'all'</tt>: the block is always displayed 110 # * <tt>'all'</tt>: the block is always displayed
111 settings_items :language, :type => :string, :default => 'all' 111 settings_items :language, :type => :string, :default => 'all'
112 112
  113 + # The block can be configured to be fixed. Only can be edited by environment admins
  114 + settings_items :fixed, :type => :boolean, :default => false
  115 +
113 # returns the description of the block, used when the user sees a list of 116 # returns the description of the block, used when the user sees a list of
114 # blocks to choose one to include in the design. 117 # blocks to choose one to include in the design.
115 # 118 #
116 # Must be redefined in subclasses to match the description of each block 119 # Must be redefined in subclasses to match the description of each block
117 - # type. 120 + # type.
118 def self.description 121 def self.description
119 '(dummy)' 122 '(dummy)'
120 end 123 end
@@ -124,13 +127,13 @@ class Block &lt; ActiveRecord::Base @@ -124,13 +127,13 @@ class Block &lt; ActiveRecord::Base
124 # This method can return several types of objects: 127 # This method can return several types of objects:
125 # 128 #
126 # * <tt>String</tt>: if the string starts with <tt>http://</tt> or <tt>https://</tt>, then it is assumed to be address of an IFRAME. Otherwise it's is used as regular HTML. 129 # * <tt>String</tt>: if the string starts with <tt>http://</tt> or <tt>https://</tt>, then it is assumed to be address of an IFRAME. Otherwise it's is used as regular HTML.
127 - # * <tt>Hash</tt>: the hash is used to build an URL that is used as the address for a IFRAME. 130 + # * <tt>Hash</tt>: the hash is used to build an URL that is used as the address for a IFRAME.
128 # * <tt>Proc</tt>: the Proc is evaluated in the scope of BoxesHelper. The 131 # * <tt>Proc</tt>: the Proc is evaluated in the scope of BoxesHelper. The
129 # block can then use <tt>render</tt>, <tt>link_to</tt>, etc. 132 # block can then use <tt>render</tt>, <tt>link_to</tt>, etc.
130 # 133 #
131 # The method can also return <tt>nil</tt>, which means "no content". 134 # The method can also return <tt>nil</tt>, which means "no content".
132 # 135 #
133 - # See BoxesHelper#extract_block_content for implementation details. 136 + # See BoxesHelper#extract_block_content for implementation details.
134 def content(args={}) 137 def content(args={})
135 "This is block number %d" % self.id 138 "This is block number %d" % self.id
136 end 139 end
@@ -192,7 +195,7 @@ class Block &lt; ActiveRecord::Base @@ -192,7 +195,7 @@ class Block &lt; ActiveRecord::Base
192 195
193 # Override in your subclasses. 196 # Override in your subclasses.
194 # Define which events and context should cause the block cache to expire 197 # Define which events and context should cause the block cache to expire
195 - # Possible events are: :article, :profile, :friendship, :category 198 + # Possible events are: :article, :profile, :friendship, :category, :role_assignment
196 # Possible contexts are: :profile, :environment 199 # Possible contexts are: :profile, :environment
197 def self.expire_on 200 def self.expire_on
198 { 201 {
@@ -221,6 +224,7 @@ class Block &lt; ActiveRecord::Base @@ -221,6 +224,7 @@ class Block &lt; ActiveRecord::Base
221 'all' => _('All users'), 224 'all' => _('All users'),
222 'logged' => _('Logged'), 225 'logged' => _('Logged'),
223 'not_logged' => _('Not logged'), 226 'not_logged' => _('Not logged'),
  227 + 'followers' => owner.class != Environment && owner.organization? ? _('Members') : _('Friends')
224 } 228 }
225 end 229 end
226 230
@@ -234,4 +238,26 @@ class Block &lt; ActiveRecord::Base @@ -234,4 +238,26 @@ class Block &lt; ActiveRecord::Base
234 duplicated_block 238 duplicated_block
235 end 239 end
236 240
  241 + def copy_from(block)
  242 + self.settings = block.settings
  243 + self.position = block.position
  244 + end
  245 +
  246 + private
  247 +
  248 + def home_page_path
  249 + home_page_url = Noosfero.root('/')
  250 +
  251 + if owner.kind_of?(Profile)
  252 + home_page_url += "profile/" if owner.home_page.nil?
  253 + home_page_url += owner.identifier
  254 + end
  255 +
  256 + return home_page_url
  257 + end
  258 +
  259 + def home_page_path? path
  260 + return path == home_page_path || path == (home_page_path + '/')
  261 + end
  262 +
237 end 263 end
app/models/blog.rb
@@ -53,7 +53,7 @@ class Blog &lt; Folder @@ -53,7 +53,7 @@ class Blog &lt; Folder
53 def prepare_external_feed 53 def prepare_external_feed
54 unless self.external_feed_data.nil? 54 unless self.external_feed_data.nil?
55 if self.external_feed(true) && self.external_feed.id == self.external_feed_data[:id].to_i 55 if self.external_feed(true) && self.external_feed.id == self.external_feed_data[:id].to_i
56 - self.external_feed.attributes = self.external_feed_data 56 + self.external_feed.attributes = self.external_feed_data.except(:id)
57 else 57 else
58 self.build_external_feed(self.external_feed_data, :without_protection => true) 58 self.build_external_feed(self.external_feed_data, :without_protection => true)
59 end 59 end
app/models/box.rb
@@ -28,9 +28,6 @@ class Box &lt; ActiveRecord::Base @@ -28,9 +28,6 @@ class Box &lt; ActiveRecord::Base
28 CategoriesBlock, 28 CategoriesBlock,
29 CommunitiesBlock, 29 CommunitiesBlock,
30 EnterprisesBlock, 30 EnterprisesBlock,
31 - # TODO EnvironmentStatisticsBlock is DEPRECATED and will be removed from  
32 - # the Noosfero core soon, see ActionItem3045  
33 - EnvironmentStatisticsBlock,  
34 FansBlock, 31 FansBlock,
35 FavoriteEnterprisesBlock, 32 FavoriteEnterprisesBlock,
36 FeedReaderBlock, 33 FeedReaderBlock,
@@ -53,9 +50,6 @@ class Box &lt; ActiveRecord::Base @@ -53,9 +50,6 @@ class Box &lt; ActiveRecord::Base
53 CommunitiesBlock, 50 CommunitiesBlock,
54 DisabledEnterpriseMessageBlock, 51 DisabledEnterpriseMessageBlock,
55 EnterprisesBlock, 52 EnterprisesBlock,
56 - # TODO EnvironmentStatisticsBlock is DEPRECATED and will be removed from  
57 - # the Noosfero core soon, see ActionItem3045  
58 - EnvironmentStatisticsBlock,  
59 FansBlock, 53 FansBlock,
60 FavoriteEnterprisesBlock, 54 FavoriteEnterprisesBlock,
61 FeaturedProductsBlock, 55 FeaturedProductsBlock,
app/models/category.rb
@@ -14,9 +14,6 @@ class Category &lt; ActiveRecord::Base @@ -14,9 +14,6 @@ class Category &lt; ActiveRecord::Base
14 validates_uniqueness_of :slug,:scope => [ :environment_id, :parent_id ], :message => N_('{fn} is already being used by another category.').fix_i18n 14 validates_uniqueness_of :slug,:scope => [ :environment_id, :parent_id ], :message => N_('{fn} is already being used by another category.').fix_i18n
15 belongs_to :environment 15 belongs_to :environment
16 16
17 - validates_inclusion_of :display_color, :in => 1..15, :allow_nil => true  
18 - validates_uniqueness_of :display_color, :scope => :environment_id, :if => (lambda { |cat| ! cat.display_color.nil? }), :message => N_('{fn} was already assigned to another category.').fix_i18n  
19 -  
20 # Finds all top level categories for a given environment. 17 # Finds all top level categories for a given environment.
21 scope :top_level_for, lambda { |environment| 18 scope :top_level_for, lambda { |environment|
22 {:conditions => ['parent_id is null and environment_id = ?', environment.id ]} 19 {:conditions => ['parent_id is null and environment_id = ?', environment.id ]}
@@ -42,6 +39,13 @@ class Category &lt; ActiveRecord::Base @@ -42,6 +39,13 @@ class Category &lt; ActiveRecord::Base
42 39
43 acts_as_having_image 40 acts_as_having_image
44 41
  42 + before_save :normalize_display_color
  43 +
  44 + def normalize_display_color
  45 + display_color.gsub!('#', '') if display_color
  46 + display_color = nil if display_color.blank?
  47 + end
  48 +
45 scope :from_types, lambda { |types| 49 scope :from_types, lambda { |types|
46 types.select{ |t| t.blank? }.empty? ? 50 types.select{ |t| t.blank? }.empty? ?
47 { :conditions => { :type => types } } : 51 { :conditions => { :type => types } } :
@@ -101,4 +105,12 @@ class Category &lt; ActiveRecord::Base @@ -101,4 +105,12 @@ class Category &lt; ActiveRecord::Base
101 self.children.find(:all, :conditions => {:display_in_menu => true}).empty? 105 self.children.find(:all, :conditions => {:display_in_menu => true}).empty?
102 end 106 end
103 107
  108 + def with_color
  109 + if display_color.blank?
  110 + parent.nil? ? nil : parent.with_color
  111 + else
  112 + self
  113 + end
  114 + end
  115 +
104 end 116 end
app/models/change_password.rb
@@ -2,16 +2,19 @@ class ChangePassword &lt; Task @@ -2,16 +2,19 @@ class ChangePassword &lt; Task
2 2
3 attr_accessor :password, :password_confirmation 3 attr_accessor :password, :password_confirmation
4 4
5 - def self.human_attribute_name(attrib, options = {}) 5 + def self.human_attribute_name_with_customization(attrib, options={})
6 case attrib.to_sym 6 case attrib.to_sym
7 when :password 7 when :password
8 _('Password') 8 _('Password')
9 when :password_confirmation 9 when :password_confirmation
10 _('Password Confirmation') 10 _('Password Confirmation')
11 else 11 else
12 - _(self.superclass.human_attribute_name(attrib)) 12 + _(self.human_attribute_name_without_customization(attrib))
13 end 13 end
14 end 14 end
  15 + class << self
  16 + alias_method_chain :human_attribute_name, :customization
  17 + end
15 18
16 validates_presence_of :requestor 19 validates_presence_of :requestor
17 20
app/models/comment.rb
@@ -109,14 +109,17 @@ class Comment &lt; ActiveRecord::Base @@ -109,14 +109,17 @@ class Comment &lt; ActiveRecord::Base
109 include Noosfero::Plugin::HotSpot 109 include Noosfero::Plugin::HotSpot
110 110
111 include Spammable 111 include Spammable
  112 + include CacheCounterHelper
112 113
113 def after_spam! 114 def after_spam!
114 SpammerLogger.log(ip_address, self) 115 SpammerLogger.log(ip_address, self)
115 Delayed::Job.enqueue(CommentHandler.new(self.id, :marked_as_spam)) 116 Delayed::Job.enqueue(CommentHandler.new(self.id, :marked_as_spam))
  117 + update_cache_counter(:spam_comments_count, source, 1) if source.kind_of?(Article)
116 end 118 end
117 119
118 def after_ham! 120 def after_ham!
119 Delayed::Job.enqueue(CommentHandler.new(self.id, :marked_as_ham)) 121 Delayed::Job.enqueue(CommentHandler.new(self.id, :marked_as_ham))
  122 + update_cache_counter(:spam_comments_count, source, -1) if source.kind_of?(Article)
120 end 123 end
121 124
122 def verify_and_notify 125 def verify_and_notify
app/models/community.rb
@@ -50,16 +50,6 @@ class Community &lt; Organization @@ -50,16 +50,6 @@ class Community &lt; Organization
50 super + FIELDS 50 super + FIELDS
51 end 51 end
52 52
53 - validate :presence_of_required_fieds  
54 -  
55 - def presence_of_required_fieds  
56 - self.required_fields.each do |field|  
57 - if self.send(field).blank?  
58 - self.errors.add_on_blank(field)  
59 - end  
60 - end  
61 - end  
62 -  
63 def active_fields 53 def active_fields
64 environment ? environment.active_community_fields : [] 54 environment ? environment.active_community_fields : []
65 end 55 end
@@ -78,7 +68,7 @@ class Community &lt; Organization @@ -78,7 +68,7 @@ class Community &lt; Organization
78 end 68 end
79 69
80 def default_template 70 def default_template
81 - environment.community_template 71 + environment.community_default_template
82 end 72 end
83 73
84 def news(limit = 30, highlight = false) 74 def news(limit = 30, highlight = false)
app/models/domain.rb
@@ -2,7 +2,7 @@ require &#39;noosfero/multi_tenancy&#39; @@ -2,7 +2,7 @@ require &#39;noosfero/multi_tenancy&#39;
2 2
3 class Domain < ActiveRecord::Base 3 class Domain < ActiveRecord::Base
4 4
5 - attr_accessible :name, :owner 5 + attr_accessible :name, :owner, :is_default
6 6
7 # relationships 7 # relationships
8 ############### 8 ###############
@@ -92,4 +92,11 @@ class Domain &lt; ActiveRecord::Base @@ -92,4 +92,11 @@ class Domain &lt; ActiveRecord::Base
92 @hosting = {} 92 @hosting = {}
93 end 93 end
94 94
  95 + # Detects a domain's custom text domain chain if available based on a domain
  96 + # served on multitenancy configuration or a registered domain.
  97 + def self.custom_locale(domainname)
  98 + domain = Noosfero::MultiTenancy.mapping[domainname] || domainname[/(.*?)\./,1]
  99 + FastGettext.translation_repositories.keys.include?(domain) ? domain : FastGettext.default_text_domain
  100 + end
  101 +
95 end 102 end
app/models/enterprise.rb
@@ -25,7 +25,10 @@ class Enterprise &lt; Organization @@ -25,7 +25,10 @@ class Enterprise &lt; Organization
25 N_('Organization website'); N_('Historic and current context'); N_('Activities short description'); N_('City'); N_('State'); N_('Country'); N_('ZIP code') 25 N_('Organization website'); N_('Historic and current context'); N_('Activities short description'); N_('City'); N_('State'); N_('Country'); N_('ZIP code')
26 26
27 settings_items :organization_website, :historic_and_current_context, :activities_short_description 27 settings_items :organization_website, :historic_and_current_context, :activities_short_description
  28 +
28 settings_items :products_per_catalog_page, :type => :integer, :default => 6 29 settings_items :products_per_catalog_page, :type => :integer, :default => 6
  30 + alias_method :products_per_catalog_page_before_type_cast, :products_per_catalog_page
  31 + validates_numericality_of :products_per_catalog_page, :allow_nil => true, :greater_than => 0
29 32
30 extend SetProfileRegionFromCityState::ClassMethods 33 extend SetProfileRegionFromCityState::ClassMethods
31 set_profile_region_from_city_state 34 set_profile_region_from_city_state
@@ -56,16 +59,6 @@ class Enterprise &lt; Organization @@ -56,16 +59,6 @@ class Enterprise &lt; Organization
56 super + FIELDS 59 super + FIELDS
57 end 60 end
58 61
59 - validate :presence_of_required_fieds  
60 -  
61 - def presence_of_required_fieds  
62 - self.required_fields.each do |field|  
63 - if self.send(field).blank?  
64 - self.errors.add_on_blank(field)  
65 - end  
66 - end  
67 - end  
68 -  
69 def active_fields 62 def active_fields
70 environment ? environment.active_enterprise_fields : [] 63 environment ? environment.active_enterprise_fields : []
71 end 64 end
@@ -104,7 +97,12 @@ class Enterprise &lt; Organization @@ -104,7 +97,12 @@ class Enterprise &lt; Organization
104 self.tasks.where(:type => 'EnterpriseActivation').first 97 self.tasks.where(:type => 'EnterpriseActivation').first
105 end 98 end
106 99
107 - def enable(owner) 100 + def enable(owner = nil)
  101 + if owner.nil?
  102 + self.visible = true
  103 + return self.save
  104 + end
  105 +
108 return if enabled 106 return if enabled
109 # must be set first for the following to work 107 # must be set first for the following to work
110 self.enabled = true 108 self.enabled = true
@@ -166,7 +164,7 @@ class Enterprise &lt; Organization @@ -166,7 +164,7 @@ class Enterprise &lt; Organization
166 end 164 end
167 165
168 def default_template 166 def default_template
169 - environment.enterprise_template 167 + environment.enterprise_default_template
170 end 168 end
171 169
172 def template_with_inactive_enterprise 170 def template_with_inactive_enterprise
app/models/environment.rb
@@ -3,7 +3,7 @@ @@ -3,7 +3,7 @@
3 # domains. 3 # domains.
4 class Environment < ActiveRecord::Base 4 class Environment < ActiveRecord::Base
5 5
6 - attr_accessible :name, :is_default, :signup_welcome_text_subject, :signup_welcome_text_body, :terms_of_use, :message_for_disabled_enterprise, :news_amount_by_folder, :default_language, :languages, :description, :organization_approval_method, :enabled_plugins, :enabled_features, :redirection_after_login, :redirection_after_signup, :contact_email, :theme, :reports_lower_bound, :noreply_email, :signup_welcome_screen_body 6 + attr_accessible :name, :is_default, :signup_welcome_text_subject, :signup_welcome_text_body, :terms_of_use, :message_for_disabled_enterprise, :news_amount_by_folder, :default_language, :languages, :description, :organization_approval_method, :enabled_plugins, :enabled_features, :redirection_after_login, :redirection_after_signup, :contact_email, :theme, :reports_lower_bound, :noreply_email, :signup_welcome_screen_body, :members_whitelist_enabled, :members_whitelist
7 7
8 has_many :users 8 has_many :users
9 9
@@ -124,6 +124,7 @@ class Environment &lt; ActiveRecord::Base @@ -124,6 +124,7 @@ class Environment &lt; ActiveRecord::Base
124 'organizations_are_moderated_by_default' => _("Organizations have moderated publication by default"), 124 'organizations_are_moderated_by_default' => _("Organizations have moderated publication by default"),
125 'enable_organization_url_change' => _("Allow organizations to change their URL"), 125 'enable_organization_url_change' => _("Allow organizations to change their URL"),
126 'admin_must_approve_new_communities' => _("Admin must approve creation of communities"), 126 'admin_must_approve_new_communities' => _("Admin must approve creation of communities"),
  127 + 'admin_must_approve_new_users' => _("Admin must approve registration of new users"),
127 'show_balloon_with_profile_links_when_clicked' => _('Show a balloon with profile links when a profile image is clicked'), 128 'show_balloon_with_profile_links_when_clicked' => _('Show a balloon with profile links when a profile image is clicked'),
128 'xmpp_chat' => _('XMPP/Jabber based chat'), 129 'xmpp_chat' => _('XMPP/Jabber based chat'),
129 'show_zoom_button_on_article_images' => _('Show a zoom link on all article images'), 130 'show_zoom_button_on_article_images' => _('Show a zoom link on all article images'),
@@ -132,7 +133,8 @@ class Environment &lt; ActiveRecord::Base @@ -132,7 +133,8 @@ class Environment &lt; ActiveRecord::Base
132 'send_welcome_email_to_new_users' => _('Send welcome e-mail to new users'), 133 'send_welcome_email_to_new_users' => _('Send welcome e-mail to new users'),
133 'allow_change_of_redirection_after_login' => _('Allow users to set the page to redirect after login'), 134 'allow_change_of_redirection_after_login' => _('Allow users to set the page to redirect after login'),
134 'display_my_communities_on_user_menu' => _('Display on menu the list of communities the user can manage'), 135 'display_my_communities_on_user_menu' => _('Display on menu the list of communities the user can manage'),
135 - 'display_my_enterprises_on_user_menu' => _('Display on menu the list of enterprises the user can manage') 136 + 'display_my_enterprises_on_user_menu' => _('Display on menu the list of enterprises the user can manage'),
  137 + 'restrict_to_members' => _('Show content only to members')
136 } 138 }
137 end 139 end
138 140
@@ -175,9 +177,6 @@ class Environment &lt; ActiveRecord::Base @@ -175,9 +177,6 @@ class Environment &lt; ActiveRecord::Base
175 177
176 # "left" area 178 # "left" area
177 env.boxes[1].blocks << LoginBlock.new 179 env.boxes[1].blocks << LoginBlock.new
178 - # TODO EnvironmentStatisticsBlock is DEPRECATED and will be removed from  
179 - # the Noosfero core soon, see ActionItem3045  
180 - env.boxes[1].blocks << EnvironmentStatisticsBlock.new  
181 env.boxes[1].blocks << RecentDocumentsBlock.new 180 env.boxes[1].blocks << RecentDocumentsBlock.new
182 181
183 # "right" area 182 # "right" area
@@ -284,6 +283,7 @@ class Environment &lt; ActiveRecord::Base @@ -284,6 +283,7 @@ class Environment &lt; ActiveRecord::Base
284 www.flickr.com 283 www.flickr.com
285 www.gmodules.com 284 www.gmodules.com
286 www.youtube.com 285 www.youtube.com
  286 + openstreetmap.org
287 ] + ('a' .. 'z').map{|i| "#{i}.yimg.com"} 287 ] + ('a' .. 'z').map{|i| "#{i}.yimg.com"}
288 288
289 settings_items :enabled_plugins, :type => Array, :default => Noosfero::Plugin.available_plugin_names 289 settings_items :enabled_plugins, :type => Array, :default => Noosfero::Plugin.available_plugin_names
@@ -303,6 +303,17 @@ class Environment &lt; ActiveRecord::Base @@ -303,6 +303,17 @@ class Environment &lt; ActiveRecord::Base
303 settings[:signup_welcome_screen_body].present? 303 settings[:signup_welcome_screen_body].present?
304 end 304 end
305 305
  306 + settings_items :members_whitelist_enabled, :type => :boolean, :default => false
  307 + settings_items :members_whitelist, :type => Array, :default => []
  308 +
  309 + def in_whitelist?(person)
  310 + !members_whitelist_enabled || members_whitelist.include?(person.id)
  311 + end
  312 +
  313 + def members_whitelist=(members)
  314 + settings[:members_whitelist] = members.split(',').map(&:to_i)
  315 + end
  316 +
306 def news_amount_by_folder=(amount) 317 def news_amount_by_folder=(amount)
307 settings[:news_amount_by_folder] = amount.to_i 318 settings[:news_amount_by_folder] = amount.to_i
308 end 319 end
@@ -646,10 +657,11 @@ class Environment &lt; ActiveRecord::Base @@ -646,10 +657,11 @@ class Environment &lt; ActiveRecord::Base
646 { :controller => 'admin_panel', :action => 'index' } 657 { :controller => 'admin_panel', :action => 'index' }
647 end 658 end
648 659
649 - def top_url  
650 - url = 'http://' 660 + def top_url(scheme = 'http')
  661 + url = scheme + '://'
651 url << (Noosfero.url_options.key?(:host) ? Noosfero.url_options[:host] : default_hostname) 662 url << (Noosfero.url_options.key?(:host) ? Noosfero.url_options[:host] : default_hostname)
652 url << ':' << Noosfero.url_options[:port].to_s if Noosfero.url_options.key?(:port) 663 url << ':' << Noosfero.url_options[:port].to_s if Noosfero.url_options.key?(:port)
  664 + url << Noosfero.root('')
653 url 665 url
654 end 666 end
655 667
@@ -717,31 +729,50 @@ class Environment &lt; ActiveRecord::Base @@ -717,31 +729,50 @@ class Environment &lt; ActiveRecord::Base
717 ] 729 ]
718 end 730 end
719 731
720 - def community_template 732 + def is_default_template?(template)
  733 + is_default = template == community_default_template
  734 + is_default = is_default || template == person_default_template
  735 + is_default = is_default || template == enterprise_default_template
  736 + is_default
  737 + end
  738 +
  739 + def community_templates
  740 + self.communities.templates
  741 + end
  742 +
  743 + def community_default_template
721 template = Community.find_by_id settings[:community_template_id] 744 template = Community.find_by_id settings[:community_template_id]
722 - template if template && template.is_template 745 + template if template && template.is_template?
  746 + end
  747 +
  748 + def community_default_template=(value)
  749 + settings[:community_template_id] = value.kind_of?(Community) ? value.id : value
723 end 750 end
724 751
725 - def community_template=(value)  
726 - settings[:community_template_id] = value.id 752 + def person_templates
  753 + self.people.templates
727 end 754 end
728 755
729 - def person_template 756 + def person_default_template
730 template = Person.find_by_id settings[:person_template_id] 757 template = Person.find_by_id settings[:person_template_id]
731 - template if template && template.is_template 758 + template if template && template.is_template?
732 end 759 end
733 760
734 - def person_template=(value)  
735 - settings[:person_template_id] = value.id 761 + def person_default_template=(value)
  762 + settings[:person_template_id] = value.kind_of?(Person) ? value.id : value
736 end 763 end
737 764
738 - def enterprise_template 765 + def enterprise_templates
  766 + self.enterprises.templates
  767 + end
  768 +
  769 + def enterprise_default_template
739 template = Enterprise.find_by_id settings[:enterprise_template_id] 770 template = Enterprise.find_by_id settings[:enterprise_template_id]
740 - template if template && template.is_template 771 + template if template && template.is_template?
741 end 772 end
742 773
743 - def enterprise_template=(value)  
744 - settings[:enterprise_template_id] = value.id 774 + def enterprise_default_template=(value)
  775 + settings[:enterprise_template_id] = value.kind_of?(Enterprise) ? value.id : value
745 end 776 end
746 777
747 def inactive_enterprise_template 778 def inactive_enterprise_template
@@ -794,7 +825,7 @@ class Environment &lt; ActiveRecord::Base @@ -794,7 +825,7 @@ class Environment &lt; ActiveRecord::Base
794 end 825 end
795 826
796 def notification_emails 827 def notification_emails
797 - [noreply_email.blank? ? nil : noreply_email].compact + admins.map(&:email) 828 + [contact_email].select(&:present?) + admins.map(&:email)
798 end 829 end
799 830
800 after_create :create_templates 831 after_create :create_templates
@@ -839,10 +870,10 @@ class Environment &lt; ActiveRecord::Base @@ -839,10 +870,10 @@ class Environment &lt; ActiveRecord::Base
839 person_template.visible = false 870 person_template.visible = false
840 person_template.save! 871 person_template.save!
841 872
842 - self.enterprise_template = enterprise_template 873 + self.enterprise_default_template = enterprise_template
843 self.inactive_enterprise_template = inactive_enterprise_template 874 self.inactive_enterprise_template = inactive_enterprise_template
844 - self.community_template = community_template  
845 - self.person_template = person_template 875 + self.community_default_template = community_template
  876 + self.person_default_template = person_template
846 self.save! 877 self.save!
847 end 878 end
848 879
@@ -906,6 +937,10 @@ class Environment &lt; ActiveRecord::Base @@ -906,6 +937,10 @@ class Environment &lt; ActiveRecord::Base
906 locales_list 937 locales_list
907 end 938 end
908 939
  940 + def has_license?
  941 + self.licenses.any?
  942 + end
  943 +
909 private 944 private
910 945
911 def default_language_available 946 def default_language_available
app/models/environment_statistics_block.rb
@@ -1,33 +0,0 @@ @@ -1,33 +0,0 @@
1 -# TODO EnvironmentStatisticsBlock is DEPRECATED and will be removed from  
2 -# the Noosfero core soon, see ActionItem3045  
3 -  
4 -class EnvironmentStatisticsBlock < Block  
5 -  
6 - def self.description  
7 - _('Environment stastistics (DEPRECATED)')  
8 - end  
9 -  
10 - def default_title  
11 - _('Statistics for %s') % owner.name  
12 - end  
13 -  
14 - def help  
15 - _('This block presents some statistics about your environment.')  
16 - end  
17 -  
18 - def content(args={})  
19 - users = owner.people.visible.count  
20 - enterprises = owner.enterprises.visible.count  
21 - communities = owner.communities.visible.count  
22 -  
23 - info = []  
24 - info << (n_('One user', '%{num} users', users) % { :num => users })  
25 - unless owner.enabled?('disable_asset_enterprises')  
26 - info << (n_('One enterprise', '%{num} enterprises', enterprises) % { :num => enterprises })  
27 - end  
28 - info << (n_('One community', '%{num} communities', communities) % { :num => communities })  
29 -  
30 - block_title(title) + content_tag('ul', info.map {|item| content_tag('li', item) }.join("\n"))  
31 - end  
32 -  
33 -end  
app/models/event.rb
@@ -19,7 +19,7 @@ class Event &lt; Article @@ -19,7 +19,7 @@ class Event &lt; Article
19 maybe_add_http(self.setting[:link]) 19 maybe_add_http(self.setting[:link])
20 end 20 end
21 21
22 - xss_terminate :only => [ :body, :link, :address ], :with => 'white_list', :on => 'validation' 22 + xss_terminate :only => [ :name, :body, :link, :address ], :with => 'white_list', :on => 'validation'
23 23
24 def initialize(*args) 24 def initialize(*args)
25 super(*args) 25 super(*args)
app/models/external_feed.rb
@@ -10,9 +10,10 @@ class ExternalFeed &lt; ActiveRecord::Base @@ -10,9 +10,10 @@ class ExternalFeed &lt; ActiveRecord::Base
10 { :conditions => ['(fetched_at is NULL) OR (fetched_at < ?)', Time.now - FeedUpdater.update_interval] } 10 { :conditions => ['(fetched_at is NULL) OR (fetched_at < ?)', Time.now - FeedUpdater.update_interval] }
11 } 11 }
12 12
13 - attr_accessible :address, :enabled 13 + attr_accessible :address, :enabled, :only_once
14 14
15 def add_item(title, link, date, content) 15 def add_item(title, link, date, content)
  16 + return if content.blank?
16 doc = Hpricot(content) 17 doc = Hpricot(content)
17 doc.search('*').each do |p| 18 doc.search('*').each do |p|
18 if p.instance_of? Hpricot::Elem 19 if p.instance_of? Hpricot::Elem
@@ -30,6 +31,7 @@ class ExternalFeed &lt; ActiveRecord::Base @@ -30,6 +31,7 @@ class ExternalFeed &lt; ActiveRecord::Base
30 article.source = link 31 article.source = link
31 article.profile = blog.profile 32 article.profile = blog.profile
32 article.parent = blog 33 article.parent = blog
  34 + article.author_name = self.feed_title
33 unless blog.children.exists?(:slug => article.slug) 35 unless blog.children.exists?(:slug => article.slug)
34 article.save! 36 article.save!
35 article.delay.create_activity 37 article.delay.create_activity
app/models/featured_products_block.rb
1 class FeaturedProductsBlock < Block 1 class FeaturedProductsBlock < Block
2 2
  3 + attr_accessible :product_ids, :groups_of, :speed, :reflect
  4 +
3 settings_items :product_ids, :type => Array, :default => [] 5 settings_items :product_ids, :type => Array, :default => []
4 settings_items :groups_of, :type => :integer, :default => 3 6 settings_items :groups_of, :type => :integer, :default => 3
5 settings_items :speed, :type => :integer, :default => 1000 7 settings_items :speed, :type => :integer, :default => 1000
app/models/feed_reader_block.rb
@@ -85,8 +85,4 @@ class FeedReaderBlock &lt; Block @@ -85,8 +85,4 @@ class FeedReaderBlock &lt; Block
85 block_title(title) + formatted_feed_content 85 block_title(title) + formatted_feed_content
86 end 86 end
87 87
88 - def editable?  
89 - true  
90 - end  
91 -  
92 end 88 end
app/models/folder.rb
@@ -12,7 +12,7 @@ class Folder &lt; Article @@ -12,7 +12,7 @@ class Folder &lt; Article
12 12
13 acts_as_having_settings :field => :setting 13 acts_as_having_settings :field => :setting
14 14
15 - xss_terminate :only => [ :body ], :with => 'white_list', :on => 'validation' 15 + xss_terminate :only => [ :name, :body ], :with => 'white_list', :on => 'validation'
16 16
17 include WhiteListFilter 17 include WhiteListFilter
18 filter_iframes :body 18 filter_iframes :body
app/models/highlights_block.rb
1 class HighlightsBlock < Block 1 class HighlightsBlock < Block
2 2
3 - attr_accessible :images 3 + attr_accessible :images, :interval, :shuffle, :navigation
4 4
5 settings_items :images, :type => Array, :default => [] 5 settings_items :images, :type => Array, :default => []
6 settings_items :interval, :type => 'integer', :default => 4 6 settings_items :interval, :type => 'integer', :default => 4
app/models/invitation.rb
@@ -65,18 +65,16 @@ class Invitation &lt; Task @@ -65,18 +65,16 @@ class Invitation &lt; Task
65 65
66 task_args = if user.nil? 66 task_args = if user.nil?
67 {:person => person, :friend_name => friend_name, :friend_email => friend_email, :message => message} 67 {:person => person, :friend_name => friend_name, :friend_email => friend_email, :message => message}
68 - elsif !user.person.is_a_friend?(person) 68 + else
69 {:person => person, :target => user.person} 69 {:person => person, :target => user.person}
70 end 70 end
71 71
72 - if !task_args.nil?  
73 - if profile.person?  
74 - InviteFriend.create(task_args)  
75 - elsif profile.community?  
76 - InviteMember.create(task_args.merge(:community_id => profile.id))  
77 - else  
78 - raise NotImplementedError, 'Don\'t know how to invite people to a %s' % profile.class.to_s  
79 - end 72 + if profile.person?
  73 + InviteFriend.create(task_args) if user.nil? || !user.person.is_a_friend?(person)
  74 + elsif profile.community?
  75 + InviteMember.create(task_args.merge(:community_id => profile.id)) if user.nil? || !user.person.is_member_of?(profile)
  76 + else
  77 + raise NotImplementedError, 'Don\'t know how to invite people to a %s' % profile.class.to_s
80 end 78 end
81 end 79 end
82 end 80 end
app/models/link_list_block.rb
@@ -78,16 +78,17 @@ class LinkListBlock &lt; Block @@ -78,16 +78,17 @@ class LinkListBlock &lt; Block
78 address 78 address
79 end 79 end
80 if add !~ /^[a-z]+:\/\// && add !~ /^\// 80 if add !~ /^[a-z]+:\/\// && add !~ /^\//
81 - 'http://' + add 81 + '//' + add
82 else 82 else
  83 + if root = Noosfero.root
  84 + if !add.starts_with?(root)
  85 + add = root + add
  86 + end
  87 + end
83 add 88 add
84 end 89 end
85 end 90 end
86 91
87 - def editable?  
88 - true  
89 - end  
90 -  
91 def icons_options 92 def icons_options
92 ICONS.map do |i| 93 ICONS.map do |i|
93 "<span title=\"#{i[1]}\" class=\"icon-#{i[0]}\" onclick=\"changeIcon(this, '#{i[0]}')\"></span>".html_safe 94 "<span title=\"#{i[1]}\" class=\"icon-#{i[0]}\" onclick=\"changeIcon(this, '#{i[0]}')\"></span>".html_safe
@@ -100,4 +101,5 @@ class LinkListBlock &lt; Block @@ -100,4 +101,5 @@ class LinkListBlock &lt; Block
100 sanitizer = HTML::WhiteListSanitizer.new 101 sanitizer = HTML::WhiteListSanitizer.new
101 sanitizer.sanitize(text) 102 sanitizer.sanitize(text)
102 end 103 end
  104 +
103 end 105 end
app/models/location_block.rb
1 class LocationBlock < Block 1 class LocationBlock < Block
2 2
  3 + attr_accessible :zoom, :map_type
  4 +
3 settings_items :zoom, :type => :integer, :default => 4 5 settings_items :zoom, :type => :integer, :default => 4
4 settings_items :map_type, :type => :string, :default => 'roadmap' 6 settings_items :map_type, :type => :string, :default => 'roadmap'
5 7
app/models/main_block.rb
@@ -16,10 +16,6 @@ class MainBlock &lt; Block @@ -16,10 +16,6 @@ class MainBlock &lt; Block
16 true 16 true
17 end 17 end
18 18
19 - def editable?  
20 - true  
21 - end  
22 -  
23 def cacheable? 19 def cacheable?
24 false 20 false
25 end 21 end
app/models/moderate_user_registration.rb 0 → 100644
@@ -0,0 +1,59 @@ @@ -0,0 +1,59 @@
  1 +class ModerateUserRegistration < Task
  2 +
  3 + settings_items :user_id, :type => String
  4 + settings_items :name, :type => String
  5 + settings_items :author_name, :type => String
  6 + settings_items :email, :type => String
  7 +
  8 + after_create :schedule_spam_checking
  9 +
  10 + alias :environment :target
  11 + alias :environment= :target=
  12 +
  13 + def schedule_spam_checking
  14 + self.delay.check_for_spam
  15 + end
  16 +
  17 + include Noosfero::Plugin::HotSpot
  18 +
  19 + def sender
  20 + "#{name} (#{email})"
  21 + end
  22 +
  23 + def perform
  24 + user=environment.users.find_by_id(user_id)
  25 + user.activate
  26 + end
  27 +
  28 + def title
  29 + _("New user")
  30 + end
  31 +
  32 + def subject
  33 + name
  34 + end
  35 +
  36 + def information
  37 + { :message => _('%{sender} wants to register.'),
  38 + :variables => {:sender => sender} }
  39 + end
  40 +
  41 + def icon
  42 + result = {:type => :defined_image, :src => '/images/icons-app/person-minor.png', :name => name}
  43 + end
  44 +
  45 + def target_notification_description
  46 + _('%{sender} tried to register.') %
  47 + {:sender => sender}
  48 + end
  49 +
  50 + def target_notification_message
  51 + target_notification_description + "\n\n" +
  52 + _('You need to login on %{system} in order to approve or reject this user.') % { :environment => self.environment }
  53 + end
  54 +
  55 + def target_notification_message
  56 + _("User \"%{user}\" just requested to register. You have to approve or reject it through the \"Pending Validations\" section in your control panel.\n") % { :user => self.name }
  57 + end
  58 +
  59 +end
0 \ No newline at end of file 60 \ No newline at end of file
app/models/organization.rb
@@ -30,6 +30,16 @@ class Organization &lt; Profile @@ -30,6 +30,16 @@ class Organization &lt; Profile
30 30
31 scope :more_popular, :order => 'members_count DESC' 31 scope :more_popular, :order => 'members_count DESC'
32 32
  33 + validate :presence_of_required_fieds, :unless => :is_template
  34 +
  35 + def presence_of_required_fieds
  36 + self.required_fields.each do |field|
  37 + if self.send(field).blank?
  38 + self.errors.add_on_blank(field)
  39 + end
  40 + end
  41 + end
  42 +
33 def validation_methodology 43 def validation_methodology
34 self.validation_info ? self.validation_info.validation_methodology : nil 44 self.validation_info ? self.validation_info.validation_methodology : nil
35 end 45 end
@@ -135,7 +145,11 @@ class Organization &lt; Profile @@ -135,7 +145,11 @@ class Organization &lt; Profile
135 end 145 end
136 146
137 def notification_emails 147 def notification_emails
138 - [contact_email.blank? ? nil : contact_email].compact + admins.map(&:email) 148 + emails = [contact_email].select(&:present?) + admins.map(&:email)
  149 + if emails.empty?
  150 + emails << environment.contact_email
  151 + end
  152 + emails
139 end 153 end
140 154
141 def already_request_membership?(person) 155 def already_request_membership?(person)
app/models/person.rb
@@ -21,6 +21,12 @@ class Person &lt; Profile @@ -21,6 +21,12 @@ class Person &lt; Profile
21 { :select => 'DISTINCT profiles.*', :joins => :role_assignments, :conditions => [conditions] } 21 { :select => 'DISTINCT profiles.*', :joins => :role_assignments, :conditions => [conditions] }
22 } 22 }
23 23
  24 + scope :by_role, lambda { |roles|
  25 + roles = [roles] unless roles.kind_of?(Array)
  26 + { :select => 'DISTINCT profiles.*', :joins => :role_assignments, :conditions => ['role_assignments.role_id IN (?)',
  27 +roles] }
  28 + }
  29 +
24 def has_permission_with_plugins?(permission, profile) 30 def has_permission_with_plugins?(permission, profile)
25 permissions = [has_permission_without_plugins?(permission, profile)] 31 permissions = [has_permission_without_plugins?(permission, profile)]
26 permissions += plugins.map do |plugin| 32 permissions += plugins.map do |plugin|
@@ -74,6 +80,10 @@ class Person &lt; Profile @@ -74,6 +80,10 @@ class Person &lt; Profile
74 80
75 belongs_to :user, :dependent => :delete 81 belongs_to :user, :dependent => :delete
76 82
  83 + def can_change_homepage?
  84 + !environment.enabled?('cant_change_homepage') || is_admin?
  85 + end
  86 +
77 def can_control_scrap?(scrap) 87 def can_control_scrap?(scrap)
78 begin 88 begin
79 !self.scraps(scrap).nil? 89 !self.scraps(scrap).nil?
@@ -161,7 +171,7 @@ class Person &lt; Profile @@ -161,7 +171,7 @@ class Person &lt; Profile
161 FIELDS 171 FIELDS
162 end 172 end
163 173
164 - validate :presence_of_required_fields 174 + validate :presence_of_required_fields, :unless => :is_template
165 175
166 def presence_of_required_fields 176 def presence_of_required_fields
167 self.required_fields.each do |field| 177 self.required_fields.each do |field|
@@ -300,7 +310,7 @@ class Person &lt; Profile @@ -300,7 +310,7 @@ class Person &lt; Profile
300 end 310 end
301 311
302 def default_template 312 def default_template
303 - environment.person_template 313 + environment.person_default_template
304 end 314 end
305 315
306 def apply_type_specific_template(template) 316 def apply_type_specific_template(template)
app/models/person_notifier.rb
@@ -67,7 +67,7 @@ class PersonNotifier @@ -67,7 +67,7 @@ class PersonNotifier
67 67
68 class Mailer < ActionMailer::Base 68 class Mailer < ActionMailer::Base
69 69
70 - add_template_helper(PersonNotifierHelper) 70 + add_template_helper(ApplicationHelper)
71 71
72 def session 72 def session
73 {:theme => nil} 73 {:theme => nil}
app/models/product.rb
@@ -11,7 +11,7 @@ class Product &lt; ActiveRecord::Base @@ -11,7 +11,7 @@ class Product &lt; ActiveRecord::Base
11 11
12 SEARCH_DISPLAYS = %w[map full] 12 SEARCH_DISPLAYS = %w[map full]
13 13
14 - attr_accessible :name, :product_category, :highlighted, :price, :enterprise, :image_builder, :description, :available, :qualifiers, :unit_id, :discount, :inputs 14 + attr_accessible :name, :product_category, :highlighted, :price, :enterprise, :image_builder, :description, :available, :qualifiers, :unit_id, :discount, :inputs, :qualifiers_list
15 15
16 def self.default_search_display 16 def self.default_search_display
17 'full' 17 'full'
app/models/product_categories_block.rb
@@ -33,7 +33,7 @@ class ProductCategoriesBlock &lt; Block @@ -33,7 +33,7 @@ class ProductCategoriesBlock &lt; Block
33 end 33 end
34 end 34 end
35 35
36 - DISPLAY_OPTIONS['catalog_only'] = _('Only on the catalog') 36 + DISPLAY_OPTIONS = DISPLAY_OPTIONS.merge('catalog_only' => _('Only on the catalog'))
37 37
38 def display 38 def display
39 settings[:display].nil? ? 'catalog_only' : super 39 settings[:display].nil? ? 'catalog_only' : super
app/models/products_block.rb
@@ -49,17 +49,10 @@ class ProductsBlock &lt; Block @@ -49,17 +49,10 @@ class ProductsBlock &lt; Block
49 49
50 def products(reload = false) 50 def products(reload = false)
51 if product_ids.blank? 51 if product_ids.blank?
52 - products_list = owner.products(reload)  
53 - result = []  
54 - [4, products_list.size].min.times do  
55 - p = products_list.sample  
56 - result << p  
57 - products_list -= [p]  
58 - end  
59 - result 52 + owner.products.order('RANDOM()').limit([4,owner.products.count].min)
60 else 53 else
61 - product_ids.map {|item| owner.products.find(item) }  
62 - end 54 + owner.products.where(:id => product_ids)
  55 + end.compact
63 end 56 end
64 57
65 end 58 end
app/models/profile.rb
@@ -97,7 +97,7 @@ class Profile &lt; ActiveRecord::Base @@ -97,7 +97,7 @@ class Profile &lt; ActiveRecord::Base
97 end 97 end
98 98
99 def members_by_name 99 def members_by_name
100 - members.order(:name) 100 + members.order('profiles.name')
101 end 101 end
102 102
103 class << self 103 class << self
@@ -108,8 +108,8 @@ class Profile &lt; ActiveRecord::Base @@ -108,8 +108,8 @@ class Profile &lt; ActiveRecord::Base
108 alias_method_chain :count, :distinct 108 alias_method_chain :count, :distinct
109 end 109 end
110 110
111 - def members_by_role(role)  
112 - Person.members_of(self).all(:conditions => ['role_assignments.role_id = ?', role.id]) 111 + def members_by_role(roles)
  112 + Person.members_of(self).by_role(roles)
113 end 113 end
114 114
115 acts_as_having_boxes 115 acts_as_having_boxes
@@ -121,7 +121,9 @@ class Profile &lt; ActiveRecord::Base @@ -121,7 +121,9 @@ class Profile &lt; ActiveRecord::Base
121 end 121 end
122 122
123 scope :visible, :conditions => { :visible => true } 123 scope :visible, :conditions => { :visible => true }
  124 + scope :disabled, :conditions => { :visible => false }
124 scope :public, :conditions => { :visible => true, :public_profile => true } 125 scope :public, :conditions => { :visible => true, :public_profile => true }
  126 + scope :enabled, :conditions => { :enabled => true }
125 127
126 # Subclasses must override this method 128 # Subclasses must override this method
127 scope :more_popular 129 scope :more_popular
@@ -346,16 +348,17 @@ class Profile &lt; ActiveRecord::Base @@ -346,16 +348,17 @@ class Profile &lt; ActiveRecord::Base
346 end 348 end
347 349
348 def copy_blocks_from(profile) 350 def copy_blocks_from(profile)
  351 + template_boxes = profile.boxes.select{|box| box.position}
349 self.boxes.destroy_all 352 self.boxes.destroy_all
350 - profile.boxes.each do |box|  
351 - new_box = Box.new 353 + self.boxes = template_boxes.size.times.map { Box.new }
  354 +
  355 + template_boxes.each_with_index do |box, i|
  356 + new_box = self.boxes[i]
352 new_box.position = box.position 357 new_box.position = box.position
353 - self.boxes << new_box  
354 box.blocks.each do |block| 358 box.blocks.each do |block|
355 new_block = block.class.new(:title => block[:title]) 359 new_block = block.class.new(:title => block[:title])
356 - new_block.settings = block.settings  
357 - new_block.position = block.position  
358 - self.boxes[-1].blocks << new_block 360 + new_block.copy_from(block)
  361 + new_box.blocks << new_block
359 end 362 end
360 end 363 end
361 end 364 end
@@ -390,7 +393,7 @@ class Profile &lt; ActiveRecord::Base @@ -390,7 +393,7 @@ class Profile &lt; ActiveRecord::Base
390 end 393 end
391 394
392 xss_terminate :only => [ :name, :nickname, :address, :contact_phone, :description ], :on => 'validation' 395 xss_terminate :only => [ :name, :nickname, :address, :contact_phone, :description ], :on => 'validation'
393 - xss_terminate :only => [ :custom_footer, :custom_header ], :with => 'white_list', :on => 'validation' 396 + xss_terminate :only => [ :custom_footer, :custom_header ], :with => 'white_list'
394 397
395 include WhiteListFilter 398 include WhiteListFilter
396 filter_iframes :custom_header, :custom_footer 399 filter_iframes :custom_header, :custom_footer
@@ -774,7 +777,7 @@ private :generate_url, :url_options @@ -774,7 +777,7 @@ private :generate_url, :url_options
774 end 777 end
775 778
776 include Noosfero::Plugin::HotSpot 779 include Noosfero::Plugin::HotSpot
777 - 780 +
778 def folder_types 781 def folder_types
779 types = Article.folder_types 782 types = Article.folder_types
780 plugins.dispatch(:content_types).each {|type| 783 plugins.dispatch(:content_types).each {|type|
@@ -898,6 +901,13 @@ private :generate_url, :url_options @@ -898,6 +901,13 @@ private :generate_url, :url_options
898 end 901 end
899 902
900 def disable 903 def disable
  904 + self.visible = false
  905 + self.save
  906 + end
  907 +
  908 + def enable
  909 + self.visible = true
  910 + self.save
901 end 911 end
902 912
903 def control_panel_settings_button 913 def control_panel_settings_button
app/models/profile_image_block.rb
@@ -23,10 +23,6 @@ class ProfileImageBlock &lt; Block @@ -23,10 +23,6 @@ class ProfileImageBlock &lt; Block
23 end 23 end
24 end 24 end
25 25
26 - def editable?  
27 - true  
28 - end  
29 -  
30 def cacheable? 26 def cacheable?
31 false 27 false
32 end 28 end
app/models/profile_info_block.rb
@@ -15,10 +15,6 @@ class ProfileInfoBlock &lt; Block @@ -15,10 +15,6 @@ class ProfileInfoBlock &lt; Block
15 end 15 end
16 end 16 end
17 17
18 - def editable?  
19 - false  
20 - end  
21 -  
22 def cacheable? 18 def cacheable?
23 false 19 false
24 end 20 end
app/models/profile_search_block.rb
@@ -11,8 +11,4 @@ class ProfileSearchBlock &lt; Block @@ -11,8 +11,4 @@ class ProfileSearchBlock &lt; Block
11 end 11 end
12 end 12 end
13 13
14 - def editable?  
15 - true  
16 - end  
17 -  
18 end 14 end
app/models/rss_feed.rb
1 class RssFeed < Article 1 class RssFeed < Article
2 2
3 - attr_accessible :limit, :enabled, :language, :include 3 + attr_accessible :limit, :enabled, :language, :include, :feed_item_description
4 4
5 def self.type_name 5 def self.type_name
6 _('RssFeed') 6 _('RssFeed')
app/models/task.rb
@@ -73,10 +73,6 @@ class Task &lt; ActiveRecord::Base @@ -73,10 +73,6 @@ class Task &lt; ActiveRecord::Base
73 end 73 end
74 end 74 end
75 75
76 - def self.all_types  
77 - %w[Invitation EnterpriseActivation AddMember Ticket SuggestArticle AddFriend CreateCommunity AbuseComplaint ApproveComment ApproveArticle CreateEnterprise ChangePassword EmailActivation InviteFriend InviteMember]  
78 - end  
79 -  
80 # this method finished the task. It calls #perform, which must be overriden 76 # this method finished the task. It calls #perform, which must be overriden
81 # by subclasses. At the end a message (as returned by #finish_message) is 77 # by subclasses. At the end a message (as returned by #finish_message) is
82 # sent to the requestor with #notify_requestor. 78 # sent to the requestor with #notify_requestor.
@@ -254,6 +250,10 @@ class Task &lt; ActiveRecord::Base @@ -254,6 +250,10 @@ class Task &lt; ActiveRecord::Base
254 { :conditions => [environment_condition, profile_condition].compact.join(' OR ') } 250 { :conditions => [environment_condition, profile_condition].compact.join(' OR ') }
255 } 251 }
256 252
  253 + def self.pending_types_for(profile)
  254 + Task.to(profile).pending.select('distinct type').map { |t| [t.class.name, t.title] }
  255 + end
  256 +
257 def opened? 257 def opened?
258 status == Task::Status::ACTIVE || status == Task::Status::HIDDEN 258 status == Task::Status::ACTIVE || status == Task::Status::HIDDEN
259 end 259 end
@@ -285,8 +285,9 @@ class Task &lt; ActiveRecord::Base @@ -285,8 +285,9 @@ class Task &lt; ActiveRecord::Base
285 # If 285 # If
286 def send_notification(action) 286 def send_notification(action)
287 if sends_email? 287 if sends_email?
288 - if self.requestor  
289 - TaskMailer.generic_message("task_#{action}", self) 288 + if self.requestor && !self.requestor.notification_emails.empty?
  289 + message = TaskMailer.generic_message("task_#{action}", self)
  290 + message.deliver if message
290 end 291 end
291 end 292 end
292 end 293 end
app/models/user.rb
@@ -5,7 +5,7 @@ require &#39;user_activation_job&#39; @@ -5,7 +5,7 @@ require &#39;user_activation_job&#39;
5 # Rails generator. 5 # Rails generator.
6 class User < ActiveRecord::Base 6 class User < ActiveRecord::Base
7 7
8 - attr_accessible :login, :email, :password, :password_confirmation 8 + attr_accessible :login, :email, :password, :password_confirmation, :activated_at
9 9
10 N_('Password') 10 N_('Password')
11 N_('Password confirmation') 11 N_('Password confirmation')
@@ -16,15 +16,18 @@ class User &lt; ActiveRecord::Base @@ -16,15 +16,18 @@ class User &lt; ActiveRecord::Base
16 end 16 end
17 17
18 # FIXME ugly workaround 18 # FIXME ugly workaround
19 - def self.human_attribute_name(attrib, options={}) 19 + def self.human_attribute_name_with_customization(attrib, options={})
20 case attrib.to_sym 20 case attrib.to_sym
21 when :login 21 when :login
22 return [_('Username'), _('Email')].join(' / ') 22 return [_('Username'), _('Email')].join(' / ')
23 when :email 23 when :email
24 return _('e-Mail') 24 return _('e-Mail')
25 - else _(self.superclass.human_attribute_name(attrib)) 25 + else _(self.human_attribute_name_without_customization(attrib))
26 end 26 end
27 end 27 end
  28 + class << self
  29 + alias_method_chain :human_attribute_name, :customization
  30 + end
28 31
29 before_create do |user| 32 before_create do |user|
30 if user.environment.nil? 33 if user.environment.nil?
@@ -47,8 +50,12 @@ class User &lt; ActiveRecord::Base @@ -47,8 +50,12 @@ class User &lt; ActiveRecord::Base
47 50
48 user.person = p 51 user.person = p
49 end 52 end
50 - if user.environment.enabled?('skip_new_user_email_confirmation')  
51 - user.activate 53 + if user.environment.enabled?('skip_new_user_email_confirmation')
  54 + if user.environment.enabled?('admin_must_approve_new_users')
  55 + create_moderate_task
  56 + else
  57 + user.activate
  58 + end
52 end 59 end
53 end 60 end
54 after_create :deliver_activation_code 61 after_create :deliver_activation_code
@@ -137,6 +144,15 @@ class User &lt; ActiveRecord::Base @@ -137,6 +144,15 @@ class User &lt; ActiveRecord::Base
137 end 144 end
138 end 145 end
139 146
  147 + def create_moderate_task
  148 + @task = ModerateUserRegistration.new
  149 + @task.user_id = self.id
  150 + @task.name = self.name
  151 + @task.email = self.email
  152 + @task.target = self.environment
  153 + @task.save
  154 + end
  155 +
140 def activated? 156 def activated?
141 self.activation_code.nil? && !self.activated_at.nil? 157 self.activation_code.nil? && !self.activated_at.nil?
142 end 158 end
@@ -185,6 +201,10 @@ class User &lt; ActiveRecord::Base @@ -185,6 +201,10 @@ class User &lt; ActiveRecord::Base
185 Digest::MD5.hexdigest(password) 201 Digest::MD5.hexdigest(password)
186 end 202 end
187 203
  204 + add_encryption_method :salted_md5 do |password, salt|
  205 + Digest::MD5.hexdigest(password+salt)
  206 + end
  207 +
188 add_encryption_method :clear do |password, salt| 208 add_encryption_method :clear do |password, salt|
189 password 209 password
190 end 210 end
@@ -334,6 +354,7 @@ class User &lt; ActiveRecord::Base @@ -334,6 +354,7 @@ class User &lt; ActiveRecord::Base
334 end 354 end
335 355
336 def delay_activation_check 356 def delay_activation_check
  357 + return if person.is_template?
337 Delayed::Job.enqueue(UserActivationJob.new(self.id), {:priority => 0, :run_at => 72.hours.from_now}) 358 Delayed::Job.enqueue(UserActivationJob.new(self.id), {:priority => 0, :run_at => 72.hours.from_now})
338 end 359 end
339 end 360 end
app/presenters/image.rb
@@ -11,4 +11,9 @@ class FilePresenter::Image &lt; FilePresenter @@ -11,4 +11,9 @@ class FilePresenter::Image &lt; FilePresenter
11 def short_description 11 def short_description
12 _('Image (%s)') % content_type.split('/')[1].upcase 12 _('Image (%s)') % content_type.split('/')[1].upcase
13 end 13 end
  14 +
  15 + #Overwriting method from FilePresenter to allow download of images
  16 + def download?(view = nil)
  17 + view.blank? || view == 'false'
  18 + end
14 end 19 end
app/sweepers/profile_sweeper.rb
@@ -8,9 +8,6 @@ class ProfileSweeper # &lt; ActiveRecord::Observer @@ -8,9 +8,6 @@ class ProfileSweeper # &lt; ActiveRecord::Observer
8 end 8 end
9 9
10 def after_create(profile) 10 def after_create(profile)
11 - # TODO EnvironmentStatisticsBlock is DEPRECATED and will be removed from  
12 - # the Noosfero core soon, see ActionItem3045  
13 - expire_statistics_block_cache(profile)  
14 end 11 end
15 12
16 protected 13 protected
@@ -31,13 +28,6 @@ protected @@ -31,13 +28,6 @@ protected
31 expire_blogs(profile) if profile.organization? 28 expire_blogs(profile) if profile.organization?
32 end 29 end
33 30
34 - # TODO EnvironmentStatisticsBlock is DEPRECATED and will be removed from  
35 - # the Noosfero core soon, see ActionItem3045  
36 - def expire_statistics_block_cache(profile)  
37 - blocks = profile.environment.blocks.select { |b| b.kind_of?(EnvironmentStatisticsBlock) }  
38 - BlockSweeper.expire_blocks(blocks)  
39 - end  
40 -  
41 def expire_blogs(profile) 31 def expire_blogs(profile)
42 profile.blogs.select{|b| !b.empty?}.each do |blog| 32 profile.blogs.select{|b| !b.empty?}.each do |blog|
43 pages = blog.posts.count / blog.posts_per_page + 1 33 pages = blog.posts.count / blog.posts_per_page + 1
app/sweepers/role_assignment_sweeper.rb
@@ -13,20 +13,22 @@ class RoleAssignmentSweeper &lt; ActiveRecord::Observer @@ -13,20 +13,22 @@ class RoleAssignmentSweeper &lt; ActiveRecord::Observer
13 protected 13 protected
14 14
15 def expire_caches(role_assignment) 15 def expire_caches(role_assignment)
16 - expire_cache(role_assignment.accessor)  
17 - expire_cache(role_assignment.resource) if role_assignment.resource.respond_to?(:cache_keys) 16 + expire_cache(role_assignment.accessor) if role_assignment.accessor.kind_of?(Profile)
  17 + expire_cache(role_assignment.resource) if role_assignment.resource.kind_of?(Profile)
18 end 18 end
19 19
20 def expire_cache(profile) 20 def expire_cache(profile)
21 per_page = Noosfero::Constants::PROFILE_PER_PAGE 21 per_page = Noosfero::Constants::PROFILE_PER_PAGE
22 - profile.cache_keys(:per_page => per_page).each { |ck|  
23 - expire_timeout_fragment(ck)  
24 - } 22 +
  23 + profile.cache_keys(:per_page => per_page).each { |ck| expire_timeout_fragment(ck) }
  24 + expire_timeout_fragment(profile.members_cache_key(:per_page => per_page))
25 25
26 profile.blocks_to_expire_cache.each { |block| 26 profile.blocks_to_expire_cache.each { |block|
27 blocks = profile.blocks.select{|b| b.kind_of?(block)} 27 blocks = profile.blocks.select{|b| b.kind_of?(block)}
28 BlockSweeper.expire_blocks(blocks) 28 BlockSweeper.expire_blocks(blocks)
29 } 29 }
  30 +
  31 + expire_blocks_cache(profile, [:role_assignment])
30 end 32 end
31 33
32 end 34 end
app/views/account/_signup_form.html.erb
@@ -136,8 +136,6 @@ @@ -136,8 +136,6 @@
136 <script type="text/javascript"> 136 <script type="text/javascript">
137 jQuery(function($) { 137 jQuery(function($) {
138 138
139 - $('#signup-form #user_login').css('width', 335 - $('#signup-domain').outerWidth());  
140 -  
141 $('#signup-form input[type=text], #signup-form textarea').each(function() { 139 $('#signup-form input[type=text], #signup-form textarea').each(function() {
142 $(this).bind('blur', function() { 140 $(this).bind('blur', function() {
143 if ($(this).val() == '') { 141 if ($(this).val() == '') {
app/views/account/signup.html.erb
@@ -2,18 +2,36 @@ @@ -2,18 +2,36 @@
2 <div id='thanks-for-signing'> 2 <div id='thanks-for-signing'>
3 <% if environment.has_custom_welcome_screen? %> 3 <% if environment.has_custom_welcome_screen? %>
4 <%= environment.settings[:signup_welcome_screen_body].html_safe %> 4 <%= environment.settings[:signup_welcome_screen_body].html_safe %>
5 - <% else %>  
6 - <h1><%= _("Welcome to %s!") % environment.name %></h1>  
7 - <h3><%= _("Thanks for signing up, we're thrilled to have you on our social network!") %></h3>  
8 - <p><%= _("Firstly, some tips for getting started:") %></p>  
9 - <h4><%= _("Confirm your account!") %></h4> 5 + <% elsif environment.enabled?('admin_must_approve_new_users')%>
  6 + <h1><%= _("Welcome to %s!") % environment.name %></h1>
  7 + <h3><%= _("Thanks for signing up, we're thrilled to have you on our social network!") %></h3>
  8 + <p><%= _("Firstly, some tips for getting started:") %></p>
  9 + <% unless environment.enabled?('skip_new_user_email_confirmation') %>
  10 + <h4><%= _("Confirm your account and wait for admin approvement!") %></h4>
10 <p><%= _("You should receive a welcome email from us shortly. Please take a second to follow the link within to confirm your account.") %></p> 11 <p><%= _("You should receive a welcome email from us shortly. Please take a second to follow the link within to confirm your account.") %></p>
11 - <p><%= _("You won't appear as %s until your account is confirmed.") % link_to(_('user'), {:controller => :search, :action => :people, :filter => 'more_recent'}, :target => '_blank') %></p>  
12 - <h4><%= _("What to do next?") %></h4>  
13 - <p><%= _("%s. Upload an avatar and let your friends find you easily :)") % link_to(_('Customize your profile'), {:controller => 'doc', :section => 'user', :topic => 'editing-person-info'}, :target => '_blank') %></p>  
14 - <p><%= _("Learn the guidelines. Read the %s for more details on how to use this social network!") % link_to(_('Documentation'), {:controller => 'doc'}, :target => '_blank') %></p>  
15 - <p><%= _("%s your Gmail, Yahoo and Hotmail contacts!") % link_to(_('Invite and find'), {:controller => 'doc', :section => 'user', :topic => 'invite-contacts'}, :target => '_blank') %></p>  
16 - <p><%= _("Start exploring and have fun!") %></p> 12 + <p><%= _("You won't appear as %s until your account is confirmed and approved.") % link_to(_('user'), {:controller => :search, :action => :people, :filter => 'more_recent'}, :target => '_blank') %></p>
  13 + <% else %>
  14 + <h4><%= _("Wait for admin approvement!") %></h4>
  15 + <p><%= _("The administrators will evaluate your signup request for approvement.") %></p>
  16 + <p><%= _("You won't appear as %s until your account is approved.") % link_to(_('user'), {:controller => :search, :action => :people, :filter => 'more_recent'}, :target => '_blank') %></p>
  17 + <% end %>
  18 + <h4><%= _("What to do next?") %></h4>
  19 + <p><%= _("%s. Upload an avatar and let your friends find you easily :)") % link_to(_('Customize your profile'), {:controller => 'doc', :section => 'user', :topic => 'editing-person-info'}, :target => '_blank') %></p>
  20 + <p><%= _("Learn the guidelines. Read the %s for more details on how to use this social network!") % link_to(_('Documentation'), {:controller => 'doc'}, :target => '_blank') %></p>
  21 + <p><%= _("%s your Gmail, Yahoo and Hotmail contacts!") % link_to(_('Invite and find'), {:controller => 'doc', :section => 'user', :topic => 'invite-contacts'}, :target => '_blank') %></p>
  22 + <p><%= _("Start exploring and have fun!") %></p>
  23 + <% else %>
  24 + <h1><%= _("Welcome to %s!") % environment.name %></h1>
  25 + <h3><%= _("Thanks for signing up, we're thrilled to have you on our social network!") %></h3>
  26 + <p><%= _("Firstly, some tips for getting started:") %></p>
  27 + <h4><%= _("Confirm your account!") %></h4>
  28 + <p><%= _("You should receive a welcome email from us shortly. Please take a second to follow the link within to confirm your account.") %></p>
  29 + <p><%= _("You won't appear as %s until your account is confirmed.") % link_to(_('user'), {:controller => :search, :action => :people, :filter => 'more_recent'}, :target => '_blank') %></p>
  30 + <h4><%= _("What to do next?") %></h4>
  31 + <p><%= _("%s. Upload an avatar and let your friends find you easily :)") % link_to(_('Customize your profile'), {:controller => 'doc', :section => 'user', :topic => 'editing-person-info'}, :target => '_blank') %></p>
  32 + <p><%= _("Learn the guidelines. Read the %s for more details on how to use this social network!") % link_to(_('Documentation'), {:controller => 'doc'}, :target => '_blank') %></p>
  33 + <p><%= _("%s your Gmail, Yahoo and Hotmail contacts!") % link_to(_('Invite and find'), {:controller => 'doc', :section => 'user', :topic => 'invite-contacts'}, :target => '_blank') %></p>
  34 + <p><%= _("Start exploring and have fun!") %></p>
17 <% end %> 35 <% end %>
18 </div> 36 </div>
19 <% else %> 37 <% else %>
app/views/admin_panel/index.html.erb
@@ -20,6 +20,7 @@ @@ -20,6 +20,7 @@
20 <tr><td><%= link_to _('Users'), :controller => 'users' %></td></tr> 20 <tr><td><%= link_to _('Users'), :controller => 'users' %></td></tr>
21 <tr><td><%= link_to _('Profile templates'), :controller => 'templates' %></td></tr> 21 <tr><td><%= link_to _('Profile templates'), :controller => 'templates' %></td></tr>
22 <tr><td><%= link_to _('Fields'), :controller => 'features', :action => 'manage_fields' %></td></tr> 22 <tr><td><%= link_to _('Fields'), :controller => 'features', :action => 'manage_fields' %></td></tr>
  23 + <tr><td><%= link_to _('Manage organizations status'), :action => 'manage_organizations_status' %></td></tr>
23 </table> 24 </table>
24 25
25 26
app/views/admin_panel/manage_organizations_status.html.erb 0 → 100644
@@ -0,0 +1,69 @@ @@ -0,0 +1,69 @@
  1 +<h1><%= _('Manage organizations') %></h1>
  2 +
  3 +<%= form_tag( { :action => 'manage_organizations_status' }, :method => 'get', :class => 'users-search' ) do %>
  4 +
  5 + <div class="search-field">
  6 + <span class="formfield">
  7 + <%= text_field_tag 'q', @q, :title => _("Find profiles"), :style=>"width:85%" %>
  8 + </span>
  9 +
  10 + <%= submit_button(:search, _('Search')) %>
  11 + </div>
  12 +
  13 + <div class="environment-users-results-header">
  14 + <div id='environment-users-filter-title'><%= @title %></div>
  15 +
  16 + <div id="environment-users-filter-filter">
  17 + <strong><%= _("Filter by: ") %></strong>
  18 +
  19 + <select id="profile_filter_select">
  20 + <%= options_for_select([['Any', 'any'],["Disabled profiles", "disabled"], ["Enabled profiles", "enabled"]], @filter) %>
  21 + </select>
  22 + </div>
  23 + <div style="clear: both"></div>
  24 + </div>
  25 +
  26 + <table>
  27 + <colgroup>
  28 + <col width="80%">
  29 + <col width="20%">
  30 + </colgroup>
  31 +
  32 + <tr>
  33 + <th><%= _('Member') %></th>
  34 + <th><%= _('Actions') %></th>
  35 + </tr>
  36 +
  37 + <% @collection.each do |p| %>
  38 + <tr title="<%= p.name %>">
  39 + <td><%= link_to_profile p.short_name, p.identifier, :title => p.name %> </td>
  40 +
  41 + <td class='actions'>
  42 + <div class="members-buttons-cell">
  43 + <% if p.visible %>
  44 + <%= button_without_text :'deactivate-user', _('Deactivate'), {:controller => "profile_editor", :action => 'deactivate_profile', :profile => p.identifier, :id => p.id}, :confirm => _("Do you want to deactivate this profile ?") %>
  45 + <% else %>
  46 + <%= button_without_text :'activate-user', _('Activate'), {:controller => "profile_editor", :action => 'activate_profile', :profile => p.identifier, :id => p.id}, :confirm => _("Do you want to activate this profile ?") %>
  47 + <% end %>
  48 + <%= button_without_text :'delete', _('Remove'), {:controller => "profile_editor", :action => 'destroy_profile', :profile => p.identifier, :id => p.id, :return_to => "/admin/admin_panel/manage_organizations_status"}, :method => :post, :confirm => _("Do you want to deactivate this profile ?") %>
  49 + </div>
  50 + </td>
  51 + </tr>
  52 + <% end %>
  53 + </table>
  54 +
  55 +<% end %>
  56 +
  57 +<%= pagination_links @collection, {:param_name => 'npage', :page_links => true} %>
  58 +
  59 +<% button_bar do %>
  60 + <%= button :back, _('Back'), :controller => 'admin_panel' %>
  61 +<% end %>
  62 +
  63 +<script type="text/javascript">
  64 + jQuery(document).ready(function(){
  65 + jQuery("#profile_filter_select").change(function(){
  66 + document.location.href = '/admin/admin_panel/manage_organizations_status?filter='+this.value;
  67 + });
  68 + });
  69 +</script>
0 \ No newline at end of file 70 \ No newline at end of file
app/views/blocks/my_network.html.erb
1 <%= block_title(title) %> 1 <%= block_title(title) %>
2 2
3 -<%= render :file => 'blocks/my_network/' + owner.class.name.underscore, :locals => { :owner => owner } %> 3 +<%= render_profile_actions owner.class %>
4 4
5 <ul> 5 <ul>
6 <li><%= link_to(_('Homepage'), owner.url, :class => 'url') %></li> 6 <li><%= link_to(_('Homepage'), owner.url, :class => 'url') %></li>
@@ -11,5 +11,5 @@ @@ -11,5 +11,5 @@
11 </ul> 11 </ul>
12 12
13 <div class="my-network-actions"> 13 <div class="my-network-actions">
14 - <%= render :file => 'blocks/profile_info_actions/' + owner.class.name.underscore %> 14 + <%= render 'blocks/profile_info_actions/' + owner.class.name.underscore %>
15 </div> 15 </div>
app/views/blocks/profile_image.html.erb
@@ -23,6 +23,6 @@ @@ -23,6 +23,6 @@
23 <% end %> 23 <% end %>
24 24
25 <div class="profile-info-options"> 25 <div class="profile-info-options">
26 - <%= render :file => view_for_profile_actions(block.owner.class) %> 26 + <%= render_profile_actions block.owner.class %>
27 </div> 27 </div>
28 </div><!-- end class="vcard" --> 28 </div><!-- end class="vcard" -->
app/views/blocks/profile_info.html.erb
@@ -40,7 +40,7 @@ @@ -40,7 +40,7 @@
40 <% end %> 40 <% end %>
41 41
42 <div class="profile-info-options"> 42 <div class="profile-info-options">
43 - <%= render :file => view_for_profile_actions(block.owner.class) %> 43 + <%= render_profile_actions block.owner.class %>
44 </div> 44 </div>
45 45
46 </div><!-- end class="vcard" --> 46 </div><!-- end class="vcard" -->
app/views/blocks/profile_info_actions/_community.html.erb 0 → 100644
@@ -0,0 +1,20 @@ @@ -0,0 +1,20 @@
  1 +<ul>
  2 + <li>
  3 + <%= render "blocks/profile_info_actions/join_leave_community" %>
  4 + </li>
  5 + <% if logged_in? %>
  6 + <% if profile.enable_contact? %>
  7 + <li>
  8 + <%= link_to content_tag('span', _('Send an e-mail')),
  9 + { :profile => profile.identifier,
  10 + :controller => 'contact',
  11 + :action => 'new' },
  12 + {:class => 'button with-text icon-menu-mail', :title => _('Send an e-mail to the administrators')} %>
  13 + </li>
  14 + <% end %>
  15 +
  16 + <li><%= report_abuse(profile, :button) %></li>
  17 +
  18 + <%= render_environment_features(:profile_actions) %>
  19 + <% end %>
  20 +</ul>
app/views/blocks/profile_info_actions/_enterprise.html.erb 0 → 100644
@@ -0,0 +1,12 @@ @@ -0,0 +1,12 @@
  1 +<ul>
  2 + <%if logged_in? %>
  3 + <%if !user.favorite_enterprises.include?(profile) %>
  4 + <li><%= link_to content_tag('span', _('Add as favorite')), { :profile => user.identifier, :controller => 'favorite_enterprises', :action => 'add', :id => profile.id }, :class => 'button with-text icon-add', :title => _('Add enterprise as favorite') %></li>
  5 + <% end %>
  6 + <% end %>
  7 + <% if profile.enable_contact? %>
  8 + <li> <%= link_to content_tag('span', _('Send an e-mail')), {:profile => profile.identifier, :controller => 'contact', :action => 'new'}, {:id => 'enterprise-contact-button', :class => 'button with-text icon-menu-mail'} %> </li>
  9 + <% end %>
  10 +
  11 + <li><%= report_abuse(profile, :button) %></li>
  12 +</ul>
app/views/blocks/profile_info_actions/_organization.html.erb 0 → 100644
app/views/blocks/profile_info_actions/_person.html.erb 0 → 100644
@@ -0,0 +1,16 @@ @@ -0,0 +1,16 @@
  1 +<ul>
  2 + <%if logged_in? && (user != profile) %>
  3 +
  4 + <% if !user.already_request_friendship?(profile) and !user.is_a_friend?(profile) %>
  5 + <li>
  6 + <%= button(:add, content_tag('span', _('Add friend')), profile.add_url, :class => 'add-friend', :title => _("Add friend"), :style => 'position: relative;') %>
  7 + </li>
  8 + <% end %>
  9 +
  10 + <% if user.is_a_friend?(profile) && profile.enable_contact? %>
  11 + <li> <%= link_to content_tag('span', _('Send an e-mail')), {:profile => profile.identifier, :controller => 'contact', :action => 'new'}, :class => 'button with-text icon-menu-mail' %> </li>
  12 + <% end %>
  13 +
  14 + <li><%= report_abuse(profile, :button) %></li>
  15 + <% end %>
  16 +</ul>
app/views/blocks/profile_info_actions/community.html.erb
@@ -1,20 +0,0 @@ @@ -1,20 +0,0 @@
1 -<ul>  
2 - <li>  
3 - <%= render "blocks/profile_info_actions/join_leave_community" %>  
4 - </li>  
5 - <% if logged_in? %>  
6 - <% if profile.enable_contact? %>  
7 - <li>  
8 - <%= link_to content_tag('span', _('Send an e-mail')),  
9 - { :profile => profile.identifier,  
10 - :controller => 'contact',  
11 - :action => 'new' },  
12 - {:class => 'button with-text icon-menu-mail', :title => _('Send an e-mail to the administrators')} %>  
13 - </li>  
14 - <% end %>  
15 -  
16 - <li><%= report_abuse(profile, :button) %></li>  
17 -  
18 - <%= render_environment_features(:profile_actions) %>  
19 - <% end %>  
20 -</ul>  
app/views/blocks/profile_info_actions/enterprise.html.erb
@@ -1,12 +0,0 @@ @@ -1,12 +0,0 @@
1 -<ul>  
2 - <%if logged_in? %>  
3 - <%if !user.favorite_enterprises.include?(profile) %>  
4 - <li><%= link_to content_tag('span', _('Add as favorite')), { :profile => user.identifier, :controller => 'favorite_enterprises', :action => 'add', :id => profile.id }, :class => 'button with-text icon-add', :title => _('Add enterprise as favorite') %></li>  
5 - <% end %>  
6 - <% end %>  
7 - <% if profile.enable_contact? %>  
8 - <li> <%= link_to content_tag('span', _('Send an e-mail')), {:profile => profile.identifier, :controller => 'contact', :action => 'new'}, {:id => 'enterprise-contact-button', :class => 'button with-text icon-menu-mail'} %> </li>  
9 - <% end %>  
10 -  
11 - <li><%= report_abuse(profile, :button) %></li>  
12 -</ul>