Jump to content

Leaderboard

Popular Content

Showing content with the highest reputation on 08/25/2016 in all areas

  1. foreach($pageOld->images as $image) { $pageNew->images->add($image->filename); } $pageNew->save(); $pageOld->images->deleteAll(); see: http://cheatsheet.processwire.com/files/page-files-multiple-wirearray/files-deleteall/
    5 points
  2. Why should it not be available on the front-end? It's just you have to output the stuff in your header. Look at the default.php of templates-admin/. I always use it in my sites. <script type="text/javascript"> var config = <?php echo json_encode($jsConfig); ?>; </script> Then use the config.key in your JS.
    4 points
  3. I don't think there's a straight-forward solution for this. Usually, advanced search requirements like this are covered by external search engines like Lucene, but those might a bit of overkill. A lean solution would be to create a (hidden) text field, let's call it titlenospace, and add it to all templates you want to search. Then, in site/ready.php (create the file if not there yet), hook into Pages::saveReady and populate the new field with the whitespace-stripped contents of the title field. <?php if($page->template == "admin") { wire()->addHookAfter("Pages::saveReady", function(HookEvent $event) { $page = $event->arguments(0); if($page->template->hasField("titlenospace")) { $page->titlenospace = str_replace(' ', '', $page->title); } }); } For a multi-language site, the titlenospace field has to be created as TextLanguage and the code gets slightly more verbose. <?php if($page->template == "admin") { wire()->addHookAfter("Pages::saveReady", function(HookEvent $event) { $page = $event->arguments(0); if($page->template->hasField("titlenospace")) { $page->titlenospace = str_replace(' ', '', $page->title); if(wire("languages")) { foreach(wire("languages") as $lang) { if(!$lang->isDefault()) { $page->setLanguageValue($lang, "titlenospace", str_replace(' ', '', $page->getLanguageValue($lang, "title"))); } } } } }); } The titlenospace field needs to be populated for existing pages (simply saving them should do). Then you can use the field in your selector instead of or in addition to the regular title field.
    4 points
  4. I am on pw 3 and this is the code that works for me. I am new to PW and haven't yet caught up with hooks -- I got this code from somewhere here. <?php $pages->addHookAfter('Page::path', null, 'hookPagePath'); function hookPagePath(HookEvent $e) { $page = $e->object; if($page->get('template') == 'article') $e->return = "/$page->name/"; } This code that updates the urls is the first half of the redirection game. The other half is about redirecting users to the right article. For that, you will have to use urlsegments. Here are the steps, roughly. -- Enable urlsegments for homepage. => This means website.com/this-is-an-article is a hit to the homepage, and this-is-an-article is the first url segment. -- Use this url segment to get a handle to the article page object. ==> $pages->get("name=this-is-an-article") -- Check if its a legit article by checking for the existence of its id. -- If it's a valid page, redirect the visitor to it. echo $article->render(); return;
    4 points
  5. I can prove that he does so: He even writes tutorials about the topic: http://soma.urlich.ch/posts/custom-js-in-processwire-admin/
    3 points
  6. You might need to do this after the foreach loop... $pageNew->save();
    3 points
  7. In addition to @Martijn Geerts's piece of advice, you might also need something like this: https://www.yourhowto.net/strip-spaces-string-php/ It's not really about find, but about working with strings.
    3 points
  8. Variables in single quotes will not be processed. Use double quotes when using variables in selectors.
    3 points
  9. In addition to hort's suggestion, writing the raw image data contained in the data URI can be as simple as: file_put_contents($filename, file_get_contents($data)); No need for manually parsing $data for the base64 part. The only reason to look at $data would be to determine the correct file extension in case other types than png are allowed too.
    3 points
  10. Like Bitpoet and netcarver said, you need to save the page before you are able to add images. ALso you should do a check if the page already exists, maybe. If you are not able to provide (HTTP) URLs to the images, and no filepathes, but those strings of data:image/png strings, you need two things: a wrapper function that extracts the image data into a temporary file and an imagename! A wrapper function is easy, but from where do you get a filename, ...? <?php require_once('../index.php'); $input = wire('input'); $sanitizer = wire('sanitizer'); $pages = wire('pages'); $item_titel = $sanitizer->text($input->get("item_titel")); $item_client = $sanitizer->text($input->get("item_client")); $item_usecase = $sanitizer->text($input->get("item_usecase")); $item_text = $sanitizer->textarea($input->get("item_text")); $item_date = $input->get("item_date"); $item_images = $_GET["item_images"]; // don't know if we can use $input->get("item_images") to get an array, // writing in browser only(!) $parentPage = $pages->get("/items/"); $templatePage = wire('templates')->get("item"); $pageName = $sanitizer->pageName($item_titel); $p = $pages->get("name={$pageName}, parent={$parentPage}, template={$templatePage}"); if(0 == $p->id) { // or: if($p InstanceOf NullPage) // only create a new page if no one exists, // otherwise you would create pages with same content but automaticly incremented pagename !! $p = new Page(); $p->of(false); $p->template = $templatePage; $p->parent = $parentPage; $p->title = $item_titel; $p->item_titel = $item_titel; $p->item_client = $item_client; $p->item_date = $item_date; $p->item_text = $item_text; $p->save(); foreach($item_images as $data) { // $data looks like: data:image/png;base64,iVBORw0KGgo... $basename = '???'; $filename = myImageExtract($data, $basename); $p->images->add($filename); } $p->save(); } function myImageExtract($data, $basename = '') { // extract the imagetype / extension and the imagedata part from the string $imagedata = ... ; $extension = ... ; // write it into a temporary file and return the filename // see: https://processwire.com/talk/topic/11843-file-upload-images-pdfs-from-base64-value/#comment-110113 $tmpDir = new WireTempDir('someName'); $fileBasename = $basename . '.' . $extension'; $filename = $tmpDir->get() . $fileBasename; file_put_contents($filename, base64_decode($imagedata)); return $filename; }
    3 points
  11. Have you set up URL segments for the home page template? See Ryan's post where he talks about the home template:
    3 points
  12. find() would also work here: $primary_tags = $article->article_tags->find("id!=1336|1337|1338|1339|1327|1326|1328"); $secondary_tags = $article->article_tags->find("id!=1042|1043|1044|1340|1341");
    2 points
  13. To be a bit more secure or serious, you want to check if everything went ok, before you delete all images on the old page. If I undestood right, the new page images should be an exact copy of the old one. Therefore we can delete all (optionally) images on the new page first. Then, after adding all images to it, we compare both collections. When on PHP >= 5.6.0, we can compare the ->items(), what contains a list of all image basenames, what is fine! If we, unfortunately, on PHP lower then 5.6, we can at least compare the count of images, or have to loop through both collections and compare the basenames one by one. $pageNew->of(false); $pageNew->images->deleteAll(); $pageNew->save(); foreach($pageOld->images as $image) { $pageNew->images->add($image->filename); } $pageNew->save(); // now check for success or failures $success = version_compare(phpversion(), '5.6.0', '>=') ? $pageNew->images->items() === $pageOld->images->items() : $pageNew->images->count() === $pageOld->images->count(); if($success) { // delete images on old page $pageOld->of(false); $pageOld->images->deleteAll() $pageOld->save(); }
    2 points
  14. Slight tweak - probably never be needed... if (false !== file_put_contents($file, $data)) { $p->item_images->add($file); unlink($file); } Might save you an error if a file save ever fails.
    2 points
  15. Hi Horst, removing the temporary files is a good idea .) - i diden't recognized that they flooded my asset folder - thanks! Just if someone is interested: I had to change from GET to POST because with GET i struggled into a HTTP 414 “Request URI too long” ERROR. So finnaly it works how i wanted - thanks to the team .) - and a good evening to you. <?php require_once('../index.php'); $input = wire('input'); $sanitizer = wire('sanitizer'); $pages = wire('pages'); $item_titel = $sanitizer->text($input->post("item_titel")); $item_client = $sanitizer->text($input->post("item_client")); $item_usecase = $sanitizer->text($input->post("item_usecase")); $item_text = $sanitizer->textarea($input->post("item_text")); $item_date = $input->post("item_date"); $image_fileNames = $_POST["image_fileNames"]; $item_images = $_POST["item_images"]; $image_types = $_POST["image_types"]; $parentPage = $pages->get("/items/"); $templatePage = wire('templates')->get("item"); $pageName = $sanitizer->pageName($item_titel); $upload_path = $config->paths->assets; $p = $pages->get("name={$pageName}, parent={$parentPage}, template={$templatePage}"); if(0 == $p->id) { $p = new Page(); $p->of(false); $p->template = $templatePage; $p->parent = $parentPage; $p->title = $item_titel; $p->item_titel = $item_titel; $p->item_client = $item_client; $p->item_date = $item_date; $p->item_text = $item_text; $p->save(); $i = 0; foreach($item_images as $data) { $name = $image_fileNames[$i]; $imgType = $image_types[$i]; myImageExtract($p, $data, $name, $upload_path, $imgType); $i++; } $p->save(); } function myImageExtract($p, $imgData, $imgName, $upload_path, $imgType) { $base64img = str_replace('data:'.$imgType.';base64,', '', $imgData); // fixed $data = base64_decode($base64img); $file = $upload_path . $imgName; file_put_contents($file, $data); $p->item_images->add($file); unlink($file); } Cheers Simon
    2 points
  16. Endless saving events are a sign that the ajax upload resulted in returning some PHP notice, warning, error via AJAX. That prevents the imagefield from updating correctly. You need to use the browsers Webtools and see what you get returned from the AJAX upload. ALso useful is to check manually in the assets/files/{12345}/ folder what files are there. (Your original file? A thumbnail? Nothing?)
    2 points
  17. @jploch before calling the function, call the module : <?php $map = $modules->get('MarkupLeafletMap'); echo $map->getLeafletMapHeaderLines(); ?>
    2 points
  18. Thanks @LostKobrakai, I'm aware. I use the browser to debug. Will remove the setting afterwards @szabesz You're welcome!
    2 points
  19. This is the first time I've heard of this browser. Looks awesome and luckily based on Chromium! (I got used to its dev tools and I'm sort of lost when using other browsers' dev tools.) Thanks for the tip!
    2 points
  20. Lots of discussion, links and approaches in this thread:
    2 points
  21. Disabling csrf, while apparently making it work for you, will also make your site vulnerable to csrf attacks, therefore it's not recommended to do that.
    2 points
  22. Q: What has the TESLA that PROCESSWIRE does not have: A: backdoors
    2 points
  23. Thanks Ivan, I really appreciate it! You give me way too much credit and are too kind, but such a heartfelt message still leaves me speechless, so thank you again. I don't think I want any kind of luxury car! I'll be honest, while I was sad to give the car back, I was also glad to because it's just plain stressful. There's no problem if someone dents my car or something gets scratched, etc., but borrowing such a fancy car makes you always worried about where you park. If a bird poops on it you have to clean it right off, and so on and so forth. All these things I never worry about, but became apparent when I had to be responsible for such an object for 2 days. I imagine a lot of stress comes with owning something like that. I'm sure to many it's worth it, but still, glad I don't have to think about that kind of stuff every day. If I were to ever own a car like this, I'd buy it after it's already many years old, inexpensive, and has the battle scars to show it. \
    2 points
  24. Since you guys asked for it, I'll take a stab at a case study on the development process. Most of the development was done in about a week and a half. I started with the basic profile, but it ended up being something somewhat similar to the Blog profile in terms of how it's structured. Below I'll cover some details on the biggest parts of the project, which included data conversion, the template structure, the front-end development and anything else I can think of. Data Conversion from WordPress to ProcessWire One of the larger parts of the project was converting all of the data over from WordPress to ProcessWire. I wrote a conversion script so that we could re-import as many times as needed since new stories get added to cmscritic.com almost daily. In order to get the data out of WordPress, I queried the WordPress database directly (my local copy of it anyway) to extract what we needed from the tables wp_posts for the blog posts and pages, and then wp_terms, wp_term_relationships, and wp_term_taxonomy for the topics and tags. WordPress stores its TinyMCE text in a state that is something in between text and HTML, with the most obvious thing being that there are no <p> tags present in the wp_posts database. Rather than trying to figure out the full methodology behind that, I just included WP's wp-formatting.php file and ran the wpautop() function on the body text before inserting into ProcessWire. I know a lot of people have bad things to say about WordPress's architecture, but I must admit that the fact that I can just include a single file from WordPress's core without worrying about any other dependencies was a nice situation, at least in this case. In order to keep track of the WordPress pages imported into ProcessWire through repeat imports, I kept a "wpid" field in ProcessWire. That just held the WordPress post ID from the wp_posts table. That way, when importing, I could very easily tell if we needed to create a new page or modify an existing one. Another factor that had to be considered during import was that the site used a lot of "Hana code", which looked like [hana-code-insert name="something" /]. I solved this by making our own version of the Hanna code module, which was posted earlier this week. Here's an abbreviated look at how to import posts from WordPress to ProcessWire: $wpdb = new PDO("mysql:dbname=wp_cmscritic;host=localhost", "root", "root", array(PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES 'UTF8'")); $posts = wire('pages')->get('/posts/'); $sql = " SELECT * FROM wp_posts WHERE post_type='post' AND post_status='publish' ORDER BY post_date "; $query = $wpdb->prepare($sql); $query->execute(); while($row = $query->fetch(PDO::FETCH_ASSOC)) { $post = $posts->child("wpid=$row[ID]"); // do we already have this post? if(!$post->id) { // create a new post $post = new Page(); $post->template = 'post'; $post->parent = $posts; echo "Creating new post...\n"; } $post->of(false); $post->name = wire('sanitizer')->pageName($row['post_name']); $post->title = $row['post_title']; $post->date = $row['post_date']; $post->summary = $row['post_excerpt']; $post->wpid = $row['ID']; // assign the bodycopy after adding <p> tags // the wpautop() function is from WordPress /wp-includes/wp-formatting.php $post->body = wpautop($row['post_content']); $post->save(); echo "Saved post: $post->path\n"; } What I've left out here is the importing of images, topics, tags, and setting the correct authors for each post. If anyone is interested, I'll be happy to go more in depth on that, but didn't want to overwhelm this message with code. Template File Structure This site makes use of the $config->prependTemplateFile to automatically include the file _init.php before rendering a template file, and $config->appendTemplateFile to automatically include the file _main.php after. So the /site/config.php has this: $config->prependTemplateFile = '_init.php'; $config->appendTemplateFile = '_main.php'; You may recognize this as being the same setup from the Skyscrapers profile. The _init.php includes files containing functions we want to be available to all of our templates, and set default values for the regions we populate: /site/templates/_init.php /** * Include function and hook definition files * */ require_once("./includes/render.php"); require_once("./includes/hooks.php"); /** * Initialize variables populated by templates that get output in _main.php * */ $browserTitle = $page->get('browser_title|title'); $body = "<h1>" . $page->get('headline|title') . "</h1>" . $page->body; $side = ''; $renderMain = true; // whether to include the _main.php file The includes/render.php file that is included above includes several functions for generating markup of navigation and post summaries, or any other shared markup generation functions. Examples are renderPost(), renderNav(), renderTags(). This is similar to the blog.inc file from the Blog profile except that I'm letting these functions generate and return their own markup rather than splitting them into separate view files. I personally find this easier to maintain even if it's not as MVC. The includes/hooks.php sets up any hooks I want to be present for all of my templates. I could have also done this with an autoload module, but found this to just be a little simpler since my hooks were only needed on the front-end. The main hook of interest is one that makes all posts look like they live off the root "/" level rather than "/posts/" (where they actually live). This was in order to keep consistency with the URLs as they were in WordPress, so that the new site would have all the same URL as the old site, without the need for 301 redirects. /site/templates/includes/hooks.php /** * This hook modifies the default behavior of the Page::path function (and thereby Page::url) * * The primary purpose is to redefine blog posts to be accessed at a URL off the root level * rather than under /posts/ (where they actually live). * */ wire()->addHookBefore('Page::path', function($event) { $page = $event->object; if($page->template == 'post') { // ensure that pages with template 'post' live off the root rather than '/posts/' $event->replace = true; $event->return = "/$page->name/"; } }); Our /site/templates/_main.php contains the entire markup for the overall template used site wide, from <html> to </html>. It outputs those variables we defined in _init.php in the right places. For example, $body gets output in the <div id='bodycopy'>, $side gets output in the right <aside>, and $browserTitle gets output in the <title> tag. /site/templates/_main.php <?php if($renderMain): ?> <html> <head> <title><?=$browserTitle?></title> </head> <body> <div id='masthead'> // ... </div> <div id='content'> <div id='bodycopy'><?=$body?></div> <aside id='sidebar'><?=$side?></aside> </div> <footer> // ... </footer> </body> </html> <?php endif; ?> We use the rest of the site's template files to simply populate those $body, $side and $browserTitle variables with the contents of the page. As an example, this is an abbreviated version of the /site/templates/post.php template: /site/templates/post.php // functions from /site/templates/includes/render.php $meta = renderMeta($page); $tags = renderTags($page); $authorBox = renderAuthor($page->createdUser); $comments = renderComments($page); $body = " <article class='post post-full'> <header> <h1>$page->title</h1> $meta </header> $page->body $tags $authorBox $comments </article> "; if(count($page->related)) { $side = "<h4>Related Stories</h4>" . renderNav($page->related); } What might also be of interest is the homepage template, as it handles the other part of routing of post URLs since they are living off the root rather than in /posts/. That means the homepage is what is triggering the render of each post: /site/templates/home.php if(strlen($input->urlSegment2)) { // we only accept 1 URL segment here, so 404 if there are any more throw new Wire404Exception(); } else if(strlen($input->urlSegment1)) { // render the blog post named in urlSegment1 $name = $sanitizer->pageName($input->urlSegment1); $post = $pages->get("/posts/")->child("name=$name"); if($post->id) echo $post->render(); else throw new Wire404Exception(); // tell _main.php not to include itself after this $renderMain = false; } else { // regular homepage output $limit = 7; // number of posts to render per page $posts = $pages->find("parent=/posts/, limit=$limit, sort=-date"); $body = renderPosts($posts); } The rest of the site's template files were handled in the same way. Though most were a little simpler than this. Several were simply blank, since the default values populated in _init.php were all that some needed. Front-end development using Foundation 4 The front-end was developed with the Foundation 4 CSS framework. I started with the Foundation blog template and then tweaked the markup and css till I had something that I thought was workable. Then Mike and I sent the _main.php template file back and forth a few times, tweaking and changing it further. There was no formal design process here. It was kind of a photoshop tennis (but in markup and CSS) where we collaborated on it equally, but all under Mike's direction. After a day or two of collaboration, I think we both felt like we had something that was very good for the reader, even if it didn't originate from a design in Photoshop or some other tool like that. I think it helps a lot that Foundation provides a great starting point and lends itself well to fine tuning it the way you want it. I also felt that the mobile-first methodology worked particularly well here. Comments System using Disqus We converted the comments system over to Disqus while the site was still running WordPress. This was done for a few reasons: Disqus comments provide one of the best experiences for the user, in my opinion. They also are platform agnostic, in that we could convert the whole site from WP to PW and not have to change a thing about the comments… no data conversion or importing necessary. Lastly, ProcessWire's built-in comments system is not quite as powerful as WordPress's yet, so I wanted cmscritic.com to get an upgrade in that area rather than anything else, and Disqus is definitely an upgrade from WP's comments. In order to ensure that Disqus could recognize the relations of comment threads to posts, we again made use of that $page->wpid variable that keeps the original WordPress ID, and also relates to the ID used by the Disqus comments. This is only for posts that originated in WordPress, as new posts use a ProcessWire-specific ID.
    1 point
  25. Recently we have had the absolute pleasure of working the professional grade monitor providers, EIZO. EIZO provide colour accurate monitors, so we took heavy influence from colour in our design process. For the website, as always ProcessWire has been a perfect fit. The modules I have used are as follows: ProCache ProFields Hanna Code MarkupSEO ColorPicker MapMarker MobileDetect Any feedback would be much appreciated — http://eizocolour.com/
    1 point
  26. Alan, it will not mix up sessions, but it is less secure in regard of session steeling possibilities. If this is a special device with a known Useragent, I would suggest dynamicly disable sessionFingerprint only for that UA. something like that in the site/config.php: if(isset($_SERVER['HTTP_USER_AGENT']) && 'StringOfTheProblematicUserAgentHere' == $_SERVER['HTTP_USER_AGENT']) { $config->sessionFingerprint = 0; }
    1 point
  27. Does this: $sub_image = $pages->get("has_parent.id=$sub->id,template=product, sort=random")->product_images->find('tags=prod')->getRandom(); work? (You may want to also include a "product_images.tags=prod" subfield selector for the pages in case you have pages without a production ready image)
    1 point
  28. not() modifies the original PageArray, so you need to populate your variables with a copy of the original PageArray before you filter them. ($primary_tags = $article->article_tags->slice(0))->not("id=1336|1337|1338|1339|1327|1326|1328"); ($secondary_tags = $article->article_tags->slice(0))->not("id=1042|1043|1044|1340|1341");
    1 point
  29. @Macrura that's outdated info. I've implemented the pipe OR switches probably about a year ago. Only the OR groups are not supported in that regard. The issue here is that support for inputfield dependencies in repeater/matrix fields is still kinda experimantal. It can work, but often it doesn't.
    1 point
  30. Don't understand enough from the server responses, but it's clearly no PW issue. You may investigate more into max_upload sizes, max_memory, etc. This isn't apache, or?
    1 point
  31. Don't we have a Moderator around? @horst is speaking alien language which is seriously off-topic
    1 point
  32. what is returned via the AJAX request? what is in the logs? have you turned $config->debug to true?
    1 point
  33. Js would try to add properties to ProcessWire obj but on front end it's not available. Try var ProcessWire = ProcessWire || {}; but perhaps you should add Js another way instead. At least that's my theory Plus ProcessWire.config will be unavailable too.
    1 point
  34. Hi, looks good. Only additional suggestion from me would be to use another upload path ($config->uploadTmpDir) if is set in your environment, but not really necessary. And you better should remove the temporary file after it got added to the image field. ... $i = 0; foreach($item_images as $data) { $name = $image_fileNames[$i++]; // fortunately i can pass this from ajax myImageExtract($p, $data, $name, $upload_path); } $p->save(); } function myImageExtract(&$p, $imgData, $imgName, $uploadPath) { $base64img = str_replace('data:image/png;base64,', '', $imgData); // TODO - must be dynamic - could be jpg, gif ... $data = base64_decode($base64img); $file = $uploadPath . $imgName; file_put_contents($file, $data); $p->item_images->add($file); unlink($file); // delete temp file after adding it to image field }
    1 point
  35. See https://processwire.com/api/selectors/inputfield-dependencies/#limitations
    1 point
  36. I'd pick a different upload directory that $config->paths->assets (which amounts to site/assets). Perhaps create an upload directory inside the assets dir and save it there. You could also shorten your image extraction function a little (and make it image type agnostic): function myImageExtract($imgData, $imgName, $assets) { $file = $assets . $imgName; file_put_contents($file, file_get_contents($imgData)); return $file; }
    1 point
  37. So finaly it works -) What do you think - is it okay this way or is there something that should be fixed? PS: the $tmpDir solution didn't work - somehow the images couldn't be found... $tmpDir = new WireTempDir('someName'); Actual code: <?php require_once('../index.php'); $input = wire('input'); $sanitizer = wire('sanitizer'); $pages = wire('pages'); $item_titel = $sanitizer->text($input->get("item_titel")); $item_client = $sanitizer->text($input->get("item_client")); $item_usecase = $sanitizer->text($input->get("item_usecase")); $item_text = $sanitizer->textarea($input->get("item_text")); $item_date = $input->get("item_date"); $image_fileNames = $_GET["image_fileNames"]; $item_images = $_GET["item_images"]; $parentPage = $pages->get("/items/"); $templatePage = wire('templates')->get("item"); $pageName = $sanitizer->pageName($item_titel); $upload_path = $config->paths->assets; $p = $pages->get("name={$pageName}, parent={$parentPage}, template={$templatePage}"); if(0 == $p->id) { $p = new Page(); $p->of(false); $p->template = $templatePage; $p->parent = $parentPage; $p->title = $item_titel; $p->item_titel = $item_titel; $p->item_client = $item_client; $p->item_date = $item_date; $p->item_text = $item_text; $p->save(); $i = 0; foreach($item_images as $data) { $name = $image_fileNames[$i]; // fortunately i can pass this from ajax $filename = myImageExtract($data, $name, $upload_path); $p->item_images->add($filename); $i++; } $p->save(); } function myImageExtract($imgData, $imgName, $assets) { $base64img = str_replace('data:image/png;base64,', '', $imgData); // TODO - must be dynamic - could be jpg, gif ... $data = base64_decode($base64img); $file = $assets . $imgName; file_put_contents($file, $data); return $file; } And thanks again - this realy a helpfull forum! Cheeers Simon
    1 point
  38. In ProcessPageList::find you can set showRootPage to false like this (trial and error): $event->object->set('showRootPage', false); // or this: // $event->object->showRootPage = false;
    1 point
  39. Thank you very much, much appreciated
    1 point
  40. Thanks, @BitPoet I'll take a closer look at the code changes soon. Meanwhile I've created a new issue to the ProcessWire repository regarding UserGroups issue #45 and the related change in the ProcessWire core. I'd like to hear what Ryan thinks about that before implementing any kind of fix for that.
    1 point
  41. @ryan I was pretty sure you don't. For some people making things is much more interesting than having them. So Tesla won't be more fun than what you already doing (unless you're not a mechanic - or electric in this case ). I think words of appreciation won't hurt time to time. This just felt like the right place for a few. Promise not to write this kind of stuff after each and every you blog post))
    1 point
  42. @Robin S is right - you wrote tausands of chapters on one book....than i forgot one really big additional option in managing chapters right for editors....;) https://processwire.com/api/modules/lister-pro/ With lister you can setup a view where someone can select the book - or search for it and CRUD chapters... The Profield Table can paginate, filter and sort, too so this would scale for many chapters. But one the first run i would give book/chapters a go and use BatchChildEditor. With BCE you could create dummy data, pages via CSV import, too!! Thats the propose i use it in some projects. Most important thing choose wise and have fun!
    1 point
  43. v053 fixes the issue with label-less checkboxes not having field edit tooltips (thanks @ceberlin!)
    1 point
  44. I know someone has to write this, so let it be me. The first time I realised what I could do with the ProcessWire API it was like an insane mode in mentioned Tesla Model S. But it was just the beginning as PW keeps accelerating me ever since. Of course there are rough edges, but I am sure there are some in Tesla too - you just have to own it a bit longer to discover them . This creation of yours, Ryan, is something that was a mind-changer and a life-changer for so many of us here and more around the globe. And it is not just cheaper and better, it is open source and the best you can get! Tesla team made a great job. So did you - alone. More people everywhere in the world are using PW now than probably ever will be using Tesla cars. So the impact not only on the future, but on the present is quite comparable (Tesla team just has to work harder to not fall behind too far). ProcessWire is equally fine crafted mixture of technology and design, as this electric car... But none of us have to give it back some day soon. But not only the technology is to be mentioned. ProcessWire is a community, open source and global. People from Africa use it alongside people from Europe and Americas. And they (actually we) come together every day to talk to each other about a topic of no envy and hatred, but a common love and perspective. The world seems to be so unstable and fragmented these days. At the place that I live I hear a lot of negative words aimed at US and its policy. Some of it might be true, some of it is an obvious propaganda. But without other channels of information and communication you can easily lose your own point of view. I am sure something similar is happening on the so called "other side". Here in community we overcome that way of thinking. You, Ryan, and the open source ProcessWire thing is doing better job for creating a world as a better place than NSA spying scandals and troops being brought to places abroad for sure. And your avatar is the most friendly face of America to be seen for many. I do not know if making one of the best pieces of software in the world for free and inspiring one of the most friendly and helpful international communities shall ever help you to buy a luxury electric car (I really hope so), but "at least" your children have something to be really proud about.
    1 point
  45. Thank you, it was a very thought through decision. We almost always avoid scrolljacking (I'm personally like yourself, not a fan). However we really wanted to give a full screen almost TV like experience for this. We felt this was the best way at the time. Maybe it's something we could revisit in the future if we find a better alternative.
    1 point
  46. Moar updates: Finished working on named types for parameters, which was the base param-type before ({name:type}). As you can see below, we're testing with {fileext:ext} which converts to the regex format for FastRoute to handle: Request URI: string(12) "AboutUs.html" Matched Jumplink Object: object(stdClass)#5 (4) { ["from"]=> string(113) "{page}.{fileext:aspx|asp|cfm|cgi|fcgi|dll|html|htm|shtml|shtm|jhtml|phtml|xhtm|xhtml|rbml|jspx|jsp|phps|php4|php}" ["to"]=> string(7) "{page}/" ["deepClean"]=> bool(true) ["origFrom"]=> string(20) "{page}.{fileext:ext}" } Captured Parameters: array(2) { ["page"]=> string(7) "AboutUs" ["fileext"]=> string(4) "html" } Parameter 'page' cleaned (deep = yes) from 'AboutUs' to 'about-us' Compiled Destination: string(9) "about-us/" Also notice the deepClean property of the Jumplink object: Instead of setting the old Enhanced Wildcard Cleaning in settings, this is now done on a per-jumplink basis (defaults to false). Going to start working on aliasing (aka old smart wildcards) now. Aliases will convert, for example, {id} to {id:\d+}.
    1 point
  47. Typically the file compiler in PW3 takes care of making modules without namespaces work in 3.x, however I have had a couple of situations where I have had to conditionally check if a class exists and if not, prefix it with \ProcessWire\
    1 point
  48. What I do is use $config->js to populate the config array that I then output in the head for dynamic variables that want to share in a script. $config->js("myconfig", array("myajaxurl" => $pages->get(1991)->url); You can do this in templates or modules doesn't matter as long as it's before rendering page. Then this little to output as json. This is the same as PW uses in the admin to share config vars with js. <script type="text/javascript"> <?php // output javascript config json string to html // for use in javascripts from this point on $jsConfig = $config->js(); $jsConfig['debug'] = $config->debug; $jsConfig['urls'] = array( 'current_url' => $page->url, 'root' => $config->urls->root, ); ?> var config = <?php echo json_encode($jsConfig); ?>; </script> Then use in your script as var rootUrl = config.urls.root; for example
    1 point
  49. Session fingerprint also keeps track of useragent. So if your useragent or IP is changing, then the session is considered no longer valid. This can help to prevent session hijacking. But it can be a nuisance if your IP and/or useragent are changing for a valid reason. In that case, you should disable session fingerprint from your /site/config.php file. Locate this line and changed it to 'false' as shown below: /** * sessionFingerprint: should login sessions be tied to IP and user agent? * * More secure, but will conflict with dynamic IPs. * */ $config->sessionFingerprint = false;
    1 point
×
×
  • Create New...