diff --git a/src/cake/app/models/cs_test.php b/src/cake/app/models/cs_test.php new file mode 100644 index 00000000..4b44c07f --- /dev/null +++ b/src/cake/app/models/cs_test.php @@ -0,0 +1,13 @@ + array( + 'streams' => array( + 'cs_content_stream_id' => 'document' + ) + ) + ); +} diff --git a/src/cake/app/plugins/backstage/config/backstage.php b/src/cake/app/plugins/backstage/config/backstage.php index 6ca95726..c9973dbe 100644 --- a/src/cake/app/plugins/backstage/config/backstage.php +++ b/src/cake/app/plugins/backstage/config/backstage.php @@ -55,7 +55,7 @@ ), 'customRow' => true, 'customSearch' => true, - 'contain' => array('UserPermission'), + 'contain' => array('UserPermission', 'UserUser'), ), 'user_permissions' => array( 'actions' => array('delete','edit', 'create'), @@ -70,4 +70,4 @@ 'customSearch' => true, ), ) -); \ No newline at end of file +); diff --git a/src/cake/app/plugins/backstage/controllers/back_contents_controller.php b/src/cake/app/plugins/backstage/controllers/back_contents_controller.php index 9e5534d7..243072d4 100644 --- a/src/cake/app/plugins/backstage/controllers/back_contents_controller.php +++ b/src/cake/app/plugins/backstage/controllers/back_contents_controller.php @@ -464,6 +464,12 @@ function create_empty_translation($moduleName, $id = null) function layout_test() { - + $this->loadModel('CsTest'); + $data = $this->CsTest->findById(1); + if (empty($data)) + { + $data = $this->CsTest->save(array('id' => 1)); + } + $this->data = $data; } } diff --git a/src/cake/app/plugins/backstage/views/back_contents/layout_test.ctp b/src/cake/app/plugins/backstage/views/back_contents/layout_test.ctp index b233a44f..606a4230 100644 --- a/src/cake/app/plugins/backstage/views/back_contents/layout_test.ctp +++ b/src/cake/app/plugins/backstage/views/back_contents/layout_test.ctp @@ -58,7 +58,7 @@ echo $this->Bl->sbox(null, array('size' => array('M' => 7, 'g' => -1))); 'default' => 'Suspendisse dignissim ante sit amet leo bibendum rhoncus? Integer at enim eget tortor cursus tristique. Cras vel vehicula nisi? Phasellus nisl massa, commodo sed porttitor quis, imperdiet quis lacus. Aliquam erat volutpat. Sed dictum, dui blandit sodales dapibus, sapien massa mollis augue, in porta ligula odio vel sapien. Donec interdum metus eu nunc tristique mattis. Donec luctus aliquam lectus, quis fermentum arcu dignissim at.' ) ) - ); + ); // Textarea with textile controll echo $this->Buro->input( @@ -224,7 +224,25 @@ echo $this->Bl->sbox(null, array('size' => array('M' => 7, 'g' => -1))); ) ) ); - + + echo $this->Buro->sform(null, array('model' => 'CsTest')); + + echo $this->Buro->input( + array(), + array( + 'type' => 'content_stream', + 'label' => 'Label for a content_stream input', + 'instructions' => 'Instructions for a content_stream input', + 'options' => array( + 'foreignKey' => 'cs_content_stream_id' + ) + ) + ); + echo $this->Bl->floatBreak(); + + echo $this->Buro->eform(); + echo $this->Bl->floatBreak(); + // Datetime without time echo $this->Buro->input( null, @@ -289,7 +307,8 @@ echo $this->Bl->sbox(null, array('size' => array('M' => 7, 'g' => -1))); 'type' => 'upload', 'fieldName' => 'upload', 'label' => 'Label for a upload input', - 'instructions' => 'Instructions for a upload input' + 'instructions' => 'Instructions for a upload input', + 'options' => array('model' => 'JjMedia.SfilBigFile') ) ); diff --git a/src/cake/app/plugins/burocrata/locale/por/LC_MESSAGES/burocrata.mo b/src/cake/app/plugins/burocrata/locale/por/LC_MESSAGES/burocrata.mo index 182d57ff..c6988b71 100644 Binary files a/src/cake/app/plugins/burocrata/locale/por/LC_MESSAGES/burocrata.mo and b/src/cake/app/plugins/burocrata/locale/por/LC_MESSAGES/burocrata.mo differ diff --git a/src/cake/app/plugins/burocrata/locale/por/LC_MESSAGES/burocrata.po b/src/cake/app/plugins/burocrata/locale/por/LC_MESSAGES/burocrata.po index 13cfd4af..0927fa12 100644 --- a/src/cake/app/plugins/burocrata/locale/por/LC_MESSAGES/burocrata.po +++ b/src/cake/app/plugins/burocrata/locale/por/LC_MESSAGES/burocrata.po @@ -4,8 +4,8 @@ msgid "" msgstr "" "Project-Id-Version: PROJECT VERSION\n" -"POT-Creation-Date: 2012-01-13 12:23-0200\n" -"PO-Revision-Date: 2012-01-13 17:46-0300\n" +"POT-Creation-Date: 2013-03-21 22:51-0300\n" +"PO-Revision-Date: 2013-03-21 22:59-0300\n" "Last-Translator: Daniel Abrahão \n" "Language-Team: Preface Design \n" "Language: \n" @@ -16,218 +16,270 @@ msgstr "" "X-Poedit-Language: Portuguese\n" "X-Poedit-Country: BRAZIL\n" -#: /plugins/burocrata/views/helpers/buro_burocrata.php:561 +#: /plugins/burocrata/views/helpers/buro_burocrata.php:574 msgid "Burocrata::submit - Submit label" msgstr "Enviar" -#: /plugins/burocrata/views/helpers/buro_burocrata.php:575;652 +#: /plugins/burocrata/views/helpers/buro_burocrata.php:588;665 msgid "Burocrata::okOrCancel - Cancel label" msgstr "Cancelar" -#: /plugins/burocrata/views/helpers/buro_burocrata.php:634 +#: /plugins/burocrata/views/helpers/buro_burocrata.php:647 msgid "Burocrata::okOrCancel - OK label" msgstr "Ok" -#: /plugins/burocrata/views/helpers/buro_burocrata.php:662 +#: /plugins/burocrata/views/helpers/buro_burocrata.php:675 msgid "anchorList or" msgstr "ou" -#: /plugins/burocrata/views/helpers/buro_burocrata.php:917 +#: /plugins/burocrata/views/helpers/buro_burocrata.php:972 msgid "Burocrata: nothing found on autocomplete." msgstr "Nada encontrado." -#: /plugins/burocrata/views/helpers/buro_burocrata.php:1020;1833 +#: /plugins/burocrata/views/helpers/buro_burocrata.php:1081;1971 msgid "Burocrata: create a new related item" msgstr "Criar um novo" -#: /plugins/burocrata/views/helpers/buro_burocrata.php:1021;1834 +#: /plugins/burocrata/views/helpers/buro_burocrata.php:1082;1972 msgid "Burocrata: edit related data" msgstr "Editar" -#: /plugins/burocrata/views/helpers/buro_burocrata.php:1022 +#: /plugins/burocrata/views/helpers/buro_burocrata.php:1083 msgid "Burocrata: nothing found on autocomplete" msgstr "Nada encontrado." -#: /plugins/burocrata/views/helpers/buro_burocrata.php:1023 +#: /plugins/burocrata/views/helpers/buro_burocrata.php:1084 msgid "Burocrata: choose another related item" msgstr "Escolher um outro" -#: /plugins/burocrata/views/helpers/buro_burocrata.php:1024 +#: /plugins/burocrata/views/helpers/buro_burocrata.php:1085 msgid "Burocrata: Bring last item back" msgstr "Usar último item" -#: /plugins/burocrata/views/helpers/buro_burocrata.php:1561 +#: /plugins/burocrata/views/helpers/buro_burocrata.php:1644 msgid "Burocrata::orderdItensMenu - list caption:" msgstr "Adicionar:" -#: /plugins/burocrata/views/helpers/buro_burocrata.php:1567 +#: /plugins/burocrata/views/helpers/buro_burocrata.php:1650 msgid "Burocrata::orderdItensMenu - close list" msgstr "Fechar" -#: /plugins/burocrata/views/helpers/buro_burocrata.php:1669 +#: /plugins/burocrata/views/helpers/buro_burocrata.php:1752 msgid "Burocrata::orderedItensControls - up" msgstr "Mover para cima" -#: /plugins/burocrata/views/helpers/buro_burocrata.php:1675 +#: /plugins/burocrata/views/helpers/buro_burocrata.php:1758 msgid "Burocrata::orderedItensControls - down" msgstr "Mover para baixo" -#: /plugins/burocrata/views/helpers/buro_burocrata.php:1681 +#: /plugins/burocrata/views/helpers/buro_burocrata.php:1764 msgid "Burocrata::orderedItensControls - delete" msgstr "Excluir" -#: /plugins/burocrata/views/helpers/buro_burocrata.php:1687 +#: /plugins/burocrata/views/helpers/buro_burocrata.php:1772 msgid "Burocrata::orderedItensControls - duplicate" msgstr "Duplicar" -#: /plugins/burocrata/views/helpers/buro_burocrata.php:1693 +#: /plugins/burocrata/views/helpers/buro_burocrata.php:1779 msgid "Burocrata::orderedItensControls - edit" msgstr "Editar" -#: /plugins/burocrata/views/helpers/buro_burocrata.php:1835 +#: /plugins/burocrata/views/helpers/buro_burocrata.php:1973 msgid "Burocrata: view related data" msgstr "Ver dados completos" -#: /plugins/burocrata/views/helpers/buro_burocrata.php:1836 +#: /plugins/burocrata/views/helpers/buro_burocrata.php:1974 msgid "Burocrata: unlink related data" msgstr "Remover" -#: /plugins/burocrata/views/helpers/buro_burocrata.php:1837 +#: /plugins/burocrata/views/helpers/buro_burocrata.php:1975 msgid "Burocrata: confirm unlinking" msgstr "Deseja remover mesmo?" -#: /plugins/burocrata/views/helpers/buro_burocrata.php:2217 -msgid "The uploaded file is too large. (filesize > upload_max_filesize or filesize > Model::$validate definitions)" -msgstr "O arquivo enviado é muito grande." - -#: /plugins/burocrata/views/helpers/buro_burocrata.php:2218 -msgid "The uploaded file is too large. (filesize > post_max_size)" -msgstr "O arquivo enviado é muito grande." - -#: /plugins/burocrata/views/helpers/buro_burocrata.php:2285 +#: /plugins/burocrata/views/helpers/buro_burocrata.php:2420 msgid "Burocrata::inputUpload - Change file" msgstr "Alterar" -#: /plugins/burocrata/views/helpers/buro_burocrata.php:2313 +#: /plugins/burocrata/views/helpers/buro_burocrata.php:2453 msgid "Burocrata::inputUpload - Download file" msgstr "Baixar arquivo" -#: /plugins/burocrata/views/helpers/buro_burocrata.php:2317 +#: /plugins/burocrata/views/helpers/buro_burocrata.php:2455 msgid "Burocrata::inputUpload - File: " msgstr "Arquivo:" -#: /plugins/burocrata/views/helpers/buro_burocrata.php:2347 +#: /plugins/burocrata/views/helpers/buro_burocrata.php:2487 msgid "Burocrata::inputImage - Change image" msgstr "Alterar essa imagem" -#: /plugins/burocrata/views/helpers/buro_burocrata.php:2349 +#: /plugins/burocrata/views/helpers/buro_burocrata.php:2489 msgid "Burocrata::inputImage - Remove image" msgstr "Remover essa imagem" -#: /plugins/burocrata/views/helpers/buro_burocrata.php:2351 -msgid "The uploaded file is not a valid image file." -msgstr "O arquivo enviado deveria ser de imagem." - -#: /plugins/burocrata/views/helpers/buro_burocrata.php:2390 +#: /plugins/burocrata/views/helpers/buro_burocrata.php:2536 msgid "Burocrata::inputImage - or " msgstr " ou " -#: /plugins/burocrata/views/helpers/buro_burocrata.php:2469 +#: /plugins/burocrata/views/helpers/buro_burocrata.php:2617 msgid "Burocrata::inputTextile - Preview" msgstr "Visualizar" -#: /plugins/burocrata/views/helpers/buro_burocrata.php:2498 +#: /plugins/burocrata/views/helpers/buro_burocrata.php:2652 msgid "Burocrata::inputTextile - Add bold" msgstr "Negrito" -#: /plugins/burocrata/views/helpers/buro_burocrata.php:2499 +#: /plugins/burocrata/views/helpers/buro_burocrata.php:2653 msgid "Burocrata::inputTextile - Add italic" msgstr "Itálico" -#: /plugins/burocrata/views/helpers/buro_burocrata.php:2500 +#: /plugins/burocrata/views/helpers/buro_burocrata.php:2654 msgid "Burocrata::inputTextile - Add link" msgstr "Link" -#: /plugins/burocrata/views/helpers/buro_burocrata.php:2501 +#: /plugins/burocrata/views/helpers/buro_burocrata.php:2655 msgid "Burocrata::inputTextile - Add title" msgstr "Título" -#: /plugins/burocrata/views/helpers/buro_burocrata.php:2502 +#: /plugins/burocrata/views/helpers/buro_burocrata.php:2656 msgid "Burocrata::inputTextile - Add image" msgstr "Imagem" -#: /plugins/burocrata/views/helpers/buro_burocrata.php:2503 +#: /plugins/burocrata/views/helpers/buro_burocrata.php:2657 msgid "Burocrata::inputTextile - Add file" msgstr "Arquivo" -#: /plugins/burocrata/views/helpers/buro_burocrata.php:2504 +#: /plugins/burocrata/views/helpers/buro_burocrata.php:2658 msgid "Burocrata::inputTextile - Add superscript" msgstr "Sobrescrito" -#: /plugins/burocrata/views/helpers/buro_burocrata.php:2505 +#: /plugins/burocrata/views/helpers/buro_burocrata.php:2659 msgid "Burocrata::inputTextile - Add subscript" msgstr "Subscrito" -#: /plugins/burocrata/views/helpers/buro_burocrata.php:2520 +#: /plugins/burocrata/views/helpers/buro_burocrata.php:2674 msgid "Burocrata::_popupTextileLink - Instructions for link" msgstr " " -#: /plugins/burocrata/views/helpers/buro_burocrata.php:2521 +#: /plugins/burocrata/views/helpers/buro_burocrata.php:2675 msgid "Burocrata::_popupTextileLink - What is the text for this link" msgstr "Qual é o texto para este link?" -#: /plugins/burocrata/views/helpers/buro_burocrata.php:2522 +#: /plugins/burocrata/views/helpers/buro_burocrata.php:2676 msgid "Burocrata::_popupTextileLink - What is the URL of this link" msgstr "Qual é o endereço para o link?" -#: /plugins/burocrata/views/helpers/buro_burocrata.php:2523 +#: /plugins/burocrata/views/helpers/buro_burocrata.php:2677 msgid "Burocrata::_popupTextileLink - Title of link popup" msgstr "Link" -#: /plugins/burocrata/views/helpers/buro_burocrata.php:2555 +#: /plugins/burocrata/views/helpers/buro_burocrata.php:2709 msgid "Burocrata::_popupTextileTitle - Instructions for link" msgstr " " -#: /plugins/burocrata/views/helpers/buro_burocrata.php:2556 +#: /plugins/burocrata/views/helpers/buro_burocrata.php:2710 msgid "Burocrata::_popupTextileTitle - What is the type of this title" msgstr " Tipo do título" -#: /plugins/burocrata/views/helpers/buro_burocrata.php:2557 +#: /plugins/burocrata/views/helpers/buro_burocrata.php:2711 msgid "Burocrata::_popupTextileTitle - Title" msgstr " Título" -#: /plugins/burocrata/views/helpers/buro_burocrata.php:2558 +#: /plugins/burocrata/views/helpers/buro_burocrata.php:2712 msgid "Burocrata::_popupTextileTitle - Subtitle" msgstr " Título" -#: /plugins/burocrata/views/helpers/buro_burocrata.php:2559 +#: /plugins/burocrata/views/helpers/buro_burocrata.php:2713 msgid "Burocrata::_popupTextileTitle - What is the title" msgstr " Título" -#: /plugins/burocrata/views/helpers/buro_burocrata.php:2560 +#: /plugins/burocrata/views/helpers/buro_burocrata.php:2714 msgid "Burocrata::_popupTextileTitle - Title of title popup" msgstr " Título" -#: /plugins/burocrata/views/helpers/buro_burocrata.php:2605 +#: /plugins/burocrata/views/helpers/buro_burocrata.php:2759 msgid "Burocrata::_popupTextilePreview - Title of preview popup" msgstr " " -#: /plugins/burocrata/views/helpers/buro_burocrata.php:2630 +#: /plugins/burocrata/views/helpers/buro_burocrata.php:2784 msgid "Burocrata::_popupTextileFile - Title of `add file` popup" msgstr " Adição de arquivo" -#: /plugins/burocrata/views/helpers/buro_burocrata.php:2631 +#: /plugins/burocrata/views/helpers/buro_burocrata.php:2785 msgid "Burocrata::_popupTextileFile - Label of file input" msgstr " Arquivo:" -#: /plugins/burocrata/views/helpers/buro_burocrata.php:2669 +#: /plugins/burocrata/views/helpers/buro_burocrata.php:2823 msgid "Burocrata::_popupTextileImage - Title of `add image` popup" msgstr " Adição de imagem" -#: /plugins/burocrata/views/helpers/buro_burocrata.php:2670 +#: /plugins/burocrata/views/helpers/buro_burocrata.php:2824 msgid "Burocrata::_popupTextileImage - Label of file input" msgstr " Imagem:" +#: /plugins/burocrata/views/helpers/buro_captioner.php:55 +msgid "The uploaded file is too large. (filesize > upload_max_filesize or filesize > Model::$validate definitions)" +msgstr "O arquivo enviado é muito grande." + +#: /plugins/burocrata/views/helpers/buro_captioner.php:57 +msgid "The uploaded file is too large. (filesize > post_max_size)" +msgstr "O arquivo enviado é muito grande." + +#: /plugins/burocrata/views/helpers/buro_captioner.php:59 +msgid "The upload process could not be completed because the file was placed on a non-allowed directory." +msgstr "O local que o arquivo foi colocado não é permitido. Isso pode significar tentativa de burlar o sistema ou falha na configuração do servidor." + +#: /plugins/burocrata/views/helpers/buro_captioner.php:61 +msgid "The resource is blocked and the webserver can not work properly with it." +msgstr "Não foi possível ter acesso ao recurso enviado." + +#: /plugins/burocrata/views/helpers/buro_captioner.php:63 +msgid "The upload data does not define any type of resource" +msgstr "Os dados enviados não configuram um recurso que possa ser convertido em arquivo." + +#: /plugins/burocrata/views/helpers/buro_captioner.php:65 +msgid "Uploading file #{fileName}. Please, wait..." +msgstr "Enviando o arquivo \"#{fileName}\". Aguarde..." + +#: /plugins/burocrata/views/helpers/buro_captioner.php:73 +msgid "Cancel" +msgstr "Cancelar" + +#: /plugins/burocrata/views/helpers/buro_captioner.php:75 +msgid "Try again" +msgstr "Tentar novamente" + +#: /plugins/burocrata/views/helpers/buro_captioner.php:77 +msgid "Remove this file" +msgstr "Remover o arquivo" + +#: /plugins/burocrata/views/helpers/buro_captioner.php:79 +msgid "Really abort?" +msgstr "Deseja realmente cancelar o envio?" + +#: /plugins/burocrata/views/helpers/buro_captioner.php:81 +msgid "Really remove?" +msgstr "Você tem certeza que deseja remover o arquivo?" + +#: /plugins/burocrata/views/helpers/buro_captioner.php:83 +msgid "Something went wrong and the file was not sent." +msgstr "Algo deu errado ao enviar os dados. É provável que sua comunicação com o site esteja com problema." + +#: /plugins/burocrata/views/helpers/buro_captioner.php:85 +msgid "Something went wrong and the file was not sent. The server returned #{error}" +msgstr "Algo deu errado com o envio. O servidor retornou \"#{error}\"." + +#: /plugins/burocrata/views/helpers/buro_captioner.php:87 +msgid "The file #{filename} was successfully received." +msgstr "O arquivo \"#{filename}\" foi recebido com sucesso." + +#: /plugins/burocrata/views/helpers/buro_captioner.php:89 +msgid "Download the file" +msgstr "Baixar arquivo" + +#: /plugins/burocrata/views/helpers/buro_captioner.php:100 +msgid "The uploaded file is not a valid image file." +msgstr "O arquivo enviado deveria ser de imagem." + #~ msgid "Burocrata: default save button" #~ msgstr "Salvar" diff --git a/src/cake/app/plugins/burocrata/views/helpers/buro_burocrata.php b/src/cake/app/plugins/burocrata/views/helpers/buro_burocrata.php index 82ede28b..52f78110 100644 --- a/src/cake/app/plugins/burocrata/views/helpers/buro_burocrata.php +++ b/src/cake/app/plugins/burocrata/views/helpers/buro_burocrata.php @@ -12,29 +12,22 @@ * @link https://github.com/prefacedesign/jodeljodel Jodel Jodel public repository */ -/** - * Main Helper for burocrata plugin - * - * PHP versions 5 - * - * @package jodel - * @subpackage jodel.burocrata.views.helpers - */ App::import('Helper', 'Burocrata.XmlTag'); App::import('Lib', 'JjUtils.SecureParams'); - /** - * BuroOfficeBoy helper. + * Main Helper for burocrata plugin * - * Creates all javascript necessary for BuroBurocrataHelper work. + * PHP versions 5 * * @package jodel * @subpackage jodel.burocrata.views.helpers */ class BuroBurocrataHelper extends XmlTagHelper { - public $helpers = array('Html', 'Form', 'Ajax', 'Js' => 'prototype', 'Burocrata.BuroOfficeBoy', + public $helpers = array('Html', 'Form', 'Ajax', 'Js' => 'prototype', + 'Burocrata.BuroOfficeBoy', + 'Burocrata.BuroCaptioner', 'JjUtils.Jodel', 'Typographer.*TypeBricklayer' => array( 'name' => 'Bl', @@ -2351,22 +2344,23 @@ protected function _uploadParams($options) $gen_options = $options['options'] + $defaults; - // Temporary warning - if ($gen_options['model'] != 'JjMedia.SfilStoredFile') - { - trigger_error('BuroBurocrataHelper::_uploadParams() - Changing the upload model is not supported yet! Using the default.'); - $gen_options['model'] = 'JjMedia.SfilStoredFile'; - } - if (isset($file_input_options['error'])) { $gen_options['error'] = $file_input_options['error']; unset($file_input_options['error']); } - - $gen_options['error']['size'] = __d('burocrata', 'The uploaded file is too large. (filesize > upload_max_filesize or filesize > Model::$validate definitions)', true); - $gen_options['error']['post_max_size'] = __d('burocrata', 'The uploaded file is too large. (filesize > post_max_size)', true); - + + $value = $this->Form->value($file_input_options['fieldName']); + if (!empty($value)) + { + $SfilStoredFile = ClassRegistry::init('JjMedia.SfilStoredFile'); + $SfilStoredFile->id = $value; + $gen_options['aditionalData']['dlurl'] = $this->Bl->fileURL($value, '', true); + $gen_options['aditionalData']['filename'] = $SfilStoredFile->field('original_filename'); + } + + $this->BuroCaptioner->addCaptions('upload'); + return compact('gen_options', 'file_input_options'); } @@ -2437,7 +2431,8 @@ public function inputUpload($options) $ids = array('act', 'prv', 'lnk', 'chg'); foreach ($ids as $id) ${$id.'_id'} = $id . $gen_options['baseID']; - + + $fileCaption = __d('burocrata','Burocrata::inputUpload - File: ', true); $out = ''; if (empty($gen_options['callbacks']['onSave']['js'])) @@ -2448,23 +2443,32 @@ public function inputUpload($options) $gen_options['callbacks']['onRestart']['js'] = ''; $gen_options['callbacks']['onRestart']['js'] .= "$('{$act_id}').hide(); $('{$prv_id}').hide();"; - $value = $this->Form->value($file_input_options['fieldName']); - - $script = ''; - if (empty($value)) - $script .= "$('{$act_id}').hide(); $('{$prv_id}').hide();"; - $script .= "$('{$chg_id}').observe('click', function(ev){ev.stop(); BuroCR.get('{$gen_options['baseID']}').again();});"; - $out .= $this->BuroOfficeBoy->addHtmlEmbScript($script); + $out .= $this->BuroOfficeBoy->addHtmlEmbScript( + "$('{$chg_id}').observe('click', function(ev){ev.stop(); BuroCR.get('{$gen_options['baseID']}').again();});" + . "$('{$act_id}').hide(); $('{$prv_id}').hide();" + ); + + if (!isset($gen_options['callbacks']['ajax']['onSave']['js'])) + $gen_options['callbacks']['ajax']['onSave']['js'] = ''; + $gen_options['callbacks']['ajax']['onSave']['js'] .= "upload.addCaption(BuroCaption.get('upload', 'transfer_ok', {filename: upload.getFileName()}));"; + + if (!empty($gen_options['aditionalData']['dlurl'])) + { + if (!isset($gen_options['callbacks']['ajax']['onLoad']['js'])) + $gen_options['callbacks']['ajax']['onLoad']['js'] = ''; + $gen_options['callbacks']['ajax']['onLoad']['js'] .= "upload.addCaption('$fileCaption ' + upload.getFileName());"; + } $out .= $this->_upload($gen_options, $file_input_options); - + + $exists = !empty($gen_options['aditionalData']['dlurl']); // Div for previews $out .= $this->Bl->sdiv(array('id' => $prv_id)); $filename = __d('burocrata','Burocrata::inputUpload - Download file', true); - $htmlAttributes = array('id' => $lnk_id); - if (!empty($value)) - $htmlAttributes['href'] = $this->Bl->fileURL($value, '', true); - $out .= $this->Bl->pDry(__d('burocrata','Burocrata::inputUpload - File: ', true) . $this->Bl->a($htmlAttributes, array(), $filename)); + $out .= $this->Bl->pDry( + "$fileCaption " . + $this->Bl->a(array('id' => $lnk_id, 'href' => $exists ? $gen_options['aditionalData']['dlurl'] : ''), array(), $filename) + ); $out .= $this->Bl->ediv(); // Div for actions ID must be `'act' . $gen_options['baseID']` @@ -2497,10 +2501,8 @@ public function inputImage($options) $gen_options['change_file_text'] = __d('burocrata','Burocrata::inputImage - Change image', true); if (empty($gen_options['remove_file_text'])) $gen_options['remove_file_text'] = __d('burocrata','Burocrata::inputImage - Remove image', true); - - $gen_options['error'] += array('validImage' => __d('burocrata','The uploaded file is not a valid image file.',true)); - - $value = $this->Form->value($file_input_options['fieldName']); + + $this->BuroCaptioner->addCaptions('imageUpload'); $ids = array('act', 'prv', 'img', 'chg', 'rmv'); foreach ($ids as $id) @@ -2511,30 +2513,34 @@ public function inputImage($options) if (empty($gen_options['callbacks']['onSave']['js'])) $gen_options['callbacks']['onSave']['js'] = ''; $gen_options['callbacks']['onSave']['js'] .= "$('{$img_id}').src = ''; $('{$img_id}').writeAttribute({src: json.url, alt: json.filename}); $('{$act_id}').show(); $('{$prv_id}').show();"; - if (empty($gen_options['callbacks']['onRestart']['js'])) $gen_options['callbacks']['onRestart']['js'] = ''; $gen_options['callbacks']['onRestart']['js'] .= "$('{$act_id}').hide(); $('{$prv_id}').hide();"; - - $script = ''; - $script .= "$('{$chg_id}').observe('click', function(ev){ev.stop(); BuroCR.get('{$gen_options['baseID']}').again();});"; - $script .= "$('{$rmv_id}').observe('click', function(ev){ev.stop(); BuroCR.get('{$gen_options['baseID']}').again(true);});"; + + if (empty($gen_options['callbacks']['ajax']['onSave']['js'])) + $gen_options['callbacks']['ajax']['onSave']['js'] = ''; + $gen_options['callbacks']['ajax']['onSave']['js'] .= "$('{$img_id}').src = json.dlurl; $('{$prv_id}').show();"; + if (empty($gen_options['callbacks']['ajax']['onRestart']['js'])) + $gen_options['callbacks']['ajax']['onRestart']['js'] = ''; + $gen_options['callbacks']['ajax']['onRestart']['js'] .= "$('{$prv_id}').hide();"; + + $out .= $this->BuroOfficeBoy->addHtmlEmbScript( + "$('{$chg_id}').observe('click', function(ev){ev.stop(); BuroCR.get('{$gen_options['baseID']}').again();});" + . "$('{$rmv_id}').observe('click', function(ev){ev.stop(); BuroCR.get('{$gen_options['baseID']}').again(true);});" + . "$('{$act_id}').hide();" + ); $gen_options['model'] = 'JjMedia.SfilImageFile'; - - $out .= $this->BuroOfficeBoy->addHtmlEmbScript($script); $out .= $this->_upload($gen_options, $file_input_options); // Div for previews - $out .= $this->Bl->sdiv(array('id' => $prv_id, 'style' => empty($value) ? 'display:none;' : '')); - $url = ''; - if (!empty($value)) - $url = $this->Bl->imageURL($value, $gen_options['version']); - $out .= $this->Bl->img(array('id' => $img_id, 'alt' => '', 'src' => $url)); + $exists = !empty($gen_options['aditionalData']['dlurl']); + $out .= $this->Bl->sdiv(array('id' => $prv_id, 'style' => $exists ? '' : 'display:none;')); + $out .= $this->Bl->img(array('id' => $img_id, 'alt' => '', 'src' => $exists ? $gen_options['aditionalData']['dlurl'] : '')); $out .= $this->Bl->ediv(); - + // Div for actions ID must be `'act' . $gen_options['baseID']` - $out .= $this->Bl->sdiv(array('id' => $act_id, 'style' => empty($value) ? 'display:none;' : '')); + $out .= $this->Bl->sdiv(array('id' => $act_id, 'style' => $exists ? '' : 'display:none;')); $change_link = $this->Bl->a(array('href' => '#', 'id' => $chg_id), array(), $gen_options['change_file_text']); $remove_link = $this->Bl->a(array('href' => '#', 'id' => $rmv_id), array(), $gen_options['remove_file_text']); $out .= $this->Bl->pDry($change_link . __d('burocrata','Burocrata::inputImage - or ', true) . $remove_link); diff --git a/src/cake/app/plugins/burocrata/views/helpers/buro_captioner.php b/src/cake/app/plugins/burocrata/views/helpers/buro_captioner.php new file mode 100644 index 00000000..ab054bab --- /dev/null +++ b/src/cake/app/plugins/burocrata/views/helpers/buro_captioner.php @@ -0,0 +1,102 @@ +{"_$type"}(); + } + } + +/** + * Adds all captions for upload input + * + * @access protected + */ + protected function _upload() + { + $this->BuroOfficeBoy->addCaption('upload', 'error_size', + __d('burocrata', 'The uploaded file is too large. (filesize > upload_max_filesize or filesize > Model::$validate definitions)', true)); + $this->BuroOfficeBoy->addCaption('upload', 'error_post_max_size', + __d('burocrata', 'The uploaded file is too large. (filesize > post_max_size)', true)); + $this->BuroOfficeBoy->addCaption('upload', 'error_location', + __d('burocrata', 'The upload process could not be completed because the file was placed on a non-allowed directory.', true)); + $this->BuroOfficeBoy->addCaption('upload', 'error_access', + __d('burocrata', 'The resource is blocked and the webserver can not work properly with it.', true)); + $this->BuroOfficeBoy->addCaption('upload', 'error_resource', + __d('burocrata', 'The upload data does not define any type of resource', true)); + $this->BuroOfficeBoy->addCaption('upload', 'sending', + __d('burocrata', 'Uploading file #{fileName}. Please, wait...', true)); + //$this->BuroOfficeBoy->addCaption('upload', 'hours_left', + // __d('burocrata', 'Faltando #{hours} horas', true)); + //$this->BuroOfficeBoy->addCaption('upload', 'minutes_left', + // __d('burocrata', 'Faltando #{minutes} minutos', true)); + //$this->BuroOfficeBoy->addCaption('upload', 'seconds_left', + // __d('burocrata', 'Faltando #{seconds} segundos', true)); + $this->BuroOfficeBoy->addCaption('upload', 'cancel', + __d('burocrata', 'Cancel', true)); + $this->BuroOfficeBoy->addCaption('upload', 'try_again', + __d('burocrata', 'Try again', true)); + $this->BuroOfficeBoy->addCaption('upload', 'remove', + __d('burocrata', 'Remove this file', true)); + $this->BuroOfficeBoy->addCaption('upload', 'really_abort', + __d('burocrata', 'Really abort?', true)); + $this->BuroOfficeBoy->addCaption('upload', 'really_remove', + __d('burocrata', 'Really remove?', true)); + $this->BuroOfficeBoy->addCaption('upload', 'generic_error', + __d('burocrata', 'Something went wrong and the file was not sent.', true)); + $this->BuroOfficeBoy->addCaption('upload', 'error_with_server_resp', + __d('burocrata', 'Something went wrong and the file was not sent. The server returned #{error}', true)); + $this->BuroOfficeBoy->addCaption('upload', 'transfer_ok', + __d('burocrata', 'The file #{filename} was successfully received.', true)); + $this->BuroOfficeBoy->addCaption('upload', 'get_file', + __d('burocrata', 'Download the file', true)); + } + +/** + * Complement for image upload field + * + * @access + */ + protected function _imageUpload() + { + $this->BuroOfficeBoy->addCaption('upload', 'error_validImage', + __d('burocrata','The uploaded file is not a valid image file.',true)); + } +} diff --git a/src/cake/app/plugins/burocrata/views/helpers/buro_office_boy.php b/src/cake/app/plugins/burocrata/views/helpers/buro_office_boy.php index 711f85eb..0727d2a4 100644 --- a/src/cake/app/plugins/burocrata/views/helpers/buro_office_boy.php +++ b/src/cake/app/plugins/burocrata/views/helpers/buro_office_boy.php @@ -12,15 +12,6 @@ * @link https://github.com/prefacedesign/jodeljodel Jodel Jodel public repository */ -/** - * Office boy Helper for burocrata. - * - * PHP versions 5 - * - * @package jodel - * @subpackage jodel.burocrata.views.helpers - */ - /** * BuroOfficeBoy helper. * @@ -40,6 +31,17 @@ class BuroOfficeBoyHelper extends AppHelper */ public $helpers = array('Html', 'Ajax', 'Js' => 'prototype'); +/** + * List of captions for JS + * + * This variable holds a list of captions that will or may be used by the Javascript + * for construct some interface items. + * + * @access protected + * @var array + */ + protected $captions = array(); + /** * Callbacks template * @@ -95,6 +97,16 @@ class BuroOfficeBoyHelper extends AppHelper 'onRestart' => 'function(){%s}', 'onError' => 'function(code, error, json){%s}' ), + 'upload_ajax' => array( + 'onLoad' => 'function(upload){%s}', + 'onStart' => 'function(upload){%s}', + 'onComplete' => 'function(upload, json){%s}', + 'onPieceSent' => 'function(upload, json){%s}', + 'onReject' => 'function(upload, json, saved){%s}', + 'onSave' => 'function(upload, json, saved){%s}', + 'onRestart' => 'function(upload){%s}', + 'onError' => 'function(upload, json){%s}' + ), 'listOfItems' => array( 'onShowForm' => 'function(form){%s}', 'onAction' => 'function(action, id, content_type){%s}', @@ -115,6 +127,21 @@ class BuroOfficeBoyHelper extends AppHelper */ protected $scripts = array(); +/** + * Boolean variable used to tracking if the layout was rendered + * + * @access protected + * @var boolean + */ + protected $rendered = false; + +/** + * Before render logic + * + * This method links some script files to the HTML + * + * @access public + */ public function beforeRender() { if (!$this->Ajax->isAjax() && ClassRegistry::getObject('view')) @@ -131,7 +158,9 @@ public function beforeRender() } /** - * afterRender callback used for print automagically all created scripts on HTML + * After render logic + * + * This callback is used for automagically print all created scripts on HTML * when it is not a Ajax request * * @access public @@ -141,14 +170,61 @@ public function afterRender() $View = ClassRegistry::getObject('view'); if ($View && !$this->Ajax->isAjax()) { - $this->Html->scriptBlock('var debug = ' . Configure::read() . ';', array('inline' => false)); + $preScript = array(); + $preScript[] = 'var debug = ' . Configure::read() . ';'; + + // Ajax calls will handle captions on JsonView or directly on View + if (empty($this->captions)) + $preScript[] = 'var buroCaptions = {};'; + else + $preScript[] = 'var buroCaptions = '.$this->Js->object($this->captions).';'; $script = implode("\n", $this->scripts); if (Configure::read('debug')) - $script = sprintf('try{ %s }catch(e){ console.log(e); }', $script); - - $View->addScript($this->Html->scriptBlock($this->Js->domReady($script))); + $script = sprintf('try{ %s }catch(e){ console.error(e); }', $script); + + $script = implode("\n", $preScript) . "\n" . $this->Js->domReady($script); + + $View->addScript($this->Html->scriptBlock($script)); } + + $this->rendered = true; + } + +/** + * Add caption for JS interface + * + * Those captions will be available using the BuroCaption instance on JS + * + * @access public + */ + public function addCaption($space, $key, $caption = '') + { + $this->captions[$space][$key] = $caption; + } + +/** + * Returns all caption structure + * + * @access public + */ + public function getAllCaptions($flush = true) + { + $captions = $this->captions; + if ($flush) + $this->flushCaptions(); + + return $captions; + } + +/** + * Empties all registered captions + * + * @access public + */ + public function flushCaptions() + { + $this->captions = array(); } /** @@ -300,20 +376,37 @@ public function listOfItems($options) */ public function upload($options) { - $defaults = array('callbacks' => array(), 'baseID' => uniqid(), 'url' => '', 'error' => array()); + $defaults = array('baseID' => uniqid(), 'url' => ''); extract(am($defaults, $options)); unset($defaults); - if (!empty($error)) $error = $this->Js->object($error); - else $error = '{}'; - - if (!empty($parameters)) $parameters = $this->Js->object($parameters); - else $parameters = '{}'; - - $script = sprintf("new BuroUpload('%s', '%s', %s, %s)", $baseID, $url, $error, $parameters); - if(!empty($callbacks) && is_array($callbacks)) - $script .= sprintf('.addCallbacks(%s)', $this->formatCallbacks('upload', $callbacks)); + if (empty($parameters)) $parameters = '{}'; + else $parameters = $this->Js->object($parameters); + + if (empty($aditionalData)) $aditionalData = '{}'; + else $aditionalData = $this->Js->object($aditionalData); + $script = sprintf("new BuroUploadGeneric('%s', '%s', %s, %s)", $baseID, $url, $parameters, $aditionalData); + if(!empty($callbacks)) + { + if (isset($callbacks['ajax'])) + { + $script .= sprintf(".addCallbacks('ajax', %s)", $this->formatCallbacks('upload_ajax', $callbacks['ajax'])); + unset($callbacks['ajax']); + } + + $classic = array(); + if (isset($callbacks['classic'])) + { + $classic = $callbacks['classic']; + unset($callbacks['classic']); + } + + $classic += $callbacks; + if (!empty($callbacks)) + $script .= sprintf(".addCallbacks('classic', %s)", $this->formatCallbacks('upload', $classic)); + } + return $this->addHtmlEmbScript($script); } @@ -368,8 +461,10 @@ public function color($options) */ public function addHtmlEmbScript($script) { - if($this->Ajax->isAjax()) + if ($this->Ajax->isAjax()) return $this->Html->scriptBlock($script); + elseif ($this->rendered) + return $this->Html->scriptBlock($this->Js->domReady($script)); else $this->scripts[] = $script; } diff --git a/src/cake/app/plugins/burocrata/webroot/js/burocrata.js b/src/cake/app/plugins/burocrata/webroot/js/burocrata.js index 0698d87a..05caf707 100644 --- a/src/cake/app/plugins/burocrata/webroot/js/burocrata.js +++ b/src/cake/app/plugins/burocrata/webroot/js/burocrata.js @@ -49,6 +49,60 @@ var BuroCR = new (Class.create(Hash, { }))(); +/** + * Caption manager + * + * BuroCaption is an instace at window scope that is used to retrieve + * a caption given a namespace and a key. + * + * If either do not exists at the calling time, than it issues an error + * + * @access public + */ +var BuroCaption = new (Class.create({ + initialize: function() + { + }, + get: function(space, key, interpolateData) + { + if (!this.isSet(space, key)) + throw "BuroCaption::get() - Pair space/key given ("+space+"/"+key+") is not set."; + + var caption = buroCaptions[space][key]; + if (typeof interpolateData == 'object') + caption = caption.interpolate(interpolateData); + + return caption; + }, + isSet: function(space, key) + { + if (Object.isUndefined(buroCaptions[space])) + return false; + if (Object.isUndefined(buroCaptions[space][key])) + return false; + return true; + }, + merge: function(data) + { + if (typeof data != 'object') + throw "BuroCaption::merge() - Data must be an object"; + + for (space in data) + { + if (typeof data[space] != 'object') + throw "BuroCaption::merge() - Data inside each space must be object"; + + for (key in data[space]) + { + if (!buroCaptions[space]) + buroCaptions[space] = {}; + buroCaptions[space][key] = data[space][key]; + } + } + } +}))(); + + /** * Abstract class that implements the behaviour of callbacks * with the methods `addCallbacks` and `trigger` @@ -589,10 +643,17 @@ var BuroAjax = Class.create(BuroCallbackable, { this.trigger('onError', E_NOT_JSON); if (debug != 0 && !this.fulldebug) this.dumpResquest(re); - } else if (json.error != false) { - this.trigger('onError', E_JSON, json.error, json); } else { - this.trigger('onSuccess', re, json); + if (json.extraCaptions) { + BuroCaption.merge(json.extraCaptions); + delete json.extraCaptions; + } + + if (json.error != false) { + this.trigger('onError', E_JSON, json.error, json); + } else { + this.trigger('onSuccess', re, json); + } } }, requestOnFailure: function(re) @@ -1793,9 +1854,36 @@ var BuroEditableList = Class.create(BuroCallbackable, { }); +var BuroUploadGeneric = Class.create({ + initialize: function(id_base, url, parameters, aditionalData) + { + this.ajax_upload = ( + 'multiple' in new Element('input', {type: 'file'}) && + !Object.isUndefined(File) && + !Object.isUndefined((new XMLHttpRequest()).upload) + ); + + if (this.ajax_upload) + { + this.object = new BuroAjaxUpload(this, id_base, url, parameters, aditionalData); + return; + } + + this.object = new BuroUpload(id_base, url, parameters); + }, + addCallbacks: function(type, callbacks) + { + if (type == 'ajax' && this.ajax_upload) + this.object.addCallbacks(callbacks); + else if (type == 'classic' && !this.ajax_upload) + this.object.addCallbacks(callbacks); + + return this; + } +}); /** - * + * Classic "Ajax" upload using the iframe method * * Callbacks: * - `onStart` function (input){} @@ -1807,7 +1895,7 @@ var BuroEditableList = Class.create(BuroCallbackable, { * @access public */ var BuroUpload = Class.create(BuroCallbackable, { - initialize: function(id_base, url, errors, parameters) + initialize: function(id_base, url, parameters) { if (Prototype.Browser.IE) { @@ -1821,11 +1909,10 @@ var BuroUpload = Class.create(BuroCallbackable, { this.uploading = false; this.id_base = id_base; this.url = url; - this.errors = errors; this.parameters = $H(parameters); - + BuroCR.set(this.id_base, this); - + this.iframe = new Element('iframe', { name: 'if'+this.id_base, id: 'if'+this.id_base, @@ -1872,6 +1959,11 @@ var BuroUpload = Class.create(BuroCallbackable, { this.tmp_input.observe('change', this.submit.bind(this)); this.master_input.insert({after: this.tmp_input}); } + + if (!this.hidden_input.value.blank()) + { + ['act' + this.id_base, 'prv' + this.id_base].each(Element.show); + } }, submit: function() { @@ -1953,17 +2045,22 @@ var BuroUpload = Class.create(BuroCallbackable, { }, rejected: function() { + var errorName, errorMsg = []; this.hidden_input.value = ''; - if (this.responseJSON.validationErrors && this.errors) + if (typeof this.responseJSON.validationErrors == 'object') { - if (this.errors[$H(this.responseJSON.validationErrors).values()[0]]) - this.responseJSON.error = this.errors[$H(this.responseJSON.validationErrors).values()[0]]; - else - this.responseJSON.error = $H(this.responseJSON.validationErrors).values()[0]; + for (errorName in this.responseJSON.validationErrors) + { + errorName = this.responseJSON.validationErrors[errorName]; + if (BuroCaption.isSet('upload', 'error_'+errorName)) + errorMsg.push(BuroCaption.get('upload', 'error_'+errorName)) + else + errorMsg.push(errorName); + } } this.div_hidden.up().addClassName('error'); - this.div_hidden.up().insert(new Element('div', {className:'error-message'}).update(this.responseJSON.error)); + this.div_hidden.up().insert(new Element('div', {className:'error-message'}).update(errorMsg.join('
'))); this.trigger('onReject', this.tmp_input, this.responseJSON, this.responseJSON.saved); @@ -1972,6 +2069,444 @@ var BuroUpload = Class.create(BuroCallbackable, { }); +/** + * HTML 5 upload, using XMLHttpRequest + * + * Callbacks: + * - `onStart` function(upload){%s} + * - `onComplete` function(upload, json){%s} + * - `onPieceSent` function(upload, json){%s} + * - `onReject` function(upload, json, saved){%s} + * - `onRestart` function(upload){%s} + * - `onError` function(upload, json){%s} + * + * @access public + */ +var BuroAjaxUpload = Class.create(BuroCallbackable, { + chunkSize: 1024*1024, // 1M + MAX_TRIES: 5, + ST_READY: 1 , ST_UPLOADING: 2, ST_DONE: 3, ST_ERROR: 4, ST_INVALIDATED: 5, + initialize: function(parent, id_base, url, parameters, additionalData) + { + this.parent = parent; + this.id_base = id_base; + this.url = url; + this.parameters = null; + this.additionalData = additionalData; + + if (typeof parameters == 'object') + this.parameters = parameters; + + BuroCR.set(this.id_base, this); + + if (document.loaded) this.loaded.bind(this).defer(); + else document.observe('dom:loaded', this.loaded.bind(this)) + }, + loaded: function() + { + this.cancelLink = new Element('a', {href: '#'}).update(BuroCaption.get('upload', 'cancel')); + this.cancelLink.on('click', function(ev){ ev.stop(); this.abort(); }.bind(this)); + this.tryAgainLink = new Element('a', {href: '#'}).update(BuroCaption.get('upload', 'try_again')); + this.tryAgainLink.on('click', this.again.bind(this)); + this.removeFileLink = new Element('a', {href: '#'}).update(BuroCaption.get('upload', 'remove')); + this.removeFileLink.on('click', this.removeFile.bind(this)); + this.getFileLink = new Element('a', {href: ''}).update(BuroCaption.get('upload', 'get_file')); + + this.controls = new Element('div', {className: 'upload_control'}); + this.controls.insert(this.cancelLink).insert(' ') + .insert(this.tryAgainLink).insert(' ') + .insert(this.removeFileLink).insert(' ') + .insert(this.getFileLink); + + this.progress_bar = new Element('div', {className: 'progress_bar'}); + this.progress_bar.insert(new Element('div', {className: 'filling'})); + this.progress_bar.insert(new Element('span', {className: 'label'})); + + this.upload_input = $('mi'+this.id_base); + this.upload_input.insert({ after: this.controls }); + this.upload_input.insert({ after: this.progress_bar }); + this.upload_input.on('change', this.inputChange.bind(this)); + + this.handleAbortBinded = this.handleAbort.bind(this); + this.handleErrorBinded = this.handleError.bind(this); + this.handleProgressBinded = this.handleProgress.bind(this); + this.uploadStatusChangeBinded = this.uploadStatusChange.bind(this); + + this.hidden_input = $('hi' + this.id_base); + + this.reset(); + + if (!this.hidden_input.value.blank()) + { + this.upload_input.hide(); + this.finish(); + } + this.trigger('onLoad', this); + }, + reset: function() + { + this.json = this.hash = this.startTime = this.file = null; + this.currentByte = this.errorCount = 0; + this.aborted = false; + this.state = this.ST_READY; + + this.upload_input.show().value = ''; + if (this.upload_input.up('.input')) + this.upload_input.up('.input').removeClassName('error').select('.error-message').invoke('remove'); + this.progress_bar.hide(); + + this.clearCaption().clearXHR().controlControls(); + }, + addCaption: function(caption) + { + this.clearCaption(); + this.upload_input.insert({ + after: this.caption = (new Element('span')).insert(caption) + }); + }, + clearCaption: function() + { + if (this.caption) + { + this.caption.remove(); + this.caption = null; + } + return this; + }, + clearXHR: function() + { + if (this.xhr) + { + this.xhr.upload.removeEventListener('error', this.handleErrorBinded); + this.xhr.upload.removeEventListener('progress', this.handleProgressBinded); + this.xhr.upload.removeEventListener('abort', this.handleAbortBinded); + this.xhr.onreadystatechange = null; + this.xhr = null; + } + return this; + }, + controlControls: function() + { + this.tryAgainLink.hide(); + this.removeFileLink.hide(); + this.cancelLink.hide(); + this.getFileLink.hide(); + switch (this.state) + { + case this.ST_READY: + break; + + case this.ST_UPLOADING: + this.cancelLink.show(); + break; + + case this.ST_DONE: + this.removeFileLink.show(); + this.getFileLink.show(); + break; + + case this.ST_ERROR: + this.tryAgainLink.show(); + break; + } + }, + abort: function() + { + if (this.xhr && this.xhr.readyState != 4) + { + this.xhr.onreadystatechange = function() {}; + this.xhr.abort(); + this.clearXHR(); + } + + if (!confirm(BuroCaption.get('upload', 'really_abort'))) + { + this.uploadOnePiece(); + return; + } + + this.aborted = true; + this.handleAbort(); + }, + again: function(ev) + { + if (ev) ev.stop(); + + this.reset(); + this.trigger('onRestart', this); + }, + removeFile: function(ev) + { + ev.stop(); + if (confirm(BuroCaption.get('upload', 'really_remove'))) + this.again(); + }, + inputChange: function(ev) + { + if (this.state != this.ST_READY) + return; + + if (!this.upload_input.files.length) + { + this.reset(); + } + else if (this.upload_input.files.length == 1) + { + var file = this.upload_input.files[0]; + + this.reset(); + this.file = file; + + this.upload_input.hide(); + this.addCaption(BuroCaption.get('upload', 'sending', {fileName: this.getFileName()})); + + this.startTime = new Date().getTime(); + this.controls.setStyle({visibility: 'visible'}); + + this.trigger('onStart', this); + this.uploadOnePiece(); + } + }, + getFileSize: function() + { + if (this.file) + return this.file.size || this.file.fileSize; + return null; + }, + getFileName: function() + { + if (this.file) + return this.file.name || this.file.fileName; + else if (this.additionalData.filename) + return this.additionalData.filename; + return null; + }, + uploadOnePiece: function() + { + if (this.xhr) + return ; + + var chunk, form; + + this.endByte = Math.min(this.currentByte + this.chunkSize, this.getFileSize()); + this.isLast = this.endByte == this.getFileSize(); + + if (this.file.mozSlice) + chunk = this.file.mozSlice(this.currentByte, this.endByte); + else if (this.file.webkitSlice) + chunk = this.file.webkitSlice(this.currentByte, this.endByte); + else if (this.file.slice) + chunk = this.file.slice(this.currentByte, this.endByte - this.currentByte); + + if (!chunk) + throw "Chunk is empty"; + + this.xhr = new XMLHttpRequest(); + this.xhr.upload.addEventListener('error', this.handleErrorBinded); + this.xhr.upload.addEventListener('progress', this.handleProgressBinded); + this.xhr.onreadystatechange = this.uploadStatusChangeBinded; + + this.xhr.open('POST', this.url, true); + this.xhr.setRequestHeader('Cache-Control', 'no-cache'); + this.xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest'); + this.xhr.setRequestHeader('X-Uploader-Start-Byte', this.currentByte); + this.xhr.setRequestHeader('X-Uploader-Is-Last', this.isLast ? 'yes' : 'no'); + this.xhr.setRequestHeader('X-Uploader-Chunk-Size', this.endByte-this.currentByte); + + form = new FormData(); + form.append(this.upload_input.name, chunk); + for (fieldName in this.parameters) + form.append(fieldName, this.parameters[fieldName]); + + if (this.hash) + form.append('data[hash]', this.hash); + + if (this.isLast) + form.append('data[original_name]', this.getFileName()); + + this.state = this.ST_UPLOADING; + this.controlControls(); + + this.xhr.send(form); + }, + uploadStatusChange: function() + { + if (this.xhr.readyState != 4) + return; + + if (this.xhr.status != 200) + this.handleError(); + + this.requestEnded(); + + if (this.isLast) + this.trigger('onComplete', this, this.json); + }, + requestEnded: function() + { + this.json = false; + if (!this.xhr) + return; + + if (this.xhr.response.isJSON()) + this.json = this.xhr.response.evalJSON(); + + if (this.aborted) + return this.handleAbort(); + + if (!this.json) + return this.handleError(); + + if (this.json.hash) + this.hash = this.json.hash; + + if (this.json.error) + { + if (this.json.error == 'chunk-doesnt-fit' && this.json.nextByte) + { + this.currentByte = this.json.nextByte; + // Trying to sync the JS with the server (tries 5 times, and then, aborts it) + } + return this.handleError(); + } + + if (this.isLast) + this.renderProgress(100); + + if (this.json.validationErrors) + { + this.state = this.ST_INVALIDATED; + this.handleError() + this.clearXHR(); + return; + } + + this.currentByte = this.endByte; + this.clearXHR(); + this.errorCount = 0; + + if (!this.isLast) + { + this.trigger('onPieceSent', this); + this.uploadOnePiece(); + } + else if (this.state == this.ST_UPLOADING) + { + this.hidden_input.value = this.json.saved; + this.trigger('onSave', this, this.json); + this.finish(); + } + }, + handleError: function(ev) + { + if (this.state == this.ST_ERROR) + return; + + if (this.aborted) + return this.handleAbort(); + + if (this.state == this.ST_UPLOADING) + { + this.errorCount++; + if (this.errorCount < this.MAX_TRIES) + { + this.clearXHR(); + this.uploadOnePiece(); + return; + } + } + + this.renderError(); + + this.state = this.ST_ERROR; + this.controlControls(); + if (this.json && this.json.validationErrors) + this.trigger('onReject', this, this.json, false); + else + this.trigger('onError', this, this.json); + }, + handleProgress: function(ev) + { + this.renderProgress((this.currentByte + ev.loaded)/this.getFileSize()*99); + }, + handleAbort: function(ev) + { + this.reset(); + this.controlControls(); + }, + finish: function() + { + if (this.json && this.json.dlurl) + this.getFileLink.href = this.json.dlurl; + else if (this.additionalData.dlurl) + this.getFileLink.href = this.additionalData.dlurl; + else + throw "BuroAjaxUpload.finish() called, but not seems to be finished."; + + this.state = this.ST_DONE; + this.controlControls(); + }, + renderProgress: function(progress) + { + var percent = Math.round(progress) + '%', + timeTaken = new Date().getTime() - this.startTime, + timeLeft = (timeTaken / (progress/100)) - timeTaken, + formatedTime = new Date(); + + if (false) + { + formatedTime.setHours(0,0,0,timeLeft); + if (formatedTime.getHours()) + formatedTime = BuroCaption.get('upload', 'hours_left', {hours: formatedTime.getHours() + ':' + formatedTime.getMinutes()}); + else if (formatedTime.getMinutes()) + formatedTime = BuroCaption.get('upload', 'minutes_left', {minutes: formatedTime.getMinutes() + ':' + formatedTime.getSeconds()}); + else if (formatedTime.getSeconds()) + formatedTime = BuroCaption.get('upload', 'seconds_left', {seconds: formatedTime.getSeconds()}); + else + formatedTime = false; + + console.log(formatedTime); + } + + this.progress_bar.down('.filling').setStyle({width: percent}) + this.progress_bar.down('.label').update(percent); + + if (timeLeft > 2000) + this.progress_bar.show(); + }, + renderError: function() + { + var errorName, errorMsg = []; + if (typeof this.json.validationErrors == 'object') + { + for (errorName in this.json.validationErrors) + { + errorName = this.json.validationErrors[errorName]; + if (BuroCaption.isSet('upload', 'error_'+errorName)) + errorMsg.push(BuroCaption.get('upload', 'error_'+errorName)) + else + errorMsg.push(errorName); + } + } + + if (this.json.error) + { + if (BuroCaption.isSet('upload', 'error_'+errorName)) + errorMsg.push(BuroCaption.get('upload', 'error_'+errorName)) + else if (BuroCaption.isSet('upload', 'error_with_server_resp')) + errorMsg.push(BuroCaption.get('upload', 'error_with_server_resp', this.json)); + } + + if (!errorMsg.length) + errorMsg.push(BuroCaption.get('upload', 'generic_error')); + + this.upload_input.up().up().addClassName('error'); + this.controls.insert({ + before: new Element('div', {className:'error-message'}).update(errorMsg.join('
')) + }); + } +}); + /** * diff --git a/src/cake/app/plugins/content_stream/models/behaviors/cs_content_stream_holder.php b/src/cake/app/plugins/content_stream/models/behaviors/cs_content_stream_holder.php index dcd8cfe6..b4dca697 100644 --- a/src/cake/app/plugins/content_stream/models/behaviors/cs_content_stream_holder.php +++ b/src/cake/app/plugins/content_stream/models/behaviors/cs_content_stream_holder.php @@ -153,16 +153,9 @@ function setup(&$Model, $options) */ function beforeSave(&$Model) { - if (empty($Model->data[$Model->alias][$Model->primaryKey])) + if (!$Model->exists()) { - $dbo = $Model->getDataSource(); - - if (!$dbo->_transactionStarted) - { - $this->transactionContentStream = true; - $dbo->begin($Model); - } - + $this->transactionContentStream = $Model->getDataSource()->begin($Model); foreach ($this->settings[$Model->alias]['streams'] as $fk => $stream) if (empty($Model->data[$Model->alias][$fk]) && $Model->{$stream['assocName']}->createEmpty($stream['type'])) $Model->data[$Model->alias][$fk] = $Model->{$stream['assocName']}->id; @@ -184,9 +177,8 @@ function afterSave(&$Model, $created) { if ($this->transactionContentStream) { - $dbo = $Model->getDataSource(); - if ($created) $dbo->commit($Model); - else $dbo->rollback($Model); + if ($created) $Model->getDataSource()->commit($Model); + else $Model->getDataSource()->rollback($Model); $this->transactionContentStream = false; } } diff --git a/src/cake/app/plugins/jj_media/config/schema/empty b/src/cake/app/plugins/jj_media/config/schema/empty deleted file mode 100644 index e69de29b..00000000 diff --git a/src/cake/app/plugins/jj_media/config/schema/schema.php b/src/cake/app/plugins/jj_media/config/schema/schema.php new file mode 100644 index 00000000..86d278cf --- /dev/null +++ b/src/cake/app/plugins/jj_media/config/schema/schema.php @@ -0,0 +1,34 @@ + array('type' => 'integer', 'null' => false, 'default' => NULL, 'key' => 'primary'), + 'checksum' => array('type' => 'string', 'null' => false, 'default' => NULL, 'collate' => 'latin1_swedish_ci', 'charset' => 'latin1'), + 'dirname' => array('type' => 'string', 'null' => false, 'default' => NULL, 'collate' => 'latin1_swedish_ci', 'charset' => 'latin1'), + 'basename' => array('type' => 'string', 'null' => false, 'default' => NULL, 'collate' => 'latin1_swedish_ci', 'charset' => 'latin1'), + 'original_filename' => array('type' => 'string', 'null' => false, 'default' => NULL, 'collate' => 'latin1_swedish_ci', 'charset' => 'latin1'), + 'mime_type' => array('type' => 'string', 'null' => false, 'default' => NULL, 'collate' => 'latin1_swedish_ci', 'charset' => 'latin1'), + 'size' => array('type' => 'integer', 'null' => false, 'default' => NULL), + 'width' => array('type' => 'integer', 'null' => true, 'default' => NULL), + 'height' => array('type' => 'integer', 'null' => true, 'default' => NULL), + 'original_id' => array('type' => 'integer', 'null' => true, 'default' => NULL), + 'transformation_version' => array('type' => 'integer', 'null' => true, 'default' => NULL), + 'transformation' => array('type' => 'string', 'null' => true, 'default' => NULL, 'collate' => 'latin1_swedish_ci', 'charset' => 'latin1'), + 'data' => array('type' => 'text', 'null' => true, 'default' => NULL, 'collate' => 'latin1_swedish_ci', 'charset' => 'latin1'), + 'created' => array('type' => 'datetime', 'null' => true, 'default' => NULL), + 'modified' => array('type' => 'datetime', 'null' => true, 'default' => NULL), + 'indexes' => array('PRIMARY' => array('column' => 'id', 'unique' => 1)), + 'tableParameters' => array('charset' => 'latin1', 'collate' => 'latin1_swedish_ci', 'engine' => 'InnoDB') + ); +} +?> \ No newline at end of file diff --git a/src/cake/app/plugins/jj_media/controllers/components/empty b/src/cake/app/plugins/jj_media/controllers/components/empty deleted file mode 100644 index e69de29b..00000000 diff --git a/src/cake/app/plugins/jj_media/controllers/jj_media_controller.php b/src/cake/app/plugins/jj_media/controllers/jj_media_controller.php index 62264e44..2d4554fa 100644 --- a/src/cake/app/plugins/jj_media/controllers/jj_media_controller.php +++ b/src/cake/app/plugins/jj_media/controllers/jj_media_controller.php @@ -97,24 +97,24 @@ function index($download = null, $data = null, $name = null) if (count($unpacked) != 2) $this->cakeError('error404'); - $model_name = 'JjMedia.SfilStoredFile'; - if (!$this->loadModel($model_name)) + $modelName = 'JjMedia.SfilStoredFile'; + if (!$this->loadModel($modelName)) return; list($sfil_stored_files_id, $version) = $unpacked; - list($plugin, $model_name) = pluginSplit($model_name); - $model_alias = $this->{$model_name}->alias; + list($plugin, $modelName) = pluginSplit($modelName); + $model_alias = $this->{$modelName}->alias; if(!empty($sfil_stored_files_id)) { - $this->{$model_name}->contain(); - $file_data = $this->{$model_name}->findById($sfil_stored_files_id); + $this->{$modelName}->contain(); + $file_data = $this->{$modelName}->findById($sfil_stored_files_id); if (empty($file_data)) $this->cakeError('error404'); if (empty($name) && !$download) - $this->redirect(array($download, $data, $file_data[$this->{$model_name}->alias]['original_filename'])); + $this->redirect(array($download, $data, $file_data[$this->{$modelName}->alias]['original_filename'])); if(!empty($file_data)) { @@ -158,7 +158,6 @@ function index($download = null, $data = null, $name = null) } } - /** * upload action * @@ -166,53 +165,198 @@ function index($download = null, $data = null, $name = null) * It already saves the file, generating the filtered copies, and renders a JSON, directly on view. * * @access public - * @todo Receive, through posted data, the model that will handle the save */ function upload() + { + if ($this->RequestHandler->isAjax()) + { + $this->performAjaxUpload(); + return; + } + + $this->layout = 'ajax'; + $this->view = 'Typographer.Type'; + $this->set($this->saveUpload($this->data)); + } + +/** + * Method to receive and glue pieces togheter on a ajax upload + * + * This method is NOT a action. It is called at JjMediaController::upload() + * when is detected that the upload is performed by a ajax request. + * + * @access protected + * @return void + * @todo A garbage collector avoiding all the data that is left behind due errors + */ + protected function performAjaxUpload() + { + $error = false; + $version = ''; + + $startByte = env('HTTP_X_UPLOADER_START_BYTE'); + $isLast = env('HTTP_X_UPLOADER_IS_LAST'); + $chunkSize = env('HTTP_X_UPLOADER_CHUNK_SIZE'); + + $version = $fieldName = $modelName = null; + if (!empty($this->buroData['data'])) + { + list($version, $fieldName, $modelName) = SecureParams::unpack($this->buroData['data']); + list($plugin, $modelName) = pluginSplit($modelName); + } + + if (empty($this->data[$modelName]['file']['tmp_name'])) + $error = 'upload-failed'; + elseif (!file_exists($chunkFileName = $this->data[$modelName]['file']['tmp_name'])) + $error = 'upload-failed-no-tempfile'; + elseif (filesize($chunkFileName) != $chunkSize) + $error = 'upload-failed-chunksize-wrong'; + + if ($error) + goto renderAjaxUpload; + + + if (empty($this->data['hash'])) + { + $n = 0; + do { + $hash = uniqid('', true); + } while (file_exists(TMP . $hash)); + mkdir(TMP . $hash); + chmod(TMP . $hash, 0777); + } + else + { + $hash = $this->data['hash']; + } + + $chunkFile = fopen($chunkFileName, 'rb'); + $gluedFileName = TMP . $hash . DS . 'file'; + $gluedFile = fopen($gluedFileName, 'ab'); + chmod($chunkFileName, 0666); + + if (filesize($gluedFileName) != $startByte) + { + $error = 'chunk-doesnt-fit'; + $nextByte = filesize($gluedFileName); + goto renderAjaxUpload; + } + + if (!$chunkFile || !$gluedFile) + { + $error = 'reading-file-error'; + goto renderAjaxUpload; + } + + fwrite($gluedFile, fread($chunkFile, filesize($chunkFileName))); + fclose($chunkFile); + fclose($gluedFile); + + // This file will tell the GC cron job to clean files when "abandoned" + $lastInteractionFile = TMP . $hash . DS . 'last_interaction'; + file_put_contents($lastInteractionFile, time()); + chmod($lastInteractionFile, 0666); + + if ($isLast == 'yes') + { + $originalName = TMP . $hash . DS . $this->data['original_name']; + rename($gluedFileName, $originalName); + + $data = array($modelName => array('file' => $originalName)); + $savedData = $this->saveUpload($data); + + // remove temporary dir + unlink($originalName); + unlink($lastInteractionFile); + rmdir(TMP . $hash); + + if (!$savedData['saved']) + { + $validationErrors = $savedData['validationErrors']; + } + else + { + extract($savedData); + } + } + else + { + $nextByte = filesize(TMP . $hash); + } + + renderAjaxUpload: + $this->view = 'JjUtils.Json'; + $this->set('jsonVars', compact('error', 'validationErrors', 'saved', 'version', 'url', 'dlurl', 'hash', 'nextByte')); + } + +/** + * Performs the logic of saving the upload data + * + * This method receive the POSTed data from each action (classic or ajax upload) + * validates the upload and saves it. + * The returned data is a array of the generated data (that will generally be + * sent back to the view, through JSON object) + * + * @access protected + * @param array $data The POSTed data to be analised and saved + * @param string $forceModel When not null, will force a Model to be used, instead of the specified on POSTed data + * @return array The array of data of generated data + */ + protected function saveUpload($data, $forceModel = null) { $saved = $error = false; $filename = ''; $validationErrors = array(); - - $version = $fieldName = $model_name = null; + + $version = $fieldName = $modelName = null; if (!empty($this->buroData['data'])) - list($version, $fieldName, $model_name) = SecureParams::unpack($this->buroData['data']); + list($version, $fieldName, $modelName) = SecureParams::unpack($this->buroData['data']); + + if ($forceModel) + $modelName = $forceModel; - if (is_null($version) || is_null($fieldName) || is_null($model_name)) + if (is_null($version) || is_null($fieldName) || is_null($modelName)) { $validationErrors['file'] = 'post_max_size'; } - elseif (!$this->loadModel($model_name)) + elseif (!$this->loadModel($modelName)) { - $error = Configure::read()>0?'JjMediaController::upload - Model '.$model_name.' not found.':true; + $error = Configure::read()>0?'JjMediaController::upload - Model '.$modelName.' not found.':true; } else { - list($plugin, $model_name) = pluginSplit($model_name); - $Model =& $this->{$model_name}; + list($plugin, $modelName) = pluginSplit($modelName); + $Model =& $this->{$modelName}; $model_alias = $Model->alias; - if (!empty($this->data)) + if (!empty($data)) { $scope = $Model->findTheScope($fieldName); if ($scope) $Model->setScope($scope); - $Model->set($this->data); + $Model->set($data); $validationErrors = $this->validateErrors($Model); if (empty($validationErrors) && $Model->save(null, false)) { $saved = $Model->id; - $filename = $this->data[$model_alias]['file']['name']; + if (isset($data[$model_alias]['file']['name'])) + $filename = $data[$model_alias]['file']['name']; + list($fieldModelName, $fieldName) = pluginSplit($fieldName); - if (!empty($this->data[$fieldModelName][$fieldName])) - $Model->delete($this->data[$fieldModelName][$fieldName]); + if (!empty($data[$fieldModelName][$fieldName])) + $Model->delete($data[$fieldModelName][$fieldName]); + + App::import('Lib', array('JjUtils.SecureParams')); + $packed_params = SecureParams::pack(array($saved, $version), true); + $baseUrl = array('plugin' => 'jj_media', 'controller' => 'jj_media', 'action' => 'index'); + $dlurl = Router::url($baseUrl + array('1', $packed_params)); + $url = Router::url($baseUrl + array($packed_params)); } } } - $this->layout = 'ajax'; - $this->view = 'Typographer.Type'; - $this->set(compact('error', 'validationErrors', 'saved', 'version', 'filename')); + + return compact('error', 'validationErrors', 'saved', 'version', 'filename', 'url', 'dlurl'); } } diff --git a/src/cake/app/plugins/jj_media/libs/empty b/src/cake/app/plugins/jj_media/libs/empty deleted file mode 100644 index e69de29b..00000000 diff --git a/src/cake/app/plugins/jj_media/models/behaviors/stored_file_holder.php b/src/cake/app/plugins/jj_media/models/behaviors/stored_file_holder.php index 73514e09..e0b6cf90 100644 --- a/src/cake/app/plugins/jj_media/models/behaviors/stored_file_holder.php +++ b/src/cake/app/plugins/jj_media/models/behaviors/stored_file_holder.php @@ -106,8 +106,12 @@ function afterSave(&$Model, $created) $SfilStoredFile =& $this->getFileModel($Model); foreach ($this->settings[$Model->alias]['keys'] as $key) + { + if (empty($this->runtime[$Model->alias]['ids_bkp'][$key])) + continue; if (isset($Model->data[$Model->alias][$key]) && $Model->data[$Model->alias][$key] != $this->runtime[$Model->alias]['ids_bkp'][$key]) $SfilStoredFile->delete($this->runtime[$Model->alias]['ids_bkp'][$key]); + } } } diff --git a/src/cake/app/plugins/jj_media/models/datasources/empty b/src/cake/app/plugins/jj_media/models/datasources/empty deleted file mode 100644 index e69de29b..00000000 diff --git a/src/cake/app/plugins/jj_media/models/sfil_big_file.php b/src/cake/app/plugins/jj_media/models/sfil_big_file.php new file mode 100644 index 00000000..d74b7b53 --- /dev/null +++ b/src/cake/app/plugins/jj_media/models/sfil_big_file.php @@ -0,0 +1,62 @@ + array( + 'notempty' => array( + 'rule' => array('notempty'), + ), + ), + 'dirname' => array( + 'notempty' => array( + 'rule' => array('notempty'), + ), + ), + 'basename' => array( + 'notempty' => array( + 'rule' => array('notempty'), + ), + ), + 'original_filename' => array( + 'notempty' => array( + 'rule' => array('notempty'), + ), + ), + 'mime_type' => array( + 'notempty' => array( + 'rule' => array('notempty'), + ), + ), + 'size' => array( + 'numeric' => array( + 'rule' => array('numeric'), + ), + ), + 'file' => array( + 'resource' => array('rule' => 'checkResource'), + 'access' => array('rule' => 'checkAccess'), + 'location' => array('rule' => array('checkLocation', array(MEDIA_TRANSFER, TMP, '/tmp/', 'D:\wamp\tmp'))), + 'permission' => array('rule' => array('checkPermission', '*')), + 'size' => array('rule' => array('checkSize', '500M')) + ), + ); +} diff --git a/src/cake/app/plugins/jj_media/tests/cases/behaviors/empty b/src/cake/app/plugins/jj_media/tests/cases/behaviors/empty deleted file mode 100644 index e69de29b..00000000 diff --git a/src/cake/app/plugins/jj_media/tests/cases/components/empty b/src/cake/app/plugins/jj_media/tests/cases/components/empty deleted file mode 100644 index e69de29b..00000000 diff --git a/src/cake/app/plugins/jj_media/tests/cases/helpers/empty b/src/cake/app/plugins/jj_media/tests/cases/helpers/empty deleted file mode 100644 index e69de29b..00000000 diff --git a/src/cake/app/plugins/jj_media/tests/fixtures/empty b/src/cake/app/plugins/jj_media/tests/fixtures/empty deleted file mode 100644 index e69de29b..00000000 diff --git a/src/cake/app/plugins/jj_media/tests/groups/empty b/src/cake/app/plugins/jj_media/tests/groups/empty deleted file mode 100644 index e69de29b..00000000 diff --git a/src/cake/app/plugins/jj_media/vendors/empty b/src/cake/app/plugins/jj_media/vendors/empty deleted file mode 100644 index e69de29b..00000000 diff --git a/src/cake/app/plugins/jj_media/vendors/shells/tasks/empty b/src/cake/app/plugins/jj_media/vendors/shells/tasks/empty deleted file mode 100644 index e69de29b..00000000 diff --git a/src/cake/app/plugins/jj_media/vendors/shells/upload_gc.php b/src/cake/app/plugins/jj_media/vendors/shells/upload_gc.php new file mode 100644 index 00000000..3ebddd4a --- /dev/null +++ b/src/cake/app/plugins/jj_media/vendors/shells/upload_gc.php @@ -0,0 +1,87 @@ +params['quiet'])) + { + $this->quiet = true; + } + + $tmp = new Folder(TMP); + $folders = reset($tmp->read()); // read only directories (array[0]) + + foreach ($folders as $folder) + { + $tmp->cd(TMP); + $tmp->cd($folder); + $files = end($tmp->read()); // read only files (array[1]) + if (in_array('last_interaction', $files)) + { + $file_interaction = (int) file_get_contents($tmp->pwd() . DS . 'last_interaction'); + + // as each piece is 1Mb, this will give the user the chance of uploading at 13,7 kbps (1,7 kb/s) + if (time() - $file_interaction > 600) + { + $this->out("Removing $folder"); + foreach ($files as $file) + unlink($tmp->pwd() . DS . $file); + $tmp->delete(); + } + } + } + } + +/** + * Overwrites parent method to introduce the "quiet" variant + * + * @access public + */ + function out($msg = '') + { + if (!$this->quiet) + parent::out($msg); + } +} diff --git a/src/cake/app/plugins/jj_media/views/helpers/empty b/src/cake/app/plugins/jj_media/views/helpers/empty deleted file mode 100644 index e69de29b..00000000 diff --git a/src/cake/app/plugins/jj_media/views/jj_media/upload.ctp b/src/cake/app/plugins/jj_media/views/jj_media/upload.ctp index 97754d2f..447b382b 100644 --- a/src/cake/app/plugins/jj_media/views/jj_media/upload.ctp +++ b/src/cake/app/plugins/jj_media/views/jj_media/upload.ctp @@ -19,5 +19,7 @@ $url = $this->Bl->fileURL($saved, $version); $dlurl = $this->Bl->fileURL($saved, $version, true); } + + $extraCaptions = $this->BuroOfficeBoy->getAllCaptions(); - echo json_encode(compact('error', 'validationErrors', 'saved', 'url', 'dlurl', 'filename')); \ No newline at end of file + echo json_encode(compact('error', 'validationErrors', 'saved', 'url', 'dlurl', 'filename', 'extraCaptions')); diff --git a/src/cake/app/plugins/jj_media/webroot/empty b/src/cake/app/plugins/jj_media/webroot/empty deleted file mode 100644 index e69de29b..00000000 diff --git a/src/cake/app/plugins/jj_users/controllers/components/jj_auth.php b/src/cake/app/plugins/jj_users/controllers/components/jj_auth.php index b71a2193..07be8acf 100644 --- a/src/cake/app/plugins/jj_users/controllers/components/jj_auth.php +++ b/src/cake/app/plugins/jj_users/controllers/components/jj_auth.php @@ -56,26 +56,38 @@ function initialize(&$Controller, $settings = array()) /** * Compile the array of permissions suming all UserPermission.slug from database. * - * For performance pouposes, this array is cached on a session var. + * For performance pouposes, this array is cached on a session var. But it checks + * for the `modified` field on users table to decide when is necessary to update + * the cache. * * @access protected + * @param boolean $force When true, the cache will be updated + * @return void */ protected function compilePermissions($force = false) { - $permissions = $this->user('permissions'); - if (!empty($permissions) && !$force) - { - return; - } - $id = $this->user('id'); if (empty($id)) { $this->Session->delete($this->sessionKey); return; } - + $userModel =& $this->getModel(); + $permissions = $this->user('permissions'); + + if (!empty($permissions)) + { + $userModel->id = $id; + $last_modified_at = $userModel->field('modified'); + $force = $force || $last_modified_at != $this->user('modified'); + + if (!$force) + { + return; + } + } + $userData = $userModel->find('first', array( 'conditions' => array('UserUser.id' => $this->user('id')), 'contain' => array('UserProfile' => array('UserPermission')) @@ -88,7 +100,6 @@ protected function compilePermissions($force = false) $this->Session->write($this->sessionKey, $userData['UserUser']); } - /** * Verify the permissions * diff --git a/src/cake/app/plugins/jj_users/locale/por/LC_MESSAGES/jj_users.mo b/src/cake/app/plugins/jj_users/locale/por/LC_MESSAGES/jj_users.mo index 88f83bd4..5fd15bd8 100644 Binary files a/src/cake/app/plugins/jj_users/locale/por/LC_MESSAGES/jj_users.mo and b/src/cake/app/plugins/jj_users/locale/por/LC_MESSAGES/jj_users.mo differ diff --git a/src/cake/app/plugins/jj_users/locale/por/LC_MESSAGES/jj_users.po b/src/cake/app/plugins/jj_users/locale/por/LC_MESSAGES/jj_users.po index 2bf93229..f5b2486c 100644 --- a/src/cake/app/plugins/jj_users/locale/por/LC_MESSAGES/jj_users.po +++ b/src/cake/app/plugins/jj_users/locale/por/LC_MESSAGES/jj_users.po @@ -4,146 +4,164 @@ msgid "" msgstr "" "Project-Id-Version: Jodel\n" -"POT-Creation-Date: 2012-05-15 11:30+0000\n" -"PO-Revision-Date: 2012-05-15 08:43-0300\n" -"Last-Translator: Rodrigo \n" +"POT-Creation-Date: 2013-03-04 15:38-0300\n" +"PO-Revision-Date: 2013-03-04 15:44-0300\n" +"Last-Translator: Daniel Abrahão \n" "Language-Team: \n" +"Language: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n" -#: \plugins\jj_users\views\elements\user_permission.ctp:47 +#: /plugins/jj_users/models/user_user.php:115 +msgid "Por favor, selecione ao menos um perfil" +msgstr "" + +#: /plugins/jj_users/views/elements/user_permission.ctp:60 msgid "user_permisson name label" msgstr "Nome" -#: \plugins\jj_users\views\elements\user_permission.ctp:48 +#: /plugins/jj_users/views/elements/user_permission.ctp:61 msgid "user_permission name instructions" msgstr " " -#: \plugins\jj_users\views\elements\user_permission.ctp:57 +#: /plugins/jj_users/views/elements/user_permission.ctp:70 msgid "user_permission slug label" msgstr "Slug" -#: \plugins\jj_users\views\elements\user_permission.ctp:58 +#: /plugins/jj_users/views/elements/user_permission.ctp:71 msgid "user_permission slug instructions" msgstr " " -#: \plugins\jj_users\views\elements\user_permission.ctp:67 +#: /plugins/jj_users/views/elements/user_permission.ctp:80 msgid "user_permission description label" msgstr "Descrição" -#: \plugins\jj_users\views\elements\user_permission.ctp:68 +#: /plugins/jj_users/views/elements/user_permission.ctp:81 msgid "user_permission description instructions" msgstr " " -#: \plugins\jj_users\views\elements\user_permission.ctp:77 -#: \plugins\jj_users\views\elements\user_profile.ctp:94 -#: \plugins\jj_users\views\elements\user_user.ctp:175;185 +#: /plugins/jj_users/views/elements/user_permission.ctp:90 +#: /plugins/jj_users/views/elements/user_profile.ctp:107 +#: /plugins/jj_users/views/elements/user_user.ctp:186;196 msgid "submit label" msgstr "Salvar" -#: \plugins\jj_users\views\elements\user_profile.ctp:48 +#: /plugins/jj_users/views/elements/user_profile.ctp:61 msgid "user_profile name label" msgstr "Nome" -#: \plugins\jj_users\views\elements\user_profile.ctp:49 +#: /plugins/jj_users/views/elements/user_profile.ctp:62 msgid "user_profile name instructions" msgstr " " -#: \plugins\jj_users\views\elements\user_profile.ctp:58 +#: /plugins/jj_users/views/elements/user_profile.ctp:71 msgid "user_profile slug label" msgstr "Slug" -#: \plugins\jj_users\views\elements\user_profile.ctp:59 +#: /plugins/jj_users/views/elements/user_profile.ctp:72 msgid "user_profile slug instructions" msgstr " " -#: \plugins\jj_users\views\elements\user_profile.ctp:68 +#: /plugins/jj_users/views/elements/user_profile.ctp:81 msgid "user_profile description label" msgstr "Descrição" -#: \plugins\jj_users\views\elements\user_profile.ctp:69 +#: /plugins/jj_users/views/elements/user_profile.ctp:82 msgid "user_profile description instructions" msgstr " " -#: \plugins\jj_users\views\elements\user_profile.ctp:78 +#: /plugins/jj_users/views/elements/user_profile.ctp:91 msgid "UserPermission label" msgstr "Permissões" -#: \plugins\jj_users\views\elements\user_profile.ctp:79 +#: /plugins/jj_users/views/elements/user_profile.ctp:92 msgid "UserPermission instructions" msgstr " " -#: \plugins\jj_users\views\elements\user_user.ctp:55 +#: /plugins/jj_users/views/elements/user_profile.ctp:136 +msgid "Cada perfil engloba uma ou mais permissões do sistema administrativo. Atenção para a exclusão de perfis: não é possível excluir um perfil se o mesmo ainda está em uso por algum usuário." +msgstr "" + +#: /plugins/jj_users/views/elements/user_user.ctp:68 msgid "name_surname super_field label" msgstr "Nome" -#: \plugins\jj_users\views\elements\user_user.ctp:56 +#: /plugins/jj_users/views/elements/user_user.ctp:69 msgid "name_surname super_field instructions" msgstr " " -#: \plugins\jj_users\views\elements\user_user.ctp:65 +#: /plugins/jj_users/views/elements/user_user.ctp:78 msgid "name label" msgstr "Primeiro nome" -#: \plugins\jj_users\views\elements\user_user.ctp:66 +#: /plugins/jj_users/views/elements/user_user.ctp:79 msgid "name instructions" msgstr " " -#: \plugins\jj_users\views\elements\user_user.ctp:75 +#: /plugins/jj_users/views/elements/user_user.ctp:88 msgid "surname label" msgstr "Sobrenome" -#: \plugins\jj_users\views\elements\user_user.ctp:76 +#: /plugins/jj_users/views/elements/user_user.ctp:89 msgid "surname instructions" msgstr " " -#: \plugins\jj_users\views\elements\user_user.ctp:87 +#: /plugins/jj_users/views/elements/user_user.ctp:100 msgid "account super_field label" msgstr "Sua conta" -#: \plugins\jj_users\views\elements\user_user.ctp:88 +#: /plugins/jj_users/views/elements/user_user.ctp:101 msgid "account super_field instructions" msgstr " " -#: \plugins\jj_users\views\elements\user_user.ctp:97 +#: /plugins/jj_users/views/elements/user_user.ctp:110 msgid "username label" msgstr "Nome de usuário" -#: \plugins\jj_users\views\elements\user_user.ctp:98 +#: /plugins/jj_users/views/elements/user_user.ctp:111 msgid "username instructions" msgstr "Da próxima vez que for acessar a página administrativa, você deverá usar esse nome de usuário." -#: \plugins\jj_users\views\elements\user_user.ctp:107 +#: /plugins/jj_users/views/elements/user_user.ctp:117 +msgid "create password label" +msgstr "Criar uma senha" + +#: /plugins/jj_users/views/elements/user_user.ctp:118 +msgid "create password instructions" +msgstr " " + +#: /plugins/jj_users/views/elements/user_user.ctp:122 msgid "password_change label" msgstr "Alterar a senha" -#: \plugins\jj_users\views\elements\user_user.ctp:108 +#: /plugins/jj_users/views/elements/user_user.ctp:123 msgid "password_change instructions" -msgstr "Se não deseja alterar, deixe em branco" +msgstr "Se quiser alterar a senha deste usuário, preencha esse campo e o seguinte. Caso contrário, favor deixar ambos em branco. " -#: \plugins\jj_users\views\elements\user_user.ctp:117 +#: /plugins/jj_users/views/elements/user_user.ctp:140 msgid "password_retype label" msgstr "Repita a senha" -#: \plugins\jj_users\views\elements\user_user.ctp:118 +#: /plugins/jj_users/views/elements/user_user.ctp:141 msgid "password_retype instructions" msgstr " " -#: \plugins\jj_users\views\elements\user_user.ctp:129 -msgid "profiles super_field label" -msgstr "Perfis" - -#: \plugins\jj_users\views\elements\user_user.ctp:130 -msgid "profiles super_field instructions" -msgstr "Selecione um ou mais perfis abaixo" - -#: \plugins\jj_users\views\elements\user_user.ctp:155 +#: /plugins/jj_users/views/elements/user_user.ctp:169 msgid "UserProfile label" msgstr "Perfis" -#: \plugins\jj_users\views\elements\user_user.ctp:156 +#: /plugins/jj_users/views/elements/user_user.ctp:170 msgid "UserProfile instructions" msgstr " " +#: /plugins/jj_users/views/elements/user_user.ctp:264 +msgid "Sem nome, ainda" +msgstr "" + +#~ msgid "profiles super_field label" +#~ msgstr "Perfis" + +#~ msgid "profiles super_field instructions" +#~ msgstr "Selecione um ou mais perfis abaixo" diff --git a/src/cake/app/plugins/jj_users/models/user_profile.php b/src/cake/app/plugins/jj_users/models/user_profile.php index 13460d19..7cfaa3aa 100644 --- a/src/cake/app/plugins/jj_users/models/user_profile.php +++ b/src/cake/app/plugins/jj_users/models/user_profile.php @@ -32,39 +32,56 @@ class UserProfile extends JjUsersAppModel 'notempty' => array('rule' => array('notempty')), ) ); - + var $hasAndBelongsToMany = array( 'UserPermission' => array( 'className' => 'JjUsers.UserPermission', 'joinTable' => 'user_profiles_user_permissions', + ), + 'UserUser' => array( + 'className' => 'JjUsers.UserUser', + 'joinTable' => 'user_users_user_profiles', + 'unique' => false ) ); - - + function backDelete($id) { - $this->bindModel(array( - 'hasMany' => array( - 'UserUsersUserProfile' => array( - 'className' => 'jjUsers.UserUsersUserProfile', - ) - ) - )); - - $this->UserUsersUserProfile->deleteAll(array('user_profile_id' => $id), false); + $this->contain('UserUser'); + $data = $this->findById($id); + if (!empty($data['UserUser'])) + return false; return $this->delete($id); } - /* Creates a blank row in the table. It is part of the backstage contract. - * - */ +/** + * Creates a blank row in the table. It is part of the backstage contract. + */ function createEmpty() { - - $data = $this->saveAll(array($this->alias => array()), array('validate' => false)); - $data = $this->find('first', array('conditions' => array($this->alias.'.id' => $this->id))); - - return $data; + $saved = $this->saveAll(array($this->alias => array()), array('validate' => false)); + if ($saved) + return $this->id; + return false; + } + +/** + * Ensures that all related users be updated forcing permission reload of logged users. + * + * @access public + */ + function afterSave() + { + $this->contain('UserUser'); + $data = $this->read(); + + $usersId = Set::extract('/UserUser/id', $data); + if (!empty($usersId)) + { + $this->UserUser->updateAll( + array('UserUser.modified' => '"' . date('Y-m-d H:i:s') . '"'), + array('UserUser.id' => $usersId) + ); + } } - } diff --git a/src/cake/app/plugins/jj_users/models/user_user.php b/src/cake/app/plugins/jj_users/models/user_user.php index c744d71e..e101ed63 100644 --- a/src/cake/app/plugins/jj_users/models/user_user.php +++ b/src/cake/app/plugins/jj_users/models/user_user.php @@ -26,68 +26,106 @@ class UserUser extends JjUsersAppModel var $validate = array( 'name' => array( - 'notempty' => array('rule' => array('notempty')) + 'rule' => 'notEmpty', + 'message' => 'Não deixe em branco' ), 'email' => array( - 'notempty' => array('rule' => array('notempty')), - 'email' => array('rule' => array('email')) + 'notempty' => array( + 'rule' => 'notEmpty', + 'message' => 'Não deixe em branco' + ), + 'email' => array( + 'rule' => 'email' + ) ), 'username' => array( - 'notempty' => array('rule' => array('notempty')), + 'rule' => 'notEmpty', + 'message' => 'Não deixe em branco' ), 'password_change' => array( - 'notempty' => array('rule' => array('notempty')), - 'minLength' => array('rule' => array('minLength', 6), 'message' => 'A senha deve conter no mínimo 6 caracteres.') + 'minLength' => array( + 'rule' => array('minLength', 6), + 'message' => 'A senha deve conter no mínimo 6 caracteres.' + ) ), 'password_retype' => array( - 'same' => array('rule' => array('identicalFieldValues', 'password_change')) - ), + 'rule' => array('identicalFieldValues', 'password_change'), + 'message' => 'Deve ser igual ao campo anterior' + ) ); - - var $hasAndBelongsToMany = array('UserProfile' => array('className' => 'JjUsers.UserProfile', 'joinTable' => 'user_users_user_profiles')); - - - /* Creates a blank row in the table. It is part of the backstage contract. - * - */ +/** + * Many to many relationship + * + * @access + */ + var $hasAndBelongsToMany = array( + 'UserProfile' => array( + 'className' => 'JjUsers.UserProfile', + 'joinTable' => 'user_users_user_profiles' + ) + ); + +/** + * Creates a blank row in the table. It is part of the backstage contract. + */ function createEmpty() { - - $data = $this->saveAll(array(), array('validate' => false)); - $data = $this->find('first', array('conditions' => array($this->alias.'.id' => $this->id))); - - return $data; + if ($this->saveAll(array(), array('validate' => false))) + return $this->id; + return false; } - + +/** + * Saves data from burocrata form + * + * This method does some data validation and manipulation mainly + * with the password sent + * + * @access public + * @param array $data Data to save + */ function saveBurocrata($data) - { - App::import('Component','JjUsers.JjAuth'); - + { + unset($data[$this->alias]['password']); + $this->set($data); - - if ($this->validates()) { - if (!empty($data[$this->alias]['password_change'])) { - $data[$this->alias]['password'] = JjAuthComponent::password($data[$this->alias]['password_change']); - } + + if ($this->validates()) + { + if (!empty($data[$this->alias]['password_change'])) + $data[$this->alias]['password'] = Security::hash($data[$this->alias]['password_change'], null, true); - return $this->saveAll($data); - } - else { - return false; + return $this->save($data); } + return false; } - + +/** + * Some hard-coded validations + * + * @access public + */ function beforeValidate($options) { if (empty($this->data[$this->alias]['password_change']) && empty($this->data[$this->alias]['password_retype'])) unset($this->data[$this->alias]['password_change'], $this->data[$this->alias]['password_retype']); + + $currentPassword = $this->field('password'); + if (empty($currentPassword) && empty($this->data[$this->alias]['password_change'])) + $this->invalidate('password_change', __d('jj_user', 'Favor criar uma senha para o usuário.', true)); - if ((!isset($this->data['UserProfile']['UserProfile']) || empty($this->data['UserProfile']['UserProfile'])) && isset($this->data[$this->alias]['validate_profiles'])) + if (empty($this->data['UserProfile']['UserProfile']) && isset($this->data[$this->alias]['validate_profiles'])) { $this->invalidate('non_existent_field'); // fake validation error on Profile - $this->UserProfile->invalidate('UserProfile', 'Por favor, selecione ao menos um perfil'); + $this->UserProfile->invalidate('UserProfile', __d('jj_users', 'Por favor, selecione ao menos um perfil', true)); } return true; } + + function findBurocrata($user_user_id) + { + $this->contain('UserProfile'); + return $this->findById($user_user_id); + } } diff --git a/src/cake/app/plugins/jj_users/views/elements/user_profile.ctp b/src/cake/app/plugins/jj_users/views/elements/user_profile.ctp index 59939461..be3d9909 100644 --- a/src/cake/app/plugins/jj_users/views/elements/user_profile.ctp +++ b/src/cake/app/plugins/jj_users/views/elements/user_profile.ctp @@ -131,6 +131,13 @@ switch ($type[0]) break; case 'table': + echo $this->Bl->br(); + echo $this->Bl->sboxContainer(array(), array('size' => array('M' => 4))); + echo $this->Bl->pDry(__d('jj_users', 'Cada perfil engloba uma ou mais permissões do sistema administrativo. Atenção para a exclusão de perfis: não é possível excluir um perfil se o mesmo ainda está em uso por algum usuário.', true)); + echo $this->Bl->eboxContainer(); + echo $this->Bl->floatBreak(); + echo $this->Bl->br(); + $classSize = array('M' => 9, 'g' => -1); $this->Bl->TypeStyleFactory->widthGenerateClasses(array(0 => $classSize)); $className = $this->Bl->TypeStyleFactory->widthClassNames($classSize); @@ -166,7 +173,7 @@ switch ($type[0]) $smartTableRow[] = ' '; - $links = $this->Bl->sdiv(array('class' => 'actions', array())); + $links = $this->Bl->sdiv(array('class' => 'actions')); $links .= $this->Bl->anchor( array('class' => 'link_button'), @@ -178,14 +185,17 @@ switch ($type[0]) ); $delete_url = $this->Html->url(array('action' => 'delete_item','user_profiles', $data['UserProfile']['id'])); - $links .= $this->Bl->anchor( - array( + $htmlAttr = array( 'class' => 'link_button', 'onclick' => "deleteID = '". $delete_url . "'; showPopup('delete_alert_confirmation'); event.returnValue = false; return false;", - ), - array('url' => ''), - __d('backstage','Delete', true) - ); + ); + if (!empty($data['UserUser'])) + { + $htmlAttr['class'] .= ' disabled'; + $htmlAttr['onclick'] = "alert('Existem usuários com o perfil \'{$data['UserProfile']['name']}\'. Por isso não é possível apagá-lo.'); return false;"; + } + + $links .= $this->Bl->anchor($htmlAttr, array('url' => ''), __d('backstage','Delete', true)); $links .= $this->Bl->ediv(); diff --git a/src/cake/app/plugins/jj_users/views/elements/user_user.ctp b/src/cake/app/plugins/jj_users/views/elements/user_user.ctp index f5b6e1ac..7f7e19b3 100644 --- a/src/cake/app/plugins/jj_users/views/elements/user_user.ctp +++ b/src/cake/app/plugins/jj_users/views/elements/user_user.ctp @@ -55,8 +55,8 @@ switch ($type[0]) 'callbacks' => array( 'onStart' => array('lockForm', 'js' => 'form.setLoading()'), 'onComplete' => array('unlockForm', 'js' => 'form.unsetLoading()'), - 'onReject' => array('js' => '$("content").scrollTo(); showPopup("error");', 'contentUpdate' => 'replace'), - 'onSave' => array('js' => '$("content").scrollTo(); showPopup("custom_notice");'), + 'onReject' => array('contentUpdate' => 'replace', 'js' => 'showPopup("error");'), + 'onSave' => array('contentUpdate' => 'replace', 'js' => 'showPopup("custom_notice");'), ) )); } @@ -111,22 +111,42 @@ switch ($type[0]) 'instructions' => __d('jj_users', 'username instructions', true) ) ); - + + if (empty($this->data['UserUser']['password'])) + { + $label = __d('jj_users', 'create password label', true); + $instructions = __d('jj_users', 'create password instructions', true); + } + else + { + $label = __d('jj_users', 'password_change label', true); + $instructions = __d('jj_users', 'password_change instructions', true); + echo $this->Buro->input( + array(), + array( + 'type' => 'hidden', + 'fieldName' => 'password', + 'options' => array( + 'value' => 'nothing_here' + ) + ) + ); + } echo $this->Buro->input( array(), array( 'fieldName' => 'password_change', - 'type' => 'text', - 'label' => __d('jj_users', 'password_change label', true), - 'instructions' => __d('jj_users', 'password_change instructions', true) + 'type' => 'password', + 'label' => $label, + 'instructions' => $instructions ) ); - + echo $this->Buro->input( array(), array( 'fieldName' => 'password_retype', - 'type' => 'text', + 'type' => 'password', 'label' => __d('jj_users', 'password_retype label', true), 'instructions' => __d('jj_users', 'password_retype instructions', true) ) @@ -246,7 +266,18 @@ switch ($type[0]) case 'row': $smartTableRow = array(); - $smartTableRow[] = $data['UserUser']['name']; + $data['UserUser']['full_name'] = trim($data['UserUser']['full_name']); + if (empty($data['UserUser']['full_name'])) + { + $smartTableRow[] .= $this->Bl->span( + array('class' => 'demoted'), array(), + __d('jj_users', 'Sem nome, ainda', true) + ); + } + else + { + $smartTableRow[] = $data['UserUser']['full_name']; + } if (!empty($data['UserProfile'])) { diff --git a/src/cake/app/plugins/jj_utils/views/json.php b/src/cake/app/plugins/jj_utils/views/json.php index 2147bb70..3ea78090 100644 --- a/src/cake/app/plugins/jj_utils/views/json.php +++ b/src/cake/app/plugins/jj_utils/views/json.php @@ -36,18 +36,31 @@ function render($action = null, $layout = null, $file = null) if(Configure::read() > 1) Configure::write('debug', 1); header('Content-Type: application/json; charset=UTF-8'); - - $loaded; - if(!isset($this->Js)) - $this->_loadHelpers($loaded, array('Js')); - $this->Js = $loaded['Js']; - - if(isset($this->viewVars['jsonVars'])) { - return $this->Js->object($this->viewVars['jsonVars']); - } else { - if(empty($layout)) + + if (isset($this->viewVars['jsonVars'])) + { + return json_encode($this->viewVars['jsonVars']); + } + else + { + if (empty($layout)) $layout = 'ajax'; - return parent::render($action, $layout, $file); + + $out = parent::render($action, $layout, $file); + + if (isset($this->BuroOfficeBoy)) + { + $extraCaptions = $this->BuroOfficeBoy->getAllCaptions(); + if (!empty($extraCaptions)) + { + $json = json_decode($out, true); + if (is_array($json)) + $json['extraCaptions'] = $extraCaptions; + $out = json_encode($json); + } + } + + return $out; } } } diff --git a/src/cake/app/plugins/typographer/views/elements/backstage_css.ctp b/src/cake/app/plugins/typographer/views/elements/backstage_css.ctp index 33edc48e..f2a3fb38 100644 --- a/src/cake/app/plugins/typographer/views/elements/backstage_css.ctp +++ b/src/cake/app/plugins/typographer/views/elements/backstage_css.ctp @@ -478,16 +478,6 @@ 'margin-right' => $hg->size(array('m' => 2)), )); - $this->Decorator->rule( - 'a.link_button.disabled', array( - 'color' => $palette['button_fg_disabled']->write(), - 'background-color' => $palette['button_bg_disabled']->write(), - )); - - $this->Decorator->rule( - 'a.link_button:visited', array( - 'color' => $palette['text']->write(), - )); $this->Decorator->rule( 'a.link_button:hover', array( @@ -500,6 +490,13 @@ 'color' => $palette['bg']->write(), 'background-color' => $palette['button_bg_hover']->write(), )); + + $this->Decorator->rule( + 'a.link_button.disabled, a.link_button.disabled:active, a.link_button.disabled:hover', array( + 'color' => $palette['button_fg_disabled'], + 'border-color' => $palette['button_fg_disabled'] . '!important', + 'background-color' => $palette['button_bg_disabled'] + )); // Textile input @@ -888,6 +885,12 @@ '.small_text', array( 'font-size' => $u->t($line_height * 11/18) )); + + $this->Decorator->rule( + '.demoted', array( + 'color' => $palette['button_fg_disabled'] + ) + ); // Control Box @@ -996,6 +999,7 @@ 'font-style' => 'italic', 'display' => 'block' )); + @@ -1270,6 +1274,49 @@ '#login_box input[type=text], #login_box input[type=password]', array( 'width' => $u->t($hg->size(array('M' => 4, 'g' => -1),false) - 2*($border_size + $padding_size)) )); + + $this->Decorator->rule( + '.input.buro .progress_bar', array( + 'border' => '1px solid ' . $palette['input_borders'], + 'height' => $u->t($vg->size(array('g' => 1.5),false) - 2*$border_size - $padding_top), + 'padding' => $u->t($padding_top) . ' ' . $u->t($padding_size), + 'width' => $u->t($hg->size(array('M' => 5, 'g' => -1),false) - 2*($border_size + $padding_size)), + 'position' => 'relative', + 'margin-top' => $vg->size('m') + ) + ); + + $this->Decorator->rule( + '.input.buro .progress_bar .filling', array( + 'background' => $palette['menu_bg'], + 'float' => 'left', + 'height' => $u->t($vg->size(array('g' => 1.5),false) - 2*$border_size - $padding_top), + 'width' => 0 + ) + ); + + $this->Decorator->rule( + '.buro_form .buro_form .input.buro .progress_bar .filling', array( + 'background' => $palette['bg'] + ) + ); + + $this->Decorator->rule( + '.input.buro .progress_bar .label', array( + 'position' => 'absolute', + 'left' => 0, + 'text-align' => 'center', + 'width' => '100%' + ) + ); + + // Input upload + + $this->Decorator->rule( + '.upload_control', array( + 'margin' => $vg->size('m') . ' 0' + ) + ); $this->Decorator->rule( 'select.buro', array(