This is a post from my original site, which was hosted by the former blog service of the University of Osnabrück. I have moved it to the new site for archiving. Pages linked in this article may no longer work today, and the blog comments under the article no longer exist. Opinions expressed in this article reflect the point of view of the time of publication and do not necessarily reflect my opinion today.
If you're running a Drupal-based webpage which is completely restricted to authenticated users, Anonymous would get an "403 Access Denied" on every page he tries. But if you want your visitors to see a friendly login page (instead of just this error message and a small "login block") you might want to put the following code into your sites/default/setting.php:
You should also check $path if you want to use this on some pages only, e.g. on your frontpage.
UPDATE: This code is erroneous! You should return $result instead of $path, or some other modules like pathauto or path_redirect won't work as expected!
This is a post from my original site, which was hosted by the former blog service of the University of Osnabrück. I have moved it to the new site for archiving. Pages linked in this article may no longer work today, and the blog comments under the article no longer exist. Opinions expressed in this article reflect the point of view of the time of publication and do not necessarily reflect my opinion today.
If you need flash support, you should have a look at the current github version of this script at http://github.com/AdamN/python-webkit2png/ mentioned above. We've extend the script a few month ago.
From time to time you may want to create a screenshot of a web page from command line, for example if you wish to create thumbnails for your web-application. So you might search for such a program and find tools like webkit2png, which is for Mac OS X only, or khtml2png, which requires a lot of KDE stuff to be installed on your server.
But since Qt Software, formerly known als Trolltech, integrated Safari's famous rendering engine WebKit (which is based on Konqueror's khtml engine) into its framework, we are now able to make use of it with the help of some Python and PyQt4.
This is a post from my original site, which was hosted by the former blog service of the University of Osnabrück. I have moved it to the new site for archiving. Pages linked in this article may no longer work today, and the blog comments under the article no longer exist. Opinions expressed in this article reflect the point of view of the time of publication and do not necessarily reflect my opinion today.
Symfony provides a nice feature called "embedded Forms" ( sfForm::embedForm) to embed subforms into a parent form. This can be used to edit multiple records at the same time. So let's say you have a basic user table called 'sf_guard_user' and a profile table called 'user_profile', then you might follow this guide to merge these forms together: lib/forms/doctrine/sfUserGuardAdminForm.php:
classsfGuardUserAdminFormextendsBasesfGuardUserAdminForm{publicfunctionconfigure(){parent::configure();// Embed UserProfileForm into sfGuardUserAdminForm$profileForm=newUserProfileForm($this->object->Profile);unset($profileForm['id'],$profileForm['sf_guard_user_id']);$this->embedForm("profile",$profileForm);}}
Remember to add "profile" to the list of visible columns in apps/backend/modules/sfGuardUser/config/generator.yml as decribed in the linked guide. The result may look like this:
This does what it is expected to do, but it doesn't look very nice. Especially for 1:1 related tables I'm more interested in a solution that looks like this:
You can reach this using sfForm::mergeForm, but sadly the merged model won't get updated and you'll run into problems if the forms are sharing fieldnames. The solution is the following method embedMergeForm which can be defined in BaseFormDoctrine to be avaible in all other forms:
lib/forms/doctrine/BaseFormDoctrine.php:
abstractclassBaseFormDoctrineextendssfFormDoctrine{/**
* Embeds a form like "mergeForm" does, but will still
* save the input data.
*/publicfunctionembedMergeForm($name,sfForm$form){// This starts like sfForm::embedForm$name=(string)$name;if(true===$this->isBound()||true===$form->isBound()){thrownewLogicException('A bound form cannot be merged');}$this->embeddedForms[$name]=$form;$form=clone$form;unset($form[self::$CSRFFieldName]);// But now, copy each widget instead of the while form into the current// form. Each widget ist named "formname|fieldname".foreach($form->getWidgetSchema()->getFields()as$field=>$widget){$widgetName="$name|$field";if(isset($this->widgetSchema[$widgetName])){thrownewLogicException("The forms cannot be merged. A field name '$widgetName' already exists.");}$this->widgetSchema[$widgetName]=$widget;// Copy widget$this->validatorSchema[$widgetName]=$form->validatorSchema[$field];// Copy schema$this->setDefault($widgetName,$form->getDefault($field));// Copy default valueif(!$widget->getLabel()){// Re-create label if not set (otherwise it would be named 'ucfirst($widgetName)')$label=$form->getWidgetSchema()->getFormFormatter()->generateLabelName($field);$this->getWidgetSchema()->setLabel($widgetName,$label);}}// And this is like in sfForm::embedForm$this->resetFormFields();}/**
* Override sfFormDoctrine to prepare the
* values: FORMNAME|FIELDNAME has to be transformed
* to FORMNAME[FIELDNAME]
*/publicfunctionupdateObject($values=null){if(is_null($values)){$values=$this->values;foreach($this->embeddedFormsAS$name=>$form){foreach($formAS$field=>$f){if(isset($values["$name|$field"])){// Re-rename the form field and remove// the original field$values[$name][$field]=$values["$name|$field"];unset($values["$name|$field"]);}}}}// Give the request to the original methodparent::updateObject($values);}}
This method ensures that each fieldname is unique (named 'FORMNAME|FIELDNAME') and the subform is validated and saved. It is used like embedForm:
lib/forms/doctrine/sfUserGuardAdminForm.php:
classsfGuardUserAdminFormextendsBasesfGuardUserAdminForm{publicfunctionconfigure(){parent::configure();// Embed UserProfileForm into sfGuardUserAdminForm// without looking like an embedded form$profileForm=newUserProfileForm($this->object->Profile);unset($profileForm['id'],$profileForm['sf_guard_user_id']);$this->embedMergeForm("profile",$profileForm);}}
Feel free to use this method in your own project. Maybe this method get's merged into Symfony some day ;-)
Update
frostpearl reported a problem using embedFormMerge() in conjunction with the autocompleter widget from sfFormExtraPlugin. If you expire these problems try to replace all occurences of $name|$field with $name-$field.
This is a post from my original site, which was hosted by the former blog service of the University of Osnabrück. I have moved it to the new site for archiving. Pages linked in this article may no longer work today, and the blog comments under the article no longer exist. Opinions expressed in this article reflect the point of view of the time of publication and do not necessarily reflect my opinion today.
In my current Abobe Flex project, I needed to upload multple generated files and form fields to a server. UploadPostHelper by Jonathan Marston is a great for uploading one file at time, but sadly I couldn't use (or even modify) it - it's licensed under NonCommercial CC, and my project is a commercial one.
So I had to write my own code which I would like to share with other's (dual-licensed under MPL 1.1 and LGPL 2.1).
Usage of HttpPostData-class: <Update April 1st 2010>I had an error in this text for a half year and nobody noticed? Strange...</Update>
Create an Instance of HttpPostData:
varpostData:HttpPostData =newHttpPostData()
Add your parameters and file attachments
postData.addParameter('foo1','bar1');// POST-Field 'foo1' has value 'bar1'
postData.addParameter('foo2','bar2');// POST-Field 'foo2' has value 'bar2'// POST-Field 'uploadedFile1' contains someBinaryData1 (ByteArray)// as 'application/octet-stream' with filename 'uploadedFile1'
postData.addFile('uploadedFile1', someBinaryData1);// POST-Field 'uploadedFile2' contains someBinaryData2 (ByteArray)// as 'image/png' with filename 'image.png'
postData.addFile('uploadedFile2', someBinaryData2,'image.png','image/png')
Close this object. This will append the ending boundary to the data which makes it impossible to add additional form data.
This is a post from my original site, which was hosted by the former blog service of the University of Osnabrück. I have moved it to the new site for archiving. Pages linked in this article may no longer work today, and the blog comments under the article no longer exist. Opinions expressed in this article reflect the point of view of the time of publication and do not necessarily reflect my opinion today.
When doing MVC programming in Java, there is a problem that most people don't know about. I've ignored it myself much too long. The problem is that when you bind a model class to an UI component you will get a giant memory leak.
What happens?
Well, imagine a model class supporting listening for property changes. A simple example might look like this (I extend from PropertyChangeSupport here so that I don't have to delegate all the methods, normally you wouldn't do so, of course):
publicclassModelextendsPropertyChangeSupport{privateString name;publicModel(String name){super(newObject());// Only an example! Don't do this in RL!this.name = name;}publicStringgetName(){return name;}publicvoidsetName(String name){firePropertyChange("name",this.name,this.name = name);}}
Next, imagine a view for this model class. It has an input field that is binded in both direction with the model (very simplified example here, I normally don't code this way ;-)):
From now on we have a memory leak, because the JPanel, the JLabel and the JTextField (and all other referenced) objects will never be removed by the garbage collector as long as the model exists (which might be until the applications end of life). The reason is that the anonymous inner PropertyChangeListener instance has (and must have!) an implicit reference to the JPanel. And even if you replace it by a static class it does have to know the textfield which is a child object of the panel and has a reference back to it. So even if nobody else references the panel the garbage collector sees:
Model => PropertyChangeListener => JPanel
There is a little known class called WeakReference (and his brother WeakHashMap). It contains an object, but the object could still be removed by the garbage collector as long as there is no other (non-weak) reference to it.
A naive idea is to just encapsulate the PropertyChangeListener within a WeakReference object:
publicclassWeakListenerimplementsPropertyChangeListener{privatefinalWeakReference<PropertyChangeListener> listener;publicWeakListener(PropertyChangeListener listener){this.listener =newWeakReference<PropertyChangeListener>(listener);}publicvoidpropertyChange(PropertyChangeEvent e){PropertyChangeListener l =this.listener.get();if(l !=null){
l.propertyChange(e);}}}
Code in ModelView constructor:
// Bind model => textfield (with little memory leak)
model.addPropertyChangeListener("name",newWeakListener(newPropertyChangeListener(){publicvoidpropertyChange(PropertyChangeEvent e){
textfield.setText(model.getName());}}));
The idea is that you still have this simple and small WeakListener object within your model's listener list, but the really big part (the original listener, the panel, label, textfield, etc) could be free'd. Sadly, this will not work, because as soon as you gave the anonymous PropertyChangeListener to WeakListener's constructor nobody else does reference to it, so the garbage collector will remove the object immediately.
The trick is to create a single reference to it which belongs the parent object:
publicclassModelViewextendsJPanel{privatePropertyChangeListener modelTextfieldListener;publicModelView(finalModel model){super(newBorderLayout());add(newJLabel("Name: "),BorderLayout.WEST);finalJTextField textfield =newJTextField(model.getName());add(textfield,BorderLayout.CENTER);// Bind textfield => model (harmless)
textfield.addActionListener(newActionListener(){publicvoidactionPerformed(ActionEvent e){
model.setName(textfield.getText());}});// Bind model => textfield (with little memory leak)
model.addPropertyChangeListener("name",newWeakListener(modelTextfieldListener =newPropertyChangeListener(){publicvoidpropertyChange(PropertyChangeEvent e){
textfield.setText(model.getName());}}));}}
That's it. To make this easier I've created a little support class WeakListenerSupport that's very helpful if you have to deal with multiple input-property-bindings. Also it tries to remove ("unlink") itself from the model if the listener doesn't exist any longer. It even allows to unlink all weak listeners from a single object.
With this class the above example would look like:
This is a post from my original site, which was hosted by the former blog service of the University of Osnabrück. I have moved it to the new site for archiving. Pages linked in this article may no longer work today, and the blog comments under the article no longer exist. Opinions expressed in this article reflect the point of view of the time of publication and do not necessarily reflect my opinion today.
JTextPane and his ancestors JEditorPane and JTextComponent won't respect the color defined with setBackground(Color) since they display a "styled document" and expect the background color to be defined in the content. You'll always see a white background.
To change the background color (without modifying the content) you have to define attributes for the document:
JTextPane textPane =newJTextPane();
textPane.setContentType("text/html");// or any other styled content type
textPane.setText("White text on a red background");
textPane.setForeground(Color.white);// Works as expected
textPane.setBackground(Color.red);// Obsolete, no affect// Define a default background color attributeColor backgroundColor =Color.red;SimpleAttributeSet background =newSimpleAttributeSet();StyleConstants.setBackground(background, backgroundColor);
textPane.getStyledDocument().setParagraphAttributes(0,
textPane.getDocument().getLength(), background,false);// And remove default (white) margin
textPane.setBorder(BorderFactory.createEmptyBorder());// Alternative: Leave a 2px border but draw it in the same color
textPane.setBorder(BorderFactory.createLineBorder(backgroundColor,2));