Leaderboard
Popular Content
Showing content with the highest reputation on 08/31/2014 in all areas
-
Save process: $page->fieldName = 'value'; sends 'value' to Fieldtype::sanitizeValue(); and then sanitized value is kept with $page. $pages->save($page); calls Fieldtype::savePageField() for each field on the page that changed. Numbers 3 and 4 below repeat for each of these calls. Fieldtype::savePageField() calls Fieldtype::sleepValue() to return value as basic type for storage. If value is something simple like an integer or string, then sleepValue may not need to do anything at all. Fieldtype::savePageField() saves the "sleeping" value to DB. Load process: Access to $page->fieldName (i.e. $page->title) calls Page::getFieldValue(). Page::getFieldValue() calls Fieldtype::loadPageField() to load value from DB (if not previously loaded). After Fieldtype::loadPageField() loads value from DB, it calls Fieldtype::wakeupValue() to convert value from basic storage type to runtime type (i.e. array to object). If value is something simple like an integer or string, wakeupValue may not need to do anything at all. The "awake" value gets returned to Page::getFieldValue(). With this value hand, Page::getFieldValue() remembers the value so it doesn't have to pull from DB again. If $page->outputFormatting is TRUE, Page::getFieldValue() runs the value through Fieldtype::formatValue(). That modifies the value for runtime output (example: applying an entity encoder to a text value). In the case of text fields, this would be when the value is routed through Textformatter modules. Note that formatValue() is called on every access to $page->fieldName, as PW only keeps the unformatted value in memory. Page::getFieldValue() returns the value, which you see as the result of your $page->fieldName call. Note that when you get a $page object, the fields aren't actually loaded until you try to access them. Meaning the above process occurs upon field access, not at page load. However, if the field has the "autojoin" option checked, then the above process is very different. However, those differences don't matter to any Fieldtype code (or any other code I can think of). As for error handing, this would typically be done in the Inputfield module, most commonly at Inputfield::processInput or in some cases Inputfield::setAttribute('value', 'my value'). However, it is also okay to trigger errors from Fieldtype::sanitizeValue, but just note that that method will be called on values regardless of whether they came from the API, user input or from the DB. Meaning, time consuming validations are best performed at the input (Inputfield) stage. This sounds a lot like a Textformatter module. If that's your need, then your job is simple and you don't have to worry about any hooks or anything other than making a Textformatter module with Textformatter::format($value) or the newer Textformatter::formatValue($page, $field, $value). More likely you just want FieldtypeTextarea::wakeupValue, as that should be called for both instances above (FieldtypeTextareaLanguage extends FieldtypeTextarea). Most likely you are getting double calls having the two above hooks.8 points
-
5 points
-
Here's an example module that removes "Add New" button(s) on InputfieldPageTable on a condition (here if there's 2 ore more entries). Hook before InputfieldPageTable::render, then add hook after InputfieldButton::render. Since InputfieldButton is used by PageTable, we just use that hook to empty the returned markup for the button. Then remove that button hook after the InputfieldPageTable rendered. https://gist.github.com/somatonic/c9db5c43f10d050bb14d5 points
-
EDIT: Ignore this idea completely - soma's solution hooking into InputfieldButton::render is obviously a much better idea I don't have time right now to put a working solution together, but you'll want to hook into InputfieldPageTable::render and do an $event->replace = true and then scan the content and strip out the add new button. You could do that with a regex, eg: function strip_selected_tags_by_id_or_class($array_of_id_or_class, $text) { $name = implode('|', $array_of_id_or_class); $regex = '#<(\w+)\s[^>]*(class|id)\s*=\s*[\'"](' . $name . ')[\'"][^>]*>.*</\\1>#isU'; return(preg_replace($regex, '', $text)); } or perhaps more efficiently with domdocument's removeChild() - eg: http://stackoverflow.com/questions/12903483/remove-a-domnode-with-a-certain-class-in-php Something like this: <?php class RemoveAddButton extends WireData implements Module { public static function getModuleInfo() { return array( 'title' => 'Conditionally Remove Page Table Add Button', 'version' => 1, 'singular' => true, 'autoload' => true ); } public function init() { $this->addHookAfter('InputfieldPageTable::render', $this, 'removeButton'); } public function removeButton(HookEvent $event) { $event->replace = true; if(count(array)==0){ $event->return = regex or removechild here to remove button from original $event->return; } } Hope that gets you going. Otherwise, I'll put something working together for you tomorrow.4 points
-
Hello, So I'm working on a PW project in a shared hosting like Hostgator. For this to work you need ssh access, and of course git. I always have problems working with FTP, I feel my productivity decreases when using them, also you have no control over changes that are made. So a single file deletion could cause a big catastrophe. The first thing you have to do is cloning the PW repo, and checkout to dev branch Here we clone the repo, use the dev branch. Delete the entire PW git directory and initialize a new one $ git clone https://github.com/ryancramerdesign/ProcessWire/ $ cd ProcessWire $ git checkout dev $ rm -rf .git $ rm .gitignore $ git init $ git add . $ git commit -m "Initial Commit" Note: The file .gitignore from the dev branch have some files that you want to be commited, like /sites. I recommend deleting that file and create a new one. Ok, now we need to configure our remote repo inside the shared hosting. You need to login using a terminal. Linux and Mac have ssh already installed, if you are in Windows you can use Putty. ssh username@domain.com -p 2222 ... Enter your password: ********* Now we need to authorize our computer in the hosting, so we can push the commits. We need the contents of ~/.ssh/id_rsa.pub located our computer. A more complete guide for generating such keys is available here. Then we will copy the contents to ~/.ssh/authorized_keys. create the authorized_keys in the hosting if not exists using touch ~/.ssh/authorized_keys The next step is creating a new repo and configure some hooks in our server. $ mkdir www/processwire $ cd www/processwire $ git init $ git config receive.denyCurrentBranch ignore $ cd .git $ cd hooks $ touch post-receive The contents of post-receive hook should be. (this is a ruby script, but could be any language available on the server) #!/usr/bin/env ruby # post-receive # 1. Read STDIN (Format: "from_commit to_commit branch_name") from, to, branch = ARGF.read.split " " # 2. Only deploy if master branch was pushed if (branch =~ /master$/) == nil puts "Received branch #{branch}, not deploying." exit end # 3. Copy files to deploy directory deploy_to_dir = File.expand_path('../') `GIT_WORK_TREE="#{deploy_to_dir}" git checkout -f master` puts "DEPLOY: master(#{to}) copied to '#{deploy_to_dir}'" # 4.TODO: Deployment Tasks # i.e.: Run Puppet Apply, Restart Daemons, etc Now we make it executable using chmod $ chmod +x post-receive With all that done, we should enable a passwordless login so we can push without a password prompt on every push. In our local machine look for this file ~/.ssh/config And add this text (Change your-domain.com and port as needed) Host your-domain.com Port 2222 PreferredAuthentications publickey Now we should go to our project directory and add the remote host with $ git remote add hosting user@domain.com:www/processwire $ git push --set-upstream hosting master This should do the trick for commiting changes and upload files without ftp. Now we must install Processwire and then pull the changes. Go to your domain and start PW setup. once you are ready installing processwire, you need to pull changes that PW installer made. Login to your hosting via ssh and commit the changes that installer made. $ ssh user@domain.com $ cd www/processwire $ git rm $(git ls-files --deleted) $ git add . -f $ git commit -m "Initial PW Setup" When that is ready go back to your local machine and pull the repo. $ cd Processwire $ git fetch $ git reset --hard hosting/master Now we are finally ready to start working with PW in shared hosts or other machines that have ssh enabled. simply makes changes like $ touch site/templates/welcome.php $ git add . $ git commit -m "Added welcome.php" $ git push Now if you have some problems you can zip the setup using $ git tag -a v0.0.1 -m "Initial PW Setup" $ git archive --format=zip --output=pw.zip v0.0.1 And download the file and work from there Thats all References: http://www.arlocarreon.com/blog/git/push-git-repo-into-shared-hosting-account-like-hostgator/ http://ahmadassaf.com/blog/miscellaneous/how-to-use-git-to-host-and-push-projects-on-shared-hosting-services/ http://motorscript.com/setting-up-a-remote-git-repo-on-shared-server-like-hostgator/ http://krisjordan.com/essays/setting-up-push-to-deploy-with-git http://git-scm.com/book/en/Customizing-Git-Git-Hooks3 points
-
Update: Version 1.3.0 - 31 August 2014 Summary of Changes Version 1.3.0 BlogPublishDate - Part of the Blog module suite, new small autoload module to save and preserve a Blog Post's publication date. The value (current time and date) is saved on Post's publish. It can be manually modified. Unless manually modified, the original published date is preserved between subsequent unpublish/publish events. Thanks @Adrian for idea, @SiNNuT and @Soma for code. For new installs, the new module will be automatically installed by PW when you install ProcessBlog. For existing installs, you will have to manually install BlogPublishDate. You will also have to set the field 'blog_date' not to automatically default to current date. Change this in Setup->Fields->blog_date. On the Input tab, scroll to the bottom and find 'Default to today's date?'. Untick the checkbox. Posts Dashboard (see screenshot) Date column: Now shows 'Pending' for unpublished posts (never before published ones), 'Expired' (published then unpublished posts) and published Date for currently published posts Date column: Date shown is formatted according to the format user set in 'blog_date'. Blog's default is 'j F Y g:i a', e.g. 8 April 2012 Date column: Sorting by date column now works correctly. Thanks @webweaver and @Teppo for solution Posts Dashboard, Categories Dashboard, Tags Dashboard Number of posts/categories/tags per page now shown - e.g. 'Posts 1 to 10 of 120' Customisable number of posts/categories/tags to show per page (via a drop-down select). Default is 10. Selected value is preserved (state saved via a cookie - browser specific, of course) per context (e.g. can have different values for posts, categories and tags dashboard) and per ProcessWire user. Thanks to @Nik for code idea. Some code clean-up Pending: - Featured image widget - Auto-publish/unpublish by set date Note: Issue in Dev: If you are running latest Dev, you will get an error about TinyMCE not being the default editor (if it is not installed), etc. when editing Posts. Follow the instructions given by PW. Once PW 2.5 is released, I will change 'blog_body' to use CKEditor.3 points
-
Okay guys I am truly overwhelmed by your support. I think this is VERY rare nowadays. That really encourages me to support PW even more by buying some Pro modules soon. It's really, really good to have a community like this! @adrian: Thank you for you effort. After reading your code it gave me a more deeper understanding on where to put the hooks! @LostKobrakai: Your dedication is stunning. And you're right: the "init" PHP is only executed front-end wise. Thank you for opening my eyes! Basically, you're right. Adding this hook globally to all pages might seem too much, but Soma does a little check before doing anything: if($table->name !== "mypagetable") return; I think the performance hit (if any) is still bearable. @Soma: Hero Member really suits you. I just copied your source from Git, installed the module and it worked out of the box! I cannot mark two posts as "solved", so the "solved" goes also to yours, adrian! Just a short follow up to working with classes: since I'm outside the normal scope of the "$pages" object, I have to use the global (ugh) "wire('pages')" inside the class instead, am I right?3 points
-
I've to add a few things here. In your other thread we where talking about denying the page creating and your idea now is hiding the button upfront. Both ways to solve your problem should be not that different to implement, as both need just hooks to work. Now, after writing the post, came this to my mind: InputfieldPageTable::render is only called on, big surprise, page render. So in your usecase, this wouldn't be great, because the limit of pages in your pagetable has to work even if the user doesn't leave the page. So I still think that my suggestion of using Pages::add would be more useful, even if it's a little bit less userfriendly, because the add button will throw an error, instead of simply disappearing. An addition to adrians post: You put your hook in the init.php in the template folder? If so, it can't work because this file is only called if your browsing the frontend. You need your hook to work in the backend. While you can use hooks in template files, we don't change the core admin template files. So the best way to get your hook into the backend is via a small module, like the one adrian posted. This example code with the docs about hooks and modules here on processwire.com should get you at least somewhere. What's missing in the code of adrian, is a condition, when to remove the "add" button. I would limit the check for players / positions to the right template or the right field in the hook and only then do the checkup.3 points
-
Here´s a videotutorial http://processwire.tv/videos/processwire-basic-guide---first-steps/?autoplay=12 points
-
Hey teppo, Minor, but fatal, bug for you. If you have Template checked under Visibility Settings and there are some entries in the log that refer to a template which has since been deleted from the system, you get a: Fatal error: Call to a member function get() on a non-object in /site/modules/ProcessChangelog/ProcessChangelog.module on line 765 Obviously just need a check to make sure that the template still exists. Thanks!2 points
-
HTML Purifier doesn't support new elements added in HTML5. It does indeed support specifying allowed elements (like you've just noted), but here's the catch: Based on a quick glance at those advanced customization features, adding support for new elements is doable, but allowing valid HTML5 tags would seem to require a custom DTD (or something like that) -- or at least a whole lot of new rules. That's where I lost my interest and switched the whole thing off. HTML Purifier has caused me more harm than good and until it gets a proper update, I don't think it's really worth it.2 points
-
Sadly there's no documentation about the progression of functions there's only this http://processwire.com/api/hooks/captain-hook/ to find hookable functions. But often the hooks are quite declarative. You want your error handling to happen when a page is saved => Page::save. Another example, when a new Page is added to the tree => Pages::add and so on. Your example of Page::render or InputfieldTextarea::render does not make sense for error handling, as this functions only generate markup. Also it's called if someone opens the page, to late for useful error handling, as the user has to reopen the page, before getting the errors.2 points
-
Hey all Since the topic of backups comes along every so often I decided to write a module to encapsulate some code I use for backups on Linux installs. It's not quite ready yet as I want a fallback option for Windows as well as an option for Linux that will work on shared hosting where you usually cant run system commands, but it is 80% complete for stage 1 and Linux backups work nicely. The general idea is that you set the number of days to store backups (I standardised it to 1 day, 3 days, 1 week, 2 weeks, 1 month, 3 months, 6 months and 1 year rather than having it as an integer field because I think these fit the most common scenarios and I wanted to have a dropdown in my module config too It defaults to 1 week, but depending on the size of the site and how much space you have you might want to increase or decrease the retention period. The idea is that you are given a URL with a unique hash (generated at install) which you then pass off to a cron job or Windows Scheduler and this generates the backups. It will be expanded on once I've got the backups working across different environments but the initial plan is to release a version that simply backs up the site and database, then a version that has a page where you can download backups from as well as an option to FTP/sync them to another server. I don't want to tackle restores though as this would be difficult - you are logged into the admin whilst running the restore so I think the first thing it would do when it has restored the database is log you out, plus I don't want to make assumptions about replacing a user's /site/ folder so I think restores require some manual intervention to be honest. An alternative would be to do this anyway but rename your /site/ folder and take another database copy before restoring, but I'm getting into the realms of trying to be too clever then and anticipate what people are trying to do and ProcessWire is all about not making assumptions Fortunately I have access to a site with several gigs if uploaded files as well as a reasonably large database so I should be able to monitor how well it handles that on Linux and Windows, but smaller sites shouldn't take more than a minute to backup, often a matter of seconds. I shall keep you posted.1 point
-
Thanks for reporting this, adrian Version 1.2.10 includes a fix for aforementioned issue and is now committed and pushed to GitHub. My approach looks kind of complicated and I might tweak that later, but it should work as intended anyway.1 point
-
Why would you "hook" into render or renderTable when you're extending the modules? If you wanted to hook into InputfieldPageTable you wouldn't need to extend it. Since you extend the inputfield you just overwrite the render method from the parent, or use its render method. public function ___renderTable(array $columns) { if($this->renderLayout) { $out = $this->attr("value"); // your method } else { $out = parent::___renderTable(); // InputfieldPageTable method } return $out; }1 point
-
I think you're missing the inputfield init() to set the properties // fieldtype and inputfield config settings $this->set('parent_id', 0); $this->set('template_id', 0); // placeholder only $this->set('columns', ''); $this->set('nameFormat', '');1 point
-
I think, it's possible to configure HTMLpurifier for html5: http://htmlpurifier.org/live/configdoc/plain.html#HTML.Allowed Must be in this file?: https://github.com/ryancramerdesign/ProcessWire/blob/dev/wire/modules/Markup/MarkupHTMLPurifier/htmlpurifier/standalone/HTMLPurifier/ConfigSchema/schema/HTML.Allowed.txt Maybe someone knows how to do this?1 point
-
Tutorial That Explains How To Incorporate A Front-End Framework In PW http://processwire.com/docs/tutorials/installing-a-css-framework/1 point
-
The small project walkthrough should get you started http://wiki.processwire.com/index.php/Small_Project_Walkthrough Or the basic website tutorial http://wiki.processwire.com/index.php/Basic_Website_Tutorial1 point
-
Hey thank you guys so I got it. Every solution I ever have come right about when Im falling asleep. It turns out I have a script that that clears the form when the modal closes but when you submit the modal closes before post is done processing. Total noob mistake, I just removed the form clear from submit click and it worked $(document).ready(function(){ $('#submitQuestion').on('click',function(){ document.getElementById("contact").reset(); }); $('#contactModal').on('hidden.bs.modal', function (e) { document.getElementById("contact").reset(); }); }); So the email was sending perfectly just without any form values that were entered. I guess I forgot about the fact that I used a redirect on send also.1 point
-
I wanted to use PW mapmarker.... but for frontend what I needed it was not suited. I now use geocomplete from ubilabs for frontend. Looks great, works excellent. The google api3 docs have an excellent video on retrieving addresses. So in my form I have 1 autocomplete address field that catches Country, State and City level (I explicitly set it to real addresses, NOT from hotels or anything) and use those values to populate fields for members. If any is missing, it would not be valid. Yes, I could use a dropdown (thousands of cities), or use a input field (no way to validate). So this was a good solution.1 point
-
@bytesource: it's really nice to build own modules. You make your hands dirty with code and get better skills in PW and PHP. But IMHO for your need to change a page-id into a link, I simply would go with hanna code module.1 point
-
Not specifically about retina images, but rather responsive images in general and the polyfill for the new standard: http://css-tricks.com/video-screencasts/133-figuring-responsive-images/ Includes mention of providing a specific 2x version of images.1 point
-
@Jan Romero: What version of PHP and MySQL are you running? You also mentioned 3rd party modules–which modules? (If not Textareas ProField?). The ProFields have been developed in tandem with the dev branch, so I'm fairly sure that wouldn't be it. But the commit you indicated did change the way module information is cached. I found one other instance of a similar upgrade error and we traced it to a bug in a specific PHP Version. That's why I'm curious about the versions of software you are running. I think this is largely the inclusion of CKEditor. The Iridium profile does take up some space since it has a lot of photos, so I may leave that one as an external install. Overall though, I think we're being pretty safe with file size. I can still download a ZIP from GitHub in less than 3 seconds, and we've never had any complaints that file size was preventing someone from trying or using PW. As a result, I think we're better off using file space where we can to make sure PW really impresses people when they download and try it out. On the other hand, we should also be safe and not include multiple RTEs, etc. For example, we removed TinyMCE when we bundled in CKEditor. There has been little demand for this, that's why it keeps getting pushed back. How many threads do you see posted of people asking for this capability? I agree it's a nice capability, and I would like it too. But I try and focus my efforts on what will get used the most. At least the non-sponsored new additions you see in 2.5 are largely based on what's been asked for repeatedly in the forums (as well as what I would personally find useful). So we'll count your request here as momentum for drafts. The funny thing is that PW1 had full drafts capability, had a huge amount of work behind it, and it worked well. The unfunny thing is that clients rarely used it. The primary time that clients (my clients at least) wanted a draft of something was when creating a page. That's why we've already got that in PW2. I ended up feeling that all the work behind drafts in PW1 was kind of a waste of time. Of course the PW2 user base is much larger and the potential audience for such a feature is much larger now. I personally would like to have drafts for already published pages too, but the reality is there's only a small segment that will actually take advantage of it. It's a feature that sounds good, but few use. Still, we may have the critical mass now for it to be worthwhile. And it's also on the checklist of many, even if they won't use it. I even have it mostly built already, and have been occasionally working on it, but it's been kept in the background as more popular features have gotten attention. I appreciate the interest of course, but I don't think this is necessary. We've already got commercial modules funding developing of ProcessWire. The focus on what gets added is also largely based on what are the most common needs people have around here, within the limits of feasibility and schedule.1 point
-
If you change the stored value of the textfield, it is of course loaded this way the next time in the backend. Dynamic transformation is done by textformatters. To accomplish your needs you could implement the evaluation and the replacement seperately. The textformatter for replacement and a hook into page::save() to check for missing / trashed IDs.1 point
-
Hi, Your module is not autoloaded - it does not get executed automatically by ProcessWire in each request. Try adding autoload=true to your getModuleInfo method. Cheers (also Stefan )1 point
-
@dragan: if you're literally using var_dump(), it should be noted that it doesn't return anything. In order to store it's value in a variable you'd need to use output buffering or some other trick. Another option is to use print_r() with return param set to true. Main difference between var_dump() and print_r() is that var_dump() provides more information about the data types involved, while print_r() only outputs content. Edit: you should also take a look at this comparison between var_dump(), print_r() and var_export().1 point
-
Nothing simpler than that. You know that every page in Admin is a page under "Admin"? So you can drag the Changelog page from /Admin/Setup/ and drop it below the /Admin/Pages page.. et voila, the page is no longer displayed under "Setup"1 point
-
Every time i set access to templates, 90% of the time a page is protected I set also "Redirect to another URL". Well could be useful to have a select and choose internal page for this redirection because I usually write something like "/login/", which is enough, but I was thinking, if a day I want to change my login url? I have to edit all the access rules for my templates...1 point