Jump to content

Leaderboard

Popular Content

Showing content with the highest reputation on 01/28/2016 in all areas

  1. I have a test version of imagesizer now where the chosen algorithm depends on available memory. If there is enough memory, it uses USM, if there is less memory, it levels down to use the other algorithm, and if there also isn't enough memory available for this, sharpening is completly skipped. After some testing I will commit this to github.
    7 points
  2. Fresh from the oven!! http://www.cloudways.com/blog/processwire-ryan-cramer-interview/ Now I will read it Edit: Already did. Congratulations for another great interview Ryan!
    6 points
  3. Okay, I must really like ProcessWire. I registered with a throw-away account and voted.
    5 points
  4. Great interview! This is pretty darn important, and is probably one of the most important things that sets PW apart.
    4 points
  5. They won't let me login without a Twitter or Facebook account - what is the world coming to
    4 points
  6. For those concerned about security, you could do this afterwards on Twitter: I can confirm your vote is still there afterwards.
    3 points
  7. Good news! We were chosen by the product hunt team to be featured in their permanent list, and we are now on their homepage with the other tech products of today Any of you has a nice animated gif that shows the admin? Would be great for showing off!
    3 points
  8. Disturbing read Willy! but good idea - disposable Twitter account worked a treat - I've voted!
    3 points
  9. So, some days later I'm the one who has submission powers in product hunt. They just sent me an invite And... here it is! https://www.producthunt.com/tech/processwire PS: You don't need an invite to register and upvote, and we need those upvotes to appear on the homepage
    3 points
  10. I posted this here https://processwire.com/talk/topic/11998-growing-processwire-in-2016/?p=111884 but I thought it would be better to open a new thread to catch the attention of more people. Today I submitted PW to Product Hunt. https://www.producthunt.com/tech/processwire This is a site with great exposure, but only if PW gets featured on the homepage. For this it has to be reviewed by the Product Hunt team and one of the most important factors is the number of upvotes. So, what are you waiting for? Why are you still here? Edit: If anyone would like to suggest different pictures for the header and thumbnail, go ahead.
    2 points
  11. Was there a question in there? $out = "<ul>"; $duplicates = array(); foreach($page->images as $image){ // rather than count words, let's just explode each string into an array (even if only one word) $tagsArray = explode(' ', $image->tags); foreach ($tagsArray as $t) { if(in_array($t, $duplicates)) continue;// skip duplicate tags $out .= "<li class='' data-uk-filter='{$t}'>" . "<a href='#'>{$t}</a>" . "</li>"; $duplicates[] = $t; } } $out .= "</ul>"; echo $out;
    2 points
  12. Ok i tried some different setting, but without luck for the function - but i studied the ProcessPageSearch and found: // non superuser doesn't get any admin pages in their results $s .= ", has_parent!=$adminRootPage"; And now come one of PW greatest things - without fear i switched the parent (for the contentblock root) from my settings page to admin page...with kinda a 300 pages there....switched parent -> all works, editors don't get any single PageTable Pages -> all good! Best regards mr-fan
    2 points
  13. I have converted the relevant db query code to PDO and will issue a pull request.
    2 points
  14. out for this. Isn't there another way to upvote for processwire without spreading my private data around ? i alsos donut like.to spread my.privates a round withs tweetster u.can jus make throws away acct to uses.for this stuffs butt fecesbook tweetster and friendsters blocked in.my cuntry butt i stil haves myspaces butt no work w produt hunter butt at lest not blocked .i keep try to make work
    2 points
  15. So this is basically a recreation of a menu tutorial from W3Bits, tweaked to include the Advanced checkbox hack. Demo. Even the Advanced hack itself was tweaked: apparently this bit is causing issues with Safari, so I removed it: @-webkit-keyframes bugfix { from {padding:0;} to {padding:0;} }I found this particular configuration to work quite nicely. A previous menu I tried had a problem with the menu items staying expanded between media query breakpoints, when resizing the browser. Below is the CSS for the menu. You will notice that it is mobile-first: /* Menu from http://w3bits.com/css-responsive-nav-menu/ */ /* Note: the tutorial code is slightly different from the demo code */ .cf:after { /* micro clearfix */ content: ""; display: table; clear: both; } body { -webkit-animation: bugfix infinite 1s; } #mainMenu { margin-bottom: 2em; } #mainMenu ul { margin: 0; padding: 0; } #mainMenu .main-menu { display: none; } #tm:checked + .main-menu { display: block; } #mainMenu input[type="checkbox"], #mainMenu ul span.drop-icon { display: none; } #mainMenu li, #toggle-menu, #mainMenu .sub-menu { border-style: solid; border-color: rgba(0, 0, 0, .05); } #mainMenu li, #toggle-menu { border-width: 0 0 1px; } #mainMenu .sub-menu { background-color: #444; border-width: 1px 1px 0; margin: 0 1em; } #mainMenu .sub-menu li:last-child { border-width: 0; } #mainMenu li, #toggle-menu, #mainMenu a { position: relative; display: block; color: white; text-shadow: 1px 1px 0 rgba(0, 0, 0, .125); } #mainMenu, #toggle-menu { background-color: #09c; } #toggle-menu, #mainMenu a { padding: 1em 1.5em; } #mainMenu a { transition: all .125s ease-in-out; -webkit-transition: all .125s ease-in-out; } #mainMenu a:hover { background-color: white; color: #09c; } #mainMenu .sub-menu { display: none; } #mainMenu input[type="checkbox"]:checked + .sub-menu { display: block; } #mainMenu .sub-menu a:hover { color: #444; } #toggle-menu .drop-icon, #mainMenu li label.drop-icon { position: absolute; right: 0; top: 0; } #mainMenu label.drop-icon, #toggle-menu span.drop-icon { padding: 1em; font-size: 1em; text-align: center; background-color: rgba(0, 0, 0, .125); text-shadow: 0 0 0 transparent; color: rgba(255, 255, 255, .75); } label { cursor: pointer; user-select: none; } @media only screen and (max-width: 64em) and (min-width: 52.01em) { #mainMenu li { width: 33.333%; } #mainMenu .sub-menu li { width: auto; } } @media only screen and (min-width: 52em) { #mainMenu .main-menu { display: block; } #toggle-menu, #mainMenu label.drop-icon { display: none; } #mainMenu ul span.drop-icon { display: inline-block; } #mainMenu li { float: left; border-width: 0 1px 0 0; } #mainMenu .sub-menu li { float: none; } #mainMenu .sub-menu { border-width: 0; margin: 0; position: absolute; top: 100%; left: 0; width: 12em; z-index: 3000; } #mainMenu .sub-menu, #mainMenu input[type="checkbox"]:checked + .sub-menu { display: none; } #mainMenu .sub-menu li { border-width: 0 0 1px; } #mainMenu .sub-menu .sub-menu { top: 0; left: 100%; } #mainMenu li:hover > input[type="checkbox"] + .sub-menu { display: block; } }Below is the markup outputted using mindplay.dk's method. I found it impossible to output with MarkupSimpleNavigation or MenuBuilder. The homepage is added as the first top-level item. Notice the onclicks that make it work on iOS < 6.0. The clearfix class cf for the top ul is important. Otherwise the element will have no height (got bitten by this..). <nav id="mainMenu"> <label for='tm' id='toggle-menu' onclick>Navigation <span class='drop-icon'>▼</span></label> <input id='tm' type='checkbox'> <ul class='main-menu cf'> <?php /** * Recursive traverse and visit every child in a sub-tree of Pages. * * @param Page $parent root Page from which to traverse * @param callable $enter function to call upon visiting a child Page * @param callable|null $exit function to call after visiting a child Page (and all of it's children) * * From mindplay.dk */ echo '<li><a href="' . $pages->get(1)->url . '">Home</a></li>'; function visit(Page $parent, $enter, $exit=null) { foreach ($parent->children() as $child) { call_user_func($enter, $child); if ($child->numChildren > 0) { visit($child, $enter, $exit); } if ($exit) { call_user_func($exit, $child); } } } visit( $pages->get(1) , function(Page $page) { echo '<li><a href="' . $page->url . '">' . $page->title; if ($page->numChildren > 0) { echo '<span class="drop-icon">▼</span> <label title="Toggle Drop-down" class="drop-icon" for="' . $page->name . '" onclick>▼</label> </a> <input type="checkbox" id="' . $page->name . '"><ul class="sub-menu">'; } else { echo '</a>'; } } , function(Page $page) { if ($page->numChildren > 0) { echo '</ul>'; } echo '</li>'; } ); ?> </ul> </nav>Edit: fixed the end part, thanks er314.
    1 point
  16. Background - I came across http://www.responsivebreakpoints.com/ the other day and thought it was a nice idea, but that could be done in PW using the API. In a nutshell, what it does is create an image width breakpoint at roughly every 20kb of file size between a minimum and maximum pixel size. According to this article on CSS-Tricks, "If you’re just changing resolutions, use srcset", so the markup is as suggested there. There is already the excellent Srcset Image Textformatter which works on images in RTE fields, but if you want responsive images elsewhere in your templates, you need to do the markup and decide on breakpoint sizes yourself. However, Field Templates have got you covered! Just save this as a field template file in /site/templates/fields/my_image.php as described above. <?php $maxWidth = 1000; //largest breakpoint $minWidth = 200; //smallest breakpoint $srcQuality = 40; //jpeg quality of the 'src' image $srcsetQuality = 80; //jpeg quality of the 'srcset' images $breakpointStepFileSize = 20; //i.e. 20kb $class = ""; //change this if you want to add eg "class='responsive'" $horizAspect = $value->width / $value->height; $minSizeArea = round($minWidth * ($minWidth / $horizAspect)); $maxSizeArea = round($maxWidth * ($maxWidth / $horizAspect)); $areaDiff = $maxSizeArea - $minSizeArea; $minFile = $value->width($minWidth, array('quality' => $srcsetQuality)); $maxFile = $value->width($maxWidth, array('quality' => $srcsetQuality)); $minFileSize = $minFile->filesize; $maxFileSize = $maxFile->filesize; $fileSizeDiff = $maxFileSize - $minFileSize; if($fileSizeDiff > ($breakpointStepFileSize * 1024)){ $numBreakpoints = round($fileSizeDiff / ($breakpointStepFileSize * 1024)); for($s = 1; $s < $numBreakpoints; $s++){ $breakpointStepArea = $minSizeArea + (($areaDiff / $numBreakpoints) * $s); $breakpointWidth = round(sqrt($breakpointStepArea * $horizAspect)); $breakpoints[] = $breakpointWidth; } } $src = $value->width($maxWidth, array('quality' => $srcQuality))->url; $min = "$minFile->url {$minWidth}w, "; $out = "<img src='$src' srcset='$min"; foreach($breakpoints as $breakpoint){ $bp = $value->width($breakpoint, array('quality' => $srcsetQuality))->url; $out .= "$bp {$breakpoint}w, "; } $out .= "$maxFile->url {$maxWidth}w"; $out .= "' alt='$value->description' $class>"; echo $out; Then use something like echo $page->render->my_image; in your page template and you'll get something like <img src='/site/assets/files/1/photo.1000x0.jpg' srcset='/site/assets/files/1/photo.200x0.jpg 200w, /site/assets/files/1/photo.482x0.jpg 482w, /site/assets/files/1/photo.651x0.jpg 651w, /site/assets/files/1/photo.785x0.jpg 785w, /site/assets/files/1/photo.899x0.jpg 899w, /site/assets/files/1/photo.1000x0.jpg 1000w' alt='pic' > (Bear in mind that PW has to create all these image variations on first page load, so it will take a moment.) Give it a try and see what you think!
    1 point
  17. Hi Richard, Have you tried the following: http://snippi.com/s/bnx7cij
    1 point
  18. Great - thank you very much! The query and if statements are never a real problem since i like to try out how it works and dig into - but sometimes i don't find the right hook or methode that i have to jump on (ProcessPageSearch::executeFor). Thank you for the hint - i will provide a complete snippet if it works. (Just some little offtopic - i place this kind of hooks until now in my admin.php - i don't get the whole difference between ready.php and admin.php...it's not really documentated where i should run/setup different little hooks/tasks better)
    1 point
  19. I know you said you have tried using start, but I only see one "start=1". I admit I haven't really read your code carefully, but the usual issue is that you need to put "start=0" in each of the selectors that is not the main page one - in this case it would be the "then" and "older" queries. But as I said, I didn't read carefully so may be off on this one
    1 point
  20. @mr-fan, This actually should be quite simple. Add an after hook on: ProcessPageSearch::executeFor and call this method: public function removeHiddenFromSearch($event) { $response = $event->return; $responseArray = json_decode($response, true); $matches = $responseArray['matches']; $i=0; foreach($matches as $match) { if($this->pages->get($match['id'])->isHidden()) { unset($matches[$i]); } $i++; } $responseArray['matches'] = $matches; $event->return = json_encode($responseArray); } This will remove all hidden pages from the results, but I get the feeling the pages themselves are not actually hidden, just the "Settings" parent. Is that correct? In that case change "isHidden()" to check if the page is a child of the "Settings" parent - I'll let you figure that out
    1 point
  21. Thank you guys, used the following $this->pages->addHookAfter('saveReady', null, 'order_number'); function order_number($event) { $page = $event->arguments[0]; if($page->template != 'booking') return; if(!isset($page->booking_orderno)) { $max = wire('pages')->get("template=booking, sort=-id"); $lastNumber = $max->booking_orderno +1; $page->booking_orderno = $lastNumber; } }
    1 point
  22. $max = wire('pages')->get("template=booking, sort=id"); $lastNumber = $max->your_number_field + 1;
    1 point
  23. Also the original image is never changed except if the image field does have max. dimensions set and the image is larger.
    1 point
  24. I'm completely lost here. Reading what?
    1 point
  25. I'll try to look into this as soon as possible, but if someone already fixed it and can submit a merge request it would be a great help. //Jasper
    1 point
  26. It's not about pages or repeaters – which is irrelevant – but about the way you handle them. For the most part any method you call directly on the $pages object will result in a database query, whereas all the other find() or get() calls are only searching pages, which are already in memory. That's the differentiating factor.
    1 point
  27. sure, you could have a hook on page save ready, which checks to see if page has an order number and if not it gets the order with the highest number and adds 1, and then sets the field value
    1 point
  28. Re, ok I ended up modifying the content of a CKEditor field before il gets saved. I made a module with autoload=true and hooked it after the input field is processed. the module will detect images that are from the web or encoded in base64 (begining with http, ftp and data) and fetch it , copy it to images field and replace the link with the new uploaded image link. public function init() { // add before-hook to the inputfield render method $this->addHookAfter("InputfieldCKEditor::processInput", $this, "downloadPastedImages"); } public function downloadPastedImages(HookEvent $event) { // // get the current field $field = $event->object; if($field->name === 'projet_body' && $field->value !== '' ) { $page = $this->modules->ProcessPageEdit->getPage(); // ===== custom class $manipulator = new textManipulator; // custom function of the class to get images src into a array $images = $manipulator->getImagesArray($field->value); // vérifie si c'est un lien image qui vient du web avec http en début $images_fromweb = array(); foreach($images as $key=>$image){ if(substr( $image, 0, 4 ) === "http" || substr( $image, 0, 4 ) === "data" || substr( $image, 0, 3 ) === "ftp") $images_fromweb[] = $image; } $filename = $page->name."_image_"; // si on a des images du web non copié encore => on efface tout pour copier if(count($images_fromweb) > 0){ // efface toute les images // autre technique : $page->images->removeAll(); $page->save(); } //wire('pages')->uncache($page); // just in case we need the memory foreach($images_fromweb as $key=>$image){ // save images if not in local server $page->setOutputFormatting(false); // copie de l'image vers le dossier de la page (sans extension encore) $file = $page->images->path . $filename.$key; $file_url = $page->images->url . $filename.$key; $temp_image = file_get_contents($image); file_put_contents($file, $temp_image); // detecte l'extension $ext = ".png"; if(mime_content_type($file) === "image/gif") { $ext = ".gif"; } else if(mime_content_type($file) === "image/jpeg") { $ext = ".jpg"; } else if(mime_content_type($file) === "image/bmp") { $ext = ".bmp"; }else if(mime_content_type($file) === "image/svg+xml") { $ext = ".svg"; } // ajoute l'extension rename($file,$file.$ext); // remplace le chemin de l'image à présent copiée dans le texte source $field->value = str_replace($image, $file_url.$ext, $field->value); // add to page $page->images->add($file.$ext); // save the page $page->save(); } } }
    1 point
  29. Even if the date would show up it would just be a quite unreadable timestamp. I'd suggest formatting the date which will additionally make sure it's a sting and not parsed as anything special.
    1 point
  30. Disturbing read Willy! but good idea - disposable Twitter account worked a treat - I've voted! sorrey for me.englich code. bettter for me
    1 point
  31. $page->addStatus(Page::statusLocked); $page->removeStatus(Page::statusLocked); Have a look at the cheatsheet.
    1 point
  32. Glad that worked for. Just in case you don't know you can avoid the need for an entire module to add simple hooks like this. You can place the hook and method in site/templates/admin.php There are also site/init.php site/ready.php and site/finished.php files that you can make use of. More reading here: https://processwire.com/blog/posts/processwire-2.6.7-core-updates-and-more/#new-core-files-for-site-hooks
    1 point
  33. Thanks for testing Spica! All what you have found out belongs to sharpening, and indeed there are two instances where currently no memory-check is invoked. Those both (not several!) instances belong to the unsharpMask function, what is enabled by default to create the best possible result for your images. So, as we have to find a balance between fast image processing and to avoid going out of memory, every user should take a bit care with his sites. If you are low on memory, you definetly should limit the max dimensions for upload images. Besides that, you uncovered that we need to describe more features we have under the hood with image processing. With a slide change in the $config settings we can disable the usage of the UnsharpMask for sharpening and switch to another algorithm, what needs much much lesser memory. This unsharp algorythm was there earlier, but we decided to switch to the visually better working USM by default in times where 256M seems to be a common value for memory usage. Conclusion: we will implement memory checking for those two instances currently not covered too, and we will provide flags within the $config settings that enables users to simply switch between sharpening algorythms in systems with low memory. Once again, thanks for your tests and reports, it is much appreciated.
    1 point
  34. It may not cover all needs, but I usually use an InputfiedMarkup: $f = wire('modules')->get("InputfieldMarkup"); $f->value = "Any HTML you want here";
    1 point
  35. Sourcetree (and I believe other clients) handle the folders for the branches for you behind the scenes. Using Sourcetree I have only 1 main project folder per project (with sub-folders and files inside, of course). I start off with a master branch which I then clone to become a 'dev' branch. My dev branch then becomes my 'working' branch. Every time I edit my files, I am working on the dev branch. When I am ready to share the code, I push the dev branch to 'origin' which in many cases is GitHub (but can be BitBucket as well). Sourcetree will ask which branches in the origin I am pushing to. I push local 'dev' to origin (i.e. remote) dev. When the code is stable enough, I merge dev to master. If I switch to master as the working branch, and edit my files, Sourcetree makes sure that my text editor is editing master files and not dev. So, it is important to ensure you have the correct branch set as the working branch. Earlier in the days I used to have separate folders for master and dev branches and it was just too tedious... I suggest you Google some intro to GitHub or Git. There's some nice resources out there Edit: Check out your repository settings RE linking your local and remote branches..
    1 point
  36. Good job! Starting to write modules is like a rebirth - a few lines and suddenly you are a programmer. Congrats! I also mentioned inconsistency in naming. Better pick one name and go with it.
    1 point
  37. Real-Life Example Website: crms.sdtool.info Purpose: Collaborative Resource Management System (CRMS) Ok, this website uses Adrian's Protected Mode module to control access to the website. ProcessWire (PW) Roles are then used throughout to control access to selected pages. Fields within templates are also controlled via this method. These PW Roles are added at each PW template using the Access Tab. I use a concept I call a "Security Container" that sits at the top of the PW Page Tree (backend) on the website. This is how the "Security Container"is explained on the website: Each "Security Container" has a PW template that controls who has access to that particular page. Once again, access is gained via one or more PW Roles. You have to have access to the gateway "Security Container" page to get to any pages under it. My Client: (I will be using the name Axxxx, as I still need to respect confidentiality and privacy) is an Internet Marketing and Investment Company in the Washington DC Metropolitan Area. They provide selected SEO services to their clients. My role with this client is to provide back-end Internet-based infrastructure support for Axxxx and their clients. This comprises of: Manage/maintain existing web hosting user accounts (SSH/SFTP) and creating new ones (when required) Database creation and upkeep Domain and SSL/TLS registrations Wordpress website installations, day-to-day back-end management and upkeep Email domain/account creation, back-end management and upkeep (website, plug-ins and themes) Centralized database backups and restorals Analytics management using Google Tag Manager/Analytics, Piwik and Woopra Work with Wordpress developers, on behalf of the client, to integrate third-party plug-ins or capabilities Accessing Axxxx Client Data or Resources The Axxxx Client has three possible PW Roles that can be assigned: axxxx-client-access (Contractors or any outside Axxxx related entity) axxxx-manager-access (Axxxx Business Owner or Manager) axxxx-staff-access (Axxxx Staff who aren't at the manager level) The top-level Axxxx "Security Container" Page ensures that only the above three PW Roles have access to Axxxx data or resources. Whenever an Axxxx employee logs into the website, they only see Axxxx related information. Form-Based Page Submissions All newly created pages (by clients) make extensive use of Ryan's Form Builder module. Support request pages and emails are created using this handy tool. Each client has dedicated Form Builder forms that are applicable to their particular mission. Email-Based Page Submissions All my clients have the capability to submit updates or new submissions to me through email. I use the fantastic Email To Page module by Pete and Adrian to achieve this feat. I now make extensive use of Twilio based communications capabilities due this module being installed on this website. Axxxx Company Clients The Axxxx Client company has clients of their own and their data is stored within the website's "Client Portal" Security Container. They can all see the "Client Portal" page (but not any CStevensJr or Axxxx data) and each has an individual named page (which is a "Security Container" for their permissions) under it. PW Roles are used here also to segregate access to each client's own data. Whenever a Axxxx client logs into the CRMS, they only see the "Client Portal" PW Page and beneath that their own data/resources. Final Thoughts PW has an extensive Roles and Permissions system which has significantly improved over the last year. I previously made use of Ryan's Page Edit Field Permission module but now use the greatly expanded native permissions instead. My SDTool Project has progressed very nicely and is being expanded to make use of all the great new capabilities that PW provides. I hope this rather long explanation is helpful. This is just one way I work with PW. I will, in the next few months, provide some more promised updates on the SDTool Project (in the linked post) .
    1 point
  38. The modules does use standard datetime fields, therefore if other datetime fields do suffer from the same issue it's probably a core issue.
    1 point
  39. Macrura - very cool - I hadn't thought of using it that way and will actually need similar buttons in an upcoming project so might just consider using this module to do it! The trouble I am having with PW lately is that there are so many great new ways of doing things and it's hard to keep track of them all
    1 point
  40. I've always happily used VI (VIM) and always will. But I found a way to make the newest PHPStorm look and behave like VIM, so that's what I'm slowly adapting to. So far I like it, it's a fairly impressive piece of software. Lets me still be in VIM (or at least trick me into thinking I am) while giving me all the power of PHPStorm. I was also motivated by their support of open source–they provided the full license for free for ProcessWire development.
    1 point
×
×
  • Create New...