Jump to content

Leaderboard

Popular Content

Showing content with the highest reputation on 03/23/2013 in all areas

  1. Hello guys. Just let you know that I'm still learning php, javascript, and Processwire. This time, I'm trying to do the image upload, and been look through this forum how to do it. Unfortunately, some of the way people did in this forum are totally not understandable, yet. What I found out is how this is process. Hope people like me would find this post and help through creating wonderful website. I'll only use php and Processwire API because I don't know about the jQuery enough, yet. 1. create form <form class='forum-form' accept-charset="utf-8" action='./' method='post' enctype='multipart/form-data' > ... <input type='file' id='attach' name='attach_file' multiple='multiple' accept='image/jpg,image/jpeg,image/gif,image/png' /> // this is the input tag for the image attachment <input type='submit' name='add_file' value='Add file'/> // this is the submit to upload image attachment before submitting entire form <input type='submit' name='form_submit' value='Submit'/> // this is the submit to send entire data ... </form> I found out that I have to put enctype='multipart/form-data' in order to submit file/image type. 2. To attach some images on the page, I guess, I have to upload those images before submitting form. PHP code seems very complicated to me, and I've found out that it is somewhat easy to use Processwire class which is WireUpload. I've made a custom function so that I can reuse and maintaining easily. I've borrowed Soma's code here.(hope this would be fine with him) private function uploadImage(){ $upload_path = $this->config->paths->root . 'tmp_uploads/'; $u = new WireUpload('attach_file'); $u->setMaxFiles(1); $u->setOverwrite(false); $u->setDestinationPath($upload_path); $u->setValidExtensions(array('jpg', 'jpeg', 'png', 'gif')); $files = $u->execute(); if ($u->getErrors()) { foreach($files as $filename) unlink($upload_path . $filename); foreach($u->getErrors() as $e) echo $e; } else { foreach($files as $filename){ $upload_path = $this->config->urls->root . 'tmp_uploads/' . $filename; $this->session->attach_markup .= $this->attachMarkup($upload_path, $filename); $_SESSION['files'][] = $filename; } } } I've changed temp directory name without a dot.(couldn't create starting a dot in WIndows system). Also that I found out Processwire API doesn't automatically create a folder, so I just manually create a folder in Windows. I can change setMaxFiles later, but for the test purpose, set this to 1. I've decided stick on setting max file upload 1 at a time. If I want to upload more file, simply run this function I guess. I couldn't figure out how to put array data on the PW session. So, I just used php session code here. Saving markup output data and each filename on the session for later use. private function attachMarkup($upload_path, $filename){ $out = <<< EOS <div> <span>Existing attachment :</span> <a href="$upload_path"> <img src="$upload_path" width='15' height='15' />$filename </a> <input type='submit' name='delete' value='Delete' /> </div> EOS; return $out; This is the attachMarkup function, which receive uploaded file path and file name to create markup. if ($this->input->post->add_file){ $this->uploadImage(); $attached_file = $this->session->attach_markup; } This should upload image file to temp directory. Whenever 'Add file' button is clicked, run this custom function. $attached_file has some markup data covering multiple file uploaded. I can simply use it like this below. <?php echo $attached_file; ?> in the middle of html code. 3. Now that I should move this image to the page. After filled with subject, body, and image files, clicking a submit to send entire form should save all these data on the page. I've used another custom function called processInput. private function processInput() { switch ($post->type) { $newPost = new Page; ............................................// all other fields data to save here such as title, name and so on $newPost->of(false); // put images into the image fields if ($_SESSION['files']){ foreach($_SESSION['files'] as $filename){ $filename_with_path = $this->config->paths->root . 'tmp_uploads/' . $filename; $newPost->forum_images = $filename_with_path; // save image into forum_images field unlink($filename_with_path); $this->session->remove(attach_markup); unset($_SESSION['files']); } } $newPost->save(); } } Because $_SESSION['files'] is the array, I have to use foreach saving each image file onto the page. Using unlink PHP function to remove files I've uploaded to temp directory. Same as attach_markup and $_SESSION['files'] data. It is no longer needed anymore. Once everything are saved correctly, image file data can easily pull out. foreach ($somepage->images_fld as $img) echo "<img class='crbox' src='{$somepage->images_fld->url}$img' />"; From the $somepage that has field named 'images_fld', I can pull out url like $somepage->images_fld->url and filename like I did above. There are some other issues I'm fighting for. If a user go back out from the form page, now that I have to remove session data and uploaded files. Thank you.
    3 points
  2. Hi Folks, today we will learn how to set up a simple jquery plugin called calendario and fill events trough our admin backend. || ATTENTION || Modern Browser needed First of all, we need the jquery plugin. Grab your copy here: http://tympanus.net/...alendar-plugin/ Now create a new template file, lets call the file calendar.php In the next step we have to include all the needed files from the .zip package. You need the following .css files: calendar.css custom_2.css demo.css Just include them in the <head> </head> of your template file. Feel free to merge them together, so you could save some http connects. Now we need to include the needed javascript. Make sure you have included the latest jQuery library. Include the jquery.calendario.js and the modernizr.custom.63321.js right into the bottom of your template file. Save the calendar.php Now we will set up Processwire where the magic wil happen. We just need one new template. Create a new template called calendar. Assign the field headline to our template. Allow children to just use this template. Hit the save button. Now create a new Page as child of home and call it Calendar. Assign our calendar template to this page. Almost ready. Now we have to do some little scripting in our template file calendar.php Add this html markup to our calendar.php <div class="custom-calendar-wrap"> <div id="custom-inner" class="custom-inner"> <div class="custom-header clearfix"> <nav> <span id="custom-prev" class="custom-prev"></span> <span id="custom-next" class="custom-next"></span> </nav> <h2 id="custom-month" class="custom-month"></h2> <h3 id="custom-year" class="custom-year"></h3> </div> <div id="calendar" class="fc-calendar-container"></div> </div> </div> Now we have to call the javascript function, to get the calendar running. Just put this snippet right under the included jquery.calendario.js <script type="text/javascript" $(function() { var transEndEventNames = { 'WebkitTransition' : 'webkitTransitionend', 'MozTransition' : 'transitionend', 'OTransition' : 'oTransitionend', 'msTransition' : 'MSTransitionend', 'transition' : 'transitionend' }, transEndEventName = transEndEventNames[ Modernizr.prefixed( 'transition' ) ], $wrapper = $( '#custom-inner' ), $calendar = $( '#calendar' ), cal = $calendar.calendario( { onDayClick : function( $el, $contentEl, dateProperties ) { if( $contentEl.length > 0 ) { showEvents( $contentEl, dateProperties ); } }, caldata : { <?= getEvents(); ?> // this is our function to grab our events }, displayWeekAbbr : false } ), $month = $( '#custom-month' ).html( cal.getMonthName() ), $year = $( '#custom-year' ).html( cal.getYear() ); $( '#custom-next' ).on( 'click', function() { cal.gotoNextMonth( updateMonthYear ); } ); $( '#custom-today' ).on( 'click', function() { cal.gotoNow( updateMonthYear ); } ); $( '#custom-prev' ).on( 'click', function() { cal.gotoPreviousMonth( updateMonthYear ); } ); function updateMonthYear() { $month.html( cal.getMonthName() ); $year.html( cal.getYear() ); } // just an example.. function showEvents( $contentEl, dateProperties ) { hideEvents(); var $events = $( '<div id="custom-content-reveal" class="custom-content-reveal"><h4>Termine am ' + dateProperties.day + '. ' + dateProperties.monthname + ' ' + dateProperties.year + '</h4></div>' ), $close = $( '<span class="custom-content-close"></span>' ).on( 'click', hideEvents ); $events.append( $contentEl.html() , $close ).insertAfter( $wrapper ); setTimeout( function() { $events.css( 'top', '0%' ); }, 25 ); } function hideEvents() { var $events = $( '#custom-content-reveal' ); if( $events.length > 0 ) { $events.css( 'top', '100%' ); Modernizr.csstransitions ? $events.on( transEndEventName, function() { $( this ).remove(); } ) : $events.remove(); } } }); </script> We are almost finished, but we are missing some very essential, have a look to our javascript. We are calling a function named getEvents() This function will grab our events and fire it right to our calendar. So here is the code: function getEvents() { $events = wire('pages')->get("/calendar/")->children(); foreach ($events as $event) { echo "'$event->title' : '<span>$event->headline</span> ',"; } } Put this snippet above the javascript includes. We will now create our first entry. Go back to the PW admin backend and create a Child of Calendar. Title and name need the Date on which the event has to be displayed. You have to form a date in this format: mm-dd-yyyy e.g. 12-27-2012. The headline field is our Event description. Hit the save button, go to your site and enjoy your event calendar. With a little coding you could extend the calendar to let it look like mine attached as screenshot. Hope this was useful to somebody. Cheerio.
    1 point
  3. Would be nice to be able to upload images from the clipboard. I investigated a bit how the image field could be extended with this and found some useful information here http://www.smartjava.org/content/copy-and-paste-images-your-browser-using-w3c-clipboard-api Turns out that we couldn't just catch a ctl+v command like in that example, because we have text area and other image fields where we might be pasting on the same page. The solution could be to create a hidden (opacity:0) element somewhere in the uploads box with the attribute "ContentEditable" (I tried, for intance, over the "drag and drop files in here" span) so we can use the paste entry in the context menu. Here is an example of how it can work https://github.com/JoelBesada/pasteboard/blob/master/assets/js/modules/copyandpaste.coffee from the source code of http://pasteboard.co/ You people think this might be usefull? Is it doable? edit: see the next post
    1 point
  4. This module provides simplified (no fancy diff etc. features available, at least yet) version control for text type fields. Originally introduced in another post as a proof of concept, I'm now considering it stable enough to deserve a thread of it's own here. Just so that you know: I've tested this module in multiple ProcessWire installations, three or four different versions in total running on two different platforms, but it still hasn't seen too much real world use. Any information you folks can provide me about how well (or badly) it worked (or didn't work) for you would be considered extremely helpful! So, what does it do? When editing pages, fields with old revisions available show up with a new icon in their header bars. By hovering that icon you get a list of available revisions and by clicking any one of those the value of that particular field is reverted to that revision. No changes are made to page until you choose a revision and save the page, which means that you can keep switching between revisions to get an idea what's really changed without inadvertently causing any content to change. How does it work? Behind the scenes hooks provided by ProcessWire are utilized to catch page edits. If text fields (such as FieldtypeText, FieldtypeTextarea etc.) selected at module configuration to be tracked were changed, their values (along with some metadata) are saved to two custom database tables. See attached screenshots for better idea about how this thing works. Please note that before you've selected at least one template + field combination to be tracked via module settings nothing will be saved to database! Getting started Module is available at GitHub: https://github.com/teppokoivula/VersionControlForTextFields. Here's a direct download link if that's what you prefer. Installation instructions etc. are available at README.md. If you've got any questions, feel free to post them here or PM me!
    1 point
  5. Imagine a hotel website. Done? Yeah, most of them look the same ;-) In this project I took another approach. The client is - thank PW - able to (re)create the whole look of his website by changing tiles (images, sizes, texts). The size adapts to the screen size, so on nearly every device the look is different. But not the user experience. After one week online I can say: It works. Thanks to a lot(!) of image material and an engaged client it is one of the biggest sites I've ever made. There is a lot to discover (only german yet, english is due in May). So click around... Der Blaue Reiter - Design Hotel Karlsruhe
    1 point
  6. Hi stefan, This is not possible at the moment (sorry Nico ) Only those characters are supported for page names: [-_.a-zA-Z0-9/] More information in this thread: http://processwire.com/talk/topic/3000-non-alphabetic-page-name/?p=29532 Cheers too, stefan too
    1 point
  7. Hello Ryan, In the introduction you write that there is an issue when using ProCache with the LanguageLocalizedURL module. Is this still an issue and if so when do you expect it will be save to use? Thanks BTW, and thank you and all contributors for making ProcessWire for what it is (and will be in the future). With Processwire I feel like starting to build what I want instead of first stripping what I don't want. I've tried several CMSs and examined how far I could get (with my limited coding capabilities) to make exactly what I want. Processwire is the first that hasn't stopped me and doesn't force me to make all kinds compromises.
    1 point
  8. Hey all, I've converted the ProcessWire 2.3 rules to Nginx. Hope this will help some people Greetings, Niek server { listen 80; listen 443 ssl; root /var/www/example.com/public_html; server_name example.com www.example.com; ssl_certificate /etc/pki/tls/certs/example.com.crt; ssl_certificate_key /etc/pki/tls/private/example.com.key; client_max_body_size 50m; access_log /var/www/example.com/_logs/access.log; error_log /var/www/example.com/_logs/error.log; # ----------------------------------------------------------------------------------------------- # Set default directory index files # ----------------------------------------------------------------------------------------------- index index.php index.html index.htm; # ----------------------------------------------------------------------------------------------- # Optional: Redirect users to the 'www.' version of the site (uncomment to enable). # For example: http://processwire.com/ would be redirected to http://www.processwire.com/ # ----------------------------------------------------------------------------------------------- if ($host !~* ^www\.) { rewrite ^(.*)$ $scheme://www.$host$1 permanent; } # ----------------------------------------------------------------------------------------------- # Access Restrictions: Protect ProcessWire system files # ----------------------------------------------------------------------------------------------- # Block access to ProcessWire system files location ~ \.(inc|info|module|sh|sql)$ { deny all; } # Block access to any file or directory that begins with a period location ~ /\. { deny all; } # Block access to protected assets directories location ~ ^/(site|site-[^/]+)/assets/(cache|logs|backups|sessions|config|install|tmp)($|/.*$) { deny all; } # Block acceess to the /site/install/ directory location ~ ^/(site|site-[^/]+)/install($|/.*$) { deny all; } # Block dirs in /site/assets/ dirs that start with a hyphen location ~ ^/(site|site-[^/]+)/assets.*/-.+/.* { deny all; } # Block access to /wire/config.php, /site/config.php, /site/config-dev.php, and /wire/index.config.php location ~ ^/(wire|site|site-[^/]+)/(config|index\.config|config-dev)\.php$ { deny all; } # Block access to any PHP-based files in /templates-admin/ location ~ ^/(wire|site|site-[^/]+)/templates-admin($|/|/.*\.(php|html?|tpl|inc))$ { deny all; } # Block access to any PHP or markup files in /site/templates/ location ~ ^/(site|site-[^/]+)/templates($|/|/.*\.(php|html?|tpl|inc))$ { deny all; } # Block access to any PHP files in /site/assets/ location ~ ^/(site|site-[^/]+)/assets($|/|/.*\.php)$ { deny all; } # Block access to any PHP files in core or core module directories location ~ ^/wire/(core|modules)/.*\.(php|inc|tpl|module)$ { deny all; } # Block access to any PHP files in /site/modules/ location ~ ^/(site|site-[^/]+)/modules/.*\.(php|inc|tpl|module)$ { deny all; } # Block access to any software identifying txt files location ~ ^/(COPYRIGHT|INSTALL|README|htaccess)\.(txt|md)$ { deny all; } # Block all http access to the default/uninstalled site-default directory location ~ ^/site-default/ { deny all; } # ----------------------------------------------------------------------------------------------- # If the request is for a static file, then set expires header and disable logging. # Give control to ProcessWire if the requested file or directory is non-existing. # ----------------------------------------------------------------------------------------------- location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|eot|woff|ttf)$ { expires 24h; log_not_found off; access_log off; try_files $uri $uri/ /index.php?it=$uri&$args; } # ----------------------------------------------------------------------------------------------- # This location processes all other requests. If the request is for a file or directory that # physically exists on the server, then load the file. Else give control to ProcessWire. # ----------------------------------------------------------------------------------------------- location / { try_files $uri $uri/ /index.php?it=$uri&$args; } # ----------------------------------------------------------------------------------------------- # Pass .php requests to fastcgi socket # ----------------------------------------------------------------------------------------------- location ~ \.php$ { # Check if the requested PHP file actually exists for security try_files $uri =404; # Fix for server variables that behave differently under nginx/php-fpm than typically expected fastcgi_split_path_info ^(.+\.php)(/.+)$; # Set environment variables include fastcgi_params; fastcgi_param PATH_INFO $fastcgi_path_info; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; # Pass request to php-fpm fastcgi socket fastcgi_pass unix:/var/run/example.com_fpm.sock; } }
    1 point
  9. Current method with template based access control works very well in most of the sites and apps. But if you have lots of "horizontal" needs, then it gets complicated. What I mean with horizontal needs is things like: we need to have 15 news sections with different editors and readers. Each of those news sections are in different parts of the site tree. Template based access control just falls short here, since we don't want to duplicate those 15 news templates (and create new duplicate each time we need new news section). News section is just an example, it could be also things like "workgroup section", "blog" or "private room" etc. CustomPageRoles module definitely helps here and I have been able to do all the things with it. But our sites usually are dynamic in a way that client themselves need to create those sections. Since CustomPageRoles build upon the template access control, it still needs quite a clicking on template access tabs etc. I have also made some tweaks to that module that I need to share. I like the idea of "global" and "local" - you could add "local" access control that will be inherited from some part of the site. See this: Home (home) -- services (basic-page) -- news (news) -- -- news item 1 (news-item) -- -- news item 2 (news-item) -- -- office intranet (intranet) * -- -- -- our rules (basic-page) -- -- -- office news (news) -- -- -- -- office news item 1 (news-item) -- -- -- -- office news item 2 (news-item) I would have defined my global template access like this: home guest role - view access office-member role - edit access * Then I would have added local template access to page "office intranet" and have defined there these rules: intranet guest role - no view access office-member role - view access office-admin - edit access news guest role - no view access office-member role - view access office-news-editor - edit access office-admin - edit access Not sure how complicated this would get, but I still find the current way a little bit cumbersome for our sites (with lots of "horizontal needs").
    1 point
×
×
  • Create New...