Leaderboard
Popular Content
Showing content with the highest reputation on 07/18/2014 in all areas
-
Glad you worked it out. Just a small note on PHP syntax: date(Y) will work, but will throw a: Notice: Use of undefined constant Y - assumed 'Y' error It should be: date("Y")2 points
-
Processwire is the tool for building anything ....lots of examples around the forums...2 points
-
Hi guys, recently, I'm reading Stephen Hay's "Responsive Design Workflow" and am fascinated by its idea of "Content reference workflows". In short: this approach does not use any software like OmniGraffle, MS Visio, etc. but plain HTML. This way the wireframes can be responsive (and be created quickly since one is at home in HTML anyway). The other thing is, that these type of wireframes are very minimalistic and, instead of a detailed graphic-design-like approach, it more or less uses two colors, borders and labels. So the danger of mistaking these wireframes as a design proposal is minimized. And since metaphors are always good I tried to tweak this philosophy with a well known instrument of the "analogue" world: blueprints. This way, at least thats the intention, it becomes even more clear for the customer that this is an abstraction. If you communicate it right, for example with a explainatory popup/modal, no customer ever should misunderstand it and ask: "What? My website is meant to be blue?" Find some screenshots below and a demo of what I'm aiming for here: http://demo.marcus-herrmann.com/blueprint-wireframes/ Before I confront any more customers of mine with this approach I would be very thankfully to hear any feedback on this from fellow developers. What is your (or your employer's) approach on this? Are there any obvious quirks with this one? As usual, you can find the code on GitHub: https://github.com/marcus-herrmann/blueprint-wireframes Have a nice weekend! Marcus1 point
-
Hey guys, got asked to share how to set up mpdf with processwire so it's time to make a little tutorial Disclaimer: ( ) This is my first tutorial and I'm not a real coder yet so every tips and hints are highly appreciated Grab a copy of mPDF unzip it and put it in a nice place outside of your Processwire folder(s) - (as far as I remember is has to be outside or within a module to work, but I could be wrong?!) Open the template from which you want to create the PDF from In my case I have a "course.php" which is showing a page with a weekly schedule table and I wanted to provide this schedule as pdf next to the website version. I turned on urlSegments for "course" template, because I find it nicer than a get variable Then in my course.php template file after the normal website output I added the following It's probably better to have this logic at the very top of the template file to prevent unnecessary code execution right?? Aha, now I remember why it's at the bottom. I have some more logic above it which I wanted to share for browser output and pdf creation and this was the easiest way, probably I'll rearrange everything to make it faster At least the if( file_exists logic could go at the very top <?php // In case you don't have other urlSegments it's better to throw a 404 when someone types a non existing url, // could be managed better but at the moment it's easier if($input->urlSegment1 && $sanitizer->pageName($input->urlSegment1) != 'pdf') throw new Wire404Exception(); // if urlSegment /pdf/ output course table as PDF file if($sanitizer->pageName($input->urlSegment1) === 'pdf') { // $config->paths->files = PWs /assets/files/ folder, page ID and the title of the page could be any field or anything else // maybe you want to add the date $pdfPath = $config->paths->files . $page->id . "/" . $page->title.'.pdf'; // Options for wireSendFile because they're needed more then once $wireSendOptions = array('exit' => true, 'forceDownload' => true, 'downloadFilename' => ''); // If file already exists force download it and stop further execution which is handled $wireSendOptions 'exit' => true if(file_exists( $pdfPath )) wireSendFile($config->paths->files . $page->id . "/" . $headline.'.pdf', $wireSendOptions ); // include mPDF.php conditionally for localhost and productive website, you probably don't need it if structure is the same // included it at this point because we don't need it to provide an existing file // you could even include it after your output logic just before PDF creation.. if($config->httpHost == 'localhost') { include("../../../../classes/MPDF57/mpdf.php") } else { include("../../../classes/MPDF57/mpdf.php"); } // at this point you create the logic for your output // I'm not sure wether mPDF understands single 'quotes' properly // TCPDF doesn't really liked them so I stick to double "quotes" for now // just a little example how it might look you can of course have a loop populate everything from $page or somewhere else ;-) $pdfOutput = '<table class="data"> <tr> <th>Entry Header 1</th> <th>Entry Header 2</th> <th>Entry Header 3</th> <th>Entry Header 4</th> </tr> <tr> <td>Entry First Line 1</td> <td>Entry First Line 2</td> <td>Entry First Line 3</td> <td>Entry First Line 4</td> </tr> <tr> <td>Entry Line 1</td> <td>Entry Line 2</td> <td>Entry Line 3</td> <td>Entry Line 4</td> </tr> <tr> <td>Entry Last Line 1</td> <td>Entry Last Line 2</td> <td>Entry Last Line 3</td> <td>Entry Last Line 4</td> </tr> </table>'; // now the best part // the next comment explains the mPDF() parameters as in the manual http://mpdf1.com/manual/index.php?tid=184 // mode, format, default_font_size, default_font, margin_left, margin_right, // margin_top, margin_bottom, margin_header, margin_footer, orientation $mpdf = new mPDF('utf-8','A4-L', 0, '', 5, 5, 16, 6, 5, 5, 'L'); // The header is repeated on all pages, it's possibly to have different headers (even/odd) and other fancy stuff // You can have images as well, just have a look at the documentation it's pretty good $mpdf->SetHTMLHeader("<h2>{$page->title}</h2>"); // this one puts your table, created above, into the file $mpdf->WriteHTML($pdfOutput); // I'm saving the PDF file to the disc first as set in line 9 // 'D' would output the file inline in the browser window but then we're not able to store it for faster serving $mpdf->Output($pdfPath,'F'); // Thanks to Ryan and his nice functions we can use wireSendFile (as above) to get the created file and force download it wireSendFile($pdfPath, $wireSendOptions ); } // End if /pdf/ If you want to create the file everytime it's called and don't want the it to get stored just strip line 12, 15 and 67 and change the 'F' in line 64 to 'D' If you want to have a newly created file each time you change the page you have to install a little module to hookAfter page save It's just one file, I called it like hooks.module because maybe I will add some hooks later and there is no need to have each hook in a separate module. <?php class Hooks extends WireData implements Module { public static function getModuleInfo() { return array( 'title' => 'Custom Hooks', 'summary' => 'Hooks, PDF deletion on page save for example', 'version' => 1, 'autoload' => true, // You want it to autoload, otherwise it would never get called ); } public function init() { $this->pages->addHookAfter('save', $this, 'deletePDF'); //initialise the hook } // Most of it is just copied from Pages2PDF module from Wanze, a little 'simplified' though^^ public function deletePDF(HookEvent $event) { $page = $event->arguments[0]; $pdf = wire('config')->paths->files . $page->id . "/" . $page->title.'.pdf'; if (file_exists($pdf) && is_file($pdf)) { $name = $page->title.'.pdf'; if (@unlink($pdf)) { $this->message($this->_(sprintf("The following file got deleted '%s'", $name))); } else { $this->error($this->_(sprintf("Failed to delete '%s'", $name))); } } } } Hope you can follow the steps. Please let me know if not and why Any improvements are welcome because I would love to learn more as well1 point
-
Eheh, I give an example for my second suggestion on that thread, thanks Adrian http://modules.processwire.com/authors/adrian/1 point
-
Or you can use SQL directly as per Ryan's suggestion to a similar question I had: https://processwire.com/talk/topic/3053-possible-to-select-modifiedcreated/?p=30093 It always feels dirty to me to query and then truncate1 point
-
Not possible, you can only have field names on the left of the operand. Alternatively you could either find all the pages where price is not empty, and then remove the ones where retail price is the same inside a foreach: // not tested $result = $pages->find('Price!='); foreach ($result as $r) { $result->remove($result->get("RetailPrice=$r->Price")); } or create a new field that holds the diference of those two fields by hooking on page save to populate it.1 point
-
You might also want to have a look at some ready solutions for selling digital goods. Smashing Mag has a good article about it http://www.smashingmagazine.com/2012/03/29/selling-digital-goods-online-e-commerce-services-compared/1 point
-
There is this mention: https://processwire.com/talk/topic/5281-paypal-payment-method-for-processwire-shop/?p=67668 So long as whatever payment system you are using (Paypal in the example mentioned above) has some way of securely confirming that the user's payment has been received, you can easily make the download available based on whether a "paid" flag has been set for their order.1 point
-
@marcus: I think profiles can really push PW forward. For the developers starting their way with the CMS (like me) it is a good way to learn by reading someone else's code. For the non-coders it is certainly easier to start with a profile. I found out about this one only due to Teppo's flamingruby blog, while having visited site profiles page several times. If it is not as polished as it could be, you can mark it as "early beta" (but as everything good in modules directory seems to be in beta it probably won't stop anyone) . I think some communities shall grow around those profiles. Reading that PW vs WP article I started thinking that Processwire is the tool for building Wordpress-like systems (and Ryan's blog profile is the proof to that). But not only Wordpress-like. We should have both examples of the capability of PW and easy to use systems (read "profiles") build on it. Your profile is both. If I got it right you used Pure css framework, which is not demonstrated in other profiles. So only that is worth looking at.1 point
-
Now available on the module directory: http://modules.processwire.com/modules/schedule-cloud-backups1 point
-
Yep it does. If not installed, calling the MarkupCache like below will install it and function. $cache = $this->modules->get("MarkupCache"); // See the $this-> call if(!$data = $cache->get("something")) { $data = "test me"; $cache->save($data); } return $data; // contains "test me"1 point
-
Hi everyone! It's been a little bit of time since the update - the last month was very busy, but we are on the track and planning to release the first public beta version of PassiveCron / cron.pw in the next week. Like the previous previews, I want to share with you two additional features of cron.pw. 1) Dashboard Just like minimize.pw, cron.pw comes with a Dashboard, on which you can control every background task and upgrade your plan. It looks a lot like minimize, although it's blue this time ;-) 2) Task Reports cron.pw lets you take a look at the history of every module's tasks and their executions. This allows you to check out - if necessary - if a certain task has been executed correctly. ... and to enhance your development abilities, cron.pw lets you also inspect every task in detail, including transmitted request parameters and response output. Thank you in advance for your feedback!1 point
-
Quick question: does your module enable backup to Amazon Glacier, which is cheaper than S3? http://aws.amazon.com/glacier/1 point
-
Hi folks, I have refactored the module and a new version is available on the dev branch here: https://github.com/wanze/Pages2Pdf/tree/dev The module now uses mpdf in the background which has superior HTML/CSS support compared to TCPDF, but the library is slightly heavier. What's new? Creating PDFs is handled by a separate module "WirePDF". This module is just a wrapper around mpdf and you could also use it independently from Pages2Pdf as a Service to create/save/download PDF files from ProcessWire templates All the configuration options related to configure mpdf (margins, document orientation...) are now defined in the module WirePDF Some new config options in module pages2pdf. You can configure the PDF filename and the GET variable that is used when requesting a download You can download a PDF from any page The default templates have changed, with mpdf you now can use a separate stylesheet to separate CSS from HTML markup Triggering the creation/download of a PDF file is handled earlier: After the ProcessWire API is ready but before page rendering is initialized. This should improve the performance. Calling the render() method is technically no longer required, but it can still be used to output the download link. However, you could write the link by yourself if you prefer. If you'd like to test out the new version and upgrade the module: Please note down all the current settings Uninstall pages2pdf module, then replace it with the current one Install the new version Maybe add your previous settings in the WirePDF module. Some settings are no longer supported or have changed slightly If you created manual links to triggering the download in your templates, e.g. added ?pdf=1, you should change the GET variable in the module configs from 'pages2pdf' to 'pdf' Take a look at the default_templates in /site/modules/Pages2Pdf. With mpdf, it's better to separate CSS from HTML, so you can create a "styles.css" in /site/modules/templates/pages2pdf/ and define all CSS styles there. The styles are then availalble in your templates. I hope that's the most important stuff. I'm short in time today (going to a festival), so I can't support Cheers1 point
-
But Ivan is right - I could really publish it there: http://modules.processwire.com/categories/site-profile/ Will do it, but with a big "This! Is! Alpha!" warning sign The very rudimentary state actually kept me from putting it there until now. But thanks for the feedback1 point
-
Okay so what happens if: I take a copy of the production site (incl. database) and make some changes on my local machine. At the same time my client logs in and edits something, or the production database is otherwise altered. Then, I dump my db, and upload it and the files to the production server. You have just overwritten your client's changes. If you can ensure that they will not make any changes during the time between you taking a copy, and uploading the changed database, it works fine. Unfortunately I cannot make this guarantee. Additionally, since the metadata is in the database, rather than files, it will not be tracked by your version control system (assuming you're using one). This also makes collaborating with other developers much harder than it needs to be.1 point
-
Just re-read your message, and just wanted to make this clear: I do not make assumptions about your design. When I ask questions, challenge your ideas, or propose alternatives, I'm merely testing the boat to see if it holds water - it's nothing personal, it's just the way my mind works. And most of the time, you are able to clarify your objectives or explain your choices to my satisfaction ... as Einstein said, "question everything" - this is how we arrive, not at perfection, but as you say, the best possible choices gives the context and goals. Please assume that I'm trying to help - if my tone suggests otherwise, I apologize, I'm not always eloquent with my words. I never got on the Drupal, Joomla or WordPress forums to try to help there - because I never saw any of those projects as being worth my time. This project is. So I hope you'll put up with me, even if I ask obnoxious or provocative questions at times. As Rafael Dohms just pointed out on Twitter: Discussion is evolution, whether you are right or wrong the exercise of discussing will teach you something new.1 point
-
Joss actually emailed me a similar question and I'll duplicate my reply here since it seems relevant: Performance as it relates to database is really not an issue that one needs to consider much (or at all) when it comes to creating their fields. Most field data in ProcessWire is loaded on-demand. It loads data selectively and only when it needs it. This enables it to be highly memory efficient with large quantities of pages in memory at once. When you have a $page, behind the scenes, none of the page data is actually loaded until you access it. For instance, if you access $page->body, then it goes and retrieves it at that moment (if it hasn't already retrieved it before). MySQL is extremely fast with simple primary key, non-joined selects, and we take advantage of that. What I'm trying to get across is that quantity of fields does not translate to an increase in joins or other factors that would slow the system down. Where ProcessWire does join data automatically is at page load time is when you check the "autojoin" box on a Field's "advanced" tab. Some fields you know will always be needed with every $page instance, and that's what autojoin is for. Typically, I make my "title" field autojoin, as it is already by default. I've hidden that autojoin option under the Advanced tab simply because most people never need to consider it. The original intentions behind autojoin have become less applicable than I originally thought [with regards to performance], so it's not something that comes up that often. ProcessWire also uses joins when it performs queries for $pages->find("selector"), and related DB-querying selector functions. It joins all the tables for fields that you query. So if you perform a find for "date>2012-12-19, body*=holidays" then it's going to join the field_date and field_body tables when a value matches. Though it doesn't do this for the purpose of loading the data, only for matching the data. Technically this type of query could be potentially faster if all those fields were in one table. But that doesn't translate to results that matter for us, and doesn't affect the way that you should use ProcessWire. The benefits of our one-table-per-field architecture far outweigh any drawbacks. I put a lot of time into finding the right architecture and balance here when coding ProcessWire 2. Incidentally, ProcessWire 1 did use the one-table approach (all the field data was stored with the page rather than in separate tables) and it was far less efficient with memory, and about the same in terms of performance. It's better to re-use something like "body" (when possible) rather than create "article_maintext" or other template-coupled variations like that. The reasons for that are for your own benefit. It is less to keep track of, and tends to foster better consistency. It also results in more reusable code and broadens the potential of where the data can be used. Take the example of an on-site search engine, like you see in the upper right corner of processwire.com. If we know that the main text field(s) of most templates has some consistency in their field names (like title and body), then we can write code that doesn't need to know whether something is an article, a press release or a product. We can find all pages that match "holidays" in the text just by doing this: $pages->find("title|body*=holidays"); But if created a separate textarea field for every template, then any code that queries those fields needs to know a lot more about them: $pages->find("title|article_maintext|pr_maintext|product_maintext*=holidays"); While that still works, it doesn't scale nearly as well. This also translates to the code you use to output the results. If you want to show a snippet of the matching text with the search results, you are going to have a lot more fields to consider than just "body". Now if each of your templates genuinely needs very different settings for each of their main text fields, then of course it's fine to create them as you need them. But in the real world, I think you draw more benefit by planning for reusability when possible. The benefits are for you (the developer), as it doesn't matter much to ProcessWire. Reuse fields where it's obvious that the name of the field makes sense in the context of multiple templates. If template "employee" needs a date_of_birth field and template "press_release" needs a date_publish field then just create one field called date and use it on both templates. On the other hand, if you need multiple date fields on the same template (like date_unpublish) then more specific field names start to make sense. In that case, I would usually use my date field for publish date, and create a separate date_unpublish field for my unpublished date field. Though some may prefer to actually have separate date_publish and date_unpublish fields because they are obviously related by name. Ultimately, use what works best for you, but always keep an eye out for obvious reusability potential with fields. I think that most people naturally arrive at the right balance for their needs after some experimentation. What is a best practice for one need might not necessarily be for another. So these are mostly general purpose guidelines and people should find what makes the most sense in their context. For the majority of cases, I think avoiding tightly coupled template and field names is a better strategy. TL;DR: It doesn't matter to ProcessWire what you do. Aim to reuse fields when you can and when it makes sense, for your benefit.1 point